aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-4.4/0533-brcmvirt_gpio-Create-coherent-buffer-and-push-to-fir.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm2708/patches-4.4/0533-brcmvirt_gpio-Create-coherent-buffer-and-push-to-fir.patch')
-rw-r--r--target/linux/brcm2708/patches-4.4/0533-brcmvirt_gpio-Create-coherent-buffer-and-push-to-fir.patch169
1 files changed, 169 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-4.4/0533-brcmvirt_gpio-Create-coherent-buffer-and-push-to-fir.patch b/target/linux/brcm2708/patches-4.4/0533-brcmvirt_gpio-Create-coherent-buffer-and-push-to-fir.patch
new file mode 100644
index 0000000000..ede0abea34
--- /dev/null
+++ b/target/linux/brcm2708/patches-4.4/0533-brcmvirt_gpio-Create-coherent-buffer-and-push-to-fir.patch
@@ -0,0 +1,169 @@
+From 07afae52a73991a3ea948aab5d0303a5a9805b41 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Wed, 9 Nov 2016 22:42:39 +0000
+Subject: [PATCH] brcmvirt_gpio: Create coherent buffer and push to firmware
+
+---
+ drivers/gpio/gpio-bcm-virt.c | 88 +++++++++++++++++++++---------
+ include/soc/bcm2835/raspberrypi-firmware.h | 1 +
+ 2 files changed, 62 insertions(+), 27 deletions(-)
+
+--- a/drivers/gpio/gpio-bcm-virt.c
++++ b/drivers/gpio/gpio-bcm-virt.c
+@@ -15,6 +15,7 @@
+ #include <linux/module.h>
+ #include <linux/basic_mmio_gpio.h>
+ #include <linux/platform_device.h>
++#include <linux/dma-mapping.h>
+ #include <soc/bcm2835/raspberrypi-firmware.h>
+
+ #define MODULE_NAME "brcmvirt-gpio"
+@@ -26,6 +27,7 @@ struct brcmvirt_gpio {
+ /* two packed 16-bit counts of enabled and disables
+ Allows host to detect a brief enable that was missed */
+ u32 enables_disables[NUM_GPIO];
++ dma_addr_t bus_addr;
+ };
+
+ static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off)
+@@ -76,13 +78,13 @@ static void brcmvirt_gpio_set(struct gpi
+
+ static int brcmvirt_gpio_probe(struct platform_device *pdev)
+ {
++ int err = 0;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct device_node *fw_node;
+ struct rpi_firmware *fw;
+ struct brcmvirt_gpio *ucb;
+ u32 gpiovirtbuf;
+- int err = 0;
+
+ fw_node = of_parse_phandle(np, "firmware", 0);
+ if (!fw_node) {
+@@ -94,35 +96,56 @@ static int brcmvirt_gpio_probe(struct pl
+ if (!fw)
+ return -EPROBE_DEFER;
+
+- err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF,
+- &gpiovirtbuf, sizeof(gpiovirtbuf));
+-
+- if (err) {
+- dev_err(dev, "Failed to get gpiovirtbuf\n");
+- goto err;
+- }
+-
+- if (!gpiovirtbuf) {
+- dev_err(dev, "No virtgpio buffer\n");
+- err = -ENOENT;
+- goto err;
+- }
+-
+ ucb = devm_kzalloc(dev, sizeof *ucb, GFP_KERNEL);
+ if (!ucb) {
+ err = -EINVAL;
+- goto err;
++ goto out;
+ }
+
+- // mmap the physical memory
+- gpiovirtbuf &= ~0xc0000000;
+- ucb->ts_base = ioremap(gpiovirtbuf, 4096);
+- if (ucb->ts_base == NULL) {
+- dev_err(dev, "Failed to map physical address\n");
+- err = -ENOENT;
+- goto err;
++ ucb->ts_base = dma_zalloc_coherent(NULL, PAGE_SIZE, &ucb->bus_addr, GFP_KERNEL);
++ if (!ucb->ts_base) {
++ pr_err("[%s]: failed to dma_alloc_coherent(%ld)\n",
++ __func__, PAGE_SIZE);
++ err = -ENOMEM;
++ goto out;
+ }
+
++ gpiovirtbuf = (u32)ucb->bus_addr;
++ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF,
++ &gpiovirtbuf, sizeof(gpiovirtbuf));
++
++ if (err || gpiovirtbuf != 0) {
++ dev_warn(dev, "Failed to set gpiovirtbuf, trying to get err:%x\n", err);
++ dma_free_coherent(NULL, PAGE_SIZE, ucb->ts_base, ucb->bus_addr);
++ ucb->ts_base = 0;
++ ucb->bus_addr = 0;
++ }
++
++ if (!ucb->ts_base) {
++ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF,
++ &gpiovirtbuf, sizeof(gpiovirtbuf));
++
++ if (err) {
++ dev_err(dev, "Failed to get gpiovirtbuf\n");
++ goto out;
++ }
++
++ if (!gpiovirtbuf) {
++ dev_err(dev, "No virtgpio buffer\n");
++ err = -ENOENT;
++ goto out;
++ }
++
++ // mmap the physical memory
++ gpiovirtbuf &= ~0xc0000000;
++ ucb->ts_base = ioremap(gpiovirtbuf, 4096);
++ if (ucb->ts_base == NULL) {
++ dev_err(dev, "Failed to map physical address\n");
++ err = -ENOENT;
++ goto out;
++ }
++ ucb->bus_addr = 0;
++ }
+ ucb->gc.label = MODULE_NAME;
+ ucb->gc.owner = THIS_MODULE;
+ ucb->gc.dev = dev;
+@@ -138,13 +161,21 @@ static int brcmvirt_gpio_probe(struct pl
+
+ err = gpiochip_add(&ucb->gc);
+ if (err)
+- goto err;
++ goto out;
+
+ platform_set_drvdata(pdev, ucb);
+
+-err:
++ return 0;
++out:
++ if (ucb->bus_addr) {
++ dma_free_coherent(NULL, PAGE_SIZE, ucb->ts_base, ucb->bus_addr);
++ ucb->bus_addr = 0;
++ ucb->ts_base = NULL;
++ } else if (ucb->ts_base) {
++ iounmap(ucb->ts_base);
++ ucb->ts_base = NULL;
++ }
+ return err;
+-
+ }
+
+ static int brcmvirt_gpio_remove(struct platform_device *pdev)
+@@ -153,7 +184,10 @@ static int brcmvirt_gpio_remove(struct p
+ struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev);
+
+ gpiochip_remove(&ucb->gc);
+- iounmap(ucb->ts_base);
++ if (ucb->bus_addr)
++ dma_free_coherent(NULL, PAGE_SIZE, ucb->ts_base, ucb->bus_addr);
++ else if (ucb->ts_base)
++ iounmap(ucb->ts_base);
+ return err;
+ }
+
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -118,6 +118,7 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f,
++ RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f,
+