blob: 053a7f0a83e6d1d27e1844acd105756f39181cbd [file] [log] [blame]
Anton Vorontsovaeec56e2010-10-27 15:33:15 -07001/*
Grant Likelyc103de22011-06-04 18:38:28 -06002 * Generic driver for memory-mapped GPIO controllers.
Anton Vorontsovaeec56e2010-10-27 15:33:15 -07003 *
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 .
21o ` ~~~~\___/~~~~ ` 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>
Jamie Iles280df6b2011-05-20 00:40:19 -060048#include <linux/err.h>
Anton Vorontsovaeec56e2010-10-27 15:33:15 -070049#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>
Linus Walleij4b637392016-01-05 11:13:28 +010061#include <linux/bitops.h>
Anton Vorontsovaeec56e2010-10-27 15:33:15 -070062#include <linux/platform_device.h>
63#include <linux/mod_devicetable.h>
64#include <linux/basic_mmio_gpio.h>
65
Jamie Iles8467afe2011-05-20 00:40:14 -060066static void bgpio_write8(void __iomem *reg, unsigned long data)
Anton Vorontsovaeec56e2010-10-27 15:33:15 -070067{
Jamie Ilesfd996232011-05-20 00:40:17 -060068 writeb(data, reg);
Anton Vorontsovaeec56e2010-10-27 15:33:15 -070069}
70
Jamie Iles8467afe2011-05-20 00:40:14 -060071static unsigned long bgpio_read8(void __iomem *reg)
Anton Vorontsovaeec56e2010-10-27 15:33:15 -070072{
Jamie Ilesfd996232011-05-20 00:40:17 -060073 return readb(reg);
Anton Vorontsovaeec56e2010-10-27 15:33:15 -070074}
75
Jamie Iles8467afe2011-05-20 00:40:14 -060076static void bgpio_write16(void __iomem *reg, unsigned long data)
77{
Jamie Ilesfd996232011-05-20 00:40:17 -060078 writew(data, reg);
Jamie Iles8467afe2011-05-20 00:40:14 -060079}
80
81static unsigned long bgpio_read16(void __iomem *reg)
82{
Jamie Ilesfd996232011-05-20 00:40:17 -060083 return readw(reg);
Jamie Iles8467afe2011-05-20 00:40:14 -060084}
85
86static void bgpio_write32(void __iomem *reg, unsigned long data)
87{
Jamie Ilesfd996232011-05-20 00:40:17 -060088 writel(data, reg);
Jamie Iles8467afe2011-05-20 00:40:14 -060089}
90
91static unsigned long bgpio_read32(void __iomem *reg)
92{
Jamie Ilesfd996232011-05-20 00:40:17 -060093 return readl(reg);
Jamie Iles8467afe2011-05-20 00:40:14 -060094}
95
96#if BITS_PER_LONG >= 64
97static void bgpio_write64(void __iomem *reg, unsigned long data)
98{
Jamie Ilesfd996232011-05-20 00:40:17 -060099 writeq(data, reg);
Jamie Iles8467afe2011-05-20 00:40:14 -0600100}
101
102static unsigned long bgpio_read64(void __iomem *reg)
103{
Jamie Ilesfd996232011-05-20 00:40:17 -0600104 return readq(reg);
Jamie Iles8467afe2011-05-20 00:40:14 -0600105}
106#endif /* BITS_PER_LONG >= 64 */
107
Andreas Larsson2b78f1e2013-03-15 14:45:38 +0100108static void bgpio_write16be(void __iomem *reg, unsigned long data)
109{
110 iowrite16be(data, reg);
111}
112
113static unsigned long bgpio_read16be(void __iomem *reg)
114{
115 return ioread16be(reg);
116}
117
118static void bgpio_write32be(void __iomem *reg, unsigned long data)
119{
120 iowrite32be(data, reg);
121}
122
123static unsigned long bgpio_read32be(void __iomem *reg)
124{
125 return ioread32be(reg);
126}
127
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700128static unsigned long bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin)
129{
Linus Walleij4b637392016-01-05 11:13:28 +0100130 return BIT(pin);
Jamie Iles8467afe2011-05-20 00:40:14 -0600131}
132
133static unsigned long bgpio_pin2mask_be(struct bgpio_chip *bgc,
134 unsigned int pin)
135{
Linus Walleij4b637392016-01-05 11:13:28 +0100136 return BIT(bgc->bits - 1 - pin);
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700137}
138
Vladimir Zapolskiyb19e7f52015-04-29 18:34:59 +0300139static 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)
Linus Walleij67a76aa2015-12-10 15:55:29 +0100145 return !!(bgc->read_reg(bgc->reg_set) & pinmask);
Vladimir Zapolskiyb19e7f52015-04-29 18:34:59 +0300146 else
Linus Walleij67a76aa2015-12-10 15:55:29 +0100147 return !!(bgc->read_reg(bgc->reg_dat) & pinmask);
Vladimir Zapolskiyb19e7f52015-04-29 18:34:59 +0300148}
149
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700150static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
151{
152 struct bgpio_chip *bgc = to_bgpio_chip(gc);
153
Linus Walleij25b35da2014-02-05 14:08:02 +0100154 return !!(bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio));
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700155}
156
Rabin Vincent91492a42015-07-22 15:05:18 +0200157static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val)
158{
159}
160
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700161static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
162{
163 struct bgpio_chip *bgc = to_bgpio_chip(gc);
Jamie Iles8467afe2011-05-20 00:40:14 -0600164 unsigned long mask = bgc->pin2mask(bgc, gpio);
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700165 unsigned long flags;
166
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700167 spin_lock_irqsave(&bgc->lock, flags);
168
169 if (val)
170 bgc->data |= mask;
171 else
172 bgc->data &= ~mask;
173
Jamie Iles8467afe2011-05-20 00:40:14 -0600174 bgc->write_reg(bgc->reg_dat, bgc->data);
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700175
176 spin_unlock_irqrestore(&bgc->lock, flags);
177}
178
Jamie Ilese027d6f2011-05-20 00:40:16 -0600179static 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
Jamie Ilesdd86a0c2011-05-20 00:40:16 -0600191static 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
Rojhalat Ibrahim73c4ced2015-01-14 15:46:38 +0100209static 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
231static 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
251static 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
259static 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
267static 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
Jamie Iles31029112011-05-20 00:40:17 -0600282static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
283{
284 return 0;
285}
286
Rabin Vincent91492a42015-07-22 15:05:18 +0200287static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio,
288 int val)
289{
290 return -EINVAL;
291}
292
Jamie Iles31029112011-05-20 00:40:17 -0600293static 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
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700301static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
302{
Jamie Iles31029112011-05-20 00:40:17 -0600303 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
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700313 return 0;
314}
315
Philipp Zabeldb3b0fc2015-06-12 18:20:35 +0200316static 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
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700324static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
325{
Jamie Iles31029112011-05-20 00:40:17 -0600326 struct bgpio_chip *bgc = to_bgpio_chip(gc);
327 unsigned long flags;
328
Jamie Ilese027d6f2011-05-20 00:40:16 -0600329 gc->set(gc, gpio, val);
330
Jamie Iles31029112011-05-20 00:40:17 -0600331 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
341static 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
356static 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
361 gc->set(gc, gpio, val);
362
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
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700370 return 0;
371}
372
Philipp Zabeldb3b0fc2015-06-12 18:20:35 +0200373static 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
Jamie Iles280df6b2011-05-20 00:40:19 -0600381static int bgpio_setup_accessors(struct device *dev,
382 struct bgpio_chip *bgc,
Andreas Larsson2b78f1e2013-03-15 14:45:38 +0100383 bool bit_be,
384 bool byte_be)
Jamie Iles364b5e82011-05-20 00:40:16 -0600385{
Jamie Iles8467afe2011-05-20 00:40:14 -0600386
387 switch (bgc->bits) {
388 case 8:
389 bgc->read_reg = bgpio_read8;
390 bgc->write_reg = bgpio_write8;
391 break;
392 case 16:
Andreas Larsson2b78f1e2013-03-15 14:45:38 +0100393 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 }
Jamie Iles8467afe2011-05-20 00:40:14 -0600400 break;
401 case 32:
Andreas Larsson2b78f1e2013-03-15 14:45:38 +0100402 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 }
Jamie Iles8467afe2011-05-20 00:40:14 -0600409 break;
410#if BITS_PER_LONG >= 64
411 case 64:
Andreas Larsson2b78f1e2013-03-15 14:45:38 +0100412 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 }
Jamie Iles8467afe2011-05-20 00:40:14 -0600420 break;
421#endif /* BITS_PER_LONG >= 64 */
422 default:
Jamie Iles280df6b2011-05-20 00:40:19 -0600423 dev_err(dev, "unsupported data width %u bits\n", bgc->bits);
Jamie Iles8467afe2011-05-20 00:40:14 -0600424 return -EINVAL;
425 }
426
Andreas Larsson2b78f1e2013-03-15 14:45:38 +0100427 bgc->pin2mask = bit_be ? bgpio_pin2mask_be : bgpio_pin2mask;
Jamie Iles8467afe2011-05-20 00:40:14 -0600428
429 return 0;
430}
431
Jamie Ilese027d6f2011-05-20 00:40:16 -0600432/*
433 * Create the device and allocate the resources. For setting GPIO's there are
Jamie Ilesdd86a0c2011-05-20 00:40:16 -0600434 * three supported configurations:
Jamie Ilese027d6f2011-05-20 00:40:16 -0600435 *
Jamie Ilesdd86a0c2011-05-20 00:40:16 -0600436 * - single input/output register resource (named "dat").
Jamie Ilese027d6f2011-05-20 00:40:16 -0600437 * - set/clear pair (named "set" and "clr").
Jamie Ilesdd86a0c2011-05-20 00:40:16 -0600438 * - single output register resource and single input resource ("set" and
439 * dat").
Jamie Ilese027d6f2011-05-20 00:40:16 -0600440 *
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.
Jamie Iles31029112011-05-20 00:40:17 -0600445 *
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.
Jamie Ilese027d6f2011-05-20 00:40:16 -0600453 */
Jamie Iles280df6b2011-05-20 00:40:19 -0600454static int bgpio_setup_io(struct bgpio_chip *bgc,
455 void __iomem *dat,
456 void __iomem *set,
Vladimir Zapolskiyb19e7f52015-04-29 18:34:59 +0300457 void __iomem *clr,
458 unsigned long flags)
Jamie Iles8467afe2011-05-20 00:40:14 -0600459{
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700460
Jamie Iles280df6b2011-05-20 00:40:19 -0600461 bgc->reg_dat = dat;
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700462 if (!bgc->reg_dat)
Jamie Iles280df6b2011-05-20 00:40:19 -0600463 return -EINVAL;
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700464
Jamie Iles280df6b2011-05-20 00:40:19 -0600465 if (set && clr) {
466 bgc->reg_set = set;
467 bgc->reg_clr = clr;
Jamie Ilese027d6f2011-05-20 00:40:16 -0600468 bgc->gc.set = bgpio_set_with_clear;
Rojhalat Ibrahim73c4ced2015-01-14 15:46:38 +0100469 bgc->gc.set_multiple = bgpio_set_multiple_with_clear;
Jamie Iles280df6b2011-05-20 00:40:19 -0600470 } else if (set && !clr) {
471 bgc->reg_set = set;
Jamie Ilesdd86a0c2011-05-20 00:40:16 -0600472 bgc->gc.set = bgpio_set_set;
Rojhalat Ibrahim73c4ced2015-01-14 15:46:38 +0100473 bgc->gc.set_multiple = bgpio_set_multiple_set;
Rabin Vincent91492a42015-07-22 15:05:18 +0200474 } else if (flags & BGPIOF_NO_OUTPUT) {
475 bgc->gc.set = bgpio_set_none;
476 bgc->gc.set_multiple = NULL;
Jamie Ilese027d6f2011-05-20 00:40:16 -0600477 } else {
478 bgc->gc.set = bgpio_set;
Rojhalat Ibrahim73c4ced2015-01-14 15:46:38 +0100479 bgc->gc.set_multiple = bgpio_set_multiple;
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700480 }
481
Vladimir Zapolskiyb19e7f52015-04-29 18:34:59 +0300482 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;
Jamie Ilesdd86a0c2011-05-20 00:40:16 -0600487
Jamie Ilese027d6f2011-05-20 00:40:16 -0600488 return 0;
489}
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700490
Jamie Iles280df6b2011-05-20 00:40:19 -0600491static int bgpio_setup_direction(struct bgpio_chip *bgc,
492 void __iomem *dirout,
Rabin Vincent91492a42015-07-22 15:05:18 +0200493 void __iomem *dirin,
494 unsigned long flags)
Jamie Iles31029112011-05-20 00:40:17 -0600495{
Jamie Iles280df6b2011-05-20 00:40:19 -0600496 if (dirout && dirin) {
Jamie Iles31029112011-05-20 00:40:17 -0600497 return -EINVAL;
Jamie Iles280df6b2011-05-20 00:40:19 -0600498 } else if (dirout) {
499 bgc->reg_dir = dirout;
Jamie Iles31029112011-05-20 00:40:17 -0600500 bgc->gc.direction_output = bgpio_dir_out;
501 bgc->gc.direction_input = bgpio_dir_in;
Philipp Zabeldb3b0fc2015-06-12 18:20:35 +0200502 bgc->gc.get_direction = bgpio_get_dir;
Jamie Iles280df6b2011-05-20 00:40:19 -0600503 } else if (dirin) {
504 bgc->reg_dir = dirin;
Jamie Iles31029112011-05-20 00:40:17 -0600505 bgc->gc.direction_output = bgpio_dir_out_inv;
506 bgc->gc.direction_input = bgpio_dir_in_inv;
Philipp Zabeldb3b0fc2015-06-12 18:20:35 +0200507 bgc->gc.get_direction = bgpio_get_dir_inv;
Jamie Iles31029112011-05-20 00:40:17 -0600508 } else {
Rabin Vincent91492a42015-07-22 15:05:18 +0200509 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;
Jamie Iles31029112011-05-20 00:40:17 -0600513 bgc->gc.direction_input = bgpio_simple_dir_in;
514 }
515
516 return 0;
517}
518
Anthony Fee7b42e3d2014-05-19 18:49:14 +0100519static 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
Russell King4f5b0482011-09-14 16:22:29 -0700527int bgpio_remove(struct bgpio_chip *bgc)
Jamie Ilese027d6f2011-05-20 00:40:16 -0600528{
abdoulaye berthe9f5132a2014-07-12 22:30:12 +0200529 gpiochip_remove(&bgc->gc);
530 return 0;
Jamie Iles280df6b2011-05-20 00:40:19 -0600531}
532EXPORT_SYMBOL_GPL(bgpio_remove);
533
Russell King4f5b0482011-09-14 16:22:29 -0700534int 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,
Shawn Guo3e11f7b2012-05-19 21:34:58 +0800537 unsigned long flags)
Jamie Iles280df6b2011-05-20 00:40:19 -0600538{
Jamie Ilese027d6f2011-05-20 00:40:16 -0600539 int ret;
Jamie Ilese027d6f2011-05-20 00:40:16 -0600540
Jamie Iles280df6b2011-05-20 00:40:19 -0600541 if (!is_power_of_2(sz))
542 return -EINVAL;
Jamie Ilese027d6f2011-05-20 00:40:16 -0600543
Jamie Iles280df6b2011-05-20 00:40:19 -0600544 bgc->bits = sz * 8;
545 if (bgc->bits > BITS_PER_LONG)
546 return -EINVAL;
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700547
Jamie Ilese027d6f2011-05-20 00:40:16 -0600548 spin_lock_init(&bgc->lock);
Linus Walleij58383c782015-11-04 09:56:26 +0100549 bgc->gc.parent = dev;
Jamie Iles280df6b2011-05-20 00:40:19 -0600550 bgc->gc.label = dev_name(dev);
551 bgc->gc.base = -1;
552 bgc->gc.ngpio = bgc->bits;
Anthony Fee7b42e3d2014-05-19 18:49:14 +0100553 bgc->gc.request = bgpio_request;
Jamie Iles280df6b2011-05-20 00:40:19 -0600554
Vladimir Zapolskiyb19e7f52015-04-29 18:34:59 +0300555 ret = bgpio_setup_io(bgc, dat, set, clr, flags);
Jamie Iles280df6b2011-05-20 00:40:19 -0600556 if (ret)
557 return ret;
558
Andreas Larsson2b78f1e2013-03-15 14:45:38 +0100559 ret = bgpio_setup_accessors(dev, bgc, flags & BGPIOF_BIG_ENDIAN,
560 flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER);
Jamie Iles280df6b2011-05-20 00:40:19 -0600561 if (ret)
562 return ret;
563
Rabin Vincent91492a42015-07-22 15:05:18 +0200564 ret = bgpio_setup_direction(bgc, dirout, dirin, flags);
Jamie Iles31029112011-05-20 00:40:17 -0600565 if (ret)
566 return ret;
567
Jamie Iles8467afe2011-05-20 00:40:14 -0600568 bgc->data = bgc->read_reg(bgc->reg_dat);
Shawn Guo3e11f7b2012-05-19 21:34:58 +0800569 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);
Jamie Iles924e7a92011-05-20 00:40:15 -0600574
Jamie Iles280df6b2011-05-20 00:40:19 -0600575 return ret;
576}
577EXPORT_SYMBOL_GPL(bgpio_init);
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700578
Grant Likelyc103de22011-06-04 18:38:28 -0600579#ifdef CONFIG_GPIO_GENERIC_PLATFORM
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700580
Jamie Iles280df6b2011-05-20 00:40:19 -0600581static void __iomem *bgpio_map(struct platform_device *pdev,
582 const char *name,
Heiner Kallweit8d240262015-09-30 23:52:36 +0200583 resource_size_t sane_sz)
Jamie Iles280df6b2011-05-20 00:40:19 -0600584{
Jamie Iles280df6b2011-05-20 00:40:19 -0600585 struct resource *r;
Jamie Iles280df6b2011-05-20 00:40:19 -0600586 resource_size_t sz;
Jamie Iles280df6b2011-05-20 00:40:19 -0600587
588 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
Heiner Kallweit8d240262015-09-30 23:52:36 +0200589 if (!r)
Guenter Roeckb2f68b62015-10-21 00:12:00 -0700590 return NULL;
Jamie Iles280df6b2011-05-20 00:40:19 -0600591
592 sz = resource_size(r);
Heiner Kallweit8d240262015-09-30 23:52:36 +0200593 if (sz != sane_sz)
594 return IOMEM_ERR_PTR(-EINVAL);
Jamie Iles280df6b2011-05-20 00:40:19 -0600595
Heiner Kallweit8d240262015-09-30 23:52:36 +0200596 return devm_ioremap_resource(&pdev->dev, r);
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700597}
598
Bill Pemberton38363092012-11-19 13:22:34 -0500599static int bgpio_pdev_probe(struct platform_device *pdev)
Jamie Iles280df6b2011-05-20 00:40:19 -0600600{
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;
Alexander Shiyan19338532014-03-16 09:10:34 +0400609 unsigned long flags = pdev->id_entry->driver_data;
Jamie Iles280df6b2011-05-20 00:40:19 -0600610 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
Heiner Kallweit8d240262015-09-30 23:52:36 +0200620 dat = bgpio_map(pdev, "dat", sz);
621 if (IS_ERR(dat))
622 return PTR_ERR(dat);
Jamie Iles280df6b2011-05-20 00:40:19 -0600623
Heiner Kallweit8d240262015-09-30 23:52:36 +0200624 set = bgpio_map(pdev, "set", sz);
625 if (IS_ERR(set))
626 return PTR_ERR(set);
Jamie Iles280df6b2011-05-20 00:40:19 -0600627
Heiner Kallweit8d240262015-09-30 23:52:36 +0200628 clr = bgpio_map(pdev, "clr", sz);
629 if (IS_ERR(clr))
630 return PTR_ERR(clr);
Jamie Iles280df6b2011-05-20 00:40:19 -0600631
Heiner Kallweit8d240262015-09-30 23:52:36 +0200632 dirout = bgpio_map(pdev, "dirout", sz);
633 if (IS_ERR(dirout))
634 return PTR_ERR(dirout);
Jamie Iles280df6b2011-05-20 00:40:19 -0600635
Heiner Kallweit8d240262015-09-30 23:52:36 +0200636 dirin = bgpio_map(pdev, "dirin", sz);
637 if (IS_ERR(dirin))
638 return PTR_ERR(dirin);
Jamie Iles280df6b2011-05-20 00:40:19 -0600639
Jamie Iles280df6b2011-05-20 00:40:19 -0600640 bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
641 if (!bgc)
642 return -ENOMEM;
643
Shawn Guo3e11f7b2012-05-19 21:34:58 +0800644 err = bgpio_init(bgc, dev, sz, dat, set, clr, dirout, dirin, flags);
Jamie Iles280df6b2011-05-20 00:40:19 -0600645 if (err)
646 return err;
647
648 if (pdata) {
Pawel Moll781f6d72014-01-30 13:18:57 +0000649 if (pdata->label)
650 bgc->gc.label = pdata->label;
Jamie Iles280df6b2011-05-20 00:40:19 -0600651 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
Bill Pemberton206210c2012-11-19 13:25:50 -0500661static int bgpio_pdev_remove(struct platform_device *pdev)
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700662{
Jamie Iles4ddb8ae2011-05-20 00:40:14 -0600663 struct bgpio_chip *bgc = platform_get_drvdata(pdev);
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700664
Jamie Iles280df6b2011-05-20 00:40:19 -0600665 return bgpio_remove(bgc);
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700666}
667
668static const struct platform_device_id bgpio_id_table[] = {
Alexander Shiyan19338532014-03-16 09:10:34 +0400669 {
670 .name = "basic-mmio-gpio",
671 .driver_data = 0,
672 }, {
673 .name = "basic-mmio-gpio-be",
674 .driver_data = BGPIOF_BIG_ENDIAN,
675 },
676 { }
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700677};
678MODULE_DEVICE_TABLE(platform, bgpio_id_table);
679
680static struct platform_driver bgpio_driver = {
681 .driver = {
682 .name = "basic-mmio-gpio",
683 },
684 .id_table = bgpio_id_table,
Jamie Iles280df6b2011-05-20 00:40:19 -0600685 .probe = bgpio_pdev_probe,
Bill Pemberton8283c4f2012-11-19 13:20:08 -0500686 .remove = bgpio_pdev_remove,
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700687};
688
Mark Brown6f614152011-12-08 00:24:00 +0800689module_platform_driver(bgpio_driver);
Jamie Iles280df6b2011-05-20 00:40:19 -0600690
Grant Likelyc103de22011-06-04 18:38:28 -0600691#endif /* CONFIG_GPIO_GENERIC_PLATFORM */
Anton Vorontsovaeec56e2010-10-27 15:33:15 -0700692
693MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers");
694MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
695MODULE_LICENSE("GPL");