diff options
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.patch | 169 |
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, + |