diff options
-rw-r--r-- | Documentation/devicetree/bindings/gpio/snps,dw-apb-gpio.yaml | 134 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt | 65 | ||||
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-dwapb.c | 219 | ||||
-rw-r--r-- | drivers/gpio/gpio-ftgpio010.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-mlxbf2.c | 5 | ||||
-rw-r--r-- | drivers/gpio/gpio-mm-lantiq.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 6 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 24 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.h | 27 | ||||
-rw-r--r-- | include/linux/gpio/driver.h | 32 |
11 files changed, 275 insertions, 242 deletions
diff --git a/Documentation/devicetree/bindings/gpio/snps,dw-apb-gpio.yaml b/Documentation/devicetree/bindings/gpio/snps,dw-apb-gpio.yaml new file mode 100644 index 000000000000..04a3c51e1dc1 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/snps,dw-apb-gpio.yaml @@ -0,0 +1,134 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/snps,dw-apb-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Synopsys DesignWare APB GPIO controller + +description: | + Synopsys DesignWare GPIO controllers have a configurable number of ports, + each of which are intended to be represented as child nodes with the generic + GPIO-controller properties as desribed in this bindings file. + +maintainers: + - Hoan Tran <[email protected]> + - Serge Semin <[email protected]> + +properties: + $nodename: + pattern: "^gpio@[0-9a-f]+$" + + compatible: + const: snps,dw-apb-gpio + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + reg: + maxItems: 1 + + clocks: + minItems: 1 + items: + - description: APB interface clock source + - description: DW GPIO debounce reference clock source + + clock-names: + minItems: 1 + items: + - const: bus + - const: db + + resets: + maxItems: 1 + +patternProperties: + "^gpio-(port|controller)@[0-9a-f]+$": + type: object + properties: + compatible: + const: snps,dw-apb-gpio-port + + reg: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2 + + snps,nr-gpios: + description: The number of GPIO pins exported by the port. + default: 32 + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - minimum: 1 + maximum: 32 + + interrupts: + description: | + The interrupts to the parent controller raised when GPIOs generate + the interrupts. If the controller provides one combined interrupt + for all GPIOs, specify a single interrupt. If the controller provides + one interrupt for each GPIO, provide a list of interrupts that + correspond to each of the GPIO pins. + minItems: 1 + maxItems: 32 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + + required: + - compatible + - reg + - gpio-controller + - '#gpio-cells' + + dependencies: + interrupt-controller: [ interrupts ] + + additionalProperties: false + +additionalProperties: false + +required: + - compatible + - reg + - "#address-cells" + - "#size-cells" + +examples: + - | + gpio: gpio@20000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x20000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + porta: gpio-port@0 { + compatible = "snps,dw-apb-gpio-port"; + reg = <0>; + gpio-controller; + #gpio-cells = <2>; + snps,nr-gpios = <8>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&vic1>; + interrupts = <0>; + }; + + portb: gpio-port@1 { + compatible = "snps,dw-apb-gpio-port"; + reg = <1>; + gpio-controller; + #gpio-cells = <2>; + snps,nr-gpios = <8>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt deleted file mode 100644 index 839dd32ffe11..000000000000 --- a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt +++ /dev/null @@ -1,65 +0,0 @@ -* Synopsys DesignWare APB GPIO controller - -Required properties: -- compatible : Should contain "snps,dw-apb-gpio" -- reg : Address and length of the register set for the device. -- #address-cells : should be 1 (for addressing port subnodes). -- #size-cells : should be 0 (port subnodes). - -The GPIO controller has a configurable number of ports, each of which are -represented as child nodes with the following properties: - -Required properties: -- compatible : "snps,dw-apb-gpio-port" -- gpio-controller : Marks the device node as a gpio controller. -- #gpio-cells : Should be two. The first cell is the pin number and - the second cell is used to specify the gpio polarity: - 0 = active high - 1 = active low -- reg : The integer port index of the port, a single cell. - -Optional properties: -- interrupt-controller : The first port may be configured to be an interrupt -controller. -- #interrupt-cells : Specifies the number of cells needed to encode an - interrupt. Shall be set to 2. The first cell defines the interrupt number, - the second encodes the triger flags encoded as described in - Documentation/devicetree/bindings/interrupt-controller/interrupts.txt -- interrupts : The interrupts to the parent controller raised when GPIOs - generate the interrupts. If the controller provides one combined interrupt - for all GPIOs, specify a single interrupt. If the controller provides one - interrupt for each GPIO, provide a list of interrupts that correspond to each - of the GPIO pins. When specifying multiple interrupts, if any are unconnected, - use the interrupts-extended property to specify the interrupts and set the - interrupt controller handle for unused interrupts to 0. -- snps,nr-gpios : The number of pins in the port, a single cell. -- resets : Reset line for the controller. - -Example: - -gpio: gpio@20000 { - compatible = "snps,dw-apb-gpio"; - reg = <0x20000 0x1000>; - #address-cells = <1>; - #size-cells = <0>; - - porta: gpio@0 { - compatible = "snps,dw-apb-gpio-port"; - gpio-controller; - #gpio-cells = <2>; - snps,nr-gpios = <8>; - reg = <0>; - interrupt-controller; - #interrupt-cells = <2>; - interrupt-parent = <&vic1>; - interrupts = <0>; - }; - - portb: gpio@1 { - compatible = "snps,dw-apb-gpio-port"; - gpio-controller; - #gpio-cells = <2>; - snps,nr-gpios = <8>; - reg = <1>; - }; -}; diff --git a/MAINTAINERS b/MAINTAINERS index e64e5db31497..4306b329987d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16227,6 +16227,7 @@ F: drivers/tty/serial/8250/8250_lpss.c SYNOPSYS DESIGNWARE APB GPIO DRIVER M: Hoan Tran <[email protected]> +M: Serge Semin <[email protected]> S: Maintained F: Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 92e127e74813..8639c4a7f469 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -49,7 +49,9 @@ #define GPIO_EXT_PORTC 0x58 #define GPIO_EXT_PORTD 0x5c +#define DWAPB_DRIVER_NAME "gpio-dwapb" #define DWAPB_MAX_PORTS 4 + #define GPIO_EXT_PORT_STRIDE 0x04 /* register stride 32 bits */ #define GPIO_SWPORT_DR_STRIDE 0x0c /* register stride 3*32 bits */ #define GPIO_SWPORT_DDR_STRIDE 0x0c /* register stride 3*32 bits */ @@ -62,6 +64,8 @@ #define GPIO_INTSTATUS_V2 0x3c #define GPIO_PORTA_EOI_V2 0x40 +#define DWAPB_NR_CLOCKS 2 + struct dwapb_gpio; #ifdef CONFIG_PM_SLEEP @@ -97,7 +101,7 @@ struct dwapb_gpio { struct irq_domain *domain; unsigned int flags; struct reset_control *rst; - struct clk *clk; + struct clk_bulk_data clks[DWAPB_NR_CLOCKS]; }; static inline u32 gpio_reg_v2_convert(unsigned int offset) @@ -189,22 +193,21 @@ static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs) static u32 dwapb_do_irq(struct dwapb_gpio *gpio) { - u32 irq_status = dwapb_read(gpio, GPIO_INTSTATUS); - u32 ret = irq_status; + unsigned long irq_status; + irq_hw_number_t hwirq; - while (irq_status) { - int hwirq = fls(irq_status) - 1; + irq_status = dwapb_read(gpio, GPIO_INTSTATUS); + for_each_set_bit(hwirq, &irq_status, 32) { int gpio_irq = irq_find_mapping(gpio->domain, hwirq); + u32 irq_type = irq_get_trigger_type(gpio_irq); generic_handle_irq(gpio_irq); - irq_status &= ~BIT(hwirq); - if ((irq_get_trigger_type(gpio_irq) & IRQ_TYPE_SENSE_MASK) - == IRQ_TYPE_EDGE_BOTH) + if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) dwapb_toggle_trigger(gpio, hwirq); } - return ret; + return irq_status; } static void dwapb_irq_handler(struct irq_desc *desc) @@ -212,10 +215,9 @@ static void dwapb_irq_handler(struct irq_desc *desc) struct dwapb_gpio *gpio = irq_desc_get_handler_data(desc); struct irq_chip *chip = irq_desc_get_chip(desc); + chained_irq_enter(chip, desc); dwapb_do_irq(gpio); - - if (chip->irq_eoi) - chip->irq_eoi(irq_desc_get_irq_data(desc)); + chained_irq_exit(chip, desc); } static void dwapb_irq_enable(struct irq_data *d) @@ -228,7 +230,7 @@ static void dwapb_irq_enable(struct irq_data *d) spin_lock_irqsave(&gc->bgpio_lock, flags); val = dwapb_read(gpio, GPIO_INTEN); - val |= BIT(d->hwirq); + val |= BIT(irqd_to_hwirq(d)); dwapb_write(gpio, GPIO_INTEN, val); spin_unlock_irqrestore(&gc->bgpio_lock, flags); } @@ -243,46 +245,20 @@ static void dwapb_irq_disable(struct irq_data *d) spin_lock_irqsave(&gc->bgpio_lock, flags); val = dwapb_read(gpio, GPIO_INTEN); - val &= ~BIT(d->hwirq); + val &= ~BIT(irqd_to_hwirq(d)); dwapb_write(gpio, GPIO_INTEN, val); spin_unlock_irqrestore(&gc->bgpio_lock, flags); } -static int dwapb_irq_reqres(struct irq_data *d) -{ - struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d); - struct dwapb_gpio *gpio = igc->private; - struct gpio_chip *gc = &gpio->ports[0].gc; - int ret; - - ret = gpiochip_lock_as_irq(gc, irqd_to_hwirq(d)); - if (ret) { - dev_err(gpio->dev, "unable to lock HW IRQ %lu for IRQ\n", - irqd_to_hwirq(d)); - return ret; - } - return 0; -} - -static void dwapb_irq_relres(struct irq_data *d) -{ - struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d); - struct dwapb_gpio *gpio = igc->private; - struct gpio_chip *gc = &gpio->ports[0].gc; - - gpiochip_unlock_as_irq(gc, irqd_to_hwirq(d)); -} - static int dwapb_irq_set_type(struct irq_data *d, u32 type) { struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d); struct dwapb_gpio *gpio = igc->private; struct gpio_chip *gc = &gpio->ports[0].gc; - int bit = d->hwirq; + irq_hw_number_t bit = irqd_to_hwirq(d); unsigned long level, polarity, flags; - if (type & ~(IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | - IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) + if (type & ~IRQ_TYPE_SENSE_MASK) return -EINVAL; spin_lock_irqsave(&gc->bgpio_lock, flags); @@ -328,11 +304,12 @@ static int dwapb_irq_set_wake(struct irq_data *d, unsigned int enable) struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d); struct dwapb_gpio *gpio = igc->private; struct dwapb_context *ctx = gpio->ports[0].ctx; + irq_hw_number_t bit = irqd_to_hwirq(d); if (enable) - ctx->wake_en |= BIT(d->hwirq); + ctx->wake_en |= BIT(bit); else - ctx->wake_en &= ~BIT(d->hwirq); + ctx->wake_en &= ~BIT(bit); return 0; } @@ -350,9 +327,10 @@ static int dwapb_gpio_set_debounce(struct gpio_chip *gc, val_deb = dwapb_read(gpio, GPIO_PORTA_DEBOUNCE); if (debounce) - dwapb_write(gpio, GPIO_PORTA_DEBOUNCE, val_deb | mask); + val_deb |= mask; else - dwapb_write(gpio, GPIO_PORTA_DEBOUNCE, val_deb & ~mask); + val_deb &= ~mask; + dwapb_write(gpio, GPIO_PORTA_DEBOUNCE, val_deb); spin_unlock_irqrestore(&gc->bgpio_lock, flags); @@ -373,12 +351,7 @@ static int dwapb_gpio_set_config(struct gpio_chip *gc, unsigned offset, static irqreturn_t dwapb_irq_handler_mfd(int irq, void *dev_id) { - u32 worked; - struct dwapb_gpio *gpio = dev_id; - - worked = dwapb_do_irq(gpio); - - return worked ? IRQ_HANDLED : IRQ_NONE; + return IRQ_RETVAL(dwapb_do_irq(dev_id)); } static void dwapb_configure_irqs(struct dwapb_gpio *gpio, @@ -388,8 +361,9 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, struct gpio_chip *gc = &port->gc; struct fwnode_handle *fwnode = pp->fwnode; struct irq_chip_generic *irq_gc = NULL; - unsigned int hwirq, ngpio = gc->ngpio; + unsigned int ngpio = gc->ngpio; struct irq_chip_type *ct; + irq_hw_number_t hwirq; int err, i; gpio->domain = irq_domain_create_linear(fwnode, ngpio, @@ -398,7 +372,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, return; err = irq_alloc_domain_generic_chips(gpio->domain, ngpio, 2, - "gpio-dwapb", handle_level_irq, + DWAPB_DRIVER_NAME, handle_bad_irq, IRQ_NOREQUEST, 0, IRQ_GC_INIT_NESTED_LOCK); if (err) { @@ -426,8 +400,6 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, ct->chip.irq_set_type = dwapb_irq_set_type; ct->chip.irq_enable = dwapb_irq_enable; ct->chip.irq_disable = dwapb_irq_disable; - ct->chip.irq_request_resources = dwapb_irq_reqres; - ct->chip.irq_release_resources = dwapb_irq_relres; #ifdef CONFIG_PM_SLEEP ct->chip.irq_set_wake = dwapb_irq_set_wake; #endif @@ -437,6 +409,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, } irq_gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK; + irq_gc->chip_types[0].handler = handle_level_irq; irq_gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH; irq_gc->chip_types[1].handler = handle_edge_irq; @@ -455,7 +428,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, */ err = devm_request_irq(gpio->dev, pp->irq[0], dwapb_irq_handler_mfd, - IRQF_SHARED, "gpio-dwapb-mfd", gpio); + IRQF_SHARED, DWAPB_DRIVER_NAME, gpio); if (err) { dev_err(gpio->dev, "error requesting IRQ\n"); irq_domain_remove(gpio->domain); @@ -464,7 +437,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, } } - for (hwirq = 0 ; hwirq < ngpio ; hwirq++) + for (hwirq = 0; hwirq < ngpio; hwirq++) irq_create_mapping(gpio->domain, hwirq); port->gc.to_irq = dwapb_gpio_to_irq; @@ -480,7 +453,7 @@ static void dwapb_irq_teardown(struct dwapb_gpio *gpio) if (!gpio->domain) return; - for (hwirq = 0 ; hwirq < ngpio ; hwirq++) + for (hwirq = 0; hwirq < ngpio; hwirq++) irq_dispose_mapping(irq_find_mapping(gpio->domain, hwirq)); irq_domain_remove(gpio->domain); @@ -505,10 +478,9 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, return -ENOMEM; #endif - dat = gpio->regs + GPIO_EXT_PORTA + (pp->idx * GPIO_EXT_PORT_STRIDE); - set = gpio->regs + GPIO_SWPORTA_DR + (pp->idx * GPIO_SWPORT_DR_STRIDE); - dirout = gpio->regs + GPIO_SWPORTA_DDR + - (pp->idx * GPIO_SWPORT_DDR_STRIDE); + dat = gpio->regs + GPIO_EXT_PORTA + pp->idx * GPIO_EXT_PORT_STRIDE; + set = gpio->regs + GPIO_SWPORTA_DR + pp->idx * GPIO_SWPORT_DR_STRIDE; + dirout = gpio->regs + GPIO_SWPORTA_DDR + pp->idx * GPIO_SWPORT_DDR_STRIDE; /* This registers 32 GPIO lines per port */ err = bgpio_init(&port->gc, gpio->dev, 4, dat, set, NULL, dirout, @@ -555,14 +527,38 @@ static void dwapb_gpio_unregister(struct dwapb_gpio *gpio) gpiochip_remove(&gpio->ports[m].gc); } -static struct dwapb_platform_data * -dwapb_gpio_get_pdata(struct device *dev) +static void dwapb_get_irq(struct device *dev, struct fwnode_handle *fwnode, + struct dwapb_port_property *pp) +{ + struct device_node *np = NULL; + int j; + + if (fwnode_property_read_bool(fwnode, "interrupt-controller")) + np = to_of_node(fwnode); + + for (j = 0; j < pp->ngpio; j++) { + pp->irq[j] = -ENXIO; + + if (np) + pp->irq[j] = of_irq_get(np, j); + else if (has_acpi_companion(dev)) + pp->irq[j] = platform_get_irq(to_platform_device(dev), j); + + if (pp->irq[j] >= 0) + pp->has_irq = true; + } + + if (!pp->has_irq) + dev_warn(dev, "no irq for port%d\n", pp->idx); +} + +static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev) { struct fwnode_handle *fwnode; struct dwapb_platform_data *pdata; struct dwapb_port_property *pp; int nports; - int i, j; + int i; nports = device_get_child_node_count(dev); if (nports == 0) @@ -580,8 +576,6 @@ dwapb_gpio_get_pdata(struct device *dev) i = 0; device_for_each_child_node(dev, fwnode) { - struct device_node *np = NULL; - pp = &pdata->properties[i++]; pp->fwnode = fwnode; @@ -593,8 +587,7 @@ dwapb_gpio_get_pdata(struct device *dev) return ERR_PTR(-EINVAL); } - if (fwnode_property_read_u32(fwnode, "snps,nr-gpios", - &pp->ngpio)) { + if (fwnode_property_read_u32(fwnode, "snps,nr-gpios", &pp->ngpio)) { dev_info(dev, "failed to get number of gpios for port%d\n", i); @@ -608,28 +601,8 @@ dwapb_gpio_get_pdata(struct device *dev) * Only port A can provide interrupts in all configurations of * the IP. */ - if (pp->idx != 0) - continue; - - if (dev->of_node && fwnode_property_read_bool(fwnode, - "interrupt-controller")) { - np = to_of_node(fwnode); - } - - for (j = 0; j < pp->ngpio; j++) { - pp->irq[j] = -ENXIO; - - if (np) - pp->irq[j] = of_irq_get(np, j); - else if (has_acpi_companion(dev)) - pp->irq[j] = platform_get_irq(to_platform_device(dev), j); - - if (pp->irq[j] >= 0) - pp->has_irq = true; - } - - if (!pp->has_irq) - dev_warn(dev, "no irq for port%d\n", pp->idx); + if (pp->idx == 0) + dwapb_get_irq(dev, fwnode, pp); } return pdata; @@ -689,29 +662,24 @@ static int dwapb_gpio_probe(struct platform_device *pdev) if (IS_ERR(gpio->regs)) return PTR_ERR(gpio->regs); - /* Optional bus clock */ - gpio->clk = devm_clk_get(&pdev->dev, "bus"); - if (!IS_ERR(gpio->clk)) { - err = clk_prepare_enable(gpio->clk); - if (err) { - dev_info(&pdev->dev, "Cannot enable clock\n"); - return err; - } + /* Optional bus and debounce clocks */ + gpio->clks[0].id = "bus"; + gpio->clks[1].id = "db"; + err = devm_clk_bulk_get_optional(&pdev->dev, DWAPB_NR_CLOCKS, + gpio->clks); + if (err) { + dev_err(&pdev->dev, "Cannot get APB/Debounce clocks\n"); + return err; } - gpio->flags = 0; - if (dev->of_node) { - gpio->flags = (uintptr_t)of_device_get_match_data(dev); - } else if (has_acpi_companion(dev)) { - const struct acpi_device_id *acpi_id; - - acpi_id = acpi_match_device(dwapb_acpi_match, dev); - if (acpi_id) { - if (acpi_id->driver_data) - gpio->flags = acpi_id->driver_data; - } + err = clk_bulk_prepare_enable(DWAPB_NR_CLOCKS, gpio->clks); + if (err) { + dev_err(&pdev->dev, "Cannot enable APB/Debounce clocks\n"); + return err; } + gpio->flags = (uintptr_t)device_get_match_data(dev); + for (i = 0; i < gpio->nr_ports; i++) { err = dwapb_gpio_add_port(gpio, &pdata->properties[i], i); if (err) @@ -724,7 +692,7 @@ static int dwapb_gpio_probe(struct platform_device *pdev) out_unregister: dwapb_gpio_unregister(gpio); dwapb_irq_teardown(gpio); - clk_disable_unprepare(gpio->clk); + clk_bulk_disable_unprepare(DWAPB_NR_CLOCKS, gpio->clks); return err; } @@ -736,7 +704,7 @@ static int dwapb_gpio_remove(struct platform_device *pdev) dwapb_gpio_unregister(gpio); dwapb_irq_teardown(gpio); reset_control_assert(gpio->rst); - clk_disable_unprepare(gpio->clk); + clk_bulk_disable_unprepare(DWAPB_NR_CLOCKS, gpio->clks); return 0; } @@ -755,8 +723,6 @@ static int dwapb_gpio_suspend(struct device *dev) unsigned int idx = gpio->ports[i].idx; struct dwapb_context *ctx = gpio->ports[i].ctx; - BUG_ON(!ctx); - offset = GPIO_SWPORTA_DDR + idx * GPIO_SWPORT_DDR_STRIDE; ctx->dir = dwapb_read(gpio, offset); @@ -775,13 +741,12 @@ static int dwapb_gpio_suspend(struct device *dev) ctx->int_deb = dwapb_read(gpio, GPIO_PORTA_DEBOUNCE); /* Mask out interrupts */ - dwapb_write(gpio, GPIO_INTMASK, - 0xffffffff & ~ctx->wake_en); + dwapb_write(gpio, GPIO_INTMASK, ~ctx->wake_en); } } spin_unlock_irqrestore(&gc->bgpio_lock, flags); - clk_disable_unprepare(gpio->clk); + clk_bulk_disable_unprepare(DWAPB_NR_CLOCKS, gpio->clks); return 0; } @@ -791,10 +756,13 @@ static int dwapb_gpio_resume(struct device *dev) struct dwapb_gpio *gpio = dev_get_drvdata(dev); struct gpio_chip *gc = &gpio->ports[0].gc; unsigned long flags; - int i; + int i, err; - if (!IS_ERR(gpio->clk)) - clk_prepare_enable(gpio->clk); + err = clk_bulk_prepare_enable(DWAPB_NR_CLOCKS, gpio->clks); + if (err) { + dev_err(gpio->dev, "Cannot reenable APB/Debounce clocks\n"); + return err; + } spin_lock_irqsave(&gc->bgpio_lock, flags); for (i = 0; i < gpio->nr_ports; i++) { @@ -802,8 +770,6 @@ static int dwapb_gpio_resume(struct device *dev) unsigned int idx = gpio->ports[i].idx; struct dwapb_context *ctx = gpio->ports[i].ctx; - BUG_ON(!ctx); - offset = GPIO_SWPORTA_DR + idx * GPIO_SWPORT_DR_STRIDE; dwapb_write(gpio, offset, ctx->data); @@ -836,10 +802,10 @@ static SIMPLE_DEV_PM_OPS(dwapb_gpio_pm_ops, dwapb_gpio_suspend, static struct platform_driver dwapb_gpio_driver = { .driver = { - .name = "gpio-dwapb", + .name = DWAPB_DRIVER_NAME, .pm = &dwapb_gpio_pm_ops, - .of_match_table = of_match_ptr(dwapb_of_match), - .acpi_match_table = ACPI_PTR(dwapb_acpi_match), + .of_match_table = dwapb_of_match, + .acpi_match_table = dwapb_acpi_match, }, .probe = dwapb_gpio_probe, .remove = dwapb_gpio_remove, @@ -850,3 +816,4 @@ module_platform_driver(dwapb_gpio_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jamie Iles"); MODULE_DESCRIPTION("Synopsys DesignWare APB GPIO driver"); +MODULE_ALIAS("platform:" DWAPB_DRIVER_NAME); diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c index fbddb1662428..4031164780f7 100644 --- a/drivers/gpio/gpio-ftgpio010.c +++ b/drivers/gpio/gpio-ftgpio010.c @@ -193,7 +193,7 @@ static int ftgpio_gpio_set_config(struct gpio_chip *gc, unsigned int offset, if (val == deb_div) { /* * The debounce timer happens to already be set to the - * desireable value, what a coincidence! We can just enable + * desirable value, what a coincidence! We can just enable * debounce on this GPIO line and return. This happens more * often than you think, for example when all GPIO keys * on a system are requesting the same debounce interval. diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c index 7b7085050219..fca6a50d9308 100644 --- a/drivers/gpio/gpio-mlxbf2.c +++ b/drivers/gpio/gpio-mlxbf2.c @@ -14,7 +14,6 @@ #include <linux/resource.h> #include <linux/spinlock.h> #include <linux/types.h> -#include <linux/version.h> /* * There are 3 YU GPIO blocks: @@ -110,8 +109,8 @@ static int mlxbf2_gpio_get_lock_res(struct platform_device *pdev) } yu_arm_gpio_lock_param.io = devm_ioremap(dev, res->start, size); - if (IS_ERR(yu_arm_gpio_lock_param.io)) - ret = PTR_ERR(yu_arm_gpio_lock_param.io); + if (!yu_arm_gpio_lock_param.io) + ret = -ENOMEM; exit: mutex_unlock(yu_arm_gpio_lock_param.lock); diff --git a/drivers/gpio/gpio-mm-lantiq.c b/drivers/gpio/gpio-mm-lantiq.c index f460d71b0c92..538e31fe8903 100644 --- a/drivers/gpio/gpio-mm-lantiq.c +++ b/drivers/gpio/gpio-mm-lantiq.c @@ -36,7 +36,7 @@ struct ltq_mm { * @chip: Pointer to our private data structure. * * Write the shadow value to the EBU to set the gpios. We need to set the - * global EBU lock to make sure that PCI/MTD dont break. + * global EBU lock to make sure that PCI/MTD don't break. */ static void ltq_mm_apply(struct ltq_mm *chip) { diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 0017367e94ee..9276051663da 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -1353,7 +1353,7 @@ int acpi_gpio_count(struct device *dev, const char *con_id) } /* Run deferred acpi_gpiochip_request_irqs() */ -static int acpi_gpio_handle_deferred_request_irqs(void) +static int __init acpi_gpio_handle_deferred_request_irqs(void) { struct acpi_gpio_chip *acpi_gpio, *tmp; @@ -1371,7 +1371,7 @@ static int acpi_gpio_handle_deferred_request_irqs(void) /* We must use _sync so that this runs after the first deferred_probe run */ late_initcall_sync(acpi_gpio_handle_deferred_request_irqs); -static const struct dmi_system_id gpiolib_acpi_quirks[] = { +static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = { { /* * The Minix Neo Z83-4 has a micro-USB-B id-pin handler for @@ -1455,7 +1455,7 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] = { {} /* Terminating entry */ }; -static int acpi_gpio_setup_params(void) +static int __init acpi_gpio_setup_params(void) { const struct acpi_gpiolib_dmi_quirk *quirk = NULL; const struct dmi_system_id *id; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 40f2d7f69be2..48b4f70e2898 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1508,9 +1508,8 @@ static int gpiochip_setup_dev(struct gpio_device *gdev) /* From this point, the .release() function cleans up gpio_device */ gdev->dev.release = gpiodevice_release; - pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n", - __func__, gdev->base, gdev->base + gdev->ngpio - 1, - dev_name(&gdev->dev), gdev->chip->label ? : "generic"); + dev_dbg(&gdev->dev, "registered GPIOs %d to %d on %s\n", gdev->base, + gdev->base + gdev->ngpio - 1, gdev->chip->label ? : "generic"); return 0; @@ -1526,8 +1525,8 @@ static void gpiochip_machine_hog(struct gpio_chip *gc, struct gpiod_hog *hog) desc = gpiochip_get_desc(gc, hog->chip_hwnum); if (IS_ERR(desc)) { - pr_err("%s: unable to get GPIO desc: %ld\n", - __func__, PTR_ERR(desc)); + chip_err(gc, "%s: unable to get GPIO desc: %ld\n", __func__, + PTR_ERR(desc)); return; } @@ -1536,8 +1535,8 @@ static void gpiochip_machine_hog(struct gpio_chip *gc, struct gpiod_hog *hog) rv = gpiod_hog(desc, hog->line_name, hog->lflags, hog->dflags); if (rv) - pr_err("%s: unable to hog GPIO line (%s:%u): %d\n", - __func__, gc->label, hog->chip_hwnum, rv); + gpiod_err(desc, "%s: unable to hog GPIO line (%s:%u): %d\n", + __func__, gc->label, hog->chip_hwnum, rv); } static void machine_gpiochip_add(struct gpio_chip *gc) @@ -1562,8 +1561,8 @@ static void gpiochip_setup_devs(void) list_for_each_entry(gdev, &gpio_devices, list) { ret = gpiochip_setup_dev(gdev); if (ret) - pr_err("%s: Failed to initialize gpio device (%d)\n", - dev_name(&gdev->dev), ret); + dev_err(&gdev->dev, + "Failed to initialize gpio device (%d)\n", ret); } } @@ -2672,7 +2671,7 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gc, return -EINVAL; if (!gc->parent) { - pr_err("missing gpiochip .dev parent pointer\n"); + chip_err(gc, "missing gpiochip .dev parent pointer\n"); return -EINVAL; } gc->irq.threaded = threaded; @@ -4842,7 +4841,7 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, /* No particular flag request, return here... */ if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) { - pr_debug("no flags found for %s\n", con_id); + gpiod_dbg(desc, "no flags found for %s\n", con_id); return 0; } @@ -5067,8 +5066,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, /* Mark GPIO as hogged so it can be identified and removed later */ set_bit(FLAG_IS_HOGGED, &desc->flags); - pr_info("GPIO line %d (%s) hogged as %s%s\n", - desc_to_gpio(desc), name, + gpiod_info(desc, "hogged as %s%s\n", (dflags & GPIOD_FLAGS_BIT_DIR_OUT) ? "output" : "input", (dflags & GPIOD_FLAGS_BIT_DIR_OUT) ? (dflags & GPIOD_FLAGS_BIT_DIR_VAL) ? "/high" : "/low" : ""); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 853ce681b4a4..9ed242316414 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -81,8 +81,7 @@ struct gpio_array { unsigned long invert_mask[]; }; -struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, - unsigned int hwnum); +struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, unsigned int hwnum); int gpiod_get_array_value_complex(bool raw, bool can_sleep, unsigned int array_size, struct gpio_desc **desc_array, @@ -163,18 +162,18 @@ static inline int gpio_chip_hwgpio(const struct gpio_desc *desc) /* With chip prefix */ -#define chip_emerg(chip, fmt, ...) \ - dev_emerg(&chip->gpiodev->dev, "(%s): " fmt, chip->label, ##__VA_ARGS__) -#define chip_crit(chip, fmt, ...) \ - dev_crit(&chip->gpiodev->dev, "(%s): " fmt, chip->label, ##__VA_ARGS__) -#define chip_err(chip, fmt, ...) \ - dev_err(&chip->gpiodev->dev, "(%s): " fmt, chip->label, ##__VA_ARGS__) -#define chip_warn(chip, fmt, ...) \ - dev_warn(&chip->gpiodev->dev, "(%s): " fmt, chip->label, ##__VA_ARGS__) -#define chip_info(chip, fmt, ...) \ - dev_info(&chip->gpiodev->dev, "(%s): " fmt, chip->label, ##__VA_ARGS__) -#define chip_dbg(chip, fmt, ...) \ - dev_dbg(&chip->gpiodev->dev, "(%s): " fmt, chip->label, ##__VA_ARGS__) +#define chip_emerg(gc, fmt, ...) \ + dev_emerg(&gc->gpiodev->dev, "(%s): " fmt, gc->label, ##__VA_ARGS__) +#define chip_crit(gc, fmt, ...) \ + dev_crit(&gc->gpiodev->dev, "(%s): " fmt, gc->label, ##__VA_ARGS__) +#define chip_err(gc, fmt, ...) \ + dev_err(&gc->gpiodev->dev, "(%s): " fmt, gc->label, ##__VA_ARGS__) +#define chip_warn(gc, fmt, ...) \ + dev_warn(&gc->gpiodev->dev, "(%s): " fmt, gc->label, ##__VA_ARGS__) +#define chip_info(gc, fmt, ...) \ + dev_info(&gc->gpiodev->dev, "(%s): " fmt, gc->label, ##__VA_ARGS__) +#define chip_dbg(gc, fmt, ...) \ + dev_dbg(&gc->gpiodev->dev, "(%s): " fmt, gc->label, ##__VA_ARGS__) #ifdef CONFIG_GPIO_SYSFS diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index b8fc92c177eb..8c41ae41b6bb 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -267,9 +267,9 @@ struct gpio_irq_chip { * @free: optional hook for chip-specific deactivation, such as * disabling module power and clock; may sleep * @get_direction: returns direction for signal "offset", 0=out, 1=in, - * (same as GPIOF_DIR_XXX), or negative error. - * It is recommended to always implement this function, even on - * input-only or output-only gpio chips. + * (same as GPIO_LINE_DIRECTION_OUT / GPIO_LINE_DIRECTION_IN), + * or negative error. It is recommended to always implement this + * function, even on input-only or output-only gpio chips. * @direction_input: configures signal "offset" as input, or returns error * This can be omitted on input-only or output-only gpio chips. * @direction_output: configures signal "offset" as output, or returns error @@ -349,30 +349,30 @@ struct gpio_chip { struct module *owner; int (*request)(struct gpio_chip *gc, - unsigned offset); + unsigned int offset); void (*free)(struct gpio_chip *gc, - unsigned offset); + unsigned int offset); int (*get_direction)(struct gpio_chip *gc, - unsigned offset); + unsigned int offset); int (*direction_input)(struct gpio_chip *gc, - unsigned offset); + unsigned int offset); int (*direction_output)(struct gpio_chip *gc, - unsigned offset, int value); + unsigned int offset, int value); int (*get)(struct gpio_chip *gc, - unsigned offset); + unsigned int offset); int (*get_multiple)(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits); void (*set)(struct gpio_chip *gc, - unsigned offset, int value); + unsigned int offset, int value); void (*set_multiple)(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits); int (*set_config)(struct gpio_chip *gc, - unsigned offset, + unsigned int offset, unsigned long config); int (*to_irq)(struct gpio_chip *gc, - unsigned offset); + unsigned int offset); void (*dbg_show)(struct seq_file *s, struct gpio_chip *gc); @@ -459,7 +459,7 @@ struct gpio_chip { }; extern const char *gpiochip_is_requested(struct gpio_chip *gc, - unsigned offset); + unsigned int offset); /* add/remove chips */ extern int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, @@ -657,9 +657,9 @@ static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gc, } #endif /* CONFIG_LOCKDEP */ -int gpiochip_generic_request(struct gpio_chip *gc, unsigned offset); -void gpiochip_generic_free(struct gpio_chip *gc, unsigned offset); -int gpiochip_generic_config(struct gpio_chip *gc, unsigned offset, +int gpiochip_generic_request(struct gpio_chip *gc, unsigned int offset); +void gpiochip_generic_free(struct gpio_chip *gc, unsigned int offset); +int gpiochip_generic_config(struct gpio_chip *gc, unsigned int offset, unsigned long config); /** |