From b2dc4110cbf83be72e8bdf75bcf88831bf7dd0fe Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 3 Jul 2017 20:45:30 +0300 Subject: gpio: pca953x: remove incorrect le16_to_cpu calls i2c_smbus commands handle the correct byte order for smbus transactions internally. This will currently result in incorrect operation on big endian systems. Suggested-by: Sebastian Reichel Signed-off-by: Andy Shevchenko Reviewed-by: Sebastian Reichel Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 4c9e21300a26..1b9dbf691ae7 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -187,10 +187,9 @@ static int pca953x_write_regs_8(struct pca953x_chip *chip, int reg, u8 *val) static int pca953x_write_regs_16(struct pca953x_chip *chip, int reg, u8 *val) { - __le16 word = cpu_to_le16(get_unaligned((u16 *)val)); + u16 word = get_unaligned((u16 *)val); - return i2c_smbus_write_word_data(chip->client, - reg << 1, (__force u16)word); + return i2c_smbus_write_word_data(chip->client, reg << 1, word); } static int pca957x_write_regs_16(struct pca953x_chip *chip, int reg, u8 *val) @@ -241,8 +240,7 @@ static int pca953x_read_regs_16(struct pca953x_chip *chip, int reg, u8 *val) int ret; ret = i2c_smbus_read_word_data(chip->client, reg << 1); - val[0] = (u16)ret & 0xFF; - val[1] = (u16)ret >> 8; + put_unaligned(ret, (u16 *)val); return ret; } -- cgit v1.2.3-55-g7522 From 108d23e322a247d9f89ba2e2742520ead0944cc9 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 27 Jul 2017 13:19:23 -0500 Subject: gpiolib: request the gpio before querying its direction Before querying a GPIO to determine its direction, the GPIO should be formally requested. This allows the GPIO driver to block access to unavailable GPIOs, which makes it easier for some drivers to support sparse GPIO maps. Signed-off-by: Timur Tabi Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index cd003b74512f..bd90737dce77 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1201,6 +1201,14 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) struct gpio_desc *desc = &gdev->descs[i]; desc->gdev = gdev; + + if (chip->request) { + status = chip->request(chip, i); + if (status < 0) + /* The GPIO is unavailable, so skip it */ + continue; + } + /* * REVISIT: most hardware initializes GPIOs as inputs * (often with pullups enabled) so power usage is @@ -1226,6 +1234,9 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) */ set_bit(FLAG_IS_OUT, &desc->flags); } + + if (chip->free) + chip->free(chip, i); } #ifdef CONFIG_PINCTRL -- cgit v1.2.3-55-g7522 From dc749a09ea5e413564115dee742c3bc958248707 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Fri, 21 Jul 2017 11:49:00 -0500 Subject: gpiolib: allow gpio irqchip to map irqs dynamically Now IRQ mappings are always created for all (allowed) GPIOs in gpiochip in gpiochip_irqchip_add_key() which goes against the idea of SPARSE_IRQ and, as result, leads to: - increasing of memory consumption for IRQ descriptors most of which will never ever be used (espessially on platform with a high number of GPIOs). (sizeof(struct irq_desc) == 256 on my tested platforms) - imposibility to use GPIO irqchip APIs by gpio drivers when HW implements GPIO IRQ functionality as IRQ crossbar/router which has only limited number of IRQ outputs (example from [1], all GPIOs can be mapped on only 8 IRQs). Hence, remove static IRQ mapping code from gpiochip_irqchip_add_key() and instead replace irq_find_mapping() with irq_create_mapping() in gpiochip_to_irq(). Also add additional gpiochip_irqchip_irq_valid() calls in gpiochip_to_irq() and gpiochip_irq_map(). After this change gpio2irq mapping will happen the following way when GPIO irqchip APIs are used by gpio driver: - IRQ mappings will be created statically if driver passes first_irq>0 vlaue in gpiochip_irqchip_add_key(). - IRQ mappings will be created dynamically from gpio_to_irq() or of_irq_get(). Tested on am335x-evm and dra72-evm-revc. - dra72-evm-revc: number of created irq mappings decreased from 402 -> 135 Mem savings 267*256 = 68352 (66kB) - am335x-evm: number of created irq mappings decreased from 188 -> 63 Mem savings 125*256 = 32000 (31kB) [1] https://lkml.org/lkml/2017/6/15/428 Signed-off-by: Grygorii Strashko Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index bd90737dce77..92a5503f739d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1615,6 +1615,9 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, { struct gpio_chip *chip = d->host_data; + if (!gpiochip_irqchip_irq_valid(chip, hwirq)) + return -ENXIO; + irq_set_chip_data(irq, chip); /* * This lock class tells lockdep that GPIO irqs are in a different @@ -1681,7 +1684,9 @@ static void gpiochip_irq_relres(struct irq_data *d) static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset) { - return irq_find_mapping(chip->irqdomain, offset); + if (!gpiochip_irqchip_irq_valid(chip, offset)) + return -ENXIO; + return irq_create_mapping(chip->irqdomain, offset); } /** @@ -1757,9 +1762,6 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip, struct lock_class_key *lock_key) { struct device_node *of_node; - bool irq_base_set = false; - unsigned int offset; - unsigned irq_base = 0; if (!gpiochip || !irqchip) return -EINVAL; @@ -1816,25 +1818,6 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip, irqchip->irq_release_resources = gpiochip_irq_relres; } - /* - * Prepare the mapping since the irqchip shall be orthogonal to - * any gpiochip calls. If the first_irq was zero, this is - * necessary to allocate descriptors for all IRQs. - */ - for (offset = 0; offset < gpiochip->ngpio; offset++) { - if (!gpiochip_irqchip_irq_valid(gpiochip, offset)) - continue; - irq_base = irq_create_mapping(gpiochip->irqdomain, offset); - if (!irq_base_set) { - /* - * Store the base into the gpiochip to be used when - * unmapping the irqs. - */ - gpiochip->irq_base = irq_base; - irq_base_set = true; - } - } - acpi_gpiochip_request_interrupts(gpiochip); return 0; -- cgit v1.2.3-55-g7522 From 64fcf3b32e86c95256a40bda96fc675c32d7afa6 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Sat, 8 Jul 2017 17:44:12 -0500 Subject: gpio: pxa: remove gpio_to_irq() from hw irq handlers gpio_to_irq() API expected to be used by GPIO consumers and not drivers and there are no guarantee that its gpiolib implementation is irq safe. Signed-off-by: Grygorii Strashko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pxa.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 832f3e46ba9f..6029899789f3 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -451,7 +451,9 @@ static irqreturn_t pxa_gpio_demux_handler(int in_irq, void *d) for_each_set_bit(n, &gedr, BITS_PER_LONG) { loop = 1; - generic_handle_irq(gpio_to_irq(gpio + n)); + generic_handle_irq( + irq_find_mapping(pchip->irqdomain, + gpio + n)); } } handled += loop; @@ -465,9 +467,9 @@ static irqreturn_t pxa_gpio_direct_handler(int in_irq, void *d) struct pxa_gpio_chip *pchip = d; if (in_irq == pchip->irq0) { - generic_handle_irq(gpio_to_irq(0)); + generic_handle_irq(irq_find_mapping(pchip->irqdomain, 0)); } else if (in_irq == pchip->irq1) { - generic_handle_irq(gpio_to_irq(1)); + generic_handle_irq(irq_find_mapping(pchip->irqdomain, 1)); } else { pr_err("%s() unknown irq %d\n", __func__, in_irq); return IRQ_NONE; -- cgit v1.2.3-55-g7522 From c0debb3d68c3dc63f6565943b316019597587d7a Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Sat, 8 Jul 2017 17:44:11 -0500 Subject: gpio: tegra: remove gpio_to_irq() from hw irq handlers gpio_to_irq() API expected to be used by GPIO consumers and not drivers and there are no guarantee that its gpiolib implementation is irq safe. Signed-off-by: Grygorii Strashko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tegra.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 506c6a67c5fc..1e72c52fbf35 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -389,7 +389,8 @@ static void tegra_gpio_irq_handler(struct irq_desc *desc) chained_irq_exit(chip, desc); } - generic_handle_irq(gpio_to_irq(gpio + pin)); + generic_handle_irq(irq_find_mapping(tgi->irq_domain, + gpio + pin)); } } -- cgit v1.2.3-55-g7522 From 4a5c886e7cc913b60b68825846cd43dcfe7a2be0 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 11 Jul 2017 23:41:43 +0900 Subject: gpio: replace __maybe_unused in gpiolib.h with static inline In header files, static inline is more commonly used. Signed-off-by: Masahiro Yamada Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index a8be286eff86..d003ccb12781 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -219,7 +219,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, /* * Return the GPIO number of the passed descriptor relative to its chip */ -static int __maybe_unused gpio_chip_hwgpio(const struct gpio_desc *desc) +static inline int gpio_chip_hwgpio(const struct gpio_desc *desc) { return desc - &desc->gdev->descs[0]; } -- cgit v1.2.3-55-g7522 From dbd1dad2ab8ffca57e0aa386df0d7ec621c26ca8 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 11 Jul 2017 14:38:30 +0200 Subject: gpio: rcar: add gen[123] fallback compatibility strings Add fallback compatibility string for R-Car Gen 1, 2 and 3. In the case of Renesas R-Car hardware we know that there are generations of SoCs, f.e. Gen 1 and 2. But beyond that its not clear what the relationship between IP blocks might be. For example, I believe that r8a7790 is older than r8a7791 but that doesn't imply that the latter is a descendant of the former or vice versa. We can, however, by examining the documentation and behaviour of the hardware at run-time observe that the current driver implementation appears to be compatible with the IP blocks on SoCs within a given generation. For the above reasons and convenience when enabling new SoCs a per-generation fallback compatibility string scheme being adopted for drivers for Renesas SoCs. Also deprecate renesas,gpio-rcar as its name is more generic than its implementation. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven Signed-off-by: Linus Walleij --- .../devicetree/bindings/gpio/renesas,gpio-rcar.txt | 15 +++++++++++---- drivers/gpio/gpio-rcar.c | 10 ++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'drivers/gpio') diff --git a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt index 6826a371fb69..48634b01f1bf 100644 --- a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt +++ b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt @@ -2,7 +2,7 @@ Required Properties: - - compatible: should contain one of the following. + - compatible: should contain one or more of the following: - "renesas,gpio-r8a7743": for R8A7743 (RZ/G1M) compatible GPIO controller. - "renesas,gpio-r8a7778": for R8A7778 (R-Mobile M1) compatible GPIO controller. - "renesas,gpio-r8a7779": for R8A7779 (R-Car H1) compatible GPIO controller. @@ -13,7 +13,14 @@ Required Properties: - "renesas,gpio-r8a7794": for R8A7794 (R-Car E2) compatible GPIO controller. - "renesas,gpio-r8a7795": for R8A7795 (R-Car H3) compatible GPIO controller. - "renesas,gpio-r8a7796": for R8A7796 (R-Car M3-W) compatible GPIO controller. - - "renesas,gpio-rcar": for generic R-Car GPIO controller. + - "renesas,rcar-gen1-gpio": for a generic R-Car Gen1 GPIO controller. + - "renesas,rcar-gen2-gpio": for a generic R-Car Gen2 or RZ/G1 GPIO controller. + - "renesas,rcar-gen3-gpio": for a generic R-Car Gen3 GPIO controller. + - "renesas,gpio-rcar": deprecated. + + When compatible with the generic version nodes must list the + SoC-specific version corresponding to the platform first followed by + the generic version. - reg: Base address and length of each memory resource used by the GPIO controller hardware module. @@ -43,7 +50,7 @@ interrupt-controller/interrupts.txt. Example: R8A7779 (R-Car H1) GPIO controller nodes gpio0: gpio@ffc40000 { - compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar"; + compatible = "renesas,gpio-r8a7779", "renesas,rcar-gen1-gpio"; reg = <0xffc40000 0x2c>; interrupt-parent = <&gic>; interrupts = <0 141 0x4>; @@ -55,7 +62,7 @@ Example: R8A7779 (R-Car H1) GPIO controller nodes }; ... gpio6: gpio@ffc46000 { - compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar"; + compatible = "renesas,gpio-r8a7779", "renesas,rcar-gen1-gpio"; reg = <0xffc46000 0x2c>; interrupt-parent = <&gic>; interrupts = <0 147 0x4>; diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 4a1536a050bc..1f0871553fd2 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -370,6 +370,16 @@ static const struct of_device_id gpio_rcar_of_table[] = { .compatible = "renesas,gpio-r8a7796", /* Gen3 GPIO is identical to Gen2. */ .data = &gpio_rcar_info_gen2, + }, { + .compatible = "renesas,rcar-gen1-gpio", + .data = &gpio_rcar_info_gen1, + }, { + .compatible = "renesas,rcar-gen2-gpio", + .data = &gpio_rcar_info_gen2, + }, { + .compatible = "renesas,rcar-gen3-gpio", + /* Gen3 GPIO is identical to Gen2. */ + .data = &gpio_rcar_info_gen2, }, { .compatible = "renesas,gpio-rcar", .data = &gpio_rcar_info_gen1, -- cgit v1.2.3-55-g7522 From 77a4d757195fcf40f5cc0eaa1b6f5eb9a4d23851 Mon Sep 17 00:00:00 2001 From: Philipp Rosenberger Date: Wed, 12 Jul 2017 10:36:40 +0200 Subject: gpio: gpio-mxc: gpio_set_wake_irq() use proper return values Errors from enable_irq_wake() in gpio_set_wake_irq() were silently ignored. Thus led to the problem that gpio_set_wake_irq() always returned successfully, even if enable_irq_wake() returned an error. Signed-off-by: Philipp Rosenberger Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 92692251ade1..3dcd990f416e 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -324,20 +324,21 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable) struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct mxc_gpio_port *port = gc->private; u32 gpio_idx = d->hwirq; + int ret; if (enable) { if (port->irq_high && (gpio_idx >= 16)) - enable_irq_wake(port->irq_high); + ret = enable_irq_wake(port->irq_high); else - enable_irq_wake(port->irq); + ret = enable_irq_wake(port->irq); } else { if (port->irq_high && (gpio_idx >= 16)) - disable_irq_wake(port->irq_high); + ret = disable_irq_wake(port->irq_high); else - disable_irq_wake(port->irq); + ret = disable_irq_wake(port->irq); } - return 0; + return ret; } static int mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base) -- cgit v1.2.3-55-g7522 From 1a20c3f8e8c28357b63829ae4b16a212a4a7ef31 Mon Sep 17 00:00:00 2001 From: Gustavo A. R. Silva Date: Tue, 11 Jul 2017 17:15:38 -0500 Subject: gpio: altera-a10sr: constify gpio_chip structure This structure is only used to copy into another structure, so declare it as const. This issue was detected using Coccinelle and the following semantic patch: @r disable optional_qualifier@ identifier i; position p; @@ static struct gpio_chip i@p = { ... }; @ok@ identifier r.i; expression e; position p; @@ e = i@p; @bad@ position p != {r.p,ok.p}; identifier r.i; struct gpio_chip e; @@ e@i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct gpio_chip i = { ... }; In the following log you can see a significant difference in the code size and data segment, hence in the dec segment. This log is the output of the size command, before and after the code change: before: text data bss dec hex filename 1954 600 0 2554 9fa drivers/gpio/gpio-altera-a10sr.o after: text data bss dec hex filename 1655 512 0 2167 877 drivers/gpio/gpio-altera-a10sr.o Signed-off-by: Gustavo A. R. Silva Reviewed-by: Thor Thayer Signed-off-by: Linus Walleij --- drivers/gpio/gpio-altera-a10sr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-altera-a10sr.c b/drivers/gpio/gpio-altera-a10sr.c index 16a8951b2bed..6b11f1314248 100644 --- a/drivers/gpio/gpio-altera-a10sr.c +++ b/drivers/gpio/gpio-altera-a10sr.c @@ -71,7 +71,7 @@ static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc, return -EINVAL; } -static struct gpio_chip altr_a10sr_gc = { +static const struct gpio_chip altr_a10sr_gc = { .label = "altr_a10sr_gpio", .owner = THIS_MODULE, .get = altr_a10sr_gpio_get, -- cgit v1.2.3-55-g7522 From 8327e1ba12aa0e513e517fc254c053fecb0d2df5 Mon Sep 17 00:00:00 2001 From: Keerthy Date: Thu, 20 Jul 2017 15:12:16 +0530 Subject: gpio: davinci: Use devm_gpiochip_add_data in place of gpiochip_add_data Use the devm version of gpiochip_add_data and pass on the return value. This avoids memory leak due to gpiochip_add_data in case the driver is unbound. Signed-off-by: Keerthy Signed-off-by: Linus Walleij --- drivers/gpio/gpio-davinci.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 65cb359308e3..27499ecc3c5e 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -166,7 +166,7 @@ of_err: static int davinci_gpio_probe(struct platform_device *pdev) { static int ctrl_num, bank_base; - int gpio, bank; + int gpio, bank, ret = 0; unsigned ngpio, nbank; struct davinci_gpio_controller *chips; struct davinci_gpio_platform_data *pdata; @@ -232,10 +232,20 @@ static int davinci_gpio_probe(struct platform_device *pdev) for (gpio = 0, bank = 0; gpio < ngpio; gpio += 32, bank++) chips->regs[bank] = gpio_base + offset_array[bank]; - gpiochip_add_data(&chips->chip, chips); + ret = devm_gpiochip_add_data(dev, &chips->chip, chips); + if (ret) + goto err; + platform_set_drvdata(pdev, chips); davinci_gpio_irq_setup(pdev); return 0; + +err: + /* Revert the static variable increments */ + ctrl_num--; + bank_base -= ngpio; + + return ret; } /*--------------------------------------------------------------------------*/ -- cgit v1.2.3-55-g7522 From 1a9ef909acc1d2e4ded41465e4ced22291ee999a Mon Sep 17 00:00:00 2001 From: Keerthy Date: Thu, 20 Jul 2017 15:12:18 +0530 Subject: gpio: davinci: Convert prinkt to dev_err In case of devm_clk_get failure use dev_err instead of printk Signed-off-by: Keerthy Signed-off-by: Linus Walleij --- drivers/gpio/gpio-davinci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 27499ecc3c5e..3fb970a74fd7 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -487,8 +487,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) clk = devm_clk_get(dev, "gpio"); if (IS_ERR(clk)) { - printk(KERN_ERR "Error %ld getting gpio clock?\n", - PTR_ERR(clk)); + dev_err(dev, "Error %ld getting gpio clock\n", PTR_ERR(clk)); return PTR_ERR(clk); } ret = clk_prepare_enable(clk); -- cgit v1.2.3-55-g7522 From 7eb6ce2f272336ff8337f40fa8668fa04dc2d684 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 18 Jul 2017 16:43:03 -0500 Subject: gpio: Convert to using %pOF instead of full_name Now that we have a custom printf format specifier, convert users of full_name to use %pOF instead. This is preparation to remove storing of the full path string for each node. Signed-off-by: Rob Herring Cc: Tien Hock Loh Cc: Linus Walleij Cc: Alexandre Courbot Cc: Brian Norris Cc: Florian Fainelli Cc: bcm-kernel-feedback-list@broadcom.com Cc: Michal Simek Cc: "Sören Brinkmann" Cc: linux-gpio@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Acked-by: Gregory Fong Signed-off-by: Linus Walleij --- drivers/gpio/gpio-altera.c | 4 ++-- drivers/gpio/gpio-brcmstb.c | 2 +- drivers/gpio/gpio-ge.c | 6 ++---- drivers/gpio/gpio-grgpio.c | 2 +- drivers/gpio/gpio-mpc8xxx.c | 4 ++-- drivers/gpio/gpio-tb10x.c | 3 ++- drivers/gpio/gpio-tz1090.c | 10 ++++------ drivers/gpio/gpio-xilinx.c | 4 ++-- drivers/gpio/gpiolib-of.c | 29 ++++++++++++++--------------- drivers/gpio/gpiolib.c | 2 +- 10 files changed, 31 insertions(+), 35 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c index 17485dc20384..ccc02ed65b3c 100644 --- a/drivers/gpio/gpio-altera.c +++ b/drivers/gpio/gpio-altera.c @@ -324,8 +324,8 @@ skip_irq: return 0; teardown: of_mm_gpiochip_remove(&altera_gc->mmchip); - pr_err("%s: registration failed with status %d\n", - node->full_name, ret); + pr_err("%pOF: registration failed with status %d\n", + node, ret); return ret; } diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index e6489143721a..73f2c3be4657 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -483,7 +483,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) gc->of_node = np; gc->owner = THIS_MODULE; - gc->label = np->full_name; + gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", dev->of_node); gc->base = gpio_base; gc->of_gpio_n_cells = 2; gc->of_xlate = brcmstb_gpio_of_xlate; diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c index 8650b2916f87..6f5a7fe9787d 100644 --- a/drivers/gpio/gpio-ge.c +++ b/drivers/gpio/gpio-ge.c @@ -76,8 +76,7 @@ static int __init gef_gpio_probe(struct platform_device *pdev) } /* Setup pointers to chip functions */ - gc->label = devm_kstrdup(&pdev->dev, pdev->dev.of_node->full_name, - GFP_KERNEL); + gc->label = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%pOF", pdev->dev.of_node); if (!gc->label) { ret = -ENOMEM; goto err0; @@ -96,8 +95,7 @@ static int __init gef_gpio_probe(struct platform_device *pdev) return 0; err0: iounmap(regs); - pr_err("%s: GPIO chip registration failed\n", - pdev->dev.of_node->full_name); + pr_err("%pOF: GPIO chip registration failed\n", pdev->dev.of_node); return ret; }; diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c index 7847dd34f86f..6544a16ab02e 100644 --- a/drivers/gpio/gpio-grgpio.c +++ b/drivers/gpio/gpio-grgpio.c @@ -367,7 +367,7 @@ static int grgpio_probe(struct platform_device *ofdev) gc->of_node = np; gc->owner = THIS_MODULE; gc->to_irq = grgpio_to_irq; - gc->label = np->full_name; + gc->label = devm_kasprintf(&ofdev->dev, GFP_KERNEL, "%pOF", np); gc->base = -1; err = of_property_read_u32(np, "nbits", &prop); diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index 793518a30afe..8c93dec498fa 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -348,8 +348,8 @@ static int mpc8xxx_probe(struct platform_device *pdev) ret = gpiochip_add_data(gc, mpc8xxx_gc); if (ret) { - pr_err("%s: GPIO chip registration failed with status %d\n", - np->full_name, ret); + pr_err("%pOF: GPIO chip registration failed with status %d\n", + np, ret); goto err; } diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c index 80b6959ae995..091ffaaec635 100644 --- a/drivers/gpio/gpio-tb10x.c +++ b/drivers/gpio/gpio-tb10x.c @@ -191,7 +191,8 @@ static int tb10x_gpio_probe(struct platform_device *pdev) if (IS_ERR(tb10x_gpio->base)) return PTR_ERR(tb10x_gpio->base); - tb10x_gpio->gc.label = of_node_full_name(dn); + tb10x_gpio->gc.label = + devm_kasprintf(&pdev->dev, GFP_KERNEL, "%pOF", pdev->dev.of_node); tb10x_gpio->gc.parent = &pdev->dev; tb10x_gpio->gc.owner = THIS_MODULE; tb10x_gpio->gc.direction_input = tb10x_gpio_direction_in; diff --git a/drivers/gpio/gpio-tz1090.c b/drivers/gpio/gpio-tz1090.c index ca958e0f6909..22c5be65051f 100644 --- a/drivers/gpio/gpio-tz1090.c +++ b/drivers/gpio/gpio-tz1090.c @@ -527,13 +527,12 @@ static void tz1090_gpio_register_banks(struct tz1090_gpio *priv) ret = of_property_read_u32(node, "reg", &addr); if (ret) { - dev_err(priv->dev, "invalid reg on %s\n", - node->full_name); + dev_err(priv->dev, "invalid reg on %pOF\n", node); continue; } if (addr >= 3) { - dev_err(priv->dev, "index %u in %s out of range\n", - addr, node->full_name); + dev_err(priv->dev, "index %u in %pOF out of range\n", + addr, node); continue; } @@ -543,8 +542,7 @@ static void tz1090_gpio_register_banks(struct tz1090_gpio *priv) ret = tz1090_gpio_bank_probe(&info); if (ret) { - dev_err(priv->dev, "failure registering %s\n", - node->full_name); + dev_err(priv->dev, "failure registering %pOF\n", node); of_node_put(node); continue; } diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 14b2a62338ea..e8ec0e33a0a9 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -360,8 +360,8 @@ static int xgpio_probe(struct platform_device *pdev) /* Call the OF gpio helper to setup and register the GPIO device */ status = of_mm_gpiochip_add_data(np, &chip->mmchip, chip); if (status) { - pr_err("%s: error in probe function with status %d\n", - np->full_name, status); + pr_err("%pOF: error in probe function with status %d\n", + np, status); return status; } diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 54ce8dc58ad0..8cde02ed5fd5 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -78,8 +78,8 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index, &gpiospec); if (ret) { - pr_debug("%s: can't parse '%s' property of node '%s[%d]'\n", - __func__, propname, np->full_name, index); + pr_debug("%s: can't parse '%s' property of node '%pOF[%d]'\n", + __func__, propname, np, index); return ERR_PTR(ret); } @@ -93,8 +93,8 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, if (IS_ERR(desc)) goto out; - pr_debug("%s: parsed '%s' property of node '%s[%d]' - status (%d)\n", - __func__, propname, np->full_name, index, + pr_debug("%s: parsed '%s' property of node '%pOF[%d]' - status (%d)\n", + __func__, propname, np, index, PTR_ERR_OR_ZERO(desc)); out: @@ -337,7 +337,7 @@ int of_mm_gpiochip_add_data(struct device_node *np, int ret = -ENOMEM; struct gpio_chip *gc = &mm_gc->gc; - gc->label = kstrdup(np->full_name, GFP_KERNEL); + gc->label = kasprintf(GFP_KERNEL, "%pOF", np); if (!gc->label) goto err0; @@ -362,8 +362,7 @@ err2: err1: kfree(gc->label); err0: - pr_err("%s: GPIO chip registration failed with status %d\n", - np->full_name, ret); + pr_err("%pOF: GPIO chip registration failed with status %d\n", np, ret); return ret; } EXPORT_SYMBOL(of_mm_gpiochip_add_data); @@ -418,8 +417,8 @@ static int of_gpiochip_add_pin_range(struct gpio_chip *chip) group_names_propname, index, &name); if (strlen(name)) { - pr_err("%s: Group name of numeric GPIO ranges must be the empty string.\n", - np->full_name); + pr_err("%pOF: Group name of numeric GPIO ranges must be the empty string.\n", + np); break; } } @@ -434,14 +433,14 @@ static int of_gpiochip_add_pin_range(struct gpio_chip *chip) } else { /* npins == 0: special range */ if (pinspec.args[1]) { - pr_err("%s: Illegal gpio-range format.\n", - np->full_name); + pr_err("%pOF: Illegal gpio-range format.\n", + np); break; } if (!group_names) { - pr_err("%s: GPIO group range requested but no %s property.\n", - np->full_name, group_names_propname); + pr_err("%pOF: GPIO group range requested but no %s property.\n", + np, group_names_propname); break; } @@ -452,8 +451,8 @@ static int of_gpiochip_add_pin_range(struct gpio_chip *chip) break; if (!strlen(name)) { - pr_err("%s: Group name of GPIO group range cannot be the empty string.\n", - np->full_name); + pr_err("%pOF: Group name of GPIO group range cannot be the empty string.\n", + np); break; } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 92a5503f739d..528539d31274 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1787,7 +1787,7 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip, * conflicting triggers. Tell the user, and reset to NONE. */ if (WARN(of_node && type != IRQ_TYPE_NONE, - "%s: Ignoring %d default trigger\n", of_node->full_name, type)) + "%pOF: Ignoring %d default trigger\n", of_node, type)) type = IRQ_TYPE_NONE; if (has_acpi_companion(gpiochip->parent) && type != IRQ_TYPE_NONE) { acpi_handle_warn(ACPI_HANDLE(gpiochip->parent), -- cgit v1.2.3-55-g7522 From 564209037dfe09b91a9110e80bd4bcdbccfcceed Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 20 Jul 2017 18:00:56 +0200 Subject: gpio: tegra: Use platform_irq_count() Use platform_irq_count() instead of open-coding the same code sequence. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tegra.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 1e72c52fbf35..b8de130d2ecd 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -589,13 +589,12 @@ static int tegra_gpio_probe(struct platform_device *pdev) tgi->soc = config; tgi->dev = &pdev->dev; - for (;;) { - res = platform_get_resource(pdev, IORESOURCE_IRQ, - tgi->bank_count); - if (!res) - break; - tgi->bank_count++; - } + ret = platform_irq_count(pdev); + if (ret < 0) + return ret; + + tgi->bank_count = ret; + if (!tgi->bank_count) { dev_err(&pdev->dev, "Missing IRQ resource\n"); return -ENODEV; -- cgit v1.2.3-55-g7522 From 9c07409c34ddf1804721cee21ca835733e165bde Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 20 Jul 2017 18:00:57 +0200 Subject: gpio: tegra: Use platform_get_irq() Instead of using platform_get_resource() and getting the interrupts from the resource, use platform_get_irq() which is slightly easier to use and covers some special cases that the former doesn't. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tegra.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index b8de130d2ecd..755d3b61fbb7 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -641,15 +641,15 @@ static int tegra_gpio_probe(struct platform_device *pdev) return -ENODEV; for (i = 0; i < tgi->bank_count; i++) { - res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - if (!res) { - dev_err(&pdev->dev, "Missing IRQ resource\n"); - return -ENODEV; + ret = platform_get_irq(pdev, i); + if (ret < 0) { + dev_err(&pdev->dev, "Missing IRQ resource: %d\n", ret); + return ret; } bank = &tgi->bank_info[i]; bank->bank = i; - bank->irq = res->start; + bank->irq = ret; bank->tgi = tgi; } -- cgit v1.2.3-55-g7522 From 950d55f5bf7991222e34428b5f779bd030b6a42a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 24 Jul 2017 16:57:22 +0200 Subject: gpio: Cleanup kerneldoc Some kerneldoc has become stale or wasn't quite correct from the outset. Fix up the most serious issues to silence warnings when building the documentation. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 82 +++++++++++++++++++++++++++++++++------------ include/linux/gpio/driver.h | 3 +- 2 files changed, 61 insertions(+), 24 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 528539d31274..18bba1748a35 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -84,7 +84,12 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label) } /** - * Convert a GPIO number to its descriptor + * gpio_to_desc - Convert a GPIO number to its descriptor + * @gpio: global GPIO number + * + * Returns: + * The GPIO descriptor associated with the given GPIO, or %NULL if no GPIO + * with the given number exists in the system. */ struct gpio_desc *gpio_to_desc(unsigned gpio) { @@ -111,7 +116,14 @@ struct gpio_desc *gpio_to_desc(unsigned gpio) EXPORT_SYMBOL_GPL(gpio_to_desc); /** - * Get the GPIO descriptor corresponding to the given hw number for this chip. + * gpiochip_get_desc - get the GPIO descriptor corresponding to the given + * hardware number for this chip + * @chip: GPIO chip + * @hwnum: hardware number of the GPIO for this chip + * + * Returns: + * A pointer to the GPIO descriptor or %ERR_PTR(-EINVAL) if no GPIO exists + * in the given chip for the specified hardware number. */ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, u16 hwnum) @@ -125,9 +137,14 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, } /** - * Convert a GPIO descriptor to the integer namespace. + * desc_to_gpio - convert a GPIO descriptor to the integer namespace + * @desc: GPIO descriptor + * * This should disappear in the future but is needed since we still - * use GPIO numbers for error messages and sysfs nodes + * use GPIO numbers for error messages and sysfs nodes. + * + * Returns: + * The global GPIO number for the GPIO specified by its descriptor. */ int desc_to_gpio(const struct gpio_desc *desc) { @@ -254,7 +271,7 @@ static int gpiodev_add_to_list(struct gpio_device *gdev) return -EBUSY; } -/** +/* * Convert a GPIO name to its descriptor */ static struct gpio_desc *gpio_name_to_desc(const char * const name) @@ -878,7 +895,7 @@ out_free_le: return ret; } -/** +/* * gpio_ioctl() - ioctl handler for the GPIO chardev */ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) @@ -1077,11 +1094,9 @@ static void gpiochip_setup_devs(void) /** * gpiochip_add_data() - register a gpio_chip * @chip: the chip to register, with chip->base initialized - * Context: potentially before irqs will work + * @data: driver-private data associated with this chip * - * Returns a negative errno if the chip can't be registered, such as - * because the chip->base is invalid or already associated with a - * different chip. Otherwise it returns zero as a success code. + * Context: potentially before irqs will work * * When gpiochip_add_data() is called very early during boot, so that GPIOs * can be freely used, the chip->parent device must be registered before @@ -1093,6 +1108,11 @@ static void gpiochip_setup_devs(void) * * If chip->base is negative, this requests dynamic assignment of * a range of valid GPIOs. + * + * Returns: + * A negative errno if the chip can't be registered, such as because the + * chip->base is invalid or already associated with a different chip. + * Otherwise it returns zero as a success code. */ int gpiochip_add_data(struct gpio_chip *chip, void *data) { @@ -1298,6 +1318,10 @@ EXPORT_SYMBOL_GPL(gpiochip_add_data); /** * gpiochip_get_data() - get per-subdriver data for the chip + * @chip: GPIO chip + * + * Returns: + * The per-subdriver data for the chip. */ void *gpiochip_get_data(struct gpio_chip *chip) { @@ -1381,13 +1405,16 @@ static int devm_gpio_chip_match(struct device *dev, void *res, void *data) * devm_gpiochip_add_data() - Resource manager piochip_add_data() * @dev: the device pointer on which irq_chip belongs to. * @chip: the chip to register, with chip->base initialized - * Context: potentially before irqs will work + * @data: driver-private data associated with this chip * - * Returns a negative errno if the chip can't be registered, such as - * because the chip->base is invalid or already associated with a - * different chip. Otherwise it returns zero as a success code. + * Context: potentially before irqs will work * * The gpio chip automatically be released when the device is unbound. + * + * Returns: + * A negative errno if the chip can't be registered, such as because the + * chip->base is invalid or already associated with a different chip. + * Otherwise it returns zero as a success code. */ int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *chip, void *data) @@ -1433,7 +1460,7 @@ EXPORT_SYMBOL_GPL(devm_gpiochip_remove); /** * gpiochip_find() - iterator for locating a specific gpio_chip * @data: data to pass to match function - * @callback: Callback function to check gpio_chip + * @match: Callback function to check gpio_chip * * Similar to bus_find_device. It returns a reference to a gpio_chip as * determined by a user supplied @match callback. The callback should return @@ -1924,11 +1951,14 @@ EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range); /** * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping * @chip: the gpiochip to add the range for - * @pinctrl_name: the dev_name() of the pin controller to map to + * @pinctl_name: the dev_name() of the pin controller to map to * @gpio_offset: the start offset in the current gpio_chip number space * @pin_offset: the start offset in the pin controller number space * @npins: the number of pins from the offset of each pin space (GPIO and * pin controller) to accumulate in this range + * + * Returns: + * 0 on success, or a negative error-code on failure. */ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, unsigned int gpio_offset, unsigned int pin_offset, @@ -2173,7 +2203,8 @@ EXPORT_SYMBOL_GPL(gpiochip_is_requested); /** * gpiochip_request_own_desc - Allow GPIO chip to request its own descriptor - * @desc: GPIO descriptor to request + * @chip: GPIO chip + * @hwnum: hardware number of the GPIO for which to request the descriptor * @label: label for the GPIO * * Function allows GPIO chip drivers to request and use their own GPIO @@ -2181,6 +2212,10 @@ EXPORT_SYMBOL_GPL(gpiochip_is_requested); * function will not increase reference count of the GPIO chip module. This * allows the GPIO chip module to be unloaded as needed (we assume that the * GPIO chip driver handles freeing the GPIOs it has requested). + * + * Returns: + * A pointer to the GPIO descriptor, or an ERR_PTR()-encoded negative error + * code on failure. */ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, u16 hwnum, const char *label) @@ -2362,12 +2397,13 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) EXPORT_SYMBOL_GPL(gpiod_direction_output); /** - * gpiod_set_debounce - sets @debounce time for a @gpio - * @gpio: the gpio to set debounce time - * @debounce: debounce time is microseconds + * gpiod_set_debounce - sets @debounce time for a GPIO + * @desc: descriptor of the GPIO for which to set debounce time + * @debounce: debounce time in microseconds * - * returns -ENOTSUPP if the controller does not support setting - * debounce. + * Returns: + * 0 on success, %-ENOTSUPP if the controller doesn't support setting the + * debounce time. */ int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) { @@ -3316,6 +3352,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_index); * @propname: name of the firmware property representing the GPIO * @index: index of the GPIO to obtain in the consumer * @dflags: GPIO initialization flags + * @label: label to attach to the requested GPIO * * This function can be used for drivers that get their configuration * from firmware. @@ -3324,6 +3361,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_index); * underlying firmware interface and then makes sure that the GPIO * descriptor is requested before it is returned to the caller. * + * Returns: * On successful request the GPIO pin is configured in accordance with * provided @dflags. * diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index af20369ec8e7..ad4150d075c3 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -327,11 +327,10 @@ int gpiochip_generic_config(struct gpio_chip *chip, unsigned offset, /** * struct gpio_pin_range - pin range controlled by a gpio chip - * @head: list for maintaining set of pin ranges, used internally + * @node: list for maintaining set of pin ranges, used internally * @pctldev: pinctrl device which handles corresponding pins * @range: actual range of pins controlled by a gpio controller */ - struct gpio_pin_range { struct list_head node; struct pinctrl_dev *pctldev; -- cgit v1.2.3-55-g7522 From 67049c505017d7b380e16aa4f4b02344c2be0d55 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 24 Jul 2017 16:57:23 +0200 Subject: gpio: of: Improve kerneldoc Add descriptions for missing fields and fix up some parameter references to match the code. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 7 +++---- include/linux/gpio/driver.h | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 8cde02ed5fd5..bfcd20699ec8 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -273,14 +273,13 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip) } /** - * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags + * of_gpio_simple_xlate - translate gpiospec to the GPIO number and flags * @gc: pointer to the gpio_chip structure - * @np: device node of the GPIO chip - * @gpio_spec: gpio specifier as found in the device tree + * @gpiospec: GPIO specifier as found in the device tree * @flags: a flags pointer to fill in * * This is simple translation function, suitable for the most 1:1 mapped - * gpio chips. This function performs only one sanity check: whether gpio + * GPIO chips. This function performs only one sanity check: whether GPIO * is less than ngpios (that is specified in the gpio_chip). */ int of_gpio_simple_xlate(struct gpio_chip *gc, diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index ad4150d075c3..fe66c9306caf 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -180,8 +180,27 @@ struct gpio_chip { * If CONFIG_OF is enabled, then all GPIO controllers described in the * device tree automatically may have an OF translation */ + + /** + * @of_node: + * + * Pointer to a device tree node representing this GPIO controller. + */ struct device_node *of_node; + + /** + * @of_gpio_n_cells: + * + * Number of cells used to form the GPIO specifier. + */ int of_gpio_n_cells; + + /** + * @of_xlate: + * + * Callback to translate a device tree GPIO specifier into a chip- + * relative GPIO number and flags. + */ int (*of_xlate)(struct gpio_chip *gc, const struct of_phandle_args *gpiospec, u32 *flags); #endif -- cgit v1.2.3-55-g7522 From 2b7c809bd48ad99eb34ac0c3f628b7ae42630191 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 24 Jul 2017 16:57:24 +0200 Subject: gpio: devres: Improve kerneldoc Add missing descriptions for some parameters to match the code. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/devres.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c index a75511d1ea5d..afbff155a0ba 100644 --- a/drivers/gpio/devres.c +++ b/drivers/gpio/devres.c @@ -132,6 +132,7 @@ EXPORT_SYMBOL(devm_gpiod_get_index); * @index: index of the GPIO to obtain in the consumer * @child: firmware node (child of @dev) * @flags: GPIO initialization flags + * @label: label to attach to the requested GPIO * * GPIO descriptors returned from this function are automatically disposed on * driver detach. @@ -271,6 +272,7 @@ EXPORT_SYMBOL(devm_gpiod_get_array_optional); /** * devm_gpiod_put - Resource-managed gpiod_put() + * @dev: GPIO consumer * @desc: GPIO descriptor to dispose of * * Dispose of a GPIO descriptor obtained with devm_gpiod_get() or @@ -286,6 +288,7 @@ EXPORT_SYMBOL(devm_gpiod_put); /** * devm_gpiod_put_array - Resource-managed gpiod_put_array() + * @dev: GPIO consumer * @descs: GPIO descriptor array to dispose of * * Dispose of an array of GPIO descriptors obtained with devm_gpiod_get_array(). -- cgit v1.2.3-55-g7522 From db05c7ef5465341d8a73ebe70c39b7ba6ddf2f48 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 24 Jul 2017 16:57:25 +0200 Subject: gpio: acpi: Fixup kerneldoc Fix up a parameter description to match the code and fix markup for a constant to prettify output. Signed-off-by: Thierry Reding Acked-by: Andy Shevchenko Acked-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index c9b42dd12dfa..4d2113530735 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -61,7 +61,7 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) #ifdef CONFIG_PINCTRL /** * acpi_gpiochip_pin_to_gpio_offset() - translates ACPI GPIO to Linux GPIO - * @chip: GPIO chip + * @gdev: GPIO device * @pin: ACPI GPIO pin number from GpioIo/GpioInt resource * * Function takes ACPI GpioIo/GpioInt pin number as a parameter and @@ -763,7 +763,7 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, * The function is idempotent, though each time it runs it will configure GPIO * pin direction according to the flags in GpioInt resource. * - * Return: Linux IRQ number (>%0) on success, negative errno on failure. + * Return: Linux IRQ number (> %0) on success, negative errno on failure. */ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) { -- cgit v1.2.3-55-g7522 From 2d9d05192e7d1a77d5d47758f32391f8f9773532 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 24 Jul 2017 16:57:26 +0200 Subject: gpio: sysfs: Fixup kerneldoc Fix up some references to parameters to match the code. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-sysfs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 16fe9742597b..45b8c0679fee 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -534,8 +534,8 @@ static struct class gpio_class = { /** * gpiod_export - export a GPIO through sysfs - * @gpio: gpio to make available, already requested - * @direction_may_change: true if userspace may change gpio direction + * @desc: GPIO to make available, already requested + * @direction_may_change: true if userspace may change GPIO direction * Context: arch_initcall or later * * When drivers want to make a GPIO accessible to userspace after they @@ -643,7 +643,7 @@ static int match_export(struct device *dev, const void *desc) * gpiod_export_link - create a sysfs link to an exported GPIO node * @dev: device under which to create symlink * @name: name of the symlink - * @gpio: gpio to create symlink to, already exported + * @desc: GPIO to create symlink to, already exported * * Set up a symlink from /sys/.../dev/name to /sys/class/gpio/gpioN * node. Caller is responsible for unlinking. @@ -674,7 +674,7 @@ EXPORT_SYMBOL_GPL(gpiod_export_link); /** * gpiod_unexport - reverse effect of gpiod_export() - * @gpio: gpio to make unavailable + * @desc: GPIO to make unavailable * * This is implicit on gpiod_free(). */ -- cgit v1.2.3-55-g7522 From 20133bd5ebbb58cdf224c769dea2a475c746bc1a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 24 Jul 2017 16:55:05 +0200 Subject: gpio: tegra: Remove unnecessary check of_device_get_match_data() can never return NULL, therefore the check for NULL values is unnecessary. Signed-off-by: Thierry Reding Acked-by: Jon Hunter Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tegra.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 755d3b61fbb7..c68455b7e26e 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -567,7 +567,6 @@ static struct lock_class_key gpio_lock_class; static int tegra_gpio_probe(struct platform_device *pdev) { - const struct tegra_gpio_soc_config *config; struct tegra_gpio_info *tgi; struct resource *res; struct tegra_gpio_bank *bank; @@ -576,17 +575,11 @@ static int tegra_gpio_probe(struct platform_device *pdev) int i; int j; - config = of_device_get_match_data(&pdev->dev); - if (!config) { - dev_err(&pdev->dev, "Error: No device match found\n"); - return -ENODEV; - } - tgi = devm_kzalloc(&pdev->dev, sizeof(*tgi), GFP_KERNEL); if (!tgi) return -ENODEV; - tgi->soc = config; + tgi->soc = of_device_get_match_data(&pdev->dev); tgi->dev = &pdev->dev; ret = platform_irq_count(pdev); @@ -626,7 +619,7 @@ static int tegra_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, tgi); - if (config->debounce_supported) + if (tgi->soc->debounce_supported) tgi->gc.set_config = tegra_gpio_set_config; tgi->bank_info = devm_kzalloc(&pdev->dev, tgi->bank_count * -- cgit v1.2.3-55-g7522 From 9b88226924cf640059aacba7af23d048c6ec03b1 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 24 Jul 2017 16:55:06 +0200 Subject: gpio: tegra: Prefer kcalloc() over kzalloc() with multiplies Rather than manually compute the size of an array, pass the number and element size to kcalloc(). Signed-off-by: Thierry Reding Acked-by: Jon Hunter Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tegra.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index c68455b7e26e..17a664118a97 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -622,10 +622,10 @@ static int tegra_gpio_probe(struct platform_device *pdev) if (tgi->soc->debounce_supported) tgi->gc.set_config = tegra_gpio_set_config; - tgi->bank_info = devm_kzalloc(&pdev->dev, tgi->bank_count * + tgi->bank_info = devm_kcalloc(&pdev->dev, tgi->bank_count, sizeof(*tgi->bank_info), GFP_KERNEL); if (!tgi->bank_info) - return -ENODEV; + return -ENOMEM; tgi->irq_domain = irq_domain_add_linear(pdev->dev.of_node, tgi->gc.ngpio, -- cgit v1.2.3-55-g7522 From 4bc178608baec1723d9a6bb70cd3360a0a4edd21 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 24 Jul 2017 16:55:07 +0200 Subject: gpio: tegra: Fix checkpatch warnings Fix a couple of checkpatch warnings, such as complaints about bare unsigned being used (instead of unsigned int) and missing blank lines after declarations. Signed-off-by: Thierry Reding Acked-by: Jon Hunter Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tegra.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 17a664118a97..564edb40920e 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -138,12 +138,12 @@ static void tegra_gpio_disable(struct tegra_gpio_info *tgi, int gpio) tegra_gpio_mask_write(tgi, GPIO_MSK_CNF(tgi, gpio), gpio, 0); } -static int tegra_gpio_request(struct gpio_chip *chip, unsigned offset) +static int tegra_gpio_request(struct gpio_chip *chip, unsigned int offset) { return pinctrl_request_gpio(offset); } -static void tegra_gpio_free(struct gpio_chip *chip, unsigned offset) +static void tegra_gpio_free(struct gpio_chip *chip, unsigned int offset) { struct tegra_gpio_info *tgi = gpiochip_get_data(chip); @@ -151,14 +151,15 @@ static void tegra_gpio_free(struct gpio_chip *chip, unsigned offset) tegra_gpio_disable(tgi, offset); } -static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static void tegra_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { struct tegra_gpio_info *tgi = gpiochip_get_data(chip); tegra_gpio_mask_write(tgi, GPIO_MSK_OUT(tgi, offset), offset, value); } -static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset) +static int tegra_gpio_get(struct gpio_chip *chip, unsigned int offset) { struct tegra_gpio_info *tgi = gpiochip_get_data(chip); int bval = BIT(GPIO_BIT(offset)); @@ -170,7 +171,8 @@ static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset) return !!(tegra_gpio_readl(tgi, GPIO_IN(tgi, offset)) & bval); } -static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +static int tegra_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) { struct tegra_gpio_info *tgi = gpiochip_get_data(chip); @@ -179,8 +181,9 @@ static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset) return 0; } -static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset, - int value) +static int tegra_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, + int value) { struct tegra_gpio_info *tgi = gpiochip_get_data(chip); @@ -190,7 +193,8 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset, return 0; } -static int tegra_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +static int tegra_gpio_get_direction(struct gpio_chip *chip, + unsigned int offset) { struct tegra_gpio_info *tgi = gpiochip_get_data(chip); u32 pin_mask = BIT(GPIO_BIT(offset)); @@ -250,7 +254,7 @@ static int tegra_gpio_set_config(struct gpio_chip *chip, unsigned int offset, return tegra_gpio_set_debounce(chip, offset, debounce); } -static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) { struct tegra_gpio_info *tgi = gpiochip_get_data(chip); @@ -414,7 +418,8 @@ static int tegra_gpio_resume(struct device *dev) struct tegra_gpio_bank *bank = &tgi->bank_info[b]; for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { - unsigned int gpio = (b<<5) | (p<<3); + unsigned int gpio = (b << 5) | (p << 3); + tegra_gpio_writel(tgi, bank->cnf[p], GPIO_CNF(tgi, gpio)); @@ -453,7 +458,8 @@ static int tegra_gpio_suspend(struct device *dev) struct tegra_gpio_bank *bank = &tgi->bank_info[b]; for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { - unsigned int gpio = (b<<5) | (p<<3); + unsigned int gpio = (b << 5) | (p << 3); + bank->cnf[p] = tegra_gpio_readl(tgi, GPIO_CNF(tgi, gpio)); bank->out[p] = tegra_gpio_readl(tgi, @@ -514,6 +520,7 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) for (i = 0; i < tgi->bank_count; i++) { for (j = 0; j < 4; j++) { int gpio = tegra_gpio_compose(i, j, 0); + seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", i, j, @@ -543,7 +550,7 @@ static const struct file_operations debug_fops = { static void tegra_gpio_debuginit(struct tegra_gpio_info *tgi) { - (void) debugfs_create_file("tegra_gpio", S_IRUGO, + (void) debugfs_create_file("tegra_gpio", 0444, NULL, tgi, &debug_fops); } @@ -654,6 +661,7 @@ static int tegra_gpio_probe(struct platform_device *pdev) for (i = 0; i < tgi->bank_count; i++) { for (j = 0; j < 4; j++) { int gpio = tegra_gpio_compose(i, j, 0); + tegra_gpio_writel(tgi, 0x00, GPIO_INT_ENB(tgi, gpio)); } } -- cgit v1.2.3-55-g7522 From 539b7a39f5ec4cfb573af1e65aeed0edf32be8bb Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 24 Jul 2017 16:55:08 +0200 Subject: gpio: tegra: Use unsigned int where possible In most of the cases, integers in this file can't be negative, so the type can be more restricted for clarity. Signed-off-by: Thierry Reding Acked-by: Jon Hunter Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tegra.c | 56 ++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 32 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 564edb40920e..fbaf974277df 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -67,8 +67,8 @@ struct tegra_gpio_info; struct tegra_gpio_bank { - int bank; - int irq; + unsigned int bank; + unsigned int irq; spinlock_t lvl_lock[4]; spinlock_t dbc_lock[4]; /* Lock for updating debounce count register */ #ifdef CONFIG_PM_SLEEP @@ -112,13 +112,14 @@ static inline u32 tegra_gpio_readl(struct tegra_gpio_info *tgi, u32 reg) return __raw_readl(tgi->regs + reg); } -static int tegra_gpio_compose(int bank, int port, int bit) +static unsigned int tegra_gpio_compose(unsigned int bank, unsigned int port, + unsigned int bit) { return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7); } static void tegra_gpio_mask_write(struct tegra_gpio_info *tgi, u32 reg, - int gpio, int value) + unsigned int gpio, u32 value) { u32 val; @@ -128,12 +129,12 @@ static void tegra_gpio_mask_write(struct tegra_gpio_info *tgi, u32 reg, tegra_gpio_writel(tgi, val, reg); } -static void tegra_gpio_enable(struct tegra_gpio_info *tgi, int gpio) +static void tegra_gpio_enable(struct tegra_gpio_info *tgi, unsigned int gpio) { tegra_gpio_mask_write(tgi, GPIO_MSK_CNF(tgi, gpio), gpio, 1); } -static void tegra_gpio_disable(struct tegra_gpio_info *tgi, int gpio) +static void tegra_gpio_disable(struct tegra_gpio_info *tgi, unsigned int gpio) { tegra_gpio_mask_write(tgi, GPIO_MSK_CNF(tgi, gpio), gpio, 0); } @@ -162,7 +163,7 @@ static void tegra_gpio_set(struct gpio_chip *chip, unsigned int offset, static int tegra_gpio_get(struct gpio_chip *chip, unsigned int offset) { struct tegra_gpio_info *tgi = gpiochip_get_data(chip); - int bval = BIT(GPIO_BIT(offset)); + unsigned int bval = BIT(GPIO_BIT(offset)); /* If gpio is in output mode then read from the out value */ if (tegra_gpio_readl(tgi, GPIO_OE(tgi, offset)) & bval) @@ -216,7 +217,7 @@ static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset, struct tegra_gpio_bank *bank = &tgi->bank_info[GPIO_BANK(offset)]; unsigned int debounce_ms = DIV_ROUND_UP(debounce, 1000); unsigned long flags; - int port; + unsigned int port; if (!debounce_ms) { tegra_gpio_mask_write(tgi, GPIO_MSK_DBC_EN(tgi, offset), @@ -265,7 +266,7 @@ static void tegra_gpio_irq_ack(struct irq_data *d) { struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); struct tegra_gpio_info *tgi = bank->tgi; - int gpio = d->hwirq; + unsigned int gpio = d->hwirq; tegra_gpio_writel(tgi, 1 << GPIO_BIT(gpio), GPIO_INT_CLR(tgi, gpio)); } @@ -274,7 +275,7 @@ static void tegra_gpio_irq_mask(struct irq_data *d) { struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); struct tegra_gpio_info *tgi = bank->tgi; - int gpio = d->hwirq; + unsigned int gpio = d->hwirq; tegra_gpio_mask_write(tgi, GPIO_MSK_INT_ENB(tgi, gpio), gpio, 0); } @@ -283,20 +284,18 @@ static void tegra_gpio_irq_unmask(struct irq_data *d) { struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); struct tegra_gpio_info *tgi = bank->tgi; - int gpio = d->hwirq; + unsigned int gpio = d->hwirq; tegra_gpio_mask_write(tgi, GPIO_MSK_INT_ENB(tgi, gpio), gpio, 1); } static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) { - int gpio = d->hwirq; + unsigned int gpio = d->hwirq, port = GPIO_PORT(gpio), lvl_type; struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); struct tegra_gpio_info *tgi = bank->tgi; - int port = GPIO_PORT(gpio); - int lvl_type; - int val; unsigned long flags; + u32 val; int ret; switch (type & IRQ_TYPE_SENSE_MASK) { @@ -327,7 +326,7 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) ret = gpiochip_lock_as_irq(&tgi->gc, gpio); if (ret) { dev_err(tgi->dev, - "unable to lock Tegra GPIO %d as IRQ\n", gpio); + "unable to lock Tegra GPIO %u as IRQ\n", gpio); return ret; } @@ -355,17 +354,15 @@ static void tegra_gpio_irq_shutdown(struct irq_data *d) { struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); struct tegra_gpio_info *tgi = bank->tgi; - int gpio = d->hwirq; + unsigned int gpio = d->hwirq; gpiochip_unlock_as_irq(&tgi->gc, gpio); } static void tegra_gpio_irq_handler(struct irq_desc *desc) { - int port; - int pin; + unsigned int port, pin, gpio; bool unmasked = false; - int gpio; u32 lvl; unsigned long sta; struct irq_chip *chip = irq_desc_get_chip(desc); @@ -409,8 +406,7 @@ static int tegra_gpio_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct tegra_gpio_info *tgi = platform_get_drvdata(pdev); unsigned long flags; - int b; - int p; + unsigned int b, p; local_irq_save(flags); @@ -450,8 +446,7 @@ static int tegra_gpio_suspend(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct tegra_gpio_info *tgi = platform_get_drvdata(pdev); unsigned long flags; - int b; - int p; + unsigned int b, p; local_irq_save(flags); for (b = 0; b < tgi->bank_count; b++) { @@ -490,7 +485,7 @@ static int tegra_gpio_suspend(struct device *dev) static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable) { struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); - int gpio = d->hwirq; + unsigned int gpio = d->hwirq; u32 port, bit, mask; port = GPIO_PORT(gpio); @@ -514,15 +509,14 @@ static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable) static int dbg_gpio_show(struct seq_file *s, void *unused) { struct tegra_gpio_info *tgi = s->private; - int i; - int j; + unsigned int i, j; for (i = 0; i < tgi->bank_count; i++) { for (j = 0; j < 4; j++) { - int gpio = tegra_gpio_compose(i, j, 0); + unsigned int gpio = tegra_gpio_compose(i, j, 0); seq_printf(s, - "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", + "%u:%u %02x %02x %02x %02x %02x %02x %06x\n", i, j, tegra_gpio_readl(tgi, GPIO_CNF(tgi, gpio)), tegra_gpio_readl(tgi, GPIO_OE(tgi, gpio)), @@ -577,10 +571,8 @@ static int tegra_gpio_probe(struct platform_device *pdev) struct tegra_gpio_info *tgi; struct resource *res; struct tegra_gpio_bank *bank; + unsigned int gpio, i, j; int ret; - int gpio; - int i; - int j; tgi = devm_kzalloc(&pdev->dev, sizeof(*tgi), GFP_KERNEL); if (!tgi) -- cgit v1.2.3-55-g7522 From 01062ad31b531f2a3bcbfd9f6267e4e0c1103010 Mon Sep 17 00:00:00 2001 From: Diego Elio Pettenò Date: Tue, 25 Jul 2017 22:10:29 +0100 Subject: gpio: it87: add support for IT8772F Super I/O. From the datasheet, the GPIO interface is identical to IT8728 (same description), so just add it to the same case as the other chip. Signed-off-by: Diego Elio Pettenò Signed-off-by: Linus Walleij --- drivers/gpio/gpio-it87.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-it87.c b/drivers/gpio/gpio-it87.c index 45d29e488dbb..d43d0a2cc4c5 100644 --- a/drivers/gpio/gpio-it87.c +++ b/drivers/gpio/gpio-it87.c @@ -2,6 +2,7 @@ * GPIO interface for IT87xx Super I/O chips * * Author: Diego Elio Pettenò + * Copyright (c) 2017 Google, Inc. * * Based on it87_wdt.c by Oliver Schuster * gpio-it8761e.c by Denis Turischev @@ -39,6 +40,7 @@ #define IT8728_ID 0x8728 #define IT8732_ID 0x8732 #define IT8761_ID 0x8761 +#define IT8772_ID 0x8772 /* IO Ports */ #define REG 0x2e @@ -314,6 +316,7 @@ static int __init it87_gpio_init(void) break; case IT8728_ID: case IT8732_ID: + case IT8772_ID: gpio_ba_reg = 0x62; it87_gpio->io_size = 8; it87_gpio->output_base = 0xc8; -- cgit v1.2.3-55-g7522 From d829b37ae3bfdb7252e63bd098ad75a96adabe97 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Tue, 1 Aug 2017 12:13:05 +0530 Subject: gpio: mb86s7x: Handle return value of clk_prepare_enable. clk_prepare_enable() can fail here and we must check its return value. Signed-off-by: Arvind Yadav Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mb86s7x.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c index ffb73f688ae1..94d772677ed6 100644 --- a/drivers/gpio/gpio-mb86s7x.c +++ b/drivers/gpio/gpio-mb86s7x.c @@ -168,7 +168,9 @@ static int mb86s70_gpio_probe(struct platform_device *pdev) if (IS_ERR(gchip->clk)) return PTR_ERR(gchip->clk); - clk_prepare_enable(gchip->clk); + ret = clk_prepare_enable(gchip->clk); + if (ret) + return ret; spin_lock_init(&gchip->lock); -- cgit v1.2.3-55-g7522 From e2c3c1969dc77d4630cc88669f5fc6253210a025 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Tue, 1 Aug 2017 12:14:31 +0530 Subject: gpio: omap : Add missing clk_unprepare(). omap_gpio_probe() can fail here and we must disable clock. Signed-off-by: Arvind Yadav Reviewed-by: Grygorii Strashko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index f8c550de6c72..dbf869fb63ce 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1247,6 +1247,8 @@ static int omap_gpio_probe(struct platform_device *pdev) if (ret) { pm_runtime_put_sync(dev); pm_runtime_disable(dev); + if (bank->dbck_flag) + clk_unprepare(bank->dbck); return ret; } -- cgit v1.2.3-55-g7522 From ca1f3ae3154ad6d08caa740c99be0d86644a4e44 Mon Sep 17 00:00:00 2001 From: Gustavo A. R. Silva Date: Thu, 3 Aug 2017 17:00:01 -0500 Subject: gpio: msic: fix error return code in platform_msic_gpio_probe() platform_get_irq() returns an error code, but the gpio-msic driver ignores it and always returns -EINVAL. This is not correct, and prevents -EPROBE_DEFER from being propagated properly. Notice that platform_get_irq() no longer returns 0 on error: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e330b9a6bb35dc7097a4f02cb1ae7b6f96df92af Print and propagate the return value of platform_get_irq on failure. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Linus Walleij --- drivers/gpio/gpio-msic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c index 1b7ce7f85886..6cb67595d15f 100644 --- a/drivers/gpio/gpio-msic.c +++ b/drivers/gpio/gpio-msic.c @@ -265,8 +265,8 @@ static int platform_msic_gpio_probe(struct platform_device *pdev) int i; if (irq < 0) { - dev_err(dev, "no IRQ line\n"); - return -EINVAL; + dev_err(dev, "no IRQ line: %d\n", irq); + return irq; } if (!pdata || !pdata->gpio_base) { -- cgit v1.2.3-55-g7522 From 659d8a62311ffc61742927350534643ad58aee81 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Tue, 1 Aug 2017 22:04:17 +0800 Subject: gpio: vf610: add imx7ulp support The Rapid General-Purpose Input and Output with 2 Ports (RGPIO2P) on MX7ULP is similar to GPIO on Vibrid. But unlike Vibrid, the RGPIO2P has an extra Port Data Direction Register (PDDR) used to configure the individual port pins for input or output. We introduce a bool have_paddr with fsl_gpio_soc_data data to distinguish this differences. And we support getting the output status by checking the GPIO direction in PDDR. Cc: Alexandre Courbot Cc: Shawn Guo Cc: Stefan Agner Cc: Fugang Duan Cc: Peter Chen Signed-off-by: Dong Aisheng Signed-off-by: Linus Walleij --- drivers/gpio/gpio-vf610.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 521fbe338589..cbe9e06861de 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -30,10 +30,16 @@ #define VF610_GPIO_PER_PORT 32 +struct fsl_gpio_soc_data { + /* SoCs has a Port Data Direction Register (PDDR) */ + bool have_paddr; +}; + struct vf610_gpio_port { struct gpio_chip gc; void __iomem *base; void __iomem *gpio_base; + const struct fsl_gpio_soc_data *sdata; u8 irqc[VF610_GPIO_PER_PORT]; int irq; }; @@ -43,6 +49,7 @@ struct vf610_gpio_port { #define GPIO_PCOR 0x08 #define GPIO_PTOR 0x0c #define GPIO_PDIR 0x10 +#define GPIO_PDDR 0x14 #define PORT_PCR(n) ((n) * 0x4) #define PORT_PCR_IRQC_OFFSET 16 @@ -61,8 +68,13 @@ struct vf610_gpio_port { static struct irq_chip vf610_gpio_irq_chip; +static const struct fsl_gpio_soc_data imx_data = { + .have_paddr = true, +}; + static const struct of_device_id vf610_gpio_dt_ids[] = { - { .compatible = "fsl,vf610-gpio" }, + { .compatible = "fsl,vf610-gpio", .data = NULL, }, + { .compatible = "fsl,imx7ulp-gpio", .data = &imx_data, }, { /* sentinel */ } }; @@ -79,8 +91,18 @@ static inline u32 vf610_gpio_readl(void __iomem *reg) static int vf610_gpio_get(struct gpio_chip *gc, unsigned int gpio) { struct vf610_gpio_port *port = gpiochip_get_data(gc); - - return !!(vf610_gpio_readl(port->gpio_base + GPIO_PDIR) & BIT(gpio)); + unsigned long mask = BIT(gpio); + void __iomem *addr; + + if (port->sdata && port->sdata->have_paddr) { + mask &= vf610_gpio_readl(port->gpio_base + GPIO_PDDR); + addr = mask ? port->gpio_base + GPIO_PDOR : + port->gpio_base + GPIO_PDIR; + return !!(vf610_gpio_readl(addr) & BIT(gpio)); + } else { + return !!(vf610_gpio_readl(port->gpio_base + GPIO_PDIR) + & BIT(gpio)); + } } static void vf610_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) @@ -96,12 +118,28 @@ static void vf610_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) static int vf610_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) { + struct vf610_gpio_port *port = gpiochip_get_data(chip); + unsigned long mask = BIT(gpio); + u32 val; + + if (port->sdata && port->sdata->have_paddr) { + val = vf610_gpio_readl(port->gpio_base + GPIO_PDDR); + val &= ~mask; + vf610_gpio_writel(val, port->gpio_base + GPIO_PDDR); + } + return pinctrl_gpio_direction_input(chip->base + gpio); } static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value) { + struct vf610_gpio_port *port = gpiochip_get_data(chip); + unsigned long mask = BIT(gpio); + + if (port->sdata && port->sdata->have_paddr) + vf610_gpio_writel(mask, port->gpio_base + GPIO_PDDR); + vf610_gpio_set(chip, gpio, value); return pinctrl_gpio_direction_output(chip->base + gpio); @@ -216,6 +254,8 @@ static struct irq_chip vf610_gpio_irq_chip = { static int vf610_gpio_probe(struct platform_device *pdev) { + const struct of_device_id *of_id = of_match_device(vf610_gpio_dt_ids, + &pdev->dev); struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct vf610_gpio_port *port; @@ -227,6 +267,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) if (!port) return -ENOMEM; + port->sdata = of_id->data; iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); port->base = devm_ioremap_resource(dev, iores); if (IS_ERR(port->base)) -- cgit v1.2.3-55-g7522 From 5e7a0ce7395ad65f71cfbc47d6dd6d6b329dab84 Mon Sep 17 00:00:00 2001 From: Keerthy Date: Thu, 20 Jul 2017 15:12:17 +0530 Subject: gpio: davinci: Handle the return value of davinci_gpio_irq_setup function Currently davinci_gpio_irq_setup return value is ignored. Handle the return value appropriately. Signed-off-by: Keerthy Signed-off-by: Linus Walleij --- drivers/gpio/gpio-davinci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 3fb970a74fd7..f75d8443ecaf 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -237,7 +237,10 @@ static int davinci_gpio_probe(struct platform_device *pdev) goto err; platform_set_drvdata(pdev, chips); - davinci_gpio_irq_setup(pdev); + ret = davinci_gpio_irq_setup(pdev); + if (ret) + goto err; + return 0; err: -- cgit v1.2.3-55-g7522 From 275b13a65547e2dc39c75d660d2e0f0fddde90f6 Mon Sep 17 00:00:00 2001 From: Rajmohan Mani Date: Fri, 28 Jul 2017 17:30:25 -0700 Subject: gpio: Add support for TPS68470 GPIOs This patch adds support for TPS68470 GPIOs. There are 7 GPIOs and a few sensor related GPIOs. These GPIOs can be requested and configured as appropriate. The GPIOs are also provided with descriptive names. However, the typical use case is that the OS GPIO driver will interact with TPS68470 GPIO driver to configure these GPIOs, as requested by the platform firmware. Signed-off-by: Rajmohan Mani Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 15 ++++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-tps68470.c | 176 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 192 insertions(+) create mode 100644 drivers/gpio/gpio-tps68470.c (limited to 'drivers/gpio') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 461d6fc3688b..b304579fc4cd 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1065,6 +1065,21 @@ config GPIO_TPS65912 help This driver supports TPS65912 gpio chip +config GPIO_TPS68470 + bool "TPS68470 GPIO" + depends on MFD_TPS68470 + help + Select this option to enable GPIO driver for the TPS68470 + chip family. + There are 7 GPIOs and few sensor related GPIOs supported + by the TPS68470. While the 7 GPIOs can be configured as + input or output as appropriate, the sensor related GPIOs + are "output only" GPIOs. + + This driver config is bool, as the GPIO functionality + of the TPS68470 must be available before dependent + drivers are loaded. + config GPIO_TWL4030 tristate "TWL4030, TWL5030, and TPS659x0 GPIOs" depends on TWL4030_CORE diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index a9fda6c55113..37f2029218cb 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -121,6 +121,7 @@ obj-$(CONFIG_GPIO_TPS65218) += gpio-tps65218.o obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o +obj-$(CONFIG_GPIO_TPS68470) += gpio-tps68470.o obj-$(CONFIG_GPIO_TS4800) += gpio-ts4800.o obj-$(CONFIG_GPIO_TS4900) += gpio-ts4900.o obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o diff --git a/drivers/gpio/gpio-tps68470.c b/drivers/gpio/gpio-tps68470.c new file mode 100644 index 000000000000..fa2662f8b026 --- /dev/null +++ b/drivers/gpio/gpio-tps68470.c @@ -0,0 +1,176 @@ +/* + * GPIO driver for TPS68470 PMIC + * + * Copyright (C) 2017 Intel Corporation + * + * Authors: + * Antti Laakso + * Tianshu Qiu + * Jian Xu Zheng + * Yuning Pu + * + * 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 version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#define TPS68470_N_LOGIC_OUTPUT 3 +#define TPS68470_N_REGULAR_GPIO 7 +#define TPS68470_N_GPIO (TPS68470_N_LOGIC_OUTPUT + TPS68470_N_REGULAR_GPIO) + +struct tps68470_gpio_data { + struct regmap *tps68470_regmap; + struct gpio_chip gc; +}; + +static int tps68470_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); + struct regmap *regmap = tps68470_gpio->tps68470_regmap; + unsigned int reg = TPS68470_REG_GPDO; + int val, ret; + + if (offset >= TPS68470_N_REGULAR_GPIO) { + offset -= TPS68470_N_REGULAR_GPIO; + reg = TPS68470_REG_SGPO; + } + + ret = regmap_read(regmap, reg, &val); + if (ret) { + dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n", + TPS68470_REG_SGPO); + return ret; + } + return !!(val & BIT(offset)); +} + +/* Return 0 if output, 1 if input */ +static int tps68470_gpio_get_direction(struct gpio_chip *gc, + unsigned int offset) +{ + struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); + struct regmap *regmap = tps68470_gpio->tps68470_regmap; + int val, ret; + + /* rest are always outputs */ + if (offset >= TPS68470_N_REGULAR_GPIO) + return 0; + + ret = regmap_read(regmap, TPS68470_GPIO_CTL_REG_A(offset), &val); + if (ret) { + dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n", + TPS68470_GPIO_CTL_REG_A(offset)); + return ret; + } + + val &= TPS68470_GPIO_MODE_MASK; + return val >= TPS68470_GPIO_MODE_OUT_CMOS ? 0 : 1; +} + +static void tps68470_gpio_set(struct gpio_chip *gc, unsigned int offset, + int value) +{ + struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); + struct regmap *regmap = tps68470_gpio->tps68470_regmap; + unsigned int reg = TPS68470_REG_GPDO; + + if (offset >= TPS68470_N_REGULAR_GPIO) { + reg = TPS68470_REG_SGPO; + offset -= TPS68470_N_REGULAR_GPIO; + } + + regmap_update_bits(regmap, reg, BIT(offset), value ? BIT(offset) : 0); +} + +static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset, + int value) +{ + struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); + struct regmap *regmap = tps68470_gpio->tps68470_regmap; + + /* rest are always outputs */ + if (offset >= TPS68470_N_REGULAR_GPIO) + return 0; + + /* Set the initial value */ + tps68470_gpio_set(gc, offset, value); + + return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset), + TPS68470_GPIO_MODE_MASK, + TPS68470_GPIO_MODE_OUT_CMOS); +} + +static int tps68470_gpio_input(struct gpio_chip *gc, unsigned int offset) +{ + struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); + struct regmap *regmap = tps68470_gpio->tps68470_regmap; + + /* rest are always outputs */ + if (offset >= TPS68470_N_REGULAR_GPIO) + return -EINVAL; + + return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset), + TPS68470_GPIO_MODE_MASK, 0x00); +} + +static const char *tps68470_names[TPS68470_N_GPIO] = { + "gpio.0", "gpio.1", "gpio.2", "gpio.3", + "gpio.4", "gpio.5", "gpio.6", + "s_enable", "s_idle", "s_resetn", +}; + +static int tps68470_gpio_probe(struct platform_device *pdev) +{ + struct tps68470_gpio_data *tps68470_gpio; + int ret; + + tps68470_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps68470_gpio), + GFP_KERNEL); + if (!tps68470_gpio) + return -ENOMEM; + + tps68470_gpio->tps68470_regmap = dev_get_drvdata(pdev->dev.parent); + tps68470_gpio->gc.label = "tps68470-gpio"; + tps68470_gpio->gc.owner = THIS_MODULE; + tps68470_gpio->gc.direction_input = tps68470_gpio_input; + tps68470_gpio->gc.direction_output = tps68470_gpio_output; + tps68470_gpio->gc.get = tps68470_gpio_get; + tps68470_gpio->gc.get_direction = tps68470_gpio_get_direction; + tps68470_gpio->gc.set = tps68470_gpio_set; + tps68470_gpio->gc.can_sleep = true; + tps68470_gpio->gc.names = tps68470_names; + tps68470_gpio->gc.ngpio = TPS68470_N_GPIO; + tps68470_gpio->gc.base = -1; + tps68470_gpio->gc.parent = &pdev->dev; + + ret = devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc, + tps68470_gpio); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register gpio_chip: %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, tps68470_gpio); + + return ret; +} + +static struct platform_driver tps68470_gpio_driver = { + .driver = { + .name = "tps68470-gpio", + }, + .probe = tps68470_gpio_probe, +}; + +builtin_platform_driver(tps68470_gpio_driver) -- cgit v1.2.3-55-g7522 From e11de4de28c077d31235f5afcac91d4b4b0b7a6b Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Mon, 7 Aug 2017 13:01:54 +0200 Subject: gpio: zynq: Add support for suspend resume Add support for suspend resume. Now that we can lose context across a suspend/ resume cycle. Add support for the context restore. Signed-off-by: Shubhrajyoti Datta Signed-off-by: Michal Simek Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zynq.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 3 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index df0851464006..064033803449 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -99,6 +99,17 @@ /* set to differentiate zynq from zynqmp, 0=zynqmp, 1=zynq */ #define ZYNQ_GPIO_QUIRK_IS_ZYNQ BIT(0) +struct gpio_regs { + u32 datamsw[ZYNQMP_GPIO_MAX_BANK]; + u32 datalsw[ZYNQMP_GPIO_MAX_BANK]; + u32 dirm[ZYNQMP_GPIO_MAX_BANK]; + u32 outen[ZYNQMP_GPIO_MAX_BANK]; + u32 int_en[ZYNQMP_GPIO_MAX_BANK]; + u32 int_dis[ZYNQMP_GPIO_MAX_BANK]; + u32 int_type[ZYNQMP_GPIO_MAX_BANK]; + u32 int_polarity[ZYNQMP_GPIO_MAX_BANK]; + u32 int_any[ZYNQMP_GPIO_MAX_BANK]; +}; /** * struct zynq_gpio - gpio device private data structure * @chip: instance of the gpio_chip @@ -106,6 +117,7 @@ * @clk: clock resource for this controller * @irq: interrupt for the GPIO device * @p_data: pointer to platform data + * @context: context registers */ struct zynq_gpio { struct gpio_chip chip; @@ -113,6 +125,7 @@ struct zynq_gpio { struct clk *clk; int irq; const struct zynq_platform_data *p_data; + struct gpio_regs context; }; /** @@ -560,14 +573,72 @@ static void zynq_gpio_irqhandler(struct irq_desc *desc) chained_irq_exit(irqchip, desc); } +static void zynq_gpio_save_context(struct zynq_gpio *gpio) +{ + unsigned int bank_num; + + for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) { + gpio->context.datalsw[bank_num] = + readl_relaxed(gpio->base_addr + + ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num)); + gpio->context.datamsw[bank_num] = + readl_relaxed(gpio->base_addr + + ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num)); + gpio->context.dirm[bank_num] = readl_relaxed(gpio->base_addr + + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); + gpio->context.int_en[bank_num] = readl_relaxed(gpio->base_addr + + ZYNQ_GPIO_INTMASK_OFFSET(bank_num)); + gpio->context.int_type[bank_num] = + readl_relaxed(gpio->base_addr + + ZYNQ_GPIO_INTTYPE_OFFSET(bank_num)); + gpio->context.int_polarity[bank_num] = + readl_relaxed(gpio->base_addr + + ZYNQ_GPIO_INTPOL_OFFSET(bank_num)); + gpio->context.int_any[bank_num] = + readl_relaxed(gpio->base_addr + + ZYNQ_GPIO_INTANY_OFFSET(bank_num)); + } +} + +static void zynq_gpio_restore_context(struct zynq_gpio *gpio) +{ + unsigned int bank_num; + + for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) { + writel_relaxed(gpio->context.datalsw[bank_num], + gpio->base_addr + + ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num)); + writel_relaxed(gpio->context.datamsw[bank_num], + gpio->base_addr + + ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num)); + writel_relaxed(gpio->context.dirm[bank_num], + gpio->base_addr + + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); + writel_relaxed(gpio->context.int_en[bank_num], + gpio->base_addr + + ZYNQ_GPIO_INTEN_OFFSET(bank_num)); + writel_relaxed(gpio->context.int_type[bank_num], + gpio->base_addr + + ZYNQ_GPIO_INTTYPE_OFFSET(bank_num)); + writel_relaxed(gpio->context.int_polarity[bank_num], + gpio->base_addr + + ZYNQ_GPIO_INTPOL_OFFSET(bank_num)); + writel_relaxed(gpio->context.int_any[bank_num], + gpio->base_addr + + ZYNQ_GPIO_INTANY_OFFSET(bank_num)); + } +} static int __maybe_unused zynq_gpio_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); int irq = platform_get_irq(pdev, 0); struct irq_data *data = irq_get_irq_data(irq); + struct zynq_gpio *gpio = platform_get_drvdata(pdev); - if (!irqd_is_wakeup_set(data)) + if (!irqd_is_wakeup_set(data)) { + zynq_gpio_save_context(gpio); return pm_runtime_force_suspend(dev); + } return 0; } @@ -577,9 +648,14 @@ static int __maybe_unused zynq_gpio_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); int irq = platform_get_irq(pdev, 0); struct irq_data *data = irq_get_irq_data(irq); + struct zynq_gpio *gpio = platform_get_drvdata(pdev); + int ret; - if (!irqd_is_wakeup_set(data)) - return pm_runtime_force_resume(dev); + if (!irqd_is_wakeup_set(data)) { + ret = pm_runtime_force_resume(dev); + zynq_gpio_restore_context(gpio); + return ret; + } return 0; } -- cgit v1.2.3-55-g7522 From 06aa09081d44c778309346ae8161841e0c104b7a Mon Sep 17 00:00:00 2001 From: Swapna Manupati Date: Mon, 7 Aug 2017 13:01:57 +0200 Subject: gpio: zynq: Provided workaround for GPIO This patch provides workaround in the gpio driver for Zynq and ZynqMP Platforms by reading pin value of EMIO banks through DATA register as it was unable to read the value of it from DATA_RO register. Signed-off-by: Swapna Manupati Signed-off-by: Michal Simek Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zynq.c | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 064033803449..a9ffe2d94c81 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -67,6 +67,7 @@ /* MSW Mask & Data -WO */ #define ZYNQ_GPIO_DATA_MSW_OFFSET(BANK) (0x004 + (8 * BANK)) /* Data Register-RW */ +#define ZYNQ_GPIO_DATA_OFFSET(BANK) (0x040 + (4 * BANK)) #define ZYNQ_GPIO_DATA_RO_OFFSET(BANK) (0x060 + (4 * BANK)) /* Direction mode reg-RW */ #define ZYNQ_GPIO_DIRM_OFFSET(BANK) (0x204 + (0x40 * BANK)) @@ -98,6 +99,7 @@ /* set to differentiate zynq from zynqmp, 0=zynqmp, 1=zynq */ #define ZYNQ_GPIO_QUIRK_IS_ZYNQ BIT(0) +#define GPIO_QUIRK_DATA_RO_BUG BIT(1) struct gpio_regs { u32 datamsw[ZYNQMP_GPIO_MAX_BANK]; @@ -159,6 +161,17 @@ static int zynq_gpio_is_zynq(struct zynq_gpio *gpio) return !!(gpio->p_data->quirks & ZYNQ_GPIO_QUIRK_IS_ZYNQ); } +/** + * gpio_data_ro_bug - test if HW bug exists or not + * @gpio: Pointer to driver data struct + * + * Return: 0 if bug doesnot exist, 1 if bug exists. + */ +static int gpio_data_ro_bug(struct zynq_gpio *gpio) +{ + return !!(gpio->p_data->quirks & GPIO_QUIRK_DATA_RO_BUG); +} + /** * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank * for a given pin in the GPIO device @@ -210,9 +223,28 @@ static int zynq_gpio_get_value(struct gpio_chip *chip, unsigned int pin) zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio); - data = readl_relaxed(gpio->base_addr + - ZYNQ_GPIO_DATA_RO_OFFSET(bank_num)); - + if (gpio_data_ro_bug(gpio)) { + if (zynq_gpio_is_zynq(gpio)) { + if (bank_num <= 1) { + data = readl_relaxed(gpio->base_addr + + ZYNQ_GPIO_DATA_RO_OFFSET(bank_num)); + } else { + data = readl_relaxed(gpio->base_addr + + ZYNQ_GPIO_DATA_OFFSET(bank_num)); + } + } else { + if (bank_num <= 2) { + data = readl_relaxed(gpio->base_addr + + ZYNQ_GPIO_DATA_RO_OFFSET(bank_num)); + } else { + data = readl_relaxed(gpio->base_addr + + ZYNQ_GPIO_DATA_OFFSET(bank_num)); + } + } + } else { + data = readl_relaxed(gpio->base_addr + + ZYNQ_GPIO_DATA_RO_OFFSET(bank_num)); + } return (data >> bank_pin_num) & 1; } @@ -704,6 +736,7 @@ static const struct dev_pm_ops zynq_gpio_dev_pm_ops = { static const struct zynq_platform_data zynqmp_gpio_def = { .label = "zynqmp_gpio", + .quirks = GPIO_QUIRK_DATA_RO_BUG, .ngpio = ZYNQMP_GPIO_NR_GPIOS, .max_bank = ZYNQMP_GPIO_MAX_BANK, .bank_min[0] = ZYNQ_GPIO_BANK0_PIN_MIN(MP), @@ -722,7 +755,7 @@ static const struct zynq_platform_data zynqmp_gpio_def = { static const struct zynq_platform_data zynq_gpio_def = { .label = "zynq_gpio", - .quirks = ZYNQ_GPIO_QUIRK_IS_ZYNQ, + .quirks = ZYNQ_GPIO_QUIRK_IS_ZYNQ | GPIO_QUIRK_DATA_RO_BUG, .ngpio = ZYNQ_GPIO_NR_GPIOS, .max_bank = ZYNQ_GPIO_MAX_BANK, .bank_min[0] = ZYNQ_GPIO_BANK0_PIN_MIN(), -- cgit v1.2.3-55-g7522 From 6ae5104cbaa5326a00287abd141af6a2307a6f70 Mon Sep 17 00:00:00 2001 From: Nava kishore Manne Date: Mon, 7 Aug 2017 13:01:58 +0200 Subject: gpio: zynq: Fix kernel doc warnings This patch fixes the kernel doc warnings in the driver. Signed-off-by: Nava kishore Manne Signed-off-by: Michal Simek Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zynq.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index a9ffe2d94c81..1ac640eccb9f 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -133,11 +133,12 @@ struct zynq_gpio { /** * struct zynq_platform_data - zynq gpio platform data structure * @label: string to store in gpio->label + * @quirks: Flags is used to identify the platform * @ngpio: max number of gpio pins * @max_bank: maximum number of gpio banks * @bank_min: this array represents bank's min pin * @bank_max: this array represents bank's max pin -*/ + */ struct zynq_platform_data { const char *label; u32 quirks; @@ -180,6 +181,7 @@ static int gpio_data_ro_bug(struct zynq_gpio *gpio) * pin * @bank_pin_num: an output parameter used to return pin number within a bank * for the given gpio pin + * @gpio: gpio device data structure * * Returns the bank number and pin offset within the bank. */ @@ -575,7 +577,6 @@ static void zynq_gpio_handle_bank_irq(struct zynq_gpio *gpio, /** * zynq_gpio_irqhandler - IRQ handler for the gpio banks of a gpio device - * @irq: irq number of the gpio bank where interrupt has occurred * @desc: irq descriptor instance of the 'irq' * * This function reads the Interrupt Status Register of each bank to get the -- cgit v1.2.3-55-g7522 From eb73d6eaa630d086b5c78c840bd0dcaf35a618db Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 7 Aug 2017 13:01:59 +0200 Subject: gpio: zynq: Fix empty lines in driver Remove one additional line and add two new. All are reported by checkpatch. Signed-off-by: Michal Simek Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zynq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 1ac640eccb9f..0129f82886eb 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -60,7 +60,6 @@ #define ZYNQ_GPIO_BANK5_PIN_MAX(str) (ZYNQ_GPIO_BANK5_PIN_MIN(str) + \ ZYNQ##str##_GPIO_BANK5_NGPIO - 1) - /* Register offsets for the GPIO device */ /* LSW Mask & Data -WO */ #define ZYNQ_GPIO_DATA_LSW_OFFSET(BANK) (0x000 + (8 * BANK)) @@ -112,6 +111,7 @@ struct gpio_regs { u32 int_polarity[ZYNQMP_GPIO_MAX_BANK]; u32 int_any[ZYNQMP_GPIO_MAX_BANK]; }; + /** * struct zynq_gpio - gpio device private data structure * @chip: instance of the gpio_chip @@ -661,6 +661,7 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio) ZYNQ_GPIO_INTANY_OFFSET(bank_num)); } } + static int __maybe_unused zynq_gpio_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); -- cgit v1.2.3-55-g7522 From 2717cfcaf564913c0f46dd19734a9dca6563c5e7 Mon Sep 17 00:00:00 2001 From: Nava kishore Manne Date: Mon, 7 Aug 2017 13:02:00 +0200 Subject: gpio: zynq: Fix warnings in the driver This patch fixes the below warning -->Block comments should align the * on each line. -->suspect code indent for conditional statements. -->Prefer 'unsigned int' to bare use of 'unsigned' Signed-off-by: Nava kishore Manne Signed-off-by: Michal Simek Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zynq.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 0129f82886eb..3120d0cacf42 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -195,10 +195,10 @@ static inline void zynq_gpio_get_bank_pin(unsigned int pin_num, for (bank = 0; bank < gpio->p_data->max_bank; bank++) { if ((pin_num >= gpio->p_data->bank_min[bank]) && (pin_num <= gpio->p_data->bank_max[bank])) { - *bank_num = bank; - *bank_pin_num = pin_num - - gpio->p_data->bank_min[bank]; - return; + *bank_num = bank; + *bank_pin_num = pin_num - + gpio->p_data->bank_min[bank]; + return; } } @@ -712,7 +712,7 @@ static int __maybe_unused zynq_gpio_runtime_resume(struct device *dev) return clk_prepare_enable(gpio->clk); } -static int zynq_gpio_request(struct gpio_chip *chip, unsigned offset) +static int zynq_gpio_request(struct gpio_chip *chip, unsigned int offset) { int ret; @@ -725,7 +725,7 @@ static int zynq_gpio_request(struct gpio_chip *chip, unsigned offset) return ret < 0 ? ret : 0; } -static void zynq_gpio_free(struct gpio_chip *chip, unsigned offset) +static void zynq_gpio_free(struct gpio_chip *chip, unsigned int offset) { pm_runtime_put(chip->parent); } -- cgit v1.2.3-55-g7522 From 16ee62e560bcd194c360d943aeceeb73820fcaa5 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 7 Aug 2017 13:02:01 +0200 Subject: gpio: zynq: Fix driver function parameters alignment Fix function parameters alignment reported by checkpatch. Signed-off-by: Michal Simek Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zynq.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 3120d0cacf42..b3cc948a2d8b 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -194,7 +194,7 @@ static inline void zynq_gpio_get_bank_pin(unsigned int pin_num, for (bank = 0; bank < gpio->p_data->max_bank; bank++) { if ((pin_num >= gpio->p_data->bank_min[bank]) && - (pin_num <= gpio->p_data->bank_max[bank])) { + (pin_num <= gpio->p_data->bank_max[bank])) { *bank_num = bank; *bank_pin_num = pin_num - gpio->p_data->bank_min[bank]; @@ -310,7 +310,7 @@ static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin) * as inputs. */ if (zynq_gpio_is_zynq(gpio) && bank_num == 0 && - (bank_pin_num == 7 || bank_pin_num == 8)) + (bank_pin_num == 7 || bank_pin_num == 8)) return -EINVAL; /* clear the bit in direction mode reg to set the pin as input */ @@ -511,13 +511,14 @@ static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type) writel_relaxed(int_any, gpio->base_addr + ZYNQ_GPIO_INTANY_OFFSET(bank_num)); - if (type & IRQ_TYPE_LEVEL_MASK) { + if (type & IRQ_TYPE_LEVEL_MASK) irq_set_chip_handler_name_locked(irq_data, - &zynq_gpio_level_irqchip, handle_fasteoi_irq, NULL); - } else { + &zynq_gpio_level_irqchip, + handle_fasteoi_irq, NULL); + else irq_set_chip_handler_name_locked(irq_data, - &zynq_gpio_edge_irqchip, handle_level_irq, NULL); - } + &zynq_gpio_edge_irqchip, + handle_level_irq, NULL); return 0; } @@ -733,7 +734,7 @@ static void zynq_gpio_free(struct gpio_chip *chip, unsigned int offset) static const struct dev_pm_ops zynq_gpio_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(zynq_gpio_suspend, zynq_gpio_resume) SET_RUNTIME_PM_OPS(zynq_gpio_runtime_suspend, - zynq_gpio_runtime_resume, NULL) + zynq_gpio_runtime_resume, NULL) }; static const struct zynq_platform_data zynqmp_gpio_def = { -- cgit v1.2.3-55-g7522 From ee949b51e4165107fe4d9ed18c23829119078722 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 12 Aug 2017 11:39:09 +0530 Subject: gpio: max77620: Make regmap_irq_chip const Make the structure const as it is only passed to the function devm_regmap_add_irq_chip having the corresponding argument as const. Done using Coccinelle. Signed-off-by: Bhumika Goyal Signed-off-by: Linus Walleij --- drivers/gpio/gpio-max77620.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-max77620.c b/drivers/gpio/gpio-max77620.c index 743459d9477d..538bce4b5b42 100644 --- a/drivers/gpio/gpio-max77620.c +++ b/drivers/gpio/gpio-max77620.c @@ -82,7 +82,7 @@ static const struct regmap_irq max77620_gpio_irqs[] = { }, }; -static struct regmap_irq_chip max77620_gpio_irq_chip = { +static const struct regmap_irq_chip max77620_gpio_irq_chip = { .name = "max77620-gpio", .irqs = max77620_gpio_irqs, .num_irqs = ARRAY_SIZE(max77620_gpio_irqs), -- cgit v1.2.3-55-g7522 From 7ebc194d0fd4bb0fc8c7aca4b500b5b24e733267 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 7 Aug 2017 09:41:50 -0300 Subject: gpio: 74x164: Introduce 'enable-gpios' property 74HC595 has an /OE (output enable) pin that can be controlled by a GPIO. Introduce an optional property called 'enable-gpios' that allows controlling the /OE pin. Signed-off-by: Fabio Estevam Acked-by: Rob Herring Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/gpio/gpio-74x164.txt | 3 +++ drivers/gpio/gpio-74x164.c | 10 ++++++++++ 2 files changed, 13 insertions(+) (limited to 'drivers/gpio') diff --git a/Documentation/devicetree/bindings/gpio/gpio-74x164.txt b/Documentation/devicetree/bindings/gpio/gpio-74x164.txt index ce1b2231bf5d..2a97553d8d76 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-74x164.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-74x164.txt @@ -12,6 +12,9 @@ Required properties: 1 = active low - registers-number: Number of daisy-chained shift registers +Optional properties: +- enable-gpios: GPIO connected to the OE (Output Enable) pin. + Example: gpio5: gpio5@0 { diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index a6607faf2fdf..6b535ec858cc 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -9,6 +9,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include @@ -31,6 +32,7 @@ struct gen_74x164_chip { * numbering, store the bytes in reverse order. */ u8 buffer[0]; + struct gpio_desc *gpiod_oe; }; static int __gen_74x164_write_config(struct gen_74x164_chip *chip) @@ -126,6 +128,13 @@ static int gen_74x164_probe(struct spi_device *spi) if (!chip) return -ENOMEM; + chip->gpiod_oe = devm_gpiod_get_optional(&spi->dev, "enable", + GPIOD_OUT_LOW); + if (IS_ERR(chip->gpiod_oe)) + return PTR_ERR(chip->gpiod_oe); + + gpiod_set_value_cansleep(chip->gpiod_oe, 1); + spi_set_drvdata(spi, chip); chip->gpio_chip.label = spi->modalias; @@ -164,6 +173,7 @@ static int gen_74x164_remove(struct spi_device *spi) { struct gen_74x164_chip *chip = spi_get_drvdata(spi); + gpiod_set_value_cansleep(chip->gpiod_oe, 0); gpiochip_remove(&chip->gpio_chip); mutex_destroy(&chip->lock); -- cgit v1.2.3-55-g7522 From 754c04582a98fa2a24ff1b4c4b88964b114eb526 Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Tue, 8 Aug 2017 15:37:36 +0930 Subject: gpio: aspeed: Remove reference to clock name in debounce warning message HPLL is in fact not the clock we need. Remove the description of which clock we failed to find a phandle to in order to avoid any further error. Signed-off-by: Andrew Jeffery Acked-by: Joel Stanley Signed-off-by: Linus Walleij --- drivers/gpio/gpio-aspeed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index 4ca436e66bdb..bfc53995064a 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -834,7 +834,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) gpio->clk = of_clk_get(pdev->dev.of_node, 0); if (IS_ERR(gpio->clk)) { dev_warn(&pdev->dev, - "No HPLL clock phandle provided, debouncing disabled\n"); + "Failed to get clock from devicetree, debouncing disabled\n"); gpio->clk = NULL; } -- cgit v1.2.3-55-g7522 From 90e1fc4c4ccfaefe8a2cbd6e7cfff5a77ef35437 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 9 Aug 2017 14:25:00 +0200 Subject: gpio: mxc: disallow unbinding the driver This driver is non-modular so explicitly disallow a driver unbind. Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 3dcd990f416e..619fe7ad3cec 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -508,6 +508,7 @@ static struct platform_driver mxc_gpio_driver = { .driver = { .name = "gpio-mxc", .of_match_table = mxc_gpio_dt_ids, + .suppress_bind_attrs = true, }, .probe = mxc_gpio_probe, .id_table = mxc_gpio_devtype, -- cgit v1.2.3-55-g7522 From 60909ec93b77849b4110480a5e629bbb8e98b993 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 9 Aug 2017 14:25:01 +0200 Subject: gpio: mxs: disallow unbinding the driver This driver is non-modular so explicitly disallow a driver unbind. Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 6ae583f36733..159927876577 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -379,6 +379,7 @@ static struct platform_driver mxs_gpio_driver = { .driver = { .name = "gpio-mxs", .of_match_table = mxs_gpio_dt_ids, + .suppress_bind_attrs = true, }, .probe = mxs_gpio_probe, .id_table = mxs_gpio_ids, -- cgit v1.2.3-55-g7522 From a6f5f1b95602f8173a3270d32ec0ee17c526ecce Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 9 Aug 2017 14:25:02 +0200 Subject: gpio: sta2x11: disallow unbinding the driver This driver is non-modular so explicitly disallow a driver unbind. Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sta2x11.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c index 9e705162da8d..56beb31c03db 100644 --- a/drivers/gpio/gpio-sta2x11.c +++ b/drivers/gpio/gpio-sta2x11.c @@ -432,6 +432,7 @@ static int gsta_probe(struct platform_device *dev) static struct platform_driver sta2x11_gpio_platform_driver = { .driver = { .name = "sta2x11-gpio", + .suppress_bind_attrs = true, }, .probe = gsta_probe, }; -- cgit v1.2.3-55-g7522 From 624b5a9c0bb4ba86d36ff989d0a09e2215637cbc Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 9 Aug 2017 14:25:03 +0200 Subject: gpio: sta2x11: use devres for irq generic chip Use resource managed variants of irq_alloc_generic_chip() and irq_setup_generic_chip(). Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sta2x11.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c index 56beb31c03db..407359da08f9 100644 --- a/drivers/gpio/gpio-sta2x11.c +++ b/drivers/gpio/gpio-sta2x11.c @@ -324,9 +324,11 @@ static int gsta_alloc_irq_chip(struct gsta_gpio *chip) { struct irq_chip_generic *gc; struct irq_chip_type *ct; + int rv; - gc = irq_alloc_generic_chip(KBUILD_MODNAME, 1, chip->irq_base, - chip->reg_base, handle_simple_irq); + gc = devm_irq_alloc_generic_chip(chip->dev, KBUILD_MODNAME, 1, + chip->irq_base, + chip->reg_base, handle_simple_irq); if (!gc) return -ENOMEM; @@ -338,8 +340,11 @@ static int gsta_alloc_irq_chip(struct gsta_gpio *chip) ct->chip.irq_enable = gsta_irq_enable; /* FIXME: this makes at most 32 interrupts. Request 0 by now */ - irq_setup_generic_chip(gc, 0 /* IRQ_MSK(GSTA_GPIO_PER_BLOCK) */, 0, - IRQ_NOREQUEST | IRQ_NOPROBE, 0); + rv = devm_irq_setup_generic_chip(chip->dev, gc, + 0 /* IRQ_MSK(GSTA_GPIO_PER_BLOCK) */, + 0, IRQ_NOREQUEST | IRQ_NOPROBE, 0); + if (rv) + return rv; /* Set up all all 128 interrupts: code from setup_generic_chip */ { -- cgit v1.2.3-55-g7522 From 469d59430f15e1649771ba0e816dd6c9afb39fcc Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 9 Aug 2017 14:25:04 +0200 Subject: gpio: ml-ioh: use devres for irq generic chip Use resource managed variants of irq_alloc_generic_chip() and irq_setup_generic_chip(). Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ml-ioh.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 74fdce096c26..4b80e996d976 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -391,9 +391,10 @@ static int ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip, { struct irq_chip_generic *gc; struct irq_chip_type *ct; + int rv; - gc = irq_alloc_generic_chip("ioh_gpio", 1, irq_start, chip->base, - handle_simple_irq); + gc = devm_irq_alloc_generic_chip(chip->dev, "ioh_gpio", 1, irq_start, + chip->base, handle_simple_irq); if (!gc) return -ENOMEM; @@ -406,10 +407,11 @@ static int ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip, ct->chip.irq_disable = ioh_irq_disable; ct->chip.irq_enable = ioh_irq_enable; - irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, - IRQ_NOREQUEST | IRQ_NOPROBE, 0); + rv = devm_irq_setup_generic_chip(chip->dev, gc, IRQ_MSK(num), + IRQ_GC_INIT_MASK_CACHE, + IRQ_NOREQUEST | IRQ_NOPROBE, 0); - return 0; + return rv; } static int ioh_gpio_probe(struct pci_dev *pdev, -- cgit v1.2.3-55-g7522 From e0fc5a1b8ea3040936a89ae2b85321e06a78b3af Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 9 Aug 2017 14:25:05 +0200 Subject: gpio: pch: use devres for irq generic chip Use resource managed variants of irq_alloc_generic_chip() and irq_setup_generic_chip(). Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pch.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index f6600f8ada52..68c6d0c5a6d1 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -337,9 +337,10 @@ static int pch_gpio_alloc_generic_chip(struct pch_gpio *chip, { struct irq_chip_generic *gc; struct irq_chip_type *ct; + int rv; - gc = irq_alloc_generic_chip("pch_gpio", 1, irq_start, chip->base, - handle_simple_irq); + gc = devm_irq_alloc_generic_chip(chip->dev, "pch_gpio", 1, irq_start, + chip->base, handle_simple_irq); if (!gc) return -ENOMEM; @@ -351,10 +352,11 @@ static int pch_gpio_alloc_generic_chip(struct pch_gpio *chip, ct->chip.irq_unmask = pch_irq_unmask; ct->chip.irq_set_type = pch_irq_type; - irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, - IRQ_NOREQUEST | IRQ_NOPROBE, 0); + rv = devm_irq_setup_generic_chip(chip->dev, gc, IRQ_MSK(num), + IRQ_GC_INIT_MASK_CACHE, + IRQ_NOREQUEST | IRQ_NOPROBE, 0); - return 0; + return rv; } static int pch_gpio_probe(struct pci_dev *pdev, -- cgit v1.2.3-55-g7522 From db5270acaae5b6d63ce1a6f053aeabc7a9c939bb Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 9 Aug 2017 14:25:06 +0200 Subject: gpio: mxc: use devres for irq generic chip Use resource managed variants of irq_alloc_generic_chip() and irq_setup_generic_chip(). Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxc.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 619fe7ad3cec..5245a2fe62ae 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -66,6 +66,7 @@ struct mxc_gpio_port { int irq_high; struct irq_domain *domain; struct gpio_chip gc; + struct device *dev; u32 both_edges; }; @@ -345,9 +346,10 @@ static int mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base) { struct irq_chip_generic *gc; struct irq_chip_type *ct; + int rv; - gc = irq_alloc_generic_chip("gpio-mxc", 1, irq_base, - port->base, handle_level_irq); + gc = devm_irq_alloc_generic_chip(port->dev, "gpio-mxc", 1, irq_base, + port->base, handle_level_irq); if (!gc) return -ENOMEM; gc->private = port; @@ -362,10 +364,11 @@ static int mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base) ct->regs.ack = GPIO_ISR; ct->regs.mask = GPIO_IMR; - irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK, - IRQ_NOREQUEST, 0); + rv = devm_irq_setup_generic_chip(port->dev, gc, IRQ_MSK(32), + IRQ_GC_INIT_NESTED_LOCK, + IRQ_NOREQUEST, 0); - return 0; + return rv; } static void mxc_gpio_get_hw(struct platform_device *pdev) @@ -419,6 +422,8 @@ static int mxc_gpio_probe(struct platform_device *pdev) if (!port) return -ENOMEM; + port->dev = &pdev->dev; + iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); port->base = devm_ioremap_resource(&pdev->dev, iores); if (IS_ERR(port->base)) -- cgit v1.2.3-55-g7522 From 5751d3dcf43e24aeca3337b09387e7e7a92e8ba4 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 9 Aug 2017 14:25:07 +0200 Subject: gpio: mxs: use devres for irq generic chip Use resource managed variants of irq_alloc_generic_chip() and irq_setup_generic_chip(). Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxs.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 159927876577..435def22445d 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -66,6 +66,7 @@ struct mxs_gpio_port { int irq; struct irq_domain *domain; struct gpio_chip gc; + struct device *dev; enum mxs_gpio_id devid; u32 both_edges; }; @@ -209,9 +210,10 @@ static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base) { struct irq_chip_generic *gc; struct irq_chip_type *ct; + int rv; - gc = irq_alloc_generic_chip("gpio-mxs", 2, irq_base, - port->base, handle_level_irq); + gc = devm_irq_alloc_generic_chip(port->dev, "gpio-mxs", 2, irq_base, + port->base, handle_level_irq); if (!gc) return -ENOMEM; @@ -242,10 +244,11 @@ static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base) ct->regs.disable = PINCTRL_IRQEN(port) + MXS_CLR; ct->handler = handle_level_irq; - irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK, - IRQ_NOREQUEST, 0); + rv = devm_irq_setup_generic_chip(port->dev, gc, IRQ_MSK(32), + IRQ_GC_INIT_NESTED_LOCK, + IRQ_NOREQUEST, 0); - return 0; + return rv; } static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) @@ -304,6 +307,7 @@ static int mxs_gpio_probe(struct platform_device *pdev) if (port->id < 0) return port->id; port->devid = (enum mxs_gpio_id) of_id->data; + port->dev = &pdev->dev; port->irq = platform_get_irq(pdev, 0); if (port->irq < 0) return port->irq; -- cgit v1.2.3-55-g7522 From b4c495f03ae3d332e3304eb62b4748b31f1170dd Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 14 Aug 2017 13:20:56 +0200 Subject: gpio: mockup: use irq_sim Shrink the driver by removing the code dealing with dummy interrupts and replacing it with calls to the irq_sim API. Signed-off-by: Bartosz Golaszewski Acked-by: Jonathan Cameron Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-mockup.c | 77 +++++----------------------------------------- 2 files changed, 8 insertions(+), 71 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b304579fc4cd..fc9b75c9e3ba 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -311,7 +311,7 @@ config GPIO_MOCKUP depends on GPIOLIB && SYSFS select GPIO_SYSFS select GPIOLIB_IRQCHIP - select IRQ_WORK + select IRQ_SIM help This enables GPIO Testing driver, which provides a way to test GPIO subsystem through sysfs(or char device) and debugfs. GPIO_SYSFS diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index a6565e128f9e..6db7163e6d98 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include @@ -47,18 +47,12 @@ enum { struct gpio_mockup_line_status { int dir; bool value; - bool irq_enabled; -}; - -struct gpio_mockup_irq_context { - struct irq_work work; - int irq; }; struct gpio_mockup_chip { struct gpio_chip gc; struct gpio_mockup_line_status *lines; - struct gpio_mockup_irq_context irq_ctx; + struct irq_sim irqsim; struct dentry *dbg_dir; }; @@ -144,65 +138,11 @@ static int gpio_mockup_name_lines(struct device *dev, return 0; } -static int gpio_mockup_to_irq(struct gpio_chip *chip, unsigned int offset) -{ - return chip->irq_base + offset; -} - -static void gpio_mockup_irqmask(struct irq_data *data) +static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset) { - struct gpio_chip *gc = irq_data_get_irq_chip_data(data); struct gpio_mockup_chip *chip = gpiochip_get_data(gc); - chip->lines[data->irq - gc->irq_base].irq_enabled = false; -} - -static void gpio_mockup_irqunmask(struct irq_data *data) -{ - struct gpio_chip *gc = irq_data_get_irq_chip_data(data); - struct gpio_mockup_chip *chip = gpiochip_get_data(gc); - - chip->lines[data->irq - gc->irq_base].irq_enabled = true; -} - -static struct irq_chip gpio_mockup_irqchip = { - .name = GPIO_MOCKUP_NAME, - .irq_mask = gpio_mockup_irqmask, - .irq_unmask = gpio_mockup_irqunmask, -}; - -static void gpio_mockup_handle_irq(struct irq_work *work) -{ - struct gpio_mockup_irq_context *irq_ctx; - - irq_ctx = container_of(work, struct gpio_mockup_irq_context, work); - handle_simple_irq(irq_to_desc(irq_ctx->irq)); -} - -static int gpio_mockup_irqchip_setup(struct device *dev, - struct gpio_mockup_chip *chip) -{ - struct gpio_chip *gc = &chip->gc; - int irq_base, i; - - irq_base = devm_irq_alloc_descs(dev, -1, 0, gc->ngpio, 0); - if (irq_base < 0) - return irq_base; - - gc->irq_base = irq_base; - gc->irqchip = &gpio_mockup_irqchip; - - for (i = 0; i < gc->ngpio; i++) { - irq_set_chip(irq_base + i, gc->irqchip); - irq_set_chip_data(irq_base + i, gc); - irq_set_handler(irq_base + i, &handle_simple_irq); - irq_modify_status(irq_base + i, - IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE); - } - - init_irq_work(&chip->irq_ctx.work, gpio_mockup_handle_irq); - - return 0; + return irq_sim_irqnum(&chip->irqsim, offset); } static ssize_t gpio_mockup_event_write(struct file *file, @@ -228,11 +168,8 @@ static ssize_t gpio_mockup_event_write(struct file *file, chip = priv->chip; gc = &chip->gc; - if (chip->lines[priv->offset].irq_enabled) { - gpiod_set_value_cansleep(desc, val); - priv->chip->irq_ctx.irq = gc->irq_base + priv->offset; - irq_work_queue(&priv->chip->irq_ctx.work); - } + gpiod_set_value_cansleep(desc, val); + irq_sim_fire(&chip->irqsim, priv->offset); return size; } @@ -319,7 +256,7 @@ static int gpio_mockup_add(struct device *dev, return ret; } - ret = gpio_mockup_irqchip_setup(dev, chip); + ret = devm_irq_sim_init(dev, &chip->irqsim, gc->ngpio); if (ret) return ret; -- cgit v1.2.3-55-g7522 From 5a2a30024d8c04cf638be05508e655b66f1c6103 Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 17 Aug 2017 17:53:35 -0700 Subject: gpio: Add gpio driver support for ThunderX and OCTEON-TX Cavium ThunderX and OCTEON-TX are arm64 based SoCs. Add driver for the on-chip GPIO pins. Signed-off-by: David Daney Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 9 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-thunderx.c | 639 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 649 insertions(+) create mode 100644 drivers/gpio/gpio-thunderx.c (limited to 'drivers/gpio') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index fc9b75c9e3ba..3388d54ba114 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -450,6 +450,15 @@ config GPIO_TS4800 help This driver support TS-4800 FPGA GPIO controllers. +config GPIO_THUNDERX + tristate "Cavium ThunderX/OCTEON-TX GPIO" + depends on ARCH_THUNDER || (64BIT && COMPILE_TEST) + depends on PCI_MSI && IRQ_DOMAIN_HIERARCHY + select IRQ_FASTEOI_HIERARCHY_HANDLERS + help + Say yes here to support the on-chip GPIO lines on the ThunderX + and OCTEON-TX families of SoCs. + config GPIO_TZ1090 bool "Toumaz Xenif TZ1090 GPIO support" depends on SOC_TZ1090 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 37f2029218cb..aeb70e9de6f2 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -113,6 +113,7 @@ obj-$(CONFIG_GPIO_SYSCON) += gpio-syscon.o obj-$(CONFIG_GPIO_TB10X) += gpio-tb10x.o obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o obj-$(CONFIG_GPIO_TEGRA) += gpio-tegra.o +obj-$(CONFIG_GPIO_THUNDERX) += gpio-thunderx.o obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o obj-$(CONFIG_GPIO_TPIC2810) += gpio-tpic2810.o diff --git a/drivers/gpio/gpio-thunderx.c b/drivers/gpio/gpio-thunderx.c new file mode 100644 index 000000000000..57efb251f9c4 --- /dev/null +++ b/drivers/gpio/gpio-thunderx.c @@ -0,0 +1,639 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2016, 2017 Cavium Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define GPIO_RX_DAT 0x0 +#define GPIO_TX_SET 0x8 +#define GPIO_TX_CLR 0x10 +#define GPIO_CONST 0x90 +#define GPIO_CONST_GPIOS_MASK 0xff +#define GPIO_BIT_CFG 0x400 +#define GPIO_BIT_CFG_TX_OE BIT(0) +#define GPIO_BIT_CFG_PIN_XOR BIT(1) +#define GPIO_BIT_CFG_INT_EN BIT(2) +#define GPIO_BIT_CFG_INT_TYPE BIT(3) +#define GPIO_BIT_CFG_FIL_MASK GENMASK(11, 4) +#define GPIO_BIT_CFG_FIL_CNT_SHIFT 4 +#define GPIO_BIT_CFG_FIL_SEL_SHIFT 8 +#define GPIO_BIT_CFG_TX_OD BIT(12) +#define GPIO_BIT_CFG_PIN_SEL_MASK GENMASK(25, 16) +#define GPIO_INTR 0x800 +#define GPIO_INTR_INTR BIT(0) +#define GPIO_INTR_INTR_W1S BIT(1) +#define GPIO_INTR_ENA_W1C BIT(2) +#define GPIO_INTR_ENA_W1S BIT(3) +#define GPIO_2ND_BANK 0x1400 + +#define GLITCH_FILTER_400NS ((4u << GPIO_BIT_CFG_FIL_SEL_SHIFT) | \ + (9u << GPIO_BIT_CFG_FIL_CNT_SHIFT)) + +struct thunderx_gpio; + +struct thunderx_line { + struct thunderx_gpio *txgpio; + unsigned int line; + unsigned int fil_bits; +}; + +struct thunderx_gpio { + struct gpio_chip chip; + u8 __iomem *register_base; + struct irq_domain *irqd; + struct msix_entry *msix_entries; /* per line MSI-X */ + struct thunderx_line *line_entries; /* per line irq info */ + raw_spinlock_t lock; + unsigned long invert_mask[2]; + unsigned long od_mask[2]; + int base_msi; +}; + +static unsigned int bit_cfg_reg(unsigned int line) +{ + return 8 * line + GPIO_BIT_CFG; +} + +static unsigned int intr_reg(unsigned int line) +{ + return 8 * line + GPIO_INTR; +} + +static bool thunderx_gpio_is_gpio_nowarn(struct thunderx_gpio *txgpio, + unsigned int line) +{ + u64 bit_cfg = readq(txgpio->register_base + bit_cfg_reg(line)); + + return (bit_cfg & GPIO_BIT_CFG_PIN_SEL_MASK) == 0; +} + +/* + * Check (and WARN) that the pin is available for GPIO. We will not + * allow modification of the state of non-GPIO pins from this driver. + */ +static bool thunderx_gpio_is_gpio(struct thunderx_gpio *txgpio, + unsigned int line) +{ + bool rv = thunderx_gpio_is_gpio_nowarn(txgpio, line); + + WARN_RATELIMIT(!rv, "Pin %d not available for GPIO\n", line); + + return rv; +} + +static int thunderx_gpio_request(struct gpio_chip *chip, unsigned int line) +{ + struct thunderx_gpio *txgpio = gpiochip_get_data(chip); + + return thunderx_gpio_is_gpio(txgpio, line) ? 0 : -EIO; +} + +static int thunderx_gpio_dir_in(struct gpio_chip *chip, unsigned int line) +{ + struct thunderx_gpio *txgpio = gpiochip_get_data(chip); + + if (!thunderx_gpio_is_gpio(txgpio, line)) + return -EIO; + + raw_spin_lock(&txgpio->lock); + clear_bit(line, txgpio->invert_mask); + clear_bit(line, txgpio->od_mask); + writeq(txgpio->line_entries[line].fil_bits, + txgpio->register_base + bit_cfg_reg(line)); + raw_spin_unlock(&txgpio->lock); + return 0; +} + +static void thunderx_gpio_set(struct gpio_chip *chip, unsigned int line, + int value) +{ + struct thunderx_gpio *txgpio = gpiochip_get_data(chip); + int bank = line / 64; + int bank_bit = line % 64; + + void __iomem *reg = txgpio->register_base + + (bank * GPIO_2ND_BANK) + (value ? GPIO_TX_SET : GPIO_TX_CLR); + + writeq(BIT_ULL(bank_bit), reg); +} + +static int thunderx_gpio_dir_out(struct gpio_chip *chip, unsigned int line, + int value) +{ + struct thunderx_gpio *txgpio = gpiochip_get_data(chip); + u64 bit_cfg = txgpio->line_entries[line].fil_bits | GPIO_BIT_CFG_TX_OE; + + if (!thunderx_gpio_is_gpio(txgpio, line)) + return -EIO; + + raw_spin_lock(&txgpio->lock); + + thunderx_gpio_set(chip, line, value); + + if (test_bit(line, txgpio->invert_mask)) + bit_cfg |= GPIO_BIT_CFG_PIN_XOR; + + if (test_bit(line, txgpio->od_mask)) + bit_cfg |= GPIO_BIT_CFG_TX_OD; + + writeq(bit_cfg, txgpio->register_base + bit_cfg_reg(line)); + + raw_spin_unlock(&txgpio->lock); + return 0; +} + +static int thunderx_gpio_get_direction(struct gpio_chip *chip, unsigned int line) +{ + struct thunderx_gpio *txgpio = gpiochip_get_data(chip); + u64 bit_cfg; + + if (!thunderx_gpio_is_gpio_nowarn(txgpio, line)) + /* + * Say it is input for now to avoid WARNing on + * gpiochip_add_data(). We will WARN if someone + * requests it or tries to use it. + */ + return 1; + + bit_cfg = readq(txgpio->register_base + bit_cfg_reg(line)); + + return !(bit_cfg & GPIO_BIT_CFG_TX_OE); +} + +static int thunderx_gpio_set_config(struct gpio_chip *chip, + unsigned int line, + unsigned long cfg) +{ + bool orig_invert, orig_od, orig_dat, new_invert, new_od; + u32 arg, sel; + u64 bit_cfg; + int bank = line / 64; + int bank_bit = line % 64; + int ret = -ENOTSUPP; + struct thunderx_gpio *txgpio = gpiochip_get_data(chip); + void __iomem *reg = txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_SET; + + if (!thunderx_gpio_is_gpio(txgpio, line)) + return -EIO; + + raw_spin_lock(&txgpio->lock); + orig_invert = test_bit(line, txgpio->invert_mask); + new_invert = orig_invert; + orig_od = test_bit(line, txgpio->od_mask); + new_od = orig_od; + orig_dat = ((readq(reg) >> bank_bit) & 1) ^ orig_invert; + bit_cfg = readq(txgpio->register_base + bit_cfg_reg(line)); + switch (pinconf_to_config_param(cfg)) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + /* + * Weird, setting open-drain mode causes signal + * inversion. Note this so we can compensate in the + * dir_out function. + */ + set_bit(line, txgpio->invert_mask); + new_invert = true; + set_bit(line, txgpio->od_mask); + new_od = true; + ret = 0; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + clear_bit(line, txgpio->invert_mask); + new_invert = false; + clear_bit(line, txgpio->od_mask); + new_od = false; + ret = 0; + break; + case PIN_CONFIG_INPUT_DEBOUNCE: + arg = pinconf_to_config_argument(cfg); + if (arg > 1228) { /* 15 * 2^15 * 2.5nS maximum */ + ret = -EINVAL; + break; + } + arg *= 400; /* scale to 2.5nS clocks. */ + sel = 0; + while (arg > 15) { + sel++; + arg++; /* always round up */ + arg >>= 1; + } + txgpio->line_entries[line].fil_bits = + (sel << GPIO_BIT_CFG_FIL_SEL_SHIFT) | + (arg << GPIO_BIT_CFG_FIL_CNT_SHIFT); + bit_cfg &= ~GPIO_BIT_CFG_FIL_MASK; + bit_cfg |= txgpio->line_entries[line].fil_bits; + writeq(bit_cfg, txgpio->register_base + bit_cfg_reg(line)); + ret = 0; + break; + default: + break; + } + raw_spin_unlock(&txgpio->lock); + + /* + * If currently output and OPEN_DRAIN changed, install the new + * settings + */ + if ((new_invert != orig_invert || new_od != orig_od) && + (bit_cfg & GPIO_BIT_CFG_TX_OE)) + ret = thunderx_gpio_dir_out(chip, line, orig_dat ^ new_invert); + + return ret; +} + +static int thunderx_gpio_get(struct gpio_chip *chip, unsigned int line) +{ + struct thunderx_gpio *txgpio = gpiochip_get_data(chip); + int bank = line / 64; + int bank_bit = line % 64; + u64 read_bits = readq(txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_RX_DAT); + u64 masked_bits = read_bits & BIT_ULL(bank_bit); + + if (test_bit(line, txgpio->invert_mask)) + return masked_bits == 0; + else + return masked_bits != 0; +} + +static void thunderx_gpio_set_multiple(struct gpio_chip *chip, + unsigned long *mask, + unsigned long *bits) +{ + int bank; + u64 set_bits, clear_bits; + struct thunderx_gpio *txgpio = gpiochip_get_data(chip); + + for (bank = 0; bank <= chip->ngpio / 64; bank++) { + set_bits = bits[bank] & mask[bank]; + clear_bits = ~bits[bank] & mask[bank]; + writeq(set_bits, txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_SET); + writeq(clear_bits, txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_CLR); + } +} + +static void thunderx_gpio_irq_ack(struct irq_data *data) +{ + struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + + writeq(GPIO_INTR_INTR, + txline->txgpio->register_base + intr_reg(txline->line)); +} + +static void thunderx_gpio_irq_mask(struct irq_data *data) +{ + struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + + writeq(GPIO_INTR_ENA_W1C, + txline->txgpio->register_base + intr_reg(txline->line)); +} + +static void thunderx_gpio_irq_mask_ack(struct irq_data *data) +{ + struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + + writeq(GPIO_INTR_ENA_W1C | GPIO_INTR_INTR, + txline->txgpio->register_base + intr_reg(txline->line)); +} + +static void thunderx_gpio_irq_unmask(struct irq_data *data) +{ + struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + + writeq(GPIO_INTR_ENA_W1S, + txline->txgpio->register_base + intr_reg(txline->line)); +} + +static int thunderx_gpio_irq_set_type(struct irq_data *data, + unsigned int flow_type) +{ + struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + struct thunderx_gpio *txgpio = txline->txgpio; + u64 bit_cfg; + + irqd_set_trigger_type(data, flow_type); + + bit_cfg = txline->fil_bits | GPIO_BIT_CFG_INT_EN; + + if (flow_type & IRQ_TYPE_EDGE_BOTH) { + irq_set_handler_locked(data, handle_fasteoi_ack_irq); + bit_cfg |= GPIO_BIT_CFG_INT_TYPE; + } else { + irq_set_handler_locked(data, handle_fasteoi_mask_irq); + } + + raw_spin_lock(&txgpio->lock); + if (flow_type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)) { + bit_cfg |= GPIO_BIT_CFG_PIN_XOR; + set_bit(txline->line, txgpio->invert_mask); + } else { + clear_bit(txline->line, txgpio->invert_mask); + } + clear_bit(txline->line, txgpio->od_mask); + writeq(bit_cfg, txgpio->register_base + bit_cfg_reg(txline->line)); + raw_spin_unlock(&txgpio->lock); + + return IRQ_SET_MASK_OK; +} + +static void thunderx_gpio_irq_enable(struct irq_data *data) +{ + irq_chip_enable_parent(data); + thunderx_gpio_irq_unmask(data); +} + +static void thunderx_gpio_irq_disable(struct irq_data *data) +{ + thunderx_gpio_irq_mask(data); + irq_chip_disable_parent(data); +} + +static int thunderx_gpio_irq_request_resources(struct irq_data *data) +{ + struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + struct thunderx_gpio *txgpio = txline->txgpio; + struct irq_data *parent_data = data->parent_data; + int r; + + r = gpiochip_lock_as_irq(&txgpio->chip, txline->line); + if (r) + return r; + + if (parent_data && parent_data->chip->irq_request_resources) { + r = parent_data->chip->irq_request_resources(parent_data); + if (r) + goto error; + } + + return 0; +error: + gpiochip_unlock_as_irq(&txgpio->chip, txline->line); + return r; +} + +static void thunderx_gpio_irq_release_resources(struct irq_data *data) +{ + struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + struct thunderx_gpio *txgpio = txline->txgpio; + struct irq_data *parent_data = data->parent_data; + + if (parent_data && parent_data->chip->irq_release_resources) + parent_data->chip->irq_release_resources(parent_data); + + gpiochip_unlock_as_irq(&txgpio->chip, txline->line); +} + +/* + * Interrupts are chained from underlying MSI-X vectors. We have + * these irq_chip functions to be able to handle level triggering + * semantics and other acknowledgment tasks associated with the GPIO + * mechanism. + */ +static struct irq_chip thunderx_gpio_irq_chip = { + .name = "GPIO", + .irq_enable = thunderx_gpio_irq_enable, + .irq_disable = thunderx_gpio_irq_disable, + .irq_ack = thunderx_gpio_irq_ack, + .irq_mask = thunderx_gpio_irq_mask, + .irq_mask_ack = thunderx_gpio_irq_mask_ack, + .irq_unmask = thunderx_gpio_irq_unmask, + .irq_eoi = irq_chip_eoi_parent, + .irq_set_affinity = irq_chip_set_affinity_parent, + .irq_request_resources = thunderx_gpio_irq_request_resources, + .irq_release_resources = thunderx_gpio_irq_release_resources, + .irq_set_type = thunderx_gpio_irq_set_type, + + .flags = IRQCHIP_SET_TYPE_MASKED +}; + +static int thunderx_gpio_irq_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hwirq) +{ + struct thunderx_gpio *txgpio = d->host_data; + + if (hwirq >= txgpio->chip.ngpio) + return -EINVAL; + if (!thunderx_gpio_is_gpio_nowarn(txgpio, hwirq)) + return -EPERM; + return 0; +} + +static int thunderx_gpio_irq_translate(struct irq_domain *d, + struct irq_fwspec *fwspec, + irq_hw_number_t *hwirq, + unsigned int *type) +{ + struct thunderx_gpio *txgpio = d->host_data; + + if (WARN_ON(fwspec->param_count < 2)) + return -EINVAL; + if (fwspec->param[0] >= txgpio->chip.ngpio) + return -EINVAL; + *hwirq = fwspec->param[0]; + *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; + return 0; +} + +static int thunderx_gpio_irq_alloc(struct irq_domain *d, unsigned int virq, + unsigned int nr_irqs, void *arg) +{ + struct thunderx_line *txline = arg; + + return irq_domain_set_hwirq_and_chip(d, virq, txline->line, + &thunderx_gpio_irq_chip, txline); +} + +static const struct irq_domain_ops thunderx_gpio_irqd_ops = { + .map = thunderx_gpio_irq_map, + .alloc = thunderx_gpio_irq_alloc, + .translate = thunderx_gpio_irq_translate +}; + +static int thunderx_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) +{ + struct thunderx_gpio *txgpio = gpiochip_get_data(chip); + + return irq_find_mapping(txgpio->irqd, offset); +} + +static int thunderx_gpio_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + void __iomem * const *tbl; + struct device *dev = &pdev->dev; + struct thunderx_gpio *txgpio; + struct gpio_chip *chip; + int ngpio, i; + int err = 0; + + txgpio = devm_kzalloc(dev, sizeof(*txgpio), GFP_KERNEL); + if (!txgpio) + return -ENOMEM; + + raw_spin_lock_init(&txgpio->lock); + chip = &txgpio->chip; + + pci_set_drvdata(pdev, txgpio); + + err = pcim_enable_device(pdev); + if (err) { + dev_err(dev, "Failed to enable PCI device: err %d\n", err); + goto out; + } + + err = pcim_iomap_regions(pdev, 1 << 0, KBUILD_MODNAME); + if (err) { + dev_err(dev, "Failed to iomap PCI device: err %d\n", err); + goto out; + } + + tbl = pcim_iomap_table(pdev); + txgpio->register_base = tbl[0]; + if (!txgpio->register_base) { + dev_err(dev, "Cannot map PCI resource\n"); + err = -ENOMEM; + goto out; + } + + if (pdev->subsystem_device == 0xa10a) { + /* CN88XX has no GPIO_CONST register*/ + ngpio = 50; + txgpio->base_msi = 48; + } else { + u64 c = readq(txgpio->register_base + GPIO_CONST); + + ngpio = c & GPIO_CONST_GPIOS_MASK; + txgpio->base_msi = (c >> 8) & 0xff; + } + + txgpio->msix_entries = devm_kzalloc(dev, + sizeof(struct msix_entry) * ngpio, + GFP_KERNEL); + if (!txgpio->msix_entries) { + err = -ENOMEM; + goto out; + } + + txgpio->line_entries = devm_kzalloc(dev, + sizeof(struct thunderx_line) * ngpio, + GFP_KERNEL); + if (!txgpio->line_entries) { + err = -ENOMEM; + goto out; + } + + for (i = 0; i < ngpio; i++) { + u64 bit_cfg = readq(txgpio->register_base + bit_cfg_reg(i)); + + txgpio->msix_entries[i].entry = txgpio->base_msi + (2 * i); + txgpio->line_entries[i].line = i; + txgpio->line_entries[i].txgpio = txgpio; + /* + * If something has already programmed the pin, use + * the existing glitch filter settings, otherwise go + * to 400nS. + */ + txgpio->line_entries[i].fil_bits = bit_cfg ? + (bit_cfg & GPIO_BIT_CFG_FIL_MASK) : GLITCH_FILTER_400NS; + + if ((bit_cfg & GPIO_BIT_CFG_TX_OE) && (bit_cfg & GPIO_BIT_CFG_TX_OD)) + set_bit(i, txgpio->od_mask); + if (bit_cfg & GPIO_BIT_CFG_PIN_XOR) + set_bit(i, txgpio->invert_mask); + } + + + /* Enable all MSI-X for interrupts on all possible lines. */ + err = pci_enable_msix_range(pdev, txgpio->msix_entries, ngpio, ngpio); + if (err < 0) + goto out; + + /* + * Push GPIO specific irqdomain on hierarchy created as a side + * effect of the pci_enable_msix() + */ + txgpio->irqd = irq_domain_create_hierarchy(irq_get_irq_data(txgpio->msix_entries[0].vector)->domain, + 0, 0, of_node_to_fwnode(dev->of_node), + &thunderx_gpio_irqd_ops, txgpio); + if (!txgpio->irqd) + goto out; + + /* Push on irq_data and the domain for each line. */ + for (i = 0; i < ngpio; i++) { + err = irq_domain_push_irq(txgpio->irqd, + txgpio->msix_entries[i].vector, + &txgpio->line_entries[i]); + if (err < 0) + dev_err(dev, "irq_domain_push_irq: %d\n", err); + } + + chip->label = KBUILD_MODNAME; + chip->parent = dev; + chip->owner = THIS_MODULE; + chip->request = thunderx_gpio_request; + chip->base = -1; /* System allocated */ + chip->can_sleep = false; + chip->ngpio = ngpio; + chip->get_direction = thunderx_gpio_get_direction; + chip->direction_input = thunderx_gpio_dir_in; + chip->get = thunderx_gpio_get; + chip->direction_output = thunderx_gpio_dir_out; + chip->set = thunderx_gpio_set; + chip->set_multiple = thunderx_gpio_set_multiple; + chip->set_config = thunderx_gpio_set_config; + chip->to_irq = thunderx_gpio_to_irq; + err = devm_gpiochip_add_data(dev, chip, txgpio); + if (err) + goto out; + + dev_info(dev, "ThunderX GPIO: %d lines with base %d.\n", + ngpio, chip->base); + return 0; +out: + pci_set_drvdata(pdev, NULL); + return err; +} + +static void thunderx_gpio_remove(struct pci_dev *pdev) +{ + int i; + struct thunderx_gpio *txgpio = pci_get_drvdata(pdev); + + for (i = 0; i < txgpio->chip.ngpio; i++) + irq_domain_pop_irq(txgpio->irqd, + txgpio->msix_entries[i].vector); + + irq_domain_remove(txgpio->irqd); + + pci_set_drvdata(pdev, NULL); +} + +static const struct pci_device_id thunderx_gpio_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xA00A) }, + { 0, } /* end of table */ +}; + +MODULE_DEVICE_TABLE(pci, thunderx_gpio_id_table); + +static struct pci_driver thunderx_gpio_driver = { + .name = KBUILD_MODNAME, + .id_table = thunderx_gpio_id_table, + .probe = thunderx_gpio_probe, + .remove = thunderx_gpio_remove, +}; + +module_pci_driver(thunderx_gpio_driver); + +MODULE_DESCRIPTION("Cavium Inc. ThunderX/OCTEON-TX GPIO Driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-55-g7522 From f89c6eafa35ae06390eea50f81c94d9a3c5ee5fe Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 10 Aug 2017 07:51:27 +0900 Subject: gpio: brcmstb: check return value of gpiochip_irqchip_add() Because gpiochip_irqchip_add() may fail, its return value should be checked. Signed-off-by: Masahiro Yamada Acked-by: Gregory Fong Signed-off-by: Linus Walleij --- drivers/gpio/gpio-brcmstb.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index 73f2c3be4657..dd0308cc8bb0 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -339,6 +339,7 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev, struct brcmstb_gpio_priv *priv = bank->parent_priv; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; + int err; bank->irq_chip.name = dev_name(dev); bank->irq_chip.irq_mask = brcmstb_gpio_irq_mask; @@ -355,8 +356,6 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev, dev_warn(dev, "Couldn't get wake IRQ - GPIOs will not be able to wake from sleep"); } else { - int err; - /* * Set wakeup capability before requesting wakeup * interrupt, so we can process boot-time "wakeups" @@ -383,8 +382,10 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev, if (priv->can_wake) bank->irq_chip.irq_set_wake = brcmstb_gpio_irq_set_wake; - gpiochip_irqchip_add(&bank->gc, &bank->irq_chip, 0, - handle_simple_irq, IRQ_TYPE_NONE); + err = gpiochip_irqchip_add(&bank->gc, &bank->irq_chip, 0, + handle_simple_irq, IRQ_TYPE_NONE); + if (err) + return err; gpiochip_set_chained_irqchip(&bank->gc, &bank->irq_chip, priv->parent_irq, brcmstb_gpio_irq_handler); -- cgit v1.2.3-55-g7522 From 3946d18765be0b0fe278bea4f87a54cf13858019 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 14 Aug 2017 21:59:55 -0700 Subject: gpio: add gpio_add_lookup_tables() to add several tables at once When converting legacy board to use gpiod API() there might be several lookup tables in board file, let's provide a way to register them all at once. Reviewed-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Dmitry Torokhov Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 17 +++++++++++++++++ include/linux/gpio/machine.h | 3 +++ 2 files changed, 20 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 18bba1748a35..e452768f316d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3010,6 +3010,23 @@ void gpiod_set_raw_array_value_cansleep(unsigned int array_size, } EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value_cansleep); +/** + * gpiod_add_lookup_tables() - register GPIO device consumers + * @tables: list of tables of consumers to register + * @n: number of tables in the list + */ +void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n) +{ + unsigned int i; + + mutex_lock(&gpio_lookup_lock); + + for (i = 0; i < n; i++) + list_add_tail(&tables[i]->list, &gpio_lookup_list); + + mutex_unlock(&gpio_lookup_lock); +} + /** * gpiod_set_array_value_cansleep() - assign values to an array of GPIOs * @array_size: number of elements in the descriptor / value arrays diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index 6e76b16fcade..ba4ccfd900f9 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h @@ -60,11 +60,14 @@ struct gpiod_lookup_table { #ifdef CONFIG_GPIOLIB void gpiod_add_lookup_table(struct gpiod_lookup_table *table); +void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n); void gpiod_remove_lookup_table(struct gpiod_lookup_table *table); #else static inline void gpiod_add_lookup_table(struct gpiod_lookup_table *table) {} static inline +void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n) {} +static inline void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) {} #endif -- cgit v1.2.3-55-g7522 From 4a14af45f70945cfa894188ec35a23e4aa394370 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sun, 20 Aug 2017 23:57:46 +0530 Subject: gpio: zevio: make gpio_chip const Make this const as it is only used as a copy operation. Done using Coccinelle. Signed-off-by: Bhumika Goyal Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zevio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-zevio.c b/drivers/gpio/gpio-zevio.c index e23ef7b9451d..3926ce9c2840 100644 --- a/drivers/gpio/gpio-zevio.c +++ b/drivers/gpio/gpio-zevio.c @@ -156,7 +156,7 @@ static int zevio_gpio_to_irq(struct gpio_chip *chip, unsigned pin) return -ENXIO; } -static struct gpio_chip zevio_gpio_chip = { +static const struct gpio_chip zevio_gpio_chip = { .direction_input = zevio_gpio_direction_input, .direction_output = zevio_gpio_direction_output, .set = zevio_gpio_set, -- cgit v1.2.3-55-g7522 From 1253baaafff03c695e49d6c63956f4ccf12dc0c8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 23 Aug 2017 02:33:55 +0900 Subject: gpio: twl6040: remove unneeded forward declaration There is no reference to twl6040gpo_chip before its definition. Signed-off-by: Masahiro Yamada Signed-off-by: Linus Walleij --- drivers/gpio/gpio-twl6040.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-twl6040.c b/drivers/gpio/gpio-twl6040.c index b780314cdfc9..dadeacf43e0c 100644 --- a/drivers/gpio/gpio-twl6040.c +++ b/drivers/gpio/gpio-twl6040.c @@ -32,8 +32,6 @@ #include -static struct gpio_chip twl6040gpo_chip; - static int twl6040gpo_get(struct gpio_chip *chip, unsigned offset) { struct twl6040 *twl6040 = dev_get_drvdata(chip->parent->parent); -- cgit v1.2.3-55-g7522 From 9e238e380c2a8aff21d37f713b5c24b079a726a5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 31 Aug 2017 07:58:17 +0200 Subject: Revert "gpiolib: request the gpio before querying its direction" This reverts commit 108d23e322a247d9f89ba2e2742520ead0944cc9. It turns out this causes a regression on the OMAP, Marvell and Renesas. Reported-by: Tony Lindgren Reported-by: Thomas Petazzoni Reported-by: Jacopo Mondi Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e452768f316d..eb80dac4e26a 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1221,14 +1221,6 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) struct gpio_desc *desc = &gdev->descs[i]; desc->gdev = gdev; - - if (chip->request) { - status = chip->request(chip, i); - if (status < 0) - /* The GPIO is unavailable, so skip it */ - continue; - } - /* * REVISIT: most hardware initializes GPIOs as inputs * (often with pullups enabled) so power usage is @@ -1254,9 +1246,6 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) */ set_bit(FLAG_IS_OUT, &desc->flags); } - - if (chip->free) - chip->free(chip, i); } #ifdef CONFIG_PINCTRL -- cgit v1.2.3-55-g7522 From 72c7c78e68d1e509c19bade5496d9d55d81699a5 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Wed, 23 Aug 2017 21:45:09 +0530 Subject: gpio: pl061: constify amba_id amba_id are not supposed to change at runtime. All functions working with const amba_id. So mark the non-const structs as const. Signed-off-by: Arvind Yadav Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pl061.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 3d3d6b6645a7..6aaaab79c205 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -405,7 +405,7 @@ static const struct dev_pm_ops pl061_dev_pm_ops = { }; #endif -static struct amba_id pl061_ids[] = { +static const struct amba_id pl061_ids[] = { { .id = 0x00041061, .mask = 0x000fffff, -- cgit v1.2.3-55-g7522 From 02b6bddb0b0a4e27fad6623d82579f2a1e35d3d3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 24 Aug 2017 12:34:22 +0100 Subject: gpio: mockup: remove unused variable gc The variable gc is assigned but never read and is redundant. Remove it. Cleans up clang warning: drivers/gpio/gpio-mockup.c:169:2: warning: Value stored to 'gc' is never read Signed-off-by: Colin Ian King Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mockup.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index 6db7163e6d98..9532d86a82f7 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -153,7 +153,6 @@ static ssize_t gpio_mockup_event_write(struct file *file, struct gpio_mockup_chip *chip; struct seq_file *sfile; struct gpio_desc *desc; - struct gpio_chip *gc; int rv, val; rv = kstrtoint_from_user(usr_buf, size, 0, &val); @@ -166,7 +165,6 @@ static ssize_t gpio_mockup_event_write(struct file *file, priv = sfile->private; desc = priv->desc; chip = priv->chip; - gc = &chip->gc; gpiod_set_value_cansleep(desc, val); irq_sim_fire(&chip->irqsim, priv->offset); -- cgit v1.2.3-55-g7522