aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-06-23 08:29:25 -0400
committerLinus Walleij <linus.walleij@linaro.org>2012-07-17 14:59:53 -0400
commit31ba56f274d60d0b84efae4d15a9cd3e0486fa8c (patch)
tree8a5a49462f4c88b7d1a915e3a1bd5dbcd31871a2 /drivers/gpio
parent0bdfeddc49a80eeb4544ae50b46db7ed695accb8 (diff)
gpiolib: Add support for Wolfson Microelectronics Arizona class devices
The Arizona class devices provide some GPIOs for use in the system. This driver provides support for these via gpiolib. Currently interrupts are not supported, normally the GPIOs are outputs only. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> [Fold in WM5110 support patch] Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig6
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-arizona.c163
3 files changed, 170 insertions, 0 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index c2dfa9f90b47..4002def0b524 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -253,6 +253,12 @@ config GPIO_GE_FPGA
253 253
254comment "I2C GPIO expanders:" 254comment "I2C GPIO expanders:"
255 255
256config GPIO_ARIZONA
257 tristate "Wolfson Microelectronics Arizona class devices"
258 depends on MFD_ARIZONA
259 help
260 Support for GPIOs on Wolfson Arizona class devices.
261
256config GPIO_MAX7300 262config GPIO_MAX7300
257 tristate "Maxim MAX7300 GPIO expander" 263 tristate "Maxim MAX7300 GPIO expander"
258 depends on I2C 264 depends on I2C
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 3a95b17dae86..d37048105a87 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_GPIO_AB8500) += gpio-ab8500.o
13obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o 13obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
14obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o 14obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
15obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o 15obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
16obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
16obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o 17obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
17obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o 18obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
18obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o 19obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
new file mode 100644
index 000000000000..8740d2eb06f8
--- /dev/null
+++ b/drivers/gpio/gpio-arizona.c
@@ -0,0 +1,163 @@
1/*
2 * gpiolib support for Wolfson Arizona class devices
3 *
4 * Copyright 2012 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/kernel.h>
16#include <linux/slab.h>
17#include <linux/module.h>
18#include <linux/gpio.h>
19#include <linux/platform_device.h>
20#include <linux/seq_file.h>
21
22#include <linux/mfd/arizona/core.h>
23#include <linux/mfd/arizona/pdata.h>
24#include <linux/mfd/arizona/registers.h>
25
26struct arizona_gpio {
27 struct arizona *arizona;
28 struct gpio_chip gpio_chip;
29};
30
31static inline struct arizona_gpio *to_arizona_gpio(struct gpio_chip *chip)
32{
33 return container_of(chip, struct arizona_gpio, gpio_chip);
34}
35
36static int arizona_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
37{
38 struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip);
39 struct arizona *arizona = arizona_gpio->arizona;
40
41 return regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset,
42 ARIZONA_GPN_DIR, ARIZONA_GPN_DIR);
43}
44
45static int arizona_gpio_get(struct gpio_chip *chip, unsigned offset)
46{
47 struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip);
48 struct arizona *arizona = arizona_gpio->arizona;
49 unsigned int val;
50 int ret;
51
52 ret = regmap_read(arizona->regmap, ARIZONA_GPIO1_CTRL + offset, &val);
53 if (ret < 0)
54 return ret;
55
56 if (val & ARIZONA_GPN_LVL)
57 return 1;
58 else
59 return 0;
60}
61
62static int arizona_gpio_direction_out(struct gpio_chip *chip,
63 unsigned offset, int value)
64{
65 struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip);
66 struct arizona *arizona = arizona_gpio->arizona;
67
68 if (value)
69 value = ARIZONA_GPN_LVL;
70
71 return regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset,
72 ARIZONA_GPN_DIR | ARIZONA_GPN_LVL, value);
73}
74
75static void arizona_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
76{
77 struct arizona_gpio *arizona_gpio = to_arizona_gpio(chip);
78 struct arizona *arizona = arizona_gpio->arizona;
79
80 if (value)
81 value = ARIZONA_GPN_LVL;
82
83 regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset,
84 ARIZONA_GPN_LVL, value);
85}
86
87static struct gpio_chip template_chip = {
88 .label = "arizona",
89 .owner = THIS_MODULE,
90 .direction_input = arizona_gpio_direction_in,
91 .get = arizona_gpio_get,
92 .direction_output = arizona_gpio_direction_out,
93 .set = arizona_gpio_set,
94 .can_sleep = 1,
95};
96
97static int __devinit arizona_gpio_probe(struct platform_device *pdev)
98{
99 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
100 struct arizona_pdata *pdata = arizona->dev->platform_data;
101 struct arizona_gpio *arizona_gpio;
102 int ret;
103
104 arizona_gpio = devm_kzalloc(&pdev->dev, sizeof(*arizona_gpio),
105 GFP_KERNEL);
106 if (arizona_gpio == NULL)
107 return -ENOMEM;
108
109 arizona_gpio->arizona = arizona;
110 arizona_gpio->gpio_chip = template_chip;
111 arizona_gpio->gpio_chip.dev = &pdev->dev;
112
113 switch (arizona->type) {
114 case WM5102:
115 case WM5110:
116 arizona_gpio->gpio_chip.ngpio = 5;
117 break;
118 default:
119 dev_err(&pdev->dev, "Unknown chip variant %d\n",
120 arizona->type);
121 return -EINVAL;
122 }
123
124 if (pdata && pdata->gpio_base)
125 arizona_gpio->gpio_chip.base = pdata->gpio_base;
126 else
127 arizona_gpio->gpio_chip.base = -1;
128
129 ret = gpiochip_add(&arizona_gpio->gpio_chip);
130 if (ret < 0) {
131 dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
132 ret);
133 goto err;
134 }
135
136 platform_set_drvdata(pdev, arizona_gpio);
137
138 return ret;
139
140err:
141 return ret;
142}
143
144static int __devexit arizona_gpio_remove(struct platform_device *pdev)
145{
146 struct arizona_gpio *arizona_gpio = platform_get_drvdata(pdev);
147
148 return gpiochip_remove(&arizona_gpio->gpio_chip);
149}
150
151static struct platform_driver arizona_gpio_driver = {
152 .driver.name = "arizona-gpio",
153 .driver.owner = THIS_MODULE,
154 .probe = arizona_gpio_probe,
155 .remove = __devexit_p(arizona_gpio_remove),
156};
157
158module_platform_driver(arizona_gpio_driver);
159
160MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
161MODULE_DESCRIPTION("GPIO interface for Arizona devices");
162MODULE_LICENSE("GPL");
163MODULE_ALIAS("platform:arizona-gpio");