diff options
29 files changed, 1522 insertions, 243 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt b/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt new file mode 100644 index 000000000000..a0e4cf885213 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | STMPE gpio | ||
2 | ---------- | ||
3 | |||
4 | Required properties: | ||
5 | - compatible: "st,stmpe-gpio" | ||
6 | |||
7 | Optional properties: | ||
8 | - st,norequest-mask: bitmask specifying which GPIOs should _not_ be requestable | ||
9 | due to different usage (e.g. touch, keypad) | ||
10 | |||
11 | Node name must be stmpe_gpio and should be child node of stmpe node to which it | ||
12 | belongs. | ||
13 | |||
14 | Example: | ||
15 | stmpe_gpio { | ||
16 | compatible = "st,stmpe-gpio"; | ||
17 | st,norequest-mask = <0x20>; //gpio 5 can't be used | ||
18 | }; | ||
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 672e0a2d5871..8a027f9e339e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -366,6 +366,7 @@ config ARCH_CNS3XXX | |||
366 | 366 | ||
367 | config ARCH_CLPS711X | 367 | config ARCH_CLPS711X |
368 | bool "Cirrus Logic CLPS711x/EP721x/EP731x-based" | 368 | bool "Cirrus Logic CLPS711x/EP721x/EP731x-based" |
369 | select ARCH_REQUIRE_GPIOLIB | ||
369 | select ARCH_USES_GETTIMEOFFSET | 370 | select ARCH_USES_GETTIMEOFFSET |
370 | select CLKDEV_LOOKUP | 371 | select CLKDEV_LOOKUP |
371 | select COMMON_CLK | 372 | select COMMON_CLK |
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c index 0a43f3189c21..7a05de794a8c 100644 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ b/arch/arm/mach-shmobile/board-kzm9g.c | |||
@@ -548,7 +548,6 @@ static struct platform_device fsi_ak4648_device = { | |||
548 | /* I2C */ | 548 | /* I2C */ |
549 | static struct pcf857x_platform_data pcf8575_pdata = { | 549 | static struct pcf857x_platform_data pcf8575_pdata = { |
550 | .gpio_base = GPIO_PCF8575_BASE, | 550 | .gpio_base = GPIO_PCF8575_BASE, |
551 | .irq = intcs_evt2irq(0x3260), /* IRQ19 */ | ||
552 | }; | 551 | }; |
553 | 552 | ||
554 | static struct i2c_board_info i2c0_devices[] = { | 553 | static struct i2c_board_info i2c0_devices[] = { |
@@ -570,6 +569,7 @@ static struct i2c_board_info i2c1_devices[] = { | |||
570 | static struct i2c_board_info i2c3_devices[] = { | 569 | static struct i2c_board_info i2c3_devices[] = { |
571 | { | 570 | { |
572 | I2C_BOARD_INFO("pcf8575", 0x20), | 571 | I2C_BOARD_INFO("pcf8575", 0x20), |
572 | .irq = intcs_evt2irq(0x3260), /* IRQ19 */ | ||
573 | .platform_data = &pcf8575_pdata, | 573 | .platform_data = &pcf8575_pdata, |
574 | }, | 574 | }, |
575 | }; | 575 | }; |
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 f16557690cfd..14a6c2913e49 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -90,11 +90,26 @@ config GPIO_DA9052 | |||
90 | help | 90 | help |
91 | Say yes here to enable the GPIO driver for the DA9052 chip. | 91 | Say yes here to enable the GPIO driver for the DA9052 chip. |
92 | 92 | ||
93 | config GPIO_DA9055 | ||
94 | tristate "Dialog Semiconductor DA9055 GPIO" | ||
95 | depends on MFD_DA9055 | ||
96 | help | ||
97 | Say yes here to enable the GPIO driver for the DA9055 chip. | ||
98 | |||
99 | The Dialog DA9055 PMIC chip has 3 GPIO pins that can be | ||
100 | be controller by this driver. | ||
101 | |||
102 | If driver is built as a module it will be called gpio-da9055. | ||
103 | |||
93 | config GPIO_MAX730X | 104 | config GPIO_MAX730X |
94 | tristate | 105 | tristate |
95 | 106 | ||
96 | comment "Memory mapped GPIO drivers:" | 107 | comment "Memory mapped GPIO drivers:" |
97 | 108 | ||
109 | config GPIO_CLPS711X | ||
110 | def_bool y | ||
111 | depends on ARCH_CLPS711X | ||
112 | |||
98 | config GPIO_GENERIC_PLATFORM | 113 | config GPIO_GENERIC_PLATFORM |
99 | tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" | 114 | tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" |
100 | select GPIO_GENERIC | 115 | select GPIO_GENERIC |
@@ -174,7 +189,7 @@ config GPIO_MXS | |||
174 | 189 | ||
175 | config GPIO_PL061 | 190 | config GPIO_PL061 |
176 | bool "PrimeCell PL061 GPIO support" | 191 | bool "PrimeCell PL061 GPIO support" |
177 | depends on ARM_AMBA | 192 | depends on ARM && ARM_AMBA |
178 | select GENERIC_IRQ_CHIP | 193 | select GENERIC_IRQ_CHIP |
179 | help | 194 | help |
180 | Say yes here to support the PrimeCell PL061 GPIO device | 195 | Say yes here to support the PrimeCell PL061 GPIO device |
@@ -185,6 +200,13 @@ config GPIO_PXA | |||
185 | help | 200 | help |
186 | Say yes here to support the PXA GPIO device | 201 | Say yes here to support the PXA GPIO device |
187 | 202 | ||
203 | config GPIO_SPEAR_SPICS | ||
204 | bool "ST SPEAr13xx SPI Chip Select as GPIO support" | ||
205 | depends on PLAT_SPEAR | ||
206 | select GENERIC_IRQ_CHIP | ||
207 | help | ||
208 | Say yes here to support ST SPEAr SPI Chip Select as GPIO device | ||
209 | |||
188 | config GPIO_STA2X11 | 210 | config GPIO_STA2X11 |
189 | bool "STA2x11/ConneXt GPIO support" | 211 | bool "STA2x11/ConneXt GPIO support" |
190 | depends on MFD_STA2X11 | 212 | depends on MFD_STA2X11 |
@@ -193,6 +215,14 @@ config GPIO_STA2X11 | |||
193 | Say yes here to support the STA2x11/ConneXt GPIO device. | 215 | Say yes here to support the STA2x11/ConneXt GPIO device. |
194 | The GPIO module has 128 GPIO pins with alternate functions. | 216 | The GPIO module has 128 GPIO pins with alternate functions. |
195 | 217 | ||
218 | config GPIO_TS5500 | ||
219 | tristate "TS-5500 DIO blocks and compatibles" | ||
220 | help | ||
221 | This driver supports Digital I/O exposed by pin blocks found on some | ||
222 | Technologic Systems platforms. It includes, but is not limited to, 3 | ||
223 | blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600 | ||
224 | LCD port. | ||
225 | |||
196 | config GPIO_VT8500 | 226 | config GPIO_VT8500 |
197 | bool "VIA/Wondermedia SoC GPIO Support" | 227 | bool "VIA/Wondermedia SoC GPIO Support" |
198 | depends on ARCH_VT8500 | 228 | depends on ARCH_VT8500 |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 420dbaca05f1..76b344683251 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -17,8 +17,10 @@ obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o | |||
17 | obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o | 17 | obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o |
18 | obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o | 18 | obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o |
19 | obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o | 19 | obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o |
20 | obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o | ||
20 | obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o | 21 | obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o |
21 | obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o | 22 | obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o |
23 | obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o | ||
22 | obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o | 24 | obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o |
23 | obj-$(CONFIG_GPIO_EM) += gpio-em.o | 25 | obj-$(CONFIG_GPIO_EM) += gpio-em.o |
24 | obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o | 26 | obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o |
@@ -58,6 +60,7 @@ obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o | |||
58 | obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o | 60 | obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o |
59 | obj-$(CONFIG_GPIO_SCH) += gpio-sch.o | 61 | obj-$(CONFIG_GPIO_SCH) += gpio-sch.o |
60 | obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o | 62 | obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o |
63 | obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o | ||
61 | obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o | 64 | obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o |
62 | obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o | 65 | obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o |
63 | obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o | 66 | obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o |
@@ -69,6 +72,7 @@ obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o | |||
69 | obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o | 72 | obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o |
70 | obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o | 73 | obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o |
71 | obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o | 74 | obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o |
75 | obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o | ||
72 | obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o | 76 | obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o |
73 | obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o | 77 | obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o |
74 | obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o | 78 | obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.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-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 16af35cd2b10..a19b7457a726 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c | |||
@@ -223,11 +223,11 @@ static void pcf857x_irq_domain_cleanup(struct pcf857x *gpio) | |||
223 | 223 | ||
224 | static int pcf857x_irq_domain_init(struct pcf857x *gpio, | 224 | static int pcf857x_irq_domain_init(struct pcf857x *gpio, |
225 | struct pcf857x_platform_data *pdata, | 225 | struct pcf857x_platform_data *pdata, |
226 | struct device *dev) | 226 | struct i2c_client *client) |
227 | { | 227 | { |
228 | int status; | 228 | int status; |
229 | 229 | ||
230 | gpio->irq_domain = irq_domain_add_linear(dev->of_node, | 230 | gpio->irq_domain = irq_domain_add_linear(client->dev.of_node, |
231 | gpio->chip.ngpio, | 231 | gpio->chip.ngpio, |
232 | &pcf857x_irq_domain_ops, | 232 | &pcf857x_irq_domain_ops, |
233 | NULL); | 233 | NULL); |
@@ -235,15 +235,15 @@ static int pcf857x_irq_domain_init(struct pcf857x *gpio, | |||
235 | goto fail; | 235 | goto fail; |
236 | 236 | ||
237 | /* enable real irq */ | 237 | /* enable real irq */ |
238 | status = request_irq(pdata->irq, pcf857x_irq_demux, 0, | 238 | status = request_irq(client->irq, pcf857x_irq_demux, 0, |
239 | dev_name(dev), gpio); | 239 | dev_name(&client->dev), gpio); |
240 | if (status) | 240 | if (status) |
241 | goto fail; | 241 | goto fail; |
242 | 242 | ||
243 | /* enable gpio_to_irq() */ | 243 | /* enable gpio_to_irq() */ |
244 | INIT_WORK(&gpio->work, pcf857x_irq_demux_work); | 244 | INIT_WORK(&gpio->work, pcf857x_irq_demux_work); |
245 | gpio->chip.to_irq = pcf857x_to_irq; | 245 | gpio->chip.to_irq = pcf857x_to_irq; |
246 | gpio->irq = pdata->irq; | 246 | gpio->irq = client->irq; |
247 | 247 | ||
248 | return 0; | 248 | return 0; |
249 | 249 | ||
@@ -285,8 +285,8 @@ static int pcf857x_probe(struct i2c_client *client, | |||
285 | gpio->chip.ngpio = id->driver_data; | 285 | gpio->chip.ngpio = id->driver_data; |
286 | 286 | ||
287 | /* enable gpio_to_irq() if platform has settings */ | 287 | /* enable gpio_to_irq() if platform has settings */ |
288 | if (pdata && pdata->irq) { | 288 | if (pdata && client->irq) { |
289 | status = pcf857x_irq_domain_init(gpio, pdata, &client->dev); | 289 | status = pcf857x_irq_domain_init(gpio, pdata, client); |
290 | if (status < 0) { | 290 | if (status < 0) { |
291 | dev_err(&client->dev, "irq_domain init failed\n"); | 291 | dev_err(&client->dev, "irq_domain init failed\n"); |
292 | goto fail; | 292 | goto fail; |
@@ -368,15 +368,6 @@ static int pcf857x_probe(struct i2c_client *client, | |||
368 | if (status < 0) | 368 | if (status < 0) |
369 | goto fail; | 369 | goto fail; |
370 | 370 | ||
371 | /* NOTE: these chips can issue "some pin-changed" IRQs, which we | ||
372 | * don't yet even try to use. Among other issues, the relevant | ||
373 | * genirq state isn't available to modular drivers; and most irq | ||
374 | * methods can't be called from sleeping contexts. | ||
375 | */ | ||
376 | |||
377 | dev_info(&client->dev, "%s\n", | ||
378 | client->irq ? " (irq ignored)" : ""); | ||
379 | |||
380 | /* Let platform code set up the GPIOs and their users. | 371 | /* Let platform code set up the GPIOs and their users. |
381 | * Now is the first time anyone could use them. | 372 | * Now is the first time anyone could use them. |
382 | */ | 373 | */ |
@@ -388,13 +379,15 @@ static int pcf857x_probe(struct i2c_client *client, | |||
388 | dev_warn(&client->dev, "setup --> %d\n", status); | 379 | dev_warn(&client->dev, "setup --> %d\n", status); |
389 | } | 380 | } |
390 | 381 | ||
382 | dev_info(&client->dev, "probed\n"); | ||
383 | |||
391 | return 0; | 384 | return 0; |
392 | 385 | ||
393 | fail: | 386 | fail: |
394 | dev_dbg(&client->dev, "probe error %d for '%s'\n", | 387 | dev_dbg(&client->dev, "probe error %d for '%s'\n", |
395 | status, client->name); | 388 | status, client->name); |
396 | 389 | ||
397 | if (pdata && pdata->irq) | 390 | if (pdata && client->irq) |
398 | pcf857x_irq_domain_cleanup(gpio); | 391 | pcf857x_irq_domain_cleanup(gpio); |
399 | 392 | ||
400 | kfree(gpio); | 393 | kfree(gpio); |
@@ -418,7 +411,7 @@ static int pcf857x_remove(struct i2c_client *client) | |||
418 | } | 411 | } |
419 | } | 412 | } |
420 | 413 | ||
421 | if (pdata && pdata->irq) | 414 | if (pdata && client->irq) |
422 | pcf857x_irq_domain_cleanup(gpio); | 415 | pcf857x_irq_domain_cleanup(gpio); |
423 | 416 | ||
424 | status = gpiochip_remove(&gpio->chip); | 417 | status = gpiochip_remove(&gpio->chip); |
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..c1720de18a4f 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c | |||
@@ -48,12 +48,7 @@ struct pl061_context_save_regs { | |||
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | struct pl061_gpio { | 50 | struct pl061_gpio { |
51 | /* Each of the two spinlocks protects a different set of hardware | 51 | spinlock_t lock; |
52 | * regiters and data structurs. This decouples the code of the IRQ from | ||
53 | * the GPIO code. This also makes the case of a GPIO routine call from | ||
54 | * the IRQ code simpler. | ||
55 | */ | ||
56 | spinlock_t lock; /* GPIO registers */ | ||
57 | 52 | ||
58 | void __iomem *base; | 53 | void __iomem *base; |
59 | int irq_base; | 54 | int irq_base; |
@@ -216,39 +211,34 @@ static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base) | |||
216 | IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0); | 211 | IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0); |
217 | } | 212 | } |
218 | 213 | ||
219 | static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | 214 | static int pl061_probe(struct amba_device *adev, const struct amba_id *id) |
220 | { | 215 | { |
221 | struct pl061_platform_data *pdata; | 216 | struct device *dev = &adev->dev; |
217 | struct pl061_platform_data *pdata = dev->platform_data; | ||
222 | struct pl061_gpio *chip; | 218 | struct pl061_gpio *chip; |
223 | int ret, irq, i; | 219 | int ret, irq, i; |
224 | 220 | ||
225 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 221 | chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); |
226 | if (chip == NULL) | 222 | if (chip == NULL) |
227 | return -ENOMEM; | 223 | return -ENOMEM; |
228 | 224 | ||
229 | pdata = dev->dev.platform_data; | ||
230 | if (pdata) { | 225 | if (pdata) { |
231 | chip->gc.base = pdata->gpio_base; | 226 | chip->gc.base = pdata->gpio_base; |
232 | chip->irq_base = pdata->irq_base; | 227 | chip->irq_base = pdata->irq_base; |
233 | } else if (dev->dev.of_node) { | 228 | } else if (adev->dev.of_node) { |
234 | chip->gc.base = -1; | 229 | chip->gc.base = -1; |
235 | chip->irq_base = 0; | 230 | chip->irq_base = 0; |
236 | } else { | 231 | } else |
237 | ret = -ENODEV; | 232 | return -ENODEV; |
238 | goto free_mem; | ||
239 | } | ||
240 | 233 | ||
241 | if (!request_mem_region(dev->res.start, | 234 | if (!devm_request_mem_region(dev, adev->res.start, |
242 | resource_size(&dev->res), "pl061")) { | 235 | resource_size(&adev->res), "pl061")) |
243 | ret = -EBUSY; | 236 | return -EBUSY; |
244 | goto free_mem; | ||
245 | } | ||
246 | 237 | ||
247 | chip->base = ioremap(dev->res.start, resource_size(&dev->res)); | 238 | chip->base = devm_ioremap(dev, adev->res.start, |
248 | if (chip->base == NULL) { | 239 | resource_size(&adev->res)); |
249 | ret = -ENOMEM; | 240 | if (chip->base == NULL) |
250 | goto release_region; | 241 | return -ENOMEM; |
251 | } | ||
252 | 242 | ||
253 | spin_lock_init(&chip->lock); | 243 | spin_lock_init(&chip->lock); |
254 | 244 | ||
@@ -258,13 +248,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
258 | chip->gc.set = pl061_set_value; | 248 | chip->gc.set = pl061_set_value; |
259 | chip->gc.to_irq = pl061_to_irq; | 249 | chip->gc.to_irq = pl061_to_irq; |
260 | chip->gc.ngpio = PL061_GPIO_NR; | 250 | chip->gc.ngpio = PL061_GPIO_NR; |
261 | chip->gc.label = dev_name(&dev->dev); | 251 | chip->gc.label = dev_name(dev); |
262 | chip->gc.dev = &dev->dev; | 252 | chip->gc.dev = dev; |
263 | chip->gc.owner = THIS_MODULE; | 253 | chip->gc.owner = THIS_MODULE; |
264 | 254 | ||
265 | ret = gpiochip_add(&chip->gc); | 255 | ret = gpiochip_add(&chip->gc); |
266 | if (ret) | 256 | if (ret) |
267 | goto iounmap; | 257 | return ret; |
268 | 258 | ||
269 | /* | 259 | /* |
270 | * irq_chip support | 260 | * irq_chip support |
@@ -276,11 +266,10 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
276 | pl061_init_gc(chip, chip->irq_base); | 266 | pl061_init_gc(chip, chip->irq_base); |
277 | 267 | ||
278 | writeb(0, chip->base + GPIOIE); /* disable irqs */ | 268 | writeb(0, chip->base + GPIOIE); /* disable irqs */ |
279 | irq = dev->irq[0]; | 269 | irq = adev->irq[0]; |
280 | if (irq < 0) { | 270 | if (irq < 0) |
281 | ret = -ENODEV; | 271 | return -ENODEV; |
282 | goto iounmap; | 272 | |
283 | } | ||
284 | irq_set_chained_handler(irq, pl061_irq_handler); | 273 | irq_set_chained_handler(irq, pl061_irq_handler); |
285 | irq_set_handler_data(irq, chip); | 274 | irq_set_handler_data(irq, chip); |
286 | 275 | ||
@@ -294,18 +283,9 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
294 | } | 283 | } |
295 | } | 284 | } |
296 | 285 | ||
297 | amba_set_drvdata(dev, chip); | 286 | amba_set_drvdata(adev, chip); |
298 | 287 | ||
299 | return 0; | 288 | 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 | } | 289 | } |
310 | 290 | ||
311 | #ifdef CONFIG_PM | 291 | #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-stmpe.c b/drivers/gpio/gpio-stmpe.c index dce34727bbf8..3e1d39895cef 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c | |||
@@ -11,7 +11,9 @@ | |||
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/gpio.h> | 12 | #include <linux/gpio.h> |
13 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
14 | #include <linux/irqdomain.h> | ||
14 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <linux/of.h> | ||
15 | #include <linux/mfd/stmpe.h> | 17 | #include <linux/mfd/stmpe.h> |
16 | 18 | ||
17 | /* | 19 | /* |
@@ -28,6 +30,7 @@ struct stmpe_gpio { | |||
28 | struct stmpe *stmpe; | 30 | struct stmpe *stmpe; |
29 | struct device *dev; | 31 | struct device *dev; |
30 | struct mutex irq_lock; | 32 | struct mutex irq_lock; |
33 | struct irq_domain *domain; | ||
31 | 34 | ||
32 | int irq_base; | 35 | int irq_base; |
33 | unsigned norequest_mask; | 36 | unsigned norequest_mask; |
@@ -103,7 +106,7 @@ static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |||
103 | { | 106 | { |
104 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | 107 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); |
105 | 108 | ||
106 | return stmpe_gpio->irq_base + offset; | 109 | return irq_create_mapping(stmpe_gpio->domain, offset); |
107 | } | 110 | } |
108 | 111 | ||
109 | static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset) | 112 | static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset) |
@@ -132,7 +135,7 @@ static struct gpio_chip template_chip = { | |||
132 | static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type) | 135 | static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type) |
133 | { | 136 | { |
134 | struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); | 137 | struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); |
135 | int offset = d->irq - stmpe_gpio->irq_base; | 138 | int offset = d->hwirq; |
136 | int regoffset = offset / 8; | 139 | int regoffset = offset / 8; |
137 | int mask = 1 << (offset % 8); | 140 | int mask = 1 << (offset % 8); |
138 | 141 | ||
@@ -199,7 +202,7 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d) | |||
199 | static void stmpe_gpio_irq_mask(struct irq_data *d) | 202 | static void stmpe_gpio_irq_mask(struct irq_data *d) |
200 | { | 203 | { |
201 | struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); | 204 | struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); |
202 | int offset = d->irq - stmpe_gpio->irq_base; | 205 | int offset = d->hwirq; |
203 | int regoffset = offset / 8; | 206 | int regoffset = offset / 8; |
204 | int mask = 1 << (offset % 8); | 207 | int mask = 1 << (offset % 8); |
205 | 208 | ||
@@ -209,7 +212,7 @@ static void stmpe_gpio_irq_mask(struct irq_data *d) | |||
209 | static void stmpe_gpio_irq_unmask(struct irq_data *d) | 212 | static void stmpe_gpio_irq_unmask(struct irq_data *d) |
210 | { | 213 | { |
211 | struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); | 214 | struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); |
212 | int offset = d->irq - stmpe_gpio->irq_base; | 215 | int offset = d->hwirq; |
213 | int regoffset = offset / 8; | 216 | int regoffset = offset / 8; |
214 | int mask = 1 << (offset % 8); | 217 | int mask = 1 << (offset % 8); |
215 | 218 | ||
@@ -251,8 +254,9 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev) | |||
251 | while (stat) { | 254 | while (stat) { |
252 | int bit = __ffs(stat); | 255 | int bit = __ffs(stat); |
253 | int line = bank * 8 + bit; | 256 | int line = bank * 8 + bit; |
257 | int virq = irq_find_mapping(stmpe_gpio->domain, line); | ||
254 | 258 | ||
255 | handle_nested_irq(stmpe_gpio->irq_base + line); | 259 | handle_nested_irq(virq); |
256 | stat &= ~(1 << bit); | 260 | stat &= ~(1 << bit); |
257 | } | 261 | } |
258 | 262 | ||
@@ -267,43 +271,61 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev) | |||
267 | return IRQ_HANDLED; | 271 | return IRQ_HANDLED; |
268 | } | 272 | } |
269 | 273 | ||
270 | static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio) | 274 | int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int virq, |
275 | irq_hw_number_t hwirq) | ||
271 | { | 276 | { |
272 | int base = stmpe_gpio->irq_base; | 277 | struct stmpe_gpio *stmpe_gpio = d->host_data; |
273 | int irq; | ||
274 | 278 | ||
275 | for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) { | 279 | if (!stmpe_gpio) |
276 | irq_set_chip_data(irq, stmpe_gpio); | 280 | return -EINVAL; |
277 | irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip, | 281 | |
278 | handle_simple_irq); | 282 | irq_set_chip_data(hwirq, stmpe_gpio); |
279 | irq_set_nested_thread(irq, 1); | 283 | irq_set_chip_and_handler(hwirq, &stmpe_gpio_irq_chip, |
284 | handle_simple_irq); | ||
285 | irq_set_nested_thread(hwirq, 1); | ||
280 | #ifdef CONFIG_ARM | 286 | #ifdef CONFIG_ARM |
281 | set_irq_flags(irq, IRQF_VALID); | 287 | set_irq_flags(hwirq, IRQF_VALID); |
282 | #else | 288 | #else |
283 | irq_set_noprobe(irq); | 289 | irq_set_noprobe(hwirq); |
284 | #endif | 290 | #endif |
285 | } | ||
286 | 291 | ||
287 | return 0; | 292 | return 0; |
288 | } | 293 | } |
289 | 294 | ||
290 | static void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio) | 295 | void stmpe_gpio_irq_unmap(struct irq_domain *d, unsigned int virq) |
291 | { | 296 | { |
292 | int base = stmpe_gpio->irq_base; | ||
293 | int irq; | ||
294 | |||
295 | for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) { | ||
296 | #ifdef CONFIG_ARM | 297 | #ifdef CONFIG_ARM |
297 | set_irq_flags(irq, 0); | 298 | set_irq_flags(virq, 0); |
298 | #endif | 299 | #endif |
299 | irq_set_chip_and_handler(irq, NULL, NULL); | 300 | irq_set_chip_and_handler(virq, NULL, NULL); |
300 | irq_set_chip_data(irq, NULL); | 301 | irq_set_chip_data(virq, NULL); |
302 | } | ||
303 | |||
304 | static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = { | ||
305 | .unmap = stmpe_gpio_irq_unmap, | ||
306 | .map = stmpe_gpio_irq_map, | ||
307 | .xlate = irq_domain_xlate_twocell, | ||
308 | }; | ||
309 | |||
310 | static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio) | ||
311 | { | ||
312 | int base = stmpe_gpio->irq_base; | ||
313 | |||
314 | stmpe_gpio->domain = irq_domain_add_simple(NULL, | ||
315 | stmpe_gpio->chip.ngpio, base, | ||
316 | &stmpe_gpio_irq_simple_ops, stmpe_gpio); | ||
317 | if (!stmpe_gpio->domain) { | ||
318 | dev_err(stmpe_gpio->dev, "failed to create irqdomain\n"); | ||
319 | return -ENOSYS; | ||
301 | } | 320 | } |
321 | |||
322 | return 0; | ||
302 | } | 323 | } |
303 | 324 | ||
304 | static int __devinit stmpe_gpio_probe(struct platform_device *pdev) | 325 | static int __devinit stmpe_gpio_probe(struct platform_device *pdev) |
305 | { | 326 | { |
306 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | 327 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); |
328 | struct device_node *np = pdev->dev.of_node; | ||
307 | struct stmpe_gpio_platform_data *pdata; | 329 | struct stmpe_gpio_platform_data *pdata; |
308 | struct stmpe_gpio *stmpe_gpio; | 330 | struct stmpe_gpio *stmpe_gpio; |
309 | int ret; | 331 | int ret; |
@@ -321,13 +343,17 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev) | |||
321 | 343 | ||
322 | stmpe_gpio->dev = &pdev->dev; | 344 | stmpe_gpio->dev = &pdev->dev; |
323 | stmpe_gpio->stmpe = stmpe; | 345 | stmpe_gpio->stmpe = stmpe; |
324 | stmpe_gpio->norequest_mask = pdata ? pdata->norequest_mask : 0; | ||
325 | |||
326 | stmpe_gpio->chip = template_chip; | 346 | stmpe_gpio->chip = template_chip; |
327 | stmpe_gpio->chip.ngpio = stmpe->num_gpios; | 347 | stmpe_gpio->chip.ngpio = stmpe->num_gpios; |
328 | stmpe_gpio->chip.dev = &pdev->dev; | 348 | stmpe_gpio->chip.dev = &pdev->dev; |
329 | stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1; | 349 | stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1; |
330 | 350 | ||
351 | if (pdata) | ||
352 | stmpe_gpio->norequest_mask = pdata->norequest_mask; | ||
353 | else if (np) | ||
354 | of_property_read_u32(np, "st,norequest-mask", | ||
355 | &stmpe_gpio->norequest_mask); | ||
356 | |||
331 | if (irq >= 0) | 357 | if (irq >= 0) |
332 | stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0); | 358 | stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0); |
333 | else | 359 | else |
@@ -348,7 +374,7 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev) | |||
348 | IRQF_ONESHOT, "stmpe-gpio", stmpe_gpio); | 374 | IRQF_ONESHOT, "stmpe-gpio", stmpe_gpio); |
349 | if (ret) { | 375 | if (ret) { |
350 | dev_err(&pdev->dev, "unable to get irq: %d\n", ret); | 376 | dev_err(&pdev->dev, "unable to get irq: %d\n", ret); |
351 | goto out_removeirq; | 377 | goto out_disable; |
352 | } | 378 | } |
353 | } | 379 | } |
354 | 380 | ||
@@ -368,9 +394,6 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev) | |||
368 | out_freeirq: | 394 | out_freeirq: |
369 | if (irq >= 0) | 395 | if (irq >= 0) |
370 | free_irq(irq, stmpe_gpio); | 396 | free_irq(irq, stmpe_gpio); |
371 | out_removeirq: | ||
372 | if (irq >= 0) | ||
373 | stmpe_gpio_irq_remove(stmpe_gpio); | ||
374 | out_disable: | 397 | out_disable: |
375 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); | 398 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); |
376 | out_free: | 399 | out_free: |
@@ -398,10 +421,9 @@ static int __devexit stmpe_gpio_remove(struct platform_device *pdev) | |||
398 | 421 | ||
399 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); | 422 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); |
400 | 423 | ||
401 | if (irq >= 0) { | 424 | if (irq >= 0) |
402 | free_irq(irq, stmpe_gpio); | 425 | free_irq(irq, stmpe_gpio); |
403 | stmpe_gpio_irq_remove(stmpe_gpio); | 426 | |
404 | } | ||
405 | platform_set_drvdata(pdev, NULL); | 427 | platform_set_drvdata(pdev, NULL); |
406 | kfree(stmpe_gpio); | 428 | kfree(stmpe_gpio); |
407 | 429 | ||
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-ts5500.c b/drivers/gpio/gpio-ts5500.c new file mode 100644 index 000000000000..0634ceea3c24 --- /dev/null +++ b/drivers/gpio/gpio-ts5500.c | |||
@@ -0,0 +1,466 @@ | |||
1 | /* | ||
2 | * Digital I/O driver for Technologic Systems TS-5500 | ||
3 | * | ||
4 | * Copyright (c) 2012 Savoir-faire Linux Inc. | ||
5 | * Vivien Didelot <vivien.didelot@savoirfairelinux.com> | ||
6 | * | ||
7 | * Technologic Systems platforms have pin blocks, exposing several Digital | ||
8 | * Input/Output lines (DIO). This driver aims to support single pin blocks. | ||
9 | * In that sense, the support is not limited to the TS-5500 blocks. | ||
10 | * Actually, the following platforms have DIO support: | ||
11 | * | ||
12 | * TS-5500: | ||
13 | * Documentation: http://wiki.embeddedarm.com/wiki/TS-5500 | ||
14 | * Blocks: DIO1, DIO2 and LCD port. | ||
15 | * | ||
16 | * TS-5600: | ||
17 | * Documentation: http://wiki.embeddedarm.com/wiki/TS-5600 | ||
18 | * Blocks: LCD port (identical to TS-5500 LCD). | ||
19 | * | ||
20 | * This program is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License version 2 as | ||
22 | * published by the Free Software Foundation. | ||
23 | */ | ||
24 | |||
25 | #include <linux/bitops.h> | ||
26 | #include <linux/gpio.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/platform_data/gpio-ts5500.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/slab.h> | ||
32 | |||
33 | /* List of supported Technologic Systems platforms DIO blocks */ | ||
34 | enum ts5500_blocks { TS5500_DIO1, TS5500_DIO2, TS5500_LCD, TS5600_LCD }; | ||
35 | |||
36 | struct ts5500_priv { | ||
37 | const struct ts5500_dio *pinout; | ||
38 | struct gpio_chip gpio_chip; | ||
39 | spinlock_t lock; | ||
40 | bool strap; | ||
41 | u8 hwirq; | ||
42 | }; | ||
43 | |||
44 | /* | ||
45 | * Hex 7D is used to control several blocks (e.g. DIO2 and LCD port). | ||
46 | * This flag ensures that the region has been requested by this driver. | ||
47 | */ | ||
48 | static bool hex7d_reserved; | ||
49 | |||
50 | /* | ||
51 | * This structure is used to describe capabilities of DIO lines, | ||
52 | * such as available directions and connected interrupt (if any). | ||
53 | */ | ||
54 | struct ts5500_dio { | ||
55 | const u8 value_addr; | ||
56 | const u8 value_mask; | ||
57 | const u8 control_addr; | ||
58 | const u8 control_mask; | ||
59 | const bool no_input; | ||
60 | const bool no_output; | ||
61 | const u8 irq; | ||
62 | }; | ||
63 | |||
64 | #define TS5500_DIO_IN_OUT(vaddr, vbit, caddr, cbit) \ | ||
65 | { \ | ||
66 | .value_addr = vaddr, \ | ||
67 | .value_mask = BIT(vbit), \ | ||
68 | .control_addr = caddr, \ | ||
69 | .control_mask = BIT(cbit), \ | ||
70 | } | ||
71 | |||
72 | #define TS5500_DIO_IN(addr, bit) \ | ||
73 | { \ | ||
74 | .value_addr = addr, \ | ||
75 | .value_mask = BIT(bit), \ | ||
76 | .no_output = true, \ | ||
77 | } | ||
78 | |||
79 | #define TS5500_DIO_IN_IRQ(addr, bit, _irq) \ | ||
80 | { \ | ||
81 | .value_addr = addr, \ | ||
82 | .value_mask = BIT(bit), \ | ||
83 | .no_output = true, \ | ||
84 | .irq = _irq, \ | ||
85 | } | ||
86 | |||
87 | #define TS5500_DIO_OUT(addr, bit) \ | ||
88 | { \ | ||
89 | .value_addr = addr, \ | ||
90 | .value_mask = BIT(bit), \ | ||
91 | .no_input = true, \ | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * Input/Output DIO lines are programmed in groups of 4. Their values are | ||
96 | * available through 4 consecutive bits in a value port, whereas the direction | ||
97 | * of these 4 lines is driven by only 1 bit in a control port. | ||
98 | */ | ||
99 | #define TS5500_DIO_GROUP(vaddr, vbitfrom, caddr, cbit) \ | ||
100 | TS5500_DIO_IN_OUT(vaddr, vbitfrom + 0, caddr, cbit), \ | ||
101 | TS5500_DIO_IN_OUT(vaddr, vbitfrom + 1, caddr, cbit), \ | ||
102 | TS5500_DIO_IN_OUT(vaddr, vbitfrom + 2, caddr, cbit), \ | ||
103 | TS5500_DIO_IN_OUT(vaddr, vbitfrom + 3, caddr, cbit) | ||
104 | |||
105 | /* | ||
106 | * TS-5500 DIO1 block | ||
107 | * | ||
108 | * value control dir hw | ||
109 | * addr bit addr bit in out irq name pin offset | ||
110 | * | ||
111 | * 0x7b 0 0x7a 0 x x DIO1_0 1 0 | ||
112 | * 0x7b 1 0x7a 0 x x DIO1_1 3 1 | ||
113 | * 0x7b 2 0x7a 0 x x DIO1_2 5 2 | ||
114 | * 0x7b 3 0x7a 0 x x DIO1_3 7 3 | ||
115 | * 0x7b 4 0x7a 1 x x DIO1_4 9 4 | ||
116 | * 0x7b 5 0x7a 1 x x DIO1_5 11 5 | ||
117 | * 0x7b 6 0x7a 1 x x DIO1_6 13 6 | ||
118 | * 0x7b 7 0x7a 1 x x DIO1_7 15 7 | ||
119 | * 0x7c 0 0x7a 5 x x DIO1_8 4 8 | ||
120 | * 0x7c 1 0x7a 5 x x DIO1_9 6 9 | ||
121 | * 0x7c 2 0x7a 5 x x DIO1_10 8 10 | ||
122 | * 0x7c 3 0x7a 5 x x DIO1_11 10 11 | ||
123 | * 0x7c 4 x DIO1_12 12 12 | ||
124 | * 0x7c 5 x 7 DIO1_13 14 13 | ||
125 | */ | ||
126 | static const struct ts5500_dio ts5500_dio1[] = { | ||
127 | TS5500_DIO_GROUP(0x7b, 0, 0x7a, 0), | ||
128 | TS5500_DIO_GROUP(0x7b, 4, 0x7a, 1), | ||
129 | TS5500_DIO_GROUP(0x7c, 0, 0x7a, 5), | ||
130 | TS5500_DIO_IN(0x7c, 4), | ||
131 | TS5500_DIO_IN_IRQ(0x7c, 5, 7), | ||
132 | }; | ||
133 | |||
134 | /* | ||
135 | * TS-5500 DIO2 block | ||
136 | * | ||
137 | * value control dir hw | ||
138 | * addr bit addr bit in out irq name pin offset | ||
139 | * | ||
140 | * 0x7e 0 0x7d 0 x x DIO2_0 1 0 | ||
141 | * 0x7e 1 0x7d 0 x x DIO2_1 3 1 | ||
142 | * 0x7e 2 0x7d 0 x x DIO2_2 5 2 | ||
143 | * 0x7e 3 0x7d 0 x x DIO2_3 7 3 | ||
144 | * 0x7e 4 0x7d 1 x x DIO2_4 9 4 | ||
145 | * 0x7e 5 0x7d 1 x x DIO2_5 11 5 | ||
146 | * 0x7e 6 0x7d 1 x x DIO2_6 13 6 | ||
147 | * 0x7e 7 0x7d 1 x x DIO2_7 15 7 | ||
148 | * 0x7f 0 0x7d 5 x x DIO2_8 4 8 | ||
149 | * 0x7f 1 0x7d 5 x x DIO2_9 6 9 | ||
150 | * 0x7f 2 0x7d 5 x x DIO2_10 8 10 | ||
151 | * 0x7f 3 0x7d 5 x x DIO2_11 10 11 | ||
152 | * 0x7f 4 x 6 DIO2_13 14 12 | ||
153 | */ | ||
154 | static const struct ts5500_dio ts5500_dio2[] = { | ||
155 | TS5500_DIO_GROUP(0x7e, 0, 0x7d, 0), | ||
156 | TS5500_DIO_GROUP(0x7e, 4, 0x7d, 1), | ||
157 | TS5500_DIO_GROUP(0x7f, 0, 0x7d, 5), | ||
158 | TS5500_DIO_IN_IRQ(0x7f, 4, 6), | ||
159 | }; | ||
160 | |||
161 | /* | ||
162 | * TS-5500 LCD port used as DIO block | ||
163 | * TS-5600 LCD port is identical | ||
164 | * | ||
165 | * value control dir hw | ||
166 | * addr bit addr bit in out irq name pin offset | ||
167 | * | ||
168 | * 0x72 0 0x7d 2 x x LCD_0 8 0 | ||
169 | * 0x72 1 0x7d 2 x x LCD_1 7 1 | ||
170 | * 0x72 2 0x7d 2 x x LCD_2 10 2 | ||
171 | * 0x72 3 0x7d 2 x x LCD_3 9 3 | ||
172 | * 0x72 4 0x7d 3 x x LCD_4 12 4 | ||
173 | * 0x72 5 0x7d 3 x x LCD_5 11 5 | ||
174 | * 0x72 6 0x7d 3 x x LCD_6 14 6 | ||
175 | * 0x72 7 0x7d 3 x x LCD_7 13 7 | ||
176 | * 0x73 0 x LCD_EN 5 8 | ||
177 | * 0x73 6 x LCD_WR 6 9 | ||
178 | * 0x73 7 x 1 LCD_RS 3 10 | ||
179 | */ | ||
180 | static const struct ts5500_dio ts5500_lcd[] = { | ||
181 | TS5500_DIO_GROUP(0x72, 0, 0x7d, 2), | ||
182 | TS5500_DIO_GROUP(0x72, 4, 0x7d, 3), | ||
183 | TS5500_DIO_OUT(0x73, 0), | ||
184 | TS5500_DIO_IN(0x73, 6), | ||
185 | TS5500_DIO_IN_IRQ(0x73, 7, 1), | ||
186 | }; | ||
187 | |||
188 | static inline struct ts5500_priv *ts5500_gc_to_priv(struct gpio_chip *chip) | ||
189 | { | ||
190 | return container_of(chip, struct ts5500_priv, gpio_chip); | ||
191 | } | ||
192 | |||
193 | static inline void ts5500_set_mask(u8 mask, u8 addr) | ||
194 | { | ||
195 | u8 val = inb(addr); | ||
196 | val |= mask; | ||
197 | outb(val, addr); | ||
198 | } | ||
199 | |||
200 | static inline void ts5500_clear_mask(u8 mask, u8 addr) | ||
201 | { | ||
202 | u8 val = inb(addr); | ||
203 | val &= ~mask; | ||
204 | outb(val, addr); | ||
205 | } | ||
206 | |||
207 | static int ts5500_gpio_input(struct gpio_chip *chip, unsigned offset) | ||
208 | { | ||
209 | struct ts5500_priv *priv = ts5500_gc_to_priv(chip); | ||
210 | const struct ts5500_dio line = priv->pinout[offset]; | ||
211 | unsigned long flags; | ||
212 | |||
213 | if (line.no_input) | ||
214 | return -ENXIO; | ||
215 | |||
216 | if (line.no_output) | ||
217 | return 0; | ||
218 | |||
219 | spin_lock_irqsave(&priv->lock, flags); | ||
220 | ts5500_clear_mask(line.control_mask, line.control_addr); | ||
221 | spin_unlock_irqrestore(&priv->lock, flags); | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int ts5500_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
227 | { | ||
228 | struct ts5500_priv *priv = ts5500_gc_to_priv(chip); | ||
229 | const struct ts5500_dio line = priv->pinout[offset]; | ||
230 | |||
231 | return !!(inb(line.value_addr) & line.value_mask); | ||
232 | } | ||
233 | |||
234 | static int ts5500_gpio_output(struct gpio_chip *chip, unsigned offset, int val) | ||
235 | { | ||
236 | struct ts5500_priv *priv = ts5500_gc_to_priv(chip); | ||
237 | const struct ts5500_dio line = priv->pinout[offset]; | ||
238 | unsigned long flags; | ||
239 | |||
240 | if (line.no_output) | ||
241 | return -ENXIO; | ||
242 | |||
243 | spin_lock_irqsave(&priv->lock, flags); | ||
244 | if (!line.no_input) | ||
245 | ts5500_set_mask(line.control_mask, line.control_addr); | ||
246 | |||
247 | if (val) | ||
248 | ts5500_set_mask(line.value_mask, line.value_addr); | ||
249 | else | ||
250 | ts5500_clear_mask(line.value_mask, line.value_addr); | ||
251 | spin_unlock_irqrestore(&priv->lock, flags); | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static void ts5500_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | ||
257 | { | ||
258 | struct ts5500_priv *priv = ts5500_gc_to_priv(chip); | ||
259 | const struct ts5500_dio line = priv->pinout[offset]; | ||
260 | unsigned long flags; | ||
261 | |||
262 | spin_lock_irqsave(&priv->lock, flags); | ||
263 | if (val) | ||
264 | ts5500_set_mask(line.value_mask, line.value_addr); | ||
265 | else | ||
266 | ts5500_clear_mask(line.value_mask, line.value_addr); | ||
267 | spin_unlock_irqrestore(&priv->lock, flags); | ||
268 | } | ||
269 | |||
270 | static int ts5500_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
271 | { | ||
272 | struct ts5500_priv *priv = ts5500_gc_to_priv(chip); | ||
273 | const struct ts5500_dio *block = priv->pinout; | ||
274 | const struct ts5500_dio line = block[offset]; | ||
275 | |||
276 | /* Only one pin is connected to an interrupt */ | ||
277 | if (line.irq) | ||
278 | return line.irq; | ||
279 | |||
280 | /* As this pin is input-only, we may strap it to another in/out pin */ | ||
281 | if (priv->strap) | ||
282 | return priv->hwirq; | ||
283 | |||
284 | return -ENXIO; | ||
285 | } | ||
286 | |||
287 | static int ts5500_enable_irq(struct ts5500_priv *priv) | ||
288 | { | ||
289 | int ret = 0; | ||
290 | unsigned long flags; | ||
291 | |||
292 | spin_lock_irqsave(&priv->lock, flags); | ||
293 | if (priv->hwirq == 7) | ||
294 | ts5500_set_mask(BIT(7), 0x7a); /* DIO1_13 on IRQ7 */ | ||
295 | else if (priv->hwirq == 6) | ||
296 | ts5500_set_mask(BIT(7), 0x7d); /* DIO2_13 on IRQ6 */ | ||
297 | else if (priv->hwirq == 1) | ||
298 | ts5500_set_mask(BIT(6), 0x7d); /* LCD_RS on IRQ1 */ | ||
299 | else | ||
300 | ret = -EINVAL; | ||
301 | spin_unlock_irqrestore(&priv->lock, flags); | ||
302 | |||
303 | return ret; | ||
304 | } | ||
305 | |||
306 | static void ts5500_disable_irq(struct ts5500_priv *priv) | ||
307 | { | ||
308 | unsigned long flags; | ||
309 | |||
310 | spin_lock_irqsave(&priv->lock, flags); | ||
311 | if (priv->hwirq == 7) | ||
312 | ts5500_clear_mask(BIT(7), 0x7a); /* DIO1_13 on IRQ7 */ | ||
313 | else if (priv->hwirq == 6) | ||
314 | ts5500_clear_mask(BIT(7), 0x7d); /* DIO2_13 on IRQ6 */ | ||
315 | else if (priv->hwirq == 1) | ||
316 | ts5500_clear_mask(BIT(6), 0x7d); /* LCD_RS on IRQ1 */ | ||
317 | else | ||
318 | dev_err(priv->gpio_chip.dev, "invalid hwirq %d\n", priv->hwirq); | ||
319 | spin_unlock_irqrestore(&priv->lock, flags); | ||
320 | } | ||
321 | |||
322 | static int __devinit ts5500_dio_probe(struct platform_device *pdev) | ||
323 | { | ||
324 | enum ts5500_blocks block = platform_get_device_id(pdev)->driver_data; | ||
325 | struct ts5500_dio_platform_data *pdata = pdev->dev.platform_data; | ||
326 | struct device *dev = &pdev->dev; | ||
327 | const char *name = dev_name(dev); | ||
328 | struct ts5500_priv *priv; | ||
329 | struct resource *res; | ||
330 | unsigned long flags; | ||
331 | int ret; | ||
332 | |||
333 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
334 | if (!res) { | ||
335 | dev_err(dev, "missing IRQ resource\n"); | ||
336 | return -EINVAL; | ||
337 | } | ||
338 | |||
339 | priv = devm_kzalloc(dev, sizeof(struct ts5500_priv), GFP_KERNEL); | ||
340 | if (!priv) | ||
341 | return -ENOMEM; | ||
342 | |||
343 | platform_set_drvdata(pdev, priv); | ||
344 | priv->hwirq = res->start; | ||
345 | spin_lock_init(&priv->lock); | ||
346 | |||
347 | priv->gpio_chip.owner = THIS_MODULE; | ||
348 | priv->gpio_chip.label = name; | ||
349 | priv->gpio_chip.dev = dev; | ||
350 | priv->gpio_chip.direction_input = ts5500_gpio_input; | ||
351 | priv->gpio_chip.direction_output = ts5500_gpio_output; | ||
352 | priv->gpio_chip.get = ts5500_gpio_get; | ||
353 | priv->gpio_chip.set = ts5500_gpio_set; | ||
354 | priv->gpio_chip.to_irq = ts5500_gpio_to_irq; | ||
355 | priv->gpio_chip.base = -1; | ||
356 | if (pdata) { | ||
357 | priv->gpio_chip.base = pdata->base; | ||
358 | priv->strap = pdata->strap; | ||
359 | } | ||
360 | |||
361 | switch (block) { | ||
362 | case TS5500_DIO1: | ||
363 | priv->pinout = ts5500_dio1; | ||
364 | priv->gpio_chip.ngpio = ARRAY_SIZE(ts5500_dio1); | ||
365 | |||
366 | if (!devm_request_region(dev, 0x7a, 3, name)) { | ||
367 | dev_err(dev, "failed to request %s ports\n", name); | ||
368 | return -EBUSY; | ||
369 | } | ||
370 | break; | ||
371 | case TS5500_DIO2: | ||
372 | priv->pinout = ts5500_dio2; | ||
373 | priv->gpio_chip.ngpio = ARRAY_SIZE(ts5500_dio2); | ||
374 | |||
375 | if (!devm_request_region(dev, 0x7e, 2, name)) { | ||
376 | dev_err(dev, "failed to request %s ports\n", name); | ||
377 | return -EBUSY; | ||
378 | } | ||
379 | |||
380 | if (hex7d_reserved) | ||
381 | break; | ||
382 | |||
383 | if (!devm_request_region(dev, 0x7d, 1, name)) { | ||
384 | dev_err(dev, "failed to request %s 7D\n", name); | ||
385 | return -EBUSY; | ||
386 | } | ||
387 | |||
388 | hex7d_reserved = true; | ||
389 | break; | ||
390 | case TS5500_LCD: | ||
391 | case TS5600_LCD: | ||
392 | priv->pinout = ts5500_lcd; | ||
393 | priv->gpio_chip.ngpio = ARRAY_SIZE(ts5500_lcd); | ||
394 | |||
395 | if (!devm_request_region(dev, 0x72, 2, name)) { | ||
396 | dev_err(dev, "failed to request %s ports\n", name); | ||
397 | return -EBUSY; | ||
398 | } | ||
399 | |||
400 | if (!hex7d_reserved) { | ||
401 | if (!devm_request_region(dev, 0x7d, 1, name)) { | ||
402 | dev_err(dev, "failed to request %s 7D\n", name); | ||
403 | return -EBUSY; | ||
404 | } | ||
405 | |||
406 | hex7d_reserved = true; | ||
407 | } | ||
408 | |||
409 | /* Ensure usage of LCD port as DIO */ | ||
410 | spin_lock_irqsave(&priv->lock, flags); | ||
411 | ts5500_clear_mask(BIT(4), 0x7d); | ||
412 | spin_unlock_irqrestore(&priv->lock, flags); | ||
413 | break; | ||
414 | } | ||
415 | |||
416 | ret = gpiochip_add(&priv->gpio_chip); | ||
417 | if (ret) { | ||
418 | dev_err(dev, "failed to register the gpio chip\n"); | ||
419 | return ret; | ||
420 | } | ||
421 | |||
422 | ret = ts5500_enable_irq(priv); | ||
423 | if (ret) { | ||
424 | dev_err(dev, "invalid interrupt %d\n", priv->hwirq); | ||
425 | goto cleanup; | ||
426 | } | ||
427 | |||
428 | return 0; | ||
429 | cleanup: | ||
430 | if (gpiochip_remove(&priv->gpio_chip)) | ||
431 | dev_err(dev, "failed to remove gpio chip\n"); | ||
432 | return ret; | ||
433 | } | ||
434 | |||
435 | static int __devexit ts5500_dio_remove(struct platform_device *pdev) | ||
436 | { | ||
437 | struct ts5500_priv *priv = platform_get_drvdata(pdev); | ||
438 | |||
439 | ts5500_disable_irq(priv); | ||
440 | return gpiochip_remove(&priv->gpio_chip); | ||
441 | } | ||
442 | |||
443 | static struct platform_device_id ts5500_dio_ids[] = { | ||
444 | { "ts5500-dio1", TS5500_DIO1 }, | ||
445 | { "ts5500-dio2", TS5500_DIO2 }, | ||
446 | { "ts5500-dio-lcd", TS5500_LCD }, | ||
447 | { "ts5600-dio-lcd", TS5600_LCD }, | ||
448 | { } | ||
449 | }; | ||
450 | MODULE_DEVICE_TABLE(platform, ts5500_dio_ids); | ||
451 | |||
452 | static struct platform_driver ts5500_dio_driver = { | ||
453 | .driver = { | ||
454 | .name = "ts5500-dio", | ||
455 | .owner = THIS_MODULE, | ||
456 | }, | ||
457 | .probe = ts5500_dio_probe, | ||
458 | .remove = __devexit_p(ts5500_dio_remove), | ||
459 | .id_table = ts5500_dio_ids, | ||
460 | }; | ||
461 | |||
462 | module_platform_driver(ts5500_dio_driver); | ||
463 | |||
464 | MODULE_LICENSE("GPL"); | ||
465 | MODULE_AUTHOR("Savoir-faire Linux Inc. <kernel@savoirfairelinux.com>"); | ||
466 | MODULE_DESCRIPTION("Technologic Systems TS-5500 Digital I/O driver"); | ||
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 58b9838801c0..199fca15f270 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 |
@@ -1304,9 +1341,15 @@ int gpio_request(unsigned gpio, const char *label) | |||
1304 | desc_set_label(desc, NULL); | 1341 | desc_set_label(desc, NULL); |
1305 | module_put(chip->owner); | 1342 | module_put(chip->owner); |
1306 | clear_bit(FLAG_REQUESTED, &desc->flags); | 1343 | clear_bit(FLAG_REQUESTED, &desc->flags); |
1344 | goto done; | ||
1307 | } | 1345 | } |
1308 | } | 1346 | } |
1309 | 1347 | if (chip->get_direction) { | |
1348 | /* chip->get_direction may sleep */ | ||
1349 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
1350 | gpio_get_direction(gpio); | ||
1351 | spin_lock_irqsave(&gpio_lock, flags); | ||
1352 | } | ||
1310 | done: | 1353 | done: |
1311 | if (status) | 1354 | if (status) |
1312 | pr_debug("gpio_request: gpio-%d (%s) status %d\n", | 1355 | pr_debug("gpio_request: gpio-%d (%s) status %d\n", |
@@ -1842,6 +1885,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
1842 | if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) | 1885 | if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) |
1843 | continue; | 1886 | continue; |
1844 | 1887 | ||
1888 | gpio_get_direction(gpio); | ||
1845 | is_out = test_bit(FLAG_IS_OUT, &gdesc->flags); | 1889 | is_out = test_bit(FLAG_IS_OUT, &gdesc->flags); |
1846 | seq_printf(s, " gpio-%-3d (%-20.20s) %s %s", | 1890 | seq_printf(s, " gpio-%-3d (%-20.20s) %s %s", |
1847 | gpio, gdesc->label, | 1891 | gpio, gdesc->label, |
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index c94f521f392c..79e88d1fd99a 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c | |||
@@ -294,12 +294,14 @@ static struct resource stmpe_gpio_resources[] = { | |||
294 | 294 | ||
295 | static struct mfd_cell stmpe_gpio_cell = { | 295 | static struct mfd_cell stmpe_gpio_cell = { |
296 | .name = "stmpe-gpio", | 296 | .name = "stmpe-gpio", |
297 | .of_compatible = "st,stmpe-gpio", | ||
297 | .resources = stmpe_gpio_resources, | 298 | .resources = stmpe_gpio_resources, |
298 | .num_resources = ARRAY_SIZE(stmpe_gpio_resources), | 299 | .num_resources = ARRAY_SIZE(stmpe_gpio_resources), |
299 | }; | 300 | }; |
300 | 301 | ||
301 | static struct mfd_cell stmpe_gpio_cell_noirq = { | 302 | static struct mfd_cell stmpe_gpio_cell_noirq = { |
302 | .name = "stmpe-gpio", | 303 | .name = "stmpe-gpio", |
304 | .of_compatible = "st,stmpe-gpio", | ||
303 | /* gpio cell resources consist of an irq only so no resources here */ | 305 | /* gpio cell resources consist of an irq only so no resources here */ |
304 | }; | 306 | }; |
305 | 307 | ||
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 9fd3093d855a..20ca7663975f 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, |
diff --git a/include/linux/i2c/pcf857x.h b/include/linux/i2c/pcf857x.h index 781e6bd06c34..0767a2a6b2f1 100644 --- a/include/linux/i2c/pcf857x.h +++ b/include/linux/i2c/pcf857x.h | |||
@@ -10,7 +10,6 @@ | |||
10 | * @setup: optional callback issued once the GPIOs are valid | 10 | * @setup: optional callback issued once the GPIOs are valid |
11 | * @teardown: optional callback issued before the GPIOs are invalidated | 11 | * @teardown: optional callback issued before the GPIOs are invalidated |
12 | * @context: optional parameter passed to setup() and teardown() | 12 | * @context: optional parameter passed to setup() and teardown() |
13 | * @irq: optional interrupt number | ||
14 | * | 13 | * |
15 | * In addition to the I2C_BOARD_INFO() state appropriate to each chip, | 14 | * In addition to the I2C_BOARD_INFO() state appropriate to each chip, |
16 | * the i2c_board_info used with the pcf875x driver must provide its | 15 | * the i2c_board_info used with the pcf875x driver must provide its |
@@ -40,8 +39,6 @@ struct pcf857x_platform_data { | |||
40 | int gpio, unsigned ngpio, | 39 | int gpio, unsigned ngpio, |
41 | void *context); | 40 | void *context); |
42 | void *context; | 41 | void *context; |
43 | |||
44 | int irq; | ||
45 | }; | 42 | }; |
46 | 43 | ||
47 | #endif /* __LINUX_PCF857X_H */ | 44 | #endif /* __LINUX_PCF857X_H */ |
diff --git a/include/linux/platform_data/gpio-ts5500.h b/include/linux/platform_data/gpio-ts5500.h new file mode 100644 index 000000000000..b10d11c9bb49 --- /dev/null +++ b/include/linux/platform_data/gpio-ts5500.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * GPIO (DIO) header for Technologic Systems TS-5500 | ||
3 | * | ||
4 | * Copyright (c) 2012 Savoir-faire Linux Inc. | ||
5 | * Vivien Didelot <vivien.didelot@savoirfairelinux.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 | |||
12 | #ifndef _PDATA_GPIO_TS5500_H | ||
13 | #define _PDATA_GPIO_TS5500_H | ||
14 | |||
15 | /** | ||
16 | * struct ts5500_dio_platform_data - TS-5500 pin block configuration | ||
17 | * @base: The GPIO base number to use. | ||
18 | * @strap: The only pin connected to an interrupt in a block is input-only. | ||
19 | * If you need a bidirectional line which can trigger an IRQ, you | ||
20 | * may strap it with an in/out pin. This flag indicates this case. | ||
21 | */ | ||
22 | struct ts5500_dio_platform_data { | ||
23 | int base; | ||
24 | bool strap; | ||
25 | }; | ||
26 | |||
27 | #endif /* _PDATA_GPIO_TS5500_H */ | ||