aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2017-12-07 04:09:55 -0500
committerLinus Walleij <linus.walleij@linaro.org>2017-12-07 04:09:55 -0500
commit110e2a38c8daabb6f33e164dab6083afeeb2dd5e (patch)
tree0d2aedaee023372319fa326ba5f44e645b0f45c3
parent4070a53496ec0c94fda1da0773eee2e5a5bd0084 (diff)
parente1190083b89bd0d53c83b647ff313d9f004c6772 (diff)
Merge branch 'ib-move-axp209' into devel
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-axp209.txt49
-rw-r--r--drivers/gpio/Kconfig6
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-axp209.c188
-rw-r--r--drivers/pinctrl/Kconfig10
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/pinctrl-axp209.c476
7 files changed, 534 insertions, 197 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gpio-axp209.txt b/Documentation/devicetree/bindings/gpio/gpio-axp209.txt
index a6611304dd3c..fc42b2caa06d 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-axp209.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-axp209.txt
@@ -1,10 +1,17 @@
1AXP209 GPIO controller 1AXP209 GPIO & pinctrl controller
2 2
3This driver follows the usual GPIO bindings found in 3This driver follows the usual GPIO bindings found in
4Documentation/devicetree/bindings/gpio/gpio.txt 4Documentation/devicetree/bindings/gpio/gpio.txt
5 5
6This driver follows the usual pinctrl bindings found in
7Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
8
9This driver employs the per-pin muxing pattern.
10
6Required properties: 11Required properties:
7- compatible: Should be "x-powers,axp209-gpio" 12- compatible: Should be one of:
13 - "x-powers,axp209-gpio"
14 - "x-powers,axp813-gpio"
8- #gpio-cells: Should be two. The first cell is the pin number and the 15- #gpio-cells: Should be two. The first cell is the pin number and the
9 second is the GPIO flags. 16 second is the GPIO flags.
10- gpio-controller: Marks the device node as a GPIO controller. 17- gpio-controller: Marks the device node as a GPIO controller.
@@ -28,3 +35,41 @@ axp209: pmic@34 {
28 #gpio-cells = <2>; 35 #gpio-cells = <2>;
29 }; 36 };
30}; 37};
38
39The GPIOs can be muxed to other functions and therefore, must be a subnode of
40axp_gpio.
41
42Example:
43
44&axp_gpio {
45 gpio0_adc: gpio0-adc {
46 pins = "GPIO0";
47 function = "adc";
48 };
49};
50
51&example_node {
52 pinctrl-names = "default";
53 pinctrl-0 = <&gpio0_adc>;
54};
55
56GPIOs and their functions
57-------------------------
58
59Each GPIO is independent from the other (i.e. GPIO0 in gpio_in function does
60not force GPIO1 and GPIO2 to be in gpio_in function as well).
61
62axp209
63------
64GPIO | Functions
65------------------------
66GPIO0 | gpio_in, gpio_out, ldo, adc
67GPIO1 | gpio_in, gpio_out, ldo, adc
68GPIO2 | gpio_in, gpio_out
69
70axp813
71------
72GPIO | Functions
73------------------------
74GPIO0 | gpio_in, gpio_out, ldo, adc
75GPIO1 | gpio_in, gpio_out, ldo
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d6a8e851ad13..395669bfcc26 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -122,12 +122,6 @@ config GPIO_ATH79
122 Select this option to enable GPIO driver for 122 Select this option to enable GPIO driver for
123 Atheros AR71XX/AR724X/AR913X SoC devices. 123 Atheros AR71XX/AR724X/AR913X SoC devices.
124 124
125config GPIO_AXP209
126 tristate "X-Powers AXP209 PMIC GPIO Support"
127 depends on MFD_AXP20X
128 help
129 Say yes to enable GPIO support for the AXP209 PMIC
130
131config GPIO_BCM_KONA 125config GPIO_BCM_KONA
132 bool "Broadcom Kona GPIO" 126 bool "Broadcom Kona GPIO"
133 depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST) 127 depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST)
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 4bc24febb889..bc5dd673fa11 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -32,7 +32,6 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
32obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o 32obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
33obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o 33obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
34obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o 34obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o
35obj-$(CONFIG_GPIO_AXP209) += gpio-axp209.o
36obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o 35obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
37obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o 36obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
38obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o 37obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
diff --git a/drivers/gpio/gpio-axp209.c b/drivers/gpio/gpio-axp209.c
deleted file mode 100644
index 4a346b7b4172..000000000000
--- a/drivers/gpio/gpio-axp209.c
+++ /dev/null
@@ -1,188 +0,0 @@
1/*
2 * AXP20x GPIO driver
3 *
4 * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <linux/bitops.h>
13#include <linux/device.h>
14#include <linux/gpio/driver.h>
15#include <linux/init.h>
16#include <linux/interrupt.h>
17#include <linux/kernel.h>
18#include <linux/mfd/axp20x.h>
19#include <linux/module.h>
20#include <linux/of.h>
21#include <linux/platform_device.h>
22#include <linux/regmap.h>
23#include <linux/slab.h>
24
25#define AXP20X_GPIO_FUNCTIONS 0x7
26#define AXP20X_GPIO_FUNCTION_OUT_LOW 0
27#define AXP20X_GPIO_FUNCTION_OUT_HIGH 1
28#define AXP20X_GPIO_FUNCTION_INPUT 2
29
30struct axp20x_gpio {
31 struct gpio_chip chip;
32 struct regmap *regmap;
33};
34
35static int axp20x_gpio_get_reg(unsigned offset)
36{
37 switch (offset) {
38 case 0:
39 return AXP20X_GPIO0_CTRL;
40 case 1:
41 return AXP20X_GPIO1_CTRL;
42 case 2:
43 return AXP20X_GPIO2_CTRL;
44 }
45
46 return -EINVAL;
47}
48
49static int axp20x_gpio_input(struct gpio_chip *chip, unsigned offset)
50{
51 struct axp20x_gpio *gpio = gpiochip_get_data(chip);
52 int reg;
53
54 reg = axp20x_gpio_get_reg(offset);
55 if (reg < 0)
56 return reg;
57
58 return regmap_update_bits(gpio->regmap, reg,
59 AXP20X_GPIO_FUNCTIONS,
60 AXP20X_GPIO_FUNCTION_INPUT);
61}
62
63static int axp20x_gpio_get(struct gpio_chip *chip, unsigned offset)
64{
65 struct axp20x_gpio *gpio = gpiochip_get_data(chip);
66 unsigned int val;
67 int ret;
68
69 ret = regmap_read(gpio->regmap, AXP20X_GPIO20_SS, &val);
70 if (ret)
71 return ret;
72
73 return !!(val & BIT(offset + 4));
74}
75
76static int axp20x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
77{
78 struct axp20x_gpio *gpio = gpiochip_get_data(chip);
79 unsigned int val;
80 int reg, ret;
81
82 reg = axp20x_gpio_get_reg(offset);
83 if (reg < 0)
84 return reg;
85
86 ret = regmap_read(gpio->regmap, reg, &val);
87 if (ret)
88 return ret;
89
90 /*
91 * This shouldn't really happen if the pin is in use already,
92 * or if it's not in use yet, it doesn't matter since we're
93 * going to change the value soon anyway. Default to output.
94 */
95 if ((val & AXP20X_GPIO_FUNCTIONS) > 2)
96 return 0;
97
98 /*
99 * The GPIO directions are the three lowest values.
100 * 2 is input, 0 and 1 are output
101 */
102 return val & 2;
103}
104
105static int axp20x_gpio_output(struct gpio_chip *chip, unsigned offset,
106 int value)
107{
108 struct axp20x_gpio *gpio = gpiochip_get_data(chip);
109 int reg;
110
111 reg = axp20x_gpio_get_reg(offset);
112 if (reg < 0)
113 return reg;
114
115 return regmap_update_bits(gpio->regmap, reg,
116 AXP20X_GPIO_FUNCTIONS,
117 value ? AXP20X_GPIO_FUNCTION_OUT_HIGH
118 : AXP20X_GPIO_FUNCTION_OUT_LOW);
119}
120
121static void axp20x_gpio_set(struct gpio_chip *chip, unsigned offset,
122 int value)
123{
124 axp20x_gpio_output(chip, offset, value);
125}
126
127static int axp20x_gpio_probe(struct platform_device *pdev)
128{
129 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
130 struct axp20x_gpio *gpio;
131 int ret;
132
133 if (!of_device_is_available(pdev->dev.of_node))
134 return -ENODEV;
135
136 if (!axp20x) {
137 dev_err(&pdev->dev, "Parent drvdata not set\n");
138 return -EINVAL;
139 }
140
141 gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
142 if (!gpio)
143 return -ENOMEM;
144
145 gpio->chip.base = -1;
146 gpio->chip.can_sleep = true;
147 gpio->chip.parent = &pdev->dev;
148 gpio->chip.label = dev_name(&pdev->dev);
149 gpio->chip.owner = THIS_MODULE;
150 gpio->chip.get = axp20x_gpio_get;
151 gpio->chip.get_direction = axp20x_gpio_get_direction;
152 gpio->chip.set = axp20x_gpio_set;
153 gpio->chip.direction_input = axp20x_gpio_input;
154 gpio->chip.direction_output = axp20x_gpio_output;
155 gpio->chip.ngpio = 3;
156
157 gpio->regmap = axp20x->regmap;
158
159 ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
160 if (ret) {
161 dev_err(&pdev->dev, "Failed to register GPIO chip\n");
162 return ret;
163 }
164
165 dev_info(&pdev->dev, "AXP209 GPIO driver loaded\n");
166
167 return 0;
168}
169
170static const struct of_device_id axp20x_gpio_match[] = {
171 { .compatible = "x-powers,axp209-gpio" },
172 { }
173};
174MODULE_DEVICE_TABLE(of, axp20x_gpio_match);
175
176static struct platform_driver axp20x_gpio_driver = {
177 .probe = axp20x_gpio_probe,
178 .driver = {
179 .name = "axp20x-gpio",
180 .of_match_table = axp20x_gpio_match,
181 },
182};
183
184module_platform_driver(axp20x_gpio_driver);
185
186MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
187MODULE_DESCRIPTION("AXP20x PMIC GPIO driver");
188MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 4571cc098b76..ce126955212c 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -63,6 +63,16 @@ config PINCTRL_AS3722
63 open drain configuration for the GPIO pins of AS3722 devices. It also 63 open drain configuration for the GPIO pins of AS3722 devices. It also
64 supports the GPIO functionality through gpiolib. 64 supports the GPIO functionality through gpiolib.
65 65
66config PINCTRL_AXP209
67 tristate "X-Powers AXP209 PMIC pinctrl and GPIO Support"
68 depends on MFD_AXP20X
69 help
70 AXP PMICs provides multiple GPIOs that can be muxed for different
71 functions. This driver bundles a pinctrl driver to select the function
72 muxing and a GPIO driver to handle the GPIO when the GPIO function is
73 selected.
74 Say yes to enable pinctrl and GPIO support for the AXP209 PMIC
75
66config PINCTRL_BF54x 76config PINCTRL_BF54x
67 def_bool y if BF54x 77 def_bool y if BF54x
68 select PINCTRL_ADI2 78 select PINCTRL_ADI2
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index d0d4844f8022..4777f1595ce2 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
11obj-$(CONFIG_PINCTRL_ADI2) += pinctrl-adi2.o 11obj-$(CONFIG_PINCTRL_ADI2) += pinctrl-adi2.o
12obj-$(CONFIG_PINCTRL_ARTPEC6) += pinctrl-artpec6.o 12obj-$(CONFIG_PINCTRL_ARTPEC6) += pinctrl-artpec6.o
13obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o 13obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o
14obj-$(CONFIG_PINCTRL_AXP209) += pinctrl-axp209.o
14obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o 15obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o
15obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o 16obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o
16obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o 17obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
diff --git a/drivers/pinctrl/pinctrl-axp209.c b/drivers/pinctrl/pinctrl-axp209.c
new file mode 100644
index 000000000000..22d3bb0bf927
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-axp209.c
@@ -0,0 +1,476 @@
1/*
2 * AXP20x pinctrl and GPIO driver
3 *
4 * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
5 * Copyright (C) 2017 Quentin Schulz <quentin.schulz@free-electrons.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#include <linux/bitops.h>
14#include <linux/device.h>
15#include <linux/gpio/driver.h>
16#include <linux/init.h>
17#include <linux/interrupt.h>
18#include <linux/kernel.h>
19#include <linux/mfd/axp20x.h>
20#include <linux/module.h>
21#include <linux/of.h>
22#include <linux/of_device.h>
23#include <linux/pinctrl/pinconf-generic.h>
24#include <linux/pinctrl/pinctrl.h>
25#include <linux/pinctrl/pinmux.h>
26#include <linux/platform_device.h>
27#include <linux/regmap.h>
28#include <linux/slab.h>
29
30#define AXP20X_GPIO_FUNCTIONS 0x7
31#define AXP20X_GPIO_FUNCTION_OUT_LOW 0
32#define AXP20X_GPIO_FUNCTION_OUT_HIGH 1
33#define AXP20X_GPIO_FUNCTION_INPUT 2
34
35#define AXP20X_FUNC_GPIO_OUT 0
36#define AXP20X_FUNC_GPIO_IN 1
37#define AXP20X_FUNC_LDO 2
38#define AXP20X_FUNC_ADC 3
39#define AXP20X_FUNCS_NB 4
40
41#define AXP20X_MUX_GPIO_OUT 0
42#define AXP20X_MUX_GPIO_IN BIT(1)
43#define AXP20X_MUX_ADC BIT(2)
44
45#define AXP813_MUX_ADC (BIT(2) | BIT(0))
46
47struct axp20x_pctrl_desc {
48 const struct pinctrl_pin_desc *pins;
49 unsigned int npins;
50 /* Stores the pins supporting LDO function. Bit offset is pin number. */
51 u8 ldo_mask;
52 /* Stores the pins supporting ADC function. Bit offset is pin number. */
53 u8 adc_mask;
54 u8 gpio_status_offset;
55 u8 adc_mux;
56};
57
58struct axp20x_pinctrl_function {
59 const char *name;
60 unsigned int muxval;
61 const char **groups;
62 unsigned int ngroups;
63};
64
65struct axp20x_pctl {
66 struct gpio_chip chip;
67 struct regmap *regmap;
68 struct pinctrl_dev *pctl_dev;
69 struct device *dev;
70 const struct axp20x_pctrl_desc *desc;
71 struct axp20x_pinctrl_function funcs[AXP20X_FUNCS_NB];
72};
73
74static const struct pinctrl_pin_desc axp209_pins[] = {
75 PINCTRL_PIN(0, "GPIO0"),
76 PINCTRL_PIN(1, "GPIO1"),
77 PINCTRL_PIN(2, "GPIO2"),
78};
79
80static const struct pinctrl_pin_desc axp813_pins[] = {
81 PINCTRL_PIN(0, "GPIO0"),
82 PINCTRL_PIN(1, "GPIO1"),
83};
84
85static const struct axp20x_pctrl_desc axp20x_data = {
86 .pins = axp209_pins,
87 .npins = ARRAY_SIZE(axp209_pins),
88 .ldo_mask = BIT(0) | BIT(1),
89 .adc_mask = BIT(0) | BIT(1),
90 .gpio_status_offset = 4,
91 .adc_mux = AXP20X_MUX_ADC,
92};
93
94static const struct axp20x_pctrl_desc axp813_data = {
95 .pins = axp813_pins,
96 .npins = ARRAY_SIZE(axp813_pins),
97 .ldo_mask = BIT(0) | BIT(1),
98 .adc_mask = BIT(0),
99 .gpio_status_offset = 0,
100 .adc_mux = AXP813_MUX_ADC,
101};
102
103static int axp20x_gpio_get_reg(unsigned int offset)
104{
105 switch (offset) {
106 case 0:
107 return AXP20X_GPIO0_CTRL;
108 case 1:
109 return AXP20X_GPIO1_CTRL;
110 case 2:
111 return AXP20X_GPIO2_CTRL;
112 }
113
114 return -EINVAL;
115}
116
117static int axp20x_gpio_input(struct gpio_chip *chip, unsigned int offset)
118{
119 return pinctrl_gpio_direction_input(chip->base + offset);
120}
121
122static int axp20x_gpio_get(struct gpio_chip *chip, unsigned int offset)
123{
124 struct axp20x_pctl *pctl = gpiochip_get_data(chip);
125 unsigned int val;
126 int ret;
127
128 ret = regmap_read(pctl->regmap, AXP20X_GPIO20_SS, &val);
129 if (ret)
130 return ret;
131
132 return !!(val & BIT(offset + pctl->desc->gpio_status_offset));
133}
134
135static int axp20x_gpio_get_direction(struct gpio_chip *chip,
136 unsigned int offset)
137{
138 struct axp20x_pctl *pctl = gpiochip_get_data(chip);
139 unsigned int val;
140 int reg, ret;
141
142 reg = axp20x_gpio_get_reg(offset);
143 if (reg < 0)
144 return reg;
145
146 ret = regmap_read(pctl->regmap, reg, &val);
147 if (ret)
148 return ret;
149
150 /*
151 * This shouldn't really happen if the pin is in use already,
152 * or if it's not in use yet, it doesn't matter since we're
153 * going to change the value soon anyway. Default to output.
154 */
155 if ((val & AXP20X_GPIO_FUNCTIONS) > 2)
156 return 0;
157
158 /*
159 * The GPIO directions are the three lowest values.
160 * 2 is input, 0 and 1 are output
161 */
162 return val & 2;
163}
164
165static int axp20x_gpio_output(struct gpio_chip *chip, unsigned int offset,
166 int value)
167{
168 chip->set(chip, offset, value);
169
170 return 0;
171}
172
173static void axp20x_gpio_set(struct gpio_chip *chip, unsigned int offset,
174 int value)
175{
176 struct axp20x_pctl *pctl = gpiochip_get_data(chip);
177 int reg;
178
179 reg = axp20x_gpio_get_reg(offset);
180 if (reg < 0)
181 return;
182
183 regmap_update_bits(pctl->regmap, reg,
184 AXP20X_GPIO_FUNCTIONS,
185 value ? AXP20X_GPIO_FUNCTION_OUT_HIGH :
186 AXP20X_GPIO_FUNCTION_OUT_LOW);
187}
188
189static int axp20x_pmx_set(struct pinctrl_dev *pctldev, unsigned int offset,
190 u8 config)
191{
192 struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
193 int reg;
194
195 reg = axp20x_gpio_get_reg(offset);
196 if (reg < 0)
197 return reg;
198
199 return regmap_update_bits(pctl->regmap, reg, AXP20X_GPIO_FUNCTIONS,
200 config);
201}
202
203static int axp20x_pmx_func_cnt(struct pinctrl_dev *pctldev)
204{
205 struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
206
207 return ARRAY_SIZE(pctl->funcs);
208}
209
210static const char *axp20x_pmx_func_name(struct pinctrl_dev *pctldev,
211 unsigned int selector)
212{
213 struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
214
215 return pctl->funcs[selector].name;
216}
217
218static int axp20x_pmx_func_groups(struct pinctrl_dev *pctldev,
219 unsigned int selector,
220 const char * const **groups,
221 unsigned int *num_groups)
222{
223 struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
224
225 *groups = pctl->funcs[selector].groups;
226 *num_groups = pctl->funcs[selector].ngroups;
227
228 return 0;
229}
230
231static int axp20x_pmx_set_mux(struct pinctrl_dev *pctldev,
232 unsigned int function, unsigned int group)
233{
234 struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
235 unsigned int mask;
236
237 /* Every pin supports GPIO_OUT and GPIO_IN functions */
238 if (function <= AXP20X_FUNC_GPIO_IN)
239 return axp20x_pmx_set(pctldev, group,
240 pctl->funcs[function].muxval);
241
242 if (function == AXP20X_FUNC_LDO)
243 mask = pctl->desc->ldo_mask;
244 else
245 mask = pctl->desc->adc_mask;
246
247 if (!(BIT(group) & mask))
248 return -EINVAL;
249
250 /*
251 * We let the regulator framework handle the LDO muxing as muxing bits
252 * are basically also regulators on/off bits. It's better not to enforce
253 * any state of the regulator when selecting LDO mux so that we don't
254 * interfere with the regulator driver.
255 */
256 if (function == AXP20X_FUNC_LDO)
257 return 0;
258
259 return axp20x_pmx_set(pctldev, group, pctl->funcs[function].muxval);
260}
261
262static int axp20x_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
263 struct pinctrl_gpio_range *range,
264 unsigned int offset, bool input)
265{
266 struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
267
268 if (input)
269 return axp20x_pmx_set(pctldev, offset,
270 pctl->funcs[AXP20X_FUNC_GPIO_IN].muxval);
271
272 return axp20x_pmx_set(pctldev, offset,
273 pctl->funcs[AXP20X_FUNC_GPIO_OUT].muxval);
274}
275
276static const struct pinmux_ops axp20x_pmx_ops = {
277 .get_functions_count = axp20x_pmx_func_cnt,
278 .get_function_name = axp20x_pmx_func_name,
279 .get_function_groups = axp20x_pmx_func_groups,
280 .set_mux = axp20x_pmx_set_mux,
281 .gpio_set_direction = axp20x_pmx_gpio_set_direction,
282 .strict = true,
283};
284
285static int axp20x_groups_cnt(struct pinctrl_dev *pctldev)
286{
287 struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
288
289 return pctl->desc->npins;
290}
291
292static int axp20x_group_pins(struct pinctrl_dev *pctldev, unsigned int selector,
293 const unsigned int **pins, unsigned int *num_pins)
294{
295 struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
296
297 *pins = (unsigned int *)&pctl->desc->pins[selector];
298 *num_pins = 1;
299
300 return 0;
301}
302
303static const char *axp20x_group_name(struct pinctrl_dev *pctldev,
304 unsigned int selector)
305{
306 struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
307
308 return pctl->desc->pins[selector].name;
309}
310
311static const struct pinctrl_ops axp20x_pctrl_ops = {
312 .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
313 .dt_free_map = pinconf_generic_dt_free_map,
314 .get_groups_count = axp20x_groups_cnt,
315 .get_group_name = axp20x_group_name,
316 .get_group_pins = axp20x_group_pins,
317};
318
319static void axp20x_funcs_groups_from_mask(struct device *dev, unsigned int mask,
320 unsigned int mask_len,
321 struct axp20x_pinctrl_function *func,
322 const struct pinctrl_pin_desc *pins)
323{
324 unsigned long int mask_cpy = mask;
325 const char **group;
326 unsigned int ngroups = hweight8(mask);
327 int bit;
328
329 func->ngroups = ngroups;
330 if (func->ngroups > 0) {
331 func->groups = devm_kzalloc(dev, ngroups * sizeof(const char *),
332 GFP_KERNEL);
333 group = func->groups;
334 for_each_set_bit(bit, &mask_cpy, mask_len) {
335 *group = pins[bit].name;
336 group++;
337 }
338 }
339}
340
341static void axp20x_build_funcs_groups(struct platform_device *pdev)
342{
343 struct axp20x_pctl *pctl = platform_get_drvdata(pdev);
344 int i, pin, npins = pctl->desc->npins;
345
346 pctl->funcs[AXP20X_FUNC_GPIO_OUT].name = "gpio_out";
347 pctl->funcs[AXP20X_FUNC_GPIO_OUT].muxval = AXP20X_MUX_GPIO_OUT;
348 pctl->funcs[AXP20X_FUNC_GPIO_IN].name = "gpio_in";
349 pctl->funcs[AXP20X_FUNC_GPIO_IN].muxval = AXP20X_MUX_GPIO_IN;
350 pctl->funcs[AXP20X_FUNC_LDO].name = "ldo";
351 /*
352 * Muxval for LDO is useless as we won't use it.
353 * See comment in axp20x_pmx_set_mux.
354 */
355 pctl->funcs[AXP20X_FUNC_ADC].name = "adc";
356 pctl->funcs[AXP20X_FUNC_ADC].muxval = pctl->desc->adc_mux;
357
358 /* Every pin supports GPIO_OUT and GPIO_IN functions */
359 for (i = 0; i <= AXP20X_FUNC_GPIO_IN; i++) {
360 pctl->funcs[i].ngroups = npins;
361 pctl->funcs[i].groups = devm_kzalloc(&pdev->dev,
362 npins * sizeof(char *),
363 GFP_KERNEL);
364 for (pin = 0; pin < npins; pin++)
365 pctl->funcs[i].groups[pin] = pctl->desc->pins[pin].name;
366 }
367
368 axp20x_funcs_groups_from_mask(&pdev->dev, pctl->desc->ldo_mask,
369 npins, &pctl->funcs[AXP20X_FUNC_LDO],
370 pctl->desc->pins);
371
372 axp20x_funcs_groups_from_mask(&pdev->dev, pctl->desc->adc_mask,
373 npins, &pctl->funcs[AXP20X_FUNC_ADC],
374 pctl->desc->pins);
375}
376
377static const struct of_device_id axp20x_pctl_match[] = {
378 { .compatible = "x-powers,axp209-gpio", .data = &axp20x_data, },
379 { .compatible = "x-powers,axp813-gpio", .data = &axp813_data, },
380 { }
381};
382MODULE_DEVICE_TABLE(of, axp20x_pctl_match);
383
384static int axp20x_pctl_probe(struct platform_device *pdev)
385{
386 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
387 struct axp20x_pctl *pctl;
388 struct device *dev = &pdev->dev;
389 struct pinctrl_desc *pctrl_desc;
390 int ret;
391
392 if (!of_device_is_available(pdev->dev.of_node))
393 return -ENODEV;
394
395 if (!axp20x) {
396 dev_err(&pdev->dev, "Parent drvdata not set\n");
397 return -EINVAL;
398 }
399
400 pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
401 if (!pctl)
402 return -ENOMEM;
403
404 pctl->chip.base = -1;
405 pctl->chip.can_sleep = true;
406 pctl->chip.request = gpiochip_generic_request;
407 pctl->chip.free = gpiochip_generic_free;
408 pctl->chip.parent = &pdev->dev;
409 pctl->chip.label = dev_name(&pdev->dev);
410 pctl->chip.owner = THIS_MODULE;
411 pctl->chip.get = axp20x_gpio_get;
412 pctl->chip.get_direction = axp20x_gpio_get_direction;
413 pctl->chip.set = axp20x_gpio_set;
414 pctl->chip.direction_input = axp20x_gpio_input;
415 pctl->chip.direction_output = axp20x_gpio_output;
416 pctl->chip.ngpio = pctl->desc->npins;
417
418 pctl->desc = (struct axp20x_pctrl_desc *)of_device_get_match_data(dev);
419 pctl->regmap = axp20x->regmap;
420 pctl->dev = &pdev->dev;
421
422 platform_set_drvdata(pdev, pctl);
423
424 axp20x_build_funcs_groups(pdev);
425
426 pctrl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctrl_desc), GFP_KERNEL);
427 if (!pctrl_desc)
428 return -ENOMEM;
429
430 pctrl_desc->name = dev_name(&pdev->dev);
431 pctrl_desc->owner = THIS_MODULE;
432 pctrl_desc->pins = pctl->desc->pins;
433 pctrl_desc->npins = pctl->desc->npins;
434 pctrl_desc->pctlops = &axp20x_pctrl_ops;
435 pctrl_desc->pmxops = &axp20x_pmx_ops;
436
437 pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, pctrl_desc, pctl);
438 if (IS_ERR(pctl->pctl_dev)) {
439 dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
440 return PTR_ERR(pctl->pctl_dev);
441 }
442
443 ret = devm_gpiochip_add_data(&pdev->dev, &pctl->chip, pctl);
444 if (ret) {
445 dev_err(&pdev->dev, "Failed to register GPIO chip\n");
446 return ret;
447 }
448
449 ret = gpiochip_add_pin_range(&pctl->chip, dev_name(&pdev->dev),
450 pctl->desc->pins->number,
451 pctl->desc->pins->number,
452 pctl->desc->npins);
453 if (ret) {
454 dev_err(&pdev->dev, "failed to add pin range\n");
455 return ret;
456 }
457
458 dev_info(&pdev->dev, "AXP209 pinctrl and GPIO driver loaded\n");
459
460 return 0;
461}
462
463static struct platform_driver axp20x_pctl_driver = {
464 .probe = axp20x_pctl_probe,
465 .driver = {
466 .name = "axp20x-gpio",
467 .of_match_table = axp20x_pctl_match,
468 },
469};
470
471module_platform_driver(axp20x_pctl_driver);
472
473MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
474MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
475MODULE_DESCRIPTION("AXP20x PMIC pinctrl and GPIO driver");
476MODULE_LICENSE("GPL");