From 9b331e3fe3724b92be61ec369c61c5c0b2cfbdbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 26 Jun 2015 14:37:19 +0200 Subject: [PATCH 117/203] 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 --- 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 #include -#include -#include -#include #include -#include -#include -#include +#include #include -#include #include +#include #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 (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");