diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Kconfig | 38 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 5 | ||||
-rw-r--r-- | drivers/gpio/gpio-clps711x.c | 199 | ||||
-rw-r--r-- | drivers/gpio/gpio-da9055.c | 204 | ||||
-rw-r--r-- | drivers/gpio/gpio-em.c | 48 | ||||
-rw-r--r-- | drivers/gpio/gpio-max730x.c | 12 | ||||
-rw-r--r-- | drivers/gpio/gpio-mcp23s08.c | 6 | ||||
-rw-r--r-- | drivers/gpio/gpio-mvebu.c | 32 | ||||
-rw-r--r-- | drivers/gpio/gpio-omap.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-pca953x.c | 55 | ||||
-rw-r--r-- | drivers/gpio/gpio-pcf857x.c | 29 | ||||
-rw-r--r-- | drivers/gpio/gpio-pch.c | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-pl061.c | 66 | ||||
-rw-r--r-- | drivers/gpio/gpio-spear-spics.c | 217 | ||||
-rw-r--r-- | drivers/gpio/gpio-stmpe.c | 88 | ||||
-rw-r--r-- | drivers/gpio/gpio-tc3589x.c | 20 | ||||
-rw-r--r-- | drivers/gpio/gpio-tegra.c | 43 | ||||
-rw-r--r-- | drivers/gpio/gpio-ts5500.c | 466 | ||||
-rw-r--r-- | drivers/gpio/gpio-twl4030.c | 35 | ||||
-rw-r--r-- | drivers/gpio/gpio-vt8500.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 54 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-of.c | 52 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 200 |
23 files changed, 1632 insertions, 242 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f11d8e3b4041..14a6c2913e49 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -49,6 +49,10 @@ config OF_GPIO | |||
49 | def_bool y | 49 | def_bool y |
50 | depends on OF | 50 | depends on OF |
51 | 51 | ||
52 | config GPIO_ACPI | ||
53 | def_bool y | ||
54 | depends on ACPI | ||
55 | |||
52 | config DEBUG_GPIO | 56 | config DEBUG_GPIO |
53 | bool "Debug GPIO calls" | 57 | bool "Debug GPIO calls" |
54 | depends on DEBUG_KERNEL | 58 | depends on DEBUG_KERNEL |
@@ -86,11 +90,26 @@ config GPIO_DA9052 | |||
86 | help | 90 | help |
87 | 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. |
88 | 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 | |||
89 | config GPIO_MAX730X | 104 | config GPIO_MAX730X |
90 | tristate | 105 | tristate |
91 | 106 | ||
92 | comment "Memory mapped GPIO drivers:" | 107 | comment "Memory mapped GPIO drivers:" |
93 | 108 | ||
109 | config GPIO_CLPS711X | ||
110 | def_bool y | ||
111 | depends on ARCH_CLPS711X | ||
112 | |||
94 | config GPIO_GENERIC_PLATFORM | 113 | config GPIO_GENERIC_PLATFORM |
95 | tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" | 114 | tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" |
96 | select GPIO_GENERIC | 115 | select GPIO_GENERIC |
@@ -170,7 +189,7 @@ config GPIO_MXS | |||
170 | 189 | ||
171 | config GPIO_PL061 | 190 | config GPIO_PL061 |
172 | bool "PrimeCell PL061 GPIO support" | 191 | bool "PrimeCell PL061 GPIO support" |
173 | depends on ARM_AMBA | 192 | depends on ARM && ARM_AMBA |
174 | select GENERIC_IRQ_CHIP | 193 | select GENERIC_IRQ_CHIP |
175 | help | 194 | help |
176 | Say yes here to support the PrimeCell PL061 GPIO device | 195 | Say yes here to support the PrimeCell PL061 GPIO device |
@@ -181,6 +200,13 @@ config GPIO_PXA | |||
181 | help | 200 | help |
182 | Say yes here to support the PXA GPIO device | 201 | Say yes here to support the PXA GPIO device |
183 | 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 | |||
184 | config GPIO_STA2X11 | 210 | config GPIO_STA2X11 |
185 | bool "STA2x11/ConneXt GPIO support" | 211 | bool "STA2x11/ConneXt GPIO support" |
186 | depends on MFD_STA2X11 | 212 | depends on MFD_STA2X11 |
@@ -189,6 +215,14 @@ config GPIO_STA2X11 | |||
189 | Say yes here to support the STA2x11/ConneXt GPIO device. | 215 | Say yes here to support the STA2x11/ConneXt GPIO device. |
190 | The GPIO module has 128 GPIO pins with alternate functions. | 216 | The GPIO module has 128 GPIO pins with alternate functions. |
191 | 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 | |||
192 | config GPIO_VT8500 | 226 | config GPIO_VT8500 |
193 | bool "VIA/Wondermedia SoC GPIO Support" | 227 | bool "VIA/Wondermedia SoC GPIO Support" |
194 | depends on ARCH_VT8500 | 228 | depends on ARCH_VT8500 |
@@ -466,7 +500,7 @@ config GPIO_ADP5588_IRQ | |||
466 | 500 | ||
467 | config GPIO_ADNP | 501 | config GPIO_ADNP |
468 | tristate "Avionic Design N-bit GPIO expander" | 502 | tristate "Avionic Design N-bit GPIO expander" |
469 | depends on I2C && OF | 503 | depends on I2C && OF_GPIO |
470 | help | 504 | help |
471 | This option enables support for N GPIOs found on Avionic Design | 505 | This option enables support for N GPIOs found on Avionic Design |
472 | I2C GPIO expanders. The register space will be extended by powers | 506 | I2C GPIO expanders. The register space will be extended by powers |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 9aeed6707326..76b344683251 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -4,6 +4,7 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG | |||
4 | 4 | ||
5 | obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o | 5 | obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o |
6 | obj-$(CONFIG_OF_GPIO) += gpiolib-of.o | 6 | obj-$(CONFIG_OF_GPIO) += gpiolib-of.o |
7 | obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o | ||
7 | 8 | ||
8 | # Device drivers. Generally keep list sorted alphabetically | 9 | # Device drivers. Generally keep list sorted alphabetically |
9 | obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o | 10 | obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o |
@@ -16,8 +17,10 @@ obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o | |||
16 | obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o | 17 | obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o |
17 | obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o | 18 | obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o |
18 | obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o | 19 | obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o |
20 | obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o | ||
19 | obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o | 21 | obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o |
20 | obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o | 22 | obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o |
23 | obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o | ||
21 | obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o | 24 | obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o |
22 | obj-$(CONFIG_GPIO_EM) += gpio-em.o | 25 | obj-$(CONFIG_GPIO_EM) += gpio-em.o |
23 | obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o | 26 | obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o |
@@ -57,6 +60,7 @@ obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o | |||
57 | obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o | 60 | obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o |
58 | obj-$(CONFIG_GPIO_SCH) += gpio-sch.o | 61 | obj-$(CONFIG_GPIO_SCH) += gpio-sch.o |
59 | 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 | ||
60 | obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o | 64 | obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o |
61 | obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o | 65 | obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o |
62 | obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o | 66 | obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o |
@@ -68,6 +72,7 @@ obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o | |||
68 | obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o | 72 | obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o |
69 | obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o | 73 | obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o |
70 | obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o | 74 | obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o |
75 | obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o | ||
71 | obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o | 76 | obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o |
72 | obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o | 77 | obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o |
73 | 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 320a718cab40..bdc8302e711a 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 em_gio_probe(struct platform_device *pdev) | 236 | static int 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 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 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 22b75825a39e..00092342b84c 100644 --- a/drivers/gpio/gpio-max730x.c +++ b/drivers/gpio/gpio-max730x.c | |||
@@ -167,10 +167,6 @@ int __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 __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 __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-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index ce620f1ef4aa..3cea0ea79e80 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c | |||
@@ -77,7 +77,7 @@ struct mcp23s08_driver_data { | |||
77 | 77 | ||
78 | /*----------------------------------------------------------------------*/ | 78 | /*----------------------------------------------------------------------*/ |
79 | 79 | ||
80 | #ifdef CONFIG_I2C | 80 | #if IS_ENABLED(CONFIG_I2C) |
81 | 81 | ||
82 | static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg) | 82 | static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg) |
83 | { | 83 | { |
@@ -399,7 +399,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, | |||
399 | break; | 399 | break; |
400 | #endif /* CONFIG_SPI_MASTER */ | 400 | #endif /* CONFIG_SPI_MASTER */ |
401 | 401 | ||
402 | #ifdef CONFIG_I2C | 402 | #if IS_ENABLED(CONFIG_I2C) |
403 | case MCP_TYPE_008: | 403 | case MCP_TYPE_008: |
404 | mcp->ops = &mcp23008_ops; | 404 | mcp->ops = &mcp23008_ops; |
405 | mcp->chip.ngpio = 8; | 405 | mcp->chip.ngpio = 8; |
@@ -473,7 +473,7 @@ fail: | |||
473 | 473 | ||
474 | /*----------------------------------------------------------------------*/ | 474 | /*----------------------------------------------------------------------*/ |
475 | 475 | ||
476 | #ifdef CONFIG_I2C | 476 | #if IS_ENABLED(CONFIG_I2C) |
477 | 477 | ||
478 | static int mcp230xx_probe(struct i2c_client *client, | 478 | static int mcp230xx_probe(struct i2c_client *client, |
479 | const struct i2c_device_id *id) | 479 | const struct i2c_device_id *id) |
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index f2a04ba0ca6c..d767b534c4af 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c | |||
@@ -92,6 +92,11 @@ static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip) | |||
92 | return mvchip->membase + GPIO_OUT_OFF; | 92 | return mvchip->membase + GPIO_OUT_OFF; |
93 | } | 93 | } |
94 | 94 | ||
95 | static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip) | ||
96 | { | ||
97 | return mvchip->membase + GPIO_BLINK_EN_OFF; | ||
98 | } | ||
99 | |||
95 | static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip) | 100 | static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip) |
96 | { | 101 | { |
97 | return mvchip->membase + GPIO_IO_CONF_OFF; | 102 | return mvchip->membase + GPIO_IO_CONF_OFF; |
@@ -163,12 +168,12 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip) | |||
163 | * Functions implementing the gpio_chip methods | 168 | * Functions implementing the gpio_chip methods |
164 | */ | 169 | */ |
165 | 170 | ||
166 | int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin) | 171 | static int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin) |
167 | { | 172 | { |
168 | return pinctrl_request_gpio(chip->base + pin); | 173 | return pinctrl_request_gpio(chip->base + pin); |
169 | } | 174 | } |
170 | 175 | ||
171 | void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin) | 176 | static void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin) |
172 | { | 177 | { |
173 | pinctrl_free_gpio(chip->base + pin); | 178 | pinctrl_free_gpio(chip->base + pin); |
174 | } | 179 | } |
@@ -206,6 +211,23 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin) | |||
206 | return (u >> pin) & 1; | 211 | return (u >> pin) & 1; |
207 | } | 212 | } |
208 | 213 | ||
214 | static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value) | ||
215 | { | ||
216 | struct mvebu_gpio_chip *mvchip = | ||
217 | container_of(chip, struct mvebu_gpio_chip, chip); | ||
218 | unsigned long flags; | ||
219 | u32 u; | ||
220 | |||
221 | spin_lock_irqsave(&mvchip->lock, flags); | ||
222 | u = readl_relaxed(mvebu_gpioreg_blink(mvchip)); | ||
223 | if (value) | ||
224 | u |= 1 << pin; | ||
225 | else | ||
226 | u &= ~(1 << pin); | ||
227 | writel_relaxed(u, mvebu_gpioreg_blink(mvchip)); | ||
228 | spin_unlock_irqrestore(&mvchip->lock, flags); | ||
229 | } | ||
230 | |||
209 | static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin) | 231 | static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin) |
210 | { | 232 | { |
211 | struct mvebu_gpio_chip *mvchip = | 233 | struct mvebu_gpio_chip *mvchip = |
@@ -244,6 +266,7 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin, | |||
244 | if (ret) | 266 | if (ret) |
245 | return ret; | 267 | return ret; |
246 | 268 | ||
269 | mvebu_gpio_blink(chip, pin, 0); | ||
247 | mvebu_gpio_set(chip, pin, value); | 270 | mvebu_gpio_set(chip, pin, value); |
248 | 271 | ||
249 | spin_lock_irqsave(&mvchip->lock, flags); | 272 | spin_lock_irqsave(&mvchip->lock, flags); |
@@ -523,6 +546,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
523 | mvchip->chip.label = dev_name(&pdev->dev); | 546 | mvchip->chip.label = dev_name(&pdev->dev); |
524 | mvchip->chip.dev = &pdev->dev; | 547 | mvchip->chip.dev = &pdev->dev; |
525 | mvchip->chip.request = mvebu_gpio_request; | 548 | mvchip->chip.request = mvebu_gpio_request; |
549 | mvchip->chip.free = mvebu_gpio_free; | ||
526 | mvchip->chip.direction_input = mvebu_gpio_direction_input; | 550 | mvchip->chip.direction_input = mvebu_gpio_direction_input; |
527 | mvchip->chip.get = mvebu_gpio_get; | 551 | mvchip->chip.get = mvebu_gpio_get; |
528 | mvchip->chip.direction_output = mvebu_gpio_direction_output; | 552 | mvchip->chip.direction_output = mvebu_gpio_direction_output; |
@@ -650,8 +674,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
650 | IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); | 674 | IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); |
651 | 675 | ||
652 | /* Setup irq domain on top of the generic chip. */ | 676 | /* Setup irq domain on top of the generic chip. */ |
653 | mvchip->domain = irq_domain_add_legacy(np, mvchip->chip.ngpio, | 677 | mvchip->domain = irq_domain_add_simple(np, mvchip->chip.ngpio, |
654 | mvchip->irqbase, 0, | 678 | mvchip->irqbase, |
655 | &irq_domain_simple_ops, | 679 | &irq_domain_simple_ops, |
656 | mvchip); | 680 | mvchip); |
657 | if (!mvchip->domain) { | 681 | if (!mvchip->domain) { |
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 148a4f23d118..f1fbedb2a6f9 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c | |||
@@ -1105,7 +1105,7 @@ static int 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 fff7c2be58f9..cc102d25ee24 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 bb2b66be17a4..cdf599687cf7 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 6dff78b19725..770476a9da87 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 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 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 stmpe_gpio_probe(struct platform_device *pdev) | 325 | static int 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 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 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 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 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 839f44923cb9..c0595bbf3268 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 4cd3e1df05d8..63cb643d4b5a 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 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 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 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 8beae6627656..00329f2fc05b 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 579f26403918..b53320a16fc8 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-acpi.c b/drivers/gpio/gpiolib-acpi.c new file mode 100644 index 000000000000..cbad6e908d30 --- /dev/null +++ b/drivers/gpio/gpiolib-acpi.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * ACPI helpers for GPIO API | ||
3 | * | ||
4 | * Copyright (C) 2012, Intel Corporation | ||
5 | * Authors: Mathias Nyman <mathias.nyman@linux.intel.com> | ||
6 | * Mika Westerberg <mika.westerberg@linux.intel.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/errno.h> | ||
14 | #include <linux/gpio.h> | ||
15 | #include <linux/export.h> | ||
16 | #include <linux/acpi_gpio.h> | ||
17 | #include <linux/acpi.h> | ||
18 | |||
19 | static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) | ||
20 | { | ||
21 | if (!gc->dev) | ||
22 | return false; | ||
23 | |||
24 | return ACPI_HANDLE(gc->dev) == data; | ||
25 | } | ||
26 | |||
27 | /** | ||
28 | * acpi_get_gpio() - Translate ACPI GPIO pin to GPIO number usable with GPIO API | ||
29 | * @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1") | ||
30 | * @pin: ACPI GPIO pin number (0-based, controller-relative) | ||
31 | * | ||
32 | * Returns GPIO number to use with Linux generic GPIO API, or errno error value | ||
33 | */ | ||
34 | |||
35 | int acpi_get_gpio(char *path, int pin) | ||
36 | { | ||
37 | struct gpio_chip *chip; | ||
38 | acpi_handle handle; | ||
39 | acpi_status status; | ||
40 | |||
41 | status = acpi_get_handle(NULL, path, &handle); | ||
42 | if (ACPI_FAILURE(status)) | ||
43 | return -ENODEV; | ||
44 | |||
45 | chip = gpiochip_find(handle, acpi_gpiochip_find); | ||
46 | if (!chip) | ||
47 | return -ENODEV; | ||
48 | |||
49 | if (!gpio_is_valid(chip->base + pin)) | ||
50 | return -EINVAL; | ||
51 | |||
52 | return chip->base + pin; | ||
53 | } | ||
54 | EXPORT_SYMBOL_GPL(acpi_get_gpio); | ||
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index f1a45997aea8..d542a141811a 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/of.h> | 19 | #include <linux/of.h> |
20 | #include <linux/of_address.h> | 20 | #include <linux/of_address.h> |
21 | #include <linux/of_gpio.h> | 21 | #include <linux/of_gpio.h> |
22 | #include <linux/pinctrl/pinctrl.h> | ||
22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
23 | 24 | ||
24 | /* Private data structure for of_gpiochip_find_and_xlate */ | 25 | /* Private data structure for of_gpiochip_find_and_xlate */ |
@@ -216,6 +217,54 @@ err0: | |||
216 | } | 217 | } |
217 | EXPORT_SYMBOL(of_mm_gpiochip_add); | 218 | EXPORT_SYMBOL(of_mm_gpiochip_add); |
218 | 219 | ||
220 | #ifdef CONFIG_PINCTRL | ||
221 | static void of_gpiochip_add_pin_range(struct gpio_chip *chip) | ||
222 | { | ||
223 | struct device_node *np = chip->of_node; | ||
224 | struct of_phandle_args pinspec; | ||
225 | struct pinctrl_dev *pctldev; | ||
226 | int index = 0, ret; | ||
227 | |||
228 | if (!np) | ||
229 | return; | ||
230 | |||
231 | do { | ||
232 | ret = of_parse_phandle_with_args(np, "gpio-ranges", | ||
233 | "#gpio-range-cells", index, &pinspec); | ||
234 | if (ret) | ||
235 | break; | ||
236 | |||
237 | pctldev = of_pinctrl_get(pinspec.np); | ||
238 | if (!pctldev) | ||
239 | break; | ||
240 | |||
241 | /* | ||
242 | * This assumes that the n GPIO pins are consecutive in the | ||
243 | * GPIO number space, and that the pins are also consecutive | ||
244 | * in their local number space. Currently it is not possible | ||
245 | * to add different ranges for one and the same GPIO chip, | ||
246 | * as the code assumes that we have one consecutive range | ||
247 | * on both, mapping 1-to-1. | ||
248 | * | ||
249 | * TODO: make the OF bindings handle multiple sparse ranges | ||
250 | * on the same GPIO chip. | ||
251 | */ | ||
252 | ret = gpiochip_add_pin_range(chip, | ||
253 | pinctrl_dev_get_name(pctldev), | ||
254 | 0, /* offset in gpiochip */ | ||
255 | pinspec.args[0], | ||
256 | pinspec.args[1]); | ||
257 | |||
258 | if (ret) | ||
259 | break; | ||
260 | |||
261 | } while (index++); | ||
262 | } | ||
263 | |||
264 | #else | ||
265 | static void of_gpiochip_add_pin_range(struct gpio_chip *chip) {} | ||
266 | #endif | ||
267 | |||
219 | void of_gpiochip_add(struct gpio_chip *chip) | 268 | void of_gpiochip_add(struct gpio_chip *chip) |
220 | { | 269 | { |
221 | if ((!chip->of_node) && (chip->dev)) | 270 | if ((!chip->of_node) && (chip->dev)) |
@@ -229,11 +278,14 @@ void of_gpiochip_add(struct gpio_chip *chip) | |||
229 | chip->of_xlate = of_gpio_simple_xlate; | 278 | chip->of_xlate = of_gpio_simple_xlate; |
230 | } | 279 | } |
231 | 280 | ||
281 | of_gpiochip_add_pin_range(chip); | ||
232 | of_node_get(chip->of_node); | 282 | of_node_get(chip->of_node); |
233 | } | 283 | } |
234 | 284 | ||
235 | void of_gpiochip_remove(struct gpio_chip *chip) | 285 | void of_gpiochip_remove(struct gpio_chip *chip) |
236 | { | 286 | { |
287 | gpiochip_remove_pin_ranges(chip); | ||
288 | |||
237 | if (chip->of_node) | 289 | if (chip->of_node) |
238 | of_node_put(chip->of_node); | 290 | of_node_put(chip->of_node); |
239 | } | 291 | } |
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1c8d9e3380e1..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; |
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; | ||
768 | 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 |
@@ -1083,6 +1120,10 @@ int gpiochip_add(struct gpio_chip *chip) | |||
1083 | } | 1120 | } |
1084 | } | 1121 | } |
1085 | 1122 | ||
1123 | #ifdef CONFIG_PINCTRL | ||
1124 | INIT_LIST_HEAD(&chip->pin_ranges); | ||
1125 | #endif | ||
1126 | |||
1086 | of_gpiochip_add(chip); | 1127 | of_gpiochip_add(chip); |
1087 | 1128 | ||
1088 | unlock: | 1129 | unlock: |
@@ -1123,6 +1164,7 @@ int gpiochip_remove(struct gpio_chip *chip) | |||
1123 | 1164 | ||
1124 | spin_lock_irqsave(&gpio_lock, flags); | 1165 | spin_lock_irqsave(&gpio_lock, flags); |
1125 | 1166 | ||
1167 | gpiochip_remove_pin_ranges(chip); | ||
1126 | of_gpiochip_remove(chip); | 1168 | of_gpiochip_remove(chip); |
1127 | 1169 | ||
1128 | for (id = chip->base; id < chip->base + chip->ngpio; id++) { | 1170 | for (id = chip->base; id < chip->base + chip->ngpio; id++) { |
@@ -1180,6 +1222,77 @@ struct gpio_chip *gpiochip_find(void *data, | |||
1180 | } | 1222 | } |
1181 | EXPORT_SYMBOL_GPL(gpiochip_find); | 1223 | EXPORT_SYMBOL_GPL(gpiochip_find); |
1182 | 1224 | ||
1225 | #ifdef CONFIG_PINCTRL | ||
1226 | |||
1227 | /** | ||
1228 | * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping | ||
1229 | * @chip: the gpiochip to add the range for | ||
1230 | * @pinctrl_name: the dev_name() of the pin controller to map to | ||
1231 | * @gpio_offset: the start offset in the current gpio_chip number space | ||
1232 | * @pin_offset: the start offset in the pin controller number space | ||
1233 | * @npins: the number of pins from the offset of each pin space (GPIO and | ||
1234 | * pin controller) to accumulate in this range | ||
1235 | */ | ||
1236 | int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, | ||
1237 | unsigned int gpio_offset, unsigned int pin_offset, | ||
1238 | unsigned int npins) | ||
1239 | { | ||
1240 | struct gpio_pin_range *pin_range; | ||
1241 | int ret; | ||
1242 | |||
1243 | pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); | ||
1244 | if (!pin_range) { | ||
1245 | pr_err("%s: GPIO chip: failed to allocate pin ranges\n", | ||
1246 | chip->label); | ||
1247 | return -ENOMEM; | ||
1248 | } | ||
1249 | |||
1250 | /* Use local offset as range ID */ | ||
1251 | pin_range->range.id = gpio_offset; | ||
1252 | pin_range->range.gc = chip; | ||
1253 | pin_range->range.name = chip->label; | ||
1254 | pin_range->range.base = chip->base + gpio_offset; | ||
1255 | pin_range->range.pin_base = pin_offset; | ||
1256 | pin_range->range.npins = npins; | ||
1257 | pin_range->pctldev = pinctrl_find_and_add_gpio_range(pinctl_name, | ||
1258 | &pin_range->range); | ||
1259 | if (IS_ERR(pin_range->pctldev)) { | ||
1260 | ret = PTR_ERR(pin_range->pctldev); | ||
1261 | pr_err("%s: GPIO chip: could not create pin range\n", | ||
1262 | chip->label); | ||
1263 | kfree(pin_range); | ||
1264 | return ret; | ||
1265 | } | ||
1266 | pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PIN %d->%d\n", | ||
1267 | chip->label, gpio_offset, gpio_offset + npins - 1, | ||
1268 | pinctl_name, | ||
1269 | pin_offset, pin_offset + npins - 1); | ||
1270 | |||
1271 | list_add_tail(&pin_range->node, &chip->pin_ranges); | ||
1272 | |||
1273 | return 0; | ||
1274 | } | ||
1275 | EXPORT_SYMBOL_GPL(gpiochip_add_pin_range); | ||
1276 | |||
1277 | /** | ||
1278 | * gpiochip_remove_pin_ranges() - remove all the GPIO <-> pin mappings | ||
1279 | * @chip: the chip to remove all the mappings for | ||
1280 | */ | ||
1281 | void gpiochip_remove_pin_ranges(struct gpio_chip *chip) | ||
1282 | { | ||
1283 | struct gpio_pin_range *pin_range, *tmp; | ||
1284 | |||
1285 | list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) { | ||
1286 | list_del(&pin_range->node); | ||
1287 | pinctrl_remove_gpio_range(pin_range->pctldev, | ||
1288 | &pin_range->range); | ||
1289 | kfree(pin_range); | ||
1290 | } | ||
1291 | } | ||
1292 | EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges); | ||
1293 | |||
1294 | #endif /* CONFIG_PINCTRL */ | ||
1295 | |||
1183 | /* These "optional" allocation calls help prevent drivers from stomping | 1296 | /* These "optional" allocation calls help prevent drivers from stomping |
1184 | * on each other, and help provide better diagnostics in debugfs. | 1297 | * on each other, and help provide better diagnostics in debugfs. |
1185 | * They're called even less than the "set direction" calls. | 1298 | * They're called even less than the "set direction" calls. |
@@ -1228,9 +1341,15 @@ int gpio_request(unsigned gpio, const char *label) | |||
1228 | desc_set_label(desc, NULL); | 1341 | desc_set_label(desc, NULL); |
1229 | module_put(chip->owner); | 1342 | module_put(chip->owner); |
1230 | clear_bit(FLAG_REQUESTED, &desc->flags); | 1343 | clear_bit(FLAG_REQUESTED, &desc->flags); |
1344 | goto done; | ||
1231 | } | 1345 | } |
1232 | } | 1346 | } |
1233 | 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 | } | ||
1234 | done: | 1353 | done: |
1235 | if (status) | 1354 | if (status) |
1236 | pr_debug("gpio_request: gpio-%d (%s) status %d\n", | 1355 | pr_debug("gpio_request: gpio-%d (%s) status %d\n", |
@@ -1766,6 +1885,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
1766 | if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) | 1885 | if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) |
1767 | continue; | 1886 | continue; |
1768 | 1887 | ||
1888 | gpio_get_direction(gpio); | ||
1769 | is_out = test_bit(FLAG_IS_OUT, &gdesc->flags); | 1889 | is_out = test_bit(FLAG_IS_OUT, &gdesc->flags); |
1770 | seq_printf(s, " gpio-%-3d (%-20.20s) %s %s", | 1890 | seq_printf(s, " gpio-%-3d (%-20.20s) %s %s", |
1771 | gpio, gdesc->label, | 1891 | gpio, gdesc->label, |