diff options
author | Olof Johansson <olof@lixom.net> | 2012-11-21 12:39:13 -0500 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2012-11-21 12:39:13 -0500 |
commit | cab18d19bb05452fc7f5c45f7964643bdae80c92 (patch) | |
tree | 05069dedf6d4f1d2f77500e35d2e8abad42de164 | |
parent | c3e5dba4ee862a23c9f2273b9ddd492047cbfb15 (diff) | |
parent | 2cad6a8a4c31175578943f087e1dbef9f52e6ec3 (diff) |
Merge branch 'depends/gpio-devel' into next/soc
This is required for some of the clps711x series, so we're bringing in
the dependency explicitly.
By Linus Walleij (5) and others
via Linus Walleij
* depends/gpio-devel:
GPIO: clps711x: use platform_device_unregister in gpio_clps711x_init()
gpio/tc3589x: convert to use the simple irqdomain
gpio/em: convert to linear IRQ domain
gpio/mvebu: convert to use irq_domain_add_simple()
gpio/tegra: convert to use linear irqdomain
gpiolib: unlock on error in gpio_export()
gpiolib: add gpio get direction callback support
GPIO: clps711x: Fix direction logic for PORTD
GPIO: clps711x: Fix return value for gpio_clps711x_get
gpiolib: Refactor gpio_export
GPIO: vt8500: Add extended gpio bank for WM8505/WM8650
gpio: clps711x: delete local <mach/gpio.h> header
GPIO: Add support for GPIO on CLPS711X-target platform
DA9055 GPIO driver
gpio/gpio-omap: Use existing pointer to struct device
gpio/gpio-pl061: Covert to use devm_* functions
Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r-- | arch/arm/Kconfig | 2 | ||||
-rw-r--r-- | drivers/gpio/Kconfig | 15 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 2 | ||||
-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 | 46 | ||||
-rw-r--r-- | drivers/gpio/gpio-mvebu.c | 4 | ||||
-rw-r--r-- | drivers/gpio/gpio-omap.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-pl061.c | 59 | ||||
-rw-r--r-- | drivers/gpio/gpio-tc3589x.c | 20 | ||||
-rw-r--r-- | drivers/gpio/gpio-tegra.c | 14 | ||||
-rw-r--r-- | drivers/gpio/gpio-vt8500.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 124 | ||||
-rw-r--r-- | include/asm-generic/gpio.h | 5 |
14 files changed, 558 insertions, 140 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 69d2844dd507..7441ebdf25f8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -367,6 +367,8 @@ config ARCH_CNS3XXX | |||
367 | 367 | ||
368 | config ARCH_CLPS711X | 368 | config ARCH_CLPS711X |
369 | bool "Cirrus Logic CLPS711x/EP721x/EP731x-based" | 369 | bool "Cirrus Logic CLPS711x/EP721x/EP731x-based" |
370 | select ARCH_REQUIRE_GPIOLIB | ||
371 | select ARCH_USES_GETTIMEOFFSET | ||
370 | select CLKDEV_LOOKUP | 372 | select CLKDEV_LOOKUP |
371 | select COMMON_CLK | 373 | select COMMON_CLK |
372 | select CPU_ARM720T | 374 | select CPU_ARM720T |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f11d8e3b4041..12b0a25a7822 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -86,11 +86,26 @@ config GPIO_DA9052 | |||
86 | help | 86 | help |
87 | Say yes here to enable the GPIO driver for the DA9052 chip. | 87 | Say yes here to enable the GPIO driver for the DA9052 chip. |
88 | 88 | ||
89 | config GPIO_DA9055 | ||
90 | tristate "Dialog Semiconductor DA9055 GPIO" | ||
91 | depends on MFD_DA9055 | ||
92 | help | ||
93 | Say yes here to enable the GPIO driver for the DA9055 chip. | ||
94 | |||
95 | The Dialog DA9055 PMIC chip has 3 GPIO pins that can be | ||
96 | be controller by this driver. | ||
97 | |||
98 | If driver is built as a module it will be called gpio-da9055. | ||
99 | |||
89 | config GPIO_MAX730X | 100 | config GPIO_MAX730X |
90 | tristate | 101 | tristate |
91 | 102 | ||
92 | comment "Memory mapped GPIO drivers:" | 103 | comment "Memory mapped GPIO drivers:" |
93 | 104 | ||
105 | config GPIO_CLPS711X | ||
106 | def_bool y | ||
107 | depends on ARCH_CLPS711X | ||
108 | |||
94 | config GPIO_GENERIC_PLATFORM | 109 | config GPIO_GENERIC_PLATFORM |
95 | tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" | 110 | tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" |
96 | select GPIO_GENERIC | 111 | select GPIO_GENERIC |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 9aeed6707326..1c1b63fcaeb3 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -16,8 +16,10 @@ obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o | |||
16 | obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o | 16 | obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o |
17 | obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o | 17 | obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o |
18 | obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o | 18 | obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o |
19 | obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o | ||
19 | obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o | 20 | obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o |
20 | obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o | 21 | obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o |
22 | obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o | ||
21 | obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o | 23 | obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o |
22 | obj-$(CONFIG_GPIO_EM) += gpio-em.o | 24 | obj-$(CONFIG_GPIO_EM) += gpio-em.o |
23 | obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o | 25 | obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o |
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c new file mode 100644 index 000000000000..ce63b75b13f5 --- /dev/null +++ b/drivers/gpio/gpio-clps711x.c | |||
@@ -0,0 +1,199 @@ | |||
1 | /* | ||
2 | * CLPS711X GPIO driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/io.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/gpio.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/spinlock.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | |||
19 | #include <mach/hardware.h> | ||
20 | |||
21 | #define CLPS711X_GPIO_PORTS 5 | ||
22 | #define CLPS711X_GPIO_NAME "gpio-clps711x" | ||
23 | |||
24 | struct clps711x_gpio { | ||
25 | struct gpio_chip chip[CLPS711X_GPIO_PORTS]; | ||
26 | spinlock_t lock; | ||
27 | }; | ||
28 | |||
29 | static void __iomem *clps711x_ports[] = { | ||
30 | CLPS711X_VIRT_BASE + PADR, | ||
31 | CLPS711X_VIRT_BASE + PBDR, | ||
32 | CLPS711X_VIRT_BASE + PCDR, | ||
33 | CLPS711X_VIRT_BASE + PDDR, | ||
34 | CLPS711X_VIRT_BASE + PEDR, | ||
35 | }; | ||
36 | |||
37 | static void __iomem *clps711x_pdirs[] = { | ||
38 | CLPS711X_VIRT_BASE + PADDR, | ||
39 | CLPS711X_VIRT_BASE + PBDDR, | ||
40 | CLPS711X_VIRT_BASE + PCDDR, | ||
41 | CLPS711X_VIRT_BASE + PDDDR, | ||
42 | CLPS711X_VIRT_BASE + PEDDR, | ||
43 | }; | ||
44 | |||
45 | #define clps711x_port(x) clps711x_ports[x->base / 8] | ||
46 | #define clps711x_pdir(x) clps711x_pdirs[x->base / 8] | ||
47 | |||
48 | static int gpio_clps711x_get(struct gpio_chip *chip, unsigned offset) | ||
49 | { | ||
50 | return !!(readb(clps711x_port(chip)) & (1 << offset)); | ||
51 | } | ||
52 | |||
53 | static void gpio_clps711x_set(struct gpio_chip *chip, unsigned offset, | ||
54 | int value) | ||
55 | { | ||
56 | int tmp; | ||
57 | unsigned long flags; | ||
58 | struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev); | ||
59 | |||
60 | spin_lock_irqsave(&gpio->lock, flags); | ||
61 | tmp = readb(clps711x_port(chip)) & ~(1 << offset); | ||
62 | if (value) | ||
63 | tmp |= 1 << offset; | ||
64 | writeb(tmp, clps711x_port(chip)); | ||
65 | spin_unlock_irqrestore(&gpio->lock, flags); | ||
66 | } | ||
67 | |||
68 | static int gpio_clps711x_dir_in(struct gpio_chip *chip, unsigned offset) | ||
69 | { | ||
70 | int tmp; | ||
71 | unsigned long flags; | ||
72 | struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev); | ||
73 | |||
74 | spin_lock_irqsave(&gpio->lock, flags); | ||
75 | tmp = readb(clps711x_pdir(chip)) & ~(1 << offset); | ||
76 | writeb(tmp, clps711x_pdir(chip)); | ||
77 | spin_unlock_irqrestore(&gpio->lock, flags); | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int gpio_clps711x_dir_out(struct gpio_chip *chip, unsigned offset, | ||
83 | int value) | ||
84 | { | ||
85 | int tmp; | ||
86 | unsigned long flags; | ||
87 | struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev); | ||
88 | |||
89 | spin_lock_irqsave(&gpio->lock, flags); | ||
90 | tmp = readb(clps711x_pdir(chip)) | (1 << offset); | ||
91 | writeb(tmp, clps711x_pdir(chip)); | ||
92 | tmp = readb(clps711x_port(chip)) & ~(1 << offset); | ||
93 | if (value) | ||
94 | tmp |= 1 << offset; | ||
95 | writeb(tmp, clps711x_port(chip)); | ||
96 | spin_unlock_irqrestore(&gpio->lock, flags); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int gpio_clps711x_dir_in_inv(struct gpio_chip *chip, unsigned offset) | ||
102 | { | ||
103 | int tmp; | ||
104 | unsigned long flags; | ||
105 | struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev); | ||
106 | |||
107 | spin_lock_irqsave(&gpio->lock, flags); | ||
108 | tmp = readb(clps711x_pdir(chip)) | (1 << offset); | ||
109 | writeb(tmp, clps711x_pdir(chip)); | ||
110 | spin_unlock_irqrestore(&gpio->lock, flags); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int gpio_clps711x_dir_out_inv(struct gpio_chip *chip, unsigned offset, | ||
116 | int value) | ||
117 | { | ||
118 | int tmp; | ||
119 | unsigned long flags; | ||
120 | struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev); | ||
121 | |||
122 | spin_lock_irqsave(&gpio->lock, flags); | ||
123 | tmp = readb(clps711x_pdir(chip)) & ~(1 << offset); | ||
124 | writeb(tmp, clps711x_pdir(chip)); | ||
125 | tmp = readb(clps711x_port(chip)) & ~(1 << offset); | ||
126 | if (value) | ||
127 | tmp |= 1 << offset; | ||
128 | writeb(tmp, clps711x_port(chip)); | ||
129 | spin_unlock_irqrestore(&gpio->lock, flags); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static struct { | ||
135 | char *name; | ||
136 | int nr; | ||
137 | int inv_dir; | ||
138 | } clps711x_gpio_ports[] __initconst = { | ||
139 | { "PORTA", 8, 0, }, | ||
140 | { "PORTB", 8, 0, }, | ||
141 | { "PORTC", 8, 0, }, | ||
142 | { "PORTD", 8, 1, }, | ||
143 | { "PORTE", 3, 0, }, | ||
144 | }; | ||
145 | |||
146 | static int __init gpio_clps711x_init(void) | ||
147 | { | ||
148 | int i; | ||
149 | struct platform_device *pdev; | ||
150 | struct clps711x_gpio *gpio; | ||
151 | |||
152 | pdev = platform_device_alloc(CLPS711X_GPIO_NAME, 0); | ||
153 | if (!pdev) { | ||
154 | pr_err("Cannot create platform device: %s\n", | ||
155 | CLPS711X_GPIO_NAME); | ||
156 | return -ENOMEM; | ||
157 | } | ||
158 | |||
159 | platform_device_add(pdev); | ||
160 | |||
161 | gpio = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_gpio), | ||
162 | GFP_KERNEL); | ||
163 | if (!gpio) { | ||
164 | dev_err(&pdev->dev, "GPIO allocating memory error\n"); | ||
165 | platform_device_unregister(pdev); | ||
166 | return -ENOMEM; | ||
167 | } | ||
168 | |||
169 | platform_set_drvdata(pdev, gpio); | ||
170 | |||
171 | spin_lock_init(&gpio->lock); | ||
172 | |||
173 | for (i = 0; i < CLPS711X_GPIO_PORTS; i++) { | ||
174 | gpio->chip[i].owner = THIS_MODULE; | ||
175 | gpio->chip[i].dev = &pdev->dev; | ||
176 | gpio->chip[i].label = clps711x_gpio_ports[i].name; | ||
177 | gpio->chip[i].base = i * 8; | ||
178 | gpio->chip[i].ngpio = clps711x_gpio_ports[i].nr; | ||
179 | gpio->chip[i].get = gpio_clps711x_get; | ||
180 | gpio->chip[i].set = gpio_clps711x_set; | ||
181 | if (!clps711x_gpio_ports[i].inv_dir) { | ||
182 | gpio->chip[i].direction_input = gpio_clps711x_dir_in; | ||
183 | gpio->chip[i].direction_output = gpio_clps711x_dir_out; | ||
184 | } else { | ||
185 | gpio->chip[i].direction_input = gpio_clps711x_dir_in_inv; | ||
186 | gpio->chip[i].direction_output = gpio_clps711x_dir_out_inv; | ||
187 | } | ||
188 | WARN_ON(gpiochip_add(&gpio->chip[i])); | ||
189 | } | ||
190 | |||
191 | dev_info(&pdev->dev, "GPIO driver initialized\n"); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | arch_initcall(gpio_clps711x_init); | ||
196 | |||
197 | MODULE_LICENSE("GPL v2"); | ||
198 | MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); | ||
199 | MODULE_DESCRIPTION("CLPS711X GPIO driver"); | ||
diff --git a/drivers/gpio/gpio-da9055.c b/drivers/gpio/gpio-da9055.c new file mode 100644 index 000000000000..55d83c7d9c7f --- /dev/null +++ b/drivers/gpio/gpio-da9055.c | |||
@@ -0,0 +1,204 @@ | |||
1 | /* | ||
2 | * GPIO Driver for Dialog DA9055 PMICs. | ||
3 | * | ||
4 | * Copyright(c) 2012 Dialog Semiconductor Ltd. | ||
5 | * | ||
6 | * Author: David Dajun Chen <dchen@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/gpio.h> | ||
17 | |||
18 | #include <linux/mfd/da9055/core.h> | ||
19 | #include <linux/mfd/da9055/reg.h> | ||
20 | #include <linux/mfd/da9055/pdata.h> | ||
21 | |||
22 | #define DA9055_VDD_IO 0x0 | ||
23 | #define DA9055_PUSH_PULL 0x3 | ||
24 | #define DA9055_ACT_LOW 0x0 | ||
25 | #define DA9055_GPI 0x1 | ||
26 | #define DA9055_PORT_MASK 0x3 | ||
27 | #define DA9055_PORT_SHIFT(offset) (4 * (offset % 2)) | ||
28 | |||
29 | #define DA9055_INPUT DA9055_GPI | ||
30 | #define DA9055_OUTPUT DA9055_PUSH_PULL | ||
31 | #define DA9055_IRQ_GPI0 3 | ||
32 | |||
33 | struct da9055_gpio { | ||
34 | struct da9055 *da9055; | ||
35 | struct gpio_chip gp; | ||
36 | }; | ||
37 | |||
38 | static inline struct da9055_gpio *to_da9055_gpio(struct gpio_chip *chip) | ||
39 | { | ||
40 | return container_of(chip, struct da9055_gpio, gp); | ||
41 | } | ||
42 | |||
43 | static int da9055_gpio_get(struct gpio_chip *gc, unsigned offset) | ||
44 | { | ||
45 | struct da9055_gpio *gpio = to_da9055_gpio(gc); | ||
46 | int gpio_direction = 0; | ||
47 | int ret; | ||
48 | |||
49 | /* Get GPIO direction */ | ||
50 | ret = da9055_reg_read(gpio->da9055, (offset >> 1) + DA9055_REG_GPIO0_1); | ||
51 | if (ret < 0) | ||
52 | return ret; | ||
53 | |||
54 | gpio_direction = ret & (DA9055_PORT_MASK) << DA9055_PORT_SHIFT(offset); | ||
55 | gpio_direction >>= DA9055_PORT_SHIFT(offset); | ||
56 | switch (gpio_direction) { | ||
57 | case DA9055_INPUT: | ||
58 | ret = da9055_reg_read(gpio->da9055, DA9055_REG_STATUS_B); | ||
59 | if (ret < 0) | ||
60 | return ret; | ||
61 | break; | ||
62 | case DA9055_OUTPUT: | ||
63 | ret = da9055_reg_read(gpio->da9055, DA9055_REG_GPIO_MODE0_2); | ||
64 | if (ret < 0) | ||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | return ret & (1 << offset); | ||
69 | |||
70 | } | ||
71 | |||
72 | static void da9055_gpio_set(struct gpio_chip *gc, unsigned offset, int value) | ||
73 | { | ||
74 | struct da9055_gpio *gpio = to_da9055_gpio(gc); | ||
75 | |||
76 | da9055_reg_update(gpio->da9055, | ||
77 | DA9055_REG_GPIO_MODE0_2, | ||
78 | 1 << offset, | ||
79 | value << offset); | ||
80 | } | ||
81 | |||
82 | static int da9055_gpio_direction_input(struct gpio_chip *gc, unsigned offset) | ||
83 | { | ||
84 | struct da9055_gpio *gpio = to_da9055_gpio(gc); | ||
85 | unsigned char reg_byte; | ||
86 | |||
87 | reg_byte = (DA9055_ACT_LOW | DA9055_GPI) | ||
88 | << DA9055_PORT_SHIFT(offset); | ||
89 | |||
90 | return da9055_reg_update(gpio->da9055, (offset >> 1) + | ||
91 | DA9055_REG_GPIO0_1, | ||
92 | DA9055_PORT_MASK << | ||
93 | DA9055_PORT_SHIFT(offset), | ||
94 | reg_byte); | ||
95 | } | ||
96 | |||
97 | static int da9055_gpio_direction_output(struct gpio_chip *gc, | ||
98 | unsigned offset, int value) | ||
99 | { | ||
100 | struct da9055_gpio *gpio = to_da9055_gpio(gc); | ||
101 | unsigned char reg_byte; | ||
102 | int ret; | ||
103 | |||
104 | reg_byte = (DA9055_VDD_IO | DA9055_PUSH_PULL) | ||
105 | << DA9055_PORT_SHIFT(offset); | ||
106 | |||
107 | ret = da9055_reg_update(gpio->da9055, (offset >> 1) + | ||
108 | DA9055_REG_GPIO0_1, | ||
109 | DA9055_PORT_MASK << | ||
110 | DA9055_PORT_SHIFT(offset), | ||
111 | reg_byte); | ||
112 | if (ret < 0) | ||
113 | return ret; | ||
114 | |||
115 | da9055_gpio_set(gc, offset, value); | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static int da9055_gpio_to_irq(struct gpio_chip *gc, u32 offset) | ||
121 | { | ||
122 | struct da9055_gpio *gpio = to_da9055_gpio(gc); | ||
123 | struct da9055 *da9055 = gpio->da9055; | ||
124 | |||
125 | return regmap_irq_get_virq(da9055->irq_data, | ||
126 | DA9055_IRQ_GPI0 + offset); | ||
127 | } | ||
128 | |||
129 | static struct gpio_chip reference_gp __devinitdata = { | ||
130 | .label = "da9055-gpio", | ||
131 | .owner = THIS_MODULE, | ||
132 | .get = da9055_gpio_get, | ||
133 | .set = da9055_gpio_set, | ||
134 | .direction_input = da9055_gpio_direction_input, | ||
135 | .direction_output = da9055_gpio_direction_output, | ||
136 | .to_irq = da9055_gpio_to_irq, | ||
137 | .can_sleep = 1, | ||
138 | .ngpio = 3, | ||
139 | .base = -1, | ||
140 | }; | ||
141 | |||
142 | static int __devinit da9055_gpio_probe(struct platform_device *pdev) | ||
143 | { | ||
144 | struct da9055_gpio *gpio; | ||
145 | struct da9055_pdata *pdata; | ||
146 | int ret; | ||
147 | |||
148 | gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); | ||
149 | if (gpio == NULL) | ||
150 | return -ENOMEM; | ||
151 | |||
152 | gpio->da9055 = dev_get_drvdata(pdev->dev.parent); | ||
153 | pdata = gpio->da9055->dev->platform_data; | ||
154 | |||
155 | gpio->gp = reference_gp; | ||
156 | if (pdata && pdata->gpio_base) | ||
157 | gpio->gp.base = pdata->gpio_base; | ||
158 | |||
159 | ret = gpiochip_add(&gpio->gp); | ||
160 | if (ret < 0) { | ||
161 | dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); | ||
162 | goto err_mem; | ||
163 | } | ||
164 | |||
165 | platform_set_drvdata(pdev, gpio); | ||
166 | |||
167 | return 0; | ||
168 | |||
169 | err_mem: | ||
170 | return ret; | ||
171 | } | ||
172 | |||
173 | static int __devexit da9055_gpio_remove(struct platform_device *pdev) | ||
174 | { | ||
175 | struct da9055_gpio *gpio = platform_get_drvdata(pdev); | ||
176 | |||
177 | return gpiochip_remove(&gpio->gp); | ||
178 | } | ||
179 | |||
180 | static struct platform_driver da9055_gpio_driver = { | ||
181 | .probe = da9055_gpio_probe, | ||
182 | .remove = __devexit_p(da9055_gpio_remove), | ||
183 | .driver = { | ||
184 | .name = "da9055-gpio", | ||
185 | .owner = THIS_MODULE, | ||
186 | }, | ||
187 | }; | ||
188 | |||
189 | static int __init da9055_gpio_init(void) | ||
190 | { | ||
191 | return platform_driver_register(&da9055_gpio_driver); | ||
192 | } | ||
193 | subsys_initcall(da9055_gpio_init); | ||
194 | |||
195 | static void __exit da9055_gpio_exit(void) | ||
196 | { | ||
197 | platform_driver_unregister(&da9055_gpio_driver); | ||
198 | } | ||
199 | module_exit(da9055_gpio_exit); | ||
200 | |||
201 | MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); | ||
202 | MODULE_DESCRIPTION("DA9055 GPIO Device Driver"); | ||
203 | MODULE_LICENSE("GPL"); | ||
204 | MODULE_ALIAS("platform:da9055-gpio"); | ||
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index efb4c2d0d132..88bdfe37816f 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c | |||
@@ -35,7 +35,6 @@ | |||
35 | struct em_gio_priv { | 35 | struct em_gio_priv { |
36 | void __iomem *base0; | 36 | void __iomem *base0; |
37 | void __iomem *base1; | 37 | void __iomem *base1; |
38 | unsigned int irq_base; | ||
39 | spinlock_t sense_lock; | 38 | spinlock_t sense_lock; |
40 | struct platform_device *pdev; | 39 | struct platform_device *pdev; |
41 | struct gpio_chip gpio_chip; | 40 | struct gpio_chip gpio_chip; |
@@ -214,7 +213,7 @@ static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset, | |||
214 | 213 | ||
215 | static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset) | 214 | static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset) |
216 | { | 215 | { |
217 | return irq_find_mapping(gpio_to_priv(chip)->irq_domain, offset); | 216 | return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset); |
218 | } | 217 | } |
219 | 218 | ||
220 | static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq, | 219 | static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq, |
@@ -234,40 +233,6 @@ static struct irq_domain_ops em_gio_irq_domain_ops = { | |||
234 | .map = em_gio_irq_domain_map, | 233 | .map = em_gio_irq_domain_map, |
235 | }; | 234 | }; |
236 | 235 | ||
237 | static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p) | ||
238 | { | ||
239 | struct platform_device *pdev = p->pdev; | ||
240 | struct gpio_em_config *pdata = pdev->dev.platform_data; | ||
241 | |||
242 | p->irq_base = irq_alloc_descs(pdata->irq_base, 0, | ||
243 | pdata->number_of_pins, numa_node_id()); | ||
244 | if (p->irq_base < 0) { | ||
245 | dev_err(&pdev->dev, "cannot get irq_desc\n"); | ||
246 | return p->irq_base; | ||
247 | } | ||
248 | pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n", | ||
249 | pdata->gpio_base, pdata->number_of_pins, p->irq_base); | ||
250 | |||
251 | p->irq_domain = irq_domain_add_legacy(pdev->dev.of_node, | ||
252 | pdata->number_of_pins, | ||
253 | p->irq_base, 0, | ||
254 | &em_gio_irq_domain_ops, p); | ||
255 | if (!p->irq_domain) { | ||
256 | irq_free_descs(p->irq_base, pdata->number_of_pins); | ||
257 | return -ENXIO; | ||
258 | } | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static void em_gio_irq_domain_cleanup(struct em_gio_priv *p) | ||
264 | { | ||
265 | struct gpio_em_config *pdata = p->pdev->dev.platform_data; | ||
266 | |||
267 | irq_free_descs(p->irq_base, pdata->number_of_pins); | ||
268 | /* FIXME: irq domain wants to be freed! */ | ||
269 | } | ||
270 | |||
271 | static int __devinit em_gio_probe(struct platform_device *pdev) | 236 | static int __devinit em_gio_probe(struct platform_device *pdev) |
272 | { | 237 | { |
273 | struct gpio_em_config *pdata = pdev->dev.platform_data; | 238 | struct gpio_em_config *pdata = pdev->dev.platform_data; |
@@ -334,8 +299,11 @@ static int __devinit em_gio_probe(struct platform_device *pdev) | |||
334 | irq_chip->irq_set_type = em_gio_irq_set_type; | 299 | irq_chip->irq_set_type = em_gio_irq_set_type; |
335 | irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; | 300 | irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; |
336 | 301 | ||
337 | ret = em_gio_irq_domain_init(p); | 302 | p->irq_domain = irq_domain_add_linear(pdev->dev.of_node, |
338 | if (ret) { | 303 | pdata->number_of_pins, |
304 | &em_gio_irq_domain_ops, p); | ||
305 | if (!p->irq_domain) | ||
306 | err = -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: |
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index cf7afb9eb61a..4f9399a37787 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c | |||
@@ -650,8 +650,8 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev) | |||
650 | IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); | 650 | IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); |
651 | 651 | ||
652 | /* Setup irq domain on top of the generic chip. */ | 652 | /* Setup irq domain on top of the generic chip. */ |
653 | mvchip->domain = irq_domain_add_legacy(np, mvchip->chip.ngpio, | 653 | mvchip->domain = irq_domain_add_simple(np, mvchip->chip.ngpio, |
654 | mvchip->irqbase, 0, | 654 | mvchip->irqbase, |
655 | &irq_domain_simple_ops, | 655 | &irq_domain_simple_ops, |
656 | mvchip); | 656 | mvchip); |
657 | if (!mvchip->domain) { | 657 | if (!mvchip->domain) { |
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index d335af1d4d85..d71e5bdf7b97 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c | |||
@@ -1105,7 +1105,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) | |||
1105 | if (!pdata) | 1105 | if (!pdata) |
1106 | return -EINVAL; | 1106 | return -EINVAL; |
1107 | 1107 | ||
1108 | bank = devm_kzalloc(&pdev->dev, sizeof(struct gpio_bank), GFP_KERNEL); | 1108 | bank = devm_kzalloc(dev, sizeof(struct gpio_bank), GFP_KERNEL); |
1109 | if (!bank) { | 1109 | if (!bank) { |
1110 | dev_err(dev, "Memory alloc failed\n"); | 1110 | dev_err(dev, "Memory alloc failed\n"); |
1111 | return -ENOMEM; | 1111 | return -ENOMEM; |
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index b4b5da4fd2cc..31d9c9e79ea9 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c | |||
@@ -216,39 +216,34 @@ static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base) | |||
216 | IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0); | 216 | IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0); |
217 | } | 217 | } |
218 | 218 | ||
219 | static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | 219 | static int pl061_probe(struct amba_device *adev, const struct amba_id *id) |
220 | { | 220 | { |
221 | struct pl061_platform_data *pdata; | 221 | struct device *dev = &adev->dev; |
222 | struct pl061_platform_data *pdata = dev->platform_data; | ||
222 | struct pl061_gpio *chip; | 223 | struct pl061_gpio *chip; |
223 | int ret, irq, i; | 224 | int ret, irq, i; |
224 | 225 | ||
225 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 226 | chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); |
226 | if (chip == NULL) | 227 | if (chip == NULL) |
227 | return -ENOMEM; | 228 | return -ENOMEM; |
228 | 229 | ||
229 | pdata = dev->dev.platform_data; | ||
230 | if (pdata) { | 230 | if (pdata) { |
231 | chip->gc.base = pdata->gpio_base; | 231 | chip->gc.base = pdata->gpio_base; |
232 | chip->irq_base = pdata->irq_base; | 232 | chip->irq_base = pdata->irq_base; |
233 | } else if (dev->dev.of_node) { | 233 | } else if (adev->dev.of_node) { |
234 | chip->gc.base = -1; | 234 | chip->gc.base = -1; |
235 | chip->irq_base = 0; | 235 | chip->irq_base = 0; |
236 | } else { | 236 | } else |
237 | ret = -ENODEV; | 237 | return -ENODEV; |
238 | goto free_mem; | ||
239 | } | ||
240 | 238 | ||
241 | if (!request_mem_region(dev->res.start, | 239 | if (!devm_request_mem_region(dev, adev->res.start, |
242 | resource_size(&dev->res), "pl061")) { | 240 | resource_size(&adev->res), "pl061")) |
243 | ret = -EBUSY; | 241 | return -EBUSY; |
244 | goto free_mem; | ||
245 | } | ||
246 | 242 | ||
247 | chip->base = ioremap(dev->res.start, resource_size(&dev->res)); | 243 | chip->base = devm_ioremap(dev, adev->res.start, |
248 | if (chip->base == NULL) { | 244 | resource_size(&adev->res)); |
249 | ret = -ENOMEM; | 245 | if (chip->base == NULL) |
250 | goto release_region; | 246 | return -ENOMEM; |
251 | } | ||
252 | 247 | ||
253 | spin_lock_init(&chip->lock); | 248 | spin_lock_init(&chip->lock); |
254 | 249 | ||
@@ -258,13 +253,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
258 | chip->gc.set = pl061_set_value; | 253 | chip->gc.set = pl061_set_value; |
259 | chip->gc.to_irq = pl061_to_irq; | 254 | chip->gc.to_irq = pl061_to_irq; |
260 | chip->gc.ngpio = PL061_GPIO_NR; | 255 | chip->gc.ngpio = PL061_GPIO_NR; |
261 | chip->gc.label = dev_name(&dev->dev); | 256 | chip->gc.label = dev_name(dev); |
262 | chip->gc.dev = &dev->dev; | 257 | chip->gc.dev = dev; |
263 | chip->gc.owner = THIS_MODULE; | 258 | chip->gc.owner = THIS_MODULE; |
264 | 259 | ||
265 | ret = gpiochip_add(&chip->gc); | 260 | ret = gpiochip_add(&chip->gc); |
266 | if (ret) | 261 | if (ret) |
267 | goto iounmap; | 262 | return ret; |
268 | 263 | ||
269 | /* | 264 | /* |
270 | * irq_chip support | 265 | * irq_chip support |
@@ -276,11 +271,10 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
276 | pl061_init_gc(chip, chip->irq_base); | 271 | pl061_init_gc(chip, chip->irq_base); |
277 | 272 | ||
278 | writeb(0, chip->base + GPIOIE); /* disable irqs */ | 273 | writeb(0, chip->base + GPIOIE); /* disable irqs */ |
279 | irq = dev->irq[0]; | 274 | irq = adev->irq[0]; |
280 | if (irq < 0) { | 275 | if (irq < 0) |
281 | ret = -ENODEV; | 276 | return -ENODEV; |
282 | goto iounmap; | 277 | |
283 | } | ||
284 | irq_set_chained_handler(irq, pl061_irq_handler); | 278 | irq_set_chained_handler(irq, pl061_irq_handler); |
285 | irq_set_handler_data(irq, chip); | 279 | irq_set_handler_data(irq, chip); |
286 | 280 | ||
@@ -294,18 +288,9 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
294 | } | 288 | } |
295 | } | 289 | } |
296 | 290 | ||
297 | amba_set_drvdata(dev, chip); | 291 | amba_set_drvdata(adev, chip); |
298 | 292 | ||
299 | return 0; | 293 | return 0; |
300 | |||
301 | iounmap: | ||
302 | iounmap(chip->base); | ||
303 | release_region: | ||
304 | release_mem_region(dev->res.start, resource_size(&dev->res)); | ||
305 | free_mem: | ||
306 | kfree(chip); | ||
307 | |||
308 | return ret; | ||
309 | } | 294 | } |
310 | 295 | ||
311 | #ifdef CONFIG_PM | 296 | #ifdef CONFIG_PM |
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 1e48317e70fb..8c8447c7d2a8 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c | |||
@@ -292,17 +292,15 @@ static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio, | |||
292 | { | 292 | { |
293 | int base = tc3589x_gpio->irq_base; | 293 | int base = tc3589x_gpio->irq_base; |
294 | 294 | ||
295 | if (base) { | 295 | /* |
296 | tc3589x_gpio->domain = irq_domain_add_legacy( | 296 | * If this results in a linear domain, irq_create_mapping() will |
297 | NULL, tc3589x_gpio->chip.ngpio, base, | 297 | * take care of allocating IRQ descriptors at runtime. When a base |
298 | 0, &tc3589x_irq_ops, tc3589x_gpio); | 298 | * is provided, the IRQ descriptors will be allocated when the |
299 | } | 299 | * domain is instantiated. |
300 | else { | 300 | */ |
301 | tc3589x_gpio->domain = irq_domain_add_linear( | 301 | tc3589x_gpio->domain = irq_domain_add_simple(np, |
302 | np, tc3589x_gpio->chip.ngpio, | 302 | tc3589x_gpio->chip.ngpio, base, &tc3589x_irq_ops, |
303 | &tc3589x_irq_ops, tc3589x_gpio); | 303 | tc3589x_gpio); |
304 | } | ||
305 | |||
306 | if (!tc3589x_gpio->domain) { | 304 | if (!tc3589x_gpio->domain) { |
307 | dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n"); | 305 | dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n"); |
308 | return -ENOSYS; | 306 | return -ENOSYS; |
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index d982593d7563..c7c175a4aff1 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c | |||
@@ -380,7 +380,6 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) | |||
380 | { | 380 | { |
381 | const struct of_device_id *match; | 381 | const struct of_device_id *match; |
382 | struct tegra_gpio_soc_config *config; | 382 | struct tegra_gpio_soc_config *config; |
383 | int irq_base; | ||
384 | struct resource *res; | 383 | struct resource *res; |
385 | struct tegra_gpio_bank *bank; | 384 | struct tegra_gpio_bank *bank; |
386 | int gpio; | 385 | int gpio; |
@@ -417,14 +416,11 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) | |||
417 | return -ENODEV; | 416 | return -ENODEV; |
418 | } | 417 | } |
419 | 418 | ||
420 | irq_base = irq_alloc_descs(-1, 0, tegra_gpio_chip.ngpio, 0); | 419 | irq_domain = irq_domain_add_linear(pdev->dev.of_node, |
421 | if (irq_base < 0) { | 420 | 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); | 421 | &irq_domain_simple_ops, NULL); |
422 | if (!irq_domain) | ||
423 | return -ENODEV; | ||
428 | 424 | ||
429 | for (i = 0; i < tegra_gpio_bank_count; i++) { | 425 | for (i = 0; i < tegra_gpio_bank_count; i++) { |
430 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); | 426 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); |
@@ -464,7 +460,7 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) | |||
464 | gpiochip_add(&tegra_gpio_chip); | 460 | gpiochip_add(&tegra_gpio_chip); |
465 | 461 | ||
466 | for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) { | 462 | for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) { |
467 | int irq = irq_find_mapping(irq_domain, gpio); | 463 | int irq = irq_create_mapping(irq_domain, gpio); |
468 | /* No validity check; all Tegra GPIOs are valid IRQs */ | 464 | /* No validity check; all Tegra GPIOs are valid IRQs */ |
469 | 465 | ||
470 | bank = &tegra_gpio_banks[GPIO_BANK(gpio)]; | 466 | bank = &tegra_gpio_banks[GPIO_BANK(gpio)]; |
diff --git a/drivers/gpio/gpio-vt8500.c b/drivers/gpio/gpio-vt8500.c index bcd8e4aa7c7d..9ed2a2b347fa 100644 --- a/drivers/gpio/gpio-vt8500.c +++ b/drivers/gpio/gpio-vt8500.c | |||
@@ -96,6 +96,7 @@ static struct vt8500_gpio_data wm8505_data = { | |||
96 | VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12), | 96 | VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12), |
97 | VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16), | 97 | VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16), |
98 | VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22), | 98 | VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22), |
99 | VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6), | ||
99 | }, | 100 | }, |
100 | }; | 101 | }; |
101 | 102 | ||
@@ -115,6 +116,7 @@ static struct vt8500_gpio_data wm8650_data = { | |||
115 | VT8500_BANK(0x58, 0x98, 0xD8, 0x18, 32), | 116 | VT8500_BANK(0x58, 0x98, 0xD8, 0x18, 32), |
116 | VT8500_BANK(0x5C, 0x9C, 0xDC, 0x1C, 32), | 117 | VT8500_BANK(0x5C, 0x9C, 0xDC, 0x1C, 32), |
117 | VT8500_BANK(0x7C, 0xBC, 0xFC, 0x3C, 32), | 118 | VT8500_BANK(0x7C, 0xBC, 0xFC, 0x3C, 32), |
119 | VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6), | ||
118 | }, | 120 | }, |
119 | }; | 121 | }; |
120 | 122 | ||
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1c8d9e3380e1..4c079044bf56 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -191,6 +191,32 @@ err: | |||
191 | return ret; | 191 | return ret; |
192 | } | 192 | } |
193 | 193 | ||
194 | /* caller ensures gpio is valid and requested, chip->get_direction may sleep */ | ||
195 | static int gpio_get_direction(unsigned gpio) | ||
196 | { | ||
197 | struct gpio_chip *chip; | ||
198 | struct gpio_desc *desc = &gpio_desc[gpio]; | ||
199 | int status = -EINVAL; | ||
200 | |||
201 | chip = gpio_to_chip(gpio); | ||
202 | gpio -= chip->base; | ||
203 | |||
204 | if (!chip->get_direction) | ||
205 | return status; | ||
206 | |||
207 | status = chip->get_direction(chip, gpio); | ||
208 | if (status > 0) { | ||
209 | /* GPIOF_DIR_IN, or other positive */ | ||
210 | status = 1; | ||
211 | clear_bit(FLAG_IS_OUT, &desc->flags); | ||
212 | } | ||
213 | if (status == 0) { | ||
214 | /* GPIOF_DIR_OUT */ | ||
215 | set_bit(FLAG_IS_OUT, &desc->flags); | ||
216 | } | ||
217 | return status; | ||
218 | } | ||
219 | |||
194 | #ifdef CONFIG_GPIO_SYSFS | 220 | #ifdef CONFIG_GPIO_SYSFS |
195 | 221 | ||
196 | /* lock protects against unexport_gpio() being called while | 222 | /* lock protects against unexport_gpio() being called while |
@@ -223,6 +249,7 @@ static ssize_t gpio_direction_show(struct device *dev, | |||
223 | struct device_attribute *attr, char *buf) | 249 | struct device_attribute *attr, char *buf) |
224 | { | 250 | { |
225 | const struct gpio_desc *desc = dev_get_drvdata(dev); | 251 | const struct gpio_desc *desc = dev_get_drvdata(dev); |
252 | unsigned gpio = desc - gpio_desc; | ||
226 | ssize_t status; | 253 | ssize_t status; |
227 | 254 | ||
228 | mutex_lock(&sysfs_lock); | 255 | mutex_lock(&sysfs_lock); |
@@ -230,6 +257,7 @@ static ssize_t gpio_direction_show(struct device *dev, | |||
230 | if (!test_bit(FLAG_EXPORT, &desc->flags)) | 257 | if (!test_bit(FLAG_EXPORT, &desc->flags)) |
231 | status = -EIO; | 258 | status = -EIO; |
232 | else | 259 | else |
260 | gpio_get_direction(gpio); | ||
233 | status = sprintf(buf, "%s\n", | 261 | status = sprintf(buf, "%s\n", |
234 | test_bit(FLAG_IS_OUT, &desc->flags) | 262 | test_bit(FLAG_IS_OUT, &desc->flags) |
235 | ? "out" : "in"); | 263 | ? "out" : "in"); |
@@ -704,8 +732,9 @@ int gpio_export(unsigned gpio, bool direction_may_change) | |||
704 | { | 732 | { |
705 | unsigned long flags; | 733 | unsigned long flags; |
706 | struct gpio_desc *desc; | 734 | struct gpio_desc *desc; |
707 | int status = -EINVAL; | 735 | int status; |
708 | const char *ioname = NULL; | 736 | const char *ioname = NULL; |
737 | struct device *dev; | ||
709 | 738 | ||
710 | /* can't export until sysfs is available ... */ | 739 | /* can't export until sysfs is available ... */ |
711 | if (!gpio_class.p) { | 740 | if (!gpio_class.p) { |
@@ -713,59 +742,66 @@ int gpio_export(unsigned gpio, bool direction_may_change) | |||
713 | return -ENOENT; | 742 | return -ENOENT; |
714 | } | 743 | } |
715 | 744 | ||
716 | if (!gpio_is_valid(gpio)) | 745 | if (!gpio_is_valid(gpio)) { |
717 | goto done; | 746 | pr_debug("%s: gpio %d is not valid\n", __func__, gpio); |
747 | return -EINVAL; | ||
748 | } | ||
718 | 749 | ||
719 | mutex_lock(&sysfs_lock); | 750 | mutex_lock(&sysfs_lock); |
720 | 751 | ||
721 | spin_lock_irqsave(&gpio_lock, flags); | 752 | spin_lock_irqsave(&gpio_lock, flags); |
722 | desc = &gpio_desc[gpio]; | 753 | desc = &gpio_desc[gpio]; |
723 | if (test_bit(FLAG_REQUESTED, &desc->flags) | 754 | if (!test_bit(FLAG_REQUESTED, &desc->flags) || |
724 | && !test_bit(FLAG_EXPORT, &desc->flags)) { | 755 | test_bit(FLAG_EXPORT, &desc->flags)) { |
725 | status = 0; | 756 | spin_unlock_irqrestore(&gpio_lock, flags); |
726 | if (!desc->chip->direction_input | 757 | pr_debug("%s: gpio %d unavailable (requested=%d, exported=%d)\n", |
727 | || !desc->chip->direction_output) | 758 | __func__, gpio, |
728 | direction_may_change = false; | 759 | test_bit(FLAG_REQUESTED, &desc->flags), |
760 | test_bit(FLAG_EXPORT, &desc->flags)); | ||
761 | status = -EPERM; | ||
762 | goto fail_unlock; | ||
729 | } | 763 | } |
764 | |||
765 | if (!desc->chip->direction_input || !desc->chip->direction_output) | ||
766 | direction_may_change = false; | ||
730 | spin_unlock_irqrestore(&gpio_lock, flags); | 767 | spin_unlock_irqrestore(&gpio_lock, flags); |
731 | 768 | ||
732 | if (desc->chip->names && desc->chip->names[gpio - desc->chip->base]) | 769 | if (desc->chip->names && desc->chip->names[gpio - desc->chip->base]) |
733 | ioname = desc->chip->names[gpio - desc->chip->base]; | 770 | ioname = desc->chip->names[gpio - desc->chip->base]; |
734 | 771 | ||
735 | if (status == 0) { | 772 | dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), |
736 | struct device *dev; | 773 | desc, ioname ? ioname : "gpio%u", gpio); |
737 | 774 | if (IS_ERR(dev)) { | |
738 | dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), | 775 | status = PTR_ERR(dev); |
739 | desc, ioname ? ioname : "gpio%u", gpio); | 776 | goto fail_unlock; |
740 | if (!IS_ERR(dev)) { | ||
741 | status = sysfs_create_group(&dev->kobj, | ||
742 | &gpio_attr_group); | ||
743 | |||
744 | if (!status && direction_may_change) | ||
745 | status = device_create_file(dev, | ||
746 | &dev_attr_direction); | ||
747 | |||
748 | if (!status && gpio_to_irq(gpio) >= 0 | ||
749 | && (direction_may_change | ||
750 | || !test_bit(FLAG_IS_OUT, | ||
751 | &desc->flags))) | ||
752 | status = device_create_file(dev, | ||
753 | &dev_attr_edge); | ||
754 | |||
755 | if (status != 0) | ||
756 | device_unregister(dev); | ||
757 | } else | ||
758 | status = PTR_ERR(dev); | ||
759 | if (status == 0) | ||
760 | set_bit(FLAG_EXPORT, &desc->flags); | ||
761 | } | 777 | } |
762 | 778 | ||
763 | mutex_unlock(&sysfs_lock); | 779 | status = sysfs_create_group(&dev->kobj, &gpio_attr_group); |
764 | |||
765 | done: | ||
766 | if (status) | 780 | if (status) |
767 | pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); | 781 | goto fail_unregister_device; |
768 | 782 | ||
783 | if (direction_may_change) { | ||
784 | status = device_create_file(dev, &dev_attr_direction); | ||
785 | if (status) | ||
786 | goto fail_unregister_device; | ||
787 | } | ||
788 | |||
789 | if (gpio_to_irq(gpio) >= 0 && (direction_may_change || | ||
790 | !test_bit(FLAG_IS_OUT, &desc->flags))) { | ||
791 | status = device_create_file(dev, &dev_attr_edge); | ||
792 | if (status) | ||
793 | goto fail_unregister_device; | ||
794 | } | ||
795 | |||
796 | set_bit(FLAG_EXPORT, &desc->flags); | ||
797 | mutex_unlock(&sysfs_lock); | ||
798 | return 0; | ||
799 | |||
800 | fail_unregister_device: | ||
801 | device_unregister(dev); | ||
802 | fail_unlock: | ||
803 | mutex_unlock(&sysfs_lock); | ||
804 | pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); | ||
769 | return status; | 805 | return status; |
770 | } | 806 | } |
771 | EXPORT_SYMBOL_GPL(gpio_export); | 807 | EXPORT_SYMBOL_GPL(gpio_export); |
@@ -1075,6 +1111,7 @@ int gpiochip_add(struct gpio_chip *chip) | |||
1075 | * inputs (often with pullups enabled) so power | 1111 | * inputs (often with pullups enabled) so power |
1076 | * usage is minimized. Linux code should set the | 1112 | * usage is minimized. Linux code should set the |
1077 | * gpio direction first thing; but until it does, | 1113 | * gpio direction first thing; but until it does, |
1114 | * and in case chip->get_direction is not set, | ||
1078 | * we may expose the wrong direction in sysfs. | 1115 | * we may expose the wrong direction in sysfs. |
1079 | */ | 1116 | */ |
1080 | gpio_desc[id].flags = !chip->direction_input | 1117 | gpio_desc[id].flags = !chip->direction_input |
@@ -1228,9 +1265,15 @@ int gpio_request(unsigned gpio, const char *label) | |||
1228 | desc_set_label(desc, NULL); | 1265 | desc_set_label(desc, NULL); |
1229 | module_put(chip->owner); | 1266 | module_put(chip->owner); |
1230 | clear_bit(FLAG_REQUESTED, &desc->flags); | 1267 | clear_bit(FLAG_REQUESTED, &desc->flags); |
1268 | goto done; | ||
1231 | } | 1269 | } |
1232 | } | 1270 | } |
1233 | 1271 | if (chip->get_direction) { | |
1272 | /* chip->get_direction may sleep */ | ||
1273 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
1274 | gpio_get_direction(gpio); | ||
1275 | spin_lock_irqsave(&gpio_lock, flags); | ||
1276 | } | ||
1234 | done: | 1277 | done: |
1235 | if (status) | 1278 | if (status) |
1236 | pr_debug("gpio_request: gpio-%d (%s) status %d\n", | 1279 | pr_debug("gpio_request: gpio-%d (%s) status %d\n", |
@@ -1766,6 +1809,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
1766 | if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) | 1809 | if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) |
1767 | continue; | 1810 | continue; |
1768 | 1811 | ||
1812 | gpio_get_direction(gpio); | ||
1769 | is_out = test_bit(FLAG_IS_OUT, &gdesc->flags); | 1813 | is_out = test_bit(FLAG_IS_OUT, &gdesc->flags); |
1770 | seq_printf(s, " gpio-%-3d (%-20.20s) %s %s", | 1814 | seq_printf(s, " gpio-%-3d (%-20.20s) %s %s", |
1771 | gpio, gdesc->label, | 1815 | gpio, gdesc->label, |
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index a9432fc6b8ba..eb70ca295971 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h | |||
@@ -56,6 +56,8 @@ struct device_node; | |||
56 | * enabling module power and clock; may sleep | 56 | * enabling module power and clock; may sleep |
57 | * @free: optional hook for chip-specific deactivation, such as | 57 | * @free: optional hook for chip-specific deactivation, such as |
58 | * disabling module power and clock; may sleep | 58 | * disabling module power and clock; may sleep |
59 | * @get_direction: returns direction for signal "offset", 0=out, 1=in, | ||
60 | * (same as GPIOF_DIR_XXX), or negative error | ||
59 | * @direction_input: configures signal "offset" as input, or returns error | 61 | * @direction_input: configures signal "offset" as input, or returns error |
60 | * @get: returns value for signal "offset"; for output signals this | 62 | * @get: returns value for signal "offset"; for output signals this |
61 | * returns either the value actually sensed, or zero | 63 | * returns either the value actually sensed, or zero |
@@ -100,7 +102,8 @@ struct gpio_chip { | |||
100 | unsigned offset); | 102 | unsigned offset); |
101 | void (*free)(struct gpio_chip *chip, | 103 | void (*free)(struct gpio_chip *chip, |
102 | unsigned offset); | 104 | unsigned offset); |
103 | 105 | int (*get_direction)(struct gpio_chip *chip, | |
106 | unsigned offset); | ||
104 | int (*direction_input)(struct gpio_chip *chip, | 107 | int (*direction_input)(struct gpio_chip *chip, |
105 | unsigned offset); | 108 | unsigned offset); |
106 | int (*get)(struct gpio_chip *chip, | 109 | int (*get)(struct gpio_chip *chip, |