aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 21:28:06 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 21:28:06 -0400
commit2a2bf85f05e42b12ea6bfe821e2d19221cf93555 (patch)
tree11abcdaef6e4f8307574056998d306d21558b6ed /drivers/gpio
parent11801e9de26992d37cb869cc74f389b6a7677e0e (diff)
parent99261fbad0a16f105b262d7525801697588ba526 (diff)
Merge tag 'dt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM soc device tree updates from Olof Johansson: "Device tree conversion and enablement branch. Mostly a bunch of new bindings and setup for various platforms, but the Via/Winchip VT8500 platform is also converted over from being 100% legacy to now use device tree for probing. More of that will come for 3.8." Trivial conflicts due to removal of vt8500 files, and one documentation file that was added with slightly different contents both here and in the USb tree. * tag 'dt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (212 commits) arm: vt8500: Fixup for missing gpio.h ARM: LPC32xx: LED fix in PHY3250 DTS file ARM: dt: mmp-dma: add binding file arm: vt8500: Update arch-vt8500 to devicetree support. arm: vt8500: gpio: Devicetree support for arch-vt8500 arm: vt8500: doc: Add device tree bindings for arch-vt8500 devices arm: vt8500: clk: Add Common Clock Framework support video: vt8500: Add devicetree support for vt8500-fb and wm8505-fb serial: vt8500: Add devicetree support for vt8500-serial rtc: vt8500: Add devicetree support for vt8500-rtc arm: vt8500: Add device tree files for VIA/Wondermedia SoC's ARM: tegra: Add Avionic Design Tamonten Evaluation Carrier support ARM: tegra: Add Avionic Design Medcom-Wide support ARM: tegra: Add Avionic Design Plutux support ARM: tegra: Add Avionic Design Tamonten support ARM: tegra: dts: Add pwm label ARM: ux500: Fix SSP register address format ARM: ux500: Apply tc3589x's GPIO/IRQ properties to HREF's DT ARM: ux500: Remove redundant #gpio-cell properties from Snowball DT ARM: ux500: Add all encompassing sound node to the HREF Device Tree ...
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig6
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-pxa.c77
-rw-r--r--drivers/gpio/gpio-samsung.c63
-rw-r--r--drivers/gpio/gpio-twl4030.c77
-rw-r--r--drivers/gpio/gpio-vt8500.c316
6 files changed, 461 insertions, 79 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index ba7926f5c099..a00b828b1643 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -183,6 +183,12 @@ config GPIO_STA2X11
183 Say yes here to support the STA2x11/ConneXt GPIO device. 183 Say yes here to support the STA2x11/ConneXt GPIO device.
184 The GPIO module has 128 GPIO pins with alternate functions. 184 The GPIO module has 128 GPIO pins with alternate functions.
185 185
186config GPIO_VT8500
187 bool "VIA/Wondermedia SoC GPIO Support"
188 depends on ARCH_VT8500
189 help
190 Say yes here to support the VT8500/WM8505/WM8650 GPIO controller.
191
186config GPIO_XILINX 192config GPIO_XILINX
187 bool "Xilinx GPIO support" 193 bool "Xilinx GPIO support"
188 depends on PPC_OF || MICROBLAZE 194 depends on PPC_OF || MICROBLAZE
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 153caceeb053..a288142ad998 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o
69obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o 69obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
70obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o 70obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
71obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o 71obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
72obj-$(CONFIG_GPIO_VT8500) += gpio-vt8500.o
72obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o 73obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
73obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o 74obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o
74obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o 75obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index 9cac88a65f78..9528779ca463 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -26,6 +26,8 @@
26#include <linux/syscore_ops.h> 26#include <linux/syscore_ops.h>
27#include <linux/slab.h> 27#include <linux/slab.h>
28 28
29#include <asm/mach/irq.h>
30
29#include <mach/irqs.h> 31#include <mach/irqs.h>
30 32
31/* 33/*
@@ -59,6 +61,7 @@
59#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) 61#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
60 62
61int pxa_last_gpio; 63int pxa_last_gpio;
64static int irq_base;
62 65
63#ifdef CONFIG_OF 66#ifdef CONFIG_OF
64static struct irq_domain *domain; 67static struct irq_domain *domain;
@@ -167,63 +170,14 @@ static inline int __gpio_is_occupied(unsigned gpio)
167 return ret; 170 return ret;
168} 171}
169 172
170#ifdef CONFIG_ARCH_PXA
171static inline int __pxa_gpio_to_irq(int gpio)
172{
173 if (gpio_is_pxa_type(gpio_type))
174 return PXA_GPIO_TO_IRQ(gpio);
175 return -1;
176}
177
178static inline int __pxa_irq_to_gpio(int irq)
179{
180 if (gpio_is_pxa_type(gpio_type))
181 return irq - PXA_GPIO_TO_IRQ(0);
182 return -1;
183}
184#else
185static inline int __pxa_gpio_to_irq(int gpio) { return -1; }
186static inline int __pxa_irq_to_gpio(int irq) { return -1; }
187#endif
188
189#ifdef CONFIG_ARCH_MMP
190static inline int __mmp_gpio_to_irq(int gpio)
191{
192 if (gpio_is_mmp_type(gpio_type))
193 return MMP_GPIO_TO_IRQ(gpio);
194 return -1;
195}
196
197static inline int __mmp_irq_to_gpio(int irq)
198{
199 if (gpio_is_mmp_type(gpio_type))
200 return irq - MMP_GPIO_TO_IRQ(0);
201 return -1;
202}
203#else
204static inline int __mmp_gpio_to_irq(int gpio) { return -1; }
205static inline int __mmp_irq_to_gpio(int irq) { return -1; }
206#endif
207
208static int pxa_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 173static int pxa_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
209{ 174{
210 int gpio, ret; 175 return chip->base + offset + irq_base;
211
212 gpio = chip->base + offset;
213 ret = __pxa_gpio_to_irq(gpio);
214 if (ret >= 0)
215 return ret;
216 return __mmp_gpio_to_irq(gpio);
217} 176}
218 177
219int pxa_irq_to_gpio(int irq) 178int pxa_irq_to_gpio(int irq)
220{ 179{
221 int ret; 180 return irq - irq_base;
222
223 ret = __pxa_irq_to_gpio(irq);
224 if (ret >= 0)
225 return ret;
226 return __mmp_irq_to_gpio(irq);
227} 181}
228 182
229static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 183static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -403,6 +357,9 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
403 struct pxa_gpio_chip *c; 357 struct pxa_gpio_chip *c;
404 int loop, gpio, gpio_base, n; 358 int loop, gpio, gpio_base, n;
405 unsigned long gedr; 359 unsigned long gedr;
360 struct irq_chip *chip = irq_desc_get_chip(desc);
361
362 chained_irq_enter(chip, desc);
406 363
407 do { 364 do {
408 loop = 0; 365 loop = 0;
@@ -422,6 +379,8 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
422 } 379 }
423 } 380 }
424 } while (loop); 381 } while (loop);
382
383 chained_irq_exit(chip, desc);
425} 384}
426 385
427static void pxa_ack_muxed_gpio(struct irq_data *d) 386static void pxa_ack_muxed_gpio(struct irq_data *d)
@@ -535,7 +494,7 @@ const struct irq_domain_ops pxa_irq_domain_ops = {
535 494
536static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev) 495static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev)
537{ 496{
538 int ret, nr_banks, nr_gpios, irq_base; 497 int ret, nr_banks, nr_gpios;
539 struct device_node *prev, *next, *np = pdev->dev.of_node; 498 struct device_node *prev, *next, *np = pdev->dev.of_node;
540 const struct of_device_id *of_id = 499 const struct of_device_id *of_id =
541 of_match_device(pxa_gpio_dt_ids, &pdev->dev); 500 of_match_device(pxa_gpio_dt_ids, &pdev->dev);
@@ -590,10 +549,20 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev)
590 int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0; 549 int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0;
591 550
592 ret = pxa_gpio_probe_dt(pdev); 551 ret = pxa_gpio_probe_dt(pdev);
593 if (ret < 0) 552 if (ret < 0) {
594 pxa_last_gpio = pxa_gpio_nums(); 553 pxa_last_gpio = pxa_gpio_nums();
595 else 554#ifdef CONFIG_ARCH_PXA
555 if (gpio_is_pxa_type(gpio_type))
556 irq_base = PXA_GPIO_TO_IRQ(0);
557#endif
558#ifdef CONFIG_ARCH_MMP
559 if (gpio_is_mmp_type(gpio_type))
560 irq_base = MMP_GPIO_TO_IRQ(0);
561#endif
562 } else {
596 use_of = 1; 563 use_of = 1;
564 }
565
597 if (!pxa_last_gpio) 566 if (!pxa_last_gpio)
598 return -EINVAL; 567 return -EINVAL;
599 568
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index 1c169324e357..8af4b06e80f7 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -938,6 +938,67 @@ static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
938 s3c_gpiolib_track(chip); 938 s3c_gpiolib_track(chip);
939} 939}
940 940
941#if defined(CONFIG_PLAT_S3C24XX) && defined(CONFIG_OF)
942static int s3c24xx_gpio_xlate(struct gpio_chip *gc,
943 const struct of_phandle_args *gpiospec, u32 *flags)
944{
945 unsigned int pin;
946
947 if (WARN_ON(gc->of_gpio_n_cells < 3))
948 return -EINVAL;
949
950 if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
951 return -EINVAL;
952
953 if (gpiospec->args[0] > gc->ngpio)
954 return -EINVAL;
955
956 pin = gc->base + gpiospec->args[0];
957
958 if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1])))
959 pr_warn("gpio_xlate: failed to set pin function\n");
960 if (s3c_gpio_setpull(pin, gpiospec->args[2] & 0xffff))
961 pr_warn("gpio_xlate: failed to set pin pull up/down\n");
962
963 if (flags)
964 *flags = gpiospec->args[2] >> 16;
965
966 return gpiospec->args[0];
967}
968
969static const struct of_device_id s3c24xx_gpio_dt_match[] __initdata = {
970 { .compatible = "samsung,s3c24xx-gpio", },
971 {}
972};
973
974static __init void s3c24xx_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
975 u64 base, u64 offset)
976{
977 struct gpio_chip *gc = &chip->chip;
978 u64 address;
979
980 if (!of_have_populated_dt())
981 return;
982
983 address = chip->base ? base + ((u32)chip->base & 0xfff) : base + offset;
984 gc->of_node = of_find_matching_node_by_address(NULL,
985 s3c24xx_gpio_dt_match, address);
986 if (!gc->of_node) {
987 pr_info("gpio: device tree node not found for gpio controller"
988 " with base address %08llx\n", address);
989 return;
990 }
991 gc->of_gpio_n_cells = 3;
992 gc->of_xlate = s3c24xx_gpio_xlate;
993}
994#else
995static __init void s3c24xx_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
996 u64 base, u64 offset)
997{
998 return;
999}
1000#endif /* defined(CONFIG_PLAT_S3C24XX) && defined(CONFIG_OF) */
1001
941static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip, 1002static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
942 int nr_chips, void __iomem *base) 1003 int nr_chips, void __iomem *base)
943{ 1004{
@@ -962,6 +1023,8 @@ static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
962 gc->direction_output = samsung_gpiolib_2bit_output; 1023 gc->direction_output = samsung_gpiolib_2bit_output;
963 1024
964 samsung_gpiolib_add(chip); 1025 samsung_gpiolib_add(chip);
1026
1027 s3c24xx_gpiolib_attach_ofnode(chip, S3C24XX_PA_GPIO, i * 0x10);
965 } 1028 }
966} 1029}
967 1030
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index f030880bc9bb..c5f8ca233e1f 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -396,6 +396,29 @@ static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
396 396
397static int gpio_twl4030_remove(struct platform_device *pdev); 397static int gpio_twl4030_remove(struct platform_device *pdev);
398 398
399static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev)
400{
401 struct twl4030_gpio_platform_data *omap_twl_info;
402
403 omap_twl_info = devm_kzalloc(dev, sizeof(*omap_twl_info), GFP_KERNEL);
404 if (!omap_twl_info)
405 return NULL;
406
407 omap_twl_info->use_leds = of_property_read_bool(dev->of_node,
408 "ti,use-leds");
409
410 of_property_read_u32(dev->of_node, "ti,debounce",
411 &omap_twl_info->debounce);
412 of_property_read_u32(dev->of_node, "ti,mmc-cd",
413 (u32 *)&omap_twl_info->mmc_cd);
414 of_property_read_u32(dev->of_node, "ti,pullups",
415 &omap_twl_info->pullups);
416 of_property_read_u32(dev->of_node, "ti,pulldowns",
417 &omap_twl_info->pulldowns);
418
419 return omap_twl_info;
420}
421
399static int __devinit gpio_twl4030_probe(struct platform_device *pdev) 422static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
400{ 423{
401 struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data; 424 struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
@@ -428,33 +451,37 @@ no_irqs:
428 twl_gpiochip.ngpio = TWL4030_GPIO_MAX; 451 twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
429 twl_gpiochip.dev = &pdev->dev; 452 twl_gpiochip.dev = &pdev->dev;
430 453
431 if (pdata) { 454 if (node)
432 /* 455 pdata = of_gpio_twl4030(&pdev->dev);
433 * NOTE: boards may waste power if they don't set pullups 456
434 * and pulldowns correctly ... default for non-ULPI pins is 457 if (pdata == NULL) {
435 * pulldown, and some other pins may have external pullups 458 dev_err(&pdev->dev, "Platform data is missing\n");
436 * or pulldowns. Careful! 459 return -ENXIO;
437 */
438 ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
439 if (ret)
440 dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
441 pdata->pullups, pdata->pulldowns,
442 ret);
443
444 ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
445 if (ret)
446 dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
447 pdata->debounce, pdata->mmc_cd,
448 ret);
449
450 /*
451 * NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
452 * is (still) clear if use_leds is set.
453 */
454 if (pdata->use_leds)
455 twl_gpiochip.ngpio += 2;
456 } 460 }
457 461
462 /*
463 * NOTE: boards may waste power if they don't set pullups
464 * and pulldowns correctly ... default for non-ULPI pins is
465 * pulldown, and some other pins may have external pullups
466 * or pulldowns. Careful!
467 */
468 ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
469 if (ret)
470 dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
471 pdata->pullups, pdata->pulldowns, ret);
472
473 ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
474 if (ret)
475 dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
476 pdata->debounce, pdata->mmc_cd, ret);
477
478 /*
479 * NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
480 * is (still) clear if use_leds is set.
481 */
482 if (pdata->use_leds)
483 twl_gpiochip.ngpio += 2;
484
458 ret = gpiochip_add(&twl_gpiochip); 485 ret = gpiochip_add(&twl_gpiochip);
459 if (ret < 0) { 486 if (ret < 0) {
460 dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret); 487 dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret);
diff --git a/drivers/gpio/gpio-vt8500.c b/drivers/gpio/gpio-vt8500.c
new file mode 100644
index 000000000000..bcd8e4aa7c7d
--- /dev/null
+++ b/drivers/gpio/gpio-vt8500.c
@@ -0,0 +1,316 @@
1/* drivers/gpio/gpio-vt8500.c
2 *
3 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
4 * Based on arch/arm/mach-vt8500/gpio.c:
5 * - Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/err.h>
20#include <linux/io.h>
21#include <linux/gpio.h>
22#include <linux/platform_device.h>
23#include <linux/bitops.h>
24#include <linux/of.h>
25#include <linux/of_address.h>
26#include <linux/of_irq.h>
27#include <linux/of_device.h>
28
29/*
30 We handle GPIOs by bank, each bank containing up to 32 GPIOs covered
31 by one set of registers (although not all may be valid).
32
33 Because different SoC's have different register offsets, we pass the
34 register offsets as data in vt8500_gpio_dt_ids[].
35
36 A value of NO_REG is used to indicate that this register is not
37 supported. Only used for ->en at the moment.
38*/
39
40#define NO_REG 0xFFFF
41
42/*
43 * struct vt8500_gpio_bank_regoffsets
44 * @en: offset to enable register of the bank
45 * @dir: offset to direction register of the bank
46 * @data_out: offset to the data out register of the bank
47 * @data_in: offset to the data in register of the bank
48 * @ngpio: highest valid pin in this bank
49 */
50
51struct vt8500_gpio_bank_regoffsets {
52 unsigned int en;
53 unsigned int dir;
54 unsigned int data_out;
55 unsigned int data_in;
56 unsigned char ngpio;
57};
58
59struct vt8500_gpio_data {
60 unsigned int num_banks;
61 struct vt8500_gpio_bank_regoffsets banks[];
62};
63
64#define VT8500_BANK(__en, __dir, __out, __in, __ngpio) \
65{ \
66 .en = __en, \
67 .dir = __dir, \
68 .data_out = __out, \
69 .data_in = __in, \
70 .ngpio = __ngpio, \
71}
72
73static struct vt8500_gpio_data vt8500_data = {
74 .num_banks = 7,
75 .banks = {
76 VT8500_BANK(0x00, 0x20, 0x40, 0x60, 26),
77 VT8500_BANK(0x04, 0x24, 0x44, 0x64, 28),
78 VT8500_BANK(0x08, 0x28, 0x48, 0x68, 31),
79 VT8500_BANK(0x0C, 0x2C, 0x4C, 0x6C, 19),
80 VT8500_BANK(0x10, 0x30, 0x50, 0x70, 19),
81 VT8500_BANK(0x14, 0x34, 0x54, 0x74, 23),
82 VT8500_BANK(NO_REG, 0x3C, 0x5C, 0x7C, 9),
83 },
84};
85
86static struct vt8500_gpio_data wm8505_data = {
87 .num_banks = 10,
88 .banks = {
89 VT8500_BANK(0x40, 0x68, 0x90, 0xB8, 8),
90 VT8500_BANK(0x44, 0x6C, 0x94, 0xBC, 32),
91 VT8500_BANK(0x48, 0x70, 0x98, 0xC0, 6),
92 VT8500_BANK(0x4C, 0x74, 0x9C, 0xC4, 16),
93 VT8500_BANK(0x50, 0x78, 0xA0, 0xC8, 25),
94 VT8500_BANK(0x54, 0x7C, 0xA4, 0xCC, 5),
95 VT8500_BANK(0x58, 0x80, 0xA8, 0xD0, 5),
96 VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12),
97 VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16),
98 VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),
99 },
100};
101
102/*
103 * No information about which bits are valid so we just make
104 * them all available until its figured out.
105 */
106static struct vt8500_gpio_data wm8650_data = {
107 .num_banks = 9,
108 .banks = {
109 VT8500_BANK(0x40, 0x80, 0xC0, 0x00, 32),
110 VT8500_BANK(0x44, 0x84, 0xC4, 0x04, 32),
111 VT8500_BANK(0x48, 0x88, 0xC8, 0x08, 32),
112 VT8500_BANK(0x4C, 0x8C, 0xCC, 0x0C, 32),
113 VT8500_BANK(0x50, 0x90, 0xD0, 0x10, 32),
114 VT8500_BANK(0x54, 0x94, 0xD4, 0x14, 32),
115 VT8500_BANK(0x58, 0x98, 0xD8, 0x18, 32),
116 VT8500_BANK(0x5C, 0x9C, 0xDC, 0x1C, 32),
117 VT8500_BANK(0x7C, 0xBC, 0xFC, 0x3C, 32),
118 },
119};
120
121struct vt8500_gpio_chip {
122 struct gpio_chip chip;
123
124 const struct vt8500_gpio_bank_regoffsets *regs;
125 void __iomem *base;
126};
127
128
129#define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
130
131static int vt8500_gpio_request(struct gpio_chip *chip, unsigned offset)
132{
133 u32 val;
134 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
135
136 if (vt8500_chip->regs->en == NO_REG)
137 return 0;
138
139 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->en);
140 val |= BIT(offset);
141 writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->en);
142
143 return 0;
144}
145
146static void vt8500_gpio_free(struct gpio_chip *chip, unsigned offset)
147{
148 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
149 u32 val;
150
151 if (vt8500_chip->regs->en == NO_REG)
152 return;
153
154 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->en);
155 val &= ~BIT(offset);
156 writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->en);
157}
158
159static int vt8500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
160{
161 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
162
163 u32 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->dir);
164 val &= ~BIT(offset);
165 writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->dir);
166
167 return 0;
168}
169
170static int vt8500_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
171 int value)
172{
173 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
174
175 u32 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->dir);
176 val |= BIT(offset);
177 writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->dir);
178
179 if (value) {
180 val = readl_relaxed(vt8500_chip->base +
181 vt8500_chip->regs->data_out);
182 val |= BIT(offset);
183 writel_relaxed(val, vt8500_chip->base +
184 vt8500_chip->regs->data_out);
185 }
186 return 0;
187}
188
189static int vt8500_gpio_get_value(struct gpio_chip *chip, unsigned offset)
190{
191 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
192
193 return (readl_relaxed(vt8500_chip->base + vt8500_chip->regs->data_in) >>
194 offset) & 1;
195}
196
197static void vt8500_gpio_set_value(struct gpio_chip *chip, unsigned offset,
198 int value)
199{
200 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
201
202 u32 val = readl_relaxed(vt8500_chip->base +
203 vt8500_chip->regs->data_out);
204 if (value)
205 val |= BIT(offset);
206 else
207 val &= ~BIT(offset);
208
209 writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->data_out);
210}
211
212static int vt8500_of_xlate(struct gpio_chip *gc,
213 const struct of_phandle_args *gpiospec, u32 *flags)
214{
215 /* bank if specificed in gpiospec->args[0] */
216 if (flags)
217 *flags = gpiospec->args[2];
218
219 return gpiospec->args[1];
220}
221
222static int vt8500_add_chips(struct platform_device *pdev, void __iomem *base,
223 const struct vt8500_gpio_data *data)
224{
225 struct vt8500_gpio_chip *vtchip;
226 struct gpio_chip *chip;
227 int i;
228 int pin_cnt = 0;
229
230 vtchip = devm_kzalloc(&pdev->dev,
231 sizeof(struct vt8500_gpio_chip) * data->num_banks,
232 GFP_KERNEL);
233 if (!vtchip) {
234 pr_err("%s: failed to allocate chip memory\n", __func__);
235 return -ENOMEM;
236 }
237
238 for (i = 0; i < data->num_banks; i++) {
239 vtchip[i].base = base;
240 vtchip[i].regs = &data->banks[i];
241
242 chip = &vtchip[i].chip;
243
244 chip->of_xlate = vt8500_of_xlate;
245 chip->of_gpio_n_cells = 3;
246 chip->of_node = pdev->dev.of_node;
247
248 chip->request = vt8500_gpio_request;
249 chip->free = vt8500_gpio_free;
250 chip->direction_input = vt8500_gpio_direction_input;
251 chip->direction_output = vt8500_gpio_direction_output;
252 chip->get = vt8500_gpio_get_value;
253 chip->set = vt8500_gpio_set_value;
254 chip->can_sleep = 0;
255 chip->base = pin_cnt;
256 chip->ngpio = data->banks[i].ngpio;
257
258 pin_cnt += data->banks[i].ngpio;
259
260 gpiochip_add(chip);
261 }
262 return 0;
263}
264
265static struct of_device_id vt8500_gpio_dt_ids[] = {
266 { .compatible = "via,vt8500-gpio", .data = &vt8500_data, },
267 { .compatible = "wm,wm8505-gpio", .data = &wm8505_data, },
268 { .compatible = "wm,wm8650-gpio", .data = &wm8650_data, },
269 { /* Sentinel */ },
270};
271
272static int __devinit vt8500_gpio_probe(struct platform_device *pdev)
273{
274 void __iomem *gpio_base;
275 struct device_node *np;
276 const struct of_device_id *of_id =
277 of_match_device(vt8500_gpio_dt_ids, &pdev->dev);
278
279 if (!of_id) {
280 dev_err(&pdev->dev, "Failed to find gpio controller\n");
281 return -ENODEV;
282 }
283
284 np = pdev->dev.of_node;
285 if (!np) {
286 dev_err(&pdev->dev, "Missing GPIO description in devicetree\n");
287 return -EFAULT;
288 }
289
290 gpio_base = of_iomap(np, 0);
291 if (!gpio_base) {
292 dev_err(&pdev->dev, "Unable to map GPIO registers\n");
293 of_node_put(np);
294 return -ENOMEM;
295 }
296
297 vt8500_add_chips(pdev, gpio_base, of_id->data);
298
299 return 0;
300}
301
302static struct platform_driver vt8500_gpio_driver = {
303 .probe = vt8500_gpio_probe,
304 .driver = {
305 .name = "vt8500-gpio",
306 .owner = THIS_MODULE,
307 .of_match_table = vt8500_gpio_dt_ids,
308 },
309};
310
311module_platform_driver(vt8500_gpio_driver);
312
313MODULE_DESCRIPTION("VT8500 GPIO Driver");
314MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
315MODULE_LICENSE("GPL v2");
316MODULE_DEVICE_TABLE(of, vt8500_gpio_dt_ids);