Pull GPIO changes from Linus Walleij: "This is the bulk of GPIO changes for the v3.18 development cycle: - Increase the default ARCH_NR_GPIO from 256 to 512. This was done to avoid having a custom <asm/gpio.h> header for the x86 architecture - GPIO is custom and complicated enough as it is already! We want to move to a radix to store the descriptors going forward, and finally get rid of this fixed array size altogether. - Endgame patching of the gpio_remove() semantics initiated by Abdoulaye Berthe. It is not accepted by the system that the removal of a GPIO chip fails during eg reboot or shutdown, and therefore the return value has now painfully been refactored away. For special cases like GPIO expanders on a hot-pluggable bus like USB, we may later add some gpiochip_try_remove() call, but for the cases we have now, return values are moot. - Some incremental refactoring of the gpiolib core and ACPI GPIO library for more descriptor usage. - Refactor the chained IRQ handler set-up method to handle also threaded, nested interrupts and set up the parent IRQ correctly. Switch STMPE and TC3589x drivers to use this registration method. - Add a .irq_not_threaded flag to the struct gpio_chip, so that also GPIO expanders that block but are still not using threaded IRQ handlers. - New drivers for the ARM64 X-Gene SoC GPIO controller. - The syscon GPIO driver has been improved to handle the "DSP GPIO" found on the TI Keystone 2 SoC:s. - ADNP driver switched to use gpiolib irqchip helpers. - Refactor the DWAPB driver to support being instantiated from and MFD cell (platform device). - Incremental feature improvement in the Zynq, MCP23S08, DWAPB, OMAP, Xilinx and Crystalcove drivers. - Various minor fixes" * tag 'gpio-v3.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (52 commits) gpio: pch: Build context save/restore only for PM pinctrl: abx500: get rid of unused variable gpio: ks8695: fix 'else should follow close brace '}'' gpio: stmpe: add verbose debug code gpio: stmpe: fix up interrupt enable logic gpio: staticize xway_stp_init() gpio: handle also nested irqchips in the chained handler set-up gpio: set parent irq on chained handlers gpiolib: irqchip: use irq_find_mapping while removing irqchip gpio: crystalcove: support virtual GPIO pinctrl: bcm281xx: make Kconfig dependency more strict gpio: kona: enable only on BCM_MOBILE or for compile testing gpio, bcm-kona, LLVMLinux: Remove use of __initconst gpio: Fix ngpio in gpio-xilinx driver gpio: dwapb: fix pointer to integer cast gpio: xgene: Remove unneeded #ifdef CONFIG_OF guard gpio: xgene: Remove unneeded forward declation for struct xgene_gpio gpio: xgene: Fix missing spin_lock_init() gpio: ks8695: fix switch case indentation gpiolib: add irq_not_threaded flag to gpio_chip ...
Unified · Split
| @@ -0,0 +1,39 @@ | ||
| 1 | +Keystone 2 DSP GPIO controller bindings | |
| 2 | + | |
| 3 | +HOST OS userland running on ARM can send interrupts to DSP cores using | |
| 4 | +the DSP GPIO controller IP. It provides 28 IRQ signals per each DSP core. | |
| 5 | +This is one of the component used by the IPC mechanism used on Keystone SOCs. | |
| 6 | + | |
| 7 | +For example TCI6638K2K SoC has 8 DSP GPIO controllers: | |
| 8 | + - 8 for C66x CorePacx CPUs 0-7 | |
| 9 | + | |
| 10 | +Keystone 2 DSP GPIO controller has specific features: | |
| 11 | +- each GPIO can be configured only as output pin; | |
| 12 | +- setting GPIO value to 1 causes IRQ generation on target DSP core; | |
| 13 | +- reading pin value returns 0 - if IRQ was handled or 1 - IRQ is still | |
| 14 | + pending. | |
| 15 | + | |
| 16 | +Required Properties: | |
| 17 | +- compatible: should be "ti,keystone-dsp-gpio" | |
| 18 | +- ti,syscon-dev: phandle/offset pair. The phandle to syscon used to | |
| 19 | + access device state control registers and the offset of device's specific | |
| 20 | + registers within device state control registers range. | |
| 21 | +- gpio-controller: Marks the device node as a gpio controller. | |
| 22 | +- #gpio-cells: Should be 2. | |
| 23 | + | |
| 24 | +Please refer to gpio.txt in this directory for details of the common GPIO | |
| 25 | +bindings used by client devices. | |
| 26 | + | |
| 27 | +Example: | |
| 28 | + dspgpio0: keystone_dsp_gpio@02620240 { | |
| 29 | + compatible = "ti,keystone-dsp-gpio"; | |
| 30 | + ti,syscon-dev = <&devctrl 0x240>; | |
| 31 | + gpio-controller; | |
| 32 | + #gpio-cells = <2>; | |
| 33 | + }; | |
| 34 | + | |
| 35 | + dsp0: dsp0 { | |
| 36 | + compatible = "linux,rproc-user"; | |
| 37 | + ... | |
| 38 | + kick-gpio = <&dspgpio0 27>; | |
| 39 | + }; | |
| @@ -0,0 +1,39 @@ | ||
| 1 | +* NXP PCA953x I2C GPIO multiplexer | |
| 2 | + | |
| 3 | +Required properties: | |
| 4 | + - compatible: Has to contain one of the following: | |
| 5 | + nxp,pca9505 | |
| 6 | + nxp,pca9534 | |
| 7 | + nxp,pca9535 | |
| 8 | + nxp,pca9536 | |
| 9 | + nxp,pca9537 | |
| 10 | + nxp,pca9538 | |
| 11 | + nxp,pca9539 | |
| 12 | + nxp,pca9554 | |
| 13 | + nxp,pca9555 | |
| 14 | + nxp,pca9556 | |
| 15 | + nxp,pca9557 | |
| 16 | + nxp,pca9574 | |
| 17 | + nxp,pca9575 | |
| 18 | + nxp,pca9698 | |
| 19 | + maxim,max7310 | |
| 20 | + maxim,max7312 | |
| 21 | + maxim,max7313 | |
| 22 | + maxim,max7315 | |
| 23 | + ti,pca6107 | |
| 24 | + ti,tca6408 | |
| 25 | + ti,tca6416 | |
| 26 | + ti,tca6424 | |
| 27 | + exar,xra1202 | |
| 28 | + | |
| 29 | +Example: | |
| 30 | + | |
| 31 | + | |
| 32 | + gpio@20 { | |
| 33 | + compatible = "nxp,pca9505"; | |
| 34 | + reg = <0x20>; | |
| 35 | + pinctrl-names = "default"; | |
| 36 | + pinctrl-0 = <&pinctrl_pca9505>; | |
| 37 | + interrupt-parent = <&gpio3>; | |
| 38 | + interrupts = <23 IRQ_TYPE_LEVEL_LOW>; | |
| 39 | + }; | |
| @@ -0,0 +1,22 @@ | ||
| 1 | +APM X-Gene SoC GPIO controller bindings | |
| 2 | + | |
| 3 | +This is a gpio controller that is part of the flash controller. | |
| 4 | +This gpio controller controls a total of 48 gpios. | |
| 5 | + | |
| 6 | +Required properties: | |
| 7 | +- compatible: "apm,xgene-gpio" for X-Gene GPIO controller | |
| 8 | +- reg: Physical base address and size of the controller's registers | |
| 9 | +- #gpio-cells: Should be two. | |
| 10 | + - first cell is the pin number | |
| 11 | + - second cell is used to specify the gpio polarity: | |
| 12 | + 0 = active high | |
| 13 | + 1 = active low | |
| 14 | +- gpio-controller: Marks the device node as a GPIO controller. | |
| 15 | + | |
| 16 | +Example: | |
| 17 | + gpio0: gpio0@1701c000 { | |
| 18 | + compatible = "apm,xgene-gpio"; | |
| 19 | + reg = <0x0 0x1701c000 0x0 0x40>; | |
| 20 | + gpio-controller; | |
| 21 | + #gpio-cells = <2>; | |
| 22 | + }; | |
| @@ -19,7 +19,7 @@ Required properties: · 18 unmodified lines | ||
| 19 | 19 | - gpio-controller : Marks the device node as a gpio controller. |
| 20 | 20 | - #gpio-cells : Should be one. It is the pin number. |
| 21 | 21 | |
| 22 | −Example: | |
| 22 | +Example for a MMP platform: | |
| 23 | 23 | |
| 24 | 24 | gpio: gpio@d4019000 { |
| 25 | 25 | compatible = "marvell,mmp-gpio"; |
| @@ -32,6 +32,19 @@ Example: · 6 unmodified lines | ||
| 32 | 32 | #interrupt-cells = <1>; |
| 33 | 33 | }; |
| 34 | 34 | |
| 35 | +Example for a PXA3xx platform: | |
| 36 | + | |
| 37 | + gpio: gpio@40e00000 { | |
| 38 | + compatible = "intel,pxa3xx-gpio"; | |
| 39 | + reg = <0x40e00000 0x10000>; | |
| 40 | + interrupt-names = "gpio0", "gpio1", "gpio_mux"; | |
| 41 | + interrupts = <8 9 10>; | |
| 42 | + gpio-controller; | |
| 43 | + #gpio-cells = <0x2>; | |
| 44 | + interrupt-controller; | |
| 45 | + #interrupt-cells = <0x2>; | |
| 46 | + }; | |
| 47 | + | |
| 35 | 48 | * Marvell Orion GPIO Controller |
| 36 | 49 | |
| 37 | 50 | Required properties: |
| @@ -124,7 +124,8 @@ symbol: · 123 unmodified lines | ||
| 124 | 124 | * gpiochip_set_chained_irqchip(): sets up a chained irq handler for a |
| 125 | 125 | gpio_chip from a parent IRQ and passes the struct gpio_chip* as handler |
| 126 | 126 | data. (Notice handler data, since the irqchip data is likely used by the |
| 127 | − parent irqchip!) This is for the chained type of chip. | |
| 127 | + parent irqchip!) This is for the chained type of chip. This is also used | |
| 128 | + to set up a nested irqchip if NULL is passed as handler. | |
| 128 | 129 | |
| 129 | 130 | To use the helpers please keep the following in mind: |
| 130 | 131 | |
| @@ -178,7 +179,8 @@ does not help since it pins the module to the kernel forever (it calls · 47 unmodified lines | ||
| 178 | 179 | try_module_get()). A GPIO driver can use the following functions instead |
| 179 | 180 | to request and free descriptors without being pinned to the kernel forever. |
| 180 | 181 | |
| 181 | − int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label) | |
| 182 | + struct gpio_desc *gpiochip_request_own_desc(struct gpio_desc *desc, | |
| 183 | + const char *label) | |
| 182 | 184 | |
| 183 | 185 | void gpiochip_free_own_desc(struct gpio_desc *desc) |
| 184 | 186 | |
| @@ -243,18 +243,12 @@ err_ioremap: · 242 unmodified lines | ||
| 243 | 243 | static int scoop_remove(struct platform_device *pdev) |
| 244 | 244 | { |
| 245 | 245 | struct scoop_dev *sdev = platform_get_drvdata(pdev); |
| 246 | − int ret; | |
| 247 | 246 | |
| 248 | 247 | if (!sdev) |
| 249 | 248 | return -EINVAL; |
| 250 | 249 | |
| 251 | − if (sdev->gpio.base != -1) { | |
| 252 | − ret = gpiochip_remove(&sdev->gpio); | |
| 253 | − if (ret) { | |
| 254 | − dev_err(&pdev->dev, "Can't remove gpio chip: %d\n", ret); | |
| 255 | − return ret; | |
| 256 | − } | |
| 257 | − } | |
| 250 | + if (sdev->gpio.base != -1) | |
| 251 | + gpiochip_remove(&sdev->gpio); | |
| 258 | 252 | |
| 259 | 253 | platform_set_drvdata(pdev, NULL); |
| 260 | 254 | iounmap(sdev->base); |
| @@ -789,11 +789,11 @@ void __init txx9_iocled_init(unsigned long baseaddr, · 788 unmodified lines | ||
| 789 | 789 | if (platform_device_add(pdev)) |
| 790 | 790 | goto out_pdev; |
| 791 | 791 | return; |
| 792 | + | |
| 792 | 793 | out_pdev: |
| 793 | 794 | platform_device_put(pdev); |
| 794 | 795 | out_gpio: |
| 795 | − if (gpiochip_remove(&iocled->chip)) | |
| 796 | − return; | |
| 796 | + gpiochip_remove(&iocled->chip); | |
| 797 | 797 | out_unmap: |
| 798 | 798 | iounmap(iocled->mmioaddr); |
| 799 | 799 | out_free: |
| @@ -141,7 +141,8 @@ static int mcu_gpiochip_add(struct mcu *mcu) · 140 unmodified lines | ||
| 141 | 141 | |
| 142 | 142 | static int mcu_gpiochip_remove(struct mcu *mcu) |
| 143 | 143 | { |
| 144 | − return gpiochip_remove(&mcu->gc); | |
| 144 | + gpiochip_remove(&mcu->gc); | |
| 145 | + return 0; | |
| 145 | 146 | } |
| 146 | 147 | |
| 147 | 148 | static int mcu_probe(struct i2c_client *client, const struct i2c_device_id *id) |
| @@ -128,10 +128,8 @@ int __init x3proto_gpio_setup(void) · 127 unmodified lines | ||
| 128 | 128 | return 0; |
| 129 | 129 | |
| 130 | 130 | err_irq: |
| 131 | − ret = gpiochip_remove(&x3proto_gpio_chip); | |
| 132 | − if (unlikely(ret)) | |
| 133 | − pr_err("Failed deregistering GPIO\n"); | |
| 134 | − | |
| 131 | + gpiochip_remove(&x3proto_gpio_chip); | |
| 132 | + ret = 0; | |
| 135 | 133 | err_gpio: |
| 136 | 134 | synchronize_irq(ilsel); |
| 137 | 135 | |
| @@ -255,5 +255,6 @@ int bcma_gpio_init(struct bcma_drv_cc *cc) · 254 unmodified lines | ||
| 255 | 255 | int bcma_gpio_unregister(struct bcma_drv_cc *cc) |
| 256 | 256 | { |
| 257 | 257 | bcma_gpio_irq_domain_exit(cc); |
| 258 | − return gpiochip_remove(&cc->gpio); | |
| 258 | + gpiochip_remove(&cc->gpio); | |
| 259 | + return 0; | |
| 259 | 260 | } |
| @@ -136,7 +136,6 @@ config GPIO_DWAPB · 135 unmodified lines | ||
| 136 | 136 | tristate "Synopsys DesignWare APB GPIO driver" |
| 137 | 137 | select GPIO_GENERIC |
| 138 | 138 | select GENERIC_IRQ_CHIP |
| 139 | − depends on OF_GPIO | |
| 140 | 139 | help |
| 141 | 140 | Say Y or M here to build support for the Synopsys DesignWare APB |
| 142 | 141 | GPIO block. |
| @@ -334,6 +333,15 @@ config GPIO_TZ1090_PDC · 191 unmodified lines | ||
| 334 | 333 | help |
| 335 | 334 | Say yes here to support Toumaz Xenif TZ1090 PDC GPIOs. |
| 336 | 335 | |
| 336 | +config GPIO_XGENE | |
| 337 | + bool "APM X-Gene GPIO controller support" | |
| 338 | + depends on ARM64 && OF_GPIO | |
| 339 | + help | |
| 340 | + This driver is to support the GPIO block within the APM X-Gene SoC | |
| 341 | + platform's generic flash controller. The GPIO pins are muxed with | |
| 342 | + the generic flash controller's address and data pins. Say yes | |
| 343 | + here to enable the GFC GPIO functionality. | |
| 344 | + | |
| 337 | 345 | config GPIO_XILINX |
| 338 | 346 | bool "Xilinx GPIO support" |
| 339 | 347 | depends on PPC_OF || MICROBLAZE || ARCH_ZYNQ |
| @@ -681,6 +689,7 @@ config GPIO_ADP5588_IRQ · 341 unmodified lines | ||
| 681 | 689 | config GPIO_ADNP |
| 682 | 690 | tristate "Avionic Design N-bit GPIO expander" |
| 683 | 691 | depends on I2C && OF_GPIO |
| 692 | + select GPIOLIB_IRQCHIP | |
| 684 | 693 | help |
| 685 | 694 | This option enables support for N GPIOs found on Avionic Design |
| 686 | 695 | I2C GPIO expanders. The register space will be extended by powers |
| @@ -796,7 +805,6 @@ config GPIO_MAX7301 · 109 unmodified lines | ||
| 796 | 805 | |
| 797 | 806 | config GPIO_MCP23S08 |
| 798 | 807 | tristate "Microchip MCP23xxx I/O expander" |
| 799 | − depends on OF_GPIO | |
| 800 | 808 | depends on (SPI_MASTER && !I2C) || I2C |
| 801 | 809 | help |
| 802 | 810 | SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017 |
| @@ -880,7 +888,7 @@ config GPIO_MSIC · 77 unmodified lines | ||
| 880 | 888 | |
| 881 | 889 | config GPIO_BCM_KONA |
| 882 | 890 | bool "Broadcom Kona GPIO" |
| 883 | − depends on OF_GPIO | |
| 891 | + depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST) | |
| 884 | 892 | help |
| 885 | 893 | Turn on GPIO support for Broadcom "Kona" chips. |
| 886 | 894 | |
| @@ -101,6 +101,7 @@ obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o · 100 unmodified lines | ||
| 101 | 101 | obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o |
| 102 | 102 | obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o |
| 103 | 103 | obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o |
| 104 | +obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o | |
| 104 | 105 | obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o |
| 105 | 106 | obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o |
| 106 | 107 | obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o |
| @@ -6,10 +6,9 @@ · 5 unmodified lines | ||
| 6 | 6 | * published by the Free Software Foundation. |
| 7 | 7 | */ |
| 8 | 8 | |
| 9 | −#include <linux/gpio.h> | |
| 9 | +#include <linux/gpio/driver.h> | |
| 10 | 10 | #include <linux/i2c.h> |
| 11 | 11 | #include <linux/interrupt.h> |
| 12 | −#include <linux/irqdomain.h> | |
| 13 | 12 | #include <linux/module.h> |
| 14 | 13 | #include <linux/of_irq.h> |
| 15 | 14 | #include <linux/seq_file.h> |
| @@ -27,8 +26,6 @@ struct adnp { · 11 unmodified lines | ||
| 27 | 26 | unsigned int reg_shift; |
| 28 | 27 | |
| 29 | 28 | struct mutex i2c_lock; |
| 30 | − | |
| 31 | − struct irq_domain *domain; | |
| 32 | 29 | struct mutex irq_lock; |
| 33 | 30 | |
| 34 | 31 | u8 *irq_enable; |
| @@ -253,6 +250,7 @@ static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) · 218 unmodified lines | ||
| 253 | 250 | static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios) |
| 254 | 251 | { |
| 255 | 252 | struct gpio_chip *chip = &adnp->gpio; |
| 253 | + int err; | |
| 256 | 254 | |
| 257 | 255 | adnp->reg_shift = get_count_order(num_gpios) - 3; |
| 258 | 256 | |
| @@ -272,6 +270,10 @@ static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios) · 13 unmodified lines | ||
| 272 | 270 | chip->of_node = chip->dev->of_node; |
| 273 | 271 | chip->owner = THIS_MODULE; |
| 274 | 272 | |
| 273 | + err = gpiochip_add(chip); | |
| 274 | + if (err) | |
| 275 | + return err; | |
| 276 | + | |
| 275 | 277 | return 0; |
| 276 | 278 | } |
| 277 | 279 | |
| @@ -326,7 +328,8 @@ static irqreturn_t adnp_irq(int irq, void *data) · 48 unmodified lines | ||
| 326 | 328 | |
| 327 | 329 | for_each_set_bit(bit, &pending, 8) { |
| 328 | 330 | unsigned int child_irq; |
| 329 | − child_irq = irq_find_mapping(adnp->domain, base + bit); | |
| 331 | + child_irq = irq_find_mapping(adnp->gpio.irqdomain, | |
| 332 | + base + bit); | |
| 330 | 333 | handle_nested_irq(child_irq); |
| 331 | 334 | } |
| 332 | 335 | } |
| @@ -334,35 +337,32 @@ static irqreturn_t adnp_irq(int irq, void *data) · 1 unmodified line | ||
| 334 | 337 | return IRQ_HANDLED; |
| 335 | 338 | } |
| 336 | 339 | |
| 337 | −static int adnp_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |
| 338 | −{ | |
| 339 | − struct adnp *adnp = to_adnp(chip); | |
| 340 | − return irq_create_mapping(adnp->domain, offset); | |
| 341 | −} | |
| 342 | − | |
| 343 | −static void adnp_irq_mask(struct irq_data *data) | |
| 340 | +static void adnp_irq_mask(struct irq_data *d) | |
| 344 | 341 | { |
| 345 | − struct adnp *adnp = irq_data_get_irq_chip_data(data); | |
| 346 | − unsigned int reg = data->hwirq >> adnp->reg_shift; | |
| 347 | − unsigned int pos = data->hwirq & 7; | |
| 342 | + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | |
| 343 | + struct adnp *adnp = to_adnp(gc); | |
| 344 | + unsigned int reg = d->hwirq >> adnp->reg_shift; | |
| 345 | + unsigned int pos = d->hwirq & 7; | |
| 348 | 346 | |
| 349 | 347 | adnp->irq_enable[reg] &= ~BIT(pos); |
| 350 | 348 | } |
| 351 | 349 | |
| 352 | −static void adnp_irq_unmask(struct irq_data *data) | |
| 350 | +static void adnp_irq_unmask(struct irq_data *d) | |
| 353 | 351 | { |
| 354 | − struct adnp *adnp = irq_data_get_irq_chip_data(data); | |
| 355 | − unsigned int reg = data->hwirq >> adnp->reg_shift; | |
| 356 | − unsigned int pos = data->hwirq & 7; | |
| 352 | + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | |
| 353 | + struct adnp *adnp = to_adnp(gc); | |
| 354 | + unsigned int reg = d->hwirq >> adnp->reg_shift; | |
| 355 | + unsigned int pos = d->hwirq & 7; | |
| 357 | 356 | |
| 358 | 357 | adnp->irq_enable[reg] |= BIT(pos); |
| 359 | 358 | } |
| 360 | 359 | |
| 361 | −static int adnp_irq_set_type(struct irq_data *data, unsigned int type) | |
| 360 | +static int adnp_irq_set_type(struct irq_data *d, unsigned int type) | |
| 362 | 361 | { |
| 363 | − struct adnp *adnp = irq_data_get_irq_chip_data(data); | |
| 364 | − unsigned int reg = data->hwirq >> adnp->reg_shift; | |
| 365 | − unsigned int pos = data->hwirq & 7; | |
| 362 | + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | |
| 363 | + struct adnp *adnp = to_adnp(gc); | |
| 364 | + unsigned int reg = d->hwirq >> adnp->reg_shift; | |
| 365 | + unsigned int pos = d->hwirq & 7; | |
| 366 | 366 | |
| 367 | 367 | if (type & IRQ_TYPE_EDGE_RISING) |
| 368 | 368 | adnp->irq_rise[reg] |= BIT(pos); |
| @@ -387,16 +387,18 @@ static int adnp_irq_set_type(struct irq_data *data, unsigned int type) · 18 unmodified lines | ||
| 387 | 387 | return 0; |
| 388 | 388 | } |
| 389 | 389 | |
| 390 | −static void adnp_irq_bus_lock(struct irq_data *data) | |
| 390 | +static void adnp_irq_bus_lock(struct irq_data *d) | |
| 391 | 391 | { |
| 392 | − struct adnp *adnp = irq_data_get_irq_chip_data(data); | |
| 392 | + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | |
| 393 | + struct adnp *adnp = to_adnp(gc); | |
| 393 | 394 | |
| 394 | 395 | mutex_lock(&adnp->irq_lock); |
| 395 | 396 | } |
| 396 | 397 | |
| 397 | −static void adnp_irq_bus_unlock(struct irq_data *data) | |
| 398 | +static void adnp_irq_bus_unlock(struct irq_data *d) | |
| 398 | 399 | { |
| 399 | − struct adnp *adnp = irq_data_get_irq_chip_data(data); | |
| 400 | + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | |
| 401 | + struct adnp *adnp = to_adnp(gc); | |
| 400 | 402 | unsigned int num_regs = 1 << adnp->reg_shift, i; |
| 401 | 403 | |
| 402 | 404 | mutex_lock(&adnp->i2c_lock); |
| @@ -408,26 +410,6 @@ static void adnp_irq_bus_unlock(struct irq_data *data) · 5 unmodified lines | ||
| 408 | 410 | mutex_unlock(&adnp->irq_lock); |
| 409 | 411 | } |
| 410 | 412 | |
| 411 | −static int adnp_irq_reqres(struct irq_data *data) | |
| 412 | −{ | |
| 413 | − struct adnp *adnp = irq_data_get_irq_chip_data(data); | |
| 414 | − | |
| 415 | − if (gpio_lock_as_irq(&adnp->gpio, data->hwirq)) { | |
| 416 | − dev_err(adnp->gpio.dev, | |
| 417 | − "unable to lock HW IRQ %lu for IRQ\n", | |
| 418 | − data->hwirq); | |
| 419 | − return -EINVAL; | |
| 420 | − } | |
| 421 | − return 0; | |
| 422 | −} | |
| 423 | − | |
| 424 | −static void adnp_irq_relres(struct irq_data *data) | |
| 425 | −{ | |
| 426 | − struct adnp *adnp = irq_data_get_irq_chip_data(data); | |
| 427 | − | |
| 428 | − gpio_unlock_as_irq(&adnp->gpio, data->hwirq); | |
| 429 | −} | |
| 430 | − | |
| 431 | 413 | static struct irq_chip adnp_irq_chip = { |
| 432 | 414 | .name = "gpio-adnp", |
| 433 | 415 | .irq_mask = adnp_irq_mask, |
| @@ -435,29 +417,6 @@ static struct irq_chip adnp_irq_chip = { · 1 unmodified line | ||
| 435 | 417 | .irq_set_type = adnp_irq_set_type, |
| 436 | 418 | .irq_bus_lock = adnp_irq_bus_lock, |
| 437 | 419 | .irq_bus_sync_unlock = adnp_irq_bus_unlock, |
| 438 | − .irq_request_resources = adnp_irq_reqres, | |
| 439 | − .irq_release_resources = adnp_irq_relres, | |
| 440 | −}; | |
| 441 | − | |
| 442 | −static int adnp_irq_map(struct irq_domain *domain, unsigned int irq, | |
| 443 | − irq_hw_number_t hwirq) | |
| 444 | −{ | |
| 445 | − irq_set_chip_data(irq, domain->host_data); | |
| 446 | − irq_set_chip(irq, &adnp_irq_chip); | |
| 447 | − irq_set_nested_thread(irq, true); | |
| 448 | − | |
| 449 | −#ifdef CONFIG_ARM | |
| 450 | − set_irq_flags(irq, IRQF_VALID); | |
| 451 | −#else | |
| 452 | − irq_set_noprobe(irq); | |
| 453 | −#endif | |
| 454 | − | |
| 455 | − return 0; | |
| 456 | −} | |
| 457 | − | |
| 458 | −static const struct irq_domain_ops adnp_irq_domain_ops = { | |
| 459 | − .map = adnp_irq_map, | |
| 460 | − .xlate = irq_domain_xlate_twocell, | |
| 461 | 420 | }; |
| 462 | 421 | |
| 463 | 422 | static int adnp_irq_setup(struct adnp *adnp) |
| @@ -503,35 +462,28 @@ static int adnp_irq_setup(struct adnp *adnp) · 39 unmodified lines | ||
| 503 | 462 | adnp->irq_enable[i] = 0x00; |
| 504 | 463 | } |
| 505 | 464 | |
| 506 | − adnp->domain = irq_domain_add_linear(chip->of_node, chip->ngpio, | |
| 507 | − &adnp_irq_domain_ops, adnp); | |
| 508 | − | |
| 509 | − err = request_threaded_irq(adnp->client->irq, NULL, adnp_irq, | |
| 510 | − IRQF_TRIGGER_RISING | IRQF_ONESHOT, | |
| 511 | − dev_name(chip->dev), adnp); | |
| 465 | + err = devm_request_threaded_irq(chip->dev, adnp->client->irq, | |
| 466 | + NULL, adnp_irq, | |
| 467 | + IRQF_TRIGGER_RISING | IRQF_ONESHOT, | |
| 468 | + dev_name(chip->dev), adnp); | |
| 512 | 469 | if (err != 0) { |
| 513 | 470 | dev_err(chip->dev, "can't request IRQ#%d: %d\n", |
| 514 | 471 | adnp->client->irq, err); |
| 515 | 472 | return err; |
| 516 | 473 | } |
| 517 | 474 | |
| 518 | − chip->to_irq = adnp_gpio_to_irq; | |
| 519 | − return 0; | |
| 520 | −} | |
| 521 | − | |
| 522 | −static void adnp_irq_teardown(struct adnp *adnp) | |
| 523 | −{ | |
| 524 | − unsigned int irq, i; | |
| 525 | − | |
| 526 | − free_irq(adnp->client->irq, adnp); | |
| 527 | − | |
| 528 | − for (i = 0; i < adnp->gpio.ngpio; i++) { | |
| 529 | − irq = irq_find_mapping(adnp->domain, i); | |
| 530 | − if (irq > 0) | |
| 531 | − irq_dispose_mapping(irq); | |
| 475 | + err = gpiochip_irqchip_add(chip, | |
| 476 | + &adnp_irq_chip, | |
| 477 | + 0, | |
| 478 | + handle_simple_irq, | |
| 479 | + IRQ_TYPE_NONE); | |
| 480 | + if (err) { | |
| 481 | + dev_err(chip->dev, | |
| 482 | + "could not connect irqchip to gpiochip\n"); | |
| 483 | + return err; | |
| 532 | 484 | } |
| 533 | 485 | |
| 534 | − irq_domain_remove(adnp->domain); | |
| 486 | + return 0; | |
| 535 | 487 | } |
| 536 | 488 | |
| 537 | 489 | static int adnp_i2c_probe(struct i2c_client *client, |
| @@ -558,38 +510,25 @@ static int adnp_i2c_probe(struct i2c_client *client, · 20 unmodified lines | ||
| 558 | 510 | adnp->client = client; |
| 559 | 511 | |
| 560 | 512 | err = adnp_gpio_setup(adnp, num_gpios); |
| 561 | − if (err < 0) | |
| 513 | + if (err) | |
| 562 | 514 | return err; |
| 563 | 515 | |
| 564 | 516 | if (of_find_property(np, "interrupt-controller", NULL)) { |
| 565 | 517 | err = adnp_irq_setup(adnp); |
| 566 | − if (err < 0) | |
| 567 | − goto teardown; | |
| 518 | + if (err) | |
| 519 | + return err; | |
| 568 | 520 | } |
| 569 | 521 | |
| 570 | − err = gpiochip_add(&adnp->gpio); | |
| 571 | − if (err < 0) | |
| 572 | − goto teardown; | |
| 573 | − | |
| 574 | 522 | i2c_set_clientdata(client, adnp); |
| 575 | − return 0; | |
| 576 | 523 | |
| 577 | −teardown: | |
| 578 | − if (of_find_property(np, "interrupt-controller", NULL)) | |
| 579 | − adnp_irq_teardown(adnp); | |
| 580 | − | |
| 581 | − return err; | |
| 524 | + return 0; | |
| 582 | 525 | } |
| 583 | 526 | |
| 584 | 527 | static int adnp_i2c_remove(struct i2c_client *client) |
| 585 | 528 | { |
| 586 | 529 | struct adnp *adnp = i2c_get_clientdata(client); |
| 587 | − struct device_node *np = client->dev.of_node; | |
| 588 | 530 | |
| 589 | 531 | gpiochip_remove(&adnp->gpio); |
| 590 | − if (of_find_property(np, "interrupt-controller", NULL)) | |
| 591 | − adnp_irq_teardown(adnp); | |
| 592 | − | |
| 593 | 532 | return 0; |
| 594 | 533 | } |
| 595 | 534 | |
| @@ -496,7 +496,7 @@ static struct irq_chip bcm_gpio_irq_chip = { · 495 unmodified lines | ||
| 496 | 496 | .irq_release_resources = bcm_kona_gpio_irq_relres, |
| 497 | 497 | }; |
| 498 | 498 | |
| 499 | −static struct __initconst of_device_id bcm_kona_gpio_of_match[] = { | |
| 499 | +static struct of_device_id const bcm_kona_gpio_of_match[] = { | |
| 500 | 500 | { .compatible = "brcm,kona-gpio" }, |
| 501 | 501 | {} |
| 502 | 502 | }; |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #include <linux/mfd/intel_soc_pmic.h> |
| 25 | 25 | |
| 26 | 26 | #define CRYSTALCOVE_GPIO_NUM 16 |
| 27 | +#define CRYSTALCOVE_VGPIO_NUM 94 | |
| 27 | 28 | |
| 28 | 29 | #define UPDATE_IRQ_TYPE BIT(0) |
| 29 | 30 | #define UPDATE_IRQ_MASK BIT(1) |
| @@ -130,6 +131,9 @@ static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio) · 100 unmodified lines | ||
| 130 | 131 | { |
| 131 | 132 | struct crystalcove_gpio *cg = to_cg(chip); |
| 132 | 133 | |
| 134 | + if (gpio > CRYSTALCOVE_VGPIO_NUM) | |
| 135 | + return 0; | |
| 136 | + | |
| 133 | 137 | return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT), |
| 134 | 138 | CTLO_INPUT_SET); |
| 135 | 139 | } |
| @@ -139,6 +143,9 @@ static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio, · 3 unmodified lines | ||
| 139 | 143 | { |
| 140 | 144 | struct crystalcove_gpio *cg = to_cg(chip); |
| 141 | 145 | |
| 146 | + if (gpio > CRYSTALCOVE_VGPIO_NUM) | |
| 147 | + return 0; | |
| 148 | + | |
| 142 | 149 | return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT), |
| 143 | 150 | CTLO_OUTPUT_SET | value); |
| 144 | 151 | } |
| @@ -149,6 +156,9 @@ static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio) · 4 unmodified lines | ||
| 149 | 156 | int ret; |
| 150 | 157 | unsigned int val; |
| 151 | 158 | |
| 159 | + if (gpio > CRYSTALCOVE_VGPIO_NUM) | |
| 160 | + return 0; | |
| 161 | + | |
| 152 | 162 | ret = regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &val); |
| 153 | 163 | if (ret) |
| 154 | 164 | return ret; |
| @@ -161,6 +171,9 @@ static void crystalcove_gpio_set(struct gpio_chip *chip, · 6 unmodified lines | ||
| 161 | 171 | { |
| 162 | 172 | struct crystalcove_gpio *cg = to_cg(chip); |
| 163 | 173 | |
| 174 | + if (gpio > CRYSTALCOVE_VGPIO_NUM) | |
| 175 | + return; | |
| 176 | + | |
| 164 | 177 | if (value) |
| 165 | 178 | regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 1); |
| 166 | 179 | else |
| @@ -256,7 +269,7 @@ static irqreturn_t crystalcove_gpio_irq_handler(int irq, void *data) · 89 unmodified lines | ||
| 256 | 269 | |
| 257 | 270 | pending = p0 | p1 << 8; |
| 258 | 271 | |
| 259 | − for (gpio = 0; gpio < cg->chip.ngpio; gpio++) { | |
| 272 | + for (gpio = 0; gpio < CRYSTALCOVE_GPIO_NUM; gpio++) { | |
| 260 | 273 | if (pending & BIT(gpio)) { |
| 261 | 274 | virq = irq_find_mapping(cg->chip.irqdomain, gpio); |
| 262 | 275 | generic_handle_irq(virq); |
| @@ -273,7 +286,7 @@ static void crystalcove_gpio_dbg_show(struct seq_file *s, · 10 unmodified lines | ||
| 273 | 286 | int gpio, offset; |
| 274 | 287 | unsigned int ctlo, ctli, mirqs0, mirqsx, irq; |
| 275 | 288 | |
| 276 | − for (gpio = 0; gpio < cg->chip.ngpio; gpio++) { | |
| 289 | + for (gpio = 0; gpio < CRYSTALCOVE_GPIO_NUM; gpio++) { | |
| 277 | 290 | regmap_read(cg->regmap, to_reg(gpio, CTRL_OUT), &ctlo); |
| 278 | 291 | regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &ctli); |
| 279 | 292 | regmap_read(cg->regmap, gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0, |
| @@ -320,7 +333,7 @@ static int crystalcove_gpio_probe(struct platform_device *pdev) · 40 unmodified lines | ||
| 320 | 333 | cg->chip.get = crystalcove_gpio_get; |
| 321 | 334 | cg->chip.set = crystalcove_gpio_set; |
| 322 | 335 | cg->chip.base = -1; |
| 323 | − cg->chip.ngpio = CRYSTALCOVE_GPIO_NUM; | |
| 336 | + cg->chip.ngpio = CRYSTALCOVE_VGPIO_NUM; | |
| 324 | 337 | cg->chip.can_sleep = true; |
| 325 | 338 | cg->chip.dev = dev; |
| 326 | 339 | cg->chip.dbg_show = crystalcove_gpio_dbg_show; |
| @@ -346,7 +359,7 @@ static int crystalcove_gpio_probe(struct platform_device *pdev) · 19 unmodified lines | ||
| 346 | 359 | return 0; |
| 347 | 360 | |
| 348 | 361 | out_remove_gpio: |
| 349 | − WARN_ON(gpiochip_remove(&cg->chip)); | |
| 362 | + gpiochip_remove(&cg->chip); | |
| 350 | 363 | return retval; |
| 351 | 364 | } |
| 352 | 365 | |
| @@ -354,14 +367,11 @@ static int crystalcove_gpio_remove(struct platform_device *pdev) · 1 unmodified line | ||
| 354 | 367 | { |
| 355 | 368 | struct crystalcove_gpio *cg = platform_get_drvdata(pdev); |
| 356 | 369 | int irq = platform_get_irq(pdev, 0); |
| 357 | − int err; | |
| 358 | − | |
| 359 | − err = gpiochip_remove(&cg->chip); | |
| 360 | 370 | |
| 371 | + gpiochip_remove(&cg->chip); | |
| 361 | 372 | if (irq >= 0) |
| 362 | 373 | free_irq(irq, cg); |
| 363 | − | |
| 364 | − return err; | |
| 374 | + return 0; | |
| 365 | 375 | } |
| 366 | 376 | |
| 367 | 377 | static struct platform_driver crystalcove_gpio_driver = { |
| @@ -201,7 +201,8 @@ EXPORT_SYMBOL_GPL(cs5535_gpio_setup_event); · 200 unmodified lines | ||
| 201 | 201 | |
| 202 | 202 | static int chip_gpio_request(struct gpio_chip *c, unsigned offset) |
| 203 | 203 | { |
| 204 | − struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c; | |
| 204 | + struct cs5535_gpio_chip *chip = | |
| 205 | + container_of(c, struct cs5535_gpio_chip, chip); | |
| 205 | 206 | unsigned long flags; |
| 206 | 207 | |
| 207 | 208 | spin_lock_irqsave(&chip->lock, flags); |
| @@ -241,7 +242,8 @@ static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val) · 33 unmodified lines | ||
| 241 | 242 | |
| 242 | 243 | static int chip_direction_input(struct gpio_chip *c, unsigned offset) |
| 243 | 244 | { |
| 244 | − struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c; | |
| 245 | + struct cs5535_gpio_chip *chip = | |
| 246 | + container_of(c, struct cs5535_gpio_chip, chip); | |
| 245 | 247 | unsigned long flags; |
| 246 | 248 | |
| 247 | 249 | spin_lock_irqsave(&chip->lock, flags); |
| @@ -254,7 +256,8 @@ static int chip_direction_input(struct gpio_chip *c, unsigned offset) · 6 unmodified lines | ||
| 254 | 256 | |
| 255 | 257 | static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val) |
| 256 | 258 | { |
| 257 | − struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c; | |
| 259 | + struct cs5535_gpio_chip *chip = | |
| 260 | + container_of(c, struct cs5535_gpio_chip, chip); | |
| 258 | 261 | unsigned long flags; |
| 259 | 262 | |
| 260 | 263 | spin_lock_irqsave(&chip->lock, flags); |
| @@ -21,6 +21,8 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/of_irq.h> |
| 22 | 22 | #include <linux/platform_device.h> |
| 23 | 23 | #include <linux/spinlock.h> |
| 24 | +#include <linux/platform_data/gpio-dwapb.h> | |
| 25 | +#include <linux/slab.h> | |
| 24 | 26 | |
| 25 | 27 | #define GPIO_SWPORTA_DR 0x00 |
| 26 | 28 | #define GPIO_SWPORTA_DDR 0x04 |
| @@ -35,6 +37,7 @@ · 8 unmodified lines | ||
| 35 | 37 | #define GPIO_INTTYPE_LEVEL 0x38 |
| 36 | 38 | #define GPIO_INT_POLARITY 0x3c |
| 37 | 39 | #define GPIO_INTSTATUS 0x40 |
| 40 | +#define GPIO_PORTA_DEBOUNCE 0x48 | |
| 38 | 41 | #define GPIO_PORTA_EOI 0x4c |
| 39 | 42 | #define GPIO_EXT_PORTA 0x50 |
| 40 | 43 | #define GPIO_EXT_PORTB 0x54 |
| @@ -48,10 +51,28 @@ · 7 unmodified lines | ||
| 48 | 51 | |
| 49 | 52 | struct dwapb_gpio; |
| 50 | 53 | |
| 54 | +#ifdef CONFIG_PM_SLEEP | |
| 55 | +/* Store GPIO context across system-wide suspend/resume transitions */ | |
| 56 | +struct dwapb_context { | |
| 57 | + u32 data; | |
| 58 | + u32 dir; | |
| 59 | + u32 ext; | |
| 60 | + u32 int_en; | |
| 61 | + u32 int_mask; | |
| 62 | + u32 int_type; | |
| 63 | + u32 int_pol; | |
| 64 | + u32 int_deb; | |
| 65 | +}; | |
| 66 | +#endif | |
| 67 | + | |
| 51 | 68 | struct dwapb_gpio_port { |
| 52 | 69 | struct bgpio_chip bgc; |
| 53 | 70 | bool is_registered; |
| 54 | 71 | struct dwapb_gpio *gpio; |
| 72 | +#ifdef CONFIG_PM_SLEEP | |
| 73 | + struct dwapb_context *ctx; | |
| 74 | +#endif | |
| 75 | + unsigned int idx; | |
| 55 | 76 | }; |
| 56 | 77 | |
| 57 | 78 | struct dwapb_gpio { |
| @@ -62,11 +83,33 @@ struct dwapb_gpio { · 4 unmodified lines | ||
| 62 | 83 | struct irq_domain *domain; |
| 63 | 84 | }; |
| 64 | 85 | |
| 86 | +static inline struct dwapb_gpio_port * | |
| 87 | +to_dwapb_gpio_port(struct bgpio_chip *bgc) | |
| 88 | +{ | |
| 89 | + return container_of(bgc, struct dwapb_gpio_port, bgc); | |
| 90 | +} | |
| 91 | + | |
| 92 | +static inline u32 dwapb_read(struct dwapb_gpio *gpio, unsigned int offset) | |
| 93 | +{ | |
| 94 | + struct bgpio_chip *bgc = &gpio->ports[0].bgc; | |
| 95 | + void __iomem *reg_base = gpio->regs; | |
| 96 | + | |
| 97 | + return bgc->read_reg(reg_base + offset); | |
| 98 | +} | |
| 99 | + | |
| 100 | +static inline void dwapb_write(struct dwapb_gpio *gpio, unsigned int offset, | |
| 101 | + u32 val) | |
| 102 | +{ | |
| 103 | + struct bgpio_chip *bgc = &gpio->ports[0].bgc; | |
| 104 | + void __iomem *reg_base = gpio->regs; | |
| 105 | + | |
| 106 | + bgc->write_reg(reg_base + offset, val); | |
| 107 | +} | |
| 108 | + | |
| 65 | 109 | static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) |
| 66 | 110 | { |
| 67 | 111 | struct bgpio_chip *bgc = to_bgpio_chip(gc); |
| 68 | − struct dwapb_gpio_port *port = container_of(bgc, struct | |
| 69 | − dwapb_gpio_port, bgc); | |
| 112 | + struct dwapb_gpio_port *port = to_dwapb_gpio_port(bgc); | |
| 70 | 113 | struct dwapb_gpio *gpio = port->gpio; |
| 71 | 114 | |
| 72 | 115 | return irq_find_mapping(gpio->domain, offset); |
| @@ -74,21 +117,20 @@ static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) · 1 unmodified line | ||
| 74 | 117 | |
| 75 | 118 | static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs) |
| 76 | 119 | { |
| 77 | − u32 v = readl(gpio->regs + GPIO_INT_POLARITY); | |
| 120 | + u32 v = dwapb_read(gpio, GPIO_INT_POLARITY); | |
| 78 | 121 | |
| 79 | 122 | if (gpio_get_value(gpio->ports[0].bgc.gc.base + offs)) |
| 80 | 123 | v &= ~BIT(offs); |
| 81 | 124 | else |
| 82 | 125 | v |= BIT(offs); |
| 83 | 126 | |
| 84 | − writel(v, gpio->regs + GPIO_INT_POLARITY); | |
| 127 | + dwapb_write(gpio, GPIO_INT_POLARITY, v); | |
| 85 | 128 | } |
| 86 | 129 | |
| 87 | −static void dwapb_irq_handler(u32 irq, struct irq_desc *desc) | |
| 130 | +static u32 dwapb_do_irq(struct dwapb_gpio *gpio) | |
| 88 | 131 | { |
| 89 | − struct dwapb_gpio *gpio = irq_get_handler_data(irq); | |
| 90 | − struct irq_chip *chip = irq_desc_get_chip(desc); | |
| 91 | 132 | u32 irq_status = readl_relaxed(gpio->regs + GPIO_INTSTATUS); |
| 133 | + u32 ret = irq_status; | |
| 92 | 134 | |
| 93 | 135 | while (irq_status) { |
| 94 | 136 | int hwirq = fls(irq_status) - 1; |
| @@ -102,6 +144,16 @@ static void dwapb_irq_handler(u32 irq, struct irq_desc *desc) · 7 unmodified lines | ||
| 102 | 144 | dwapb_toggle_trigger(gpio, hwirq); |
| 103 | 145 | } |
| 104 | 146 | |
| 147 | + return ret; | |
| 148 | +} | |
| 149 | + | |
| 150 | +static void dwapb_irq_handler(u32 irq, struct irq_desc *desc) | |
| 151 | +{ | |
| 152 | + struct dwapb_gpio *gpio = irq_get_handler_data(irq); | |
| 153 | + struct irq_chip *chip = irq_desc_get_chip(desc); | |
| 154 | + | |
| 155 | + dwapb_do_irq(gpio); | |
| 156 | + | |
| 105 | 157 | if (chip->irq_eoi) |
| 106 | 158 | chip->irq_eoi(irq_desc_get_irq_data(desc)); |
| 107 | 159 | } |
| @@ -115,9 +167,9 @@ static void dwapb_irq_enable(struct irq_data *d) · 7 unmodified lines | ||
| 115 | 167 | u32 val; |
| 116 | 168 | |
| 117 | 169 | spin_lock_irqsave(&bgc->lock, flags); |
| 118 | − val = readl(gpio->regs + GPIO_INTEN); | |
| 170 | + val = dwapb_read(gpio, GPIO_INTEN); | |
| 119 | 171 | val |= BIT(d->hwirq); |
| 120 | − writel(val, gpio->regs + GPIO_INTEN); | |
| 172 | + dwapb_write(gpio, GPIO_INTEN, val); | |
| 121 | 173 | spin_unlock_irqrestore(&bgc->lock, flags); |
| 122 | 174 | } |
| 123 | 175 | |
| @@ -130,9 +182,9 @@ static void dwapb_irq_disable(struct irq_data *d) · 6 unmodified lines | ||
| 130 | 182 | u32 val; |
| 131 | 183 | |
| 132 | 184 | spin_lock_irqsave(&bgc->lock, flags); |
| 133 | − val = readl(gpio->regs + GPIO_INTEN); | |
| 185 | + val = dwapb_read(gpio, GPIO_INTEN); | |
| 134 | 186 | val &= ~BIT(d->hwirq); |
| 135 | − writel(val, gpio->regs + GPIO_INTEN); | |
| 187 | + dwapb_write(gpio, GPIO_INTEN, val); | |
| 136 | 188 | spin_unlock_irqrestore(&bgc->lock, flags); |
| 137 | 189 | } |
| 138 | 190 | |
| @@ -172,8 +224,8 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type) · 33 unmodified lines | ||
| 172 | 224 | return -EINVAL; |
| 173 | 225 | |
| 174 | 226 | spin_lock_irqsave(&bgc->lock, flags); |
| 175 | − level = readl(gpio->regs + GPIO_INTTYPE_LEVEL); | |
| 176 | − polarity = readl(gpio->regs + GPIO_INT_POLARITY); | |
| 227 | + level = dwapb_read(gpio, GPIO_INTTYPE_LEVEL); | |
| 228 | + polarity = dwapb_read(gpio, GPIO_INT_POLARITY); | |
| 177 | 229 | |
| 178 | 230 | switch (type) { |
| 179 | 231 | case IRQ_TYPE_EDGE_BOTH: |
| @@ -200,29 +252,55 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type) · 20 unmodified lines | ||
| 200 | 252 | |
| 201 | 253 | irq_setup_alt_chip(d, type); |
| 202 | 254 | |
| 203 | − writel(level, gpio->regs + GPIO_INTTYPE_LEVEL); | |
| 204 | − writel(polarity, gpio->regs + GPIO_INT_POLARITY); | |
| 255 | + dwapb_write(gpio, GPIO_INTTYPE_LEVEL, level); | |
| 256 | + dwapb_write(gpio, GPIO_INT_POLARITY, polarity); | |
| 257 | + spin_unlock_irqrestore(&bgc->lock, flags); | |
| 258 | + | |
| 259 | + return 0; | |
| 260 | +} | |
| 261 | + | |
| 262 | +static int dwapb_gpio_set_debounce(struct gpio_chip *gc, | |
| 263 | + unsigned offset, unsigned debounce) | |
| 264 | +{ | |
| 265 | + struct bgpio_chip *bgc = to_bgpio_chip(gc); | |
| 266 | + struct dwapb_gpio_port *port = to_dwapb_gpio_port(bgc); | |
| 267 | + struct dwapb_gpio *gpio = port->gpio; | |
| 268 | + unsigned long flags, val_deb; | |
| 269 | + unsigned long mask = bgc->pin2mask(bgc, offset); | |
| 270 | + | |
| 271 | + spin_lock_irqsave(&bgc->lock, flags); | |
| 272 | + | |
| 273 | + val_deb = dwapb_read(gpio, GPIO_PORTA_DEBOUNCE); | |
| 274 | + if (debounce) | |
| 275 | + dwapb_write(gpio, GPIO_PORTA_DEBOUNCE, val_deb | mask); | |
| 276 | + else | |
| 277 | + dwapb_write(gpio, GPIO_PORTA_DEBOUNCE, val_deb & ~mask); | |
| 278 | + | |
| 205 | 279 | spin_unlock_irqrestore(&bgc->lock, flags); |
| 206 | 280 | |
| 207 | 281 | return 0; |
| 208 | 282 | } |
| 209 | 283 | |
| 284 | +static irqreturn_t dwapb_irq_handler_mfd(int irq, void *dev_id) | |
| 285 | +{ | |
| 286 | + u32 worked; | |
| 287 | + struct dwapb_gpio *gpio = dev_id; | |
| 288 | + | |
| 289 | + worked = dwapb_do_irq(gpio); | |
| 290 | + | |
| 291 | + return worked ? IRQ_HANDLED : IRQ_NONE; | |
| 292 | +} | |
| 293 | + | |
| 210 | 294 | static void dwapb_configure_irqs(struct dwapb_gpio *gpio, |
| 211 | − struct dwapb_gpio_port *port) | |
| 295 | + struct dwapb_gpio_port *port, | |
| 296 | + struct dwapb_port_property *pp) | |
| 212 | 297 | { |
| 213 | 298 | struct gpio_chip *gc = &port->bgc.gc; |
| 214 | − struct device_node *node = gc->of_node; | |
| 215 | − struct irq_chip_generic *irq_gc; | |
| 299 | + struct device_node *node = pp->node; | |
| 300 | + struct irq_chip_generic *irq_gc = NULL; | |
| 216 | 301 | unsigned int hwirq, ngpio = gc->ngpio; |
| 217 | 302 | struct irq_chip_type *ct; |
| 218 | − int err, irq, i; | |
| 219 | − | |
| 220 | − irq = irq_of_parse_and_map(node, 0); | |
| 221 | − if (!irq) { | |
| 222 | − dev_warn(gpio->dev, "no irq for bank %s\n", | |
| 223 | − port->bgc.gc.of_node->full_name); | |
| 224 | − return; | |
| 225 | − } | |
| 303 | + int err, i; | |
| 226 | 304 | |
| 227 | 305 | gpio->domain = irq_domain_add_linear(node, ngpio, |
| 228 | 306 | &irq_generic_chip_ops, gpio); |
| @@ -269,8 +347,24 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, · 40 unmodified lines | ||
| 269 | 347 | irq_gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH; |
| 270 | 348 | irq_gc->chip_types[1].handler = handle_edge_irq; |
| 271 | 349 | |
| 272 | − irq_set_chained_handler(irq, dwapb_irq_handler); | |
| 273 | − irq_set_handler_data(irq, gpio); | |
| 350 | + if (!pp->irq_shared) { | |
| 351 | + irq_set_chained_handler(pp->irq, dwapb_irq_handler); | |
| 352 | + irq_set_handler_data(pp->irq, gpio); | |
| 353 | + } else { | |
| 354 | + /* | |
| 355 | + * Request a shared IRQ since where MFD would have devices | |
| 356 | + * using the same irq pin | |
| 357 | + */ | |
| 358 | + err = devm_request_irq(gpio->dev, pp->irq, | |
| 359 | + dwapb_irq_handler_mfd, | |
| 360 | + IRQF_SHARED, "gpio-dwapb-mfd", gpio); | |
| 361 | + if (err) { | |
| 362 | + dev_err(gpio->dev, "error requesting IRQ\n"); | |
| 363 | + irq_domain_remove(gpio->domain); | |
| 364 | + gpio->domain = NULL; | |
| 365 | + return; | |
| 366 | + } | |
| 367 | + } | |
| 274 | 368 | |
| 275 | 369 | for (hwirq = 0 ; hwirq < ngpio ; hwirq++) |
| 276 | 370 | irq_create_mapping(gpio->domain, hwirq); |
| @@ -296,57 +390,53 @@ static void dwapb_irq_teardown(struct dwapb_gpio *gpio) · 19 unmodified lines | ||
| 296 | 390 | } |
| 297 | 391 | |
| 298 | 392 | static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, |
| 299 | − struct device_node *port_np, | |
| 393 | + struct dwapb_port_property *pp, | |
| 300 | 394 | unsigned int offs) |
| 301 | 395 | { |
| 302 | 396 | struct dwapb_gpio_port *port; |
| 303 | − u32 port_idx, ngpio; | |
| 304 | 397 | void __iomem *dat, *set, *dirout; |
| 305 | 398 | int err; |
| 306 | 399 | |
| 307 | − if (of_property_read_u32(port_np, "reg", &port_idx) || | |
| 308 | − port_idx >= DWAPB_MAX_PORTS) { | |
| 309 | − dev_err(gpio->dev, "missing/invalid port index for %s\n", | |
| 310 | − port_np->full_name); | |
| 311 | − return -EINVAL; | |
| 312 | − } | |
| 313 | − | |
| 314 | 400 | port = &gpio->ports[offs]; |
| 315 | 401 | port->gpio = gpio; |
| 402 | + port->idx = pp->idx; | |
| 316 | 403 | |
| 317 | − if (of_property_read_u32(port_np, "snps,nr-gpios", &ngpio)) { | |
| 318 | − dev_info(gpio->dev, "failed to get number of gpios for %s\n", | |
| 319 | − port_np->full_name); | |
| 320 | − ngpio = 32; | |
| 321 | − } | |
| 404 | +#ifdef CONFIG_PM_SLEEP | |
| 405 | + port->ctx = devm_kzalloc(gpio->dev, sizeof(*port->ctx), GFP_KERNEL); | |
| 406 | + if (!port->ctx) | |
| 407 | + return -ENOMEM; | |
| 408 | +#endif | |
| 322 | 409 | |
| 323 | − dat = gpio->regs + GPIO_EXT_PORTA + (port_idx * GPIO_EXT_PORT_SIZE); | |
| 324 | − set = gpio->regs + GPIO_SWPORTA_DR + (port_idx * GPIO_SWPORT_DR_SIZE); | |
| 410 | + dat = gpio->regs + GPIO_EXT_PORTA + (pp->idx * GPIO_EXT_PORT_SIZE); | |
| 411 | + set = gpio->regs + GPIO_SWPORTA_DR + (pp->idx * GPIO_SWPORT_DR_SIZE); | |
| 325 | 412 | dirout = gpio->regs + GPIO_SWPORTA_DDR + |
| 326 | − (port_idx * GPIO_SWPORT_DDR_SIZE); | |
| 413 | + (pp->idx * GPIO_SWPORT_DDR_SIZE); | |
| 327 | 414 | |
| 328 | 415 | err = bgpio_init(&port->bgc, gpio->dev, 4, dat, set, NULL, dirout, |
| 329 | 416 | NULL, false); |
| 330 | 417 | if (err) { |
| 331 | 418 | dev_err(gpio->dev, "failed to init gpio chip for %s\n", |
| 332 | − port_np->full_name); | |
| 419 | + pp->name); | |
| 333 | 420 | return err; |
| 334 | 421 | } |
| 335 | 422 | |
| 336 | − port->bgc.gc.ngpio = ngpio; | |
| 337 | − port->bgc.gc.of_node = port_np; | |
| 423 | +#ifdef CONFIG_OF_GPIO | |
| 424 | + port->bgc.gc.of_node = pp->node; | |
| 425 | +#endif | |
| 426 | + port->bgc.gc.ngpio = pp->ngpio; | |
| 427 | + port->bgc.gc.base = pp->gpio_base; | |
| 338 | 428 | |
| 339 | − /* | |
| 340 | − * Only port A can provide interrupts in all configurations of the IP. | |
| 341 | − */ | |
| 342 | − if (port_idx == 0 && | |
| 343 | − of_property_read_bool(port_np, "interrupt-controller")) | |
| 344 | − dwapb_configure_irqs(gpio, port); | |
| 429 | + /* Only port A support debounce */ | |
| 430 | + if (pp->idx == 0) | |
| 431 | + port->bgc.gc.set_debounce = dwapb_gpio_set_debounce; | |
| 432 | + | |
| 433 | + if (pp->irq) | |
| 434 | + dwapb_configure_irqs(gpio, port, pp); | |
| 345 | 435 | |
| 346 | 436 | err = gpiochip_add(&port->bgc.gc); |
| 347 | 437 | if (err) |
| 348 | 438 | dev_err(gpio->dev, "failed to register gpiochip for %s\n", |
| 349 | − port_np->full_name); | |
| 439 | + pp->name); | |
| 350 | 440 | else |
| 351 | 441 | port->is_registered = true; |
| 352 | 442 | |
| @@ -362,25 +452,116 @@ static void dwapb_gpio_unregister(struct dwapb_gpio *gpio) · 9 unmodified lines | ||
| 362 | 452 | gpiochip_remove(&gpio->ports[m].bgc.gc); |
| 363 | 453 | } |
| 364 | 454 | |
| 455 | +static struct dwapb_platform_data * | |
| 456 | +dwapb_gpio_get_pdata_of(struct device *dev) | |
| 457 | +{ | |
| 458 | + struct device_node *node, *port_np; | |
| 459 | + struct dwapb_platform_data *pdata; | |
| 460 | + struct dwapb_port_property *pp; | |
| 461 | + int nports; | |
| 462 | + int i; | |
| 463 | + | |
| 464 | + node = dev->of_node; | |
| 465 | + if (!IS_ENABLED(CONFIG_OF_GPIO) || !node) | |
| 466 | + return ERR_PTR(-ENODEV); | |
| 467 | + | |
| 468 | + nports = of_get_child_count(node); | |
| 469 | + if (nports == 0) | |
| 470 | + return ERR_PTR(-ENODEV); | |
| 471 | + | |
| 472 | + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | |
| 473 | + if (!pdata) | |
| 474 | + return ERR_PTR(-ENOMEM); | |
| 475 | + | |
| 476 | + pdata->properties = kcalloc(nports, sizeof(*pp), GFP_KERNEL); | |
| 477 | + if (!pdata->properties) { | |
| 478 | + kfree(pdata); | |
| 479 | + return ERR_PTR(-ENOMEM); | |
| 480 | + } | |
| 481 | + | |
| 482 | + pdata->nports = nports; | |
| 483 | + | |
| 484 | + i = 0; | |
| 485 | + for_each_child_of_node(node, port_np) { | |
| 486 | + pp = &pdata->properties[i++]; | |
| 487 | + pp->node = port_np; | |
| 488 | + | |
| 489 | + if (of_property_read_u32(port_np, "reg", &pp->idx) || | |
| 490 | + pp->idx >= DWAPB_MAX_PORTS) { | |
| 491 | + dev_err(dev, "missing/invalid port index for %s\n", | |
| 492 | + port_np->full_name); | |
| 493 | + kfree(pdata->properties); | |
| 494 | + kfree(pdata); | |
| 495 | + return ERR_PTR(-EINVAL); | |
| 496 | + } | |
| 497 | + | |
| 498 | + if (of_property_read_u32(port_np, "snps,nr-gpios", | |
| 499 | + &pp->ngpio)) { | |
| 500 | + dev_info(dev, "failed to get number of gpios for %s\n", | |
| 501 | + port_np->full_name); | |
| 502 | + pp->ngpio = 32; | |
| 503 | + } | |
| 504 | + | |
| 505 | + /* | |
| 506 | + * Only port A can provide interrupts in all configurations of | |
| 507 | + * the IP. | |
| 508 | + */ | |
| 509 | + if (pp->idx == 0 && | |
| 510 | + of_property_read_bool(port_np, "interrupt-controller")) { | |
| 511 | + pp->irq = irq_of_parse_and_map(port_np, 0); | |
| 512 | + if (!pp->irq) { | |
| 513 | + dev_warn(dev, "no irq for bank %s\n", | |
| 514 | + port_np->full_name); | |
| 515 | + } | |
| 516 | + } | |
| 517 | + | |
| 518 | + pp->irq_shared = false; | |
| 519 | + pp->gpio_base = -1; | |
| 520 | + pp->name = port_np->full_name; | |
| 521 | + } | |
| 522 | + | |
| 523 | + return pdata; | |
| 524 | +} | |
| 525 | + | |
| 526 | +static inline void dwapb_free_pdata_of(struct dwapb_platform_data *pdata) | |
| 527 | +{ | |
| 528 | + if (!IS_ENABLED(CONFIG_OF_GPIO) || !pdata) | |
| 529 | + return; | |
| 530 | + | |
| 531 | + kfree(pdata->properties); | |
| 532 | + kfree(pdata); | |
| 533 | +} | |
| 534 | + | |
| 365 | 535 | static int dwapb_gpio_probe(struct platform_device *pdev) |
| 366 | 536 | { |
| 537 | + unsigned int i; | |
| 367 | 538 | struct resource *res; |
| 368 | 539 | struct dwapb_gpio *gpio; |
| 369 | − struct device_node *np; | |
| 370 | 540 | int err; |
| 371 | − unsigned int offs = 0; | |
| 541 | + struct device *dev = &pdev->dev; | |
| 542 | + struct dwapb_platform_data *pdata = dev_get_platdata(dev); | |
| 543 | + bool is_pdata_alloc = !pdata; | |
| 544 | + | |
| 545 | + if (is_pdata_alloc) { | |
| 546 | + pdata = dwapb_gpio_get_pdata_of(dev); | |
| 547 | + if (IS_ERR(pdata)) | |
| 548 | + return PTR_ERR(pdata); | |
| 549 | + } | |
| 372 | 550 | |
| 373 | − gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); | |
| 374 | − if (!gpio) | |
| 375 | − return -ENOMEM; | |
| 376 | − gpio->dev = &pdev->dev; | |
| 551 | + if (!pdata->nports) { | |
| 552 | + err = -ENODEV; | |
| 553 | + goto out_err; | |
| 554 | + } | |
| 377 | 555 | |
| 378 | − gpio->nr_ports = of_get_child_count(pdev->dev.of_node); | |
| 379 | − if (!gpio->nr_ports) { | |
| 380 | − err = -EINVAL; | |
| 556 | + gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); | |
| 557 | + if (!gpio) { | |
| 558 | + err = -ENOMEM; | |
| 381 | 559 | goto out_err; |
| 382 | 560 | } |
| 383 | − gpio->ports = devm_kzalloc(&pdev->dev, gpio->nr_ports * | |
| 561 | + gpio->dev = &pdev->dev; | |
| 562 | + gpio->nr_ports = pdata->nports; | |
| 563 | + | |
| 564 | + gpio->ports = devm_kcalloc(&pdev->dev, gpio->nr_ports, | |
| 384 | 565 | sizeof(*gpio->ports), GFP_KERNEL); |
| 385 | 566 | if (!gpio->ports) { |
| 386 | 567 | err = -ENOMEM; |
| @@ -394,20 +575,23 @@ static int dwapb_gpio_probe(struct platform_device *pdev) · 7 unmodified lines | ||
| 394 | 575 | goto out_err; |
| 395 | 576 | } |
| 396 | 577 | |
| 397 | − for_each_child_of_node(pdev->dev.of_node, np) { | |
| 398 | − err = dwapb_gpio_add_port(gpio, np, offs++); | |
| 578 | + for (i = 0; i < gpio->nr_ports; i++) { | |
| 579 | + err = dwapb_gpio_add_port(gpio, &pdata->properties[i], i); | |
| 399 | 580 | if (err) |
| 400 | 581 | goto out_unregister; |
| 401 | 582 | } |
| 402 | 583 | platform_set_drvdata(pdev, gpio); |
| 403 | 584 | |
| 404 | − return 0; | |
| 585 | + goto out_err; | |
| 405 | 586 | |
| 406 | 587 | out_unregister: |
| 407 | 588 | dwapb_gpio_unregister(gpio); |
| 408 | 589 | dwapb_irq_teardown(gpio); |
| 409 | 590 | |
| 410 | 591 | out_err: |
| 592 | + if (is_pdata_alloc) | |
| 593 | + dwapb_free_pdata_of(pdata); | |
| 594 | + | |
| 411 | 595 | return err; |
| 412 | 596 | } |
| 413 | 597 | |
| @@ -427,10 +611,100 @@ static const struct of_device_id dwapb_of_match[] = { · 13 unmodified lines | ||
| 427 | 611 | }; |
| 428 | 612 | MODULE_DEVICE_TABLE(of, dwapb_of_match); |
| 429 | 613 | |
| 614 | +#ifdef CONFIG_PM_SLEEP | |
| 615 | +static int dwapb_gpio_suspend(struct device *dev) | |
| 616 | +{ | |
| 617 | + struct platform_device *pdev = to_platform_device(dev); | |
| 618 | + struct dwapb_gpio *gpio = platform_get_drvdata(pdev); | |
| 619 | + struct bgpio_chip *bgc = &gpio->ports[0].bgc; | |
| 620 | + unsigned long flags; | |
| 621 | + int i; | |
| 622 | + | |
| 623 | + spin_lock_irqsave(&bgc->lock, flags); | |
| 624 | + for (i = 0; i < gpio->nr_ports; i++) { | |
| 625 | + unsigned int offset; | |
| 626 | + unsigned int idx = gpio->ports[i].idx; | |
| 627 | + struct dwapb_context *ctx = gpio->ports[i].ctx; | |
| 628 | + | |
| 629 | + BUG_ON(!ctx); | |
| 630 | + | |
| 631 | + offset = GPIO_SWPORTA_DDR + idx * GPIO_SWPORT_DDR_SIZE; | |
| 632 | + ctx->dir = dwapb_read(gpio, offset); | |
| 633 | + | |
| 634 | + offset = GPIO_SWPORTA_DR + idx * GPIO_SWPORT_DR_SIZE; | |
| 635 | + ctx->data = dwapb_read(gpio, offset); | |
| 636 | + | |
| 637 | + offset = GPIO_EXT_PORTA + idx * GPIO_EXT_PORT_SIZE; | |
| 638 | + ctx->ext = dwapb_read(gpio, offset); | |
| 639 | + | |
| 640 | + /* Only port A can provide interrupts */ | |
| 641 | + if (idx == 0) { | |
| 642 | + ctx->int_mask = dwapb_read(gpio, GPIO_INTMASK); | |
| 643 | + ctx->int_en = dwapb_read(gpio, GPIO_INTEN); | |
| 644 | + ctx->int_pol = dwapb_read(gpio, GPIO_INT_POLARITY); | |
| 645 | + ctx->int_type = dwapb_read(gpio, GPIO_INTTYPE_LEVEL); | |
| 646 | + ctx->int_deb = dwapb_read(gpio, GPIO_PORTA_DEBOUNCE); | |
| 647 | + | |
| 648 | + /* Mask out interrupts */ | |
| 649 | + dwapb_write(gpio, GPIO_INTMASK, 0xffffffff); | |
| 650 | + } | |
| 651 | + } | |
| 652 | + spin_unlock_irqrestore(&bgc->lock, flags); | |
| 653 | + | |
| 654 | + return 0; | |
| 655 | +} | |
| 656 | + | |
| 657 | +static int dwapb_gpio_resume(struct device *dev) | |
| 658 | +{ | |
| 659 | + struct platform_device *pdev = to_platform_device(dev); | |
| 660 | + struct dwapb_gpio *gpio = platform_get_drvdata(pdev); | |
| 661 | + struct bgpio_chip *bgc = &gpio->ports[0].bgc; | |
| 662 | + unsigned long flags; | |
| 663 | + int i; | |
| 664 | + | |
| 665 | + spin_lock_irqsave(&bgc->lock, flags); | |
| 666 | + for (i = 0; i < gpio->nr_ports; i++) { | |
| 667 | + unsigned int offset; | |
| 668 | + unsigned int idx = gpio->ports[i].idx; | |
| 669 | + struct dwapb_context *ctx = gpio->ports[i].ctx; | |
| 670 | + | |
| 671 | + BUG_ON(!ctx); | |
| 672 | + | |
| 673 | + offset = GPIO_SWPORTA_DR + idx * GPIO_SWPORT_DR_SIZE; | |
| 674 | + dwapb_write(gpio, offset, ctx->data); | |
| 675 | + | |
| 676 | + offset = GPIO_SWPORTA_DDR + idx * GPIO_SWPORT_DDR_SIZE; | |
| 677 | + dwapb_write(gpio, offset, ctx->dir); | |
| 678 | + | |
| 679 | + offset = GPIO_EXT_PORTA + idx * GPIO_EXT_PORT_SIZE; | |
| 680 | + dwapb_write(gpio, offset, ctx->ext); | |
| 681 | + | |
| 682 | + /* Only port A can provide interrupts */ | |
| 683 | + if (idx == 0) { | |
| 684 | + dwapb_write(gpio, GPIO_INTTYPE_LEVEL, ctx->int_type); | |
| 685 | + dwapb_write(gpio, GPIO_INT_POLARITY, ctx->int_pol); | |
| 686 | + dwapb_write(gpio, GPIO_PORTA_DEBOUNCE, ctx->int_deb); | |
| 687 | + dwapb_write(gpio, GPIO_INTEN, ctx->int_en); | |
| 688 | + dwapb_write(gpio, GPIO_INTMASK, ctx->int_mask); | |
| 689 | + | |
| 690 | + /* Clear out spurious interrupts */ | |
| 691 | + dwapb_write(gpio, GPIO_PORTA_EOI, 0xffffffff); | |
| 692 | + } | |
| 693 | + } | |
| 694 | + spin_unlock_irqrestore(&bgc->lock, flags); | |
| 695 | + | |
| 696 | + return 0; | |
| 697 | +} | |
| 698 | +#endif | |
| 699 | + | |
| 700 | +static SIMPLE_DEV_PM_OPS(dwapb_gpio_pm_ops, dwapb_gpio_suspend, | |
| 701 | + dwapb_gpio_resume); | |
| 702 | + | |
| 430 | 703 | static struct platform_driver dwapb_gpio_driver = { |
| 431 | 704 | .driver = { |
| 432 | 705 | .name = "gpio-dwapb", |
| 433 | 706 | .owner = THIS_MODULE, |
| 707 | + .pm = &dwapb_gpio_pm_ops, | |
| 434 | 708 | .of_match_table = of_match_ptr(dwapb_of_match), |
| 435 | 709 | }, |
| 436 | 710 | .probe = dwapb_gpio_probe, |
| @@ -265,29 +265,27 @@ static int ks8695_gpio_show(struct seq_file *s, void *unused) · 264 unmodified lines | ||
| 265 | 265 | seq_printf(s, "EXT%i ", i); |
| 266 | 266 | |
| 267 | 267 | switch ((ctrl & intmask[i]) >> (4 * i)) { |
| 268 | − case IOPC_TM_LOW: | |
| 269 | − seq_printf(s, "(Low)"); break; | |
| 270 | − case IOPC_TM_HIGH: | |
| 271 | − seq_printf(s, "(High)"); break; | |
| 272 | − case IOPC_TM_RISING: | |
| 273 | − seq_printf(s, "(Rising)"); break; | |
| 274 | − case IOPC_TM_FALLING: | |
| 275 | − seq_printf(s, "(Falling)"); break; | |
| 276 | − case IOPC_TM_EDGE: | |
| 277 | − seq_printf(s, "(Edges)"); break; | |
| 268 | + case IOPC_TM_LOW: | |
| 269 | + seq_printf(s, "(Low)"); break; | |
| 270 | + case IOPC_TM_HIGH: | |
| 271 | + seq_printf(s, "(High)"); break; | |
| 272 | + case IOPC_TM_RISING: | |
| 273 | + seq_printf(s, "(Rising)"); break; | |
| 274 | + case IOPC_TM_FALLING: | |
| 275 | + seq_printf(s, "(Falling)"); break; | |
| 276 | + case IOPC_TM_EDGE: | |
| 277 | + seq_printf(s, "(Edges)"); break; | |
| 278 | 278 | } |
| 279 | − } | |
| 280 | − else | |
| 279 | + } else | |
| 281 | 280 | seq_printf(s, "GPIO\t"); |
| 282 | − } | |
| 283 | − else if (i <= KS8695_GPIO_5) { | |
| 281 | + } else if (i <= KS8695_GPIO_5) { | |
| 284 | 282 | if (ctrl & enable[i]) |
| 285 | 283 | seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4); |
| 286 | 284 | else |
| 287 | 285 | seq_printf(s, "GPIO\t"); |
| 288 | − } | |
| 289 | − else | |
| 286 | + } else { | |
| 290 | 287 | seq_printf(s, "GPIO\t"); |
| 288 | + } | |
| 291 | 289 | |
| 292 | 290 | seq_printf(s, "\t"); |
| 293 | 291 | |
| @@ -479,7 +479,7 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp) · 478 unmodified lines | ||
| 479 | 479 | |
| 480 | 480 | mutex_init(&mcp->irq_lock); |
| 481 | 481 | |
| 482 | − mcp->irq_domain = irq_domain_add_linear(chip->of_node, chip->ngpio, | |
| 482 | + mcp->irq_domain = irq_domain_add_linear(chip->dev->of_node, chip->ngpio, | |
| 483 | 483 | &irq_domain_simple_ops, mcp); |
| 484 | 484 | if (!mcp->irq_domain) |
| 485 | 485 | return -ENODEV; |
| @@ -581,7 +581,7 @@ done: · 95 unmodified lines | ||
| 581 | 581 | |
| 582 | 582 | static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, |
| 583 | 583 | void *data, unsigned addr, unsigned type, |
| 584 | − unsigned base, unsigned pullups) | |
| 584 | + struct mcp23s08_platform_data *pdata, int cs) | |
| 585 | 585 | { |
| 586 | 586 | int status; |
| 587 | 587 | bool mirror = false; |
| @@ -635,7 +635,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, · 47 unmodified lines | ||
| 635 | 635 | return -EINVAL; |
| 636 | 636 | } |
| 637 | 637 | |
| 638 | − mcp->chip.base = base; | |
| 638 | + mcp->chip.base = pdata->base; | |
| 639 | 639 | mcp->chip.can_sleep = true; |
| 640 | 640 | mcp->chip.dev = dev; |
| 641 | 641 | mcp->chip.owner = THIS_MODULE; |
| @@ -648,11 +648,9 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, · 6 unmodified lines | ||
| 648 | 648 | if (status < 0) |
| 649 | 649 | goto fail; |
| 650 | 650 | |
| 651 | − mcp->irq_controller = of_property_read_bool(mcp->chip.of_node, | |
| 652 | − "interrupt-controller"); | |
| 651 | + mcp->irq_controller = pdata->irq_controller; | |
| 653 | 652 | if (mcp->irq && mcp->irq_controller && (type == MCP_TYPE_017)) |
| 654 | − mirror = of_property_read_bool(mcp->chip.of_node, | |
| 655 | − "microchip,irq-mirror"); | |
| 653 | + mirror = pdata->mirror; | |
| 656 | 654 | |
| 657 | 655 | if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror) { |
| 658 | 656 | /* mcp23s17 has IOCON twice, make sure they are in sync */ |
| @@ -668,7 +666,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, · 9 unmodified lines | ||
| 668 | 666 | } |
| 669 | 667 | |
| 670 | 668 | /* configure ~100K pullups */ |
| 671 | − status = mcp->ops->write(mcp, MCP_GPPU, pullups); | |
| 669 | + status = mcp->ops->write(mcp, MCP_GPPU, pdata->chip[cs].pullups); | |
| 672 | 670 | if (status < 0) |
| 673 | 671 | goto fail; |
| 674 | 672 | |
| @@ -768,25 +766,29 @@ MODULE_DEVICE_TABLE(of, mcp23s08_i2c_of_match); · 93 unmodified lines | ||
| 768 | 766 | static int mcp230xx_probe(struct i2c_client *client, |
| 769 | 767 | const struct i2c_device_id *id) |
| 770 | 768 | { |
| 771 | − struct mcp23s08_platform_data *pdata; | |
| 769 | + struct mcp23s08_platform_data *pdata, local_pdata; | |
| 772 | 770 | struct mcp23s08 *mcp; |
| 773 | − int status, base, pullups; | |
| 771 | + int status; | |
| 774 | 772 | const struct of_device_id *match; |
| 775 | 773 | |
| 776 | 774 | match = of_match_device(of_match_ptr(mcp23s08_i2c_of_match), |
| 777 | 775 | &client->dev); |
| 778 | − pdata = dev_get_platdata(&client->dev); | |
| 779 | − if (match || !pdata) { | |
| 780 | − base = -1; | |
| 781 | − pullups = 0; | |
| 776 | + if (match) { | |
| 777 | + pdata = &local_pdata; | |
| 778 | + pdata->base = -1; | |
| 779 | + pdata->chip[0].pullups = 0; | |
| 780 | + pdata->irq_controller = of_property_read_bool( | |
| 781 | + client->dev.of_node, | |
| 782 | + "interrupt-controller"); | |
| 783 | + pdata->mirror = of_property_read_bool(client->dev.of_node, | |
| 784 | + "microchip,irq-mirror"); | |
| 782 | 785 | client->irq = irq_of_parse_and_map(client->dev.of_node, 0); |
| 783 | 786 | } else { |
| 784 | − if (!gpio_is_valid(pdata->base)) { | |
| 787 | + pdata = dev_get_platdata(&client->dev); | |
| 788 | + if (!pdata || !gpio_is_valid(pdata->base)) { | |
| 785 | 789 | dev_dbg(&client->dev, "invalid platform data\n"); |
| 786 | 790 | return -EINVAL; |
| 787 | 791 | } |
| 788 | − base = pdata->base; | |
| 789 | − pullups = pdata->chip[0].pullups; | |
| 790 | 792 | } |
| 791 | 793 | |
| 792 | 794 | mcp = kzalloc(sizeof(*mcp), GFP_KERNEL); |
| @@ -795,7 +797,7 @@ static int mcp230xx_probe(struct i2c_client *client, · 2 unmodified lines | ||
| 795 | 797 | |
| 796 | 798 | mcp->irq = client->irq; |
| 797 | 799 | status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr, |
| 798 | − id->driver_data, base, pullups); | |
| 800 | + id->driver_data, pdata, 0); | |
| 799 | 801 | if (status) |
| 800 | 802 | goto fail; |
| 801 | 803 | |
| @@ -863,14 +865,12 @@ static void mcp23s08_i2c_exit(void) { } · 61 unmodified lines | ||
| 863 | 865 | |
| 864 | 866 | static int mcp23s08_probe(struct spi_device *spi) |
| 865 | 867 | { |
| 866 | − struct mcp23s08_platform_data *pdata; | |
| 868 | + struct mcp23s08_platform_data *pdata, local_pdata; | |
| 867 | 869 | unsigned addr; |
| 868 | 870 | int chips = 0; |
| 869 | 871 | struct mcp23s08_driver_data *data; |
| 870 | 872 | int status, type; |
| 871 | − unsigned base = -1, | |
| 872 | − ngpio = 0, | |
| 873 | − pullups[ARRAY_SIZE(pdata->chip)]; | |
| 873 | + unsigned ngpio = 0; | |
| 874 | 874 | const struct of_device_id *match; |
| 875 | 875 | u32 spi_present_mask = 0; |
| 876 | 876 | |
| @@ -893,11 +893,18 @@ static int mcp23s08_probe(struct spi_device *spi) · 16 unmodified lines | ||
| 893 | 893 | return -ENODEV; |
| 894 | 894 | } |
| 895 | 895 | |
| 896 | + pdata = &local_pdata; | |
| 897 | + pdata->base = -1; | |
| 896 | 898 | for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) { |
| 897 | − pullups[addr] = 0; | |
| 899 | + pdata->chip[addr].pullups = 0; | |
| 898 | 900 | if (spi_present_mask & (1 << addr)) |
| 899 | 901 | chips++; |
| 900 | 902 | } |
| 903 | + pdata->irq_controller = of_property_read_bool( | |
| 904 | + spi->dev.of_node, | |
| 905 | + "interrupt-controller"); | |
| 906 | + pdata->mirror = of_property_read_bool(spi->dev.of_node, | |
| 907 | + "microchip,irq-mirror"); | |
| 901 | 908 | } else { |
| 902 | 909 | type = spi_get_device_id(spi)->driver_data; |
| 903 | 910 | pdata = dev_get_platdata(&spi->dev); |
| @@ -917,10 +924,7 @@ static int mcp23s08_probe(struct spi_device *spi) · 13 unmodified lines | ||
| 917 | 924 | return -EINVAL; |
| 918 | 925 | } |
| 919 | 926 | spi_present_mask |= 1 << addr; |
| 920 | − pullups[addr] = pdata->chip[addr].pullups; | |
| 921 | 927 | } |
| 922 | − | |
| 923 | − base = pdata->base; | |
| 924 | 928 | } |
| 925 | 929 | |
| 926 | 930 | if (!chips) |
| @@ -938,13 +942,13 @@ static int mcp23s08_probe(struct spi_device *spi) · 11 unmodified lines | ||
| 938 | 942 | chips--; |
| 939 | 943 | data->mcp[addr] = &data->chip[chips]; |
| 940 | 944 | status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi, |
| 941 | − 0x40 | (addr << 1), type, base, | |
| 942 | − pullups[addr]); | |
| 945 | + 0x40 | (addr << 1), type, pdata, | |
| 946 | + addr); | |
| 943 | 947 | if (status < 0) |
| 944 | 948 | goto fail; |
| 945 | 949 | |
| 946 | − if (base != -1) | |
| 947 | − base += (type == MCP_TYPE_S17) ? 16 : 8; | |
| 950 | + if (pdata->base != -1) | |
| 951 | + pdata->base += (type == MCP_TYPE_S17) ? 16 : 8; | |
| 948 | 952 | ngpio += (type == MCP_TYPE_S17) ? 16 : 8; |
| 949 | 953 | } |
| 950 | 954 | data->ngpio = ngpio; |
| @@ -857,16 +857,6 @@ static void omap_gpio_unmask_irq(struct irq_data *d) · 856 unmodified lines | ||
| 857 | 857 | spin_unlock_irqrestore(&bank->lock, flags); |
| 858 | 858 | } |
| 859 | 859 | |
| 860 | −static struct irq_chip gpio_irq_chip = { | |
| 861 | − .name = "GPIO", | |
| 862 | − .irq_shutdown = omap_gpio_irq_shutdown, | |
| 863 | − .irq_ack = omap_gpio_ack_irq, | |
| 864 | − .irq_mask = omap_gpio_mask_irq, | |
| 865 | − .irq_unmask = omap_gpio_unmask_irq, | |
| 866 | − .irq_set_type = omap_gpio_irq_type, | |
| 867 | − .irq_set_wake = omap_gpio_wake_enable, | |
| 868 | −}; | |
| 869 | − | |
| 870 | 860 | /*---------------------------------------------------------------------*/ |
| 871 | 861 | |
| 872 | 862 | static int omap_mpuio_suspend_noirq(struct device *dev) |
| @@ -1088,7 +1078,7 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start, · 215 unmodified lines | ||
| 1088 | 1078 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); |
| 1089 | 1079 | } |
| 1090 | 1080 | |
| 1091 | −static int omap_gpio_chip_init(struct gpio_bank *bank) | |
| 1081 | +static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) | |
| 1092 | 1082 | { |
| 1093 | 1083 | int j; |
| 1094 | 1084 | static int gpio; |
| @@ -1137,17 +1127,17 @@ static int omap_gpio_chip_init(struct gpio_bank *bank) · 42 unmodified lines | ||
| 1137 | 1127 | } |
| 1138 | 1128 | #endif |
| 1139 | 1129 | |
| 1140 | − ret = gpiochip_irqchip_add(&bank->chip, &gpio_irq_chip, | |
| 1130 | + ret = gpiochip_irqchip_add(&bank->chip, irqc, | |
| 1141 | 1131 | irq_base, omap_gpio_irq_handler, |
| 1142 | 1132 | IRQ_TYPE_NONE); |
| 1143 | 1133 | |
| 1144 | 1134 | if (ret) { |
| 1145 | 1135 | dev_err(bank->dev, "Couldn't add irqchip to gpiochip %d\n", ret); |
| 1146 | − ret = gpiochip_remove(&bank->chip); | |
| 1136 | + gpiochip_remove(&bank->chip); | |
| 1147 | 1137 | return -ENODEV; |
| 1148 | 1138 | } |
| 1149 | 1139 | |
| 1150 | − gpiochip_set_chained_irqchip(&bank->chip, &gpio_irq_chip, | |
| 1140 | + gpiochip_set_chained_irqchip(&bank->chip, irqc, | |
| 1151 | 1141 | bank->irq, omap_gpio_irq_handler); |
| 1152 | 1142 | |
| 1153 | 1143 | for (j = 0; j < bank->width; j++) { |
| @@ -1172,6 +1162,7 @@ static int omap_gpio_probe(struct platform_device *pdev) · 18 unmodified lines | ||
| 1172 | 1162 | const struct omap_gpio_platform_data *pdata; |
| 1173 | 1163 | struct resource *res; |
| 1174 | 1164 | struct gpio_bank *bank; |
| 1165 | + struct irq_chip *irqc; | |
| 1175 | 1166 | int ret; |
| 1176 | 1167 | |
| 1177 | 1168 | match = of_match_device(of_match_ptr(omap_gpio_match), dev); |
| @@ -1186,6 +1177,18 @@ static int omap_gpio_probe(struct platform_device *pdev) · 8 unmodified lines | ||
| 1186 | 1177 | return -ENOMEM; |
| 1187 | 1178 | } |
| 1188 | 1179 | |
| 1180 | + irqc = devm_kzalloc(dev, sizeof(*irqc), GFP_KERNEL); | |
| 1181 | + if (!irqc) | |
| 1182 | + return -ENOMEM; | |
| 1183 | + | |
| 1184 | + irqc->irq_shutdown = omap_gpio_irq_shutdown, | |
| 1185 | + irqc->irq_ack = omap_gpio_ack_irq, | |
| 1186 | + irqc->irq_mask = omap_gpio_mask_irq, | |
| 1187 | + irqc->irq_unmask = omap_gpio_unmask_irq, | |
| 1188 | + irqc->irq_set_type = omap_gpio_irq_type, | |
| 1189 | + irqc->irq_set_wake = omap_gpio_wake_enable, | |
| 1190 | + irqc->name = dev_name(&pdev->dev); | |
| 1191 | + | |
| 1189 | 1192 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
| 1190 | 1193 | if (unlikely(!res)) { |
| 1191 | 1194 | dev_err(dev, "Invalid IRQ resource\n"); |
| @@ -1241,7 +1244,7 @@ static int omap_gpio_probe(struct platform_device *pdev) · 49 unmodified lines | ||
| 1241 | 1244 | |
| 1242 | 1245 | omap_gpio_mod_init(bank); |
| 1243 | 1246 | |
| 1244 | − ret = omap_gpio_chip_init(bank); | |
| 1247 | + ret = omap_gpio_chip_init(bank, irqc); | |
| 1245 | 1248 | if (ret) |
| 1246 | 1249 | return ret; |
| 1247 | 1250 | |
| @@ -520,7 +520,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, · 519 unmodified lines | ||
| 520 | 520 | struct i2c_client *client = chip->client; |
| 521 | 521 | int ret, i, offset = 0; |
| 522 | 522 | |
| 523 | − if (irq_base != -1 | |
| 523 | + if (client->irq && irq_base != -1 | |
| 524 | 524 | && (id->driver_data & PCA_INT)) { |
| 525 | 525 | |
| 526 | 526 | switch (chip->chip_type) { |
| @@ -586,50 +586,6 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, · 59 unmodified lines | ||
| 586 | 586 | } |
| 587 | 587 | #endif |
| 588 | 588 | |
| 589 | −/* | |
| 590 | − * Handlers for alternative sources of platform_data | |
| 591 | − */ | |
| 592 | −#ifdef CONFIG_OF_GPIO | |
| 593 | −/* | |
| 594 | − * Translate OpenFirmware node properties into platform_data | |
| 595 | − * WARNING: This is DEPRECATED and will be removed eventually! | |
| 596 | − */ | |
| 597 | −static void | |
| 598 | −pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert) | |
| 599 | −{ | |
| 600 | − struct device_node *node; | |
| 601 | − const __be32 *val; | |
| 602 | − int size; | |
| 603 | − | |
| 604 | − *gpio_base = -1; | |
| 605 | − | |
| 606 | − node = client->dev.of_node; | |
| 607 | − if (node == NULL) | |
| 608 | − return; | |
| 609 | − | |
| 610 | − val = of_get_property(node, "linux,gpio-base", &size); | |
| 611 | − WARN(val, "%s: device-tree property 'linux,gpio-base' is deprecated!", __func__); | |
| 612 | − if (val) { | |
| 613 | − if (size != sizeof(*val)) | |
| 614 | − dev_warn(&client->dev, "%s: wrong linux,gpio-base\n", | |
| 615 | − node->full_name); | |
| 616 | − else | |
| 617 | − *gpio_base = be32_to_cpup(val); | |
| 618 | − } | |
| 619 | − | |
| 620 | − val = of_get_property(node, "polarity", NULL); | |
| 621 | − WARN(val, "%s: device-tree property 'polarity' is deprecated!", __func__); | |
| 622 | − if (val) | |
| 623 | − *invert = *val; | |
| 624 | −} | |
| 625 | −#else | |
| 626 | −static void | |
| 627 | −pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert) | |
| 628 | −{ | |
| 629 | − *gpio_base = -1; | |
| 630 | −} | |
| 631 | −#endif | |
| 632 | − | |
| 633 | 589 | static int device_pca953x_init(struct pca953x_chip *chip, u32 invert) |
| 634 | 590 | { |
| 635 | 591 | int ret; |
| @@ -704,12 +660,8 @@ static int pca953x_probe(struct i2c_client *client, · 68 unmodified lines | ||
| 704 | 660 | invert = pdata->invert; |
| 705 | 661 | chip->names = pdata->names; |
| 706 | 662 | } else { |
| 707 | − pca953x_get_alt_pdata(client, &chip->gpio_start, &invert); | |
| 708 | −#ifdef CONFIG_OF_GPIO | |
| 709 | − /* If I2C node has no interrupts property, disable GPIO interrupts */ | |
| 710 | − if (of_find_property(client->dev.of_node, "interrupts", NULL) == NULL) | |
| 711 | − irq_base = -1; | |
| 712 | −#endif | |
| 663 | + chip->gpio_start = -1; | |
| 664 | + irq_base = 0; | |
| 713 | 665 | } |
| 714 | 666 | |
| 715 | 667 | chip->client = client; |
| @@ -171,6 +171,7 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) · 170 unmodified lines | ||
| 171 | 171 | return 0; |
| 172 | 172 | } |
| 173 | 173 | |
| 174 | +#ifdef CONFIG_PM | |
| 174 | 175 | /* |
| 175 | 176 | * Save register configuration and disable interrupts. |
| 176 | 177 | */ |
| @@ -206,6 +207,7 @@ static void pch_gpio_restore_reg_conf(struct pch_gpio *chip) · 29 unmodified lines | ||
| 206 | 207 | iowrite32(chip->pch_gpio_reg.gpio_use_sel_reg, |
| 207 | 208 | &chip->reg->gpio_use_sel); |
| 208 | 209 | } |
| 210 | +#endif | |
| 209 | 211 | |
| 210 | 212 | static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned offset) |
| 211 | 213 | { |
| @@ -1309,56 +1309,6 @@ samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin) · 1308 unmodified lines | ||
| 1309 | 1309 | } |
| 1310 | 1310 | EXPORT_SYMBOL(s3c_gpio_getpull); |
| 1311 | 1311 | |
| 1312 | −#ifdef CONFIG_S5P_GPIO_DRVSTR | |
| 1313 | −s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin) | |
| 1314 | −{ | |
| 1315 | − struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin); | |
| 1316 | − unsigned int off; | |
| 1317 | − void __iomem *reg; | |
| 1318 | − int shift; | |
| 1319 | − u32 drvstr; | |
| 1320 | − | |
| 1321 | − if (!chip) | |
| 1322 | − return -EINVAL; | |
| 1323 | − | |
| 1324 | − off = pin - chip->chip.base; | |
| 1325 | − shift = off * 2; | |
| 1326 | − reg = chip->base + 0x0C; | |
| 1327 | − | |
| 1328 | − drvstr = __raw_readl(reg); | |
| 1329 | − drvstr = drvstr >> shift; | |
| 1330 | − drvstr &= 0x3; | |
| 1331 | − | |
| 1332 | − return (__force s5p_gpio_drvstr_t)drvstr; | |
| 1333 | −} | |
| 1334 | −EXPORT_SYMBOL(s5p_gpio_get_drvstr); | |
| 1335 | − | |
| 1336 | −int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr) | |
| 1337 | −{ | |
| 1338 | − struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin); | |
| 1339 | − unsigned int off; | |
| 1340 | − void __iomem *reg; | |
| 1341 | − int shift; | |
| 1342 | − u32 tmp; | |
| 1343 | − | |
| 1344 | − if (!chip) | |
| 1345 | − return -EINVAL; | |
| 1346 | − | |
| 1347 | − off = pin - chip->chip.base; | |
| 1348 | − shift = off * 2; | |
| 1349 | − reg = chip->base + 0x0C; | |
| 1350 | − | |
| 1351 | − tmp = __raw_readl(reg); | |
| 1352 | − tmp &= ~(0x3 << shift); | |
| 1353 | − tmp |= drvstr << shift; | |
| 1354 | − | |
| 1355 | − __raw_writel(tmp, reg); | |
| 1356 | − | |
| 1357 | − return 0; | |
| 1358 | −} | |
| 1359 | −EXPORT_SYMBOL(s5p_gpio_set_drvstr); | |
| 1360 | −#endif /* CONFIG_S5P_GPIO_DRVSTR */ | |
| 1361 | − | |
| 1362 | 1312 | #ifdef CONFIG_PLAT_S3C24XX |
| 1363 | 1313 | unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change) |
| 1364 | 1314 | { |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/interrupt.h> |
| 14 | 14 | #include <linux/of.h> |
| 15 | 15 | #include <linux/mfd/stmpe.h> |
| 16 | +#include <linux/seq_file.h> | |
| 16 | 17 | |
| 17 | 18 | /* |
| 18 | 19 | * These registers are modified under the irq bus lock and cached to avoid |
| @@ -127,19 +128,19 @@ static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type) · 108 unmodified lines | ||
| 127 | 128 | int regoffset = offset / 8; |
| 128 | 129 | int mask = 1 << (offset % 8); |
| 129 | 130 | |
| 130 | − if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH) | |
| 131 | + if (type & IRQ_TYPE_LEVEL_LOW || type & IRQ_TYPE_LEVEL_HIGH) | |
| 131 | 132 | return -EINVAL; |
| 132 | 133 | |
| 133 | 134 | /* STMPE801 doesn't have RE and FE registers */ |
| 134 | 135 | if (stmpe_gpio->stmpe->partnum == STMPE801) |
| 135 | 136 | return 0; |
| 136 | 137 | |
| 137 | − if (type == IRQ_TYPE_EDGE_RISING) | |
| 138 | + if (type & IRQ_TYPE_EDGE_RISING) | |
| 138 | 139 | stmpe_gpio->regs[REG_RE][regoffset] |= mask; |
| 139 | 140 | else |
| 140 | 141 | stmpe_gpio->regs[REG_RE][regoffset] &= ~mask; |
| 141 | 142 | |
| 142 | − if (type == IRQ_TYPE_EDGE_FALLING) | |
| 143 | + if (type & IRQ_TYPE_EDGE_FALLING) | |
| 143 | 144 | stmpe_gpio->regs[REG_FE][regoffset] |= mask; |
| 144 | 145 | else |
| 145 | 146 | stmpe_gpio->regs[REG_FE][regoffset] &= ~mask; |
| @@ -211,6 +212,77 @@ static void stmpe_gpio_irq_unmask(struct irq_data *d) · 65 unmodified lines | ||
| 211 | 212 | stmpe_gpio->regs[REG_IE][regoffset] |= mask; |
| 212 | 213 | } |
| 213 | 214 | |
| 215 | +static void stmpe_dbg_show_one(struct seq_file *s, | |
| 216 | + struct gpio_chip *gc, | |
| 217 | + unsigned offset, unsigned gpio) | |
| 218 | +{ | |
| 219 | + struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc); | |
| 220 | + struct stmpe *stmpe = stmpe_gpio->stmpe; | |
| 221 | + const char *label = gpiochip_is_requested(gc, offset); | |
| 222 | + int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); | |
| 223 | + bool val = !!stmpe_gpio_get(gc, offset); | |
| 224 | + u8 dir_reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8); | |
| 225 | + u8 mask = 1 << (offset % 8); | |
| 226 | + int ret; | |
| 227 | + u8 dir; | |
| 228 | + | |
| 229 | + ret = stmpe_reg_read(stmpe, dir_reg); | |
| 230 | + if (ret < 0) | |
| 231 | + return; | |
| 232 | + dir = !!(ret & mask); | |
| 233 | + | |
| 234 | + if (dir) { | |
| 235 | + seq_printf(s, " gpio-%-3d (%-20.20s) out %s", | |
| 236 | + gpio, label ?: "(none)", | |
| 237 | + val ? "hi" : "lo"); | |
| 238 | + } else { | |
| 239 | + u8 edge_det_reg = stmpe->regs[STMPE_IDX_GPEDR_MSB] + num_banks - 1 - (offset / 8); | |
| 240 | + u8 rise_reg = stmpe->regs[STMPE_IDX_GPRER_LSB] - (offset / 8); | |
| 241 | + u8 fall_reg = stmpe->regs[STMPE_IDX_GPFER_LSB] - (offset / 8); | |
| 242 | + u8 irqen_reg = stmpe->regs[STMPE_IDX_IEGPIOR_LSB] - (offset / 8); | |
| 243 | + bool edge_det; | |
| 244 | + bool rise; | |
| 245 | + bool fall; | |
| 246 | + bool irqen; | |
| 247 | + | |
| 248 | + ret = stmpe_reg_read(stmpe, edge_det_reg); | |
| 249 | + if (ret < 0) | |
| 250 | + return; | |
| 251 | + edge_det = !!(ret & mask); | |
| 252 | + ret = stmpe_reg_read(stmpe, rise_reg); | |
| 253 | + if (ret < 0) | |
| 254 | + return; | |
| 255 | + rise = !!(ret & mask); | |
| 256 | + ret = stmpe_reg_read(stmpe, fall_reg); | |
| 257 | + if (ret < 0) | |
| 258 | + return; | |
| 259 | + fall = !!(ret & mask); | |
| 260 | + ret = stmpe_reg_read(stmpe, irqen_reg); | |
| 261 | + if (ret < 0) | |
| 262 | + return; | |
| 263 | + irqen = !!(ret & mask); | |
| 264 | + | |
| 265 | + seq_printf(s, " gpio-%-3d (%-20.20s) in %s %s %s%s%s", | |
| 266 | + gpio, label ?: "(none)", | |
| 267 | + val ? "hi" : "lo", | |
| 268 | + edge_det ? "edge-asserted" : "edge-inactive", | |
| 269 | + irqen ? "IRQ-enabled" : "", | |
| 270 | + rise ? " rising-edge-detection" : "", | |
| 271 | + fall ? " falling-edge-detection" : ""); | |
| 272 | + } | |
| 273 | +} | |
| 274 | + | |
| 275 | +static void stmpe_dbg_show(struct seq_file *s, struct gpio_chip *gc) | |
| 276 | +{ | |
| 277 | + unsigned i; | |
| 278 | + unsigned gpio = gc->base; | |
| 279 | + | |
| 280 | + for (i = 0; i < gc->ngpio; i++, gpio++) { | |
| 281 | + stmpe_dbg_show_one(s, gc, i, gpio); | |
| 282 | + seq_printf(s, "\n"); | |
| 283 | + } | |
| 284 | +} | |
| 285 | + | |
| 214 | 286 | static struct irq_chip stmpe_gpio_irq_chip = { |
| 215 | 287 | .name = "stmpe-gpio", |
| 216 | 288 | .irq_bus_lock = stmpe_gpio_irq_lock, |
| @@ -293,6 +365,9 @@ static int stmpe_gpio_probe(struct platform_device *pdev) · 76 unmodified lines | ||
| 293 | 365 | #endif |
| 294 | 366 | stmpe_gpio->chip.base = -1; |
| 295 | 367 | |
| 368 | + if (IS_ENABLED(CONFIG_DEBUG_FS)) | |
| 369 | + stmpe_gpio->chip.dbg_show = stmpe_dbg_show; | |
| 370 | + | |
| 296 | 371 | if (pdata) |
| 297 | 372 | stmpe_gpio->norequest_mask = pdata->norequest_mask; |
| 298 | 373 | else if (np) |
| @@ -308,6 +383,12 @@ static int stmpe_gpio_probe(struct platform_device *pdev) · 9 unmodified lines | ||
| 308 | 383 | if (ret) |
| 309 | 384 | goto out_free; |
| 310 | 385 | |
| 386 | + ret = gpiochip_add(&stmpe_gpio->chip); | |
| 387 | + if (ret) { | |
| 388 | + dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); | |
| 389 | + goto out_disable; | |
| 390 | + } | |
| 391 | + | |
| 311 | 392 | if (irq > 0) { |
| 312 | 393 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
| 313 | 394 | stmpe_gpio_irq, IRQF_ONESHOT, |
| @@ -324,14 +405,13 @@ static int stmpe_gpio_probe(struct platform_device *pdev) · 10 unmodified lines | ||
| 324 | 405 | if (ret) { |
| 325 | 406 | dev_err(&pdev->dev, |
| 326 | 407 | "could not connect irqchip to gpiochip\n"); |
| 327 | − return ret; | |
| 408 | + goto out_disable; | |
| 328 | 409 | } |
| 329 | − } | |
| 330 | 410 | |
| 331 | − ret = gpiochip_add(&stmpe_gpio->chip); | |
| 332 | − if (ret) { | |
| 333 | − dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); | |
| 334 | − goto out_disable; | |
| 411 | + gpiochip_set_chained_irqchip(&stmpe_gpio->chip, | |
| 412 | + &stmpe_gpio_irq_chip, | |
| 413 | + irq, | |
| 414 | + NULL); | |
| 335 | 415 | } |
| 336 | 416 | |
| 337 | 417 | if (pdata && pdata->setup) |
| @@ -343,6 +423,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) · 5 unmodified lines | ||
| 343 | 423 | |
| 344 | 424 | out_disable: |
| 345 | 425 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); |
| 426 | + gpiochip_remove(&stmpe_gpio->chip); | |
| 346 | 427 | out_free: |
| 347 | 428 | kfree(stmpe_gpio); |
| 348 | 429 | return ret; |
| @@ -292,7 +292,7 @@ static struct platform_driver xway_stp_driver = { · 291 unmodified lines | ||
| 292 | 292 | }, |
| 293 | 293 | }; |
| 294 | 294 | |
| 295 | −int __init xway_stp_init(void) | |
| 295 | +static int __init xway_stp_init(void) | |
| 296 | 296 | { |
| 297 | 297 | return platform_driver_register(&xway_stp_driver); |
| 298 | 298 | } |
| @@ -37,6 +37,8 @@ · 36 unmodified lines | ||
| 37 | 37 | * dat_bit_offset: Offset (in bits) to the first GPIO bit. |
| 38 | 38 | * dir_bit_offset: Optional offset (in bits) to the first bit to switch |
| 39 | 39 | * GPIO direction (Used with GPIO_SYSCON_FEAT_DIR flag). |
| 40 | + * set: HW specific callback to assigns output value | |
| 41 | + * for signal "offset" | |
| 40 | 42 | */ |
| 41 | 43 | |
| 42 | 44 | struct syscon_gpio_data { |
| @@ -45,12 +47,16 @@ struct syscon_gpio_data { · 2 unmodified lines | ||
| 45 | 47 | unsigned int bit_count; |
| 46 | 48 | unsigned int dat_bit_offset; |
| 47 | 49 | unsigned int dir_bit_offset; |
| 50 | + void (*set)(struct gpio_chip *chip, | |
| 51 | + unsigned offset, int value); | |
| 48 | 52 | }; |
| 49 | 53 | |
| 50 | 54 | struct syscon_gpio_priv { |
| 51 | 55 | struct gpio_chip chip; |
| 52 | 56 | struct regmap *syscon; |
| 53 | 57 | const struct syscon_gpio_data *data; |
| 58 | + u32 dreg_offset; | |
| 59 | + u32 dir_reg_offset; | |
| 54 | 60 | }; |
| 55 | 61 | |
| 56 | 62 | static inline struct syscon_gpio_priv *to_syscon_gpio(struct gpio_chip *chip) |
| @@ -61,9 +67,11 @@ static inline struct syscon_gpio_priv *to_syscon_gpio(struct gpio_chip *chip) · 4 unmodified lines | ||
| 61 | 67 | static int syscon_gpio_get(struct gpio_chip *chip, unsigned offset) |
| 62 | 68 | { |
| 63 | 69 | struct syscon_gpio_priv *priv = to_syscon_gpio(chip); |
| 64 | − unsigned int val, offs = priv->data->dat_bit_offset + offset; | |
| 70 | + unsigned int val, offs; | |
| 65 | 71 | int ret; |
| 66 | 72 | |
| 73 | + offs = priv->dreg_offset + priv->data->dat_bit_offset + offset; | |
| 74 | + | |
| 67 | 75 | ret = regmap_read(priv->syscon, |
| 68 | 76 | (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, &val); |
| 69 | 77 | if (ret) |
| @@ -75,7 +83,9 @@ static int syscon_gpio_get(struct gpio_chip *chip, unsigned offset) · 5 unmodified lines | ||
| 75 | 83 | static void syscon_gpio_set(struct gpio_chip *chip, unsigned offset, int val) |
| 76 | 84 | { |
| 77 | 85 | struct syscon_gpio_priv *priv = to_syscon_gpio(chip); |
| 78 | − unsigned int offs = priv->data->dat_bit_offset + offset; | |
| 86 | + unsigned int offs; | |
| 87 | + | |
| 88 | + offs = priv->dreg_offset + priv->data->dat_bit_offset + offset; | |
| 79 | 89 | |
| 80 | 90 | regmap_update_bits(priv->syscon, |
| 81 | 91 | (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, |
| @@ -88,7 +98,10 @@ static int syscon_gpio_dir_in(struct gpio_chip *chip, unsigned offset) · 6 unmodified lines | ||
| 88 | 98 | struct syscon_gpio_priv *priv = to_syscon_gpio(chip); |
| 89 | 99 | |
| 90 | 100 | if (priv->data->flags & GPIO_SYSCON_FEAT_DIR) { |
| 91 | − unsigned int offs = priv->data->dir_bit_offset + offset; | |
| 101 | + unsigned int offs; | |
| 102 | + | |
| 103 | + offs = priv->dir_reg_offset + | |
| 104 | + priv->data->dir_bit_offset + offset; | |
| 92 | 105 | |
| 93 | 106 | regmap_update_bits(priv->syscon, |
| 94 | 107 | (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, |
| @@ -103,7 +116,10 @@ static int syscon_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int val) · 8 unmodified lines | ||
| 103 | 116 | struct syscon_gpio_priv *priv = to_syscon_gpio(chip); |
| 104 | 117 | |
| 105 | 118 | if (priv->data->flags & GPIO_SYSCON_FEAT_DIR) { |
| 106 | − unsigned int offs = priv->data->dir_bit_offset + offset; | |
| 119 | + unsigned int offs; | |
| 120 | + | |
| 121 | + offs = priv->dir_reg_offset + | |
| 122 | + priv->data->dir_bit_offset + offset; | |
| 107 | 123 | |
| 108 | 124 | regmap_update_bits(priv->syscon, |
| 109 | 125 | (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, |
| @@ -111,7 +127,7 @@ static int syscon_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int val) · 1 unmodified line | ||
| 111 | 127 | BIT(offs % SYSCON_REG_BITS)); |
| 112 | 128 | } |
| 113 | 129 | |
| 114 | − syscon_gpio_set(chip, offset, val); | |
| 130 | + priv->data->set(chip, offset, val); | |
| 115 | 131 | |
| 116 | 132 | return 0; |
| 117 | 133 | } |
| @@ -124,11 +140,46 @@ static const struct syscon_gpio_data clps711x_mctrl_gpio = { · 6 unmodified lines | ||
| 124 | 140 | .dat_bit_offset = 0x40 * 8 + 8, |
| 125 | 141 | }; |
| 126 | 142 | |
| 143 | +#define KEYSTONE_LOCK_BIT BIT(0) | |
| 144 | + | |
| 145 | +static void keystone_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | |
| 146 | +{ | |
| 147 | + struct syscon_gpio_priv *priv = to_syscon_gpio(chip); | |
| 148 | + unsigned int offs; | |
| 149 | + int ret; | |
| 150 | + | |
| 151 | + offs = priv->dreg_offset + priv->data->dat_bit_offset + offset; | |
| 152 | + | |
| 153 | + if (!val) | |
| 154 | + return; | |
| 155 | + | |
| 156 | + ret = regmap_update_bits( | |
| 157 | + priv->syscon, | |
| 158 | + (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, | |
| 159 | + BIT(offs % SYSCON_REG_BITS) | KEYSTONE_LOCK_BIT, | |
| 160 | + BIT(offs % SYSCON_REG_BITS) | KEYSTONE_LOCK_BIT); | |
| 161 | + if (ret < 0) | |
| 162 | + dev_err(chip->dev, "gpio write failed ret(%d)\n", ret); | |
| 163 | +} | |
| 164 | + | |
| 165 | +static const struct syscon_gpio_data keystone_dsp_gpio = { | |
| 166 | + /* ARM Keystone 2 */ | |
| 167 | + .compatible = NULL, | |
| 168 | + .flags = GPIO_SYSCON_FEAT_OUT, | |
| 169 | + .bit_count = 28, | |
| 170 | + .dat_bit_offset = 4, | |
| 171 | + .set = keystone_gpio_set, | |
| 172 | +}; | |
| 173 | + | |
| 127 | 174 | static const struct of_device_id syscon_gpio_ids[] = { |
| 128 | 175 | { |
| 129 | 176 | .compatible = "cirrus,clps711x-mctrl-gpio", |
| 130 | 177 | .data = &clps711x_mctrl_gpio, |
| 131 | 178 | }, |
| 179 | + { | |
| 180 | + .compatible = "ti,keystone-dsp-gpio", | |
| 181 | + .data = &keystone_dsp_gpio, | |
| 182 | + }, | |
| 132 | 183 | { } |
| 133 | 184 | }; |
| 134 | 185 | MODULE_DEVICE_TABLE(of, syscon_gpio_ids); |
| @@ -138,6 +189,8 @@ static int syscon_gpio_probe(struct platform_device *pdev) · 3 unmodified lines | ||
| 138 | 189 | struct device *dev = &pdev->dev; |
| 139 | 190 | const struct of_device_id *of_id = of_match_device(syscon_gpio_ids, dev); |
| 140 | 191 | struct syscon_gpio_priv *priv; |
| 192 | + struct device_node *np = dev->of_node; | |
| 193 | + int ret; | |
| 141 | 194 | |
| 142 | 195 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
| 143 | 196 | if (!priv) |
| @@ -145,10 +198,31 @@ static int syscon_gpio_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 145 | 198 | |
| 146 | 199 | priv->data = of_id->data; |
| 147 | 200 | |
| 148 | − priv->syscon = | |
| 149 | − syscon_regmap_lookup_by_compatible(priv->data->compatible); | |
| 150 | − if (IS_ERR(priv->syscon)) | |
| 151 | − return PTR_ERR(priv->syscon); | |
| 201 | + if (priv->data->compatible) { | |
| 202 | + priv->syscon = syscon_regmap_lookup_by_compatible( | |
| 203 | + priv->data->compatible); | |
| 204 | + if (IS_ERR(priv->syscon)) | |
| 205 | + return PTR_ERR(priv->syscon); | |
| 206 | + } else { | |
| 207 | + priv->syscon = | |
| 208 | + syscon_regmap_lookup_by_phandle(np, "gpio,syscon-dev"); | |
| 209 | + if (IS_ERR(priv->syscon)) | |
| 210 | + return PTR_ERR(priv->syscon); | |
| 211 | + | |
| 212 | + ret = of_property_read_u32_index(np, "gpio,syscon-dev", 1, | |
| 213 | + &priv->dreg_offset); | |
| 214 | + if (ret) | |
| 215 | + dev_err(dev, "can't read the data register offset!\n"); | |
| 216 | + | |
| 217 | + priv->dreg_offset <<= 3; | |
| 218 | + | |
| 219 | + ret = of_property_read_u32_index(np, "gpio,syscon-dev", 2, | |
| 220 | + &priv->dir_reg_offset); | |
| 221 | + if (ret) | |
| 222 | + dev_err(dev, "can't read the dir register offset!\n"); | |
| 223 | + | |
| 224 | + priv->dir_reg_offset <<= 3; | |
| 225 | + } | |
| 152 | 226 | |
| 153 | 227 | priv->chip.dev = dev; |
| 154 | 228 | priv->chip.owner = THIS_MODULE; |
| @@ -159,7 +233,7 @@ static int syscon_gpio_probe(struct platform_device *pdev) · 4 unmodified lines | ||
| 159 | 233 | if (priv->data->flags & GPIO_SYSCON_FEAT_IN) |
| 160 | 234 | priv->chip.direction_input = syscon_gpio_dir_in; |
| 161 | 235 | if (priv->data->flags & GPIO_SYSCON_FEAT_OUT) { |
| 162 | − priv->chip.set = syscon_gpio_set; | |
| 236 | + priv->chip.set = priv->data->set ? : syscon_gpio_set; | |
| 163 | 237 | priv->chip.direction_output = syscon_gpio_dir_out; |
| 164 | 238 | } |
| 165 | 239 | |
| @@ -300,6 +300,11 @@ static int tc3589x_gpio_probe(struct platform_device *pdev) · 299 unmodified lines | ||
| 300 | 300 | return ret; |
| 301 | 301 | } |
| 302 | 302 | |
| 303 | + gpiochip_set_chained_irqchip(&tc3589x_gpio->chip, | |
| 304 | + &tc3589x_gpio_irq_chip, | |
| 305 | + irq, | |
| 306 | + NULL); | |
| 307 | + | |
| 303 | 308 | if (pdata && pdata->setup) |
| 304 | 309 | pdata->setup(tc3589x, tc3589x_gpio->chip.base); |
| 305 | 310 | |
| @@ -0,0 +1,244 @@ | ||
| 1 | +/* | |
| 2 | + * AppliedMicro X-Gene SoC GPIO Driver | |
| 3 | + * | |
| 4 | + * Copyright (c) 2014, Applied Micro Circuits Corporation | |
| 5 | + * Author: Feng Kan <fkan@apm.com>. | |
| 6 | + * | |
| 7 | + * This program is free software; you can redistribute it and/or modify | |
| 8 | + * it under the terms of the GNU General Public License version 2 as | |
| 9 | + * published by the Free Software Foundation. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License | |
| 17 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 18 | + */ | |
| 19 | + | |
| 20 | +#include <linux/module.h> | |
| 21 | +#include <linux/kernel.h> | |
| 22 | +#include <linux/init.h> | |
| 23 | +#include <linux/io.h> | |
| 24 | +#include <linux/spinlock.h> | |
| 25 | +#include <linux/platform_device.h> | |
| 26 | +#include <linux/gpio/driver.h> | |
| 27 | +#include <linux/types.h> | |
| 28 | +#include <linux/bitops.h> | |
| 29 | + | |
| 30 | +#define GPIO_SET_DR_OFFSET 0x0C | |
| 31 | +#define GPIO_DATA_OFFSET 0x14 | |
| 32 | +#define GPIO_BANK_STRIDE 0x0C | |
| 33 | + | |
| 34 | +#define XGENE_GPIOS_PER_BANK 16 | |
| 35 | +#define XGENE_MAX_GPIO_BANKS 3 | |
| 36 | +#define XGENE_MAX_GPIOS (XGENE_GPIOS_PER_BANK * XGENE_MAX_GPIO_BANKS) | |
| 37 | + | |
| 38 | +#define GPIO_BIT_OFFSET(x) (x % XGENE_GPIOS_PER_BANK) | |
| 39 | +#define GPIO_BANK_OFFSET(x) ((x / XGENE_GPIOS_PER_BANK) * GPIO_BANK_STRIDE) | |
| 40 | + | |
| 41 | +struct xgene_gpio { | |
| 42 | + struct gpio_chip chip; | |
| 43 | + void __iomem *base; | |
| 44 | + spinlock_t lock; | |
| 45 | +#ifdef CONFIG_PM | |
| 46 | + u32 set_dr_val[XGENE_MAX_GPIO_BANKS]; | |
| 47 | +#endif | |
| 48 | +}; | |
| 49 | + | |
| 50 | +static inline struct xgene_gpio *to_xgene_gpio(struct gpio_chip *chip) | |
| 51 | +{ | |
| 52 | + return container_of(chip, struct xgene_gpio, chip); | |
| 53 | +} | |
| 54 | + | |
| 55 | +static int xgene_gpio_get(struct gpio_chip *gc, unsigned int offset) | |
| 56 | +{ | |
| 57 | + struct xgene_gpio *chip = to_xgene_gpio(gc); | |
| 58 | + unsigned long bank_offset; | |
| 59 | + u32 bit_offset; | |
| 60 | + | |
| 61 | + bank_offset = GPIO_DATA_OFFSET + GPIO_BANK_OFFSET(offset); | |
| 62 | + bit_offset = GPIO_BIT_OFFSET(offset); | |
| 63 | + return !!(ioread32(chip->base + bank_offset) & BIT(bit_offset)); | |
| 64 | +} | |
| 65 | + | |
| 66 | +static void __xgene_gpio_set(struct gpio_chip *gc, unsigned int offset, int val) | |
| 67 | +{ | |
| 68 | + struct xgene_gpio *chip = to_xgene_gpio(gc); | |
| 69 | + unsigned long bank_offset; | |
| 70 | + u32 setval, bit_offset; | |
| 71 | + | |
| 72 | + bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset); | |
| 73 | + bit_offset = GPIO_BIT_OFFSET(offset) + XGENE_GPIOS_PER_BANK; | |
| 74 | + | |
| 75 | + setval = ioread32(chip->base + bank_offset); | |
| 76 | + if (val) | |
| 77 | + setval |= BIT(bit_offset); | |
| 78 | + else | |
| 79 | + setval &= ~BIT(bit_offset); | |
| 80 | + iowrite32(setval, chip->base + bank_offset); | |
| 81 | +} | |
| 82 | + | |
| 83 | +static void xgene_gpio_set(struct gpio_chip *gc, unsigned int offset, int val) | |
| 84 | +{ | |
| 85 | + struct xgene_gpio *chip = to_xgene_gpio(gc); | |
| 86 | + unsigned long flags; | |
| 87 | + | |
| 88 | + spin_lock_irqsave(&chip->lock, flags); | |
| 89 | + __xgene_gpio_set(gc, offset, val); | |
| 90 | + spin_unlock_irqrestore(&chip->lock, flags); | |
| 91 | +} | |
| 92 | + | |
| 93 | +static int xgene_gpio_dir_in(struct gpio_chip *gc, unsigned int offset) | |
| 94 | +{ | |
| 95 | + struct xgene_gpio *chip = to_xgene_gpio(gc); | |
| 96 | + unsigned long flags, bank_offset; | |
| 97 | + u32 dirval, bit_offset; | |
| 98 | + | |
| 99 | + bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset); | |
| 100 | + bit_offset = GPIO_BIT_OFFSET(offset); | |
| 101 | + | |
| 102 | + spin_lock_irqsave(&chip->lock, flags); | |
| 103 | + | |
| 104 | + dirval = ioread32(chip->base + bank_offset); | |
| 105 | + dirval |= BIT(bit_offset); | |
| 106 | + iowrite32(dirval, chip->base + bank_offset); | |
| 107 | + | |
| 108 | + spin_unlock_irqrestore(&chip->lock, flags); | |
| 109 | + | |
| 110 | + return 0; | |
| 111 | +} | |
| 112 | + | |
| 113 | +static int xgene_gpio_dir_out(struct gpio_chip *gc, | |
| 114 | + unsigned int offset, int val) | |
| 115 | +{ | |
| 116 | + struct xgene_gpio *chip = to_xgene_gpio(gc); | |
| 117 | + unsigned long flags, bank_offset; | |
| 118 | + u32 dirval, bit_offset; | |
| 119 | + | |
| 120 | + bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset); | |
| 121 | + bit_offset = GPIO_BIT_OFFSET(offset); | |
| 122 | + | |
| 123 | + spin_lock_irqsave(&chip->lock, flags); | |
| 124 | + | |
| 125 | + dirval = ioread32(chip->base + bank_offset); | |
| 126 | + dirval &= ~BIT(bit_offset); | |
| 127 | + iowrite32(dirval, chip->base + bank_offset); | |
| 128 | + __xgene_gpio_set(gc, offset, val); | |
| 129 | + | |
| 130 | + spin_unlock_irqrestore(&chip->lock, flags); | |
| 131 | + | |
| 132 | + return 0; | |
| 133 | +} | |
| 134 | + | |
| 135 | +#ifdef CONFIG_PM | |
| 136 | +static int xgene_gpio_suspend(struct device *dev) | |
| 137 | +{ | |
| 138 | + struct xgene_gpio *gpio = dev_get_drvdata(dev); | |
| 139 | + unsigned long bank_offset; | |
| 140 | + unsigned int bank; | |
| 141 | + | |
| 142 | + for (bank = 0; bank < XGENE_MAX_GPIO_BANKS; bank++) { | |
| 143 | + bank_offset = GPIO_SET_DR_OFFSET + bank * GPIO_BANK_STRIDE; | |
| 144 | + gpio->set_dr_val[bank] = ioread32(gpio->base + bank_offset); | |
| 145 | + } | |
| 146 | + return 0; | |
| 147 | +} | |
| 148 | + | |
| 149 | +static int xgene_gpio_resume(struct device *dev) | |
| 150 | +{ | |
| 151 | + struct xgene_gpio *gpio = dev_get_drvdata(dev); | |
| 152 | + unsigned long bank_offset; | |
| 153 | + unsigned int bank; | |
| 154 | + | |
| 155 | + for (bank = 0; bank < XGENE_MAX_GPIO_BANKS; bank++) { | |
| 156 | + bank_offset = GPIO_SET_DR_OFFSET + bank * GPIO_BANK_STRIDE; | |
| 157 | + iowrite32(gpio->set_dr_val[bank], gpio->base + bank_offset); | |
| 158 | + } | |
| 159 | + return 0; | |
| 160 | +} | |
| 161 | + | |
| 162 | +static SIMPLE_DEV_PM_OPS(xgene_gpio_pm, xgene_gpio_suspend, xgene_gpio_resume); | |
| 163 | +#define XGENE_GPIO_PM_OPS (&xgene_gpio_pm) | |
| 164 | +#else | |
| 165 | +#define XGENE_GPIO_PM_OPS NULL | |
| 166 | +#endif | |
| 167 | + | |
| 168 | +static int xgene_gpio_probe(struct platform_device *pdev) | |
| 169 | +{ | |
| 170 | + struct resource *res; | |
| 171 | + struct xgene_gpio *gpio; | |
| 172 | + int err = 0; | |
| 173 | + | |
| 174 | + gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); | |
| 175 | + if (!gpio) { | |
| 176 | + err = -ENOMEM; | |
| 177 | + goto err; | |
| 178 | + } | |
| 179 | + | |
| 180 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 181 | + gpio->base = devm_ioremap_nocache(&pdev->dev, res->start, | |
| 182 | + resource_size(res)); | |
| 183 | + if (!gpio->base) { | |
| 184 | + err = -ENOMEM; | |
| 185 | + goto err; | |
| 186 | + } | |
| 187 | + | |
| 188 | + gpio->chip.ngpio = XGENE_MAX_GPIOS; | |
| 189 | + | |
| 190 | + spin_lock_init(&gpio->lock); | |
| 191 | + gpio->chip.dev = &pdev->dev; | |
| 192 | + gpio->chip.direction_input = xgene_gpio_dir_in; | |
| 193 | + gpio->chip.direction_output = xgene_gpio_dir_out; | |
| 194 | + gpio->chip.get = xgene_gpio_get; | |
| 195 | + gpio->chip.set = xgene_gpio_set; | |
| 196 | + gpio->chip.label = dev_name(&pdev->dev); | |
| 197 | + gpio->chip.base = -1; | |
| 198 | + | |
| 199 | + platform_set_drvdata(pdev, gpio); | |
| 200 | + | |
| 201 | + err = gpiochip_add(&gpio->chip); | |
| 202 | + if (err) { | |
| 203 | + dev_err(&pdev->dev, | |
| 204 | + "failed to register gpiochip.\n"); | |
| 205 | + goto err; | |
| 206 | + } | |
| 207 | + | |
| 208 | + dev_info(&pdev->dev, "X-Gene GPIO driver registered.\n"); | |
| 209 | + return 0; | |
| 210 | +err: | |
| 211 | + dev_err(&pdev->dev, "X-Gene GPIO driver registration failed.\n"); | |
| 212 | + return err; | |
| 213 | +} | |
| 214 | + | |
| 215 | +static int xgene_gpio_remove(struct platform_device *pdev) | |
| 216 | +{ | |
| 217 | + struct xgene_gpio *gpio = platform_get_drvdata(pdev); | |
| 218 | + | |
| 219 | + gpiochip_remove(&gpio->chip); | |
| 220 | + return 0; | |
| 221 | +} | |
| 222 | + | |
| 223 | +static const struct of_device_id xgene_gpio_of_match[] = { | |
| 224 | + { .compatible = "apm,xgene-gpio", }, | |
| 225 | + {}, | |
| 226 | +}; | |
| 227 | +MODULE_DEVICE_TABLE(of, xgene_gpio_of_match); | |
| 228 | + | |
| 229 | +static struct platform_driver xgene_gpio_driver = { | |
| 230 | + .driver = { | |
| 231 | + .name = "xgene-gpio", | |
| 232 | + .owner = THIS_MODULE, | |
| 233 | + .of_match_table = xgene_gpio_of_match, | |
| 234 | + .pm = XGENE_GPIO_PM_OPS, | |
| 235 | + }, | |
| 236 | + .probe = xgene_gpio_probe, | |
| 237 | + .remove = xgene_gpio_remove, | |
| 238 | +}; | |
| 239 | + | |
| 240 | +module_platform_driver(xgene_gpio_driver); | |
| 241 | + | |
| 242 | +MODULE_AUTHOR("Feng Kan <fkan@apm.com>"); | |
| 243 | +MODULE_DESCRIPTION("APM X-Gene GPIO driver"); | |
| 244 | +MODULE_LICENSE("GPL"); | |
| @@ -197,6 +197,7 @@ static int xgpio_of_probe(struct device_node *np) · 196 unmodified lines | ||
| 197 | 197 | struct xgpio_instance *chip; |
| 198 | 198 | int status = 0; |
| 199 | 199 | const u32 *tree_info; |
| 200 | + u32 ngpio; | |
| 200 | 201 | |
| 201 | 202 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
| 202 | 203 | if (!chip) |
| @@ -211,12 +212,13 @@ static int xgpio_of_probe(struct device_node *np) · 8 unmodified lines | ||
| 211 | 212 | /* Update GPIO direction shadow register with default value */ |
| 212 | 213 | of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir); |
| 213 | 214 | |
| 214 | − /* By default assume full GPIO controller */ | |
| 215 | − chip->mmchip.gc.ngpio = 32; | |
| 216 | − | |
| 217 | − /* Check device node and parent device node for device width */ | |
| 218 | − of_property_read_u32(np, "xlnx,gpio-width", | |
| 219 | − (u32 *)&chip->mmchip.gc.ngpio); | |
| 215 | + /* | |
| 216 | + * Check device node and parent device node for device width | |
| 217 | + * and assume default width of 32 | |
| 218 | + */ | |
| 219 | + if (of_property_read_u32(np, "xlnx,gpio-width", &ngpio)) | |
| 220 | + ngpio = 32; | |
| 221 | + chip->mmchip.gc.ngpio = (u16)ngpio; | |
| 220 | 222 | |
| 221 | 223 | spin_lock_init(&chip->gpio_lock); |
| 222 | 224 | |
| @@ -258,12 +260,13 @@ static int xgpio_of_probe(struct device_node *np) · 35 unmodified lines | ||
| 258 | 260 | /* Update GPIO direction shadow register with default value */ |
| 259 | 261 | of_property_read_u32(np, "xlnx,tri-default-2", &chip->gpio_dir); |
| 260 | 262 | |
| 261 | − /* By default assume full GPIO controller */ | |
| 262 | − chip->mmchip.gc.ngpio = 32; | |
| 263 | − | |
| 264 | − /* Check device node and parent device node for device width */ | |
| 265 | − of_property_read_u32(np, "xlnx,gpio2-width", | |
| 266 | − (u32 *)&chip->mmchip.gc.ngpio); | |
| 263 | + /* | |
| 264 | + * Check device node and parent device node for device width | |
| 265 | + * and assume default width of 32 | |
| 266 | + */ | |
| 267 | + if (of_property_read_u32(np, "xlnx,gpio2-width", &ngpio)) | |
| 268 | + ngpio = 32; | |
| 269 | + chip->mmchip.gc.ngpio = (u16)ngpio; | |
| 267 | 270 | |
| 268 | 271 | spin_lock_init(&chip->gpio_lock); |
| 269 | 272 | |
| @@ -88,16 +88,17 @@ · 87 unmodified lines | ||
| 88 | 88 | * @chip: instance of the gpio_chip |
| 89 | 89 | * @base_addr: base address of the GPIO device |
| 90 | 90 | * @clk: clock resource for this controller |
| 91 | + * @irq: interrupt for the GPIO device | |
| 91 | 92 | */ |
| 92 | 93 | struct zynq_gpio { |
| 93 | 94 | struct gpio_chip chip; |
| 94 | 95 | void __iomem *base_addr; |
| 95 | 96 | struct clk *clk; |
| 97 | + int irq; | |
| 96 | 98 | }; |
| 97 | 99 | |
| 98 | 100 | static struct irq_chip zynq_gpio_level_irqchip; |
| 99 | 101 | static struct irq_chip zynq_gpio_edge_irqchip; |
| 100 | − | |
| 101 | 102 | /** |
| 102 | 103 | * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank |
| 103 | 104 | * for a given pin in the GPIO device |
| @@ -138,6 +139,13 @@ static inline void zynq_gpio_get_bank_pin(unsigned int pin_num, · 34 unmodified lines | ||
| 138 | 139 | } |
| 139 | 140 | } |
| 140 | 141 | |
| 142 | +static const unsigned int zynq_gpio_bank_offset[] = { | |
| 143 | + ZYNQ_GPIO_BANK0_PIN_MIN, | |
| 144 | + ZYNQ_GPIO_BANK1_PIN_MIN, | |
| 145 | + ZYNQ_GPIO_BANK2_PIN_MIN, | |
| 146 | + ZYNQ_GPIO_BANK3_PIN_MIN, | |
| 147 | +}; | |
| 148 | + | |
| 141 | 149 | /** |
| 142 | 150 | * zynq_gpio_get_value - Get the state of the specified pin of GPIO device |
| 143 | 151 | * @chip: gpio_chip instance to be worked on |
| @@ -427,10 +435,9 @@ static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type) · 283 unmodified lines | ||
| 427 | 435 | |
| 428 | 436 | static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on) |
| 429 | 437 | { |
| 430 | − if (on) | |
| 431 | − zynq_gpio_irq_unmask(data); | |
| 432 | − else | |
| 433 | − zynq_gpio_irq_mask(data); | |
| 438 | + struct zynq_gpio *gpio = irq_data_get_irq_chip_data(data); | |
| 439 | + | |
| 440 | + irq_set_irq_wake(gpio->irq, on); | |
| 434 | 441 | |
| 435 | 442 | return 0; |
| 436 | 443 | } |
| @@ -444,7 +451,8 @@ static struct irq_chip zynq_gpio_level_irqchip = { · 7 unmodified lines | ||
| 444 | 451 | .irq_unmask = zynq_gpio_irq_unmask, |
| 445 | 452 | .irq_set_type = zynq_gpio_set_irq_type, |
| 446 | 453 | .irq_set_wake = zynq_gpio_set_wake, |
| 447 | − .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED, | |
| 454 | + .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED | | |
| 455 | + IRQCHIP_MASK_ON_SUSPEND, | |
| 448 | 456 | }; |
| 449 | 457 | |
| 450 | 458 | static struct irq_chip zynq_gpio_edge_irqchip = { |
| @@ -455,8 +463,28 @@ static struct irq_chip zynq_gpio_edge_irqchip = { · 4 unmodified lines | ||
| 455 | 463 | .irq_unmask = zynq_gpio_irq_unmask, |
| 456 | 464 | .irq_set_type = zynq_gpio_set_irq_type, |
| 457 | 465 | .irq_set_wake = zynq_gpio_set_wake, |
| 466 | + .flags = IRQCHIP_MASK_ON_SUSPEND, | |
| 458 | 467 | }; |
| 459 | 468 | |
| 469 | +static void zynq_gpio_handle_bank_irq(struct zynq_gpio *gpio, | |
| 470 | + unsigned int bank_num, | |
| 471 | + unsigned long pending) | |
| 472 | +{ | |
| 473 | + unsigned int bank_offset = zynq_gpio_bank_offset[bank_num]; | |
| 474 | + struct irq_domain *irqdomain = gpio->chip.irqdomain; | |
| 475 | + int offset; | |
| 476 | + | |
| 477 | + if (!pending) | |
| 478 | + return; | |
| 479 | + | |
| 480 | + for_each_set_bit(offset, &pending, 32) { | |
| 481 | + unsigned int gpio_irq; | |
| 482 | + | |
| 483 | + gpio_irq = irq_find_mapping(irqdomain, offset + bank_offset); | |
| 484 | + generic_handle_irq(gpio_irq); | |
| 485 | + } | |
| 486 | +} | |
| 487 | + | |
| 460 | 488 | /** |
| 461 | 489 | * zynq_gpio_irqhandler - IRQ handler for the gpio banks of a gpio device |
| 462 | 490 | * @irq: irq number of the gpio bank where interrupt has occurred |
| @@ -482,18 +510,7 @@ static void zynq_gpio_irqhandler(unsigned int irq, struct irq_desc *desc) · 19 unmodified lines | ||
| 482 | 510 | ZYNQ_GPIO_INTSTS_OFFSET(bank_num)); |
| 483 | 511 | int_enb = readl_relaxed(gpio->base_addr + |
| 484 | 512 | ZYNQ_GPIO_INTMASK_OFFSET(bank_num)); |
| 485 | − int_sts &= ~int_enb; | |
| 486 | − if (int_sts) { | |
| 487 | − int offset; | |
| 488 | − unsigned long pending = int_sts; | |
| 489 | − | |
| 490 | − for_each_set_bit(offset, &pending, 32) { | |
| 491 | − unsigned int gpio_irq = | |
| 492 | − irq_find_mapping(gpio->chip.irqdomain, | |
| 493 | − offset); | |
| 494 | − generic_handle_irq(gpio_irq); | |
| 495 | − } | |
| 496 | − } | |
| 513 | + zynq_gpio_handle_bank_irq(gpio, bank_num, int_sts & ~int_enb); | |
| 497 | 514 | } |
| 498 | 515 | |
| 499 | 516 | chained_irq_exit(irqchip, desc); |
| @@ -501,7 +518,11 @@ static void zynq_gpio_irqhandler(unsigned int irq, struct irq_desc *desc) · 1 unmodified line | ||
| 501 | 518 | |
| 502 | 519 | static int __maybe_unused zynq_gpio_suspend(struct device *dev) |
| 503 | 520 | { |
| 504 | − if (!device_may_wakeup(dev)) | |
| 521 | + struct platform_device *pdev = to_platform_device(dev); | |
| 522 | + int irq = platform_get_irq(pdev, 0); | |
| 523 | + struct irq_data *data = irq_get_irq_data(irq); | |
| 524 | + | |
| 525 | + if (!irqd_is_wakeup_set(data)) | |
| 505 | 526 | return pm_runtime_force_suspend(dev); |
| 506 | 527 | |
| 507 | 528 | return 0; |
| @@ -509,7 +530,11 @@ static int __maybe_unused zynq_gpio_suspend(struct device *dev) · 1 unmodified line | ||
| 509 | 530 | |
| 510 | 531 | static int __maybe_unused zynq_gpio_resume(struct device *dev) |
| 511 | 532 | { |
| 512 | − if (!device_may_wakeup(dev)) | |
| 533 | + struct platform_device *pdev = to_platform_device(dev); | |
| 534 | + int irq = platform_get_irq(pdev, 0); | |
| 535 | + struct irq_data *data = irq_get_irq_data(irq); | |
| 536 | + | |
| 537 | + if (!irqd_is_wakeup_set(data)) | |
| 513 | 538 | return pm_runtime_force_resume(dev); |
| 514 | 539 | |
| 515 | 540 | return 0; |
| @@ -570,7 +595,7 @@ static const struct dev_pm_ops zynq_gpio_dev_pm_ops = { · 54 unmodified lines | ||
| 570 | 595 | */ |
| 571 | 596 | static int zynq_gpio_probe(struct platform_device *pdev) |
| 572 | 597 | { |
| 573 | − int ret, bank_num, irq; | |
| 598 | + int ret, bank_num; | |
| 574 | 599 | struct zynq_gpio *gpio; |
| 575 | 600 | struct gpio_chip *chip; |
| 576 | 601 | struct resource *res; |
| @@ -586,10 +611,10 @@ static int zynq_gpio_probe(struct platform_device *pdev) · 9 unmodified lines | ||
| 586 | 611 | if (IS_ERR(gpio->base_addr)) |
| 587 | 612 | return PTR_ERR(gpio->base_addr); |
| 588 | 613 | |
| 589 | − irq = platform_get_irq(pdev, 0); | |
| 590 | − if (irq < 0) { | |
| 614 | + gpio->irq = platform_get_irq(pdev, 0); | |
| 615 | + if (gpio->irq < 0) { | |
| 591 | 616 | dev_err(&pdev->dev, "invalid IRQ\n"); |
| 592 | − return irq; | |
| 617 | + return gpio->irq; | |
| 593 | 618 | } |
| 594 | 619 | |
| 595 | 620 | /* configure the gpio chip */ |
| @@ -637,19 +662,16 @@ static int zynq_gpio_probe(struct platform_device *pdev) · 41 unmodified lines | ||
| 637 | 662 | goto err_rm_gpiochip; |
| 638 | 663 | } |
| 639 | 664 | |
| 640 | − gpiochip_set_chained_irqchip(chip, &zynq_gpio_edge_irqchip, irq, | |
| 665 | + gpiochip_set_chained_irqchip(chip, &zynq_gpio_edge_irqchip, gpio->irq, | |
| 641 | 666 | zynq_gpio_irqhandler); |
| 642 | 667 | |
| 643 | 668 | pm_runtime_set_active(&pdev->dev); |
| 644 | 669 | pm_runtime_enable(&pdev->dev); |
| 645 | 670 | |
| 646 | − device_set_wakeup_capable(&pdev->dev, 1); | |
| 647 | − | |
| 648 | 671 | return 0; |
| 649 | 672 | |
| 650 | 673 | err_rm_gpiochip: |
| 651 | − if (gpiochip_remove(chip)) | |
| 652 | − dev_err(&pdev->dev, "Failed to remove gpio chip\n"); | |
| 674 | + gpiochip_remove(chip); | |
| 653 | 675 | err_disable_clk: |
| 654 | 676 | clk_disable_unprepare(gpio->clk); |
| 655 | 677 | |
| @@ -664,16 +686,10 @@ err_disable_clk: · 8 unmodified lines | ||
| 664 | 686 | */ |
| 665 | 687 | static int zynq_gpio_remove(struct platform_device *pdev) |
| 666 | 688 | { |
| 667 | − int ret; | |
| 668 | 689 | struct zynq_gpio *gpio = platform_get_drvdata(pdev); |
| 669 | 690 | |
| 670 | 691 | pm_runtime_get_sync(&pdev->dev); |
| 671 | − | |
| 672 | − ret = gpiochip_remove(&gpio->chip); | |
| 673 | − if (ret) { | |
| 674 | − dev_err(&pdev->dev, "Failed to remove gpio chip\n"); | |
| 675 | − return ret; | |
| 676 | − } | |
| 692 | + gpiochip_remove(&gpio->chip); | |
| 677 | 693 | clk_disable_unprepare(gpio->clk); |
| 678 | 694 | device_set_wakeup_capable(&pdev->dev, 0); |
| 679 | 695 | return 0; |
| @@ -688,7 +704,6 @@ MODULE_DEVICE_TABLE(of, zynq_gpio_of_match); · 8 unmodified lines | ||
| 688 | 704 | static struct platform_driver zynq_gpio_driver = { |
| 689 | 705 | .driver = { |
| 690 | 706 | .name = DRIVER_NAME, |
| 691 | − .owner = THIS_MODULE, | |
| 692 | 707 | .pm = &zynq_gpio_dev_pm_ops, |
| 693 | 708 | .of_match_table = zynq_gpio_of_match, |
| 694 | 709 | }, |
| @@ -25,10 +25,12 @@ struct acpi_gpio_event { · 24 unmodified lines | ||
| 25 | 25 | acpi_handle handle; |
| 26 | 26 | unsigned int pin; |
| 27 | 27 | unsigned int irq; |
| 28 | + struct gpio_desc *desc; | |
| 28 | 29 | }; |
| 29 | 30 | |
| 30 | 31 | struct acpi_gpio_connection { |
| 31 | 32 | struct list_head node; |
| 33 | + unsigned int pin; | |
| 32 | 34 | struct gpio_desc *desc; |
| 33 | 35 | }; |
| 34 | 36 | |
| @@ -143,14 +145,8 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, · 108 unmodified lines | ||
| 143 | 145 | if (!handler) |
| 144 | 146 | return AE_BAD_PARAMETER; |
| 145 | 147 | |
| 146 | − desc = gpiochip_get_desc(chip, pin); | |
| 148 | + desc = gpiochip_request_own_desc(chip, pin, "ACPI:Event"); | |
| 147 | 149 | if (IS_ERR(desc)) { |
| 148 | − dev_err(chip->dev, "Failed to get GPIO descriptor\n"); | |
| 149 | − return AE_ERROR; | |
| 150 | − } | |
| 151 | − | |
| 152 | − ret = gpiochip_request_own_desc(desc, "ACPI:Event"); | |
| 153 | − if (ret) { | |
| 154 | 150 | dev_err(chip->dev, "Failed to request GPIO\n"); |
| 155 | 151 | return AE_ERROR; |
| 156 | 152 | } |
| @@ -197,6 +193,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, · 40 unmodified lines | ||
| 197 | 193 | event->handle = evt_handle; |
| 198 | 194 | event->irq = irq; |
| 199 | 195 | event->pin = pin; |
| 196 | + event->desc = desc; | |
| 200 | 197 | |
| 201 | 198 | ret = request_threaded_irq(event->irq, NULL, handler, irqflags, |
| 202 | 199 | "ACPI:Event", event); |
| @@ -280,7 +277,7 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) · 77 unmodified lines | ||
| 280 | 277 | struct gpio_desc *desc; |
| 281 | 278 | |
| 282 | 279 | free_irq(event->irq, event); |
| 283 | − desc = gpiochip_get_desc(chip, event->pin); | |
| 280 | + desc = event->desc; | |
| 284 | 281 | if (WARN_ON(IS_ERR(desc))) |
| 285 | 282 | continue; |
| 286 | 283 | gpio_unlock_as_irq(chip, event->pin); |
| @@ -409,26 +406,20 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, · 122 unmodified lines | ||
| 409 | 406 | struct gpio_desc *desc; |
| 410 | 407 | bool found; |
| 411 | 408 | |
| 412 | − desc = gpiochip_get_desc(chip, pin); | |
| 413 | − if (IS_ERR(desc)) { | |
| 414 | − status = AE_ERROR; | |
| 415 | − goto out; | |
| 416 | − } | |
| 417 | − | |
| 418 | 409 | mutex_lock(&achip->conn_lock); |
| 419 | 410 | |
| 420 | 411 | found = false; |
| 421 | 412 | list_for_each_entry(conn, &achip->conns, node) { |
| 422 | − if (conn->desc == desc) { | |
| 413 | + if (conn->pin == pin) { | |
| 423 | 414 | found = true; |
| 415 | + desc = conn->desc; | |
| 424 | 416 | break; |
| 425 | 417 | } |
| 426 | 418 | } |
| 427 | 419 | if (!found) { |
| 428 | − int ret; | |
| 429 | − | |
| 430 | − ret = gpiochip_request_own_desc(desc, "ACPI:OpRegion"); | |
| 431 | − if (ret) { | |
| 420 | + desc = gpiochip_request_own_desc(chip, pin, | |
| 421 | + "ACPI:OpRegion"); | |
| 422 | + if (IS_ERR(desc)) { | |
| 432 | 423 | status = AE_ERROR; |
| 433 | 424 | mutex_unlock(&achip->conn_lock); |
| 434 | 425 | goto out; |
| @@ -465,6 +456,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, · 30 unmodified lines | ||
| 465 | 456 | goto out; |
| 466 | 457 | } |
| 467 | 458 | |
| 459 | + conn->pin = pin; | |
| 468 | 460 | conn->desc = desc; |
| 469 | 461 | list_add_tail(&conn->node, &achip->conns); |
| 470 | 462 | } |
| @@ -308,10 +308,9 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); · 307 unmodified lines | ||
| 308 | 308 | * |
| 309 | 309 | * A gpio_chip with any GPIOs still requested may not be removed. |
| 310 | 310 | */ |
| 311 | −int gpiochip_remove(struct gpio_chip *chip) | |
| 311 | +void gpiochip_remove(struct gpio_chip *chip) | |
| 312 | 312 | { |
| 313 | 313 | unsigned long flags; |
| 314 | − int status = 0; | |
| 315 | 314 | unsigned id; |
| 316 | 315 | |
| 317 | 316 | acpi_gpiochip_remove(chip); |
| @@ -323,24 +322,15 @@ int gpiochip_remove(struct gpio_chip *chip) · 5 unmodified lines | ||
| 323 | 322 | of_gpiochip_remove(chip); |
| 324 | 323 | |
| 325 | 324 | for (id = 0; id < chip->ngpio; id++) { |
| 326 | − if (test_bit(FLAG_REQUESTED, &chip->desc[id].flags)) { | |
| 327 | − status = -EBUSY; | |
| 328 | − break; | |
| 329 | − } | |
| 330 | − } | |
| 331 | − if (status == 0) { | |
| 332 | − for (id = 0; id < chip->ngpio; id++) | |
| 333 | − chip->desc[id].chip = NULL; | |
| 334 | − | |
| 335 | − list_del(&chip->list); | |
| 325 | + if (test_bit(FLAG_REQUESTED, &chip->desc[id].flags)) | |
| 326 | + dev_crit(chip->dev, "REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n"); | |
| 336 | 327 | } |
| 328 | + for (id = 0; id < chip->ngpio; id++) | |
| 329 | + chip->desc[id].chip = NULL; | |
| 337 | 330 | |
| 331 | + list_del(&chip->list); | |
| 338 | 332 | spin_unlock_irqrestore(&gpio_lock, flags); |
| 339 | − | |
| 340 | − if (status == 0) | |
| 341 | − gpiochip_unexport(chip); | |
| 342 | − | |
| 343 | − return status; | |
| 333 | + gpiochip_unexport(chip); | |
| 344 | 334 | } |
| 345 | 335 | EXPORT_SYMBOL_GPL(gpiochip_remove); |
| 346 | 336 | |
| @@ -395,30 +385,47 @@ static struct gpio_chip *find_chip_by_name(const char *name) · 48 unmodified lines | ||
| 395 | 385 | */ |
| 396 | 386 | |
| 397 | 387 | /** |
| 398 | − * gpiochip_add_chained_irqchip() - adds a chained irqchip to a gpiochip | |
| 399 | − * @gpiochip: the gpiochip to add the irqchip to | |
| 400 | − * @irqchip: the irqchip to add to the gpiochip | |
| 388 | + * gpiochip_set_chained_irqchip() - sets a chained irqchip to a gpiochip | |
| 389 | + * @gpiochip: the gpiochip to set the irqchip chain to | |
| 390 | + * @irqchip: the irqchip to chain to the gpiochip | |
| 401 | 391 | * @parent_irq: the irq number corresponding to the parent IRQ for this |
| 402 | 392 | * chained irqchip |
| 403 | 393 | * @parent_handler: the parent interrupt handler for the accumulated IRQ |
| 404 | − * coming out of the gpiochip | |
| 394 | + * coming out of the gpiochip. If the interrupt is nested rather than | |
| 395 | + * cascaded, pass NULL in this handler argument | |
| 405 | 396 | */ |
| 406 | 397 | void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, |
| 407 | 398 | struct irq_chip *irqchip, |
| 408 | 399 | int parent_irq, |
| 409 | 400 | irq_flow_handler_t parent_handler) |
| 410 | 401 | { |
| 411 | − if (gpiochip->can_sleep) { | |
| 412 | − chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n"); | |
| 402 | + unsigned int offset; | |
| 403 | + | |
| 404 | + if (!gpiochip->irqdomain) { | |
| 405 | + chip_err(gpiochip, "called %s before setting up irqchip\n", | |
| 406 | + __func__); | |
| 413 | 407 | return; |
| 414 | 408 | } |
| 415 | 409 | |
| 416 | − /* | |
| 417 | − * The parent irqchip is already using the chip_data for this | |
| 418 | − * irqchip, so our callbacks simply use the handler_data. | |
| 419 | − */ | |
| 420 | − irq_set_handler_data(parent_irq, gpiochip); | |
| 421 | − irq_set_chained_handler(parent_irq, parent_handler); | |
| 410 | + if (parent_handler) { | |
| 411 | + if (gpiochip->can_sleep) { | |
| 412 | + chip_err(gpiochip, | |
| 413 | + "you cannot have chained interrupts on a " | |
| 414 | + "chip that may sleep\n"); | |
| 415 | + return; | |
| 416 | + } | |
| 417 | + /* | |
| 418 | + * The parent irqchip is already using the chip_data for this | |
| 419 | + * irqchip, so our callbacks simply use the handler_data. | |
| 420 | + */ | |
| 421 | + irq_set_handler_data(parent_irq, gpiochip); | |
| 422 | + irq_set_chained_handler(parent_irq, parent_handler); | |
| 423 | + } | |
| 424 | + | |
| 425 | + /* Set the parent IRQ for all affected IRQs */ | |
| 426 | + for (offset = 0; offset < gpiochip->ngpio; offset++) | |
| 427 | + irq_set_parent(irq_find_mapping(gpiochip->irqdomain, offset), | |
| 428 | + parent_irq); | |
| 422 | 429 | } |
| 423 | 430 | EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip); |
| 424 | 431 | |
| @@ -447,7 +454,7 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, · 22 unmodified lines | ||
| 447 | 454 | irq_set_lockdep_class(irq, &gpiochip_irq_lock_class); |
| 448 | 455 | irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler); |
| 449 | 456 | /* Chips that can sleep need nested thread handlers */ |
| 450 | − if (chip->can_sleep) | |
| 457 | + if (chip->can_sleep && !chip->irq_not_threaded) | |
| 451 | 458 | irq_set_nested_thread(irq, 1); |
| 452 | 459 | #ifdef CONFIG_ARM |
| 453 | 460 | set_irq_flags(irq, IRQF_VALID); |
| @@ -524,7 +531,8 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) · 70 unmodified lines | ||
| 524 | 531 | /* Remove all IRQ mappings and delete the domain */ |
| 525 | 532 | if (gpiochip->irqdomain) { |
| 526 | 533 | for (offset = 0; offset < gpiochip->ngpio; offset++) |
| 527 | − irq_dispose_mapping(gpiochip->irq_base + offset); | |
| 534 | + irq_dispose_mapping( | |
| 535 | + irq_find_mapping(gpiochip->irqdomain, offset)); | |
| 528 | 536 | irq_domain_remove(gpiochip->irqdomain); |
| 529 | 537 | } |
| 530 | 538 | |
| @@ -895,12 +903,22 @@ EXPORT_SYMBOL_GPL(gpiochip_is_requested); · 364 unmodified lines | ||
| 895 | 903 | * allows the GPIO chip module to be unloaded as needed (we assume that the |
| 896 | 904 | * GPIO chip driver handles freeing the GPIOs it has requested). |
| 897 | 905 | */ |
| 898 | −int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label) | |
| 906 | +struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, u16 hwnum, | |
| 907 | + const char *label) | |
| 899 | 908 | { |
| 900 | − if (!desc || !desc->chip) | |
| 901 | − return -EINVAL; | |
| 909 | + struct gpio_desc *desc = gpiochip_get_desc(chip, hwnum); | |
| 910 | + int err; | |
| 902 | 911 | |
| 903 | − return __gpiod_request(desc, label); | |
| 912 | + if (IS_ERR(desc)) { | |
| 913 | + chip_err(chip, "failed to get GPIO descriptor\n"); | |
| 914 | + return desc; | |
| 915 | + } | |
| 916 | + | |
| 917 | + err = __gpiod_request(desc, label); | |
| 918 | + if (err < 0) | |
| 919 | + return ERR_PTR(err); | |
| 920 | + | |
| 921 | + return desc; | |
| 904 | 922 | } |
| 905 | 923 | EXPORT_SYMBOL_GPL(gpiochip_request_own_desc); |
| 906 | 924 | |
| @@ -1652,7 +1670,7 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev, · 745 unmodified lines | ||
| 1652 | 1670 | * a result. In that case, use platform lookup as a fallback. |
| 1653 | 1671 | */ |
| 1654 | 1672 | if (!desc || desc == ERR_PTR(-ENOENT)) { |
| 1655 | − dev_dbg(dev, "using lookup tables for GPIO lookup"); | |
| 1673 | + dev_dbg(dev, "using lookup tables for GPIO lookup\n"); | |
| 1656 | 1674 | desc = gpiod_find(dev, con_id, idx, &lookupflags); |
| 1657 | 1675 | } |
| 1658 | 1676 | |
| @@ -1069,8 +1069,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) · 1068 unmodified lines | ||
| 1069 | 1069 | return ret; |
| 1070 | 1070 | |
| 1071 | 1071 | err_gpiochip_remove: |
| 1072 | − if (gpiochip_remove(&dev->gc) < 0) | |
| 1073 | − hid_err(hdev, "error removing gpio chip\n"); | |
| 1072 | + gpiochip_remove(&dev->gc); | |
| 1074 | 1073 | err_free_i2c: |
| 1075 | 1074 | i2c_del_adapter(&dev->adap); |
| 1076 | 1075 | err_free_dev: |
| @@ -1089,8 +1088,7 @@ static void cp2112_remove(struct hid_device *hdev) · 12 unmodified lines | ||
| 1089 | 1088 | struct cp2112_device *dev = hid_get_drvdata(hdev); |
| 1090 | 1089 | |
| 1091 | 1090 | sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group); |
| 1092 | − if (gpiochip_remove(&dev->gc)) | |
| 1093 | − hid_err(hdev, "unable to remove gpio chip\n"); | |
| 1091 | + gpiochip_remove(&dev->gc); | |
| 1094 | 1092 | i2c_del_adapter(&dev->adap); |
| 1095 | 1093 | /* i2c_del_adapter has finished removing all i2c devices from our |
| 1096 | 1094 | * adapter. Well behaved devices should no longer call our cp2112_xfer |
| @@ -251,9 +251,7 @@ static void adp5588_gpio_remove(struct adp5588_kpad *kpad) · 250 unmodified lines | ||
| 251 | 251 | dev_warn(dev, "teardown failed %d\n", error); |
| 252 | 252 | } |
| 253 | 253 | |
| 254 | − error = gpiochip_remove(&kpad->gc); | |
| 255 | − if (error) | |
| 256 | − dev_warn(dev, "gpiochip_remove failed %d\n", error); | |
| 254 | + gpiochip_remove(&kpad->gc); | |
| 257 | 255 | } |
| 258 | 256 | #else |
| 259 | 257 | static inline int adp5588_gpio_add(struct adp5588_kpad *kpad) |
| @@ -567,9 +567,7 @@ static void adp5589_gpio_remove(struct adp5589_kpad *kpad) · 566 unmodified lines | ||
| 567 | 567 | dev_warn(dev, "teardown failed %d\n", error); |
| 568 | 568 | } |
| 569 | 569 | |
| 570 | − error = gpiochip_remove(&kpad->gc); | |
| 571 | − if (error) | |
| 572 | − dev_warn(dev, "gpiochip_remove failed %d\n", error); | |
| 570 | + gpiochip_remove(&kpad->gc); | |
| 573 | 571 | } |
| 574 | 572 | #else |
| 575 | 573 | static inline int adp5589_gpio_add(struct adp5589_kpad *kpad) |
| @@ -470,14 +470,10 @@ static int ad7879_gpio_add(struct ad7879 *ts, · 469 unmodified lines | ||
| 470 | 470 | static void ad7879_gpio_remove(struct ad7879 *ts) |
| 471 | 471 | { |
| 472 | 472 | const struct ad7879_platform_data *pdata = dev_get_platdata(ts->dev); |
| 473 | − int ret; | |
| 474 | 473 | |
| 475 | − if (pdata->gpio_export) { | |
| 476 | − ret = gpiochip_remove(&ts->gc); | |
| 477 | − if (ret) | |
| 478 | − dev_err(ts->dev, "failed to remove gpio %d\n", | |
| 479 | − ts->gc.base); | |
| 480 | − } | |
| 474 | + if (pdata->gpio_export) | |
| 475 | + gpiochip_remove(&ts->gc); | |
| 476 | + | |
| 481 | 477 | } |
| 482 | 478 | #else |
| 483 | 479 | static inline int ad7879_gpio_add(struct ad7879 *ts, |
| @@ -319,14 +319,8 @@ static int pca9532_destroy_devices(struct pca9532_data *data, int n_devs) · 318 unmodified lines | ||
| 319 | 319 | } |
| 320 | 320 | |
| 321 | 321 | #ifdef CONFIG_LEDS_PCA9532_GPIO |
| 322 | − if (data->gpio.dev) { | |
| 323 | − int err = gpiochip_remove(&data->gpio); | |
| 324 | − if (err) { | |
| 325 | − dev_err(&data->client->dev, "%s failed, %d\n", | |
| 326 | − "gpiochip_remove()", err); | |
| 327 | − return err; | |
| 328 | − } | |
| 329 | − } | |
| 322 | + if (data->gpio.dev) | |
| 323 | + gpiochip_remove(&data->gpio); | |
| 330 | 324 | #endif |
| 331 | 325 | |
| 332 | 326 | return 0; |
| @@ -667,11 +667,8 @@ static int tca6507_probe_gpios(struct i2c_client *client, · 666 unmodified lines | ||
| 667 | 667 | |
| 668 | 668 | static void tca6507_remove_gpio(struct tca6507_chip *tca) |
| 669 | 669 | { |
| 670 | − if (tca->gpio.ngpio) { | |
| 671 | − int err = gpiochip_remove(&tca->gpio); | |
| 672 | − dev_err(&tca->client->dev, "%s failed, %d\n", | |
| 673 | − "gpiochip_remove()", err); | |
| 674 | − } | |
| 670 | + if (tca->gpio.ngpio) | |
| 671 | + gpiochip_remove(&tca->gpio); | |
| 675 | 672 | } |
| 676 | 673 | #else /* CONFIG_GPIOLIB */ |
| 677 | 674 | static int tca6507_probe_gpios(struct i2c_client *client, |
| @@ -584,18 +584,14 @@ static int cxd2820r_get_frontend_algo(struct dvb_frontend *fe) · 583 unmodified lines | ||
| 584 | 584 | static void cxd2820r_release(struct dvb_frontend *fe) |
| 585 | 585 | { |
| 586 | 586 | struct cxd2820r_priv *priv = fe->demodulator_priv; |
| 587 | − int uninitialized_var(ret); /* silence compiler warning */ | |
| 588 | 587 | |
| 589 | 588 | dev_dbg(&priv->i2c->dev, "%s\n", __func__); |
| 590 | 589 | |
| 591 | 590 | #ifdef CONFIG_GPIOLIB |
| 592 | 591 | /* remove GPIOs */ |
| 593 | − if (priv->gpio_chip.label) { | |
| 594 | − ret = gpiochip_remove(&priv->gpio_chip); | |
| 595 | − if (ret) | |
| 596 | − dev_err(&priv->i2c->dev, "%s: gpiochip_remove() " \ | |
| 597 | − "failed=%d\n", KBUILD_MODNAME, ret); | |
| 598 | − } | |
| 592 | + if (priv->gpio_chip.label) | |
| 593 | + gpiochip_remove(&priv->gpio_chip); | |
| 594 | + | |
| 599 | 595 | #endif |
| 600 | 596 | kfree(priv); |
| 601 | 597 | return; |
| @@ -605,7 +605,8 @@ static int asic3_gpio_remove(struct platform_device *pdev) · 604 unmodified lines | ||
| 605 | 605 | { |
| 606 | 606 | struct asic3 *asic = platform_get_drvdata(pdev); |
| 607 | 607 | |
| 608 | − return gpiochip_remove(&asic->gpio); | |
| 608 | + gpiochip_remove(&asic->gpio); | |
| 609 | + return 0; | |
| 609 | 610 | } |
| 610 | 611 | |
| 611 | 612 | static void asic3_clk_enable(struct asic3 *asic, struct asic3_clk *clk) |
| @@ -481,15 +481,9 @@ static int htcpld_register_chip_gpio( · 480 unmodified lines | ||
| 481 | 481 | |
| 482 | 482 | ret = gpiochip_add(&(chip->chip_in)); |
| 483 | 483 | if (ret) { |
| 484 | − int error; | |
| 485 | − | |
| 486 | 484 | dev_warn(dev, "Unable to register input GPIOs for 0x%x: %d\n", |
| 487 | 485 | plat_chip_data->addr, ret); |
| 488 | − | |
| 489 | − error = gpiochip_remove(&(chip->chip_out)); | |
| 490 | − if (error) | |
| 491 | − dev_warn(dev, "Error while trying to unregister gpio chip: %d\n", error); | |
| 492 | − | |
| 486 | + gpiochip_remove(&(chip->chip_out)); | |
| 493 | 487 | return ret; |
| 494 | 488 | } |
| 495 | 489 | |
| @@ -1047,7 +1047,6 @@ static int sm501_register_gpio(struct sm501_devdata *sm) · 1046 unmodified lines | ||
| 1047 | 1047 | struct sm501_gpio *gpio = &sm->gpio; |
| 1048 | 1048 | resource_size_t iobase = sm->io_res->start + SM501_GPIO; |
| 1049 | 1049 | int ret; |
| 1050 | − int tmp; | |
| 1051 | 1050 | |
| 1052 | 1051 | dev_dbg(sm->dev, "registering gpio block %08llx\n", |
| 1053 | 1052 | (unsigned long long)iobase); |
| @@ -1086,11 +1085,7 @@ static int sm501_register_gpio(struct sm501_devdata *sm) · 32 unmodified lines | ||
| 1086 | 1085 | return 0; |
| 1087 | 1086 | |
| 1088 | 1087 | err_low_chip: |
| 1089 | − tmp = gpiochip_remove(&gpio->low.gpio); | |
| 1090 | − if (tmp) { | |
| 1091 | − dev_err(sm->dev, "cannot remove low chip, cannot tidy up\n"); | |
| 1092 | − return ret; | |
| 1093 | − } | |
| 1088 | + gpiochip_remove(&gpio->low.gpio); | |
| 1094 | 1089 | |
| 1095 | 1090 | err_mapped: |
| 1096 | 1091 | iounmap(gpio->regs); |
| @@ -1105,18 +1100,12 @@ static int sm501_register_gpio(struct sm501_devdata *sm) · 8 unmodified lines | ||
| 1105 | 1100 | static void sm501_gpio_remove(struct sm501_devdata *sm) |
| 1106 | 1101 | { |
| 1107 | 1102 | struct sm501_gpio *gpio = &sm->gpio; |
| 1108 | − int ret; | |
| 1109 | 1103 | |
| 1110 | 1104 | if (!sm->gpio.registered) |
| 1111 | 1105 | return; |
| 1112 | 1106 | |
| 1113 | − ret = gpiochip_remove(&gpio->low.gpio); | |
| 1114 | − if (ret) | |
| 1115 | − dev_err(sm->dev, "cannot remove low chip, cannot tidy up\n"); | |
| 1116 | − | |
| 1117 | − ret = gpiochip_remove(&gpio->high.gpio); | |
| 1118 | − if (ret) | |
| 1119 | − dev_err(sm->dev, "cannot remove high chip, cannot tidy up\n"); | |
| 1107 | + gpiochip_remove(&gpio->low.gpio); | |
| 1108 | + gpiochip_remove(&gpio->high.gpio); | |
| 1120 | 1109 | |
| 1121 | 1110 | iounmap(gpio->regs); |
| 1122 | 1111 | release_resource(gpio->regs_res); |
| @@ -607,7 +607,7 @@ static int tc6393xb_probe(struct platform_device *dev) · 606 unmodified lines | ||
| 607 | 607 | struct tc6393xb_platform_data *tcpd = dev_get_platdata(&dev->dev); |
| 608 | 608 | struct tc6393xb *tc6393xb; |
| 609 | 609 | struct resource *iomem, *rscr; |
| 610 | − int ret, temp; | |
| 610 | + int ret; | |
| 611 | 611 | |
| 612 | 612 | iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); |
| 613 | 613 | if (!iomem) |
| @@ -714,7 +714,7 @@ err_setup: · 100 unmodified lines | ||
| 714 | 714 | |
| 715 | 715 | err_gpio_add: |
| 716 | 716 | if (tc6393xb->gpio.base != -1) |
| 717 | − temp = gpiochip_remove(&tc6393xb->gpio); | |
| 717 | + gpiochip_remove(&tc6393xb->gpio); | |
| 718 | 718 | tcpd->disable(dev); |
| 719 | 719 | err_enable: |
| 720 | 720 | clk_disable(tc6393xb->clk); |
| @@ -744,13 +744,8 @@ static int tc6393xb_remove(struct platform_device *dev) · 23 unmodified lines | ||
| 744 | 744 | |
| 745 | 745 | tc6393xb_detach_irq(dev); |
| 746 | 746 | |
| 747 | − if (tc6393xb->gpio.base != -1) { | |
| 748 | − ret = gpiochip_remove(&tc6393xb->gpio); | |
| 749 | − if (ret) { | |
| 750 | − dev_err(&dev->dev, "Can't remove gpio chip: %d\n", ret); | |
| 751 | − return ret; | |
| 752 | − } | |
| 753 | − } | |
| 747 | + if (tc6393xb->gpio.base != -1) | |
| 748 | + gpiochip_remove(&tc6393xb->gpio); | |
| 754 | 749 | |
| 755 | 750 | ret = tcpd->disable(dev); |
| 756 | 751 | clk_disable(tc6393xb->clk); |
| @@ -621,7 +621,6 @@ static void ucb1x00_remove(struct mcp *mcp) · 620 unmodified lines | ||
| 621 | 621 | struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data; |
| 622 | 622 | struct ucb1x00 *ucb = mcp_get_drvdata(mcp); |
| 623 | 623 | struct list_head *l, *n; |
| 624 | − int ret; | |
| 625 | 624 | |
| 626 | 625 | mutex_lock(&ucb1x00_mutex); |
| 627 | 626 | list_del(&ucb->node); |
| @@ -631,11 +630,8 @@ static void ucb1x00_remove(struct mcp *mcp) · 3 unmodified lines | ||
| 631 | 630 | } |
| 632 | 631 | mutex_unlock(&ucb1x00_mutex); |
| 633 | 632 | |
| 634 | − if (ucb->gpio.base != -1) { | |
| 635 | − ret = gpiochip_remove(&ucb->gpio); | |
| 636 | − if (ret) | |
| 637 | − dev_err(&ucb->dev, "Can't remove gpio chip: %d\n", ret); | |
| 638 | − } | |
| 633 | + if (ucb->gpio.base != -1) | |
| 634 | + gpiochip_remove(&ucb->gpio); | |
| 639 | 635 | |
| 640 | 636 | irq_set_chained_handler(ucb->irq, NULL); |
| 641 | 637 | irq_free_descs(ucb->irq_base, 16); |
| @@ -86,7 +86,7 @@ config PINCTRL_BCM2835 · 85 unmodified lines | ||
| 86 | 86 | |
| 87 | 87 | config PINCTRL_BCM281XX |
| 88 | 88 | bool "Broadcom BCM281xx pinctrl driver" |
| 89 | − depends on OF | |
| 89 | + depends on OF && (ARCH_BCM_MOBILE || COMPILE_TEST) | |
| 90 | 90 | select PINMUX |
| 91 | 91 | select PINCONF |
| 92 | 92 | select GENERIC_PINCONF |
| @@ -1174,7 +1174,7 @@ static int abx500_gpio_probe(struct platform_device *pdev) · 1173 unmodified lines | ||
| 1174 | 1174 | const struct of_device_id *match; |
| 1175 | 1175 | struct abx500_pinctrl *pct; |
| 1176 | 1176 | unsigned int id = -1; |
| 1177 | − int ret, err; | |
| 1177 | + int ret; | |
| 1178 | 1178 | int i; |
| 1179 | 1179 | |
| 1180 | 1180 | if (!np) { |
| @@ -1266,10 +1266,7 @@ static int abx500_gpio_probe(struct platform_device *pdev) · 85 unmodified lines | ||
| 1266 | 1266 | return 0; |
| 1267 | 1267 | |
| 1268 | 1268 | out_rem_chip: |
| 1269 | − err = gpiochip_remove(&pct->chip); | |
| 1270 | − if (err) | |
| 1271 | − dev_info(&pdev->dev, "failed to remove gpiochip\n"); | |
| 1272 | − | |
| 1269 | + gpiochip_remove(&pct->chip); | |
| 1273 | 1270 | return ret; |
| 1274 | 1271 | } |
| 1275 | 1272 | |
| @@ -1280,15 +1277,8 @@ out_rem_chip: · 4 unmodified lines | ||
| 1280 | 1277 | static int abx500_gpio_remove(struct platform_device *pdev) |
| 1281 | 1278 | { |
| 1282 | 1279 | struct abx500_pinctrl *pct = platform_get_drvdata(pdev); |
| 1283 | − int ret; | |
| 1284 | − | |
| 1285 | − ret = gpiochip_remove(&pct->chip); | |
| 1286 | − if (ret < 0) { | |
| 1287 | − dev_err(pct->dev, "unable to remove gpiochip: %d\n", | |
| 1288 | − ret); | |
| 1289 | − return ret; | |
| 1290 | − } | |
| 1291 | 1280 | |
| 1281 | + gpiochip_remove(&pct->chip); | |
| 1292 | 1282 | return 0; |
| 1293 | 1283 | } |
| 1294 | 1284 | |
| @@ -1276,7 +1276,7 @@ static int nmk_gpio_probe(struct platform_device *dev) · 1275 unmodified lines | ||
| 1276 | 1276 | IRQ_TYPE_EDGE_FALLING); |
| 1277 | 1277 | if (ret) { |
| 1278 | 1278 | dev_err(&dev->dev, "could not add irqchip\n"); |
| 1279 | − ret = gpiochip_remove(&nmk_chip->chip); | |
| 1279 | + gpiochip_remove(&nmk_chip->chip); | |
| 1280 | 1280 | return -ENODEV; |
| 1281 | 1281 | } |
| 1282 | 1282 | /* Then register the chain on the parent IRQ */ |
| @@ -936,14 +936,8 @@ EXPORT_SYMBOL(msm_pinctrl_probe); · 935 unmodified lines | ||
| 936 | 936 | int msm_pinctrl_remove(struct platform_device *pdev) |
| 937 | 937 | { |
| 938 | 938 | struct msm_pinctrl *pctrl = platform_get_drvdata(pdev); |
| 939 | − int ret; | |
| 940 | − | |
| 941 | − ret = gpiochip_remove(&pctrl->chip); | |
| 942 | − if (ret) { | |
| 943 | − dev_err(&pdev->dev, "Failed to remove gpiochip\n"); | |
| 944 | − return ret; | |
| 945 | − } | |
| 946 | 939 | |
| 940 | + gpiochip_remove(&pctrl->chip); | |
| 947 | 941 | pinctrl_unregister(pctrl->pctrl); |
| 948 | 942 | |
| 949 | 943 | unregister_restart_handler(&pctrl->restart_nb); |
| @@ -874,11 +874,7 @@ static int exynos5440_gpiolib_register(struct platform_device *pdev, · 873 unmodified lines | ||
| 874 | 874 | static int exynos5440_gpiolib_unregister(struct platform_device *pdev, |
| 875 | 875 | struct exynos5440_pinctrl_priv_data *priv) |
| 876 | 876 | { |
| 877 | − int ret = gpiochip_remove(priv->gc); | |
| 878 | − if (ret) { | |
| 879 | − dev_err(&pdev->dev, "gpio chip remove failed\n"); | |
| 880 | − return ret; | |
| 881 | − } | |
| 877 | + gpiochip_remove(priv->gc); | |
| 882 | 878 | return 0; |
| 883 | 879 | } |
| 884 | 880 | |
| @@ -946,9 +946,7 @@ static int samsung_gpiolib_register(struct platform_device *pdev, · 945 unmodified lines | ||
| 946 | 946 | |
| 947 | 947 | fail: |
| 948 | 948 | for (--i, --bank; i >= 0; --i, --bank) |
| 949 | − if (gpiochip_remove(&bank->gpio_chip)) | |
| 950 | − dev_err(&pdev->dev, "gpio chip %s remove failed\n", | |
| 951 | − bank->gpio_chip.label); | |
| 949 | + gpiochip_remove(&bank->gpio_chip); | |
| 952 | 950 | return ret; |
| 953 | 951 | } |
| 954 | 952 | |
| @@ -958,16 +956,11 @@ static int samsung_gpiolib_unregister(struct platform_device *pdev, · 3 unmodified lines | ||
| 958 | 956 | { |
| 959 | 957 | struct samsung_pin_ctrl *ctrl = drvdata->ctrl; |
| 960 | 958 | struct samsung_pin_bank *bank = ctrl->pin_banks; |
| 961 | − int ret = 0; | |
| 962 | 959 | int i; |
| 963 | 960 | |
| 964 | − for (i = 0; !ret && i < ctrl->nr_banks; ++i, ++bank) | |
| 965 | − ret = gpiochip_remove(&bank->gpio_chip); | |
| 966 | − | |
| 967 | − if (ret) | |
| 968 | − dev_err(&pdev->dev, "gpio chip remove failed\n"); | |
| 969 | − | |
| 970 | − return ret; | |
| 961 | + for (i = 0; i < ctrl->nr_banks; ++i, ++bank) | |
| 962 | + gpiochip_remove(&bank->gpio_chip); | |
| 963 | + return 0; | |
| 971 | 964 | } |
| 972 | 965 | |
| 973 | 966 | static const struct of_device_id samsung_pinctrl_dt_match[]; |
| @@ -891,8 +891,7 @@ static int sirfsoc_gpio_probe(struct device_node *np) · 890 unmodified lines | ||
| 891 | 891 | |
| 892 | 892 | out_no_range: |
| 893 | 893 | out_banks: |
| 894 | − if (gpiochip_remove(&sgpio->chip.gc)) | |
| 895 | − dev_err(&pdev->dev, "could not remove gpio chip\n"); | |
| 894 | + gpiochip_remove(&sgpio->chip.gc); | |
| 896 | 895 | out: |
| 897 | 896 | iounmap(regs); |
| 898 | 897 | return err; |
| @@ -301,8 +301,7 @@ static int platform_pmic_gpio_probe(struct platform_device *pdev) · 300 unmodified lines | ||
| 301 | 301 | return 0; |
| 302 | 302 | |
| 303 | 303 | fail_request_irq: |
| 304 | − if (gpiochip_remove(&pg->chip)) | |
| 305 | − pr_err("gpiochip_remove failed\n"); | |
| 304 | + gpiochip_remove(&pg->chip); | |
| 306 | 305 | err: |
| 307 | 306 | iounmap(pg->gpiointr); |
| 308 | 307 | err2: |
| @@ -475,7 +475,8 @@ int ssb_gpio_unregister(struct ssb_bus *bus) · 474 unmodified lines | ||
| 475 | 475 | { |
| 476 | 476 | if (ssb_chipco_available(&bus->chipco) || |
| 477 | 477 | ssb_extif_available(&bus->extif)) { |
| 478 | − return gpiochip_remove(&bus->gpio); | |
| 478 | + gpiochip_remove(&bus->gpio); | |
| 479 | + return 0; | |
| 479 | 480 | } else { |
| 480 | 481 | SSB_WARN_ON(1); |
| 481 | 482 | } |
| @@ -221,9 +221,7 @@ void pio2_gpio_exit(struct pio2_card *card) · 220 unmodified lines | ||
| 221 | 221 | { |
| 222 | 222 | const char *label = card->gc.label; |
| 223 | 223 | |
| 224 | − if (gpiochip_remove(&(card->gc))) | |
| 225 | − dev_err(&card->vdev->dev, "Failed to remove GPIO\n"); | |
| 226 | − | |
| 224 | + gpiochip_remove(&(card->gc)); | |
| 227 | 225 | kfree(label); |
| 228 | 226 | } |
| 229 | 227 | |
| @@ -1248,7 +1248,7 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, · 1247 unmodified lines | ||
| 1248 | 1248 | mutex_destroy(&s->mutex); |
| 1249 | 1249 | |
| 1250 | 1250 | #ifdef CONFIG_GPIOLIB |
| 1251 | − WARN_ON(gpiochip_remove(&s->gpio)); | |
| 1251 | + gpiochip_remove(&s->gpio); | |
| 1252 | 1252 | |
| 1253 | 1253 | out_uart: |
| 1254 | 1254 | #endif |
| @@ -1263,12 +1263,10 @@ out_clk: · 8 unmodified lines | ||
| 1263 | 1263 | static int max310x_remove(struct device *dev) |
| 1264 | 1264 | { |
| 1265 | 1265 | struct max310x_port *s = dev_get_drvdata(dev); |
| 1266 | − int i, ret = 0; | |
| 1266 | + int i; | |
| 1267 | 1267 | |
| 1268 | 1268 | #ifdef CONFIG_GPIOLIB |
| 1269 | − ret = gpiochip_remove(&s->gpio); | |
| 1270 | − if (ret) | |
| 1271 | − return ret; | |
| 1269 | + gpiochip_remove(&s->gpio); | |
| 1272 | 1270 | #endif |
| 1273 | 1271 | |
| 1274 | 1272 | for (i = 0; i < s->uart.nr; i++) { |
| @@ -1282,7 +1280,7 @@ static int max310x_remove(struct device *dev) · 7 unmodified lines | ||
| 1282 | 1280 | uart_unregister_driver(&s->uart); |
| 1283 | 1281 | clk_disable_unprepare(s->clk); |
| 1284 | 1282 | |
| 1285 | − return ret; | |
| 1283 | + return 0; | |
| 1286 | 1284 | } |
| 1287 | 1285 | |
| 1288 | 1286 | static const struct of_device_id __maybe_unused max310x_dt_ids[] = { |
| @@ -1157,7 +1157,7 @@ static int sc16is7xx_probe(struct device *dev, · 1156 unmodified lines | ||
| 1157 | 1157 | |
| 1158 | 1158 | #ifdef CONFIG_GPIOLIB |
| 1159 | 1159 | if (devtype->nr_gpio) |
| 1160 | − WARN_ON(gpiochip_remove(&s->gpio)); | |
| 1160 | + gpiochip_remove(&s->gpio); | |
| 1161 | 1161 | |
| 1162 | 1162 | out_uart: |
| 1163 | 1163 | #endif |
| @@ -1173,14 +1173,11 @@ out_clk: · 9 unmodified lines | ||
| 1173 | 1173 | static int sc16is7xx_remove(struct device *dev) |
| 1174 | 1174 | { |
| 1175 | 1175 | struct sc16is7xx_port *s = dev_get_drvdata(dev); |
| 1176 | − int i, ret = 0; | |
| 1176 | + int i; | |
| 1177 | 1177 | |
| 1178 | 1178 | #ifdef CONFIG_GPIOLIB |
| 1179 | − if (s->devtype->nr_gpio) { | |
| 1180 | − ret = gpiochip_remove(&s->gpio); | |
| 1181 | − if (ret) | |
| 1182 | − return ret; | |
| 1183 | − } | |
| 1179 | + if (s->devtype->nr_gpio) | |
| 1180 | + gpiochip_remove(&s->gpio); | |
| 1184 | 1181 | #endif |
| 1185 | 1182 | |
| 1186 | 1183 | for (i = 0; i < s->uart.nr; i++) { |
| @@ -1195,7 +1192,7 @@ static int sc16is7xx_remove(struct device *dev) · 8 unmodified lines | ||
| 1195 | 1192 | if (!IS_ERR(s->clk)) |
| 1196 | 1193 | clk_disable_unprepare(s->clk); |
| 1197 | 1194 | |
| 1198 | − return ret; | |
| 1195 | + return 0; | |
| 1199 | 1196 | } |
| 1200 | 1197 | |
| 1201 | 1198 | static const struct of_device_id __maybe_unused sc16is7xx_dt_ids[] = { |
| @@ -270,7 +270,7 @@ static int viafb_gpio_probe(struct platform_device *platdev) · 269 unmodified lines | ||
| 270 | 270 | static int viafb_gpio_remove(struct platform_device *platdev) |
| 271 | 271 | { |
| 272 | 272 | unsigned long flags; |
| 273 | − int ret = 0, i; | |
| 273 | + int i; | |
| 274 | 274 | |
| 275 | 275 | #ifdef CONFIG_PM |
| 276 | 276 | viafb_pm_unregister(&viafb_gpio_pm_hooks); |
| @@ -280,11 +280,7 @@ static int viafb_gpio_remove(struct platform_device *platdev) · 3 unmodified lines | ||
| 280 | 280 | * Get unregistered. |
| 281 | 281 | */ |
| 282 | 282 | if (viafb_gpio_config.gpio_chip.ngpio > 0) { |
| 283 | − ret = gpiochip_remove(&viafb_gpio_config.gpio_chip); | |
| 284 | − if (ret) { /* Somebody still using it? */ | |
| 285 | − printk(KERN_ERR "Viafb: GPIO remove failed\n"); | |
| 286 | − return ret; | |
| 287 | − } | |
| 283 | + gpiochip_remove(&viafb_gpio_config.gpio_chip); | |
| 288 | 284 | } |
| 289 | 285 | /* |
| 290 | 286 | * Disable the ports. |
| @@ -294,7 +290,7 @@ static int viafb_gpio_remove(struct platform_device *platdev) · 3 unmodified lines | ||
| 294 | 290 | viafb_gpio_disable(viafb_gpio_config.active_gpios[i]); |
| 295 | 291 | viafb_gpio_config.gpio_chip.ngpio = 0; |
| 296 | 292 | spin_unlock_irqrestore(&viafb_gpio_config.vdev->reg_lock, flags); |
| 297 | − return ret; | |
| 293 | + return 0; | |
| 298 | 294 | } |
| 299 | 295 | |
| 300 | 296 | static struct platform_driver via_gpio_driver = { |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | */ |
| 28 | 28 | |
| 29 | 29 | #ifndef ARCH_NR_GPIOS |
| 30 | −#define ARCH_NR_GPIOS 256 | |
| 30 | +#define ARCH_NR_GPIOS 512 | |
| 31 | 31 | #endif |
| 32 | 32 | |
| 33 | 33 | /* |
| @@ -56,6 +56,8 @@ struct seq_file; · 55 unmodified lines | ||
| 56 | 56 | * as the chip access may sleep when e.g. reading out the IRQ status |
| 57 | 57 | * registers. |
| 58 | 58 | * @exported: flags if the gpiochip is exported for use from sysfs. Private. |
| 59 | + * @irq_not_threaded: flag must be set if @can_sleep is set but the | |
| 60 | + * IRQs don't need to be threaded | |
| 59 | 61 | * |
| 60 | 62 | * A gpio_chip can help platforms abstract various sources of GPIOs so |
| 61 | 63 | * they can all be accessed through a common programing interface. |
| @@ -101,6 +103,7 @@ struct gpio_chip { · 39 unmodified lines | ||
| 101 | 103 | struct gpio_desc *desc; |
| 102 | 104 | const char *const *names; |
| 103 | 105 | bool can_sleep; |
| 106 | + bool irq_not_threaded; | |
| 104 | 107 | bool exported; |
| 105 | 108 | |
| 106 | 109 | #ifdef CONFIG_GPIOLIB_IRQCHIP |
| @@ -141,7 +144,7 @@ extern const char *gpiochip_is_requested(struct gpio_chip *chip, · 34 unmodified lines | ||
| 141 | 144 | |
| 142 | 145 | /* add/remove chips */ |
| 143 | 146 | extern int gpiochip_add(struct gpio_chip *chip); |
| 144 | −extern int gpiochip_remove(struct gpio_chip *chip); | |
| 147 | +extern void gpiochip_remove(struct gpio_chip *chip); | |
| 145 | 148 | extern struct gpio_chip *gpiochip_find(void *data, |
| 146 | 149 | int (*match)(struct gpio_chip *chip, void *data)); |
| 147 | 150 | |
| @@ -166,7 +169,8 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip, · 18 unmodified lines | ||
| 166 | 169 | |
| 167 | 170 | #endif /* CONFIG_GPIOLIB_IRQCHIP */ |
| 168 | 171 | |
| 169 | −int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label); | |
| 172 | +struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, u16 hwnum, | |
| 173 | + const char *label); | |
| 170 | 174 | void gpiochip_free_own_desc(struct gpio_desc *desc); |
| 171 | 175 | |
| 172 | 176 | #else /* CONFIG_GPIOLIB */ |
| @@ -0,0 +1,32 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright(c) 2014 Intel Corporation. | |
| 3 | + * | |
| 4 | + * This program is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms and conditions of the GNU General Public License, | |
| 6 | + * version 2, as published by the Free Software Foundation. | |
| 7 | + * | |
| 8 | + * This program is distributed in the hope it will be useful, but WITHOUT | |
| 9 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 10 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
| 11 | + * more details. | |
| 12 | + */ | |
| 13 | + | |
| 14 | +#ifndef GPIO_DW_APB_H | |
| 15 | +#define GPIO_DW_APB_H | |
| 16 | + | |
| 17 | +struct dwapb_port_property { | |
| 18 | + struct device_node *node; | |
| 19 | + const char *name; | |
| 20 | + unsigned int idx; | |
| 21 | + unsigned int ngpio; | |
| 22 | + unsigned int gpio_base; | |
| 23 | + unsigned int irq; | |
| 24 | + bool irq_shared; | |
| 25 | +}; | |
| 26 | + | |
| 27 | +struct dwapb_platform_data { | |
| 28 | + struct dwapb_port_property *properties; | |
| 29 | + unsigned int nports; | |
| 30 | +}; | |
| 31 | + | |
| 32 | +#endif | |
| @@ -22,4 +22,22 @@ struct mcp23s08_platform_data { · 21 unmodified lines | ||
| 22 | 22 | * base to base+15 (or base+31 for s17 variant). |
| 23 | 23 | */ |
| 24 | 24 | unsigned base; |
| 25 | + /* Marks the device as a interrupt controller. | |
| 26 | + * NOTE: The interrupt functionality is only supported for i2c | |
| 27 | + * versions of the chips. The spi chips can also do the interrupts, | |
| 28 | + * but this is not supported by the linux driver yet. | |
| 29 | + */ | |
| 30 | + bool irq_controller; | |
| 31 | + | |
| 32 | + /* Sets the mirror flag in the IOCON register. Devices | |
| 33 | + * with two interrupt outputs (these are the devices ending with 17 and | |
| 34 | + * those that have 16 IOs) have two IO banks: IO 0-7 form bank 1 and | |
| 35 | + * IO 8-15 are bank 2. These chips have two different interrupt outputs: | |
| 36 | + * One for bank 1 and another for bank 2. If irq-mirror is set, both | |
| 37 | + * interrupts are generated regardless of the bank that an input change | |
| 38 | + * occurred on. If it is not set, the interrupt are only generated for | |
| 39 | + * the bank they belong to. | |
| 40 | + * On devices with only one interrupt output this property is useless. | |
| 41 | + */ | |
| 42 | + bool mirror; | |
| 25 | 43 | }; |
| @@ -2319,11 +2319,8 @@ static void wm5100_init_gpio(struct i2c_client *i2c) · 2318 unmodified lines | ||
| 2319 | 2319 | static void wm5100_free_gpio(struct i2c_client *i2c) |
| 2320 | 2320 | { |
| 2321 | 2321 | struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c); |
| 2322 | − int ret; | |
| 2323 | 2322 | |
| 2324 | − ret = gpiochip_remove(&wm5100->gpio_chip); | |
| 2325 | − if (ret != 0) | |
| 2326 | − dev_err(&i2c->dev, "Failed to remove GPIOs: %d\n", ret); | |
| 2323 | + gpiochip_remove(&wm5100->gpio_chip); | |
| 2327 | 2324 | } |
| 2328 | 2325 | #else |
| 2329 | 2326 | static void wm5100_init_gpio(struct i2c_client *i2c) |
| @@ -1877,11 +1877,7 @@ static void wm8903_init_gpio(struct wm8903_priv *wm8903) · 1876 unmodified lines | ||
| 1877 | 1877 | |
| 1878 | 1878 | static void wm8903_free_gpio(struct wm8903_priv *wm8903) |
| 1879 | 1879 | { |
| 1880 | − int ret; | |
| 1881 | − | |
| 1882 | − ret = gpiochip_remove(&wm8903->gpio_chip); | |
| 1883 | − if (ret != 0) | |
| 1884 | − dev_err(wm8903->dev, "Failed to remove GPIOs: %d\n", ret); | |
| 1880 | + gpiochip_remove(&wm8903->gpio_chip); | |
| 1885 | 1881 | } |
| 1886 | 1882 | #else |
| 1887 | 1883 | static void wm8903_init_gpio(struct wm8903_priv *wm8903) |
| @@ -3398,11 +3398,8 @@ static void wm8962_init_gpio(struct snd_soc_codec *codec) · 3397 unmodified lines | ||
| 3398 | 3398 | static void wm8962_free_gpio(struct snd_soc_codec *codec) |
| 3399 | 3399 | { |
| 3400 | 3400 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
| 3401 | − int ret; | |
| 3402 | 3401 | |
| 3403 | − ret = gpiochip_remove(&wm8962->gpio_chip); | |
| 3404 | − if (ret != 0) | |
| 3405 | − dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret); | |
| 3402 | + gpiochip_remove(&wm8962->gpio_chip); | |
| 3406 | 3403 | } |
| 3407 | 3404 | #else |
| 3408 | 3405 | static void wm8962_init_gpio(struct snd_soc_codec *codec) |
| @@ -2216,11 +2216,7 @@ static void wm8996_init_gpio(struct wm8996_priv *wm8996) · 2215 unmodified lines | ||
| 2216 | 2216 | |
| 2217 | 2217 | static void wm8996_free_gpio(struct wm8996_priv *wm8996) |
| 2218 | 2218 | { |
| 2219 | − int ret; | |
| 2220 | − | |
| 2221 | − ret = gpiochip_remove(&wm8996->gpio_chip); | |
| 2222 | − if (ret != 0) | |
| 2223 | − dev_err(wm8996->dev, "Failed to remove GPIOs: %d\n", ret); | |
| 2219 | + gpiochip_remove(&wm8996->gpio_chip); | |
| 2224 | 2220 | } |
| 2225 | 2221 | #else |
| 2226 | 2222 | static void wm8996_init_gpio(struct wm8996_priv *wm8996) |