Commit | Line | Data |
---|---|---|
aeec56e3 | 1 | /* |
c103de24 | 2 | * Generic driver for memory-mapped GPIO controllers. |
aeec56e3 AV |
3 | * |
4 | * Copyright 2008 MontaVista Software, Inc. | |
5 | * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
9 | * Free Software Foundation; either version 2 of the License, or (at your | |
10 | * option) any later version. | |
11 | * | |
12 | * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`....... | |
13 | * ...`` ```````.. | |
14 | * ..The simplest form of a GPIO controller that the driver supports is`` | |
15 | * `.just a single "data" register, where GPIO state can be read and/or ` | |
16 | * `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.``````` | |
17 | * ````````` | |
18 | ___ | |
19 | _/~~|___/~| . ```~~~~~~ ___/___\___ ,~.`.`.`.`````.~~...,,,,... | |
20 | __________|~$@~~~ %~ /o*o*o*o*o*o\ .. Implementing such a GPIO . | |
21 | o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` | |
22 | `....trivial..'~`.```.``` | |
23 | * ``````` | |
24 | * .```````~~~~`..`.``.``. | |
25 | * . The driver supports `... ,..```.`~~~```````````````....````.``,, | |
26 | * . big-endian notation, just`. .. A bit more sophisticated controllers , | |
27 | * . register the device with -be`. .with a pair of set/clear-bit registers , | |
28 | * `.. suffix. ```~~`````....`.` . affecting the data register and the .` | |
29 | * ``.`.``...``` ```.. output pins are also supported.` | |
30 | * ^^ `````.`````````.,``~``~``~~`````` | |
31 | * . ^^ | |
32 | * ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`.. | |
33 | * .. The expectation is that in at least some cases . ,-~~~-, | |
34 | * .this will be used with roll-your-own ASIC/FPGA .` \ / | |
35 | * .logic in Verilog or VHDL. ~~~`````````..`````~~` \ / | |
36 | * ..````````......``````````` \o_ | |
37 | * | | |
38 | * ^^ / \ | |
39 | * | |
40 | * ...`````~~`.....``.`..........``````.`.``.```........``. | |
41 | * ` 8, 16, 32 and 64 bits registers are supported, and``. | |
42 | * . the number of GPIOs is determined by the width of ~ | |
43 | * .. the registers. ,............```.`.`..`.`.~~~.`.`.`~ | |
44 | * `.......````.``` | |
45 | */ | |
46 | ||
47 | #include <linux/init.h> | |
280df6b3 | 48 | #include <linux/err.h> |
aeec56e3 AV |
49 | #include <linux/bug.h> |
50 | #include <linux/kernel.h> | |
51 | #include <linux/module.h> | |
52 | #include <linux/spinlock.h> | |
53 | #include <linux/compiler.h> | |
54 | #include <linux/types.h> | |
55 | #include <linux/errno.h> | |
56 | #include <linux/log2.h> | |
57 | #include <linux/ioport.h> | |
58 | #include <linux/io.h> | |
59 | #include <linux/gpio.h> | |
60 | #include <linux/slab.h> | |
4b63739e | 61 | #include <linux/bitops.h> |
aeec56e3 AV |
62 | #include <linux/platform_device.h> |
63 | #include <linux/mod_devicetable.h> | |
64 | #include <linux/basic_mmio_gpio.h> | |
65 | ||
8467afec | 66 | static void bgpio_write8(void __iomem *reg, unsigned long data) |
aeec56e3 | 67 | { |
fd996235 | 68 | writeb(data, reg); |
aeec56e3 AV |
69 | } |
70 | ||
8467afec | 71 | static unsigned long bgpio_read8(void __iomem *reg) |
aeec56e3 | 72 | { |
fd996235 | 73 | return readb(reg); |
8467afec JI |
74 | } |
75 | ||
76 | static void bgpio_write16(void __iomem *reg, unsigned long data) | |
77 | { | |
fd996235 | 78 | writew(data, reg); |
8467afec JI |
79 | } |
80 | ||
81 | static unsigned long bgpio_read16(void __iomem *reg) | |
82 | { | |
fd996235 | 83 | return readw(reg); |
8467afec JI |
84 | } |
85 | ||
86 | static void bgpio_write32(void __iomem *reg, unsigned long data) | |
87 | { | |
fd996235 | 88 | writel(data, reg); |
8467afec JI |
89 | } |
90 | ||
91 | static unsigned long bgpio_read32(void __iomem *reg) | |
92 | { | |
fd996235 | 93 | return readl(reg); |
8467afec JI |
94 | } |
95 | ||
aeec56e3 | 96 | #if BITS_PER_LONG >= 64 |
8467afec JI |
97 | static void bgpio_write64(void __iomem *reg, unsigned long data) |
98 | { | |
fd996235 | 99 | writeq(data, reg); |
8467afec JI |
100 | } |
101 | ||
102 | static unsigned long bgpio_read64(void __iomem *reg) | |
103 | { | |
fd996235 | 104 | return readq(reg); |
aeec56e3 | 105 | } |
8467afec | 106 | #endif /* BITS_PER_LONG >= 64 */ |
aeec56e3 | 107 | |
2b78f1e1 AL |
108 | static void bgpio_write16be(void __iomem *reg, unsigned long data) |
109 | { | |
110 | iowrite16be(data, reg); | |
111 | } | |
112 | ||
113 | static unsigned long bgpio_read16be(void __iomem *reg) | |
114 | { | |
115 | return ioread16be(reg); | |
116 | } | |
117 | ||
118 | static void bgpio_write32be(void __iomem *reg, unsigned long data) | |
119 | { | |
120 | iowrite32be(data, reg); | |
121 | } | |
122 | ||
123 | static unsigned long bgpio_read32be(void __iomem *reg) | |
124 | { | |
125 | return ioread32be(reg); | |
126 | } | |
127 | ||
aeec56e3 AV |
128 | static unsigned long bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin) |
129 | { | |
4b63739e | 130 | return BIT(pin); |
8467afec JI |
131 | } |
132 | ||
133 | static unsigned long bgpio_pin2mask_be(struct bgpio_chip *bgc, | |
134 | unsigned int pin) | |
135 | { | |
4b63739e | 136 | return BIT(bgc->bits - 1 - pin); |
aeec56e3 AV |
137 | } |
138 | ||
b19e7f51 VZ |
139 | static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio) |
140 | { | |
141 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | |
142 | unsigned long pinmask = bgc->pin2mask(bgc, gpio); | |
143 | ||
144 | if (bgc->dir & pinmask) | |
67a76aaf | 145 | return !!(bgc->read_reg(bgc->reg_set) & pinmask); |
b19e7f51 | 146 | else |
67a76aaf | 147 | return !!(bgc->read_reg(bgc->reg_dat) & pinmask); |
b19e7f51 VZ |
148 | } |
149 | ||
aeec56e3 AV |
150 | static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) |
151 | { | |
152 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | |
153 | ||
25b35da7 | 154 | return !!(bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio)); |
aeec56e3 AV |
155 | } |
156 | ||
91492a44 RV |
157 | static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val) |
158 | { | |
159 | } | |
160 | ||
aeec56e3 AV |
161 | static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) |
162 | { | |
163 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | |
8467afec | 164 | unsigned long mask = bgc->pin2mask(bgc, gpio); |
aeec56e3 AV |
165 | unsigned long flags; |
166 | ||
aeec56e3 AV |
167 | spin_lock_irqsave(&bgc->lock, flags); |
168 | ||
169 | if (val) | |
170 | bgc->data |= mask; | |
171 | else | |
172 | bgc->data &= ~mask; | |
173 | ||
8467afec | 174 | bgc->write_reg(bgc->reg_dat, bgc->data); |
aeec56e3 AV |
175 | |
176 | spin_unlock_irqrestore(&bgc->lock, flags); | |
177 | } | |
178 | ||
e027d6f9 JI |
179 | static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, |
180 | int val) | |
181 | { | |
182 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | |
183 | unsigned long mask = bgc->pin2mask(bgc, gpio); | |
184 | ||
185 | if (val) | |
186 | bgc->write_reg(bgc->reg_set, mask); | |
187 | else | |
188 | bgc->write_reg(bgc->reg_clr, mask); | |
189 | } | |
190 | ||
dd86a0cc JI |
191 | static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) |
192 | { | |
193 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | |
194 | unsigned long mask = bgc->pin2mask(bgc, gpio); | |
195 | unsigned long flags; | |
196 | ||
197 | spin_lock_irqsave(&bgc->lock, flags); | |
198 | ||
199 | if (val) | |
200 | bgc->data |= mask; | |
201 | else | |
202 | bgc->data &= ~mask; | |
203 | ||
204 | bgc->write_reg(bgc->reg_set, bgc->data); | |
205 | ||
206 | spin_unlock_irqrestore(&bgc->lock, flags); | |
207 | } | |
208 | ||
73c4ceda RI |
209 | static void bgpio_multiple_get_masks(struct bgpio_chip *bgc, |
210 | unsigned long *mask, unsigned long *bits, | |
211 | unsigned long *set_mask, | |
212 | unsigned long *clear_mask) | |
213 | { | |
214 | int i; | |
215 | ||
216 | *set_mask = 0; | |
217 | *clear_mask = 0; | |
218 | ||
219 | for (i = 0; i < bgc->bits; i++) { | |
220 | if (*mask == 0) | |
221 | break; | |
222 | if (__test_and_clear_bit(i, mask)) { | |
223 | if (test_bit(i, bits)) | |
224 | *set_mask |= bgc->pin2mask(bgc, i); | |
225 | else | |
226 | *clear_mask |= bgc->pin2mask(bgc, i); | |
227 | } | |
228 | } | |
229 | } | |
230 | ||
231 | static void bgpio_set_multiple_single_reg(struct bgpio_chip *bgc, | |
232 | unsigned long *mask, | |
233 | unsigned long *bits, | |
234 | void __iomem *reg) | |
235 | { | |
236 | unsigned long flags; | |
237 | unsigned long set_mask, clear_mask; | |
238 | ||
239 | spin_lock_irqsave(&bgc->lock, flags); | |
240 | ||
241 | bgpio_multiple_get_masks(bgc, mask, bits, &set_mask, &clear_mask); | |
242 | ||
243 | bgc->data |= set_mask; | |
244 | bgc->data &= ~clear_mask; | |
245 | ||
246 | bgc->write_reg(reg, bgc->data); | |
247 | ||
248 | spin_unlock_irqrestore(&bgc->lock, flags); | |
249 | } | |
250 | ||
251 | static void bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, | |
252 | unsigned long *bits) | |
253 | { | |
254 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | |
255 | ||
256 | bgpio_set_multiple_single_reg(bgc, mask, bits, bgc->reg_dat); | |
257 | } | |
258 | ||
259 | static void bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask, | |
260 | unsigned long *bits) | |
261 | { | |
262 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | |
263 | ||
264 | bgpio_set_multiple_single_reg(bgc, mask, bits, bgc->reg_set); | |
265 | } | |
266 | ||
267 | static void bgpio_set_multiple_with_clear(struct gpio_chip *gc, | |
268 | unsigned long *mask, | |
269 | unsigned long *bits) | |
270 | { | |
271 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | |
272 | unsigned long set_mask, clear_mask; | |
273 | ||
274 | bgpio_multiple_get_masks(bgc, mask, bits, &set_mask, &clear_mask); | |
275 | ||
276 | if (set_mask) | |
277 | bgc->write_reg(bgc->reg_set, set_mask); | |
278 | if (clear_mask) | |
279 | bgc->write_reg(bgc->reg_clr, clear_mask); | |
280 | } | |
281 | ||
31029116 JI |
282 | static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) |
283 | { | |
284 | return 0; | |
285 | } | |
286 | ||
91492a44 RV |
287 | static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio, |
288 | int val) | |
289 | { | |
290 | return -EINVAL; | |
291 | } | |
292 | ||
31029116 JI |
293 | static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio, |
294 | int val) | |
295 | { | |
296 | gc->set(gc, gpio, val); | |
297 | ||
298 | return 0; | |
299 | } | |
300 | ||
aeec56e3 AV |
301 | static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) |
302 | { | |
31029116 JI |
303 | struct bgpio_chip *bgc = to_bgpio_chip(gc); |
304 | unsigned long flags; | |
305 | ||
306 | spin_lock_irqsave(&bgc->lock, flags); | |
307 | ||
308 | bgc->dir &= ~bgc->pin2mask(bgc, gpio); | |
309 | bgc->write_reg(bgc->reg_dir, bgc->dir); | |
310 | ||
311 | spin_unlock_irqrestore(&bgc->lock, flags); | |
312 | ||
aeec56e3 AV |
313 | return 0; |
314 | } | |
315 | ||
db3b0fcc PZ |
316 | static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) |
317 | { | |
318 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | |
319 | ||
320 | return (bgc->read_reg(bgc->reg_dir) & bgc->pin2mask(bgc, gpio)) ? | |
321 | GPIOF_DIR_OUT : GPIOF_DIR_IN; | |
322 | } | |
323 | ||
aeec56e3 AV |
324 | static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) |
325 | { | |
31029116 JI |
326 | struct bgpio_chip *bgc = to_bgpio_chip(gc); |
327 | unsigned long flags; | |
328 | ||
329 | gc->set(gc, gpio, val); | |
330 | ||
331 | spin_lock_irqsave(&bgc->lock, flags); | |
332 | ||
333 | bgc->dir |= bgc->pin2mask(bgc, gpio); | |
334 | bgc->write_reg(bgc->reg_dir, bgc->dir); | |
335 | ||
336 | spin_unlock_irqrestore(&bgc->lock, flags); | |
337 | ||
338 | return 0; | |
339 | } | |
340 | ||
341 | static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio) | |
342 | { | |
343 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | |
344 | unsigned long flags; | |
345 | ||
346 | spin_lock_irqsave(&bgc->lock, flags); | |
347 | ||
348 | bgc->dir |= bgc->pin2mask(bgc, gpio); | |
349 | bgc->write_reg(bgc->reg_dir, bgc->dir); | |
350 | ||
351 | spin_unlock_irqrestore(&bgc->lock, flags); | |
352 | ||
353 | return 0; | |
354 | } | |
355 | ||
356 | static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val) | |
357 | { | |
358 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | |
359 | unsigned long flags; | |
360 | ||
e027d6f9 JI |
361 | gc->set(gc, gpio, val); |
362 | ||
31029116 JI |
363 | spin_lock_irqsave(&bgc->lock, flags); |
364 | ||
365 | bgc->dir &= ~bgc->pin2mask(bgc, gpio); | |
366 | bgc->write_reg(bgc->reg_dir, bgc->dir); | |
367 | ||
368 | spin_unlock_irqrestore(&bgc->lock, flags); | |
369 | ||
aeec56e3 AV |
370 | return 0; |
371 | } | |
372 | ||
db3b0fcc PZ |
373 | static int bgpio_get_dir_inv(struct gpio_chip *gc, unsigned int gpio) |
374 | { | |
375 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | |
376 | ||
377 | return (bgc->read_reg(bgc->reg_dir) & bgc->pin2mask(bgc, gpio)) ? | |
378 | GPIOF_DIR_IN : GPIOF_DIR_OUT; | |
379 | } | |
380 | ||
280df6b3 JI |
381 | static int bgpio_setup_accessors(struct device *dev, |
382 | struct bgpio_chip *bgc, | |
2b78f1e1 AL |
383 | bool bit_be, |
384 | bool byte_be) | |
aeec56e3 | 385 | { |
8467afec JI |
386 | |
387 | switch (bgc->bits) { | |
388 | case 8: | |
389 | bgc->read_reg = bgpio_read8; | |
390 | bgc->write_reg = bgpio_write8; | |
391 | break; | |
392 | case 16: | |
2b78f1e1 AL |
393 | if (byte_be) { |
394 | bgc->read_reg = bgpio_read16be; | |
395 | bgc->write_reg = bgpio_write16be; | |
396 | } else { | |
397 | bgc->read_reg = bgpio_read16; | |
398 | bgc->write_reg = bgpio_write16; | |
399 | } | |
8467afec JI |
400 | break; |
401 | case 32: | |
2b78f1e1 AL |
402 | if (byte_be) { |
403 | bgc->read_reg = bgpio_read32be; | |
404 | bgc->write_reg = bgpio_write32be; | |
405 | } else { | |
406 | bgc->read_reg = bgpio_read32; | |
407 | bgc->write_reg = bgpio_write32; | |
408 | } | |
8467afec JI |
409 | break; |
410 | #if BITS_PER_LONG >= 64 | |
411 | case 64: | |
2b78f1e1 AL |
412 | if (byte_be) { |
413 | dev_err(dev, | |
414 | "64 bit big endian byte order unsupported\n"); | |
415 | return -EINVAL; | |
416 | } else { | |
417 | bgc->read_reg = bgpio_read64; | |
418 | bgc->write_reg = bgpio_write64; | |
419 | } | |
8467afec JI |
420 | break; |
421 | #endif /* BITS_PER_LONG >= 64 */ | |
422 | default: | |
280df6b3 | 423 | dev_err(dev, "unsupported data width %u bits\n", bgc->bits); |
8467afec JI |
424 | return -EINVAL; |
425 | } | |
426 | ||
2b78f1e1 | 427 | bgc->pin2mask = bit_be ? bgpio_pin2mask_be : bgpio_pin2mask; |
8467afec JI |
428 | |
429 | return 0; | |
430 | } | |
431 | ||
e027d6f9 JI |
432 | /* |
433 | * Create the device and allocate the resources. For setting GPIO's there are | |
dd86a0cc | 434 | * three supported configurations: |
e027d6f9 | 435 | * |
dd86a0cc | 436 | * - single input/output register resource (named "dat"). |
e027d6f9 | 437 | * - set/clear pair (named "set" and "clr"). |
dd86a0cc JI |
438 | * - single output register resource and single input resource ("set" and |
439 | * dat"). | |
e027d6f9 JI |
440 | * |
441 | * For the single output register, this drives a 1 by setting a bit and a zero | |
442 | * by clearing a bit. For the set clr pair, this drives a 1 by setting a bit | |
443 | * in the set register and clears it by setting a bit in the clear register. | |
444 | * The configuration is detected by which resources are present. | |
31029116 JI |
445 | * |
446 | * For setting the GPIO direction, there are three supported configurations: | |
447 | * | |
448 | * - simple bidirection GPIO that requires no configuration. | |
449 | * - an output direction register (named "dirout") where a 1 bit | |
450 | * indicates the GPIO is an output. | |
451 | * - an input direction register (named "dirin") where a 1 bit indicates | |
452 | * the GPIO is an input. | |
e027d6f9 | 453 | */ |
280df6b3 JI |
454 | static int bgpio_setup_io(struct bgpio_chip *bgc, |
455 | void __iomem *dat, | |
456 | void __iomem *set, | |
b19e7f51 VZ |
457 | void __iomem *clr, |
458 | unsigned long flags) | |
8467afec | 459 | { |
aeec56e3 | 460 | |
280df6b3 | 461 | bgc->reg_dat = dat; |
aeec56e3 | 462 | if (!bgc->reg_dat) |
280df6b3 | 463 | return -EINVAL; |
e027d6f9 | 464 | |
280df6b3 JI |
465 | if (set && clr) { |
466 | bgc->reg_set = set; | |
467 | bgc->reg_clr = clr; | |
e027d6f9 | 468 | bgc->gc.set = bgpio_set_with_clear; |
73c4ceda | 469 | bgc->gc.set_multiple = bgpio_set_multiple_with_clear; |
280df6b3 JI |
470 | } else if (set && !clr) { |
471 | bgc->reg_set = set; | |
dd86a0cc | 472 | bgc->gc.set = bgpio_set_set; |
73c4ceda | 473 | bgc->gc.set_multiple = bgpio_set_multiple_set; |
91492a44 RV |
474 | } else if (flags & BGPIOF_NO_OUTPUT) { |
475 | bgc->gc.set = bgpio_set_none; | |
476 | bgc->gc.set_multiple = NULL; | |
e027d6f9 JI |
477 | } else { |
478 | bgc->gc.set = bgpio_set; | |
73c4ceda | 479 | bgc->gc.set_multiple = bgpio_set_multiple; |
aeec56e3 AV |
480 | } |
481 | ||
b19e7f51 VZ |
482 | if (!(flags & BGPIOF_UNREADABLE_REG_SET) && |
483 | (flags & BGPIOF_READ_OUTPUT_REG_SET)) | |
484 | bgc->gc.get = bgpio_get_set; | |
485 | else | |
486 | bgc->gc.get = bgpio_get; | |
dd86a0cc | 487 | |
e027d6f9 JI |
488 | return 0; |
489 | } | |
490 | ||
280df6b3 JI |
491 | static int bgpio_setup_direction(struct bgpio_chip *bgc, |
492 | void __iomem *dirout, | |
91492a44 RV |
493 | void __iomem *dirin, |
494 | unsigned long flags) | |
31029116 | 495 | { |
280df6b3 | 496 | if (dirout && dirin) { |
31029116 | 497 | return -EINVAL; |
280df6b3 JI |
498 | } else if (dirout) { |
499 | bgc->reg_dir = dirout; | |
31029116 JI |
500 | bgc->gc.direction_output = bgpio_dir_out; |
501 | bgc->gc.direction_input = bgpio_dir_in; | |
db3b0fcc | 502 | bgc->gc.get_direction = bgpio_get_dir; |
280df6b3 JI |
503 | } else if (dirin) { |
504 | bgc->reg_dir = dirin; | |
31029116 JI |
505 | bgc->gc.direction_output = bgpio_dir_out_inv; |
506 | bgc->gc.direction_input = bgpio_dir_in_inv; | |
db3b0fcc | 507 | bgc->gc.get_direction = bgpio_get_dir_inv; |
31029116 | 508 | } else { |
91492a44 RV |
509 | if (flags & BGPIOF_NO_OUTPUT) |
510 | bgc->gc.direction_output = bgpio_dir_out_err; | |
511 | else | |
512 | bgc->gc.direction_output = bgpio_simple_dir_out; | |
31029116 JI |
513 | bgc->gc.direction_input = bgpio_simple_dir_in; |
514 | } | |
515 | ||
516 | return 0; | |
517 | } | |
518 | ||
7b42e3db AF |
519 | static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin) |
520 | { | |
521 | if (gpio_pin < chip->ngpio) | |
522 | return 0; | |
523 | ||
524 | return -EINVAL; | |
525 | } | |
526 | ||
4f5b0480 | 527 | int bgpio_remove(struct bgpio_chip *bgc) |
280df6b3 | 528 | { |
9f5132ae | 529 | gpiochip_remove(&bgc->gc); |
530 | return 0; | |
280df6b3 JI |
531 | } |
532 | EXPORT_SYMBOL_GPL(bgpio_remove); | |
533 | ||
4f5b0480 RK |
534 | int bgpio_init(struct bgpio_chip *bgc, struct device *dev, |
535 | unsigned long sz, void __iomem *dat, void __iomem *set, | |
536 | void __iomem *clr, void __iomem *dirout, void __iomem *dirin, | |
3e11f7b8 | 537 | unsigned long flags) |
e027d6f9 | 538 | { |
e027d6f9 | 539 | int ret; |
e027d6f9 | 540 | |
280df6b3 JI |
541 | if (!is_power_of_2(sz)) |
542 | return -EINVAL; | |
e027d6f9 | 543 | |
280df6b3 JI |
544 | bgc->bits = sz * 8; |
545 | if (bgc->bits > BITS_PER_LONG) | |
546 | return -EINVAL; | |
547 | ||
548 | spin_lock_init(&bgc->lock); | |
58383c78 | 549 | bgc->gc.parent = dev; |
280df6b3 JI |
550 | bgc->gc.label = dev_name(dev); |
551 | bgc->gc.base = -1; | |
552 | bgc->gc.ngpio = bgc->bits; | |
7b42e3db | 553 | bgc->gc.request = bgpio_request; |
280df6b3 | 554 | |
b19e7f51 | 555 | ret = bgpio_setup_io(bgc, dat, set, clr, flags); |
e027d6f9 JI |
556 | if (ret) |
557 | return ret; | |
aeec56e3 | 558 | |
2b78f1e1 AL |
559 | ret = bgpio_setup_accessors(dev, bgc, flags & BGPIOF_BIG_ENDIAN, |
560 | flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER); | |
8467afec JI |
561 | if (ret) |
562 | return ret; | |
aeec56e3 | 563 | |
91492a44 | 564 | ret = bgpio_setup_direction(bgc, dirout, dirin, flags); |
31029116 JI |
565 | if (ret) |
566 | return ret; | |
567 | ||
8467afec | 568 | bgc->data = bgc->read_reg(bgc->reg_dat); |
3e11f7b8 SG |
569 | if (bgc->gc.set == bgpio_set_set && |
570 | !(flags & BGPIOF_UNREADABLE_REG_SET)) | |
571 | bgc->data = bgc->read_reg(bgc->reg_set); | |
572 | if (bgc->reg_dir && !(flags & BGPIOF_UNREADABLE_REG_DIR)) | |
573 | bgc->dir = bgc->read_reg(bgc->reg_dir); | |
924e7a9f | 574 | |
280df6b3 JI |
575 | return ret; |
576 | } | |
577 | EXPORT_SYMBOL_GPL(bgpio_init); | |
aeec56e3 | 578 | |
c103de24 | 579 | #ifdef CONFIG_GPIO_GENERIC_PLATFORM |
aeec56e3 | 580 | |
280df6b3 JI |
581 | static void __iomem *bgpio_map(struct platform_device *pdev, |
582 | const char *name, | |
8d240260 | 583 | resource_size_t sane_sz) |
280df6b3 | 584 | { |
280df6b3 | 585 | struct resource *r; |
280df6b3 | 586 | resource_size_t sz; |
280df6b3 JI |
587 | |
588 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); | |
8d240260 | 589 | if (!r) |
b2f68b63 | 590 | return NULL; |
280df6b3 JI |
591 | |
592 | sz = resource_size(r); | |
8d240260 HK |
593 | if (sz != sane_sz) |
594 | return IOMEM_ERR_PTR(-EINVAL); | |
280df6b3 | 595 | |
8d240260 | 596 | return devm_ioremap_resource(&pdev->dev, r); |
aeec56e3 AV |
597 | } |
598 | ||
3836309d | 599 | static int bgpio_pdev_probe(struct platform_device *pdev) |
280df6b3 JI |
600 | { |
601 | struct device *dev = &pdev->dev; | |
602 | struct resource *r; | |
603 | void __iomem *dat; | |
604 | void __iomem *set; | |
605 | void __iomem *clr; | |
606 | void __iomem *dirout; | |
607 | void __iomem *dirin; | |
608 | unsigned long sz; | |
19338530 | 609 | unsigned long flags = pdev->id_entry->driver_data; |
280df6b3 JI |
610 | int err; |
611 | struct bgpio_chip *bgc; | |
612 | struct bgpio_pdata *pdata = dev_get_platdata(dev); | |
613 | ||
614 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); | |
615 | if (!r) | |
616 | return -EINVAL; | |
617 | ||
618 | sz = resource_size(r); | |
619 | ||
8d240260 HK |
620 | dat = bgpio_map(pdev, "dat", sz); |
621 | if (IS_ERR(dat)) | |
622 | return PTR_ERR(dat); | |
280df6b3 | 623 | |
8d240260 HK |
624 | set = bgpio_map(pdev, "set", sz); |
625 | if (IS_ERR(set)) | |
626 | return PTR_ERR(set); | |
280df6b3 | 627 | |
8d240260 HK |
628 | clr = bgpio_map(pdev, "clr", sz); |
629 | if (IS_ERR(clr)) | |
630 | return PTR_ERR(clr); | |
280df6b3 | 631 | |
8d240260 HK |
632 | dirout = bgpio_map(pdev, "dirout", sz); |
633 | if (IS_ERR(dirout)) | |
634 | return PTR_ERR(dirout); | |
280df6b3 | 635 | |
8d240260 HK |
636 | dirin = bgpio_map(pdev, "dirin", sz); |
637 | if (IS_ERR(dirin)) | |
638 | return PTR_ERR(dirin); | |
280df6b3 | 639 | |
280df6b3 JI |
640 | bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL); |
641 | if (!bgc) | |
642 | return -ENOMEM; | |
643 | ||
3e11f7b8 | 644 | err = bgpio_init(bgc, dev, sz, dat, set, clr, dirout, dirin, flags); |
280df6b3 JI |
645 | if (err) |
646 | return err; | |
647 | ||
648 | if (pdata) { | |
781f6d71 PM |
649 | if (pdata->label) |
650 | bgc->gc.label = pdata->label; | |
280df6b3 JI |
651 | bgc->gc.base = pdata->base; |
652 | if (pdata->ngpio > 0) | |
653 | bgc->gc.ngpio = pdata->ngpio; | |
654 | } | |
655 | ||
656 | platform_set_drvdata(pdev, bgc); | |
657 | ||
658 | return gpiochip_add(&bgc->gc); | |
659 | } | |
660 | ||
206210ce | 661 | static int bgpio_pdev_remove(struct platform_device *pdev) |
aeec56e3 | 662 | { |
4ddb8ae2 | 663 | struct bgpio_chip *bgc = platform_get_drvdata(pdev); |
aeec56e3 | 664 | |
280df6b3 | 665 | return bgpio_remove(bgc); |
aeec56e3 AV |
666 | } |
667 | ||
668 | static const struct platform_device_id bgpio_id_table[] = { | |
19338530 AS |
669 | { |
670 | .name = "basic-mmio-gpio", | |
671 | .driver_data = 0, | |
672 | }, { | |
673 | .name = "basic-mmio-gpio-be", | |
674 | .driver_data = BGPIOF_BIG_ENDIAN, | |
675 | }, | |
676 | { } | |
aeec56e3 AV |
677 | }; |
678 | MODULE_DEVICE_TABLE(platform, bgpio_id_table); | |
679 | ||
680 | static struct platform_driver bgpio_driver = { | |
681 | .driver = { | |
682 | .name = "basic-mmio-gpio", | |
683 | }, | |
684 | .id_table = bgpio_id_table, | |
280df6b3 | 685 | .probe = bgpio_pdev_probe, |
8283c4ff | 686 | .remove = bgpio_pdev_remove, |
aeec56e3 AV |
687 | }; |
688 | ||
6f61415e | 689 | module_platform_driver(bgpio_driver); |
280df6b3 | 690 | |
c103de24 | 691 | #endif /* CONFIG_GPIO_GENERIC_PLATFORM */ |
aeec56e3 AV |
692 | |
693 | MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers"); | |
694 | MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>"); | |
695 | MODULE_LICENSE("GPL"); |