diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/devres.c | 32 | ||||
-rw-r--r-- | drivers/gpio/gpio-sch.c | 293 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 117 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 85 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.h | 7 |
5 files changed, 332 insertions, 202 deletions
diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c index 954b9f6b0ef8..13dbd3dfc33a 100644 --- a/drivers/gpio/devres.c +++ b/drivers/gpio/devres.c | |||
@@ -109,6 +109,38 @@ struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev, | |||
109 | EXPORT_SYMBOL(__devm_gpiod_get_index); | 109 | EXPORT_SYMBOL(__devm_gpiod_get_index); |
110 | 110 | ||
111 | /** | 111 | /** |
112 | * devm_get_gpiod_from_child - get a GPIO descriptor from a device's child node | ||
113 | * @dev: GPIO consumer | ||
114 | * @child: firmware node (child of @dev) | ||
115 | * | ||
116 | * GPIO descriptors returned from this function are automatically disposed on | ||
117 | * driver detach. | ||
118 | */ | ||
119 | struct gpio_desc *devm_get_gpiod_from_child(struct device *dev, | ||
120 | struct fwnode_handle *child) | ||
121 | { | ||
122 | struct gpio_desc **dr; | ||
123 | struct gpio_desc *desc; | ||
124 | |||
125 | dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *), | ||
126 | GFP_KERNEL); | ||
127 | if (!dr) | ||
128 | return ERR_PTR(-ENOMEM); | ||
129 | |||
130 | desc = fwnode_get_named_gpiod(child, "gpios"); | ||
131 | if (IS_ERR(desc)) { | ||
132 | devres_free(dr); | ||
133 | return desc; | ||
134 | } | ||
135 | |||
136 | *dr = desc; | ||
137 | devres_add(dev, dr); | ||
138 | |||
139 | return desc; | ||
140 | } | ||
141 | EXPORT_SYMBOL(devm_get_gpiod_from_child); | ||
142 | |||
143 | /** | ||
112 | * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional() | 144 | * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional() |
113 | * @dev: GPIO consumer | 145 | * @dev: GPIO consumer |
114 | * @con_id: function within the GPIO consumer | 146 | * @con_id: function within the GPIO consumer |
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index 41e91d70301e..99720c8bc8ed 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c | |||
@@ -29,290 +29,221 @@ | |||
29 | 29 | ||
30 | #include <linux/gpio.h> | 30 | #include <linux/gpio.h> |
31 | 31 | ||
32 | static DEFINE_SPINLOCK(gpio_lock); | 32 | #define GEN 0x00 |
33 | 33 | #define GIO 0x04 | |
34 | #define CGEN (0x00) | 34 | #define GLV 0x08 |
35 | #define CGIO (0x04) | 35 | |
36 | #define CGLV (0x08) | 36 | struct sch_gpio { |
37 | 37 | struct gpio_chip chip; | |
38 | #define RGEN (0x20) | 38 | spinlock_t lock; |
39 | #define RGIO (0x24) | 39 | unsigned short iobase; |
40 | #define RGLV (0x28) | 40 | unsigned short core_base; |
41 | 41 | unsigned short resume_base; | |
42 | static unsigned short gpio_ba; | 42 | }; |
43 | |||
44 | static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned gpio_num) | ||
45 | { | ||
46 | u8 curr_dirs; | ||
47 | unsigned short offset, bit; | ||
48 | |||
49 | spin_lock(&gpio_lock); | ||
50 | |||
51 | offset = CGIO + gpio_num / 8; | ||
52 | bit = gpio_num % 8; | ||
53 | |||
54 | curr_dirs = inb(gpio_ba + offset); | ||
55 | |||
56 | if (!(curr_dirs & (1 << bit))) | ||
57 | outb(curr_dirs | (1 << bit), gpio_ba + offset); | ||
58 | 43 | ||
59 | spin_unlock(&gpio_lock); | 44 | #define to_sch_gpio(c) container_of(c, struct sch_gpio, chip) |
60 | return 0; | ||
61 | } | ||
62 | 45 | ||
63 | static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num) | 46 | static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio, |
47 | unsigned reg) | ||
64 | { | 48 | { |
65 | int res; | 49 | unsigned base = 0; |
66 | unsigned short offset, bit; | ||
67 | 50 | ||
68 | offset = CGLV + gpio_num / 8; | 51 | if (gpio >= sch->resume_base) { |
69 | bit = gpio_num % 8; | 52 | gpio -= sch->resume_base; |
53 | base += 0x20; | ||
54 | } | ||
70 | 55 | ||
71 | res = !!(inb(gpio_ba + offset) & (1 << bit)); | 56 | return base + reg + gpio / 8; |
72 | return res; | ||
73 | } | 57 | } |
74 | 58 | ||
75 | static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val) | 59 | static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio) |
76 | { | 60 | { |
77 | u8 curr_vals; | 61 | if (gpio >= sch->resume_base) |
78 | unsigned short offset, bit; | 62 | gpio -= sch->resume_base; |
79 | 63 | return gpio % 8; | |
80 | spin_lock(&gpio_lock); | ||
81 | |||
82 | offset = CGLV + gpio_num / 8; | ||
83 | bit = gpio_num % 8; | ||
84 | |||
85 | curr_vals = inb(gpio_ba + offset); | ||
86 | |||
87 | if (val) | ||
88 | outb(curr_vals | (1 << bit), gpio_ba + offset); | ||
89 | else | ||
90 | outb((curr_vals & ~(1 << bit)), gpio_ba + offset); | ||
91 | spin_unlock(&gpio_lock); | ||
92 | } | 64 | } |
93 | 65 | ||
94 | static int sch_gpio_core_direction_out(struct gpio_chip *gc, | 66 | static void sch_gpio_enable(struct sch_gpio *sch, unsigned gpio) |
95 | unsigned gpio_num, int val) | ||
96 | { | 67 | { |
97 | u8 curr_dirs; | ||
98 | unsigned short offset, bit; | 68 | unsigned short offset, bit; |
69 | u8 enable; | ||
99 | 70 | ||
100 | spin_lock(&gpio_lock); | 71 | spin_lock(&sch->lock); |
101 | 72 | ||
102 | offset = CGIO + gpio_num / 8; | 73 | offset = sch_gpio_offset(sch, gpio, GEN); |
103 | bit = gpio_num % 8; | 74 | bit = sch_gpio_bit(sch, gpio); |
104 | |||
105 | curr_dirs = inb(gpio_ba + offset); | ||
106 | if (curr_dirs & (1 << bit)) | ||
107 | outb(curr_dirs & ~(1 << bit), gpio_ba + offset); | ||
108 | 75 | ||
109 | spin_unlock(&gpio_lock); | 76 | enable = inb(sch->iobase + offset); |
77 | if (!(enable & (1 << bit))) | ||
78 | outb(enable | (1 << bit), sch->iobase + offset); | ||
110 | 79 | ||
111 | /* | 80 | spin_unlock(&sch->lock); |
112 | * according to the datasheet, writing to the level register has no | ||
113 | * effect when GPIO is programmed as input. | ||
114 | * Actually the the level register is read-only when configured as input. | ||
115 | * Thus presetting the output level before switching to output is _NOT_ possible. | ||
116 | * Hence we set the level after configuring the GPIO as output. | ||
117 | * But we cannot prevent a short low pulse if direction is set to high | ||
118 | * and an external pull-up is connected. | ||
119 | */ | ||
120 | sch_gpio_core_set(gc, gpio_num, val); | ||
121 | return 0; | ||
122 | } | 81 | } |
123 | 82 | ||
124 | static struct gpio_chip sch_gpio_core = { | 83 | static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) |
125 | .label = "sch_gpio_core", | ||
126 | .owner = THIS_MODULE, | ||
127 | .direction_input = sch_gpio_core_direction_in, | ||
128 | .get = sch_gpio_core_get, | ||
129 | .direction_output = sch_gpio_core_direction_out, | ||
130 | .set = sch_gpio_core_set, | ||
131 | }; | ||
132 | |||
133 | static int sch_gpio_resume_direction_in(struct gpio_chip *gc, | ||
134 | unsigned gpio_num) | ||
135 | { | 84 | { |
85 | struct sch_gpio *sch = to_sch_gpio(gc); | ||
136 | u8 curr_dirs; | 86 | u8 curr_dirs; |
137 | unsigned short offset, bit; | 87 | unsigned short offset, bit; |
138 | 88 | ||
139 | spin_lock(&gpio_lock); | 89 | spin_lock(&sch->lock); |
140 | 90 | ||
141 | offset = RGIO + gpio_num / 8; | 91 | offset = sch_gpio_offset(sch, gpio_num, GIO); |
142 | bit = gpio_num % 8; | 92 | bit = sch_gpio_bit(sch, gpio_num); |
143 | 93 | ||
144 | curr_dirs = inb(gpio_ba + offset); | 94 | curr_dirs = inb(sch->iobase + offset); |
145 | 95 | ||
146 | if (!(curr_dirs & (1 << bit))) | 96 | if (!(curr_dirs & (1 << bit))) |
147 | outb(curr_dirs | (1 << bit), gpio_ba + offset); | 97 | outb(curr_dirs | (1 << bit), sch->iobase + offset); |
148 | 98 | ||
149 | spin_unlock(&gpio_lock); | 99 | spin_unlock(&sch->lock); |
150 | return 0; | 100 | return 0; |
151 | } | 101 | } |
152 | 102 | ||
153 | static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num) | 103 | static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num) |
154 | { | 104 | { |
105 | struct sch_gpio *sch = to_sch_gpio(gc); | ||
106 | int res; | ||
155 | unsigned short offset, bit; | 107 | unsigned short offset, bit; |
156 | 108 | ||
157 | offset = RGLV + gpio_num / 8; | 109 | offset = sch_gpio_offset(sch, gpio_num, GLV); |
158 | bit = gpio_num % 8; | 110 | bit = sch_gpio_bit(sch, gpio_num); |
111 | |||
112 | res = !!(inb(sch->iobase + offset) & (1 << bit)); | ||
159 | 113 | ||
160 | return !!(inb(gpio_ba + offset) & (1 << bit)); | 114 | return res; |
161 | } | 115 | } |
162 | 116 | ||
163 | static void sch_gpio_resume_set(struct gpio_chip *gc, | 117 | static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val) |
164 | unsigned gpio_num, int val) | ||
165 | { | 118 | { |
119 | struct sch_gpio *sch = to_sch_gpio(gc); | ||
166 | u8 curr_vals; | 120 | u8 curr_vals; |
167 | unsigned short offset, bit; | 121 | unsigned short offset, bit; |
168 | 122 | ||
169 | spin_lock(&gpio_lock); | 123 | spin_lock(&sch->lock); |
170 | 124 | ||
171 | offset = RGLV + gpio_num / 8; | 125 | offset = sch_gpio_offset(sch, gpio_num, GLV); |
172 | bit = gpio_num % 8; | 126 | bit = sch_gpio_bit(sch, gpio_num); |
173 | 127 | ||
174 | curr_vals = inb(gpio_ba + offset); | 128 | curr_vals = inb(sch->iobase + offset); |
175 | 129 | ||
176 | if (val) | 130 | if (val) |
177 | outb(curr_vals | (1 << bit), gpio_ba + offset); | 131 | outb(curr_vals | (1 << bit), sch->iobase + offset); |
178 | else | 132 | else |
179 | outb((curr_vals & ~(1 << bit)), gpio_ba + offset); | 133 | outb((curr_vals & ~(1 << bit)), sch->iobase + offset); |
180 | 134 | ||
181 | spin_unlock(&gpio_lock); | 135 | spin_unlock(&sch->lock); |
182 | } | 136 | } |
183 | 137 | ||
184 | static int sch_gpio_resume_direction_out(struct gpio_chip *gc, | 138 | static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num, |
185 | unsigned gpio_num, int val) | 139 | int val) |
186 | { | 140 | { |
141 | struct sch_gpio *sch = to_sch_gpio(gc); | ||
187 | u8 curr_dirs; | 142 | u8 curr_dirs; |
188 | unsigned short offset, bit; | 143 | unsigned short offset, bit; |
189 | 144 | ||
190 | offset = RGIO + gpio_num / 8; | 145 | spin_lock(&sch->lock); |
191 | bit = gpio_num % 8; | ||
192 | 146 | ||
193 | spin_lock(&gpio_lock); | 147 | offset = sch_gpio_offset(sch, gpio_num, GIO); |
148 | bit = sch_gpio_bit(sch, gpio_num); | ||
194 | 149 | ||
195 | curr_dirs = inb(gpio_ba + offset); | 150 | curr_dirs = inb(sch->iobase + offset); |
196 | if (curr_dirs & (1 << bit)) | 151 | if (curr_dirs & (1 << bit)) |
197 | outb(curr_dirs & ~(1 << bit), gpio_ba + offset); | 152 | outb(curr_dirs & ~(1 << bit), sch->iobase + offset); |
198 | 153 | ||
199 | spin_unlock(&gpio_lock); | 154 | spin_unlock(&sch->lock); |
200 | 155 | ||
201 | /* | 156 | /* |
202 | * according to the datasheet, writing to the level register has no | 157 | * according to the datasheet, writing to the level register has no |
203 | * effect when GPIO is programmed as input. | 158 | * effect when GPIO is programmed as input. |
204 | * Actually the the level register is read-only when configured as input. | 159 | * Actually the the level register is read-only when configured as input. |
205 | * Thus presetting the output level before switching to output is _NOT_ possible. | 160 | * Thus presetting the output level before switching to output is _NOT_ possible. |
206 | * Hence we set the level after configuring the GPIO as output. | 161 | * Hence we set the level after configuring the GPIO as output. |
207 | * But we cannot prevent a short low pulse if direction is set to high | 162 | * But we cannot prevent a short low pulse if direction is set to high |
208 | * and an external pull-up is connected. | 163 | * and an external pull-up is connected. |
209 | */ | 164 | */ |
210 | sch_gpio_resume_set(gc, gpio_num, val); | 165 | sch_gpio_set(gc, gpio_num, val); |
211 | return 0; | 166 | return 0; |
212 | } | 167 | } |
213 | 168 | ||
214 | static struct gpio_chip sch_gpio_resume = { | 169 | static struct gpio_chip sch_gpio_chip = { |
215 | .label = "sch_gpio_resume", | 170 | .label = "sch_gpio", |
216 | .owner = THIS_MODULE, | 171 | .owner = THIS_MODULE, |
217 | .direction_input = sch_gpio_resume_direction_in, | 172 | .direction_input = sch_gpio_direction_in, |
218 | .get = sch_gpio_resume_get, | 173 | .get = sch_gpio_get, |
219 | .direction_output = sch_gpio_resume_direction_out, | 174 | .direction_output = sch_gpio_direction_out, |
220 | .set = sch_gpio_resume_set, | 175 | .set = sch_gpio_set, |
221 | }; | 176 | }; |
222 | 177 | ||
223 | static int sch_gpio_probe(struct platform_device *pdev) | 178 | static int sch_gpio_probe(struct platform_device *pdev) |
224 | { | 179 | { |
180 | struct sch_gpio *sch; | ||
225 | struct resource *res; | 181 | struct resource *res; |
226 | int err, id; | ||
227 | 182 | ||
228 | id = pdev->id; | 183 | sch = devm_kzalloc(&pdev->dev, sizeof(*sch), GFP_KERNEL); |
229 | if (!id) | 184 | if (!sch) |
230 | return -ENODEV; | 185 | return -ENOMEM; |
231 | 186 | ||
232 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 187 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
233 | if (!res) | 188 | if (!res) |
234 | return -EBUSY; | 189 | return -EBUSY; |
235 | 190 | ||
236 | if (!request_region(res->start, resource_size(res), pdev->name)) | 191 | if (!devm_request_region(&pdev->dev, res->start, resource_size(res), |
192 | pdev->name)) | ||
237 | return -EBUSY; | 193 | return -EBUSY; |
238 | 194 | ||
239 | gpio_ba = res->start; | 195 | spin_lock_init(&sch->lock); |
196 | sch->iobase = res->start; | ||
197 | sch->chip = sch_gpio_chip; | ||
198 | sch->chip.label = dev_name(&pdev->dev); | ||
199 | sch->chip.dev = &pdev->dev; | ||
240 | 200 | ||
241 | switch (id) { | 201 | switch (pdev->id) { |
242 | case PCI_DEVICE_ID_INTEL_SCH_LPC: | 202 | case PCI_DEVICE_ID_INTEL_SCH_LPC: |
243 | sch_gpio_core.base = 0; | 203 | sch->core_base = 0; |
244 | sch_gpio_core.ngpio = 10; | 204 | sch->resume_base = 10; |
245 | sch_gpio_resume.base = 10; | 205 | sch->chip.ngpio = 14; |
246 | sch_gpio_resume.ngpio = 4; | 206 | |
247 | /* | 207 | /* |
248 | * GPIO[6:0] enabled by default | 208 | * GPIO[6:0] enabled by default |
249 | * GPIO7 is configured by the CMC as SLPIOVR | 209 | * GPIO7 is configured by the CMC as SLPIOVR |
250 | * Enable GPIO[9:8] core powered gpios explicitly | 210 | * Enable GPIO[9:8] core powered gpios explicitly |
251 | */ | 211 | */ |
252 | outb(0x3, gpio_ba + CGEN + 1); | 212 | sch_gpio_enable(sch, 8); |
213 | sch_gpio_enable(sch, 9); | ||
253 | /* | 214 | /* |
254 | * SUS_GPIO[2:0] enabled by default | 215 | * SUS_GPIO[2:0] enabled by default |
255 | * Enable SUS_GPIO3 resume powered gpio explicitly | 216 | * Enable SUS_GPIO3 resume powered gpio explicitly |
256 | */ | 217 | */ |
257 | outb(0x8, gpio_ba + RGEN); | 218 | sch_gpio_enable(sch, 13); |
258 | break; | 219 | break; |
259 | 220 | ||
260 | case PCI_DEVICE_ID_INTEL_ITC_LPC: | 221 | case PCI_DEVICE_ID_INTEL_ITC_LPC: |
261 | sch_gpio_core.base = 0; | 222 | sch->core_base = 0; |
262 | sch_gpio_core.ngpio = 5; | 223 | sch->resume_base = 5; |
263 | sch_gpio_resume.base = 5; | 224 | sch->chip.ngpio = 14; |
264 | sch_gpio_resume.ngpio = 9; | ||
265 | break; | 225 | break; |
266 | 226 | ||
267 | case PCI_DEVICE_ID_INTEL_CENTERTON_ILB: | 227 | case PCI_DEVICE_ID_INTEL_CENTERTON_ILB: |
268 | sch_gpio_core.base = 0; | 228 | sch->core_base = 0; |
269 | sch_gpio_core.ngpio = 21; | 229 | sch->resume_base = 21; |
270 | sch_gpio_resume.base = 21; | 230 | sch->chip.ngpio = 30; |
271 | sch_gpio_resume.ngpio = 9; | ||
272 | break; | 231 | break; |
273 | 232 | ||
274 | default: | 233 | default: |
275 | err = -ENODEV; | 234 | return -ENODEV; |
276 | goto err_sch_gpio_core; | ||
277 | } | 235 | } |
278 | 236 | ||
279 | sch_gpio_core.dev = &pdev->dev; | 237 | platform_set_drvdata(pdev, sch); |
280 | sch_gpio_resume.dev = &pdev->dev; | ||
281 | |||
282 | err = gpiochip_add(&sch_gpio_core); | ||
283 | if (err < 0) | ||
284 | goto err_sch_gpio_core; | ||
285 | 238 | ||
286 | err = gpiochip_add(&sch_gpio_resume); | 239 | return gpiochip_add(&sch->chip); |
287 | if (err < 0) | ||
288 | goto err_sch_gpio_resume; | ||
289 | |||
290 | return 0; | ||
291 | |||
292 | err_sch_gpio_resume: | ||
293 | gpiochip_remove(&sch_gpio_core); | ||
294 | |||
295 | err_sch_gpio_core: | ||
296 | release_region(res->start, resource_size(res)); | ||
297 | gpio_ba = 0; | ||
298 | |||
299 | return err; | ||
300 | } | 240 | } |
301 | 241 | ||
302 | static int sch_gpio_remove(struct platform_device *pdev) | 242 | static int sch_gpio_remove(struct platform_device *pdev) |
303 | { | 243 | { |
304 | struct resource *res; | 244 | struct sch_gpio *sch = platform_get_drvdata(pdev); |
305 | if (gpio_ba) { | ||
306 | |||
307 | gpiochip_remove(&sch_gpio_core); | ||
308 | gpiochip_remove(&sch_gpio_resume); | ||
309 | |||
310 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
311 | |||
312 | release_region(res->start, resource_size(res)); | ||
313 | gpio_ba = 0; | ||
314 | } | ||
315 | 245 | ||
246 | gpiochip_remove(&sch->chip); | ||
316 | return 0; | 247 | return 0; |
317 | } | 248 | } |
318 | 249 | ||
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 05c6275da224..ba98bb59a58f 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c | |||
@@ -287,9 +287,45 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) | |||
287 | } | 287 | } |
288 | } | 288 | } |
289 | 289 | ||
290 | int acpi_dev_add_driver_gpios(struct acpi_device *adev, | ||
291 | const struct acpi_gpio_mapping *gpios) | ||
292 | { | ||
293 | if (adev && gpios) { | ||
294 | adev->driver_gpios = gpios; | ||
295 | return 0; | ||
296 | } | ||
297 | return -EINVAL; | ||
298 | } | ||
299 | EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios); | ||
300 | |||
301 | static bool acpi_get_driver_gpio_data(struct acpi_device *adev, | ||
302 | const char *name, int index, | ||
303 | struct acpi_reference_args *args) | ||
304 | { | ||
305 | const struct acpi_gpio_mapping *gm; | ||
306 | |||
307 | if (!adev->driver_gpios) | ||
308 | return false; | ||
309 | |||
310 | for (gm = adev->driver_gpios; gm->name; gm++) | ||
311 | if (!strcmp(name, gm->name) && gm->data && index < gm->size) { | ||
312 | const struct acpi_gpio_params *par = gm->data + index; | ||
313 | |||
314 | args->adev = adev; | ||
315 | args->args[0] = par->crs_entry_index; | ||
316 | args->args[1] = par->line_index; | ||
317 | args->args[2] = par->active_low; | ||
318 | args->nargs = 3; | ||
319 | return true; | ||
320 | } | ||
321 | |||
322 | return false; | ||
323 | } | ||
324 | |||
290 | struct acpi_gpio_lookup { | 325 | struct acpi_gpio_lookup { |
291 | struct acpi_gpio_info info; | 326 | struct acpi_gpio_info info; |
292 | int index; | 327 | int index; |
328 | int pin_index; | ||
293 | struct gpio_desc *desc; | 329 | struct gpio_desc *desc; |
294 | int n; | 330 | int n; |
295 | }; | 331 | }; |
@@ -303,13 +339,24 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) | |||
303 | 339 | ||
304 | if (lookup->n++ == lookup->index && !lookup->desc) { | 340 | if (lookup->n++ == lookup->index && !lookup->desc) { |
305 | const struct acpi_resource_gpio *agpio = &ares->data.gpio; | 341 | const struct acpi_resource_gpio *agpio = &ares->data.gpio; |
342 | int pin_index = lookup->pin_index; | ||
343 | |||
344 | if (pin_index >= agpio->pin_table_length) | ||
345 | return 1; | ||
306 | 346 | ||
307 | lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr, | 347 | lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr, |
308 | agpio->pin_table[0]); | 348 | agpio->pin_table[pin_index]); |
309 | lookup->info.gpioint = | 349 | lookup->info.gpioint = |
310 | agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT; | 350 | agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT; |
311 | lookup->info.active_low = | 351 | |
312 | agpio->polarity == ACPI_ACTIVE_LOW; | 352 | /* |
353 | * ActiveLow is only specified for GpioInt resource. If | ||
354 | * GpioIo is used then the only way to set the flag is | ||
355 | * to use _DSD "gpios" property. | ||
356 | */ | ||
357 | if (lookup->info.gpioint) | ||
358 | lookup->info.active_low = | ||
359 | agpio->polarity == ACPI_ACTIVE_LOW; | ||
313 | } | 360 | } |
314 | 361 | ||
315 | return 1; | 362 | return 1; |
@@ -317,40 +364,79 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) | |||
317 | 364 | ||
318 | /** | 365 | /** |
319 | * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources | 366 | * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources |
320 | * @dev: pointer to a device to get GPIO from | 367 | * @adev: pointer to a ACPI device to get GPIO from |
368 | * @propname: Property name of the GPIO (optional) | ||
321 | * @index: index of GpioIo/GpioInt resource (starting from %0) | 369 | * @index: index of GpioIo/GpioInt resource (starting from %0) |
322 | * @info: info pointer to fill in (optional) | 370 | * @info: info pointer to fill in (optional) |
323 | * | 371 | * |
324 | * Function goes through ACPI resources for @dev and based on @index looks | 372 | * Function goes through ACPI resources for @adev and based on @index looks |
325 | * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor, | 373 | * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor, |
326 | * and returns it. @index matches GpioIo/GpioInt resources only so if there | 374 | * and returns it. @index matches GpioIo/GpioInt resources only so if there |
327 | * are total %3 GPIO resources, the index goes from %0 to %2. | 375 | * are total %3 GPIO resources, the index goes from %0 to %2. |
328 | * | 376 | * |
377 | * If @propname is specified the GPIO is looked using device property. In | ||
378 | * that case @index is used to select the GPIO entry in the property value | ||
379 | * (in case of multiple). | ||
380 | * | ||
329 | * If the GPIO cannot be translated or there is an error an ERR_PTR is | 381 | * If the GPIO cannot be translated or there is an error an ERR_PTR is |
330 | * returned. | 382 | * returned. |
331 | * | 383 | * |
332 | * Note: if the GPIO resource has multiple entries in the pin list, this | 384 | * Note: if the GPIO resource has multiple entries in the pin list, this |
333 | * function only returns the first. | 385 | * function only returns the first. |
334 | */ | 386 | */ |
335 | struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, | 387 | struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, |
388 | const char *propname, int index, | ||
336 | struct acpi_gpio_info *info) | 389 | struct acpi_gpio_info *info) |
337 | { | 390 | { |
338 | struct acpi_gpio_lookup lookup; | 391 | struct acpi_gpio_lookup lookup; |
339 | struct list_head resource_list; | 392 | struct list_head resource_list; |
340 | struct acpi_device *adev; | 393 | bool active_low = false; |
341 | acpi_handle handle; | ||
342 | int ret; | 394 | int ret; |
343 | 395 | ||
344 | if (!dev) | 396 | if (!adev) |
345 | return ERR_PTR(-EINVAL); | ||
346 | |||
347 | handle = ACPI_HANDLE(dev); | ||
348 | if (!handle || acpi_bus_get_device(handle, &adev)) | ||
349 | return ERR_PTR(-ENODEV); | 397 | return ERR_PTR(-ENODEV); |
350 | 398 | ||
351 | memset(&lookup, 0, sizeof(lookup)); | 399 | memset(&lookup, 0, sizeof(lookup)); |
352 | lookup.index = index; | 400 | lookup.index = index; |
353 | 401 | ||
402 | if (propname) { | ||
403 | struct acpi_reference_args args; | ||
404 | |||
405 | dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname); | ||
406 | |||
407 | memset(&args, 0, sizeof(args)); | ||
408 | ret = acpi_dev_get_property_reference(adev, propname, | ||
409 | index, &args); | ||
410 | if (ret) { | ||
411 | bool found = acpi_get_driver_gpio_data(adev, propname, | ||
412 | index, &args); | ||
413 | if (!found) | ||
414 | return ERR_PTR(ret); | ||
415 | } | ||
416 | |||
417 | /* | ||
418 | * The property was found and resolved so need to | ||
419 | * lookup the GPIO based on returned args instead. | ||
420 | */ | ||
421 | adev = args.adev; | ||
422 | if (args.nargs >= 2) { | ||
423 | lookup.index = args.args[0]; | ||
424 | lookup.pin_index = args.args[1]; | ||
425 | /* | ||
426 | * 3rd argument, if present is used to | ||
427 | * specify active_low. | ||
428 | */ | ||
429 | if (args.nargs >= 3) | ||
430 | active_low = !!args.args[2]; | ||
431 | } | ||
432 | |||
433 | dev_dbg(&adev->dev, "GPIO: _DSD returned %s %zd %llu %llu %llu\n", | ||
434 | dev_name(&adev->dev), args.nargs, | ||
435 | args.args[0], args.args[1], args.args[2]); | ||
436 | } else { | ||
437 | dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index); | ||
438 | } | ||
439 | |||
354 | INIT_LIST_HEAD(&resource_list); | 440 | INIT_LIST_HEAD(&resource_list); |
355 | ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio, | 441 | ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio, |
356 | &lookup); | 442 | &lookup); |
@@ -359,8 +445,11 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, | |||
359 | 445 | ||
360 | acpi_dev_free_resource_list(&resource_list); | 446 | acpi_dev_free_resource_list(&resource_list); |
361 | 447 | ||
362 | if (lookup.desc && info) | 448 | if (lookup.desc && info) { |
363 | *info = lookup.info; | 449 | *info = lookup.info; |
450 | if (active_low) | ||
451 | info->active_low = active_low; | ||
452 | } | ||
364 | 453 | ||
365 | return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT); | 454 | return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT); |
366 | } | 455 | } |
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e8e98ca25ec7..58659dbe702a 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -1505,14 +1505,36 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, | |||
1505 | unsigned int idx, | 1505 | unsigned int idx, |
1506 | enum gpio_lookup_flags *flags) | 1506 | enum gpio_lookup_flags *flags) |
1507 | { | 1507 | { |
1508 | static const char * const suffixes[] = { "gpios", "gpio" }; | ||
1509 | struct acpi_device *adev = ACPI_COMPANION(dev); | ||
1508 | struct acpi_gpio_info info; | 1510 | struct acpi_gpio_info info; |
1509 | struct gpio_desc *desc; | 1511 | struct gpio_desc *desc; |
1512 | char propname[32]; | ||
1513 | int i; | ||
1510 | 1514 | ||
1511 | desc = acpi_get_gpiod_by_index(dev, idx, &info); | 1515 | /* Try first from _DSD */ |
1512 | if (IS_ERR(desc)) | 1516 | for (i = 0; i < ARRAY_SIZE(suffixes); i++) { |
1513 | return desc; | 1517 | if (con_id && strcmp(con_id, "gpios")) { |
1518 | snprintf(propname, sizeof(propname), "%s-%s", | ||
1519 | con_id, suffixes[i]); | ||
1520 | } else { | ||
1521 | snprintf(propname, sizeof(propname), "%s", | ||
1522 | suffixes[i]); | ||
1523 | } | ||
1524 | |||
1525 | desc = acpi_get_gpiod_by_index(adev, propname, idx, &info); | ||
1526 | if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER)) | ||
1527 | break; | ||
1528 | } | ||
1514 | 1529 | ||
1515 | if (info.gpioint && info.active_low) | 1530 | /* Then from plain _CRS GPIOs */ |
1531 | if (IS_ERR(desc)) { | ||
1532 | desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info); | ||
1533 | if (IS_ERR(desc)) | ||
1534 | return desc; | ||
1535 | } | ||
1536 | |||
1537 | if (info.active_low) | ||
1516 | *flags |= GPIO_ACTIVE_LOW; | 1538 | *flags |= GPIO_ACTIVE_LOW; |
1517 | 1539 | ||
1518 | return desc; | 1540 | return desc; |
@@ -1713,6 +1735,61 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev, | |||
1713 | EXPORT_SYMBOL_GPL(__gpiod_get_index); | 1735 | EXPORT_SYMBOL_GPL(__gpiod_get_index); |
1714 | 1736 | ||
1715 | /** | 1737 | /** |
1738 | * fwnode_get_named_gpiod - obtain a GPIO from firmware node | ||
1739 | * @fwnode: handle of the firmware node | ||
1740 | * @propname: name of the firmware property representing the GPIO | ||
1741 | * | ||
1742 | * This function can be used for drivers that get their configuration | ||
1743 | * from firmware. | ||
1744 | * | ||
1745 | * Function properly finds the corresponding GPIO using whatever is the | ||
1746 | * underlying firmware interface and then makes sure that the GPIO | ||
1747 | * descriptor is requested before it is returned to the caller. | ||
1748 | * | ||
1749 | * In case of error an ERR_PTR() is returned. | ||
1750 | */ | ||
1751 | struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, | ||
1752 | const char *propname) | ||
1753 | { | ||
1754 | struct gpio_desc *desc = ERR_PTR(-ENODEV); | ||
1755 | bool active_low = false; | ||
1756 | int ret; | ||
1757 | |||
1758 | if (!fwnode) | ||
1759 | return ERR_PTR(-EINVAL); | ||
1760 | |||
1761 | if (is_of_node(fwnode)) { | ||
1762 | enum of_gpio_flags flags; | ||
1763 | |||
1764 | desc = of_get_named_gpiod_flags(of_node(fwnode), propname, 0, | ||
1765 | &flags); | ||
1766 | if (!IS_ERR(desc)) | ||
1767 | active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
1768 | } else if (is_acpi_node(fwnode)) { | ||
1769 | struct acpi_gpio_info info; | ||
1770 | |||
1771 | desc = acpi_get_gpiod_by_index(acpi_node(fwnode), propname, 0, | ||
1772 | &info); | ||
1773 | if (!IS_ERR(desc)) | ||
1774 | active_low = info.active_low; | ||
1775 | } | ||
1776 | |||
1777 | if (IS_ERR(desc)) | ||
1778 | return desc; | ||
1779 | |||
1780 | ret = gpiod_request(desc, NULL); | ||
1781 | if (ret) | ||
1782 | return ERR_PTR(ret); | ||
1783 | |||
1784 | /* Only value flag can be set from both DT and ACPI is active_low */ | ||
1785 | if (active_low) | ||
1786 | set_bit(FLAG_ACTIVE_LOW, &desc->flags); | ||
1787 | |||
1788 | return desc; | ||
1789 | } | ||
1790 | EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod); | ||
1791 | |||
1792 | /** | ||
1716 | * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO | 1793 | * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO |
1717 | * function | 1794 | * function |
1718 | * @dev: GPIO consumer, can be NULL for system-global GPIOs | 1795 | * @dev: GPIO consumer, can be NULL for system-global GPIOs |
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 9db2b6a71c5d..e3a52113a541 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h | |||
@@ -34,7 +34,8 @@ void acpi_gpiochip_remove(struct gpio_chip *chip); | |||
34 | void acpi_gpiochip_request_interrupts(struct gpio_chip *chip); | 34 | void acpi_gpiochip_request_interrupts(struct gpio_chip *chip); |
35 | void acpi_gpiochip_free_interrupts(struct gpio_chip *chip); | 35 | void acpi_gpiochip_free_interrupts(struct gpio_chip *chip); |
36 | 36 | ||
37 | struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, | 37 | struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, |
38 | const char *propname, int index, | ||
38 | struct acpi_gpio_info *info); | 39 | struct acpi_gpio_info *info); |
39 | #else | 40 | #else |
40 | static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } | 41 | static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } |
@@ -47,8 +48,8 @@ static inline void | |||
47 | acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { } | 48 | acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { } |
48 | 49 | ||
49 | static inline struct gpio_desc * | 50 | static inline struct gpio_desc * |
50 | acpi_get_gpiod_by_index(struct device *dev, int index, | 51 | acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname, |
51 | struct acpi_gpio_info *info) | 52 | int index, struct acpi_gpio_info *info) |
52 | { | 53 | { |
53 | return ERR_PTR(-ENOSYS); | 54 | return ERR_PTR(-ENOSYS); |
54 | } | 55 | } |