diff options
Diffstat (limited to 'target/linux/brcm2708/patches-4.1/0117-BCM270x-Switch-to-firmware-driver.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.1/0117-BCM270x-Switch-to-firmware-driver.patch | 595 |
1 files changed, 595 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-4.1/0117-BCM270x-Switch-to-firmware-driver.patch b/target/linux/brcm2708/patches-4.1/0117-BCM270x-Switch-to-firmware-driver.patch new file mode 100644 index 0000000000..cf2555bc28 --- /dev/null +++ b/target/linux/brcm2708/patches-4.1/0117-BCM270x-Switch-to-firmware-driver.patch @@ -0,0 +1,595 @@ +From 3349eaf79dd91c2e6f9b7aed0c155668e4f5a856 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org> +Date: Fri, 26 Jun 2015 14:37:19 +0200 +Subject: [PATCH 117/121] BCM270x: Switch to firmware driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +defconfig: enable BCM2835_MBOX, RASPBERRYPI_FIRMWARE and BCM_VCIO. +Add firmware node and change mailbox node in Device Tree. +Add/update platform file for firmware and mailbox. +Strip bcm2708-vcio of everything except the legacy API and hook it +up with the firmware driver. + +Signed-off-by: Noralf Trønnes <noralf@tronnes.org> +--- + arch/arm/boot/dts/bcm2708_common.dtsi | 8 +- + arch/arm/configs/bcm2709_defconfig | 3 + + arch/arm/configs/bcmrpi_defconfig | 3 + + arch/arm/mach-bcm2708/bcm2708.c | 13 +- + arch/arm/mach-bcm2709/bcm2709.c | 13 +- + drivers/mailbox/Kconfig | 2 +- + drivers/mailbox/bcm2708-vcio.c | 353 ++-------------------------------- + 7 files changed, 51 insertions(+), 344 deletions(-) + +--- a/arch/arm/boot/dts/bcm2708_common.dtsi ++++ b/arch/arm/boot/dts/bcm2708_common.dtsi +@@ -74,9 +74,10 @@ + }; + + mailbox: mailbox@7e00b800 { +- compatible = "brcm,bcm2708-vcio"; ++ compatible = "brcm,bcm2835-mbox"; + reg = <0x7e00b880 0x40>; + interrupts = <0 1>; ++ #mbox-cells = <0>; + }; + + watchdog: watchdog@7e100000 { +@@ -205,6 +206,11 @@ + <1 9>; + }; + ++ firmware: firmware { ++ compatible = "raspberrypi,bcm2835-firmware"; ++ mboxes = <&mailbox>; ++ }; ++ + leds: leds { + compatible = "gpio-leds"; + }; +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -574,6 +574,7 @@ CONFIG_HW_RANDOM_BCM2708=m + CONFIG_RAW_DRIVER=y + CONFIG_BRCM_CHAR_DRIVERS=y + CONFIG_BCM_VC_CMA=y ++CONFIG_BCM_VCIO=y + CONFIG_BCM_VC_SM=y + CONFIG_I2C=y + CONFIG_I2C_CHARDEV=m +@@ -1074,6 +1075,7 @@ CONFIG_FB_FLEX=m + CONFIG_FB_TFT_FBTFT_DEVICE=m + CONFIG_MAILBOX=y + CONFIG_BCM2708_MBOX=y ++CONFIG_BCM2835_MBOX=y + # CONFIG_IOMMU_SUPPORT is not set + CONFIG_EXTCON=m + CONFIG_EXTCON_ARIZONA=m +@@ -1082,6 +1084,7 @@ CONFIG_IIO_BUFFER=y + CONFIG_IIO_BUFFER_CB=y + CONFIG_IIO_KFIFO_BUF=m + CONFIG_DHT11=m ++CONFIG_RASPBERRYPI_FIRMWARE=y + CONFIG_EXT4_FS=y + CONFIG_EXT4_FS_POSIX_ACL=y + CONFIG_EXT4_FS_SECURITY=y +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -567,6 +567,7 @@ CONFIG_HW_RANDOM_BCM2708=m + CONFIG_RAW_DRIVER=y + CONFIG_BRCM_CHAR_DRIVERS=y + CONFIG_BCM_VC_CMA=y ++CONFIG_BCM_VCIO=y + CONFIG_BCM_VC_SM=y + CONFIG_I2C=y + CONFIG_I2C_CHARDEV=m +@@ -1067,6 +1068,7 @@ CONFIG_FB_FLEX=m + CONFIG_FB_TFT_FBTFT_DEVICE=m + CONFIG_MAILBOX=y + CONFIG_BCM2708_MBOX=y ++CONFIG_BCM2835_MBOX=y + # CONFIG_IOMMU_SUPPORT is not set + CONFIG_EXTCON=m + CONFIG_EXTCON_ARIZONA=m +@@ -1075,6 +1077,7 @@ CONFIG_IIO_BUFFER=y + CONFIG_IIO_BUFFER_CB=y + CONFIG_IIO_KFIFO_BUF=m + CONFIG_DHT11=m ++CONFIG_RASPBERRYPI_FIRMWARE=y + CONFIG_EXT4_FS=y + CONFIG_EXT4_FS_POSIX_ACL=y + CONFIG_EXT4_FS_SECURITY=y +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -405,7 +405,7 @@ static struct resource bcm2708_vcio_reso + static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + + static struct platform_device bcm2708_vcio_device = { +- .name = "bcm2708_vcio", ++ .name = "bcm2835-mbox", + .id = -1, /* only one VideoCore I/O area */ + .resource = bcm2708_vcio_resources, + .num_resources = ARRAY_SIZE(bcm2708_vcio_resources), +@@ -415,6 +415,16 @@ static struct platform_device bcm2708_vc + }, + }; + ++static u64 rpifw_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++static struct platform_device bcm2708_rpifw_device = { ++ .name = "raspberrypi-firmware", ++ .dev = { ++ .dma_mask = &rpifw_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++ + static struct resource bcm2708_vchiq_resources[] = { + { + .start = ARMCTRL_0_BELL_BASE, +@@ -871,6 +881,7 @@ void __init bcm2708_init(void) + + bcm_register_device_dt(&bcm2708_dmaengine_device); + bcm_register_device_dt(&bcm2708_vcio_device); ++ bcm_register_device_dt(&bcm2708_rpifw_device); + bcm_register_device_dt(&bcm2708_vchiq_device); + #ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); +--- a/arch/arm/mach-bcm2709/bcm2709.c ++++ b/arch/arm/mach-bcm2709/bcm2709.c +@@ -426,7 +426,7 @@ static struct resource bcm2708_vcio_reso + static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + + static struct platform_device bcm2708_vcio_device = { +- .name = "bcm2708_vcio", ++ .name = "bcm2835-mbox", + .id = -1, /* only one VideoCore I/O area */ + .resource = bcm2708_vcio_resources, + .num_resources = ARRAY_SIZE(bcm2708_vcio_resources), +@@ -436,6 +436,16 @@ static struct platform_device bcm2708_vc + }, + }; + ++static u64 rpifw_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++static struct platform_device bcm2708_rpifw_device = { ++ .name = "raspberrypi-firmware", ++ .dev = { ++ .dma_mask = &rpifw_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++ + static struct resource bcm2708_vchiq_resources[] = { + { + .start = ARMCTRL_0_BELL_BASE, +@@ -892,6 +902,7 @@ void __init bcm2709_init(void) + + bcm_register_device_dt(&bcm2708_dmaengine_device); + bcm_register_device_dt(&bcm2708_vcio_device); ++ bcm_register_device_dt(&bcm2708_rpifw_device); + bcm_register_device_dt(&bcm2708_vchiq_device); + #ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); +--- a/drivers/mailbox/Kconfig ++++ b/drivers/mailbox/Kconfig +@@ -9,7 +9,7 @@ if MAILBOX + + config BCM2708_MBOX + bool "Broadcom BCM2708 Mailbox (vcio)" +- depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 ++ depends on BCM2835_MBOX + help + Broadcom BCM2708 Mailbox (vcio) + +--- a/drivers/mailbox/bcm2708-vcio.c ++++ b/drivers/mailbox/bcm2708-vcio.c +@@ -1,6 +1,4 @@ + /* +- * linux/arch/arm/mach-bcm2708/vcio.c +- * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify +@@ -12,195 +10,38 @@ + * VideoCore processor + */ + +-#include <linux/device.h> + #include <linux/dma-mapping.h> +-#include <linux/module.h> +-#include <linux/errno.h> +-#include <linux/fs.h> + #include <linux/init.h> +-#include <linux/interrupt.h> +-#include <linux/io.h> +-#include <linux/ioctl.h> ++#include <linux/module.h> + #include <linux/platform_data/mailbox-bcm2708.h> +-#include <linux/platform_device.h> + #include <linux/uaccess.h> ++#include <soc/bcm2835/raspberrypi-firmware.h> + + #define DRIVER_NAME "bcm2708_vcio" +-#define DEVICE_FILE_NAME "vcio" +- +-/* offsets from a mail box base address */ +-#define MAIL0_RD 0x00 /* read - and next 4 words */ +-#define MAIL0_POL 0x10 /* read without popping the fifo */ +-#define MAIL0_SND 0x14 /* sender ID (bottom two bits) */ +-#define MAIL0_STA 0x18 /* status */ +-#define MAIL0_CNF 0x1C /* configuration */ +-#define MAIL1_WRT 0x20 /* write - and next 4 words */ +-#define MAIL1_STA 0x38 /* status */ +- +-/* On MACH_BCM270x these come through <linux/interrupt.h> (arm_control.h ) */ +-#ifndef ARM_MS_EMPTY +-#define ARM_MS_EMPTY BIT(30) +-#define ARM_MS_FULL BIT(31) +- +-#define ARM_MC_IHAVEDATAIRQEN BIT(0) +-#endif +- +-#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) +-#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) +-#define MBOX_CHAN(msg) ((msg) & 0xf) +-#define MBOX_DATA28(msg) ((msg) & ~0xf) +-#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) +- +-#define MBOX_MAGIC 0xd0d0c0de +- +-#define MAJOR_NUM 100 +-#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) +- +-static struct class *vcio_class; +- +-struct vc_mailbox { +- void __iomem *regs; +- uint32_t msg[MBOX_CHAN_COUNT]; +- struct semaphore sema[MBOX_CHAN_COUNT]; +- uint32_t magic; +-}; +- +-static void mbox_init(struct vc_mailbox *mbox_out) +-{ +- int i; +- +- for (i = 0; i < MBOX_CHAN_COUNT; i++) { +- mbox_out->msg[i] = 0; +- sema_init(&mbox_out->sema[i], 0); +- } +- +- /* Enable the interrupt on data reception */ +- writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->regs + MAIL0_CNF); +- +- mbox_out->magic = MBOX_MAGIC; +-} +- +-static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) +-{ +- if (mbox->magic != MBOX_MAGIC) +- return -EINVAL; +- +- /* wait for the mailbox FIFO to have some space in it */ +- while (0 != (readl(mbox->regs + MAIL1_STA) & ARM_MS_FULL)) +- cpu_relax(); +- +- writel(MBOX_MSG(chan, data28), mbox->regs + MAIL1_WRT); +- +- return 0; +-} +- +-static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) +-{ +- if (mbox->magic != MBOX_MAGIC) +- return -EINVAL; +- +- down(&mbox->sema[chan]); +- *data28 = MBOX_DATA28(mbox->msg[chan]); +- mbox->msg[chan] = 0; +- +- return 0; +-} +- +-static irqreturn_t mbox_irq_handler(int irq, void *dev_id) +-{ +- /* wait for the mailbox FIFO to have some data in it */ +- struct vc_mailbox *mbox = (struct vc_mailbox *)dev_id; +- int status = readl(mbox->regs + MAIL0_STA); +- int ret = IRQ_NONE; +- +- while (!(status & ARM_MS_EMPTY)) { +- uint32_t msg = readl(mbox->regs + MAIL0_RD); +- int chan = MBOX_CHAN(msg); +- +- if (chan < MBOX_CHAN_COUNT) { +- if (mbox->msg[chan]) { +- pr_err(DRIVER_NAME +- ": mbox chan %d overflow - drop %08x\n", +- chan, msg); +- } else { +- mbox->msg[chan] = (msg | 0xf); +- up(&mbox->sema[chan]); +- } +- } else { +- pr_err(DRIVER_NAME +- ": invalid channel selector (msg %08x)\n", msg); +- } +- ret = IRQ_HANDLED; +- status = readl(mbox->regs + MAIL0_STA); +- } +- return ret; +-} +- +-/* Mailbox Methods */ +- +-static struct device *mbox_dev; /* we assume there's only one! */ +- +-static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) +-{ +- struct vc_mailbox *mailbox = dev_get_drvdata(dev); +- int rc; +- +- device_lock(dev); +- rc = mbox_write(mailbox, chan, data28); +- device_unlock(dev); +- +- return rc; +-} +- +-static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) +-{ +- struct vc_mailbox *mailbox = dev_get_drvdata(dev); +- int rc; +- +- device_lock(dev); +- rc = mbox_read(mailbox, chan, data28); +- device_unlock(dev); +- +- return rc; +-} + + extern int bcm_mailbox_write(unsigned chan, uint32_t data28) + { +- if (!mbox_dev) ++ struct rpi_firmware *fw = rpi_firmware_get(NULL); ++ ++ if (!fw) + return -ENODEV; + +- return dev_mbox_write(mbox_dev, chan, data28); ++ return rpi_firmware_transaction(fw, chan, data28); + } + EXPORT_SYMBOL_GPL(bcm_mailbox_write); + + extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) + { +- if (!mbox_dev) +- return -ENODEV; +- +- return dev_mbox_read(mbox_dev, chan, data28); +-} +-EXPORT_SYMBOL_GPL(bcm_mailbox_read); +- +-static int mbox_copy_from_user(void *dst, const void *src, int size) +-{ +- if ((uint32_t)src < TASK_SIZE) +- return copy_from_user(dst, src, size); +- +- memcpy(dst, src, size); ++ struct rpi_firmware *fw = rpi_firmware_get(NULL); + +- return 0; +-} +- +-static int mbox_copy_to_user(void *dst, const void *src, int size) +-{ +- if ((uint32_t)dst < TASK_SIZE) +- return copy_to_user(dst, src, size); ++ if (!fw) ++ return -ENODEV; + +- memcpy(dst, src, size); ++ *data28 = rpi_firmware_transaction_received(fw); + + return 0; + } ++EXPORT_SYMBOL_GPL(bcm_mailbox_read); + + static DEFINE_MUTEX(mailbox_lock); + extern int bcm_mailbox_property(void *data, int size) +@@ -216,7 +57,7 @@ extern int bcm_mailbox_property(void *da + GFP_KERNEL); + if (mem_kern) { + /* create the message */ +- mbox_copy_from_user(mem_kern, data, size); ++ memcpy(mem_kern, data, size); + + /* send the message */ + wmb(); +@@ -226,7 +67,7 @@ extern int bcm_mailbox_property(void *da + if (s == 0) { + /* copy the response */ + rmb(); +- mbox_copy_to_user(data, mem_kern, size); ++ memcpy(data, mem_kern, size); + } + dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus); + } else { +@@ -240,174 +81,6 @@ extern int bcm_mailbox_property(void *da + } + EXPORT_SYMBOL_GPL(bcm_mailbox_property); + +-/* Platform Device for Mailbox */ +- +-/* This is called whenever a process attempts to open the device file */ +-static int device_open(struct inode *inode, struct file *file) +-{ +- try_module_get(THIS_MODULE); +- +- return 0; +-} +- +-static int device_release(struct inode *inode, struct file *file) +-{ +- module_put(THIS_MODULE); +- +- return 0; +-} +- +-/* +- * This function is called whenever a process tries to do an ioctl on our +- * device file. We get two extra parameters (additional to the inode and file +- * structures, which all device functions get): the number of the ioctl called +- * and the parameter given to the ioctl function. +- * +- * If the ioctl is write or read/write (meaning output is returned to the +- * calling process), the ioctl call returns the output of this function. +- * +- */ +-static long device_ioctl(struct file *file, unsigned int ioctl_num, +- unsigned long ioctl_param) +-{ +- unsigned size; +- +- switch (ioctl_num) { +- case IOCTL_MBOX_PROPERTY: +- /* +- * Receive a pointer to a message (in user space) and set that +- * to be the device's message. Get the parameter given to +- * ioctl by the process. +- */ +- mbox_copy_from_user(&size, (void *)ioctl_param, sizeof(size)); +- return bcm_mailbox_property((void *)ioctl_param, size); +- default: +- pr_err(DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); +- return -EINVAL; +- } +- +- return 0; +-} +- +-/* Module Declarations */ +- +-/* +- * This structure will hold the functions to be called +- * when a process does something to the device we +- * created. Since a pointer to this structure is kept in +- * the devices table, it can't be local to +- * init_module. NULL is for unimplemented functios. +- */ +-const struct file_operations fops = { +- .unlocked_ioctl = device_ioctl, +- .open = device_open, +- .release = device_release, /* a.k.a. close */ +-}; +- +-static int bcm_vcio_probe(struct platform_device *pdev) +-{ +- struct device *dev = &pdev->dev; +- struct device *vdev; +- struct vc_mailbox *mailbox; +- struct resource *res; +- int irq, ret; +- +- mailbox = devm_kzalloc(dev, sizeof(*mailbox), GFP_KERNEL); +- if (!mailbox) +- return -ENOMEM; +- +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- mailbox->regs = devm_ioremap_resource(dev, res); +- if (IS_ERR(mailbox->regs)) +- return PTR_ERR(mailbox->regs); +- +- irq = platform_get_irq(pdev, 0); +- ret = devm_request_irq(dev, irq, mbox_irq_handler, +- IRQF_IRQPOLL, +- dev_name(dev), mailbox); +- if (ret) { +- dev_err(dev, "Interrupt request failed %d\n", ret); +- return ret; +- } +- +- ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); +- if (ret < 0) { +- pr_err("Character device registration failed %d\n", ret); +- return ret; +- } +- +- vcio_class = class_create(THIS_MODULE, DRIVER_NAME); +- if (IS_ERR(vcio_class)) { +- ret = PTR_ERR(vcio_class); +- pr_err("Class creation failed %d\n", ret); +- goto err_class; +- } +- +- vdev = device_create(vcio_class, NULL, MKDEV(MAJOR_NUM, 0), NULL, +- "vcio"); +- if (IS_ERR(vdev)) { +- ret = PTR_ERR(vdev); +- pr_err("Device creation failed %d\n", ret); +- goto err_dev; +- } +- +- mbox_init(mailbox); +- platform_set_drvdata(pdev, mailbox); +- mbox_dev = dev; +- +- dev_info(dev, "mailbox at %p\n", mailbox->regs); +- +- return 0; +- +-err_dev: +- class_destroy(vcio_class); +-err_class: +- unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); +- +- return ret; +-} +- +-static int bcm_vcio_remove(struct platform_device *pdev) +-{ +- mbox_dev = NULL; +- platform_set_drvdata(pdev, NULL); +- device_destroy(vcio_class, MKDEV(MAJOR_NUM, 0)); +- class_destroy(vcio_class); +- unregister_chrdev(MAJOR_NUM, DEVICE_FILE_NAME); +- +- return 0; +-} +- +-static const struct of_device_id bcm_vcio_of_match_table[] = { +- { .compatible = "brcm,bcm2708-vcio", }, +- {}, +-}; +-MODULE_DEVICE_TABLE(of, bcm_vcio_of_match_table); +- +-static struct platform_driver bcm_mbox_driver = { +- .probe = bcm_vcio_probe, +- .remove = bcm_vcio_remove, +- +- .driver = { +- .name = DRIVER_NAME, +- .owner = THIS_MODULE, +- .of_match_table = bcm_vcio_of_match_table, +- }, +-}; +- +-static int __init bcm_mbox_init(void) +-{ +- return platform_driver_register(&bcm_mbox_driver); +-} +- +-static void __exit bcm_mbox_exit(void) +-{ +- platform_driver_unregister(&bcm_mbox_driver); +-} +- +-arch_initcall(bcm_mbox_init); /* Initialize early */ +-module_exit(bcm_mbox_exit); +- + MODULE_AUTHOR("Gray Girling"); + MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); + MODULE_LICENSE("GPL"); |