* [PATCH v2 0/2] gpio: mediatek: driver for gpio chip in MT7621 SoC @ 2018-06-29 12:43 Sergio Paracuellos 2018-06-29 12:43 ` [PATCH v2 1/2] gpio: mediatek: add driver for MT7621 Sergio Paracuellos 2018-06-29 12:43 ` [PATCH v2 2/2] dt-bindings: document gpio-mt7621 bindings Sergio Paracuellos 0 siblings, 2 replies; 10+ messages in thread From: Sergio Paracuellos @ 2018-06-29 12:43 UTC (permalink / raw) To: linus.walleij Cc: devicetree, gregkh, driverdev-devel, linux-gpio, robh+dt, neil This patch series add support for gpio driver in mediatek MT7621 SoC. This driver has been in staging for a while and after some cleanups cycles we consider to give it a new try to get mainlined. Previous comments from Linus Walleij are here: http://driverdev.linuxdriverproject.org/pipermail/driverdev-devel/2018-June/121742.html Comments from Rob Herring are here: http://driverdev.linuxdriverproject.org/pipermail/driverdev-devel/2018-June/121974.html Changes in v2 are the ones pointed out in previous mails: - use bgpio_init - avoid custom irq_domain using IRQF_SHARED and gpiochip_set_chained_irqchip from GPIOLIB_IRQCHIP - use only one node in the device tree making it simple - Implement high and low level irqs - avoid include gpio.h - use builtin_platform_driver - add COMPILE_TEST - cleanups after this changes Hope this helps and thanks in advance. Best regards, Sergio Paracuellos Sergio Paracuellos (2): gpio: mediatek: add driver for MT7621 dt-bindings: document gpio-mt7621 bindings .../bindings/gpio/mediatek,mt7621-gpio.txt | 35 +++ drivers/gpio/Kconfig | 8 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-mt7621.c | 320 +++++++++++++++++++++ 4 files changed, 364 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/mediatek,mt7621-gpio.txt create mode 100644 drivers/gpio/gpio-mt7621.c -- 2.7.4 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 1/2] gpio: mediatek: add driver for MT7621 2018-06-29 12:43 [PATCH v2 0/2] gpio: mediatek: driver for gpio chip in MT7621 SoC Sergio Paracuellos @ 2018-06-29 12:43 ` Sergio Paracuellos 2018-06-29 13:31 ` Dan Carpenter ` (2 more replies) 2018-06-29 12:43 ` [PATCH v2 2/2] dt-bindings: document gpio-mt7621 bindings Sergio Paracuellos 1 sibling, 3 replies; 10+ messages in thread From: Sergio Paracuellos @ 2018-06-29 12:43 UTC (permalink / raw) To: linus.walleij Cc: devicetree, gregkh, driverdev-devel, linux-gpio, robh+dt, neil Add driver support for gpio of MT7621 SoC. Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> --- drivers/gpio/Kconfig | 8 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-mt7621.c | 320 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 329 insertions(+) create mode 100644 drivers/gpio/gpio-mt7621.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 71c0ab4..836aa21 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -359,6 +359,14 @@ config GPIO_MPC8XXX Say Y here if you're going to use hardware that connects to the MPC512x/831x/834x/837x/8572/8610/QorIQ GPIOs. +config GPIO_MT7621 + bool "Mediatek MT7621 GPIO Support" + depends on SOC_MT7620 || SOC_MT7621 || COMPILE_TEST + select GPIO_GENERIC + select GPIOLIB_IRQCHIP + help + Say yes here to support the Mediatek MT7621 SoC GPIO device + config GPIO_MVEBU def_bool y depends on PLAT_ORION || ARCH_MVEBU diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 1324c8f..b264426 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -88,6 +88,7 @@ obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o +obj-$(CONFIG_GPIO_MSIC) += gpio-mt7621.o obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c new file mode 100644 index 0000000..281e621 --- /dev/null +++ b/drivers/gpio/gpio-mt7621.c @@ -0,0 +1,320 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/err.h> +#include <linux/gpio/driver.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_irq.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> + +#define MTK_BANK_CNT 3 +#define MTK_BANK_WIDTH 32 + +#define GPIO_BANK_WIDE 0x04 +#define GPIO_REG_CTRL 0x00 +#define GPIO_REG_POL 0x10 +#define GPIO_REG_DATA 0x20 +#define GPIO_REG_DSET 0x30 +#define GPIO_REG_DCLR 0x40 +#define GPIO_REG_REDGE 0x50 +#define GPIO_REG_FEDGE 0x60 +#define GPIO_REG_HLVL 0x70 +#define GPIO_REG_LLVL 0x80 +#define GPIO_REG_STAT 0x90 +#define GPIO_REG_EDGE 0xA0 + +struct mtk_gc { + struct gpio_chip chip; + spinlock_t lock; + int bank; + u32 rising; + u32 falling; + u32 hlevel; + u32 llevel; +}; + +/** + * struct mtk_data - state container for + * data of the platform driver. It is 3 + * separate gpio-chip each one with its + * own irq_chip. + * @dev: device instance + * @gpio_membase: memory base address + * @gpio_irq: irq number from the device tree + * @gc_map: array of the gpio chips + */ +struct mtk_data { + struct device *dev; + void __iomem *gpio_membase; + int gpio_irq; + struct mtk_gc gc_map[MTK_BANK_CNT]; +}; + +static inline struct mtk_gc * +to_mediatek_gpio(struct gpio_chip *chip) +{ + return container_of(chip, struct mtk_gc, chip); +} + +static inline void +mtk_gpio_w32(struct mtk_gc *rg, u32 offset, u32 val) +{ + struct gpio_chip *gc = &rg->chip; + struct mtk_data *gpio_data = gpiochip_get_data(gc); + + offset = (rg->bank * GPIO_BANK_WIDE) + offset; + gc->write_reg(gpio_data->gpio_membase + offset, val); +} + +static inline u32 +mtk_gpio_r32(struct mtk_gc *rg, u32 offset) +{ + struct gpio_chip *gc = &rg->chip; + struct mtk_data *gpio_data = gpiochip_get_data(gc); + + offset = (rg->bank * GPIO_BANK_WIDE) + offset; + return gc->read_reg(gpio_data->gpio_membase + offset); +} + +static irqreturn_t +mediatek_gpio_irq_handler(int irq, void *data) +{ + struct gpio_chip *gc = data; + struct mtk_gc *rg = to_mediatek_gpio(gc); + irqreturn_t ret = IRQ_NONE; + unsigned long pending; + int bit; + + pending = mtk_gpio_r32(rg, GPIO_REG_STAT); + + for_each_set_bit(bit, &pending, MTK_BANK_WIDTH) { + u32 map = irq_find_mapping(gc->irq.domain, bit); + + generic_handle_irq(map); + mtk_gpio_w32(rg, GPIO_REG_STAT, BIT(bit)); + ret |= IRQ_HANDLED; + } + + return ret; +} + +static void +mediatek_gpio_irq_unmask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct mtk_gc *rg = to_mediatek_gpio(gc); + int pin = d->hwirq; + unsigned long flags; + u32 rise, fall, high, low; + + spin_lock_irqsave(&rg->lock, flags); + rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); + fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); + high = mtk_gpio_r32(rg, GPIO_REG_HLVL); + low = mtk_gpio_r32(rg, GPIO_REG_LLVL); + mtk_gpio_w32(rg, GPIO_REG_REDGE, rise | (BIT(pin) & rg->rising)); + mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall | (BIT(pin) & rg->falling)); + mtk_gpio_w32(rg, GPIO_REG_HLVL, high | (BIT(pin) & rg->hlevel)); + mtk_gpio_w32(rg, GPIO_REG_LLVL, low | (BIT(pin) & rg->llevel)); + spin_unlock_irqrestore(&rg->lock, flags); +} + +static void +mediatek_gpio_irq_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct mtk_gc *rg = to_mediatek_gpio(gc); + int pin = d->hwirq; + unsigned long flags; + u32 rise, fall, high, low; + + spin_lock_irqsave(&rg->lock, flags); + rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); + fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); + high = mtk_gpio_r32(rg, GPIO_REG_HLVL); + low = mtk_gpio_r32(rg, GPIO_REG_LLVL); + mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall & ~BIT(pin)); + mtk_gpio_w32(rg, GPIO_REG_REDGE, rise & ~BIT(pin)); + mtk_gpio_w32(rg, GPIO_REG_HLVL, high & ~BIT(pin)); + mtk_gpio_w32(rg, GPIO_REG_LLVL, low & ~BIT(pin)); + spin_unlock_irqrestore(&rg->lock, flags); +} + +static int +mediatek_gpio_irq_type(struct irq_data *d, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct mtk_gc *rg = to_mediatek_gpio(gc); + int pin = d->hwirq; + u32 mask = BIT(pin); + + if (type == IRQ_TYPE_PROBE) { + if ((rg->rising | rg->falling | + rg->hlevel | rg->llevel) & mask) + return 0; + + type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; + } + + rg->rising &= ~mask; + rg->falling &= ~mask; + rg->hlevel &= ~mask; + rg->llevel &= ~mask; + + switch (type & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_EDGE_BOTH: + rg->rising |= mask; + rg->falling |= mask; + break; + case IRQ_TYPE_EDGE_RISING: + rg->rising |= mask; + break; + case IRQ_TYPE_EDGE_FALLING: + rg->falling |= mask; + break; + case IRQ_TYPE_LEVEL_HIGH: + rg->hlevel |= mask; + break; + case IRQ_TYPE_LEVEL_LOW: + rg->llevel |= mask; + break; + } + + return 0; +} + +static struct irq_chip mediatek_gpio_irq_chip = { + .irq_unmask = mediatek_gpio_irq_unmask, + .irq_mask = mediatek_gpio_irq_mask, + .irq_mask_ack = mediatek_gpio_irq_mask, + .irq_set_type = mediatek_gpio_irq_type, +}; + +static inline const char * const mediatek_gpio_bank_name(int bank) +{ + static const char * const bank_names[] = { + "mt7621-bank0", "mt7621-bank1", "mt7621-bank2", + }; + + return bank_names[bank]; +} + +static int +mediatek_gpio_bank_probe(struct platform_device *pdev, + struct device_node *node, int bank) +{ + struct mtk_data *gpio = dev_get_drvdata(&pdev->dev); + struct mtk_gc *rg; + void __iomem *dat, *set, *ctrl, *diro; + int ret; + + rg = &gpio->gc_map[bank]; + memset(rg, 0, sizeof(*rg)); + + spin_lock_init(&rg->lock); + rg->chip.of_node = node; + rg->bank = bank; + rg->chip.label = mediatek_gpio_bank_name(rg->bank); + + dat = gpio->gpio_membase + GPIO_REG_DATA + (rg->bank * GPIO_BANK_WIDE); + set = gpio->gpio_membase + GPIO_REG_DSET + (rg->bank * GPIO_BANK_WIDE); + ctrl = gpio->gpio_membase + GPIO_REG_DCLR + (rg->bank * GPIO_BANK_WIDE); + diro = gpio->gpio_membase + GPIO_REG_CTRL + (rg->bank * GPIO_BANK_WIDE); + + ret = bgpio_init(&rg->chip, &pdev->dev, 4, + dat, set, ctrl, diro, NULL, 0); + if (ret) { + dev_err(&pdev->dev, "bgpio_init() failed\n"); + return ret; + } + + ret = devm_gpiochip_add_data(&pdev->dev, &rg->chip, gpio); + if (ret < 0) { + dev_err(&pdev->dev, "Could not register gpio %d, ret=%d\n", + rg->chip.ngpio, ret); + return ret; + } + + if (gpio->gpio_irq) { + /* + * Manually request the irq here instead of passing + * a flow-handler to gpiochip_set_chained_irqchip, + * because the irq is shared. + */ + ret = devm_request_irq(&pdev->dev, gpio->gpio_irq, + mediatek_gpio_irq_handler, IRQF_SHARED, + rg->chip.label, &rg->chip); + + if (ret) { + dev_err(&pdev->dev, "Error requesting IRQ %d: %d\n", + gpio->gpio_irq, ret); + return ret; + } + + mediatek_gpio_irq_chip.name = rg->chip.label; + ret = gpiochip_irqchip_add(&rg->chip, &mediatek_gpio_irq_chip, + 0, handle_simple_irq, IRQ_TYPE_NONE); + if (ret) { + dev_err(&pdev->dev, "failed to add gpiochip_irqchip\n"); + return ret; + } + + gpiochip_set_chained_irqchip(&rg->chip, &mediatek_gpio_irq_chip, + gpio->gpio_irq, NULL); + } + + /* set polarity to low for all gpios */ + mtk_gpio_w32(rg, GPIO_REG_POL, 0); + + dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); + + return 0; +} + +static int +mediatek_gpio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct mtk_data *gpio_data; + int i; + + gpio_data = devm_kzalloc(&pdev->dev, sizeof(*gpio_data), GFP_KERNEL); + if (!gpio_data) + return -ENOMEM; + + gpio_data->gpio_membase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(gpio_data->gpio_membase)) + return PTR_ERR(gpio_data->gpio_membase); + + gpio_data->gpio_irq = irq_of_parse_and_map(np, 0); + gpio_data->dev = &pdev->dev; + platform_set_drvdata(pdev, gpio_data); + + for (i = 0; i < MTK_BANK_CNT; i++) + mediatek_gpio_bank_probe(pdev, np, i); + + return 0; +} + +static const struct of_device_id mediatek_gpio_match[] = { + { .compatible = "mediatek,mt7621-gpio" }, + {}, +}; +MODULE_DEVICE_TABLE(of, mediatek_gpio_match); + +static struct platform_driver mediatek_gpio_driver = { + .probe = mediatek_gpio_probe, + .driver = { + .name = "mt7621_gpio", + .of_match_table = mediatek_gpio_match, + }, +}; + +builtin_platform_driver(mediatek_gpio_driver); -- 2.7.4 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] gpio: mediatek: add driver for MT7621 2018-06-29 12:43 ` [PATCH v2 1/2] gpio: mediatek: add driver for MT7621 Sergio Paracuellos @ 2018-06-29 13:31 ` Dan Carpenter 2018-06-29 13:34 ` Dan Carpenter 2018-06-29 13:51 ` Sergio Paracuellos 2018-06-29 16:43 ` kbuild test robot 2018-06-30 6:12 ` Sergio Paracuellos 2 siblings, 2 replies; 10+ messages in thread From: Dan Carpenter @ 2018-06-29 13:31 UTC (permalink / raw) To: Sergio Paracuellos Cc: devicetree, gregkh, linus.walleij, driverdev-devel, linux-gpio, robh+dt, neil Looks pretty clean to me. Sorry for not reviewing v1. Smatch (private devel version) points out a little bit of dead code. drivers/staging/mt7621-gpio/gpio-mt7621.c:200 mediatek_gpio_irq_handler() warn: address of 'gpio_data->gc_map[i]' is non-NULL drivers/staging/mt7621-gpio/gpio-mt7621.c:225 mediatek_gpio_irq_unmask() warn: address of 'gpio_data->gc_map[bank]' is non-NULL drivers/staging/mt7621-gpio/gpio-mt7621.c:246 mediatek_gpio_irq_mask() warn: address of 'gpio_data->gc_map[bank]' is non-NULL drivers/staging/mt7621-gpio/gpio-mt7621.c:266 mediatek_gpio_irq_type() warn: address of 'gpio_data->gc_map[bank]' is non-NULL But that's harmless and very minor. regards, dan carpenter ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] gpio: mediatek: add driver for MT7621 2018-06-29 13:31 ` Dan Carpenter @ 2018-06-29 13:34 ` Dan Carpenter 2018-06-29 13:51 ` Sergio Paracuellos 1 sibling, 0 replies; 10+ messages in thread From: Dan Carpenter @ 2018-06-29 13:34 UTC (permalink / raw) To: Sergio Paracuellos Cc: devicetree, gregkh, linus.walleij, driverdev-devel, linux-gpio, robh+dt, neil On Fri, Jun 29, 2018 at 04:31:35PM +0300, Dan Carpenter wrote: > Looks pretty clean to me. Sorry for not reviewing v1. Smatch (private > devel version) points out a little bit of dead code. > > drivers/staging/mt7621-gpio/gpio-mt7621.c:200 mediatek_gpio_irq_handler() warn: address of 'gpio_data->gc_map[i]' is non-NULL > drivers/staging/mt7621-gpio/gpio-mt7621.c:225 mediatek_gpio_irq_unmask() warn: address of 'gpio_data->gc_map[bank]' is non-NULL > drivers/staging/mt7621-gpio/gpio-mt7621.c:246 mediatek_gpio_irq_mask() warn: address of 'gpio_data->gc_map[bank]' is non-NULL > drivers/staging/mt7621-gpio/gpio-mt7621.c:266 mediatek_gpio_irq_type() warn: address of 'gpio_data->gc_map[bank]' is non-NULL > > But that's harmless and very minor. I think you fixed all these in the non-staging version... That's fine then. regards, dan carpenter ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] gpio: mediatek: add driver for MT7621 2018-06-29 13:31 ` Dan Carpenter 2018-06-29 13:34 ` Dan Carpenter @ 2018-06-29 13:51 ` Sergio Paracuellos 1 sibling, 0 replies; 10+ messages in thread From: Sergio Paracuellos @ 2018-06-29 13:51 UTC (permalink / raw) To: Dan Carpenter Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS, Greg KH, Linus Walleij, driverdev-devel, open list:GPIO SUBSYSTEM, Rob Herring, NeilBrown On Fri, Jun 29, 2018 at 3:31 PM, Dan Carpenter <dan.carpenter@oracle.com> wrote: > Looks pretty clean to me. Sorry for not reviewing v1. Smatch (private > devel version) points out a little bit of dead code. > > drivers/staging/mt7621-gpio/gpio-mt7621.c:200 mediatek_gpio_irq_handler() warn: address of 'gpio_data->gc_map[i]' is non-NULL > drivers/staging/mt7621-gpio/gpio-mt7621.c:225 mediatek_gpio_irq_unmask() warn: address of 'gpio_data->gc_map[bank]' is non-NULL > drivers/staging/mt7621-gpio/gpio-mt7621.c:246 mediatek_gpio_irq_mask() warn: address of 'gpio_data->gc_map[bank]' is non-NULL > drivers/staging/mt7621-gpio/gpio-mt7621.c:266 mediatek_gpio_irq_type() warn: address of 'gpio_data->gc_map[bank]' is non-NULL > > But that's harmless and very minor. That warnings should not being in the staging version. Last patch series was applied yesterday... Maybe you have not run against the updated tree? This patch fix them: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git/commit/?h=staging-testing&id=bfb623c5b0935a2e4b5fe86eab79a37a37b67209 > > regards, > dan carpenter Thanks. Best regards, Sergio Paracuellos > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] gpio: mediatek: add driver for MT7621 2018-06-29 12:43 ` [PATCH v2 1/2] gpio: mediatek: add driver for MT7621 Sergio Paracuellos 2018-06-29 13:31 ` Dan Carpenter @ 2018-06-29 16:43 ` kbuild test robot 2018-06-29 16:52 ` Sergio Paracuellos 2018-06-30 6:12 ` Sergio Paracuellos 2 siblings, 1 reply; 10+ messages in thread From: kbuild test robot @ 2018-06-29 16:43 UTC (permalink / raw) To: Sergio Paracuellos Cc: devicetree, gregkh, linus.walleij, driverdev-devel, linux-gpio, robh+dt, kbuild-all, neil [-- Attachment #1: Type: text/plain, Size: 3634 bytes --] Hi Sergio, Thank you for the patch! Yet something to improve: [auto build test ERROR on gpio/for-next] [also build test ERROR on v4.18-rc2 next-20180629] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Sergio-Paracuellos/gpio-mediatek-driver-for-gpio-chip-in-MT7621-SoC/20180629-225420 base: https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git for-next config: x86_64-randconfig-s0-06292230 (attached as .config) compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 All errors (new ones prefixed by >>): drivers/gpio/gpio-mt7621.c: In function 'mediatek_gpio_bank_probe': >> drivers/gpio/gpio-mt7621.c:221:10: error: 'struct gpio_chip' has no member named 'of_node' rg->chip.of_node = node; ^ vim +221 drivers/gpio/gpio-mt7621.c 207 208 static int 209 mediatek_gpio_bank_probe(struct platform_device *pdev, 210 struct device_node *node, int bank) 211 { 212 struct mtk_data *gpio = dev_get_drvdata(&pdev->dev); 213 struct mtk_gc *rg; 214 void __iomem *dat, *set, *ctrl, *diro; 215 int ret; 216 217 rg = &gpio->gc_map[bank]; 218 memset(rg, 0, sizeof(*rg)); 219 220 spin_lock_init(&rg->lock); > 221 rg->chip.of_node = node; 222 rg->bank = bank; 223 rg->chip.label = mediatek_gpio_bank_name(rg->bank); 224 225 dat = gpio->gpio_membase + GPIO_REG_DATA + (rg->bank * GPIO_BANK_WIDE); 226 set = gpio->gpio_membase + GPIO_REG_DSET + (rg->bank * GPIO_BANK_WIDE); 227 ctrl = gpio->gpio_membase + GPIO_REG_DCLR + (rg->bank * GPIO_BANK_WIDE); 228 diro = gpio->gpio_membase + GPIO_REG_CTRL + (rg->bank * GPIO_BANK_WIDE); 229 230 ret = bgpio_init(&rg->chip, &pdev->dev, 4, 231 dat, set, ctrl, diro, NULL, 0); 232 if (ret) { 233 dev_err(&pdev->dev, "bgpio_init() failed\n"); 234 return ret; 235 } 236 237 ret = devm_gpiochip_add_data(&pdev->dev, &rg->chip, gpio); 238 if (ret < 0) { 239 dev_err(&pdev->dev, "Could not register gpio %d, ret=%d\n", 240 rg->chip.ngpio, ret); 241 return ret; 242 } 243 244 if (gpio->gpio_irq) { 245 /* 246 * Manually request the irq here instead of passing 247 * a flow-handler to gpiochip_set_chained_irqchip, 248 * because the irq is shared. 249 */ 250 ret = devm_request_irq(&pdev->dev, gpio->gpio_irq, 251 mediatek_gpio_irq_handler, IRQF_SHARED, 252 rg->chip.label, &rg->chip); 253 254 if (ret) { 255 dev_err(&pdev->dev, "Error requesting IRQ %d: %d\n", 256 gpio->gpio_irq, ret); 257 return ret; 258 } 259 260 mediatek_gpio_irq_chip.name = rg->chip.label; 261 ret = gpiochip_irqchip_add(&rg->chip, &mediatek_gpio_irq_chip, 262 0, handle_simple_irq, IRQ_TYPE_NONE); 263 if (ret) { 264 dev_err(&pdev->dev, "failed to add gpiochip_irqchip\n"); 265 return ret; 266 } 267 268 gpiochip_set_chained_irqchip(&rg->chip, &mediatek_gpio_irq_chip, 269 gpio->gpio_irq, NULL); 270 } 271 272 /* set polarity to low for all gpios */ 273 mtk_gpio_w32(rg, GPIO_REG_POL, 0); 274 275 dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); 276 277 return 0; 278 } 279 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation [-- Attachment #2: .config.gz --] [-- Type: application/gzip, Size: 27994 bytes --] [-- Attachment #3: Type: text/plain, Size: 169 bytes --] _______________________________________________ devel mailing list devel@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] gpio: mediatek: add driver for MT7621 2018-06-29 16:43 ` kbuild test robot @ 2018-06-29 16:52 ` Sergio Paracuellos 2018-06-29 19:30 ` Sergio Paracuellos 0 siblings, 1 reply; 10+ messages in thread From: Sergio Paracuellos @ 2018-06-29 16:52 UTC (permalink / raw) To: kbuild test robot Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS, Greg KH, Linus Walleij, driverdev-devel, open list:GPIO SUBSYSTEM, Rob Herring, kbuild-all, NeilBrown On Fri, Jun 29, 2018 at 6:43 PM, kbuild test robot <lkp@intel.com> wrote: > Hi Sergio, > > Thank you for the patch! Yet something to improve: > > [auto build test ERROR on gpio/for-next] > [also build test ERROR on v4.18-rc2 next-20180629] > [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] > > url: https://github.com/0day-ci/linux/commits/Sergio-Paracuellos/gpio-mediatek-driver-for-gpio-chip-in-MT7621-SoC/20180629-225420 > base: https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git for-next > config: x86_64-randconfig-s0-06292230 (attached as .config) > compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026 > reproduce: > # save the attached .config to linux build tree > make ARCH=x86_64 > > All errors (new ones prefixed by >>): > > drivers/gpio/gpio-mt7621.c: In function 'mediatek_gpio_bank_probe': >>> drivers/gpio/gpio-mt7621.c:221:10: error: 'struct gpio_chip' has no member named 'of_node' > rg->chip.of_node = node; > ^ Should I have to add #ifdef CONFIG_OF_GPIO for this line? Is kind of ugly hack... Does exist another way to fix this? Thanks, Sergio Paracuellos > > vim +221 drivers/gpio/gpio-mt7621.c > > 207 > 208 static int > 209 mediatek_gpio_bank_probe(struct platform_device *pdev, > 210 struct device_node *node, int bank) > 211 { > 212 struct mtk_data *gpio = dev_get_drvdata(&pdev->dev); > 213 struct mtk_gc *rg; > 214 void __iomem *dat, *set, *ctrl, *diro; > 215 int ret; > 216 > 217 rg = &gpio->gc_map[bank]; > 218 memset(rg, 0, sizeof(*rg)); > 219 > 220 spin_lock_init(&rg->lock); > > 221 rg->chip.of_node = node; > 222 rg->bank = bank; > 223 rg->chip.label = mediatek_gpio_bank_name(rg->bank); > 224 > 225 dat = gpio->gpio_membase + GPIO_REG_DATA + (rg->bank * GPIO_BANK_WIDE); > 226 set = gpio->gpio_membase + GPIO_REG_DSET + (rg->bank * GPIO_BANK_WIDE); > 227 ctrl = gpio->gpio_membase + GPIO_REG_DCLR + (rg->bank * GPIO_BANK_WIDE); > 228 diro = gpio->gpio_membase + GPIO_REG_CTRL + (rg->bank * GPIO_BANK_WIDE); > 229 > 230 ret = bgpio_init(&rg->chip, &pdev->dev, 4, > 231 dat, set, ctrl, diro, NULL, 0); > 232 if (ret) { > 233 dev_err(&pdev->dev, "bgpio_init() failed\n"); > 234 return ret; > 235 } > 236 > 237 ret = devm_gpiochip_add_data(&pdev->dev, &rg->chip, gpio); > 238 if (ret < 0) { > 239 dev_err(&pdev->dev, "Could not register gpio %d, ret=%d\n", > 240 rg->chip.ngpio, ret); > 241 return ret; > 242 } > 243 > 244 if (gpio->gpio_irq) { > 245 /* > 246 * Manually request the irq here instead of passing > 247 * a flow-handler to gpiochip_set_chained_irqchip, > 248 * because the irq is shared. > 249 */ > 250 ret = devm_request_irq(&pdev->dev, gpio->gpio_irq, > 251 mediatek_gpio_irq_handler, IRQF_SHARED, > 252 rg->chip.label, &rg->chip); > 253 > 254 if (ret) { > 255 dev_err(&pdev->dev, "Error requesting IRQ %d: %d\n", > 256 gpio->gpio_irq, ret); > 257 return ret; > 258 } > 259 > 260 mediatek_gpio_irq_chip.name = rg->chip.label; > 261 ret = gpiochip_irqchip_add(&rg->chip, &mediatek_gpio_irq_chip, > 262 0, handle_simple_irq, IRQ_TYPE_NONE); > 263 if (ret) { > 264 dev_err(&pdev->dev, "failed to add gpiochip_irqchip\n"); > 265 return ret; > 266 } > 267 > 268 gpiochip_set_chained_irqchip(&rg->chip, &mediatek_gpio_irq_chip, > 269 gpio->gpio_irq, NULL); > 270 } > 271 > 272 /* set polarity to low for all gpios */ > 273 mtk_gpio_w32(rg, GPIO_REG_POL, 0); > 274 > 275 dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); > 276 > 277 return 0; > 278 } > 279 > > --- > 0-DAY kernel test infrastructure Open Source Technology Center > https://lists.01.org/pipermail/kbuild-all Intel Corporation ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] gpio: mediatek: add driver for MT7621 2018-06-29 16:52 ` Sergio Paracuellos @ 2018-06-29 19:30 ` Sergio Paracuellos 0 siblings, 0 replies; 10+ messages in thread From: Sergio Paracuellos @ 2018-06-29 19:30 UTC (permalink / raw) To: kbuild test robot Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS, Greg KH, Linus Walleij, driverdev-devel, open list:GPIO SUBSYSTEM, Rob Herring, kbuild-all, NeilBrown On Fri, Jun 29, 2018 at 6:52 PM, Sergio Paracuellos <sergio.paracuellos@gmail.com> wrote: > On Fri, Jun 29, 2018 at 6:43 PM, kbuild test robot <lkp@intel.com> wrote: >> Hi Sergio, >> >> Thank you for the patch! Yet something to improve: >> >> [auto build test ERROR on gpio/for-next] >> [also build test ERROR on v4.18-rc2 next-20180629] >> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] >> >> url: https://github.com/0day-ci/linux/commits/Sergio-Paracuellos/gpio-mediatek-driver-for-gpio-chip-in-MT7621-SoC/20180629-225420 >> base: https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git for-next >> config: x86_64-randconfig-s0-06292230 (attached as .config) >> compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026 >> reproduce: >> # save the attached .config to linux build tree >> make ARCH=x86_64 >> >> All errors (new ones prefixed by >>): >> >> drivers/gpio/gpio-mt7621.c: In function 'mediatek_gpio_bank_probe': >>>> drivers/gpio/gpio-mt7621.c:221:10: error: 'struct gpio_chip' has no member named 'of_node' >> rg->chip.of_node = node; >> ^ > > Should I have to add #ifdef CONFIG_OF_GPIO for this line? Is kind of > ugly hack... Does exist another way to fix this? > Ah, this is v2 where the Makefile was wrong... I though it was v3. I think we can ignore this and see what happen with likely correct v3. Best regards, Sergio Paracuellos > Thanks, > Sergio Paracuellos > >> >> vim +221 drivers/gpio/gpio-mt7621.c >> >> 207 >> 208 static int >> 209 mediatek_gpio_bank_probe(struct platform_device *pdev, >> 210 struct device_node *node, int bank) >> 211 { >> 212 struct mtk_data *gpio = dev_get_drvdata(&pdev->dev); >> 213 struct mtk_gc *rg; >> 214 void __iomem *dat, *set, *ctrl, *diro; >> 215 int ret; >> 216 >> 217 rg = &gpio->gc_map[bank]; >> 218 memset(rg, 0, sizeof(*rg)); >> 219 >> 220 spin_lock_init(&rg->lock); >> > 221 rg->chip.of_node = node; >> 222 rg->bank = bank; >> 223 rg->chip.label = mediatek_gpio_bank_name(rg->bank); >> 224 >> 225 dat = gpio->gpio_membase + GPIO_REG_DATA + (rg->bank * GPIO_BANK_WIDE); >> 226 set = gpio->gpio_membase + GPIO_REG_DSET + (rg->bank * GPIO_BANK_WIDE); >> 227 ctrl = gpio->gpio_membase + GPIO_REG_DCLR + (rg->bank * GPIO_BANK_WIDE); >> 228 diro = gpio->gpio_membase + GPIO_REG_CTRL + (rg->bank * GPIO_BANK_WIDE); >> 229 >> 230 ret = bgpio_init(&rg->chip, &pdev->dev, 4, >> 231 dat, set, ctrl, diro, NULL, 0); >> 232 if (ret) { >> 233 dev_err(&pdev->dev, "bgpio_init() failed\n"); >> 234 return ret; >> 235 } >> 236 >> 237 ret = devm_gpiochip_add_data(&pdev->dev, &rg->chip, gpio); >> 238 if (ret < 0) { >> 239 dev_err(&pdev->dev, "Could not register gpio %d, ret=%d\n", >> 240 rg->chip.ngpio, ret); >> 241 return ret; >> 242 } >> 243 >> 244 if (gpio->gpio_irq) { >> 245 /* >> 246 * Manually request the irq here instead of passing >> 247 * a flow-handler to gpiochip_set_chained_irqchip, >> 248 * because the irq is shared. >> 249 */ >> 250 ret = devm_request_irq(&pdev->dev, gpio->gpio_irq, >> 251 mediatek_gpio_irq_handler, IRQF_SHARED, >> 252 rg->chip.label, &rg->chip); >> 253 >> 254 if (ret) { >> 255 dev_err(&pdev->dev, "Error requesting IRQ %d: %d\n", >> 256 gpio->gpio_irq, ret); >> 257 return ret; >> 258 } >> 259 >> 260 mediatek_gpio_irq_chip.name = rg->chip.label; >> 261 ret = gpiochip_irqchip_add(&rg->chip, &mediatek_gpio_irq_chip, >> 262 0, handle_simple_irq, IRQ_TYPE_NONE); >> 263 if (ret) { >> 264 dev_err(&pdev->dev, "failed to add gpiochip_irqchip\n"); >> 265 return ret; >> 266 } >> 267 >> 268 gpiochip_set_chained_irqchip(&rg->chip, &mediatek_gpio_irq_chip, >> 269 gpio->gpio_irq, NULL); >> 270 } >> 271 >> 272 /* set polarity to low for all gpios */ >> 273 mtk_gpio_w32(rg, GPIO_REG_POL, 0); >> 274 >> 275 dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); >> 276 >> 277 return 0; >> 278 } >> 279 >> >> --- >> 0-DAY kernel test infrastructure Open Source Technology Center >> https://lists.01.org/pipermail/kbuild-all Intel Corporation ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] gpio: mediatek: add driver for MT7621 2018-06-29 12:43 ` [PATCH v2 1/2] gpio: mediatek: add driver for MT7621 Sergio Paracuellos 2018-06-29 13:31 ` Dan Carpenter 2018-06-29 16:43 ` kbuild test robot @ 2018-06-30 6:12 ` Sergio Paracuellos 2 siblings, 0 replies; 10+ messages in thread From: Sergio Paracuellos @ 2018-06-30 6:12 UTC (permalink / raw) To: Linus Walleij Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS, Greg KH, driverdev-devel, open list:GPIO SUBSYSTEM, Rob Herring, NeilBrown On Fri, Jun 29, 2018 at 2:43 PM, Sergio Paracuellos <sergio.paracuellos@gmail.com> wrote: > Add driver support for gpio of MT7621 SoC. > > Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> > --- > drivers/gpio/Kconfig | 8 ++ > drivers/gpio/Makefile | 1 + > drivers/gpio/gpio-mt7621.c | 320 +++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 329 insertions(+) > create mode 100644 drivers/gpio/gpio-mt7621.c Hi all, Sorry for the noise. Ignore this and v3 for now. It seems the "only one node" approach for the gpio in the device tree is not working properly. I thought it was but Neil points out here it was not: http://driverdev.linuxdriverproject.org/pipermail/driverdev-devel/2018-June/122621.html We'll send v4 with all properly working. Thanks in advance and sorry again. Best regards, Sergio Paracuellos > > diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig > index 71c0ab4..836aa21 100644 > --- a/drivers/gpio/Kconfig > +++ b/drivers/gpio/Kconfig > @@ -359,6 +359,14 @@ config GPIO_MPC8XXX > Say Y here if you're going to use hardware that connects to the > MPC512x/831x/834x/837x/8572/8610/QorIQ GPIOs. > > +config GPIO_MT7621 > + bool "Mediatek MT7621 GPIO Support" > + depends on SOC_MT7620 || SOC_MT7621 || COMPILE_TEST > + select GPIO_GENERIC > + select GPIOLIB_IRQCHIP > + help > + Say yes here to support the Mediatek MT7621 SoC GPIO device > + > config GPIO_MVEBU > def_bool y > depends on PLAT_ORION || ARCH_MVEBU > diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile > index 1324c8f..b264426 100644 > --- a/drivers/gpio/Makefile > +++ b/drivers/gpio/Makefile > @@ -88,6 +88,7 @@ obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o > obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o > obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o > obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o > +obj-$(CONFIG_GPIO_MSIC) += gpio-mt7621.o > obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o > obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o > obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o > diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c > new file mode 100644 > index 0000000..281e621 > --- /dev/null > +++ b/drivers/gpio/gpio-mt7621.c > @@ -0,0 +1,320 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> > + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> > + */ > + > +#include <linux/err.h> > +#include <linux/gpio/driver.h> > +#include <linux/interrupt.h> > +#include <linux/io.h> > +#include <linux/module.h> > +#include <linux/of_irq.h> > +#include <linux/platform_device.h> > +#include <linux/spinlock.h> > + > +#define MTK_BANK_CNT 3 > +#define MTK_BANK_WIDTH 32 > + > +#define GPIO_BANK_WIDE 0x04 > +#define GPIO_REG_CTRL 0x00 > +#define GPIO_REG_POL 0x10 > +#define GPIO_REG_DATA 0x20 > +#define GPIO_REG_DSET 0x30 > +#define GPIO_REG_DCLR 0x40 > +#define GPIO_REG_REDGE 0x50 > +#define GPIO_REG_FEDGE 0x60 > +#define GPIO_REG_HLVL 0x70 > +#define GPIO_REG_LLVL 0x80 > +#define GPIO_REG_STAT 0x90 > +#define GPIO_REG_EDGE 0xA0 > + > +struct mtk_gc { > + struct gpio_chip chip; > + spinlock_t lock; > + int bank; > + u32 rising; > + u32 falling; > + u32 hlevel; > + u32 llevel; > +}; > + > +/** > + * struct mtk_data - state container for > + * data of the platform driver. It is 3 > + * separate gpio-chip each one with its > + * own irq_chip. > + * @dev: device instance > + * @gpio_membase: memory base address > + * @gpio_irq: irq number from the device tree > + * @gc_map: array of the gpio chips > + */ > +struct mtk_data { > + struct device *dev; > + void __iomem *gpio_membase; > + int gpio_irq; > + struct mtk_gc gc_map[MTK_BANK_CNT]; > +}; > + > +static inline struct mtk_gc * > +to_mediatek_gpio(struct gpio_chip *chip) > +{ > + return container_of(chip, struct mtk_gc, chip); > +} > + > +static inline void > +mtk_gpio_w32(struct mtk_gc *rg, u32 offset, u32 val) > +{ > + struct gpio_chip *gc = &rg->chip; > + struct mtk_data *gpio_data = gpiochip_get_data(gc); > + > + offset = (rg->bank * GPIO_BANK_WIDE) + offset; > + gc->write_reg(gpio_data->gpio_membase + offset, val); > +} > + > +static inline u32 > +mtk_gpio_r32(struct mtk_gc *rg, u32 offset) > +{ > + struct gpio_chip *gc = &rg->chip; > + struct mtk_data *gpio_data = gpiochip_get_data(gc); > + > + offset = (rg->bank * GPIO_BANK_WIDE) + offset; > + return gc->read_reg(gpio_data->gpio_membase + offset); > +} > + > +static irqreturn_t > +mediatek_gpio_irq_handler(int irq, void *data) > +{ > + struct gpio_chip *gc = data; > + struct mtk_gc *rg = to_mediatek_gpio(gc); > + irqreturn_t ret = IRQ_NONE; > + unsigned long pending; > + int bit; > + > + pending = mtk_gpio_r32(rg, GPIO_REG_STAT); > + > + for_each_set_bit(bit, &pending, MTK_BANK_WIDTH) { > + u32 map = irq_find_mapping(gc->irq.domain, bit); > + > + generic_handle_irq(map); > + mtk_gpio_w32(rg, GPIO_REG_STAT, BIT(bit)); > + ret |= IRQ_HANDLED; > + } > + > + return ret; > +} > + > +static void > +mediatek_gpio_irq_unmask(struct irq_data *d) > +{ > + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); > + struct mtk_gc *rg = to_mediatek_gpio(gc); > + int pin = d->hwirq; > + unsigned long flags; > + u32 rise, fall, high, low; > + > + spin_lock_irqsave(&rg->lock, flags); > + rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); > + fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); > + high = mtk_gpio_r32(rg, GPIO_REG_HLVL); > + low = mtk_gpio_r32(rg, GPIO_REG_LLVL); > + mtk_gpio_w32(rg, GPIO_REG_REDGE, rise | (BIT(pin) & rg->rising)); > + mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall | (BIT(pin) & rg->falling)); > + mtk_gpio_w32(rg, GPIO_REG_HLVL, high | (BIT(pin) & rg->hlevel)); > + mtk_gpio_w32(rg, GPIO_REG_LLVL, low | (BIT(pin) & rg->llevel)); > + spin_unlock_irqrestore(&rg->lock, flags); > +} > + > +static void > +mediatek_gpio_irq_mask(struct irq_data *d) > +{ > + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); > + struct mtk_gc *rg = to_mediatek_gpio(gc); > + int pin = d->hwirq; > + unsigned long flags; > + u32 rise, fall, high, low; > + > + spin_lock_irqsave(&rg->lock, flags); > + rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); > + fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); > + high = mtk_gpio_r32(rg, GPIO_REG_HLVL); > + low = mtk_gpio_r32(rg, GPIO_REG_LLVL); > + mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall & ~BIT(pin)); > + mtk_gpio_w32(rg, GPIO_REG_REDGE, rise & ~BIT(pin)); > + mtk_gpio_w32(rg, GPIO_REG_HLVL, high & ~BIT(pin)); > + mtk_gpio_w32(rg, GPIO_REG_LLVL, low & ~BIT(pin)); > + spin_unlock_irqrestore(&rg->lock, flags); > +} > + > +static int > +mediatek_gpio_irq_type(struct irq_data *d, unsigned int type) > +{ > + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); > + struct mtk_gc *rg = to_mediatek_gpio(gc); > + int pin = d->hwirq; > + u32 mask = BIT(pin); > + > + if (type == IRQ_TYPE_PROBE) { > + if ((rg->rising | rg->falling | > + rg->hlevel | rg->llevel) & mask) > + return 0; > + > + type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; > + } > + > + rg->rising &= ~mask; > + rg->falling &= ~mask; > + rg->hlevel &= ~mask; > + rg->llevel &= ~mask; > + > + switch (type & IRQ_TYPE_SENSE_MASK) { > + case IRQ_TYPE_EDGE_BOTH: > + rg->rising |= mask; > + rg->falling |= mask; > + break; > + case IRQ_TYPE_EDGE_RISING: > + rg->rising |= mask; > + break; > + case IRQ_TYPE_EDGE_FALLING: > + rg->falling |= mask; > + break; > + case IRQ_TYPE_LEVEL_HIGH: > + rg->hlevel |= mask; > + break; > + case IRQ_TYPE_LEVEL_LOW: > + rg->llevel |= mask; > + break; > + } > + > + return 0; > +} > + > +static struct irq_chip mediatek_gpio_irq_chip = { > + .irq_unmask = mediatek_gpio_irq_unmask, > + .irq_mask = mediatek_gpio_irq_mask, > + .irq_mask_ack = mediatek_gpio_irq_mask, > + .irq_set_type = mediatek_gpio_irq_type, > +}; > + > +static inline const char * const mediatek_gpio_bank_name(int bank) > +{ > + static const char * const bank_names[] = { > + "mt7621-bank0", "mt7621-bank1", "mt7621-bank2", > + }; > + > + return bank_names[bank]; > +} > + > +static int > +mediatek_gpio_bank_probe(struct platform_device *pdev, > + struct device_node *node, int bank) > +{ > + struct mtk_data *gpio = dev_get_drvdata(&pdev->dev); > + struct mtk_gc *rg; > + void __iomem *dat, *set, *ctrl, *diro; > + int ret; > + > + rg = &gpio->gc_map[bank]; > + memset(rg, 0, sizeof(*rg)); > + > + spin_lock_init(&rg->lock); > + rg->chip.of_node = node; > + rg->bank = bank; > + rg->chip.label = mediatek_gpio_bank_name(rg->bank); > + > + dat = gpio->gpio_membase + GPIO_REG_DATA + (rg->bank * GPIO_BANK_WIDE); > + set = gpio->gpio_membase + GPIO_REG_DSET + (rg->bank * GPIO_BANK_WIDE); > + ctrl = gpio->gpio_membase + GPIO_REG_DCLR + (rg->bank * GPIO_BANK_WIDE); > + diro = gpio->gpio_membase + GPIO_REG_CTRL + (rg->bank * GPIO_BANK_WIDE); > + > + ret = bgpio_init(&rg->chip, &pdev->dev, 4, > + dat, set, ctrl, diro, NULL, 0); > + if (ret) { > + dev_err(&pdev->dev, "bgpio_init() failed\n"); > + return ret; > + } > + > + ret = devm_gpiochip_add_data(&pdev->dev, &rg->chip, gpio); > + if (ret < 0) { > + dev_err(&pdev->dev, "Could not register gpio %d, ret=%d\n", > + rg->chip.ngpio, ret); > + return ret; > + } > + > + if (gpio->gpio_irq) { > + /* > + * Manually request the irq here instead of passing > + * a flow-handler to gpiochip_set_chained_irqchip, > + * because the irq is shared. > + */ > + ret = devm_request_irq(&pdev->dev, gpio->gpio_irq, > + mediatek_gpio_irq_handler, IRQF_SHARED, > + rg->chip.label, &rg->chip); > + > + if (ret) { > + dev_err(&pdev->dev, "Error requesting IRQ %d: %d\n", > + gpio->gpio_irq, ret); > + return ret; > + } > + > + mediatek_gpio_irq_chip.name = rg->chip.label; > + ret = gpiochip_irqchip_add(&rg->chip, &mediatek_gpio_irq_chip, > + 0, handle_simple_irq, IRQ_TYPE_NONE); > + if (ret) { > + dev_err(&pdev->dev, "failed to add gpiochip_irqchip\n"); > + return ret; > + } > + > + gpiochip_set_chained_irqchip(&rg->chip, &mediatek_gpio_irq_chip, > + gpio->gpio_irq, NULL); > + } > + > + /* set polarity to low for all gpios */ > + mtk_gpio_w32(rg, GPIO_REG_POL, 0); > + > + dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); > + > + return 0; > +} > + > +static int > +mediatek_gpio_probe(struct platform_device *pdev) > +{ > + struct device_node *np = pdev->dev.of_node; > + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + struct mtk_data *gpio_data; > + int i; > + > + gpio_data = devm_kzalloc(&pdev->dev, sizeof(*gpio_data), GFP_KERNEL); > + if (!gpio_data) > + return -ENOMEM; > + > + gpio_data->gpio_membase = devm_ioremap_resource(&pdev->dev, res); > + if (IS_ERR(gpio_data->gpio_membase)) > + return PTR_ERR(gpio_data->gpio_membase); > + > + gpio_data->gpio_irq = irq_of_parse_and_map(np, 0); > + gpio_data->dev = &pdev->dev; > + platform_set_drvdata(pdev, gpio_data); > + > + for (i = 0; i < MTK_BANK_CNT; i++) > + mediatek_gpio_bank_probe(pdev, np, i); > + > + return 0; > +} > + > +static const struct of_device_id mediatek_gpio_match[] = { > + { .compatible = "mediatek,mt7621-gpio" }, > + {}, > +}; > +MODULE_DEVICE_TABLE(of, mediatek_gpio_match); > + > +static struct platform_driver mediatek_gpio_driver = { > + .probe = mediatek_gpio_probe, > + .driver = { > + .name = "mt7621_gpio", > + .of_match_table = mediatek_gpio_match, > + }, > +}; > + > +builtin_platform_driver(mediatek_gpio_driver); > -- > 2.7.4 > ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 2/2] dt-bindings: document gpio-mt7621 bindings 2018-06-29 12:43 [PATCH v2 0/2] gpio: mediatek: driver for gpio chip in MT7621 SoC Sergio Paracuellos 2018-06-29 12:43 ` [PATCH v2 1/2] gpio: mediatek: add driver for MT7621 Sergio Paracuellos @ 2018-06-29 12:43 ` Sergio Paracuellos 1 sibling, 0 replies; 10+ messages in thread From: Sergio Paracuellos @ 2018-06-29 12:43 UTC (permalink / raw) To: linus.walleij Cc: devicetree, gregkh, driverdev-devel, linux-gpio, robh+dt, neil Add a devicetree binding documentation for the mt7621 gpio. Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> --- .../bindings/gpio/mediatek,mt7621-gpio.txt | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/mediatek,mt7621-gpio.txt diff --git a/Documentation/devicetree/bindings/gpio/mediatek,mt7621-gpio.txt b/Documentation/devicetree/bindings/gpio/mediatek,mt7621-gpio.txt new file mode 100644 index 0000000..ba45558 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/mediatek,mt7621-gpio.txt @@ -0,0 +1,35 @@ +Mediatek MT7621 SoC GPIO controller bindings + +The IP core used inside these SoCs has 3 banks of 32 GPIOs each. +The registers of all the banks are interwoven inside one single IO range. +We load one GPIO controller instance per bank. Also the GPIO controller can receive +interrupts on any of the GPIOs, either edge or level. It then interrupts the CPU +using GIC INT12. + +Required properties for the top level node: +- #gpio-cells : Should be two. The first cell is the GPIO pin number and the + second cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>. + Only the GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported. +- #interrupt-cells : Specifies the number of cells needed to encode an + interrupt. Should be 2. The first cell defines the interrupt number, + the second encodes the triger flags encoded as described in + Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +- compatible: + - "mediatek,mt7621-gpio" for Mediatek controllers +- reg : Physical base address and length of the controller's registers +- interrupt-parent : phandle of the parent interrupt controller. +- interrupts : Interrupt specifier for the controllers interrupt. +- interrupt-controller : Mark the device node as an interrupt controller. +- gpio-controller : Marks the device node as a GPIO controller. + +Example: + gpio@600 { + #gpio-cells = <2>; + #interrupt-cells = <2>; + compatible = "mediatek,mt7621-gpio"; + gpio-controller; + interrupt-controller; + reg = <0x600 0x100>; + interrupt-parent = <&gic>; + interrupts = <GIC_SHARED 12 IRQ_TYPE_LEVEL_HIGH>; + }; -- 2.7.4 ^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2018-06-30 6:12 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2018-06-29 12:43 [PATCH v2 0/2] gpio: mediatek: driver for gpio chip in MT7621 SoC Sergio Paracuellos 2018-06-29 12:43 ` [PATCH v2 1/2] gpio: mediatek: add driver for MT7621 Sergio Paracuellos 2018-06-29 13:31 ` Dan Carpenter 2018-06-29 13:34 ` Dan Carpenter 2018-06-29 13:51 ` Sergio Paracuellos 2018-06-29 16:43 ` kbuild test robot 2018-06-29 16:52 ` Sergio Paracuellos 2018-06-29 19:30 ` Sergio Paracuellos 2018-06-30 6:12 ` Sergio Paracuellos 2018-06-29 12:43 ` [PATCH v2 2/2] dt-bindings: document gpio-mt7621 bindings Sergio Paracuellos
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).