From 79ea239874848e67d42b9274d4f7eeb51892ccd8 Mon Sep 17 00:00:00 2001 From: popcornmix <popcornmix@gmail.com> Date: Tue, 23 Feb 2016 19:56:04 +0000 Subject: [PATCH 159/381] bcm2835-virtgpio: Virtual GPIO driver Add a virtual GPIO driver that uses the firmware mailbox interface to request that the VPU toggles LEDs. --- arch/arm/configs/bcm2709_defconfig | 1 + drivers/gpio/Kconfig | 6 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-bcm-virt.c | 180 +++++++++++++++++++++++++++++ include/soc/bcm2835/raspberrypi-firmware.h | 1 + 5 files changed, 189 insertions(+) create mode 100644 drivers/gpio/gpio-bcm-virt.c --- a/arch/arm/configs/bcm2709_defconfig +++ b/arch/arm/configs/bcm2709_defconfig @@ -607,6 +607,7 @@ CONFIG_PPS=m CONFIG_PPS_CLIENT_LDISC=m CONFIG_PPS_CLIENT_GPIO=m CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_BCM_VIRT=y CONFIG_GPIO_ARIZONA=m CONFIG_GPIO_STMPE=y CONFIG_W1=m --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -132,6 +132,12 @@ config GPIO_BCM_KONA help Turn on GPIO support for Broadcom "Kona" chips. +config GPIO_BCM_VIRT + bool "Broadcom Virt GPIO" + depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST) + help + Turn on virtual GPIO support for Broadcom BCM283X chips. + config GPIO_BRCMSTB tristate "BRCMSTB GPIO support" default y if ARCH_BRCMSTB --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o obj-$(CONFIG_ATH79) += gpio-ath79.o obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o +obj-$(CONFIG_GPIO_BCM_VIRT) += gpio-bcm-virt.o obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o --- /dev/null +++ b/drivers/gpio/gpio-bcm-virt.c @@ -0,0 +1,180 @@ +/* + * brcmvirt GPIO driver + * + * Copyright (C) 2012,2013 Dom Cobley <popcornmix@gmail.com> + * Based on gpio-clps711x.c by Alexander Shiyan <shc_work@mail.ru> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/module.h> +#include <linux/basic_mmio_gpio.h> +#include <linux/platform_device.h> +#include <soc/bcm2835/raspberrypi-firmware.h> + +#define MODULE_NAME "brcmvirt-gpio" +#define NUM_GPIO 2 + +struct brcmvirt_gpio { + struct gpio_chip gc; + u32 __iomem *ts_base; + /* two packed 16-bit counts of enabled and disables + Allows host to detect a brief enable that was missed */ + u32 enables_disables[NUM_GPIO]; +}; + +static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off) +{ + struct brcmvirt_gpio *gpio; + gpio = container_of(gc, struct brcmvirt_gpio, gc); + return -EINVAL; +} + +static int brcmvirt_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val) +{ + struct brcmvirt_gpio *gpio; + gpio = container_of(gc, struct brcmvirt_gpio, gc); + return 0; +} + +static int brcmvirt_gpio_get(struct gpio_chip *gc, unsigned off) +{ + struct brcmvirt_gpio *gpio; + unsigned v; + gpio = container_of(gc, struct brcmvirt_gpio, gc); + v = readl(gpio->ts_base + off); + return (v >> off) & 1; +} + +static void brcmvirt_gpio_set(struct gpio_chip *gc, unsigned off, int val) +{ + struct brcmvirt_gpio *gpio; + u16 enables, disables; + s16 diff; + bool lit; + gpio = container_of(gc, struct brcmvirt_gpio, gc); + enables = gpio->enables_disables[off] >> 16; + disables = gpio->enables_disables[off] >> 0; + diff = (s16)(enables - disables); + lit = diff > 0; + if ((val && lit) || (!val && !lit)) + return; + if (val) + enables++; + else + disables++; + diff = (s16)(enables - disables); + BUG_ON(diff != 0 && diff != 1); + gpio->enables_disables[off] = (enables << 16) | (disables << 0); + writel(gpio->enables_disables[off], gpio->ts_base + off); +} + +static int brcmvirt_gpio_probe(struct platform_device *pdev) +{ + 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) { + dev_err(dev, "Missing firmware node\n"); + return -ENOENT; + } + + fw = rpi_firmware_get(fw_node); + 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; + } + + // 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->gc.label = MODULE_NAME; + ucb->gc.owner = THIS_MODULE; + ucb->gc.dev = dev; + ucb->gc.of_node = np; + ucb->gc.base = 100; + ucb->gc.ngpio = NUM_GPIO; + + ucb->gc.direction_input = brcmvirt_gpio_dir_in; + ucb->gc.direction_output = brcmvirt_gpio_dir_out; + ucb->gc.get = brcmvirt_gpio_get; + ucb->gc.set = brcmvirt_gpio_set; + ucb->gc.can_sleep = true; + + err = gpiochip_add(&ucb->gc); + if (err) + goto err; + + platform_set_drvdata(pdev, ucb); + +err: + return err; + +} + +static int brcmvirt_gpio_remove(struct platform_device *pdev) +{ + int err = 0; + struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev); + + g<style>pre { line-height: 125%; margin: 0; } td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; } span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; } td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; } .highlight .hll { background-color: #ffffcc } .highlight { background: #ffffff; } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span>From 561918ec5e668f9d940051737d861ee0592816f6 Mon Sep 17 00:00:00 2001 From: Eric Anholt <eric@anholt.net> Date: Fri, 29 Mar 2019 12:04:36 -0700 Subject: [PATCH 588/806] drm/vc4: Make sure that vblank waits work without v3d loaded. This flag exists to protect legacy drivers, but when vc4's v3d doesn't probe, it doesn't get set up by vc4_v3d.c's call of drm_irq_install. This resulted in applications running as fast as possible, and laggy performance from compton as it had to wait for the latest rendering by the application for its presentation. Signed-off-by: Eric Anholt <eric@anholt.net> <span class="gd">---</span> drivers/gpu/drm/vc4/vc4_kms.c | 1 + 1 file changed, 1 insertion(+) <span class="gd">--- a/drivers/gpu/drm/vc4/vc4_kms.c</span> <span class="gi">+++ b/drivers/gpu/drm/vc4/vc4_kms.c</span> <span class="gu">@@ -422,6 +422,7 @@ int vc4_kms_load(struct drm_device *dev)</span> /* Set support for vblank irq fast disable, before drm_vblank_init() */ dev->vblank_disable_immediate = true; <span class="gi">+ dev->irq_enabled = true;</span> ret = drm_vblank_init(dev, dev->mode_config.num_crtc); if (ret < 0) { dev_err(dev->dev, "failed to initialize vblank\n"); </pre></div> </code></pre></td></tr></table> </div> <!-- class=content --> <div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.3</a> (<a href='https://git-scm.com/'>git 2.25.1</a>) at 2025-03-02 02:06:02 +0000</div> </div> <!-- id=cgit --> </body> </html>