diff options
-rw-r--r-- | Documentation/devicetree/bindings/gpio/spear_spics.txt | 50 | ||||
-rw-r--r-- | arch/arm/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/plat-spear/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpio/Kconfig | 22 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 3 | ||||
-rw-r--r-- | drivers/gpio/gpio-clps711x.c | 199 | ||||
-rw-r--r-- | drivers/gpio/gpio-da9055.c | 204 | ||||
-rw-r--r-- | drivers/gpio/gpio-em.c | 48 | ||||
-rw-r--r-- | drivers/gpio/gpio-max730x.c | 12 | ||||
-rw-r--r-- | drivers/gpio/gpio-mvebu.c | 9 | ||||
-rw-r--r-- | drivers/gpio/gpio-omap.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-pca953x.c | 55 | ||||
-rw-r--r-- | drivers/gpio/gpio-pch.c | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-pl061.c | 59 | ||||
-rw-r--r-- | drivers/gpio/gpio-spear-spics.c | 217 | ||||
-rw-r--r-- | drivers/gpio/gpio-tc3589x.c | 20 | ||||
-rw-r--r-- | drivers/gpio/gpio-tegra.c | 43 | ||||
-rw-r--r-- | drivers/gpio/gpio-twl4030.c | 35 | ||||
-rw-r--r-- | drivers/gpio/gpio-vt8500.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 124 | ||||
-rw-r--r-- | include/asm-generic/gpio.h | 5 |
21 files changed, 931 insertions, 181 deletions
diff --git a/Documentation/devicetree/bindings/gpio/spear_spics.txt b/Documentation/devicetree/bindings/gpio/spear_spics.txt new file mode 100644 index 000000000000..96c37eb15075 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/spear_spics.txt | |||
@@ -0,0 +1,50 @@ | |||
1 | === ST Microelectronics SPEAr SPI CS Driver === | ||
2 | |||
3 | SPEAr platform provides a provision to control chipselects of ARM PL022 Prime | ||
4 | Cell spi controller through its system registers, which otherwise remains under | ||
5 | PL022 control. If chipselect remain under PL022 control then they would be | ||
6 | released as soon as transfer is over and TxFIFO becomes empty. This is not | ||
7 | desired by some of the device protocols above spi which expect (multiple) | ||
8 | transfers without releasing their chipselects. | ||
9 | |||
10 | Chipselects can be controlled by software by turning them as GPIOs. SPEAr | ||
11 | provides another interface through system registers through which software can | ||
12 | directly control each PL022 chipselect. Hence, it is natural for SPEAr to export | ||
13 | the control of this interface as gpio. | ||
14 | |||
15 | Required properties: | ||
16 | |||
17 | * compatible: should be defined as "st,spear-spics-gpio" | ||
18 | * reg: mentioning address range of spics controller | ||
19 | * st-spics,peripcfg-reg: peripheral configuration register offset | ||
20 | * st-spics,sw-enable-bit: bit offset to enable sw control | ||
21 | * st-spics,cs-value-bit: bit offset to drive chipselect low or high | ||
22 | * st-spics,cs-enable-mask: chip select number bit mask | ||
23 | * st-spics,cs-enable-shift: chip select number program offset | ||
24 | * gpio-controller: Marks the device node as gpio controller | ||
25 | * #gpio-cells: should be 1 and will mention chip select number | ||
26 | |||
27 | All the above bit offsets are within peripcfg register. | ||
28 | |||
29 | Example: | ||
30 | ------- | ||
31 | spics: spics@e0700000{ | ||
32 | compatible = "st,spear-spics-gpio"; | ||
33 | reg = <0xe0700000 0x1000>; | ||
34 | st-spics,peripcfg-reg = <0x3b0>; | ||
35 | st-spics,sw-enable-bit = <12>; | ||
36 | st-spics,cs-value-bit = <11>; | ||
37 | st-spics,cs-enable-mask = <3>; | ||
38 | st-spics,cs-enable-shift = <8>; | ||
39 | gpio-controller; | ||
40 | #gpio-cells = <2>; | ||
41 | }; | ||
42 | |||
43 | |||
44 | spi0: spi@e0100000 { | ||
45 | status = "okay"; | ||
46 | num-cs = <3>; | ||
47 | cs-gpios = <&gpio1 7 0>, <&spics 0>, | ||
48 | <&spics 1>; | ||
49 | ... | ||
50 | } | ||
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ade7e924bef5..b673d65449f8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -364,6 +364,7 @@ config ARCH_CNS3XXX | |||
364 | 364 | ||
365 | config ARCH_CLPS711X | 365 | config ARCH_CLPS711X |
366 | bool "Cirrus Logic CLPS711x/EP721x/EP731x-based" | 366 | bool "Cirrus Logic CLPS711x/EP721x/EP731x-based" |
367 | select ARCH_REQUIRE_GPIOLIB | ||
367 | select ARCH_USES_GETTIMEOFFSET | 368 | select ARCH_USES_GETTIMEOFFSET |
368 | select CLKDEV_LOOKUP | 369 | select CLKDEV_LOOKUP |
369 | select COMMON_CLK | 370 | select COMMON_CLK |
diff --git a/arch/arm/plat-spear/Kconfig b/arch/arm/plat-spear/Kconfig index f8db7b2deb36..87dbd81bdf51 100644 --- a/arch/arm/plat-spear/Kconfig +++ b/arch/arm/plat-spear/Kconfig | |||
@@ -12,6 +12,7 @@ config ARCH_SPEAR13XX | |||
12 | bool "ST SPEAr13xx with Device Tree" | 12 | bool "ST SPEAr13xx with Device Tree" |
13 | select ARM_GIC | 13 | select ARM_GIC |
14 | select CPU_V7 | 14 | select CPU_V7 |
15 | select GPIO_SPEAR_SPICS | ||
15 | select HAVE_SMP | 16 | select HAVE_SMP |
16 | select MIGHT_HAVE_CACHE_L2X0 | 17 | select MIGHT_HAVE_CACHE_L2X0 |
17 | select PINCTRL | 18 | select PINCTRL |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 47150f5ded04..b0e67b200aa0 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -86,11 +86,26 @@ config GPIO_DA9052 | |||
86 | help | 86 | help |
87 | Say yes here to enable the GPIO driver for the DA9052 chip. | 87 | Say yes here to enable the GPIO driver for the DA9052 chip. |
88 | 88 | ||
89 | config GPIO_DA9055 | ||
90 | tristate "Dialog Semiconductor DA9055 GPIO" | ||
91 | depends on MFD_DA9055 | ||
92 | help | ||
93 | Say yes here to enable the GPIO driver for the DA9055 chip. | ||
94 | |||
95 | The Dialog DA9055 PMIC chip has 3 GPIO pins that can be | ||
96 | be controller by this driver. | ||
97 | |||
98 | If driver is built as a module it will be called gpio-da9055. | ||
99 | |||
89 | config GPIO_MAX730X | 100 | config GPIO_MAX730X |
90 | tristate | 101 | tristate |
91 | 102 | ||
92 | comment "Memory mapped GPIO drivers:" | 103 | comment "Memory mapped GPIO drivers:" |
93 | 104 | ||
105 | config GPIO_CLPS711X | ||
106 | def_bool y | ||
107 | depends on ARCH_CLPS711X | ||
108 | |||
94 | config GPIO_GENERIC_PLATFORM | 109 | config GPIO_GENERIC_PLATFORM |
95 | tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" | 110 | tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" |
96 | select GPIO_GENERIC | 111 | select GPIO_GENERIC |
@@ -181,6 +196,13 @@ config GPIO_PXA | |||
181 | help | 196 | help |
182 | Say yes here to support the PXA GPIO device | 197 | Say yes here to support the PXA GPIO device |
183 | 198 | ||
199 | config GPIO_SPEAR_SPICS | ||
200 | bool "ST SPEAr13xx SPI Chip Select as GPIO support" | ||
201 | depends on PLAT_SPEAR | ||
202 | select GENERIC_IRQ_CHIP | ||
203 | help | ||
204 | Say yes here to support ST SPEAr SPI Chip Select as GPIO device | ||
205 | |||
184 | config GPIO_STA2X11 | 206 | config GPIO_STA2X11 |
185 | bool "STA2x11/ConneXt GPIO support" | 207 | bool "STA2x11/ConneXt GPIO support" |
186 | depends on MFD_STA2X11 | 208 | depends on MFD_STA2X11 |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 9aeed6707326..a268d99f4e43 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -16,8 +16,10 @@ obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o | |||
16 | obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o | 16 | obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o |
17 | obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o | 17 | obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o |
18 | obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o | 18 | obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o |
19 | obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o | ||
19 | obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o | 20 | obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o |
20 | obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o | 21 | obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o |
22 | obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o | ||
21 | obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o | 23 | obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o |
22 | obj-$(CONFIG_GPIO_EM) += gpio-em.o | 24 | obj-$(CONFIG_GPIO_EM) += gpio-em.o |
23 | obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o | 25 | obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o |
@@ -57,6 +59,7 @@ obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o | |||
57 | obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o | 59 | obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o |
58 | obj-$(CONFIG_GPIO_SCH) += gpio-sch.o | 60 | obj-$(CONFIG_GPIO_SCH) += gpio-sch.o |
59 | obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o | 61 | obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o |
62 | obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o | ||
60 | obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o | 63 | obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o |
61 | obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o | 64 | obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o |
62 | obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o | 65 | obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o |
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c new file mode 100644 index 000000000000..ce63b75b13f5 --- /dev/null +++ b/drivers/gpio/gpio-clps711x.c | |||
@@ -0,0 +1,199 @@ | |||
1 | /* | ||
2 | * CLPS711X GPIO driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/io.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/gpio.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/spinlock.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | |||
19 | #include <mach/hardware.h> | ||
20 | |||
21 | #define CLPS711X_GPIO_PORTS 5 | ||
22 | #define CLPS711X_GPIO_NAME "gpio-clps711x" | ||
23 | |||
24 | struct clps711x_gpio { | ||
25 | struct gpio_chip chip[CLPS711X_GPIO_PORTS]; | ||
26 | spinlock_t lock; | ||
27 | }; | ||
28 | |||
29 | static void __iomem *clps711x_ports[] = { | ||
30 | CLPS711X_VIRT_BASE + PADR, | ||
31 | CLPS711X_VIRT_BASE + PBDR, | ||
32 | CLPS711X_VIRT_BASE + PCDR, | ||
33 | CLPS711X_VIRT_BASE + PDDR, | ||
34 | CLPS711X_VIRT_BASE + PEDR, | ||
35 | }; | ||
36 | |||
37 | static void __iomem *clps711x_pdirs[] = { | ||
38 | CLPS711X_VIRT_BASE + PADDR, | ||
39 | CLPS711X_VIRT_BASE + PBDDR, | ||
40 | CLPS711X_VIRT_BASE + PCDDR, | ||
41 | CLPS711X_VIRT_BASE + PDDDR, | ||
42 | CLPS711X_VIRT_BASE + PEDDR, | ||
43 | }; | ||
44 | |||
45 | #define clps711x_port(x) clps711x_ports[x->base / 8] | ||
46 | #define clps711x_pdir(x) clps711x_pdirs[x->base / 8] | ||
47 | |||
48 | static int gpio_clps711x_get(struct gpio_chip *chip, unsigned offset) | ||
49 | { | ||
50 | return !!(readb(clps711x_port(chip)) & (1 << offset)); | ||
51 | } | ||
52 | |||
53 | static void gpio_clps711x_set(struct gpio_chip *chip, unsigned offset, | ||
54 | int value) | ||
55 | { | ||
56 | int tmp; | ||
57 | unsigned long flags; | ||
58 | struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev); | ||
59 | |||
60 | spin_lock_irqsave(&gpio->lock, flags); | ||
61 | tmp = readb(clps711x_port(chip)) & ~(1 << offset); | ||
62 | if (value) | ||
63 | tmp |= 1 << offset; | ||
64 | writeb(tmp, clps711x_port(chip)); | ||
65 | spin_unlock_irqrestore(&gpio->lock, flags); | ||
66 | } | ||
67 | |||
68 | static int gpio_clps711x_dir_in(struct gpio_chip *chip, unsigned offset) | ||
69 | { | ||
70 | int tmp; | ||
71 | unsigned long flags; | ||
72 | struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev); | ||
73 | |||
74 | spin_lock_irqsave(&gpio->lock, flags); | ||
75 | tmp = readb(clps711x_pdir(chip)) & ~(1 << offset); | ||
76 | writeb(tmp, clps711x_pdir(chip)); | ||
77 | spin_unlock_irqrestore(&gpio->lock, flags); | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int gpio_clps711x_dir_out(struct gpio_chip *chip, unsigned offset, | ||
83 | int value) | ||
84 | { | ||
85 | int tmp; | ||
86 | unsigned long flags; | ||
87 | struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev); | ||
88 | |||
89 | spin_lock_irqsave(&gpio->lock, flags); | ||
90 | tmp = readb(clps711x_pdir(chip)) | (1 << offset); | ||
91 | writeb(tmp, clps711x_pdir(chip)); | ||
92 | tmp = readb(clps711x_port(chip)) & ~(1 << offset); | ||
93 | if (value) | ||
94 | tmp |= 1 << offset; | ||
95 | writeb(tmp, clps711x_port(chip)); | ||
96 | spin_unlock_irqrestore(&gpio->lock, flags); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int gpio_clps711x_dir_in_inv(struct gpio_chip *chip, unsigned offset) | ||
102 | { | ||
103 | int tmp; | ||
104 | unsigned long flags; | ||
105 | struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev); | ||
106 | |||
107 | spin_lock_irqsave(&gpio->lock, flags); | ||
108 | tmp = readb(clps711x_pdir(chip)) | (1 << offset); | ||
109 | writeb(tmp, clps711x_pdir(chip)); | ||
110 | spin_unlock_irqrestore(&gpio->lock, flags); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int gpio_clps711x_dir_out_inv(struct gpio_chip *chip, unsigned offset, | ||
116 | int value) | ||
117 | { | ||
118 | int tmp; | ||
119 | unsigned long flags; | ||
120 | struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev); | ||
121 | |||
122 | spin_lock_irqsave(&gpio->lock, flags); | ||
123 | tmp = readb(clps711x_pdir(chip)) & ~(1 << offset); | ||
124 | writeb(tmp, clps711x_pdir(chip)); | ||
125 | tmp = readb(clps711x_port(chip)) & ~(1 << offset); | ||
126 | if (value) | ||
127 | tmp |= 1 << offset; | ||
128 | writeb(tmp, clps711x_port(chip)); | ||
129 | spin_unlock_irqrestore(&gpio->lock, flags); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static struct { | ||
135 | char *name; | ||
136 | int nr; | ||
137 | int inv_dir; | ||
138 | } clps711x_gpio_ports[] __initconst = { | ||
139 | { "PORTA", 8, 0, }, | ||
140 | { "PORTB", 8, 0, }, | ||
141 | { "PORTC", 8, 0, }, | ||
142 | { "PORTD", 8, 1, }, | ||
143 | { "PORTE", 3, 0, }, | ||
144 | }; | ||
145 | |||
146 | static int __init gpio_clps711x_init(void) | ||
147 | { | ||
148 | int i; | ||
149 | struct platform_device *pdev; | ||
150 | struct clps711x_gpio *gpio; | ||
151 | |||
152 | pdev = platform_device_alloc(CLPS711X_GPIO_NAME, 0); | ||
153 | if (!pdev) { | ||
154 | pr_err("Cannot create platform device: %s\n", | ||
155 | CLPS711X_GPIO_NAME); | ||
156 | return -ENOMEM; | ||
157 | } | ||
158 | |||
159 | platform_device_add(pdev); | ||
160 | |||
161 | gpio = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_gpio), | ||
162 | GFP_KERNEL); | ||
163 | if (!gpio) { | ||
164 | dev_err(&pdev->dev, "GPIO allocating memory error\n"); | ||
165 | platform_device_unregister(pdev); | ||
166 | return -ENOMEM; | ||
167 | } | ||
168 | |||
169 | platform_set_drvdata(pdev, gpio); | ||
170 | |||
171 | spin_lock_init(&gpio->lock); | ||
172 | |||
173 | for (i = 0; i < CLPS711X_GPIO_PORTS; i++) { | ||
174 | gpio->chip[i].owner = THIS_MODULE; | ||
175 | gpio->chip[i].dev = &pdev->dev; | ||
176 | gpio->chip[i].label = clps711x_gpio_ports[i].name; | ||
177 | gpio->chip[i].base = i * 8; | ||
178 | gpio->chip[i].ngpio = clps711x_gpio_ports[i].nr; | ||
179 | gpio->chip[i].get = gpio_clps711x_get; | ||
180 | gpio->chip[i].set = gpio_clps711x_set; | ||
181 | if (!clps711x_gpio_ports[i].inv_dir) { | ||
182 | gpio->chip[i].direction_input = gpio_clps711x_dir_in; | ||
183 | gpio->chip[i].direction_output = gpio_clps711x_dir_out; | ||
184 | } else { | ||
185 | gpio->chip[i].direction_input = gpio_clps711x_dir_in_inv; | ||
186 | gpio->chip[i].direction_output = gpio_clps711x_dir_out_inv; | ||
187 | } | ||
188 | WARN_ON(gpiochip_add(&gpio->chip[i])); | ||
189 | } | ||
190 | |||
191 | dev_info(&pdev->dev, "GPIO driver initialized\n"); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | arch_initcall(gpio_clps711x_init); | ||
196 | |||
197 | MODULE_LICENSE("GPL v2"); | ||
198 | MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); | ||
199 | MODULE_DESCRIPTION("CLPS711X GPIO driver"); | ||
diff --git a/drivers/gpio/gpio-da9055.c b/drivers/gpio/gpio-da9055.c new file mode 100644 index 000000000000..55d83c7d9c7f --- /dev/null +++ b/drivers/gpio/gpio-da9055.c | |||
@@ -0,0 +1,204 @@ | |||
1 | /* | ||
2 | * GPIO Driver for Dialog DA9055 PMICs. | ||
3 | * | ||
4 | * Copyright(c) 2012 Dialog Semiconductor Ltd. | ||
5 | * | ||
6 | * Author: David Dajun Chen <dchen@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/gpio.h> | ||
17 | |||
18 | #include <linux/mfd/da9055/core.h> | ||
19 | #include <linux/mfd/da9055/reg.h> | ||
20 | #include <linux/mfd/da9055/pdata.h> | ||
21 | |||
22 | #define DA9055_VDD_IO 0x0 | ||
23 | #define DA9055_PUSH_PULL 0x3 | ||
24 | #define DA9055_ACT_LOW 0x0 | ||
25 | #define DA9055_GPI 0x1 | ||
26 | #define DA9055_PORT_MASK 0x3 | ||
27 | #define DA9055_PORT_SHIFT(offset) (4 * (offset % 2)) | ||
28 | |||
29 | #define DA9055_INPUT DA9055_GPI | ||
30 | #define DA9055_OUTPUT DA9055_PUSH_PULL | ||
31 | #define DA9055_IRQ_GPI0 3 | ||
32 | |||
33 | struct da9055_gpio { | ||
34 | struct da9055 *da9055; | ||
35 | struct gpio_chip gp; | ||
36 | }; | ||
37 | |||
38 | static inline struct da9055_gpio *to_da9055_gpio(struct gpio_chip *chip) | ||
39 | { | ||
40 | return container_of(chip, struct da9055_gpio, gp); | ||
41 | } | ||
42 | |||
43 | static int da9055_gpio_get(struct gpio_chip *gc, unsigned offset) | ||
44 | { | ||
45 | struct da9055_gpio *gpio = to_da9055_gpio(gc); | ||
46 | int gpio_direction = 0; | ||
47 | int ret; | ||
48 | |||
49 | /* Get GPIO direction */ | ||
50 | ret = da9055_reg_read(gpio->da9055, (offset >> 1) + DA9055_REG_GPIO0_1); | ||
51 | if (ret < 0) | ||
52 | return ret; | ||
53 | |||
54 | gpio_direction = ret & (DA9055_PORT_MASK) << DA9055_PORT_SHIFT(offset); | ||
55 | gpio_direction >>= DA9055_PORT_SHIFT(offset); | ||
56 | switch (gpio_direction) { | ||
57 | case DA9055_INPUT: | ||
58 | ret = da9055_reg_read(gpio->da9055, DA9055_REG_STATUS_B); | ||
59 | if (ret < 0) | ||
60 | return ret; | ||
61 | break; | ||
62 | case DA9055_OUTPUT: | ||
63 | ret = da9055_reg_read(gpio->da9055, DA9055_REG_GPIO_MODE0_2); | ||
64 | if (ret < 0) | ||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | return ret & (1 << offset); | ||
69 | |||
70 | } | ||
71 | |||
72 | static void da9055_gpio_set(struct gpio_chip *gc, unsigned offset, int value) | ||
73 | { | ||
74 | struct da9055_gpio *gpio = to_da9055_gpio(gc); | ||
75 | |||
76 | da9055_reg_update(gpio->da9055, | ||
77 | DA9055_REG_GPIO_MODE0_2, | ||
78 | 1 << offset, | ||
79 | value << offset); | ||
80 | } | ||
81 | |||
82 | static int da9055_gpio_direction_input(struct gpio_chip *gc, unsigned offset) | ||
83 | { | ||
84 | struct da9055_gpio *gpio = to_da9055_gpio(gc); | ||
85 | unsigned char reg_byte; | ||
86 | |||
87 | reg_byte = (DA9055_ACT_LOW | DA9055_GPI) | ||
88 | << DA9055_PORT_SHIFT(offset); | ||
89 | |||
90 | return da9055_reg_update(gpio->da9055, (offset >> 1) + | ||
91 | DA9055_REG_GPIO0_1, | ||
92 | DA9055_PORT_MASK << | ||
93 | DA9055_PORT_SHIFT(offset), | ||
94 | reg_byte); | ||
95 | } | ||
96 | |||
97 | static int da9055_gpio_direction_output(struct gpio_chip *gc, | ||
98 | unsigned offset, int value) | ||
99 | { | ||
100 | struct da9055_gpio *gpio = to_da9055_gpio(gc); | ||
101 | unsigned char reg_byte; | ||
102 | int ret; | ||
103 | |||
104 | reg_byte = (DA9055_VDD_IO | DA9055_PUSH_PULL) | ||
105 | << DA9055_PORT_SHIFT(offset); | ||
106 | |||
107 | ret = da9055_reg_update(gpio->da9055, (offset >> 1) + | ||
108 | DA9055_REG_GPIO0_1, | ||
109 | DA9055_PORT_MASK << | ||
110 | DA9055_PORT_SHIFT(offset), | ||
111 | reg_byte); | ||
112 | if (ret < 0) | ||
113 | return ret; | ||
114 | |||
115 | da9055_gpio_set(gc, offset, value); | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static int da9055_gpio_to_irq(struct gpio_chip *gc, u32 offset) | ||
121 | { | ||
122 | struct da9055_gpio *gpio = to_da9055_gpio(gc); | ||
123 | struct da9055 *da9055 = gpio->da9055; | ||
124 | |||
125 | return regmap_irq_get_virq(da9055->irq_data, | ||
126 | DA9055_IRQ_GPI0 + offset); | ||
127 | } | ||
128 | |||
129 | static struct gpio_chip reference_gp __devinitdata = { | ||
130 | .label = "da9055-gpio", | ||
131 | .owner = THIS_MODULE, | ||
132 | .get = da9055_gpio_get, | ||
133 | .set = da9055_gpio_set, | ||
134 | .direction_input = da9055_gpio_direction_input, | ||
135 | .direction_output = da9055_gpio_direction_output, | ||
136 | .to_irq = da9055_gpio_to_irq, | ||
137 | .can_sleep = 1, | ||
138 | .ngpio = 3, | ||
139 | .base = -1, | ||
140 | }; | ||
141 | |||
142 | static int __devinit da9055_gpio_probe(struct platform_device *pdev) | ||
143 | { | ||
144 | struct da9055_gpio *gpio; | ||
145 | struct da9055_pdata *pdata; | ||
146 | int ret; | ||
147 | |||
148 | gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); | ||
149 | if (gpio == NULL) | ||
150 | return -ENOMEM; | ||
151 | |||
152 | gpio->da9055 = dev_get_drvdata(pdev->dev.parent); | ||
153 | pdata = gpio->da9055->dev->platform_data; | ||
154 | |||
155 | gpio->gp = reference_gp; | ||
156 | if (pdata && pdata->gpio_base) | ||
157 | gpio->gp.base = pdata->gpio_base; | ||
158 | |||
159 | ret = gpiochip_add(&gpio->gp); | ||
160 | if (ret < 0) { | ||
161 | dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); | ||
162 | goto err_mem; | ||
163 | } | ||
164 | |||
165 | platform_set_drvdata(pdev, gpio); | ||
166 | |||
167 | return 0; | ||
168 | |||
169 | err_mem: | ||
170 | return ret; | ||
171 | } | ||
172 | |||
173 | static int __devexit da9055_gpio_remove(struct platform_device *pdev) | ||
174 | { | ||
175 | struct da9055_gpio *gpio = platform_get_drvdata(pdev); | ||
176 | |||
177 | return gpiochip_remove(&gpio->gp); | ||
178 | } | ||
179 | |||
180 | static struct platform_driver da9055_gpio_driver = { | ||
181 | .probe = da9055_gpio_probe, | ||
182 | .remove = __devexit_p(da9055_gpio_remove), | ||
183 | .driver = { | ||
184 | .name = "da9055-gpio", | ||
185 | .owner = THIS_MODULE, | ||
186 | }, | ||
187 | }; | ||
188 | |||
189 | static int __init da9055_gpio_init(void) | ||
190 | { | ||
191 | return platform_driver_register(&da9055_gpio_driver); | ||
192 | } | ||
193 | subsys_initcall(da9055_gpio_init); | ||
194 | |||
195 | static void __exit da9055_gpio_exit(void) | ||
196 | { | ||
197 | platform_driver_unregister(&da9055_gpio_driver); | ||
198 | } | ||
199 | module_exit(da9055_gpio_exit); | ||
200 | |||
201 | MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); | ||
202 | MODULE_DESCRIPTION("DA9055 GPIO Device Driver"); | ||
203 | MODULE_LICENSE("GPL"); | ||
204 | MODULE_ALIAS("platform:da9055-gpio"); | ||
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index efb4c2d0d132..b00706329d26 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c | |||
@@ -35,7 +35,6 @@ | |||
35 | struct em_gio_priv { | 35 | struct em_gio_priv { |
36 | void __iomem *base0; | 36 | void __iomem *base0; |
37 | void __iomem *base1; | 37 | void __iomem *base1; |
38 | unsigned int irq_base; | ||
39 | spinlock_t sense_lock; | 38 | spinlock_t sense_lock; |
40 | struct platform_device *pdev; | 39 | struct platform_device *pdev; |
41 | struct gpio_chip gpio_chip; | 40 | struct gpio_chip gpio_chip; |
@@ -214,7 +213,7 @@ static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset, | |||
214 | 213 | ||
215 | static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset) | 214 | static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset) |
216 | { | 215 | { |
217 | return irq_find_mapping(gpio_to_priv(chip)->irq_domain, offset); | 216 | return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset); |
218 | } | 217 | } |
219 | 218 | ||
220 | static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq, | 219 | static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq, |
@@ -234,40 +233,6 @@ static struct irq_domain_ops em_gio_irq_domain_ops = { | |||
234 | .map = em_gio_irq_domain_map, | 233 | .map = em_gio_irq_domain_map, |
235 | }; | 234 | }; |
236 | 235 | ||
237 | static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p) | ||
238 | { | ||
239 | struct platform_device *pdev = p->pdev; | ||
240 | struct gpio_em_config *pdata = pdev->dev.platform_data; | ||
241 | |||
242 | p->irq_base = irq_alloc_descs(pdata->irq_base, 0, | ||
243 | pdata->number_of_pins, numa_node_id()); | ||
244 | if (p->irq_base < 0) { | ||
245 | dev_err(&pdev->dev, "cannot get irq_desc\n"); | ||
246 | return p->irq_base; | ||
247 | } | ||
248 | pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n", | ||
249 | pdata->gpio_base, pdata->number_of_pins, p->irq_base); | ||
250 | |||
251 | p->irq_domain = irq_domain_add_legacy(pdev->dev.of_node, | ||
252 | pdata->number_of_pins, | ||
253 | p->irq_base, 0, | ||
254 | &em_gio_irq_domain_ops, p); | ||
255 | if (!p->irq_domain) { | ||
256 | irq_free_descs(p->irq_base, pdata->number_of_pins); | ||
257 | return -ENXIO; | ||
258 | } | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static void em_gio_irq_domain_cleanup(struct em_gio_priv *p) | ||
264 | { | ||
265 | struct gpio_em_config *pdata = p->pdev->dev.platform_data; | ||
266 | |||
267 | irq_free_descs(p->irq_base, pdata->number_of_pins); | ||
268 | /* FIXME: irq domain wants to be freed! */ | ||
269 | } | ||
270 | |||
271 | static int __devinit em_gio_probe(struct platform_device *pdev) | 236 | static int __devinit em_gio_probe(struct platform_device *pdev) |
272 | { | 237 | { |
273 | struct gpio_em_config *pdata = pdev->dev.platform_data; | 238 | struct gpio_em_config *pdata = pdev->dev.platform_data; |
@@ -334,8 +299,11 @@ static int __devinit em_gio_probe(struct platform_device *pdev) | |||
334 | irq_chip->irq_set_type = em_gio_irq_set_type; | 299 | irq_chip->irq_set_type = em_gio_irq_set_type; |
335 | irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; | 300 | irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; |
336 | 301 | ||
337 | ret = em_gio_irq_domain_init(p); | 302 | p->irq_domain = irq_domain_add_linear(pdev->dev.of_node, |
338 | if (ret) { | 303 | pdata->number_of_pins, |
304 | &em_gio_irq_domain_ops, p); | ||
305 | if (!p->irq_domain) { | ||
306 | ret = -ENXIO; | ||
339 | dev_err(&pdev->dev, "cannot initialize irq domain\n"); | 307 | dev_err(&pdev->dev, "cannot initialize irq domain\n"); |
340 | goto err3; | 308 | goto err3; |
341 | } | 309 | } |
@@ -364,7 +332,7 @@ err6: | |||
364 | err5: | 332 | err5: |
365 | free_irq(irq[0]->start, pdev); | 333 | free_irq(irq[0]->start, pdev); |
366 | err4: | 334 | err4: |
367 | em_gio_irq_domain_cleanup(p); | 335 | irq_domain_remove(p->irq_domain); |
368 | err3: | 336 | err3: |
369 | iounmap(p->base1); | 337 | iounmap(p->base1); |
370 | err2: | 338 | err2: |
@@ -390,7 +358,7 @@ static int __devexit em_gio_remove(struct platform_device *pdev) | |||
390 | 358 | ||
391 | free_irq(irq[1]->start, pdev); | 359 | free_irq(irq[1]->start, pdev); |
392 | free_irq(irq[0]->start, pdev); | 360 | free_irq(irq[0]->start, pdev); |
393 | em_gio_irq_domain_cleanup(p); | 361 | irq_domain_remove(p->irq_domain); |
394 | iounmap(p->base1); | 362 | iounmap(p->base1); |
395 | iounmap(p->base0); | 363 | iounmap(p->base0); |
396 | kfree(p); | 364 | kfree(p); |
diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c index 05e2dac60b3b..c4bf86abd4d8 100644 --- a/drivers/gpio/gpio-max730x.c +++ b/drivers/gpio/gpio-max730x.c | |||
@@ -167,10 +167,6 @@ int __devinit __max730x_probe(struct max7301 *ts) | |||
167 | int i, ret; | 167 | int i, ret; |
168 | 168 | ||
169 | pdata = dev->platform_data; | 169 | pdata = dev->platform_data; |
170 | if (!pdata || !pdata->base) { | ||
171 | dev_err(dev, "incorrect or missing platform data\n"); | ||
172 | return -EINVAL; | ||
173 | } | ||
174 | 170 | ||
175 | mutex_init(&ts->lock); | 171 | mutex_init(&ts->lock); |
176 | dev_set_drvdata(dev, ts); | 172 | dev_set_drvdata(dev, ts); |
@@ -178,7 +174,12 @@ int __devinit __max730x_probe(struct max7301 *ts) | |||
178 | /* Power up the chip and disable IRQ output */ | 174 | /* Power up the chip and disable IRQ output */ |
179 | ts->write(dev, 0x04, 0x01); | 175 | ts->write(dev, 0x04, 0x01); |
180 | 176 | ||
181 | ts->input_pullup_active = pdata->input_pullup_active; | 177 | if (pdata) { |
178 | ts->input_pullup_active = pdata->input_pullup_active; | ||
179 | ts->chip.base = pdata->base; | ||
180 | } else { | ||
181 | ts->chip.base = -1; | ||
182 | } | ||
182 | ts->chip.label = dev->driver->name; | 183 | ts->chip.label = dev->driver->name; |
183 | 184 | ||
184 | ts->chip.direction_input = max7301_direction_input; | 185 | ts->chip.direction_input = max7301_direction_input; |
@@ -186,7 +187,6 @@ int __devinit __max730x_probe(struct max7301 *ts) | |||
186 | ts->chip.direction_output = max7301_direction_output; | 187 | ts->chip.direction_output = max7301_direction_output; |
187 | ts->chip.set = max7301_set; | 188 | ts->chip.set = max7301_set; |
188 | 189 | ||
189 | ts->chip.base = pdata->base; | ||
190 | ts->chip.ngpio = PIN_NUMBER; | 190 | ts->chip.ngpio = PIN_NUMBER; |
191 | ts->chip.can_sleep = 1; | 191 | ts->chip.can_sleep = 1; |
192 | ts->chip.dev = dev; | 192 | ts->chip.dev = dev; |
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index be65c0451ad5..a515b9294e92 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c | |||
@@ -168,12 +168,12 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip) | |||
168 | * Functions implementing the gpio_chip methods | 168 | * Functions implementing the gpio_chip methods |
169 | */ | 169 | */ |
170 | 170 | ||
171 | int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin) | 171 | static int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin) |
172 | { | 172 | { |
173 | return pinctrl_request_gpio(chip->base + pin); | 173 | return pinctrl_request_gpio(chip->base + pin); |
174 | } | 174 | } |
175 | 175 | ||
176 | void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin) | 176 | static void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin) |
177 | { | 177 | { |
178 | pinctrl_free_gpio(chip->base + pin); | 178 | pinctrl_free_gpio(chip->base + pin); |
179 | } | 179 | } |
@@ -546,6 +546,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev) | |||
546 | mvchip->chip.label = dev_name(&pdev->dev); | 546 | mvchip->chip.label = dev_name(&pdev->dev); |
547 | mvchip->chip.dev = &pdev->dev; | 547 | mvchip->chip.dev = &pdev->dev; |
548 | mvchip->chip.request = mvebu_gpio_request; | 548 | mvchip->chip.request = mvebu_gpio_request; |
549 | mvchip->chip.free = mvebu_gpio_free; | ||
549 | mvchip->chip.direction_input = mvebu_gpio_direction_input; | 550 | mvchip->chip.direction_input = mvebu_gpio_direction_input; |
550 | mvchip->chip.get = mvebu_gpio_get; | 551 | mvchip->chip.get = mvebu_gpio_get; |
551 | mvchip->chip.direction_output = mvebu_gpio_direction_output; | 552 | mvchip->chip.direction_output = mvebu_gpio_direction_output; |
@@ -673,8 +674,8 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev) | |||
673 | IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); | 674 | IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); |
674 | 675 | ||
675 | /* Setup irq domain on top of the generic chip. */ | 676 | /* Setup irq domain on top of the generic chip. */ |
676 | mvchip->domain = irq_domain_add_legacy(np, mvchip->chip.ngpio, | 677 | mvchip->domain = irq_domain_add_simple(np, mvchip->chip.ngpio, |
677 | mvchip->irqbase, 0, | 678 | mvchip->irqbase, |
678 | &irq_domain_simple_ops, | 679 | &irq_domain_simple_ops, |
679 | mvchip); | 680 | mvchip); |
680 | if (!mvchip->domain) { | 681 | if (!mvchip->domain) { |
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index d335af1d4d85..d71e5bdf7b97 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c | |||
@@ -1105,7 +1105,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) | |||
1105 | if (!pdata) | 1105 | if (!pdata) |
1106 | return -EINVAL; | 1106 | return -EINVAL; |
1107 | 1107 | ||
1108 | bank = devm_kzalloc(&pdev->dev, sizeof(struct gpio_bank), GFP_KERNEL); | 1108 | bank = devm_kzalloc(dev, sizeof(struct gpio_bank), GFP_KERNEL); |
1109 | if (!bank) { | 1109 | if (!bank) { |
1110 | dev_err(dev, "Memory alloc failed\n"); | 1110 | dev_err(dev, "Memory alloc failed\n"); |
1111 | return -ENOMEM; | 1111 | return -ENOMEM; |
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 9c693ae17956..0c5eaf5f4c90 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
19 | #include <linux/irqdomain.h> | ||
19 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
20 | #include <linux/i2c/pca953x.h> | 21 | #include <linux/i2c/pca953x.h> |
21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
@@ -83,6 +84,7 @@ struct pca953x_chip { | |||
83 | u32 irq_trig_raise; | 84 | u32 irq_trig_raise; |
84 | u32 irq_trig_fall; | 85 | u32 irq_trig_fall; |
85 | int irq_base; | 86 | int irq_base; |
87 | struct irq_domain *domain; | ||
86 | #endif | 88 | #endif |
87 | 89 | ||
88 | struct i2c_client *client; | 90 | struct i2c_client *client; |
@@ -333,14 +335,14 @@ static void pca953x_irq_mask(struct irq_data *d) | |||
333 | { | 335 | { |
334 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); | 336 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); |
335 | 337 | ||
336 | chip->irq_mask &= ~(1 << (d->irq - chip->irq_base)); | 338 | chip->irq_mask &= ~(1 << d->hwirq); |
337 | } | 339 | } |
338 | 340 | ||
339 | static void pca953x_irq_unmask(struct irq_data *d) | 341 | static void pca953x_irq_unmask(struct irq_data *d) |
340 | { | 342 | { |
341 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); | 343 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); |
342 | 344 | ||
343 | chip->irq_mask |= 1 << (d->irq - chip->irq_base); | 345 | chip->irq_mask |= 1 << d->hwirq; |
344 | } | 346 | } |
345 | 347 | ||
346 | static void pca953x_irq_bus_lock(struct irq_data *d) | 348 | static void pca953x_irq_bus_lock(struct irq_data *d) |
@@ -372,8 +374,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) | |||
372 | static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) | 374 | static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) |
373 | { | 375 | { |
374 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); | 376 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); |
375 | u32 level = d->irq - chip->irq_base; | 377 | u32 mask = 1 << d->hwirq; |
376 | u32 mask = 1 << level; | ||
377 | 378 | ||
378 | if (!(type & IRQ_TYPE_EDGE_BOTH)) { | 379 | if (!(type & IRQ_TYPE_EDGE_BOTH)) { |
379 | dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", | 380 | dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", |
@@ -454,7 +455,7 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid) | |||
454 | 455 | ||
455 | do { | 456 | do { |
456 | level = __ffs(pending); | 457 | level = __ffs(pending); |
457 | handle_nested_irq(level + chip->irq_base); | 458 | handle_nested_irq(irq_find_mapping(chip->domain, level)); |
458 | 459 | ||
459 | pending &= ~(1 << level); | 460 | pending &= ~(1 << level); |
460 | } while (pending); | 461 | } while (pending); |
@@ -499,6 +500,17 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, | |||
499 | if (chip->irq_base < 0) | 500 | if (chip->irq_base < 0) |
500 | goto out_failed; | 501 | goto out_failed; |
501 | 502 | ||
503 | chip->domain = irq_domain_add_legacy(client->dev.of_node, | ||
504 | chip->gpio_chip.ngpio, | ||
505 | chip->irq_base, | ||
506 | 0, | ||
507 | &irq_domain_simple_ops, | ||
508 | NULL); | ||
509 | if (!chip->domain) { | ||
510 | ret = -ENODEV; | ||
511 | goto out_irqdesc_free; | ||
512 | } | ||
513 | |||
502 | for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { | 514 | for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { |
503 | int irq = lvl + chip->irq_base; | 515 | int irq = lvl + chip->irq_base; |
504 | 516 | ||
@@ -521,7 +533,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, | |||
521 | if (ret) { | 533 | if (ret) { |
522 | dev_err(&client->dev, "failed to request irq %d\n", | 534 | dev_err(&client->dev, "failed to request irq %d\n", |
523 | client->irq); | 535 | client->irq); |
524 | goto out_failed; | 536 | goto out_irqdesc_free; |
525 | } | 537 | } |
526 | 538 | ||
527 | chip->gpio_chip.to_irq = pca953x_gpio_to_irq; | 539 | chip->gpio_chip.to_irq = pca953x_gpio_to_irq; |
@@ -529,6 +541,8 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, | |||
529 | 541 | ||
530 | return 0; | 542 | return 0; |
531 | 543 | ||
544 | out_irqdesc_free: | ||
545 | irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio); | ||
532 | out_failed: | 546 | out_failed: |
533 | chip->irq_base = -1; | 547 | chip->irq_base = -1; |
534 | return ret; | 548 | return ret; |
@@ -751,9 +765,38 @@ static int pca953x_remove(struct i2c_client *client) | |||
751 | return 0; | 765 | return 0; |
752 | } | 766 | } |
753 | 767 | ||
768 | static const struct of_device_id pca953x_dt_ids[] = { | ||
769 | { .compatible = "nxp,pca9534", }, | ||
770 | { .compatible = "nxp,pca9535", }, | ||
771 | { .compatible = "nxp,pca9536", }, | ||
772 | { .compatible = "nxp,pca9537", }, | ||
773 | { .compatible = "nxp,pca9538", }, | ||
774 | { .compatible = "nxp,pca9539", }, | ||
775 | { .compatible = "nxp,pca9554", }, | ||
776 | { .compatible = "nxp,pca9555", }, | ||
777 | { .compatible = "nxp,pca9556", }, | ||
778 | { .compatible = "nxp,pca9557", }, | ||
779 | { .compatible = "nxp,pca9574", }, | ||
780 | { .compatible = "nxp,pca9575", }, | ||
781 | |||
782 | { .compatible = "maxim,max7310", }, | ||
783 | { .compatible = "maxim,max7312", }, | ||
784 | { .compatible = "maxim,max7313", }, | ||
785 | { .compatible = "maxim,max7315", }, | ||
786 | |||
787 | { .compatible = "ti,pca6107", }, | ||
788 | { .compatible = "ti,tca6408", }, | ||
789 | { .compatible = "ti,tca6416", }, | ||
790 | { .compatible = "ti,tca6424", }, | ||
791 | { } | ||
792 | }; | ||
793 | |||
794 | MODULE_DEVICE_TABLE(of, pca953x_dt_ids); | ||
795 | |||
754 | static struct i2c_driver pca953x_driver = { | 796 | static struct i2c_driver pca953x_driver = { |
755 | .driver = { | 797 | .driver = { |
756 | .name = "pca953x", | 798 | .name = "pca953x", |
799 | .of_match_table = pca953x_dt_ids, | ||
757 | }, | 800 | }, |
758 | .probe = pca953x_probe, | 801 | .probe = pca953x_probe, |
759 | .remove = pca953x_remove, | 802 | .remove = pca953x_remove, |
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 4ad0c4f9171c..e3a14fef79e1 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c | |||
@@ -215,6 +215,7 @@ static void pch_gpio_setup(struct pch_gpio *chip) | |||
215 | struct gpio_chip *gpio = &chip->gpio; | 215 | struct gpio_chip *gpio = &chip->gpio; |
216 | 216 | ||
217 | gpio->label = dev_name(chip->dev); | 217 | gpio->label = dev_name(chip->dev); |
218 | gpio->dev = chip->dev; | ||
218 | gpio->owner = THIS_MODULE; | 219 | gpio->owner = THIS_MODULE; |
219 | gpio->direction_input = pch_gpio_direction_input; | 220 | gpio->direction_input = pch_gpio_direction_input; |
220 | gpio->get = pch_gpio_get; | 221 | gpio->get = pch_gpio_get; |
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index b4b5da4fd2cc..31d9c9e79ea9 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c | |||
@@ -216,39 +216,34 @@ static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base) | |||
216 | IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0); | 216 | IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0); |
217 | } | 217 | } |
218 | 218 | ||
219 | static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | 219 | static int pl061_probe(struct amba_device *adev, const struct amba_id *id) |
220 | { | 220 | { |
221 | struct pl061_platform_data *pdata; | 221 | struct device *dev = &adev->dev; |
222 | struct pl061_platform_data *pdata = dev->platform_data; | ||
222 | struct pl061_gpio *chip; | 223 | struct pl061_gpio *chip; |
223 | int ret, irq, i; | 224 | int ret, irq, i; |
224 | 225 | ||
225 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 226 | chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); |
226 | if (chip == NULL) | 227 | if (chip == NULL) |
227 | return -ENOMEM; | 228 | return -ENOMEM; |
228 | 229 | ||
229 | pdata = dev->dev.platform_data; | ||
230 | if (pdata) { | 230 | if (pdata) { |
231 | chip->gc.base = pdata->gpio_base; | 231 | chip->gc.base = pdata->gpio_base; |
232 | chip->irq_base = pdata->irq_base; | 232 | chip->irq_base = pdata->irq_base; |
233 | } else if (dev->dev.of_node) { | 233 | } else if (adev->dev.of_node) { |
234 | chip->gc.base = -1; | 234 | chip->gc.base = -1; |
235 | chip->irq_base = 0; | 235 | chip->irq_base = 0; |
236 | } else { | 236 | } else |
237 | ret = -ENODEV; | 237 | return -ENODEV; |
238 | goto free_mem; | ||
239 | } | ||
240 | 238 | ||
241 | if (!request_mem_region(dev->res.start, | 239 | if (!devm_request_mem_region(dev, adev->res.start, |
242 | resource_size(&dev->res), "pl061")) { | 240 | resource_size(&adev->res), "pl061")) |
243 | ret = -EBUSY; | 241 | return -EBUSY; |
244 | goto free_mem; | ||
245 | } | ||
246 | 242 | ||
247 | chip->base = ioremap(dev->res.start, resource_size(&dev->res)); | 243 | chip->base = devm_ioremap(dev, adev->res.start, |
248 | if (chip->base == NULL) { | 244 | resource_size(&adev->res)); |
249 | ret = -ENOMEM; | 245 | if (chip->base == NULL) |
250 | goto release_region; | 246 | return -ENOMEM; |
251 | } | ||
252 | 247 | ||
253 | spin_lock_init(&chip->lock); | 248 | spin_lock_init(&chip->lock); |
254 | 249 | ||
@@ -258,13 +253,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
258 | chip->gc.set = pl061_set_value; | 253 | chip->gc.set = pl061_set_value; |
259 | chip->gc.to_irq = pl061_to_irq; | 254 | chip->gc.to_irq = pl061_to_irq; |
260 | chip->gc.ngpio = PL061_GPIO_NR; | 255 | chip->gc.ngpio = PL061_GPIO_NR; |
261 | chip->gc.label = dev_name(&dev->dev); | 256 | chip->gc.label = dev_name(dev); |
262 | chip->gc.dev = &dev->dev; | 257 | chip->gc.dev = dev; |
263 | chip->gc.owner = THIS_MODULE; | 258 | chip->gc.owner = THIS_MODULE; |
264 | 259 | ||
265 | ret = gpiochip_add(&chip->gc); | 260 | ret = gpiochip_add(&chip->gc); |
266 | if (ret) | 261 | if (ret) |
267 | goto iounmap; | 262 | return ret; |
268 | 263 | ||
269 | /* | 264 | /* |
270 | * irq_chip support | 265 | * irq_chip support |
@@ -276,11 +271,10 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
276 | pl061_init_gc(chip, chip->irq_base); | 271 | pl061_init_gc(chip, chip->irq_base); |
277 | 272 | ||
278 | writeb(0, chip->base + GPIOIE); /* disable irqs */ | 273 | writeb(0, chip->base + GPIOIE); /* disable irqs */ |
279 | irq = dev->irq[0]; | 274 | irq = adev->irq[0]; |
280 | if (irq < 0) { | 275 | if (irq < 0) |
281 | ret = -ENODEV; | 276 | return -ENODEV; |
282 | goto iounmap; | 277 | |
283 | } | ||
284 | irq_set_chained_handler(irq, pl061_irq_handler); | 278 | irq_set_chained_handler(irq, pl061_irq_handler); |
285 | irq_set_handler_data(irq, chip); | 279 | irq_set_handler_data(irq, chip); |
286 | 280 | ||
@@ -294,18 +288,9 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
294 | } | 288 | } |
295 | } | 289 | } |
296 | 290 | ||
297 | amba_set_drvdata(dev, chip); | 291 | amba_set_drvdata(adev, chip); |
298 | 292 | ||
299 | return 0; | 293 | return 0; |
300 | |||
301 | iounmap: | ||
302 | iounmap(chip->base); | ||
303 | release_region: | ||
304 | release_mem_region(dev->res.start, resource_size(&dev->res)); | ||
305 | free_mem: | ||
306 | kfree(chip); | ||
307 | |||
308 | return ret; | ||
309 | } | 294 | } |
310 | 295 | ||
311 | #ifdef CONFIG_PM | 296 | #ifdef CONFIG_PM |
diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c new file mode 100644 index 000000000000..5f45fc4ed5d1 --- /dev/null +++ b/drivers/gpio/gpio-spear-spics.c | |||
@@ -0,0 +1,217 @@ | |||
1 | /* | ||
2 | * SPEAr platform SPI chipselect abstraction over gpiolib | ||
3 | * | ||
4 | * Copyright (C) 2012 ST Microelectronics | ||
5 | * Shiraz Hashim <shiraz.hashim@st.com> | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/err.h> | ||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/of.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/types.h> | ||
19 | |||
20 | /* maximum chipselects */ | ||
21 | #define NUM_OF_GPIO 4 | ||
22 | |||
23 | /* | ||
24 | * Provision is available on some SPEAr SoCs to control ARM PL022 spi cs | ||
25 | * through system registers. This register lies outside spi (pl022) | ||
26 | * address space into system registers. | ||
27 | * | ||
28 | * It provides control for spi chip select lines so that any chipselect | ||
29 | * (out of 4 possible chipselects in pl022) can be made low to select | ||
30 | * the particular slave. | ||
31 | */ | ||
32 | |||
33 | /** | ||
34 | * struct spear_spics - represents spi chip select control | ||
35 | * @base: base address | ||
36 | * @perip_cfg: configuration register | ||
37 | * @sw_enable_bit: bit to enable s/w control over chipselects | ||
38 | * @cs_value_bit: bit to program high or low chipselect | ||
39 | * @cs_enable_mask: mask to select bits required to select chipselect | ||
40 | * @cs_enable_shift: bit pos of cs_enable_mask | ||
41 | * @use_count: use count of a spi controller cs lines | ||
42 | * @last_off: stores last offset caller of set_value() | ||
43 | * @chip: gpio_chip abstraction | ||
44 | */ | ||
45 | struct spear_spics { | ||
46 | void __iomem *base; | ||
47 | u32 perip_cfg; | ||
48 | u32 sw_enable_bit; | ||
49 | u32 cs_value_bit; | ||
50 | u32 cs_enable_mask; | ||
51 | u32 cs_enable_shift; | ||
52 | unsigned long use_count; | ||
53 | int last_off; | ||
54 | struct gpio_chip chip; | ||
55 | }; | ||
56 | |||
57 | /* gpio framework specific routines */ | ||
58 | static int spics_get_value(struct gpio_chip *chip, unsigned offset) | ||
59 | { | ||
60 | return -ENXIO; | ||
61 | } | ||
62 | |||
63 | static void spics_set_value(struct gpio_chip *chip, unsigned offset, int value) | ||
64 | { | ||
65 | struct spear_spics *spics = container_of(chip, struct spear_spics, | ||
66 | chip); | ||
67 | u32 tmp; | ||
68 | |||
69 | /* select chip select from register */ | ||
70 | tmp = readl_relaxed(spics->base + spics->perip_cfg); | ||
71 | if (spics->last_off != offset) { | ||
72 | spics->last_off = offset; | ||
73 | tmp &= ~(spics->cs_enable_mask << spics->cs_enable_shift); | ||
74 | tmp |= offset << spics->cs_enable_shift; | ||
75 | } | ||
76 | |||
77 | /* toggle chip select line */ | ||
78 | tmp &= ~(0x1 << spics->cs_value_bit); | ||
79 | tmp |= value << spics->cs_value_bit; | ||
80 | writel_relaxed(tmp, spics->base + spics->perip_cfg); | ||
81 | } | ||
82 | |||
83 | static int spics_direction_input(struct gpio_chip *chip, unsigned offset) | ||
84 | { | ||
85 | return -ENXIO; | ||
86 | } | ||
87 | |||
88 | static int spics_direction_output(struct gpio_chip *chip, unsigned offset, | ||
89 | int value) | ||
90 | { | ||
91 | spics_set_value(chip, offset, value); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static int spics_request(struct gpio_chip *chip, unsigned offset) | ||
96 | { | ||
97 | struct spear_spics *spics = container_of(chip, struct spear_spics, | ||
98 | chip); | ||
99 | u32 tmp; | ||
100 | |||
101 | if (!spics->use_count++) { | ||
102 | tmp = readl_relaxed(spics->base + spics->perip_cfg); | ||
103 | tmp |= 0x1 << spics->sw_enable_bit; | ||
104 | tmp |= 0x1 << spics->cs_value_bit; | ||
105 | writel_relaxed(tmp, spics->base + spics->perip_cfg); | ||
106 | } | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static void spics_free(struct gpio_chip *chip, unsigned offset) | ||
112 | { | ||
113 | struct spear_spics *spics = container_of(chip, struct spear_spics, | ||
114 | chip); | ||
115 | u32 tmp; | ||
116 | |||
117 | if (!--spics->use_count) { | ||
118 | tmp = readl_relaxed(spics->base + spics->perip_cfg); | ||
119 | tmp &= ~(0x1 << spics->sw_enable_bit); | ||
120 | writel_relaxed(tmp, spics->base + spics->perip_cfg); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | static int spics_gpio_probe(struct platform_device *pdev) | ||
125 | { | ||
126 | struct device_node *np = pdev->dev.of_node; | ||
127 | struct spear_spics *spics; | ||
128 | struct resource *res; | ||
129 | int ret; | ||
130 | |||
131 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
132 | if (!res) { | ||
133 | dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n"); | ||
134 | return -EBUSY; | ||
135 | } | ||
136 | |||
137 | spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL); | ||
138 | if (!spics) { | ||
139 | dev_err(&pdev->dev, "memory allocation fail\n"); | ||
140 | return -ENOMEM; | ||
141 | } | ||
142 | |||
143 | spics->base = devm_request_and_ioremap(&pdev->dev, res); | ||
144 | if (!spics->base) { | ||
145 | dev_err(&pdev->dev, "request and ioremap fail\n"); | ||
146 | return -ENOMEM; | ||
147 | } | ||
148 | |||
149 | if (of_property_read_u32(np, "st-spics,peripcfg-reg", | ||
150 | &spics->perip_cfg)) | ||
151 | goto err_dt_data; | ||
152 | if (of_property_read_u32(np, "st-spics,sw-enable-bit", | ||
153 | &spics->sw_enable_bit)) | ||
154 | goto err_dt_data; | ||
155 | if (of_property_read_u32(np, "st-spics,cs-value-bit", | ||
156 | &spics->cs_value_bit)) | ||
157 | goto err_dt_data; | ||
158 | if (of_property_read_u32(np, "st-spics,cs-enable-mask", | ||
159 | &spics->cs_enable_mask)) | ||
160 | goto err_dt_data; | ||
161 | if (of_property_read_u32(np, "st-spics,cs-enable-shift", | ||
162 | &spics->cs_enable_shift)) | ||
163 | goto err_dt_data; | ||
164 | |||
165 | platform_set_drvdata(pdev, spics); | ||
166 | |||
167 | spics->chip.ngpio = NUM_OF_GPIO; | ||
168 | spics->chip.base = -1; | ||
169 | spics->chip.request = spics_request; | ||
170 | spics->chip.free = spics_free; | ||
171 | spics->chip.direction_input = spics_direction_input; | ||
172 | spics->chip.direction_output = spics_direction_output; | ||
173 | spics->chip.get = spics_get_value; | ||
174 | spics->chip.set = spics_set_value; | ||
175 | spics->chip.label = dev_name(&pdev->dev); | ||
176 | spics->chip.dev = &pdev->dev; | ||
177 | spics->chip.owner = THIS_MODULE; | ||
178 | spics->last_off = -1; | ||
179 | |||
180 | ret = gpiochip_add(&spics->chip); | ||
181 | if (ret) { | ||
182 | dev_err(&pdev->dev, "unable to add gpio chip\n"); | ||
183 | return ret; | ||
184 | } | ||
185 | |||
186 | dev_info(&pdev->dev, "spear spics registered\n"); | ||
187 | return 0; | ||
188 | |||
189 | err_dt_data: | ||
190 | dev_err(&pdev->dev, "DT probe failed\n"); | ||
191 | return -EINVAL; | ||
192 | } | ||
193 | |||
194 | static const struct of_device_id spics_gpio_of_match[] = { | ||
195 | { .compatible = "st,spear-spics-gpio" }, | ||
196 | {} | ||
197 | }; | ||
198 | MODULE_DEVICE_TABLE(of, spics_gpio_of_match); | ||
199 | |||
200 | static struct platform_driver spics_gpio_driver = { | ||
201 | .probe = spics_gpio_probe, | ||
202 | .driver = { | ||
203 | .owner = THIS_MODULE, | ||
204 | .name = "spear-spics-gpio", | ||
205 | .of_match_table = spics_gpio_of_match, | ||
206 | }, | ||
207 | }; | ||
208 | |||
209 | static int __init spics_gpio_init(void) | ||
210 | { | ||
211 | return platform_driver_register(&spics_gpio_driver); | ||
212 | } | ||
213 | subsys_initcall(spics_gpio_init); | ||
214 | |||
215 | MODULE_AUTHOR("Shiraz Hashim <shiraz.hashim@st.com>"); | ||
216 | MODULE_DESCRIPTION("ST Microlectronics SPEAr SPI Chip Select Abstraction"); | ||
217 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 1e48317e70fb..8c8447c7d2a8 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c | |||
@@ -292,17 +292,15 @@ static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio, | |||
292 | { | 292 | { |
293 | int base = tc3589x_gpio->irq_base; | 293 | int base = tc3589x_gpio->irq_base; |
294 | 294 | ||
295 | if (base) { | 295 | /* |
296 | tc3589x_gpio->domain = irq_domain_add_legacy( | 296 | * If this results in a linear domain, irq_create_mapping() will |
297 | NULL, tc3589x_gpio->chip.ngpio, base, | 297 | * take care of allocating IRQ descriptors at runtime. When a base |
298 | 0, &tc3589x_irq_ops, tc3589x_gpio); | 298 | * is provided, the IRQ descriptors will be allocated when the |
299 | } | 299 | * domain is instantiated. |
300 | else { | 300 | */ |
301 | tc3589x_gpio->domain = irq_domain_add_linear( | 301 | tc3589x_gpio->domain = irq_domain_add_simple(np, |
302 | np, tc3589x_gpio->chip.ngpio, | 302 | tc3589x_gpio->chip.ngpio, base, &tc3589x_irq_ops, |
303 | &tc3589x_irq_ops, tc3589x_gpio); | 303 | tc3589x_gpio); |
304 | } | ||
305 | |||
306 | if (!tc3589x_gpio->domain) { | 304 | if (!tc3589x_gpio->domain) { |
307 | dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n"); | 305 | dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n"); |
308 | return -ENOSYS; | 306 | return -ENOSYS; |
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index d982593d7563..5389be8c2b51 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/irqdomain.h> | 28 | #include <linux/irqdomain.h> |
29 | #include <linux/pinctrl/consumer.h> | 29 | #include <linux/pinctrl/consumer.h> |
30 | #include <linux/pm.h> | ||
30 | 31 | ||
31 | #include <asm/mach/irq.h> | 32 | #include <asm/mach/irq.h> |
32 | 33 | ||
@@ -64,7 +65,7 @@ struct tegra_gpio_bank { | |||
64 | int bank; | 65 | int bank; |
65 | int irq; | 66 | int irq; |
66 | spinlock_t lvl_lock[4]; | 67 | spinlock_t lvl_lock[4]; |
67 | #ifdef CONFIG_PM | 68 | #ifdef CONFIG_PM_SLEEP |
68 | u32 cnf[4]; | 69 | u32 cnf[4]; |
69 | u32 out[4]; | 70 | u32 out[4]; |
70 | u32 oe[4]; | 71 | u32 oe[4]; |
@@ -109,20 +110,18 @@ static void tegra_gpio_enable(int gpio) | |||
109 | { | 110 | { |
110 | tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1); | 111 | tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1); |
111 | } | 112 | } |
112 | EXPORT_SYMBOL_GPL(tegra_gpio_enable); | ||
113 | 113 | ||
114 | static void tegra_gpio_disable(int gpio) | 114 | static void tegra_gpio_disable(int gpio) |
115 | { | 115 | { |
116 | tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0); | 116 | tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0); |
117 | } | 117 | } |
118 | EXPORT_SYMBOL_GPL(tegra_gpio_disable); | ||
119 | 118 | ||
120 | int tegra_gpio_request(struct gpio_chip *chip, unsigned offset) | 119 | static int tegra_gpio_request(struct gpio_chip *chip, unsigned offset) |
121 | { | 120 | { |
122 | return pinctrl_request_gpio(offset); | 121 | return pinctrl_request_gpio(offset); |
123 | } | 122 | } |
124 | 123 | ||
125 | void tegra_gpio_free(struct gpio_chip *chip, unsigned offset) | 124 | static void tegra_gpio_free(struct gpio_chip *chip, unsigned offset) |
126 | { | 125 | { |
127 | pinctrl_free_gpio(offset); | 126 | pinctrl_free_gpio(offset); |
128 | tegra_gpio_disable(offset); | 127 | tegra_gpio_disable(offset); |
@@ -135,6 +134,11 @@ static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |||
135 | 134 | ||
136 | static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset) | 135 | static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset) |
137 | { | 136 | { |
137 | /* If gpio is in output mode then read from the out value */ | ||
138 | if ((tegra_gpio_readl(GPIO_OE(offset)) >> GPIO_BIT(offset)) & 1) | ||
139 | return (tegra_gpio_readl(GPIO_OUT(offset)) >> | ||
140 | GPIO_BIT(offset)) & 0x1; | ||
141 | |||
138 | return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1; | 142 | return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1; |
139 | } | 143 | } |
140 | 144 | ||
@@ -285,8 +289,8 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
285 | 289 | ||
286 | } | 290 | } |
287 | 291 | ||
288 | #ifdef CONFIG_PM | 292 | #ifdef CONFIG_PM_SLEEP |
289 | void tegra_gpio_resume(void) | 293 | static int tegra_gpio_resume(struct device *dev) |
290 | { | 294 | { |
291 | unsigned long flags; | 295 | unsigned long flags; |
292 | int b; | 296 | int b; |
@@ -308,9 +312,10 @@ void tegra_gpio_resume(void) | |||
308 | } | 312 | } |
309 | 313 | ||
310 | local_irq_restore(flags); | 314 | local_irq_restore(flags); |
315 | return 0; | ||
311 | } | 316 | } |
312 | 317 | ||
313 | void tegra_gpio_suspend(void) | 318 | static int tegra_gpio_suspend(struct device *dev) |
314 | { | 319 | { |
315 | unsigned long flags; | 320 | unsigned long flags; |
316 | int b; | 321 | int b; |
@@ -330,6 +335,7 @@ void tegra_gpio_suspend(void) | |||
330 | } | 335 | } |
331 | } | 336 | } |
332 | local_irq_restore(flags); | 337 | local_irq_restore(flags); |
338 | return 0; | ||
333 | } | 339 | } |
334 | 340 | ||
335 | static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable) | 341 | static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable) |
@@ -345,11 +351,15 @@ static struct irq_chip tegra_gpio_irq_chip = { | |||
345 | .irq_mask = tegra_gpio_irq_mask, | 351 | .irq_mask = tegra_gpio_irq_mask, |
346 | .irq_unmask = tegra_gpio_irq_unmask, | 352 | .irq_unmask = tegra_gpio_irq_unmask, |
347 | .irq_set_type = tegra_gpio_irq_set_type, | 353 | .irq_set_type = tegra_gpio_irq_set_type, |
348 | #ifdef CONFIG_PM | 354 | #ifdef CONFIG_PM_SLEEP |
349 | .irq_set_wake = tegra_gpio_wake_enable, | 355 | .irq_set_wake = tegra_gpio_wake_enable, |
350 | #endif | 356 | #endif |
351 | }; | 357 | }; |
352 | 358 | ||
359 | static const struct dev_pm_ops tegra_gpio_pm_ops = { | ||
360 | SET_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume) | ||
361 | }; | ||
362 | |||
353 | struct tegra_gpio_soc_config { | 363 | struct tegra_gpio_soc_config { |
354 | u32 bank_stride; | 364 | u32 bank_stride; |
355 | u32 upper_offset; | 365 | u32 upper_offset; |
@@ -380,7 +390,6 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) | |||
380 | { | 390 | { |
381 | const struct of_device_id *match; | 391 | const struct of_device_id *match; |
382 | struct tegra_gpio_soc_config *config; | 392 | struct tegra_gpio_soc_config *config; |
383 | int irq_base; | ||
384 | struct resource *res; | 393 | struct resource *res; |
385 | struct tegra_gpio_bank *bank; | 394 | struct tegra_gpio_bank *bank; |
386 | int gpio; | 395 | int gpio; |
@@ -417,14 +426,11 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) | |||
417 | return -ENODEV; | 426 | return -ENODEV; |
418 | } | 427 | } |
419 | 428 | ||
420 | irq_base = irq_alloc_descs(-1, 0, tegra_gpio_chip.ngpio, 0); | 429 | irq_domain = irq_domain_add_linear(pdev->dev.of_node, |
421 | if (irq_base < 0) { | 430 | tegra_gpio_chip.ngpio, |
422 | dev_err(&pdev->dev, "Couldn't allocate IRQ numbers\n"); | ||
423 | return -ENODEV; | ||
424 | } | ||
425 | irq_domain = irq_domain_add_legacy(pdev->dev.of_node, | ||
426 | tegra_gpio_chip.ngpio, irq_base, 0, | ||
427 | &irq_domain_simple_ops, NULL); | 431 | &irq_domain_simple_ops, NULL); |
432 | if (!irq_domain) | ||
433 | return -ENODEV; | ||
428 | 434 | ||
429 | for (i = 0; i < tegra_gpio_bank_count; i++) { | 435 | for (i = 0; i < tegra_gpio_bank_count; i++) { |
430 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); | 436 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); |
@@ -464,7 +470,7 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) | |||
464 | gpiochip_add(&tegra_gpio_chip); | 470 | gpiochip_add(&tegra_gpio_chip); |
465 | 471 | ||
466 | for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) { | 472 | for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) { |
467 | int irq = irq_find_mapping(irq_domain, gpio); | 473 | int irq = irq_create_mapping(irq_domain, gpio); |
468 | /* No validity check; all Tegra GPIOs are valid IRQs */ | 474 | /* No validity check; all Tegra GPIOs are valid IRQs */ |
469 | 475 | ||
470 | bank = &tegra_gpio_banks[GPIO_BANK(gpio)]; | 476 | bank = &tegra_gpio_banks[GPIO_BANK(gpio)]; |
@@ -493,6 +499,7 @@ static struct platform_driver tegra_gpio_driver = { | |||
493 | .driver = { | 499 | .driver = { |
494 | .name = "tegra-gpio", | 500 | .name = "tegra-gpio", |
495 | .owner = THIS_MODULE, | 501 | .owner = THIS_MODULE, |
502 | .pm = &tegra_gpio_pm_ops, | ||
496 | .of_match_table = tegra_gpio_of_match, | 503 | .of_match_table = tegra_gpio_of_match, |
497 | }, | 504 | }, |
498 | .probe = tegra_gpio_probe, | 505 | .probe = tegra_gpio_probe, |
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index c5f8ca233e1f..d2138b0fd4ca 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c | |||
@@ -88,11 +88,15 @@ static inline int gpio_twl4030_write(u8 address, u8 data) | |||
88 | /*----------------------------------------------------------------------*/ | 88 | /*----------------------------------------------------------------------*/ |
89 | 89 | ||
90 | /* | 90 | /* |
91 | * LED register offsets (use TWL4030_MODULE_{LED,PWMA,PWMB})) | 91 | * LED register offsets from TWL_MODULE_LED base |
92 | * PWMs A and B are dedicated to LEDs A and B, respectively. | 92 | * PWMs A and B are dedicated to LEDs A and B, respectively. |
93 | */ | 93 | */ |
94 | 94 | ||
95 | #define TWL4030_LED_LEDEN 0x0 | 95 | #define TWL4030_LED_LEDEN_REG 0x00 |
96 | #define TWL4030_PWMAON_REG 0x01 | ||
97 | #define TWL4030_PWMAOFF_REG 0x02 | ||
98 | #define TWL4030_PWMBON_REG 0x03 | ||
99 | #define TWL4030_PWMBOFF_REG 0x04 | ||
96 | 100 | ||
97 | /* LEDEN bits */ | 101 | /* LEDEN bits */ |
98 | #define LEDEN_LEDAON BIT(0) | 102 | #define LEDEN_LEDAON BIT(0) |
@@ -104,9 +108,6 @@ static inline int gpio_twl4030_write(u8 address, u8 data) | |||
104 | #define LEDEN_PWM_LENGTHA BIT(6) | 108 | #define LEDEN_PWM_LENGTHA BIT(6) |
105 | #define LEDEN_PWM_LENGTHB BIT(7) | 109 | #define LEDEN_PWM_LENGTHB BIT(7) |
106 | 110 | ||
107 | #define TWL4030_PWMx_PWMxON 0x0 | ||
108 | #define TWL4030_PWMx_PWMxOFF 0x1 | ||
109 | |||
110 | #define PWMxON_LENGTH BIT(7) | 111 | #define PWMxON_LENGTH BIT(7) |
111 | 112 | ||
112 | /*----------------------------------------------------------------------*/ | 113 | /*----------------------------------------------------------------------*/ |
@@ -145,7 +146,7 @@ static void twl4030_led_set_value(int led, int value) | |||
145 | else | 146 | else |
146 | cached_leden |= mask; | 147 | cached_leden |= mask; |
147 | status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden, | 148 | status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden, |
148 | TWL4030_LED_LEDEN); | 149 | TWL4030_LED_LEDEN_REG); |
149 | mutex_unlock(&gpio_lock); | 150 | mutex_unlock(&gpio_lock); |
150 | } | 151 | } |
151 | 152 | ||
@@ -216,33 +217,33 @@ static int twl_request(struct gpio_chip *chip, unsigned offset) | |||
216 | if (offset >= TWL4030_GPIO_MAX) { | 217 | if (offset >= TWL4030_GPIO_MAX) { |
217 | u8 ledclr_mask = LEDEN_LEDAON | LEDEN_LEDAEXT | 218 | u8 ledclr_mask = LEDEN_LEDAON | LEDEN_LEDAEXT |
218 | | LEDEN_LEDAPWM | LEDEN_PWM_LENGTHA; | 219 | | LEDEN_LEDAPWM | LEDEN_PWM_LENGTHA; |
219 | u8 module = TWL4030_MODULE_PWMA; | 220 | u8 reg = TWL4030_PWMAON_REG; |
220 | 221 | ||
221 | offset -= TWL4030_GPIO_MAX; | 222 | offset -= TWL4030_GPIO_MAX; |
222 | if (offset) { | 223 | if (offset) { |
223 | ledclr_mask <<= 1; | 224 | ledclr_mask <<= 1; |
224 | module = TWL4030_MODULE_PWMB; | 225 | reg = TWL4030_PWMBON_REG; |
225 | } | 226 | } |
226 | 227 | ||
227 | /* initialize PWM to always-drive */ | 228 | /* initialize PWM to always-drive */ |
228 | status = twl_i2c_write_u8(module, 0x7f, | 229 | /* Configure PWM OFF register first */ |
229 | TWL4030_PWMx_PWMxOFF); | 230 | status = twl_i2c_write_u8(TWL4030_MODULE_LED, 0x7f, reg + 1); |
230 | if (status < 0) | 231 | if (status < 0) |
231 | goto done; | 232 | goto done; |
232 | status = twl_i2c_write_u8(module, 0x7f, | 233 | |
233 | TWL4030_PWMx_PWMxON); | 234 | /* Followed by PWM ON register */ |
235 | status = twl_i2c_write_u8(TWL4030_MODULE_LED, 0x7f, reg); | ||
234 | if (status < 0) | 236 | if (status < 0) |
235 | goto done; | 237 | goto done; |
236 | 238 | ||
237 | /* init LED to not-driven (high) */ | 239 | /* init LED to not-driven (high) */ |
238 | module = TWL4030_MODULE_LED; | 240 | status = twl_i2c_read_u8(TWL4030_MODULE_LED, &cached_leden, |
239 | status = twl_i2c_read_u8(module, &cached_leden, | 241 | TWL4030_LED_LEDEN_REG); |
240 | TWL4030_LED_LEDEN); | ||
241 | if (status < 0) | 242 | if (status < 0) |
242 | goto done; | 243 | goto done; |
243 | cached_leden &= ~ledclr_mask; | 244 | cached_leden &= ~ledclr_mask; |
244 | status = twl_i2c_write_u8(module, cached_leden, | 245 | status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden, |
245 | TWL4030_LED_LEDEN); | 246 | TWL4030_LED_LEDEN_REG); |
246 | if (status < 0) | 247 | if (status < 0) |
247 | goto done; | 248 | goto done; |
248 | 249 | ||
diff --git a/drivers/gpio/gpio-vt8500.c b/drivers/gpio/gpio-vt8500.c index bcd8e4aa7c7d..9ed2a2b347fa 100644 --- a/drivers/gpio/gpio-vt8500.c +++ b/drivers/gpio/gpio-vt8500.c | |||
@@ -96,6 +96,7 @@ static struct vt8500_gpio_data wm8505_data = { | |||
96 | VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12), | 96 | VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12), |
97 | VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16), | 97 | VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16), |
98 | VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22), | 98 | VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22), |
99 | VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6), | ||
99 | }, | 100 | }, |
100 | }; | 101 | }; |
101 | 102 | ||
@@ -115,6 +116,7 @@ static struct vt8500_gpio_data wm8650_data = { | |||
115 | VT8500_BANK(0x58, 0x98, 0xD8, 0x18, 32), | 116 | VT8500_BANK(0x58, 0x98, 0xD8, 0x18, 32), |
116 | VT8500_BANK(0x5C, 0x9C, 0xDC, 0x1C, 32), | 117 | VT8500_BANK(0x5C, 0x9C, 0xDC, 0x1C, 32), |
117 | VT8500_BANK(0x7C, 0xBC, 0xFC, 0x3C, 32), | 118 | VT8500_BANK(0x7C, 0xBC, 0xFC, 0x3C, 32), |
119 | VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6), | ||
118 | }, | 120 | }, |
119 | }; | 121 | }; |
120 | 122 | ||
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c5f650095faa..b667f768c23b 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -191,6 +191,32 @@ err: | |||
191 | return ret; | 191 | return ret; |
192 | } | 192 | } |
193 | 193 | ||
194 | /* caller ensures gpio is valid and requested, chip->get_direction may sleep */ | ||
195 | static int gpio_get_direction(unsigned gpio) | ||
196 | { | ||
197 | struct gpio_chip *chip; | ||
198 | struct gpio_desc *desc = &gpio_desc[gpio]; | ||
199 | int status = -EINVAL; | ||
200 | |||
201 | chip = gpio_to_chip(gpio); | ||
202 | gpio -= chip->base; | ||
203 | |||
204 | if (!chip->get_direction) | ||
205 | return status; | ||
206 | |||
207 | status = chip->get_direction(chip, gpio); | ||
208 | if (status > 0) { | ||
209 | /* GPIOF_DIR_IN, or other positive */ | ||
210 | status = 1; | ||
211 | clear_bit(FLAG_IS_OUT, &desc->flags); | ||
212 | } | ||
213 | if (status == 0) { | ||
214 | /* GPIOF_DIR_OUT */ | ||
215 | set_bit(FLAG_IS_OUT, &desc->flags); | ||
216 | } | ||
217 | return status; | ||
218 | } | ||
219 | |||
194 | #ifdef CONFIG_GPIO_SYSFS | 220 | #ifdef CONFIG_GPIO_SYSFS |
195 | 221 | ||
196 | /* lock protects against unexport_gpio() being called while | 222 | /* lock protects against unexport_gpio() being called while |
@@ -223,6 +249,7 @@ static ssize_t gpio_direction_show(struct device *dev, | |||
223 | struct device_attribute *attr, char *buf) | 249 | struct device_attribute *attr, char *buf) |
224 | { | 250 | { |
225 | const struct gpio_desc *desc = dev_get_drvdata(dev); | 251 | const struct gpio_desc *desc = dev_get_drvdata(dev); |
252 | unsigned gpio = desc - gpio_desc; | ||
226 | ssize_t status; | 253 | ssize_t status; |
227 | 254 | ||
228 | mutex_lock(&sysfs_lock); | 255 | mutex_lock(&sysfs_lock); |
@@ -230,6 +257,7 @@ static ssize_t gpio_direction_show(struct device *dev, | |||
230 | if (!test_bit(FLAG_EXPORT, &desc->flags)) | 257 | if (!test_bit(FLAG_EXPORT, &desc->flags)) |
231 | status = -EIO; | 258 | status = -EIO; |
232 | else | 259 | else |
260 | gpio_get_direction(gpio); | ||
233 | status = sprintf(buf, "%s\n", | 261 | status = sprintf(buf, "%s\n", |
234 | test_bit(FLAG_IS_OUT, &desc->flags) | 262 | test_bit(FLAG_IS_OUT, &desc->flags) |
235 | ? "out" : "in"); | 263 | ? "out" : "in"); |
@@ -704,8 +732,9 @@ int gpio_export(unsigned gpio, bool direction_may_change) | |||
704 | { | 732 | { |
705 | unsigned long flags; | 733 | unsigned long flags; |
706 | struct gpio_desc *desc; | 734 | struct gpio_desc *desc; |
707 | int status = -EINVAL; | 735 | int status; |
708 | const char *ioname = NULL; | 736 | const char *ioname = NULL; |
737 | struct device *dev; | ||
709 | 738 | ||
710 | /* can't export until sysfs is available ... */ | 739 | /* can't export until sysfs is available ... */ |
711 | if (!gpio_class.p) { | 740 | if (!gpio_class.p) { |
@@ -713,59 +742,66 @@ int gpio_export(unsigned gpio, bool direction_may_change) | |||
713 | return -ENOENT; | 742 | return -ENOENT; |
714 | } | 743 | } |
715 | 744 | ||
716 | if (!gpio_is_valid(gpio)) | 745 | if (!gpio_is_valid(gpio)) { |
717 | goto done; | 746 | pr_debug("%s: gpio %d is not valid\n", __func__, gpio); |
747 | return -EINVAL; | ||
748 | } | ||
718 | 749 | ||
719 | mutex_lock(&sysfs_lock); | 750 | mutex_lock(&sysfs_lock); |
720 | 751 | ||
721 | spin_lock_irqsave(&gpio_lock, flags); | 752 | spin_lock_irqsave(&gpio_lock, flags); |
722 | desc = &gpio_desc[gpio]; | 753 | desc = &gpio_desc[gpio]; |
723 | if (test_bit(FLAG_REQUESTED, &desc->flags) | 754 | if (!test_bit(FLAG_REQUESTED, &desc->flags) || |
724 | && !test_bit(FLAG_EXPORT, &desc->flags)) { | 755 | test_bit(FLAG_EXPORT, &desc->flags)) { |
725 | status = 0; | 756 | spin_unlock_irqrestore(&gpio_lock, flags); |
726 | if (!desc->chip->direction_input | 757 | pr_debug("%s: gpio %d unavailable (requested=%d, exported=%d)\n", |
727 | || !desc->chip->direction_output) | 758 | __func__, gpio, |
728 | direction_may_change = false; | 759 | test_bit(FLAG_REQUESTED, &desc->flags), |
760 | test_bit(FLAG_EXPORT, &desc->flags)); | ||
761 | status = -EPERM; | ||
762 | goto fail_unlock; | ||
729 | } | 763 | } |
764 | |||
765 | if (!desc->chip->direction_input || !desc->chip->direction_output) | ||
766 | direction_may_change = false; | ||
730 | spin_unlock_irqrestore(&gpio_lock, flags); | 767 | spin_unlock_irqrestore(&gpio_lock, flags); |
731 | 768 | ||
732 | if (desc->chip->names && desc->chip->names[gpio - desc->chip->base]) | 769 | if (desc->chip->names && desc->chip->names[gpio - desc->chip->base]) |
733 | ioname = desc->chip->names[gpio - desc->chip->base]; | 770 | ioname = desc->chip->names[gpio - desc->chip->base]; |
734 | 771 | ||
735 | if (status == 0) { | 772 | dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), |
736 | struct device *dev; | 773 | desc, ioname ? ioname : "gpio%u", gpio); |
737 | 774 | if (IS_ERR(dev)) { | |
738 | dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), | 775 | status = PTR_ERR(dev); |
739 | desc, ioname ? ioname : "gpio%u", gpio); | 776 | goto fail_unlock; |
740 | if (!IS_ERR(dev)) { | ||
741 | status = sysfs_create_group(&dev->kobj, | ||
742 | &gpio_attr_group); | ||
743 | |||
744 | if (!status && direction_may_change) | ||
745 | status = device_create_file(dev, | ||
746 | &dev_attr_direction); | ||
747 | |||
748 | if (!status && gpio_to_irq(gpio) >= 0 | ||
749 | && (direction_may_change | ||
750 | || !test_bit(FLAG_IS_OUT, | ||
751 | &desc->flags))) | ||
752 | status = device_create_file(dev, | ||
753 | &dev_attr_edge); | ||
754 | |||
755 | if (status != 0) | ||
756 | device_unregister(dev); | ||
757 | } else | ||
758 | status = PTR_ERR(dev); | ||
759 | if (status == 0) | ||
760 | set_bit(FLAG_EXPORT, &desc->flags); | ||
761 | } | 777 | } |
762 | 778 | ||
763 | mutex_unlock(&sysfs_lock); | 779 | status = sysfs_create_group(&dev->kobj, &gpio_attr_group); |
764 | |||
765 | done: | ||
766 | if (status) | 780 | if (status) |
767 | pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); | 781 | goto fail_unregister_device; |
768 | 782 | ||
783 | if (direction_may_change) { | ||
784 | status = device_create_file(dev, &dev_attr_direction); | ||
785 | if (status) | ||
786 | goto fail_unregister_device; | ||
787 | } | ||
788 | |||
789 | if (gpio_to_irq(gpio) >= 0 && (direction_may_change || | ||
790 | !test_bit(FLAG_IS_OUT, &desc->flags))) { | ||
791 | status = device_create_file(dev, &dev_attr_edge); | ||
792 | if (status) | ||
793 | goto fail_unregister_device; | ||
794 | } | ||
795 | |||
796 | set_bit(FLAG_EXPORT, &desc->flags); | ||
797 | mutex_unlock(&sysfs_lock); | ||
798 | return 0; | ||
799 | |||
800 | fail_unregister_device: | ||
801 | device_unregister(dev); | ||
802 | fail_unlock: | ||
803 | mutex_unlock(&sysfs_lock); | ||
804 | pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); | ||
769 | return status; | 805 | return status; |
770 | } | 806 | } |
771 | EXPORT_SYMBOL_GPL(gpio_export); | 807 | EXPORT_SYMBOL_GPL(gpio_export); |
@@ -1075,6 +1111,7 @@ int gpiochip_add(struct gpio_chip *chip) | |||
1075 | * inputs (often with pullups enabled) so power | 1111 | * inputs (often with pullups enabled) so power |
1076 | * usage is minimized. Linux code should set the | 1112 | * usage is minimized. Linux code should set the |
1077 | * gpio direction first thing; but until it does, | 1113 | * gpio direction first thing; but until it does, |
1114 | * and in case chip->get_direction is not set, | ||
1078 | * we may expose the wrong direction in sysfs. | 1115 | * we may expose the wrong direction in sysfs. |
1079 | */ | 1116 | */ |
1080 | gpio_desc[id].flags = !chip->direction_input | 1117 | gpio_desc[id].flags = !chip->direction_input |
@@ -1274,9 +1311,15 @@ int gpio_request(unsigned gpio, const char *label) | |||
1274 | desc_set_label(desc, NULL); | 1311 | desc_set_label(desc, NULL); |
1275 | module_put(chip->owner); | 1312 | module_put(chip->owner); |
1276 | clear_bit(FLAG_REQUESTED, &desc->flags); | 1313 | clear_bit(FLAG_REQUESTED, &desc->flags); |
1314 | goto done; | ||
1277 | } | 1315 | } |
1278 | } | 1316 | } |
1279 | 1317 | if (chip->get_direction) { | |
1318 | /* chip->get_direction may sleep */ | ||
1319 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
1320 | gpio_get_direction(gpio); | ||
1321 | spin_lock_irqsave(&gpio_lock, flags); | ||
1322 | } | ||
1280 | done: | 1323 | done: |
1281 | if (status) | 1324 | if (status) |
1282 | pr_debug("gpio_request: gpio-%d (%s) status %d\n", | 1325 | pr_debug("gpio_request: gpio-%d (%s) status %d\n", |
@@ -1812,6 +1855,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
1812 | if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) | 1855 | if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) |
1813 | continue; | 1856 | continue; |
1814 | 1857 | ||
1858 | gpio_get_direction(gpio); | ||
1815 | is_out = test_bit(FLAG_IS_OUT, &gdesc->flags); | 1859 | is_out = test_bit(FLAG_IS_OUT, &gdesc->flags); |
1816 | seq_printf(s, " gpio-%-3d (%-20.20s) %s %s", | 1860 | seq_printf(s, " gpio-%-3d (%-20.20s) %s %s", |
1817 | gpio, gdesc->label, | 1861 | gpio, gdesc->label, |
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 2b84fc32fae2..b6516f32280d 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h | |||
@@ -57,6 +57,8 @@ struct device_node; | |||
57 | * enabling module power and clock; may sleep | 57 | * enabling module power and clock; may sleep |
58 | * @free: optional hook for chip-specific deactivation, such as | 58 | * @free: optional hook for chip-specific deactivation, such as |
59 | * disabling module power and clock; may sleep | 59 | * disabling module power and clock; may sleep |
60 | * @get_direction: returns direction for signal "offset", 0=out, 1=in, | ||
61 | * (same as GPIOF_DIR_XXX), or negative error | ||
60 | * @direction_input: configures signal "offset" as input, or returns error | 62 | * @direction_input: configures signal "offset" as input, or returns error |
61 | * @get: returns value for signal "offset"; for output signals this | 63 | * @get: returns value for signal "offset"; for output signals this |
62 | * returns either the value actually sensed, or zero | 64 | * returns either the value actually sensed, or zero |
@@ -101,7 +103,8 @@ struct gpio_chip { | |||
101 | unsigned offset); | 103 | unsigned offset); |
102 | void (*free)(struct gpio_chip *chip, | 104 | void (*free)(struct gpio_chip *chip, |
103 | unsigned offset); | 105 | unsigned offset); |
104 | 106 | int (*get_direction)(struct gpio_chip *chip, | |
107 | unsigned offset); | ||
105 | int (*direction_input)(struct gpio_chip *chip, | 108 | int (*direction_input)(struct gpio_chip *chip, |
106 | unsigned offset); | 109 | unsigned offset); |
107 | int (*get)(struct gpio_chip *chip, | 110 | int (*get)(struct gpio_chip *chip, |