diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Kconfig | 35 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 4 | ||||
-rw-r--r-- | drivers/gpio/adp5520-gpio.c | 206 | ||||
-rw-r--r-- | drivers/gpio/bt8xxgpio.c | 7 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 253 | ||||
-rw-r--r-- | drivers/gpio/langwell_gpio.c | 297 | ||||
-rw-r--r-- | drivers/gpio/max7301.c | 1 | ||||
-rw-r--r-- | drivers/gpio/mc33880.c | 196 | ||||
-rw-r--r-- | drivers/gpio/mcp23s08.c | 5 | ||||
-rw-r--r-- | drivers/gpio/pca953x.c | 4 | ||||
-rw-r--r-- | drivers/gpio/pcf857x.c | 4 | ||||
-rw-r--r-- | drivers/gpio/ucb1400_gpio.c | 125 |
12 files changed, 1121 insertions, 16 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 6b4c484a699a..2ad0128c63c6 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -162,6 +162,16 @@ config GPIO_WM831X | |||
162 | Say yes here to access the GPIO signals of WM831x power management | 162 | Say yes here to access the GPIO signals of WM831x power management |
163 | chips from Wolfson Microelectronics. | 163 | chips from Wolfson Microelectronics. |
164 | 164 | ||
165 | config GPIO_ADP5520 | ||
166 | tristate "GPIO Support for ADP5520 PMIC" | ||
167 | depends on PMIC_ADP5520 | ||
168 | help | ||
169 | This option enables support for on-chip GPIO found | ||
170 | on Analog Devices ADP5520 PMICs. | ||
171 | |||
172 | To compile this driver as a module, choose M here: the module will | ||
173 | be called adp5520-gpio. | ||
174 | |||
165 | comment "PCI GPIO expanders:" | 175 | comment "PCI GPIO expanders:" |
166 | 176 | ||
167 | config GPIO_BT8XX | 177 | config GPIO_BT8XX |
@@ -180,6 +190,12 @@ config GPIO_BT8XX | |||
180 | 190 | ||
181 | If unsure, say N. | 191 | If unsure, say N. |
182 | 192 | ||
193 | config GPIO_LANGWELL | ||
194 | bool "Intel Moorestown Platform Langwell GPIO support" | ||
195 | depends on PCI | ||
196 | help | ||
197 | Say Y here to support Intel Moorestown platform GPIO. | ||
198 | |||
183 | comment "SPI GPIO expanders:" | 199 | comment "SPI GPIO expanders:" |
184 | 200 | ||
185 | config GPIO_MAX7301 | 201 | config GPIO_MAX7301 |
@@ -195,4 +211,23 @@ config GPIO_MCP23S08 | |||
195 | SPI driver for Microchip MCP23S08 I/O expander. This provides | 211 | SPI driver for Microchip MCP23S08 I/O expander. This provides |
196 | a GPIO interface supporting inputs and outputs. | 212 | a GPIO interface supporting inputs and outputs. |
197 | 213 | ||
214 | config GPIO_MC33880 | ||
215 | tristate "Freescale MC33880 high-side/low-side switch" | ||
216 | depends on SPI_MASTER | ||
217 | help | ||
218 | SPI driver for Freescale MC33880 high-side/low-side switch. | ||
219 | This provides GPIO interface supporting inputs and outputs. | ||
220 | |||
221 | comment "AC97 GPIO expanders:" | ||
222 | |||
223 | config GPIO_UCB1400 | ||
224 | bool "Philips UCB1400 GPIO" | ||
225 | depends on UCB1400_CORE | ||
226 | help | ||
227 | This enables support for the Philips UCB1400 GPIO pins. | ||
228 | The UCB1400 is an AC97 audio codec. | ||
229 | |||
230 | To compile this driver as a module, choose M here: the | ||
231 | module will be called ucb1400_gpio. | ||
232 | |||
198 | endif | 233 | endif |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ea7c745f26a8..00a532c9a1e2 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -4,13 +4,17 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG | |||
4 | 4 | ||
5 | obj-$(CONFIG_GPIOLIB) += gpiolib.o | 5 | obj-$(CONFIG_GPIOLIB) += gpiolib.o |
6 | 6 | ||
7 | obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o | ||
8 | obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o | ||
7 | obj-$(CONFIG_GPIO_MAX7301) += max7301.o | 9 | obj-$(CONFIG_GPIO_MAX7301) += max7301.o |
8 | obj-$(CONFIG_GPIO_MAX732X) += max732x.o | 10 | obj-$(CONFIG_GPIO_MAX732X) += max732x.o |
11 | obj-$(CONFIG_GPIO_MC33880) += mc33880.o | ||
9 | obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o | 12 | obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o |
10 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o | 13 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o |
11 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o | 14 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o |
12 | obj-$(CONFIG_GPIO_PL061) += pl061.o | 15 | obj-$(CONFIG_GPIO_PL061) += pl061.o |
13 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o | 16 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o |
17 | obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o | ||
14 | obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o | 18 | obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o |
15 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o | 19 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o |
16 | obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o | 20 | obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o |
diff --git a/drivers/gpio/adp5520-gpio.c b/drivers/gpio/adp5520-gpio.c new file mode 100644 index 000000000000..ad05bbc7ffd5 --- /dev/null +++ b/drivers/gpio/adp5520-gpio.c | |||
@@ -0,0 +1,206 @@ | |||
1 | /* | ||
2 | * GPIO driver for Analog Devices ADP5520 MFD PMICs | ||
3 | * | ||
4 | * Copyright 2009 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/mfd/adp5520.h> | ||
14 | |||
15 | #include <linux/gpio.h> | ||
16 | |||
17 | struct adp5520_gpio { | ||
18 | struct device *master; | ||
19 | struct gpio_chip gpio_chip; | ||
20 | unsigned char lut[ADP5520_MAXGPIOS]; | ||
21 | unsigned long output; | ||
22 | }; | ||
23 | |||
24 | static int adp5520_gpio_get_value(struct gpio_chip *chip, unsigned off) | ||
25 | { | ||
26 | struct adp5520_gpio *dev; | ||
27 | uint8_t reg_val; | ||
28 | |||
29 | dev = container_of(chip, struct adp5520_gpio, gpio_chip); | ||
30 | |||
31 | /* | ||
32 | * There are dedicated registers for GPIO IN/OUT. | ||
33 | * Make sure we return the right value, even when configured as output | ||
34 | */ | ||
35 | |||
36 | if (test_bit(off, &dev->output)) | ||
37 | adp5520_read(dev->master, GPIO_OUT, ®_val); | ||
38 | else | ||
39 | adp5520_read(dev->master, GPIO_IN, ®_val); | ||
40 | |||
41 | return !!(reg_val & dev->lut[off]); | ||
42 | } | ||
43 | |||
44 | static void adp5520_gpio_set_value(struct gpio_chip *chip, | ||
45 | unsigned off, int val) | ||
46 | { | ||
47 | struct adp5520_gpio *dev; | ||
48 | dev = container_of(chip, struct adp5520_gpio, gpio_chip); | ||
49 | |||
50 | if (val) | ||
51 | adp5520_set_bits(dev->master, GPIO_OUT, dev->lut[off]); | ||
52 | else | ||
53 | adp5520_clr_bits(dev->master, GPIO_OUT, dev->lut[off]); | ||
54 | } | ||
55 | |||
56 | static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off) | ||
57 | { | ||
58 | struct adp5520_gpio *dev; | ||
59 | dev = container_of(chip, struct adp5520_gpio, gpio_chip); | ||
60 | |||
61 | clear_bit(off, &dev->output); | ||
62 | |||
63 | return adp5520_clr_bits(dev->master, GPIO_CFG_2, dev->lut[off]); | ||
64 | } | ||
65 | |||
66 | static int adp5520_gpio_direction_output(struct gpio_chip *chip, | ||
67 | unsigned off, int val) | ||
68 | { | ||
69 | struct adp5520_gpio *dev; | ||
70 | int ret = 0; | ||
71 | dev = container_of(chip, struct adp5520_gpio, gpio_chip); | ||
72 | |||
73 | set_bit(off, &dev->output); | ||
74 | |||
75 | if (val) | ||
76 | ret |= adp5520_set_bits(dev->master, GPIO_OUT, dev->lut[off]); | ||
77 | else | ||
78 | ret |= adp5520_clr_bits(dev->master, GPIO_OUT, dev->lut[off]); | ||
79 | |||
80 | ret |= adp5520_set_bits(dev->master, GPIO_CFG_2, dev->lut[off]); | ||
81 | |||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | static int __devinit adp5520_gpio_probe(struct platform_device *pdev) | ||
86 | { | ||
87 | struct adp5520_gpio_platfrom_data *pdata = pdev->dev.platform_data; | ||
88 | struct adp5520_gpio *dev; | ||
89 | struct gpio_chip *gc; | ||
90 | int ret, i, gpios; | ||
91 | unsigned char ctl_mask = 0; | ||
92 | |||
93 | if (pdata == NULL) { | ||
94 | dev_err(&pdev->dev, "missing platform data\n"); | ||
95 | return -ENODEV; | ||
96 | } | ||
97 | |||
98 | if (pdev->id != ID_ADP5520) { | ||
99 | dev_err(&pdev->dev, "only ADP5520 supports GPIO\n"); | ||
100 | return -ENODEV; | ||
101 | } | ||
102 | |||
103 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
104 | if (dev == NULL) { | ||
105 | dev_err(&pdev->dev, "failed to alloc memory\n"); | ||
106 | return -ENOMEM; | ||
107 | } | ||
108 | |||
109 | dev->master = pdev->dev.parent; | ||
110 | |||
111 | for (gpios = 0, i = 0; i < ADP5520_MAXGPIOS; i++) | ||
112 | if (pdata->gpio_en_mask & (1 << i)) | ||
113 | dev->lut[gpios++] = 1 << i; | ||
114 | |||
115 | if (gpios < 1) { | ||
116 | ret = -EINVAL; | ||
117 | goto err; | ||
118 | } | ||
119 | |||
120 | gc = &dev->gpio_chip; | ||
121 | gc->direction_input = adp5520_gpio_direction_input; | ||
122 | gc->direction_output = adp5520_gpio_direction_output; | ||
123 | gc->get = adp5520_gpio_get_value; | ||
124 | gc->set = adp5520_gpio_set_value; | ||
125 | gc->can_sleep = 1; | ||
126 | |||
127 | gc->base = pdata->gpio_start; | ||
128 | gc->ngpio = gpios; | ||
129 | gc->label = pdev->name; | ||
130 | gc->owner = THIS_MODULE; | ||
131 | |||
132 | ret = adp5520_clr_bits(dev->master, GPIO_CFG_1, | ||
133 | pdata->gpio_en_mask); | ||
134 | |||
135 | if (pdata->gpio_en_mask & GPIO_C3) | ||
136 | ctl_mask |= C3_MODE; | ||
137 | |||
138 | if (pdata->gpio_en_mask & GPIO_R3) | ||
139 | ctl_mask |= R3_MODE; | ||
140 | |||
141 | if (ctl_mask) | ||
142 | ret = adp5520_set_bits(dev->master, LED_CONTROL, | ||
143 | ctl_mask); | ||
144 | |||
145 | ret |= adp5520_set_bits(dev->master, GPIO_PULLUP, | ||
146 | pdata->gpio_pullup_mask); | ||
147 | |||
148 | if (ret) { | ||
149 | dev_err(&pdev->dev, "failed to write\n"); | ||
150 | goto err; | ||
151 | } | ||
152 | |||
153 | ret = gpiochip_add(&dev->gpio_chip); | ||
154 | if (ret) | ||
155 | goto err; | ||
156 | |||
157 | platform_set_drvdata(pdev, dev); | ||
158 | return 0; | ||
159 | |||
160 | err: | ||
161 | kfree(dev); | ||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | static int __devexit adp5520_gpio_remove(struct platform_device *pdev) | ||
166 | { | ||
167 | struct adp5520_gpio *dev; | ||
168 | int ret; | ||
169 | |||
170 | dev = platform_get_drvdata(pdev); | ||
171 | ret = gpiochip_remove(&dev->gpio_chip); | ||
172 | if (ret) { | ||
173 | dev_err(&pdev->dev, "%s failed, %d\n", | ||
174 | "gpiochip_remove()", ret); | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | kfree(dev); | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static struct platform_driver adp5520_gpio_driver = { | ||
183 | .driver = { | ||
184 | .name = "adp5520-gpio", | ||
185 | .owner = THIS_MODULE, | ||
186 | }, | ||
187 | .probe = adp5520_gpio_probe, | ||
188 | .remove = __devexit_p(adp5520_gpio_remove), | ||
189 | }; | ||
190 | |||
191 | static int __init adp5520_gpio_init(void) | ||
192 | { | ||
193 | return platform_driver_register(&adp5520_gpio_driver); | ||
194 | } | ||
195 | module_init(adp5520_gpio_init); | ||
196 | |||
197 | static void __exit adp5520_gpio_exit(void) | ||
198 | { | ||
199 | platform_driver_unregister(&adp5520_gpio_driver); | ||
200 | } | ||
201 | module_exit(adp5520_gpio_exit); | ||
202 | |||
203 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
204 | MODULE_DESCRIPTION("GPIO ADP5520 Driver"); | ||
205 | MODULE_LICENSE("GPL"); | ||
206 | MODULE_ALIAS("platform:adp5520-gpio"); | ||
diff --git a/drivers/gpio/bt8xxgpio.c b/drivers/gpio/bt8xxgpio.c index 984b587f0f96..2559f2289409 100644 --- a/drivers/gpio/bt8xxgpio.c +++ b/drivers/gpio/bt8xxgpio.c | |||
@@ -46,8 +46,7 @@ | |||
46 | #include <linux/module.h> | 46 | #include <linux/module.h> |
47 | #include <linux/pci.h> | 47 | #include <linux/pci.h> |
48 | #include <linux/spinlock.h> | 48 | #include <linux/spinlock.h> |
49 | 49 | #include <linux/gpio.h> | |
50 | #include <asm/gpio.h> | ||
51 | 50 | ||
52 | /* Steal the hardware definitions from the bttv driver. */ | 51 | /* Steal the hardware definitions from the bttv driver. */ |
53 | #include "../media/video/bt8xx/bt848.h" | 52 | #include "../media/video/bt8xx/bt848.h" |
@@ -331,13 +330,13 @@ static struct pci_driver bt8xxgpio_pci_driver = { | |||
331 | .resume = bt8xxgpio_resume, | 330 | .resume = bt8xxgpio_resume, |
332 | }; | 331 | }; |
333 | 332 | ||
334 | static int bt8xxgpio_init(void) | 333 | static int __init bt8xxgpio_init(void) |
335 | { | 334 | { |
336 | return pci_register_driver(&bt8xxgpio_pci_driver); | 335 | return pci_register_driver(&bt8xxgpio_pci_driver); |
337 | } | 336 | } |
338 | module_init(bt8xxgpio_init) | 337 | module_init(bt8xxgpio_init) |
339 | 338 | ||
340 | static void bt8xxgpio_exit(void) | 339 | static void __exit bt8xxgpio_exit(void) |
341 | { | 340 | { |
342 | pci_unregister_driver(&bt8xxgpio_pci_driver); | 341 | pci_unregister_driver(&bt8xxgpio_pci_driver); |
343 | } | 342 | } |
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 51a8d4103be5..bb11a429394a 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
3 | #include <linux/interrupt.h> | ||
3 | #include <linux/irq.h> | 4 | #include <linux/irq.h> |
4 | #include <linux/spinlock.h> | 5 | #include <linux/spinlock.h> |
5 | #include <linux/device.h> | 6 | #include <linux/device.h> |
@@ -7,6 +8,7 @@ | |||
7 | #include <linux/debugfs.h> | 8 | #include <linux/debugfs.h> |
8 | #include <linux/seq_file.h> | 9 | #include <linux/seq_file.h> |
9 | #include <linux/gpio.h> | 10 | #include <linux/gpio.h> |
11 | #include <linux/idr.h> | ||
10 | 12 | ||
11 | 13 | ||
12 | /* Optional implementation infrastructure for GPIO interfaces. | 14 | /* Optional implementation infrastructure for GPIO interfaces. |
@@ -49,6 +51,13 @@ struct gpio_desc { | |||
49 | #define FLAG_RESERVED 2 | 51 | #define FLAG_RESERVED 2 |
50 | #define FLAG_EXPORT 3 /* protected by sysfs_lock */ | 52 | #define FLAG_EXPORT 3 /* protected by sysfs_lock */ |
51 | #define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */ | 53 | #define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */ |
54 | #define FLAG_TRIG_FALL 5 /* trigger on falling edge */ | ||
55 | #define FLAG_TRIG_RISE 6 /* trigger on rising edge */ | ||
56 | |||
57 | #define PDESC_ID_SHIFT 16 /* add new flags before this one */ | ||
58 | |||
59 | #define GPIO_FLAGS_MASK ((1 << PDESC_ID_SHIFT) - 1) | ||
60 | #define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE)) | ||
52 | 61 | ||
53 | #ifdef CONFIG_DEBUG_FS | 62 | #ifdef CONFIG_DEBUG_FS |
54 | const char *label; | 63 | const char *label; |
@@ -56,6 +65,15 @@ struct gpio_desc { | |||
56 | }; | 65 | }; |
57 | static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; | 66 | static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; |
58 | 67 | ||
68 | #ifdef CONFIG_GPIO_SYSFS | ||
69 | struct poll_desc { | ||
70 | struct work_struct work; | ||
71 | struct sysfs_dirent *value_sd; | ||
72 | }; | ||
73 | |||
74 | static struct idr pdesc_idr; | ||
75 | #endif | ||
76 | |||
59 | static inline void desc_set_label(struct gpio_desc *d, const char *label) | 77 | static inline void desc_set_label(struct gpio_desc *d, const char *label) |
60 | { | 78 | { |
61 | #ifdef CONFIG_DEBUG_FS | 79 | #ifdef CONFIG_DEBUG_FS |
@@ -188,10 +206,10 @@ static DEFINE_MUTEX(sysfs_lock); | |||
188 | * /value | 206 | * /value |
189 | * * always readable, subject to hardware behavior | 207 | * * always readable, subject to hardware behavior |
190 | * * may be writable, as zero/nonzero | 208 | * * may be writable, as zero/nonzero |
191 | * | 209 | * /edge |
192 | * REVISIT there will likely be an attribute for configuring async | 210 | * * configures behavior of poll(2) on /value |
193 | * notifications, e.g. to specify polling interval or IRQ trigger type | 211 | * * available only if pin can generate IRQs on input |
194 | * that would for example trigger a poll() on the "value". | 212 | * * is read/write as "none", "falling", "rising", or "both" |
195 | */ | 213 | */ |
196 | 214 | ||
197 | static ssize_t gpio_direction_show(struct device *dev, | 215 | static ssize_t gpio_direction_show(struct device *dev, |
@@ -288,6 +306,175 @@ static ssize_t gpio_value_store(struct device *dev, | |||
288 | static /*const*/ DEVICE_ATTR(value, 0644, | 306 | static /*const*/ DEVICE_ATTR(value, 0644, |
289 | gpio_value_show, gpio_value_store); | 307 | gpio_value_show, gpio_value_store); |
290 | 308 | ||
309 | static irqreturn_t gpio_sysfs_irq(int irq, void *priv) | ||
310 | { | ||
311 | struct work_struct *work = priv; | ||
312 | |||
313 | schedule_work(work); | ||
314 | return IRQ_HANDLED; | ||
315 | } | ||
316 | |||
317 | static void gpio_notify_sysfs(struct work_struct *work) | ||
318 | { | ||
319 | struct poll_desc *pdesc; | ||
320 | |||
321 | pdesc = container_of(work, struct poll_desc, work); | ||
322 | sysfs_notify_dirent(pdesc->value_sd); | ||
323 | } | ||
324 | |||
325 | static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, | ||
326 | unsigned long gpio_flags) | ||
327 | { | ||
328 | struct poll_desc *pdesc; | ||
329 | unsigned long irq_flags; | ||
330 | int ret, irq, id; | ||
331 | |||
332 | if ((desc->flags & GPIO_TRIGGER_MASK) == gpio_flags) | ||
333 | return 0; | ||
334 | |||
335 | irq = gpio_to_irq(desc - gpio_desc); | ||
336 | if (irq < 0) | ||
337 | return -EIO; | ||
338 | |||
339 | id = desc->flags >> PDESC_ID_SHIFT; | ||
340 | pdesc = idr_find(&pdesc_idr, id); | ||
341 | if (pdesc) { | ||
342 | free_irq(irq, &pdesc->work); | ||
343 | cancel_work_sync(&pdesc->work); | ||
344 | } | ||
345 | |||
346 | desc->flags &= ~GPIO_TRIGGER_MASK; | ||
347 | |||
348 | if (!gpio_flags) { | ||
349 | ret = 0; | ||
350 | goto free_sd; | ||
351 | } | ||
352 | |||
353 | irq_flags = IRQF_SHARED; | ||
354 | if (test_bit(FLAG_TRIG_FALL, &gpio_flags)) | ||
355 | irq_flags |= IRQF_TRIGGER_FALLING; | ||
356 | if (test_bit(FLAG_TRIG_RISE, &gpio_flags)) | ||
357 | irq_flags |= IRQF_TRIGGER_RISING; | ||
358 | |||
359 | if (!pdesc) { | ||
360 | pdesc = kmalloc(sizeof(*pdesc), GFP_KERNEL); | ||
361 | if (!pdesc) { | ||
362 | ret = -ENOMEM; | ||
363 | goto err_out; | ||
364 | } | ||
365 | |||
366 | do { | ||
367 | ret = -ENOMEM; | ||
368 | if (idr_pre_get(&pdesc_idr, GFP_KERNEL)) | ||
369 | ret = idr_get_new_above(&pdesc_idr, | ||
370 | pdesc, 1, &id); | ||
371 | } while (ret == -EAGAIN); | ||
372 | |||
373 | if (ret) | ||
374 | goto free_mem; | ||
375 | |||
376 | desc->flags &= GPIO_FLAGS_MASK; | ||
377 | desc->flags |= (unsigned long)id << PDESC_ID_SHIFT; | ||
378 | |||
379 | if (desc->flags >> PDESC_ID_SHIFT != id) { | ||
380 | ret = -ERANGE; | ||
381 | goto free_id; | ||
382 | } | ||
383 | |||
384 | pdesc->value_sd = sysfs_get_dirent(dev->kobj.sd, "value"); | ||
385 | if (!pdesc->value_sd) { | ||
386 | ret = -ENODEV; | ||
387 | goto free_id; | ||
388 | } | ||
389 | INIT_WORK(&pdesc->work, gpio_notify_sysfs); | ||
390 | } | ||
391 | |||
392 | ret = request_irq(irq, gpio_sysfs_irq, irq_flags, | ||
393 | "gpiolib", &pdesc->work); | ||
394 | if (ret) | ||
395 | goto free_sd; | ||
396 | |||
397 | desc->flags |= gpio_flags; | ||
398 | return 0; | ||
399 | |||
400 | free_sd: | ||
401 | sysfs_put(pdesc->value_sd); | ||
402 | free_id: | ||
403 | idr_remove(&pdesc_idr, id); | ||
404 | desc->flags &= GPIO_FLAGS_MASK; | ||
405 | free_mem: | ||
406 | kfree(pdesc); | ||
407 | err_out: | ||
408 | return ret; | ||
409 | } | ||
410 | |||
411 | static const struct { | ||
412 | const char *name; | ||
413 | unsigned long flags; | ||
414 | } trigger_types[] = { | ||
415 | { "none", 0 }, | ||
416 | { "falling", BIT(FLAG_TRIG_FALL) }, | ||
417 | { "rising", BIT(FLAG_TRIG_RISE) }, | ||
418 | { "both", BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE) }, | ||
419 | }; | ||
420 | |||
421 | static ssize_t gpio_edge_show(struct device *dev, | ||
422 | struct device_attribute *attr, char *buf) | ||
423 | { | ||
424 | const struct gpio_desc *desc = dev_get_drvdata(dev); | ||
425 | ssize_t status; | ||
426 | |||
427 | mutex_lock(&sysfs_lock); | ||
428 | |||
429 | if (!test_bit(FLAG_EXPORT, &desc->flags)) | ||
430 | status = -EIO; | ||
431 | else { | ||
432 | int i; | ||
433 | |||
434 | status = 0; | ||
435 | for (i = 0; i < ARRAY_SIZE(trigger_types); i++) | ||
436 | if ((desc->flags & GPIO_TRIGGER_MASK) | ||
437 | == trigger_types[i].flags) { | ||
438 | status = sprintf(buf, "%s\n", | ||
439 | trigger_types[i].name); | ||
440 | break; | ||
441 | } | ||
442 | } | ||
443 | |||
444 | mutex_unlock(&sysfs_lock); | ||
445 | return status; | ||
446 | } | ||
447 | |||
448 | static ssize_t gpio_edge_store(struct device *dev, | ||
449 | struct device_attribute *attr, const char *buf, size_t size) | ||
450 | { | ||
451 | struct gpio_desc *desc = dev_get_drvdata(dev); | ||
452 | ssize_t status; | ||
453 | int i; | ||
454 | |||
455 | for (i = 0; i < ARRAY_SIZE(trigger_types); i++) | ||
456 | if (sysfs_streq(trigger_types[i].name, buf)) | ||
457 | goto found; | ||
458 | return -EINVAL; | ||
459 | |||
460 | found: | ||
461 | mutex_lock(&sysfs_lock); | ||
462 | |||
463 | if (!test_bit(FLAG_EXPORT, &desc->flags)) | ||
464 | status = -EIO; | ||
465 | else { | ||
466 | status = gpio_setup_irq(desc, dev, trigger_types[i].flags); | ||
467 | if (!status) | ||
468 | status = size; | ||
469 | } | ||
470 | |||
471 | mutex_unlock(&sysfs_lock); | ||
472 | |||
473 | return status; | ||
474 | } | ||
475 | |||
476 | static DEVICE_ATTR(edge, 0644, gpio_edge_show, gpio_edge_store); | ||
477 | |||
291 | static const struct attribute *gpio_attrs[] = { | 478 | static const struct attribute *gpio_attrs[] = { |
292 | &dev_attr_direction.attr, | 479 | &dev_attr_direction.attr, |
293 | &dev_attr_value.attr, | 480 | &dev_attr_value.attr, |
@@ -473,7 +660,7 @@ int gpio_export(unsigned gpio, bool direction_may_change) | |||
473 | struct device *dev; | 660 | struct device *dev; |
474 | 661 | ||
475 | dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), | 662 | dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), |
476 | desc, ioname ? ioname : "gpio%d", gpio); | 663 | desc, ioname ? ioname : "gpio%d", gpio); |
477 | if (dev) { | 664 | if (dev) { |
478 | if (direction_may_change) | 665 | if (direction_may_change) |
479 | status = sysfs_create_group(&dev->kobj, | 666 | status = sysfs_create_group(&dev->kobj, |
@@ -481,6 +668,14 @@ int gpio_export(unsigned gpio, bool direction_may_change) | |||
481 | else | 668 | else |
482 | status = device_create_file(dev, | 669 | status = device_create_file(dev, |
483 | &dev_attr_value); | 670 | &dev_attr_value); |
671 | |||
672 | if (!status && gpio_to_irq(gpio) >= 0 | ||
673 | && (direction_may_change | ||
674 | || !test_bit(FLAG_IS_OUT, | ||
675 | &desc->flags))) | ||
676 | status = device_create_file(dev, | ||
677 | &dev_attr_edge); | ||
678 | |||
484 | if (status != 0) | 679 | if (status != 0) |
485 | device_unregister(dev); | 680 | device_unregister(dev); |
486 | } else | 681 | } else |
@@ -505,6 +700,51 @@ static int match_export(struct device *dev, void *data) | |||
505 | } | 700 | } |
506 | 701 | ||
507 | /** | 702 | /** |
703 | * gpio_export_link - create a sysfs link to an exported GPIO node | ||
704 | * @dev: device under which to create symlink | ||
705 | * @name: name of the symlink | ||
706 | * @gpio: gpio to create symlink to, already exported | ||
707 | * | ||
708 | * Set up a symlink from /sys/.../dev/name to /sys/class/gpio/gpioN | ||
709 | * node. Caller is responsible for unlinking. | ||
710 | * | ||
711 | * Returns zero on success, else an error. | ||
712 | */ | ||
713 | int gpio_export_link(struct device *dev, const char *name, unsigned gpio) | ||
714 | { | ||
715 | struct gpio_desc *desc; | ||
716 | int status = -EINVAL; | ||
717 | |||
718 | if (!gpio_is_valid(gpio)) | ||
719 | goto done; | ||
720 | |||
721 | mutex_lock(&sysfs_lock); | ||
722 | |||
723 | desc = &gpio_desc[gpio]; | ||
724 | |||
725 | if (test_bit(FLAG_EXPORT, &desc->flags)) { | ||
726 | struct device *tdev; | ||
727 | |||
728 | tdev = class_find_device(&gpio_class, NULL, desc, match_export); | ||
729 | if (tdev != NULL) { | ||
730 | status = sysfs_create_link(&dev->kobj, &tdev->kobj, | ||
731 | name); | ||
732 | } else { | ||
733 | status = -ENODEV; | ||
734 | } | ||
735 | } | ||
736 | |||
737 | mutex_unlock(&sysfs_lock); | ||
738 | |||
739 | done: | ||
740 | if (status) | ||
741 | pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); | ||
742 | |||
743 | return status; | ||
744 | } | ||
745 | EXPORT_SYMBOL_GPL(gpio_export_link); | ||
746 | |||
747 | /** | ||
508 | * gpio_unexport - reverse effect of gpio_export() | 748 | * gpio_unexport - reverse effect of gpio_export() |
509 | * @gpio: gpio to make unavailable | 749 | * @gpio: gpio to make unavailable |
510 | * | 750 | * |
@@ -527,6 +767,7 @@ void gpio_unexport(unsigned gpio) | |||
527 | 767 | ||
528 | dev = class_find_device(&gpio_class, NULL, desc, match_export); | 768 | dev = class_find_device(&gpio_class, NULL, desc, match_export); |
529 | if (dev) { | 769 | if (dev) { |
770 | gpio_setup_irq(desc, dev, 0); | ||
530 | clear_bit(FLAG_EXPORT, &desc->flags); | 771 | clear_bit(FLAG_EXPORT, &desc->flags); |
531 | put_device(dev); | 772 | put_device(dev); |
532 | device_unregister(dev); | 773 | device_unregister(dev); |
@@ -611,6 +852,8 @@ static int __init gpiolib_sysfs_init(void) | |||
611 | unsigned long flags; | 852 | unsigned long flags; |
612 | unsigned gpio; | 853 | unsigned gpio; |
613 | 854 | ||
855 | idr_init(&pdesc_idr); | ||
856 | |||
614 | status = class_register(&gpio_class); | 857 | status = class_register(&gpio_class); |
615 | if (status < 0) | 858 | if (status < 0) |
616 | return status; | 859 | return status; |
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c new file mode 100644 index 000000000000..5711ce5353c6 --- /dev/null +++ b/drivers/gpio/langwell_gpio.c | |||
@@ -0,0 +1,297 @@ | |||
1 | /* langwell_gpio.c Moorestown platform Langwell chip GPIO driver | ||
2 | * Copyright (c) 2008 - 2009, Intel Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
16 | */ | ||
17 | |||
18 | /* Supports: | ||
19 | * Moorestown platform Langwell chip. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/pci.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/stddef.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/irq.h> | ||
30 | #include <linux/io.h> | ||
31 | #include <linux/gpio.h> | ||
32 | |||
33 | struct lnw_gpio_register { | ||
34 | u32 GPLR[2]; | ||
35 | u32 GPDR[2]; | ||
36 | u32 GPSR[2]; | ||
37 | u32 GPCR[2]; | ||
38 | u32 GRER[2]; | ||
39 | u32 GFER[2]; | ||
40 | u32 GEDR[2]; | ||
41 | }; | ||
42 | |||
43 | struct lnw_gpio { | ||
44 | struct gpio_chip chip; | ||
45 | struct lnw_gpio_register *reg_base; | ||
46 | spinlock_t lock; | ||
47 | unsigned irq_base; | ||
48 | }; | ||
49 | |||
50 | static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
51 | { | ||
52 | struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); | ||
53 | u8 reg = offset / 32; | ||
54 | void __iomem *gplr; | ||
55 | |||
56 | gplr = (void __iomem *)(&lnw->reg_base->GPLR[reg]); | ||
57 | return readl(gplr) & BIT(offset % 32); | ||
58 | } | ||
59 | |||
60 | static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
61 | { | ||
62 | struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); | ||
63 | u8 reg = offset / 32; | ||
64 | void __iomem *gpsr, *gpcr; | ||
65 | |||
66 | if (value) { | ||
67 | gpsr = (void __iomem *)(&lnw->reg_base->GPSR[reg]); | ||
68 | writel(BIT(offset % 32), gpsr); | ||
69 | } else { | ||
70 | gpcr = (void __iomem *)(&lnw->reg_base->GPCR[reg]); | ||
71 | writel(BIT(offset % 32), gpcr); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
76 | { | ||
77 | struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); | ||
78 | u8 reg = offset / 32; | ||
79 | u32 value; | ||
80 | unsigned long flags; | ||
81 | void __iomem *gpdr; | ||
82 | |||
83 | gpdr = (void __iomem *)(&lnw->reg_base->GPDR[reg]); | ||
84 | spin_lock_irqsave(&lnw->lock, flags); | ||
85 | value = readl(gpdr); | ||
86 | value &= ~BIT(offset % 32); | ||
87 | writel(value, gpdr); | ||
88 | spin_unlock_irqrestore(&lnw->lock, flags); | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static int lnw_gpio_direction_output(struct gpio_chip *chip, | ||
93 | unsigned offset, int value) | ||
94 | { | ||
95 | struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); | ||
96 | u8 reg = offset / 32; | ||
97 | unsigned long flags; | ||
98 | void __iomem *gpdr; | ||
99 | |||
100 | lnw_gpio_set(chip, offset, value); | ||
101 | gpdr = (void __iomem *)(&lnw->reg_base->GPDR[reg]); | ||
102 | spin_lock_irqsave(&lnw->lock, flags); | ||
103 | value = readl(gpdr); | ||
104 | value |= BIT(offset % 32);; | ||
105 | writel(value, gpdr); | ||
106 | spin_unlock_irqrestore(&lnw->lock, flags); | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
111 | { | ||
112 | struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); | ||
113 | return lnw->irq_base + offset; | ||
114 | } | ||
115 | |||
116 | static int lnw_irq_type(unsigned irq, unsigned type) | ||
117 | { | ||
118 | struct lnw_gpio *lnw = get_irq_chip_data(irq); | ||
119 | u32 gpio = irq - lnw->irq_base; | ||
120 | u8 reg = gpio / 32; | ||
121 | unsigned long flags; | ||
122 | u32 value; | ||
123 | void __iomem *grer = (void __iomem *)(&lnw->reg_base->GRER[reg]); | ||
124 | void __iomem *gfer = (void __iomem *)(&lnw->reg_base->GFER[reg]); | ||
125 | |||
126 | if (gpio < 0 || gpio > lnw->chip.ngpio) | ||
127 | return -EINVAL; | ||
128 | spin_lock_irqsave(&lnw->lock, flags); | ||
129 | if (type & IRQ_TYPE_EDGE_RISING) | ||
130 | value = readl(grer) | BIT(gpio % 32); | ||
131 | else | ||
132 | value = readl(grer) & (~BIT(gpio % 32)); | ||
133 | writel(value, grer); | ||
134 | |||
135 | if (type & IRQ_TYPE_EDGE_FALLING) | ||
136 | value = readl(gfer) | BIT(gpio % 32); | ||
137 | else | ||
138 | value = readl(gfer) & (~BIT(gpio % 32)); | ||
139 | writel(value, gfer); | ||
140 | spin_unlock_irqrestore(&lnw->lock, flags); | ||
141 | |||
142 | return 0; | ||
143 | }; | ||
144 | |||
145 | static void lnw_irq_unmask(unsigned irq) | ||
146 | { | ||
147 | struct lnw_gpio *lnw = get_irq_chip_data(irq); | ||
148 | u32 gpio = irq - lnw->irq_base; | ||
149 | u8 reg = gpio / 32; | ||
150 | void __iomem *gedr; | ||
151 | |||
152 | gedr = (void __iomem *)(&lnw->reg_base->GEDR[reg]); | ||
153 | writel(BIT(gpio % 32), gedr); | ||
154 | }; | ||
155 | |||
156 | static void lnw_irq_mask(unsigned irq) | ||
157 | { | ||
158 | }; | ||
159 | |||
160 | static struct irq_chip lnw_irqchip = { | ||
161 | .name = "LNW-GPIO", | ||
162 | .mask = lnw_irq_mask, | ||
163 | .unmask = lnw_irq_unmask, | ||
164 | .set_type = lnw_irq_type, | ||
165 | }; | ||
166 | |||
167 | static struct pci_device_id lnw_gpio_ids[] = { | ||
168 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f) }, | ||
169 | { 0, } | ||
170 | }; | ||
171 | MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); | ||
172 | |||
173 | static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) | ||
174 | { | ||
175 | struct lnw_gpio *lnw = (struct lnw_gpio *)get_irq_data(irq); | ||
176 | u32 reg, gpio; | ||
177 | void __iomem *gedr; | ||
178 | u32 gedr_v; | ||
179 | |||
180 | /* check GPIO controller to check which pin triggered the interrupt */ | ||
181 | for (reg = 0; reg < lnw->chip.ngpio / 32; reg++) { | ||
182 | gedr = (void __iomem *)(&lnw->reg_base->GEDR[reg]); | ||
183 | gedr_v = readl(gedr); | ||
184 | if (!gedr_v) | ||
185 | continue; | ||
186 | for (gpio = reg*32; gpio < reg*32+32; gpio++) { | ||
187 | gedr_v = readl(gedr); | ||
188 | if (gedr_v & BIT(gpio % 32)) { | ||
189 | pr_debug("pin %d triggered\n", gpio); | ||
190 | generic_handle_irq(lnw->irq_base + gpio); | ||
191 | } | ||
192 | } | ||
193 | /* clear the edge detect status bit */ | ||
194 | writel(gedr_v, gedr); | ||
195 | } | ||
196 | desc->chip->eoi(irq); | ||
197 | } | ||
198 | |||
199 | static int __devinit lnw_gpio_probe(struct pci_dev *pdev, | ||
200 | const struct pci_device_id *id) | ||
201 | { | ||
202 | void *base; | ||
203 | int i; | ||
204 | resource_size_t start, len; | ||
205 | struct lnw_gpio *lnw; | ||
206 | u32 irq_base; | ||
207 | u32 gpio_base; | ||
208 | int retval = 0; | ||
209 | |||
210 | retval = pci_enable_device(pdev); | ||
211 | if (retval) | ||
212 | goto done; | ||
213 | |||
214 | retval = pci_request_regions(pdev, "langwell_gpio"); | ||
215 | if (retval) { | ||
216 | dev_err(&pdev->dev, "error requesting resources\n"); | ||
217 | goto err2; | ||
218 | } | ||
219 | /* get the irq_base from bar1 */ | ||
220 | start = pci_resource_start(pdev, 1); | ||
221 | len = pci_resource_len(pdev, 1); | ||
222 | base = ioremap_nocache(start, len); | ||
223 | if (!base) { | ||
224 | dev_err(&pdev->dev, "error mapping bar1\n"); | ||
225 | goto err3; | ||
226 | } | ||
227 | irq_base = *(u32 *)base; | ||
228 | gpio_base = *((u32 *)base + 1); | ||
229 | /* release the IO mapping, since we already get the info from bar1 */ | ||
230 | iounmap(base); | ||
231 | /* get the register base from bar0 */ | ||
232 | start = pci_resource_start(pdev, 0); | ||
233 | len = pci_resource_len(pdev, 0); | ||
234 | base = ioremap_nocache(start, len); | ||
235 | if (!base) { | ||
236 | dev_err(&pdev->dev, "error mapping bar0\n"); | ||
237 | retval = -EFAULT; | ||
238 | goto err3; | ||
239 | } | ||
240 | |||
241 | lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL); | ||
242 | if (!lnw) { | ||
243 | dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n"); | ||
244 | retval = -ENOMEM; | ||
245 | goto err4; | ||
246 | } | ||
247 | lnw->reg_base = base; | ||
248 | lnw->irq_base = irq_base; | ||
249 | lnw->chip.label = dev_name(&pdev->dev); | ||
250 | lnw->chip.direction_input = lnw_gpio_direction_input; | ||
251 | lnw->chip.direction_output = lnw_gpio_direction_output; | ||
252 | lnw->chip.get = lnw_gpio_get; | ||
253 | lnw->chip.set = lnw_gpio_set; | ||
254 | lnw->chip.to_irq = lnw_gpio_to_irq; | ||
255 | lnw->chip.base = gpio_base; | ||
256 | lnw->chip.ngpio = 64; | ||
257 | lnw->chip.can_sleep = 0; | ||
258 | pci_set_drvdata(pdev, lnw); | ||
259 | retval = gpiochip_add(&lnw->chip); | ||
260 | if (retval) { | ||
261 | dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval); | ||
262 | goto err5; | ||
263 | } | ||
264 | set_irq_data(pdev->irq, lnw); | ||
265 | set_irq_chained_handler(pdev->irq, lnw_irq_handler); | ||
266 | for (i = 0; i < lnw->chip.ngpio; i++) { | ||
267 | set_irq_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip, | ||
268 | handle_simple_irq, "demux"); | ||
269 | set_irq_chip_data(i + lnw->irq_base, lnw); | ||
270 | } | ||
271 | |||
272 | spin_lock_init(&lnw->lock); | ||
273 | goto done; | ||
274 | err5: | ||
275 | kfree(lnw); | ||
276 | err4: | ||
277 | iounmap(base); | ||
278 | err3: | ||
279 | pci_release_regions(pdev); | ||
280 | err2: | ||
281 | pci_disable_device(pdev); | ||
282 | done: | ||
283 | return retval; | ||
284 | } | ||
285 | |||
286 | static struct pci_driver lnw_gpio_driver = { | ||
287 | .name = "langwell_gpio", | ||
288 | .id_table = lnw_gpio_ids, | ||
289 | .probe = lnw_gpio_probe, | ||
290 | }; | ||
291 | |||
292 | static int __init lnw_gpio_init(void) | ||
293 | { | ||
294 | return pci_register_driver(&lnw_gpio_driver); | ||
295 | } | ||
296 | |||
297 | device_initcall(lnw_gpio_init); | ||
diff --git a/drivers/gpio/max7301.c b/drivers/gpio/max7301.c index 7b82eaae2621..480956f1ca50 100644 --- a/drivers/gpio/max7301.c +++ b/drivers/gpio/max7301.c | |||
@@ -339,3 +339,4 @@ module_exit(max7301_exit); | |||
339 | MODULE_AUTHOR("Juergen Beisert"); | 339 | MODULE_AUTHOR("Juergen Beisert"); |
340 | MODULE_LICENSE("GPL v2"); | 340 | MODULE_LICENSE("GPL v2"); |
341 | MODULE_DESCRIPTION("MAX7301 SPI based GPIO-Expander"); | 341 | MODULE_DESCRIPTION("MAX7301 SPI based GPIO-Expander"); |
342 | MODULE_ALIAS("spi:" DRIVER_NAME); | ||
diff --git a/drivers/gpio/mc33880.c b/drivers/gpio/mc33880.c new file mode 100644 index 000000000000..e7d01bd8fdb3 --- /dev/null +++ b/drivers/gpio/mc33880.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * mc33880.c MC33880 high-side/low-side switch GPIO driver | ||
3 | * Copyright (c) 2009 Intel Corporation | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | /* Supports: | ||
20 | * Freescale MC33880 high-side/low-side switch | ||
21 | */ | ||
22 | |||
23 | #include <linux/init.h> | ||
24 | #include <linux/mutex.h> | ||
25 | #include <linux/spi/spi.h> | ||
26 | #include <linux/spi/mc33880.h> | ||
27 | #include <linux/gpio.h> | ||
28 | |||
29 | #define DRIVER_NAME "mc33880" | ||
30 | |||
31 | /* | ||
32 | * Pin configurations, see MAX7301 datasheet page 6 | ||
33 | */ | ||
34 | #define PIN_CONFIG_MASK 0x03 | ||
35 | #define PIN_CONFIG_IN_PULLUP 0x03 | ||
36 | #define PIN_CONFIG_IN_WO_PULLUP 0x02 | ||
37 | #define PIN_CONFIG_OUT 0x01 | ||
38 | |||
39 | #define PIN_NUMBER 8 | ||
40 | |||
41 | |||
42 | /* | ||
43 | * Some registers must be read back to modify. | ||
44 | * To save time we cache them here in memory | ||
45 | */ | ||
46 | struct mc33880 { | ||
47 | struct mutex lock; /* protect from simultanous accesses */ | ||
48 | u8 port_config; | ||
49 | struct gpio_chip chip; | ||
50 | struct spi_device *spi; | ||
51 | }; | ||
52 | |||
53 | static int mc33880_write_config(struct mc33880 *mc) | ||
54 | { | ||
55 | return spi_write(mc->spi, &mc->port_config, sizeof(mc->port_config)); | ||
56 | } | ||
57 | |||
58 | |||
59 | static int __mc33880_set(struct mc33880 *mc, unsigned offset, int value) | ||
60 | { | ||
61 | if (value) | ||
62 | mc->port_config |= 1 << offset; | ||
63 | else | ||
64 | mc->port_config &= ~(1 << offset); | ||
65 | |||
66 | return mc33880_write_config(mc); | ||
67 | } | ||
68 | |||
69 | |||
70 | static void mc33880_set(struct gpio_chip *chip, unsigned offset, int value) | ||
71 | { | ||
72 | struct mc33880 *mc = container_of(chip, struct mc33880, chip); | ||
73 | |||
74 | mutex_lock(&mc->lock); | ||
75 | |||
76 | __mc33880_set(mc, offset, value); | ||
77 | |||
78 | mutex_unlock(&mc->lock); | ||
79 | } | ||
80 | |||
81 | static int __devinit mc33880_probe(struct spi_device *spi) | ||
82 | { | ||
83 | struct mc33880 *mc; | ||
84 | struct mc33880_platform_data *pdata; | ||
85 | int ret; | ||
86 | |||
87 | pdata = spi->dev.platform_data; | ||
88 | if (!pdata || !pdata->base) { | ||
89 | dev_dbg(&spi->dev, "incorrect or missing platform data\n"); | ||
90 | return -EINVAL; | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * bits_per_word cannot be configured in platform data | ||
95 | */ | ||
96 | spi->bits_per_word = 8; | ||
97 | |||
98 | ret = spi_setup(spi); | ||
99 | if (ret < 0) | ||
100 | return ret; | ||
101 | |||
102 | mc = kzalloc(sizeof(struct mc33880), GFP_KERNEL); | ||
103 | if (!mc) | ||
104 | return -ENOMEM; | ||
105 | |||
106 | mutex_init(&mc->lock); | ||
107 | |||
108 | dev_set_drvdata(&spi->dev, mc); | ||
109 | |||
110 | mc->spi = spi; | ||
111 | |||
112 | mc->chip.label = DRIVER_NAME, | ||
113 | mc->chip.set = mc33880_set; | ||
114 | mc->chip.base = pdata->base; | ||
115 | mc->chip.ngpio = PIN_NUMBER; | ||
116 | mc->chip.can_sleep = 1; | ||
117 | mc->chip.dev = &spi->dev; | ||
118 | mc->chip.owner = THIS_MODULE; | ||
119 | |||
120 | mc->port_config = 0x00; | ||
121 | /* write twice, because during initialisation the first setting | ||
122 | * is just for testing SPI communication, and the second is the | ||
123 | * "real" configuration | ||
124 | */ | ||
125 | ret = mc33880_write_config(mc); | ||
126 | mc->port_config = 0x00; | ||
127 | if (!ret) | ||
128 | ret = mc33880_write_config(mc); | ||
129 | |||
130 | if (ret) { | ||
131 | printk(KERN_ERR "Failed writing to " DRIVER_NAME ": %d\n", ret); | ||
132 | goto exit_destroy; | ||
133 | } | ||
134 | |||
135 | ret = gpiochip_add(&mc->chip); | ||
136 | if (ret) | ||
137 | goto exit_destroy; | ||
138 | |||
139 | return ret; | ||
140 | |||
141 | exit_destroy: | ||
142 | dev_set_drvdata(&spi->dev, NULL); | ||
143 | mutex_destroy(&mc->lock); | ||
144 | kfree(mc); | ||
145 | return ret; | ||
146 | } | ||
147 | |||
148 | static int mc33880_remove(struct spi_device *spi) | ||
149 | { | ||
150 | struct mc33880 *mc; | ||
151 | int ret; | ||
152 | |||
153 | mc = dev_get_drvdata(&spi->dev); | ||
154 | if (mc == NULL) | ||
155 | return -ENODEV; | ||
156 | |||
157 | dev_set_drvdata(&spi->dev, NULL); | ||
158 | |||
159 | ret = gpiochip_remove(&mc->chip); | ||
160 | if (!ret) { | ||
161 | mutex_destroy(&mc->lock); | ||
162 | kfree(mc); | ||
163 | } else | ||
164 | dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n", | ||
165 | ret); | ||
166 | |||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | static struct spi_driver mc33880_driver = { | ||
171 | .driver = { | ||
172 | .name = DRIVER_NAME, | ||
173 | .owner = THIS_MODULE, | ||
174 | }, | ||
175 | .probe = mc33880_probe, | ||
176 | .remove = __devexit_p(mc33880_remove), | ||
177 | }; | ||
178 | |||
179 | static int __init mc33880_init(void) | ||
180 | { | ||
181 | return spi_register_driver(&mc33880_driver); | ||
182 | } | ||
183 | /* register after spi postcore initcall and before | ||
184 | * subsys initcalls that may rely on these GPIOs | ||
185 | */ | ||
186 | subsys_initcall(mc33880_init); | ||
187 | |||
188 | static void __exit mc33880_exit(void) | ||
189 | { | ||
190 | spi_unregister_driver(&mc33880_driver); | ||
191 | } | ||
192 | module_exit(mc33880_exit); | ||
193 | |||
194 | MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>"); | ||
195 | MODULE_LICENSE("GPL v2"); | ||
196 | |||
diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c index f6fae0e50e65..cd651ec8d034 100644 --- a/drivers/gpio/mcp23s08.c +++ b/drivers/gpio/mcp23s08.c | |||
@@ -6,12 +6,10 @@ | |||
6 | #include <linux/device.h> | 6 | #include <linux/device.h> |
7 | #include <linux/workqueue.h> | 7 | #include <linux/workqueue.h> |
8 | #include <linux/mutex.h> | 8 | #include <linux/mutex.h> |
9 | 9 | #include <linux/gpio.h> | |
10 | #include <linux/spi/spi.h> | 10 | #include <linux/spi/spi.h> |
11 | #include <linux/spi/mcp23s08.h> | 11 | #include <linux/spi/mcp23s08.h> |
12 | 12 | ||
13 | #include <asm/gpio.h> | ||
14 | |||
15 | 13 | ||
16 | /* Registers are all 8 bits wide. | 14 | /* Registers are all 8 bits wide. |
17 | * | 15 | * |
@@ -433,3 +431,4 @@ static void __exit mcp23s08_exit(void) | |||
433 | module_exit(mcp23s08_exit); | 431 | module_exit(mcp23s08_exit); |
434 | 432 | ||
435 | MODULE_LICENSE("GPL"); | 433 | MODULE_LICENSE("GPL"); |
434 | MODULE_ALIAS("spi:mcp23s08"); | ||
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index cdb6574d25a6..6a2fb3fbb3d9 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/gpio.h> | ||
16 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
17 | #include <linux/i2c/pca953x.h> | 18 | #include <linux/i2c/pca953x.h> |
18 | #ifdef CONFIG_OF_GPIO | 19 | #ifdef CONFIG_OF_GPIO |
@@ -20,8 +21,6 @@ | |||
20 | #include <linux/of_gpio.h> | 21 | #include <linux/of_gpio.h> |
21 | #endif | 22 | #endif |
22 | 23 | ||
23 | #include <asm/gpio.h> | ||
24 | |||
25 | #define PCA953X_INPUT 0 | 24 | #define PCA953X_INPUT 0 |
26 | #define PCA953X_OUTPUT 1 | 25 | #define PCA953X_OUTPUT 1 |
27 | #define PCA953X_INVERT 2 | 26 | #define PCA953X_INVERT 2 |
@@ -40,6 +39,7 @@ static const struct i2c_device_id pca953x_id[] = { | |||
40 | { "pca9557", 8, }, | 39 | { "pca9557", 8, }, |
41 | 40 | ||
42 | { "max7310", 8, }, | 41 | { "max7310", 8, }, |
42 | { "max7315", 8, }, | ||
43 | { "pca6107", 8, }, | 43 | { "pca6107", 8, }, |
44 | { "tca6408", 8, }, | 44 | { "tca6408", 8, }, |
45 | { "tca6416", 16, }, | 45 | { "tca6416", 16, }, |
diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c index 9525724be731..29f19ce3e80f 100644 --- a/drivers/gpio/pcf857x.c +++ b/drivers/gpio/pcf857x.c | |||
@@ -20,14 +20,14 @@ | |||
20 | 20 | ||
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/gpio.h> | ||
23 | #include <linux/i2c.h> | 24 | #include <linux/i2c.h> |
24 | #include <linux/i2c/pcf857x.h> | 25 | #include <linux/i2c/pcf857x.h> |
25 | 26 | ||
26 | #include <asm/gpio.h> | ||
27 | |||
28 | 27 | ||
29 | static const struct i2c_device_id pcf857x_id[] = { | 28 | static const struct i2c_device_id pcf857x_id[] = { |
30 | { "pcf8574", 8 }, | 29 | { "pcf8574", 8 }, |
30 | { "pcf8574a", 8 }, | ||
31 | { "pca8574", 8 }, | 31 | { "pca8574", 8 }, |
32 | { "pca9670", 8 }, | 32 | { "pca9670", 8 }, |
33 | { "pca9672", 8 }, | 33 | { "pca9672", 8 }, |
diff --git a/drivers/gpio/ucb1400_gpio.c b/drivers/gpio/ucb1400_gpio.c new file mode 100644 index 000000000000..50e6bd1392ce --- /dev/null +++ b/drivers/gpio/ucb1400_gpio.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * Philips UCB1400 GPIO driver | ||
3 | * | ||
4 | * Author: Marek Vasut <marek.vasut@gmail.com> | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/ucb1400.h> | ||
14 | |||
15 | struct ucb1400_gpio_data *ucbdata; | ||
16 | |||
17 | static int ucb1400_gpio_dir_in(struct gpio_chip *gc, unsigned off) | ||
18 | { | ||
19 | struct ucb1400_gpio *gpio; | ||
20 | gpio = container_of(gc, struct ucb1400_gpio, gc); | ||
21 | ucb1400_gpio_set_direction(gpio->ac97, off, 0); | ||
22 | return 0; | ||
23 | } | ||
24 | |||
25 | static int ucb1400_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val) | ||
26 | { | ||
27 | struct ucb1400_gpio *gpio; | ||
28 | gpio = container_of(gc, struct ucb1400_gpio, gc); | ||
29 | ucb1400_gpio_set_direction(gpio->ac97, off, 1); | ||
30 | ucb1400_gpio_set_value(gpio->ac97, off, val); | ||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | static int ucb1400_gpio_get(struct gpio_chip *gc, unsigned off) | ||
35 | { | ||
36 | struct ucb1400_gpio *gpio; | ||
37 | gpio = container_of(gc, struct ucb1400_gpio, gc); | ||
38 | return ucb1400_gpio_get_value(gpio->ac97, off); | ||
39 | } | ||
40 | |||
41 | static void ucb1400_gpio_set(struct gpio_chip *gc, unsigned off, int val) | ||
42 | { | ||
43 | struct ucb1400_gpio *gpio; | ||
44 | gpio = container_of(gc, struct ucb1400_gpio, gc); | ||
45 | ucb1400_gpio_set_value(gpio->ac97, off, val); | ||
46 | } | ||
47 | |||
48 | static int ucb1400_gpio_probe(struct platform_device *dev) | ||
49 | { | ||
50 | struct ucb1400_gpio *ucb = dev->dev.platform_data; | ||
51 | int err = 0; | ||
52 | |||
53 | if (!(ucbdata && ucbdata->gpio_offset)) { | ||
54 | err = -EINVAL; | ||
55 | goto err; | ||
56 | } | ||
57 | |||
58 | platform_set_drvdata(dev, ucb); | ||
59 | |||
60 | ucb->gc.label = "ucb1400_gpio"; | ||
61 | ucb->gc.base = ucbdata->gpio_offset; | ||
62 | ucb->gc.ngpio = 10; | ||
63 | ucb->gc.owner = THIS_MODULE; | ||
64 | |||
65 | ucb->gc.direction_input = ucb1400_gpio_dir_in; | ||
66 | ucb->gc.direction_output = ucb1400_gpio_dir_out; | ||
67 | ucb->gc.get = ucb1400_gpio_get; | ||
68 | ucb->gc.set = ucb1400_gpio_set; | ||
69 | ucb->gc.can_sleep = 1; | ||
70 | |||
71 | err = gpiochip_add(&ucb->gc); | ||
72 | if (err) | ||
73 | goto err; | ||
74 | |||
75 | if (ucbdata && ucbdata->gpio_setup) | ||
76 | err = ucbdata->gpio_setup(&dev->dev, ucb->gc.ngpio); | ||
77 | |||
78 | err: | ||
79 | return err; | ||
80 | |||
81 | } | ||
82 | |||
83 | static int ucb1400_gpio_remove(struct platform_device *dev) | ||
84 | { | ||
85 | int err = 0; | ||
86 | struct ucb1400_gpio *ucb = platform_get_drvdata(dev); | ||
87 | |||
88 | if (ucbdata && ucbdata->gpio_teardown) { | ||
89 | err = ucbdata->gpio_teardown(&dev->dev, ucb->gc.ngpio); | ||
90 | if (err) | ||
91 | return err; | ||
92 | } | ||
93 | |||
94 | err = gpiochip_remove(&ucb->gc); | ||
95 | return err; | ||
96 | } | ||
97 | |||
98 | static struct platform_driver ucb1400_gpio_driver = { | ||
99 | .probe = ucb1400_gpio_probe, | ||
100 | .remove = ucb1400_gpio_remove, | ||
101 | .driver = { | ||
102 | .name = "ucb1400_gpio" | ||
103 | }, | ||
104 | }; | ||
105 | |||
106 | static int __init ucb1400_gpio_init(void) | ||
107 | { | ||
108 | return platform_driver_register(&ucb1400_gpio_driver); | ||
109 | } | ||
110 | |||
111 | static void __exit ucb1400_gpio_exit(void) | ||
112 | { | ||
113 | platform_driver_unregister(&ucb1400_gpio_driver); | ||
114 | } | ||
115 | |||
116 | void __init ucb1400_gpio_set_data(struct ucb1400_gpio_data *data) | ||
117 | { | ||
118 | ucbdata = data; | ||
119 | } | ||
120 | |||
121 | module_init(ucb1400_gpio_init); | ||
122 | module_exit(ucb1400_gpio_exit); | ||
123 | |||
124 | MODULE_DESCRIPTION("Philips UCB1400 GPIO driver"); | ||
125 | MODULE_LICENSE("GPL"); | ||