summaryrefslogtreecommitdiff
path: root/target/linux/brcm2708/patches-4.1/0117-BCM270x-Switch-to-firmware-driver.patch
diff options
context:
space:
mode:
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.patch595
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 0000000..cf2555b
--- /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");