aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2013-10-02 11:50:29 -0400
committerLinus Walleij <linus.walleij@linaro.org>2013-10-10 11:38:29 -0400
commitc8ce878206076b159ee9488133aa51314570da38 (patch)
tree42f9f1e3ea4c60c6b8f525ff90cea27ff31077c0
parentd1c30115d06e255a7ba69c7b63129a92c2f34de6 (diff)
pincntrl: add support for ams AS3722 pin control driver
The AS3722 is a compact system PMU suitable for mobile phones, tablets etc. Add a driver to support accessing the GPIO, pinmux and pin configuration of 8 GPIO pins found on the ams AS3722 through pin control driver and gpiolib. The driver will register itself as the pincontrol driver and gpio driver. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/pinctrl/Kconfig11
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/pinctrl-as3722.c630
3 files changed, 642 insertions, 0 deletions
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 21db2013543b..85f5462460aa 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -59,6 +59,17 @@ config PINCTRL_ADI2
59 future processors. This option is selected automatically when specific 59 future processors. This option is selected automatically when specific
60 machine and arch are selected to build. 60 machine and arch are selected to build.
61 61
62config PINCTRL_AS3722
63 bool "Pinctrl and GPIO driver for ams AS3722 PMIC"
64 depends on MFD_AS3722 && GPIOLIB
65 select PINMUX
66 select GENERIC_PINCONF
67 help
68 AS3722 device supports the configuration of GPIO pins for different
69 functionality. This driver supports the pinmux, push-pull and
70 open drain configuration for the GPIO pins of AS3722 devices. It also
71 supports the GPIO functionality through gpiolib.
72
62config PINCTRL_BF54x 73config PINCTRL_BF54x
63 def_bool y if BF54x 74 def_bool y if BF54x
64 select PINCTRL_ADI2 75 select PINCTRL_ADI2
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index bbeb98086495..3d14cb855b2c 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_PINCTRL_AB8540) += pinctrl-ab8540.o
15obj-$(CONFIG_PINCTRL_AB9540) += pinctrl-ab9540.o 15obj-$(CONFIG_PINCTRL_AB9540) += pinctrl-ab9540.o
16obj-$(CONFIG_PINCTRL_AB8505) += pinctrl-ab8505.o 16obj-$(CONFIG_PINCTRL_AB8505) += pinctrl-ab8505.o
17obj-$(CONFIG_PINCTRL_ADI2) += pinctrl-adi2.o 17obj-$(CONFIG_PINCTRL_ADI2) += pinctrl-adi2.o
18obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o
18obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o 19obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o
19obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o 20obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o
20obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o 21obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
diff --git a/drivers/pinctrl/pinctrl-as3722.c b/drivers/pinctrl/pinctrl-as3722.c
new file mode 100644
index 000000000000..01bffc1d52fd
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-as3722.c
@@ -0,0 +1,630 @@
1/*
2 * ams AS3722 pin control and GPIO driver.
3 *
4 * Copyright (c) 2013, NVIDIA Corporation.
5 *
6 * Author: Laxman Dewangan <ldewangan@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation version 2.
11 *
12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
13 * whether express or implied; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 * 02111-1307, USA
21 */
22
23#include <linux/delay.h>
24#include <linux/gpio.h>
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/mfd/as3722.h>
28#include <linux/of.h>
29#include <linux/of_device.h>
30#include <linux/platform_device.h>
31#include <linux/pinctrl/consumer.h>
32#include <linux/pinctrl/machine.h>
33#include <linux/pinctrl/pinctrl.h>
34#include <linux/pinctrl/pinconf-generic.h>
35#include <linux/pinctrl/pinconf.h>
36#include <linux/pinctrl/pinmux.h>
37#include <linux/pm.h>
38#include <linux/slab.h>
39
40#include "core.h"
41#include "pinconf.h"
42#include "pinctrl-utils.h"
43
44#define AS3722_PIN_GPIO0 0
45#define AS3722_PIN_GPIO1 1
46#define AS3722_PIN_GPIO2 2
47#define AS3722_PIN_GPIO3 3
48#define AS3722_PIN_GPIO4 4
49#define AS3722_PIN_GPIO5 5
50#define AS3722_PIN_GPIO6 6
51#define AS3722_PIN_GPIO7 7
52#define AS3722_PIN_NUM (AS3722_PIN_GPIO7 + 1)
53
54#define AS3722_GPIO_MODE_PULL_UP BIT(PIN_CONFIG_BIAS_PULL_UP)
55#define AS3722_GPIO_MODE_PULL_DOWN BIT(PIN_CONFIG_BIAS_PULL_DOWN)
56#define AS3722_GPIO_MODE_HIGH_IMPED BIT(PIN_CONFIG_BIAS_HIGH_IMPEDANCE)
57#define AS3722_GPIO_MODE_OPEN_DRAIN BIT(PIN_CONFIG_DRIVE_OPEN_DRAIN)
58
59struct as3722_pin_function {
60 const char *name;
61 const char * const *groups;
62 unsigned ngroups;
63 int mux_option;
64};
65
66struct as3722_gpio_pin_control {
67 bool enable_gpio_invert;
68 unsigned mode_prop;
69 int io_function;
70};
71
72struct as3722_pingroup {
73 const char *name;
74 const unsigned pins[1];
75 unsigned npins;
76};
77
78struct as3722_pctrl_info {
79 struct device *dev;
80 struct pinctrl_dev *pctl;
81 struct as3722 *as3722;
82 struct gpio_chip gpio_chip;
83 int pins_current_opt[AS3722_PIN_NUM];
84 const struct as3722_pin_function *functions;
85 unsigned num_functions;
86 const struct as3722_pingroup *pin_groups;
87 int num_pin_groups;
88 const struct pinctrl_pin_desc *pins;
89 unsigned num_pins;
90 struct as3722_gpio_pin_control gpio_control[AS3722_PIN_NUM];
91};
92
93static const struct pinctrl_pin_desc as3722_pins_desc[] = {
94 PINCTRL_PIN(AS3722_PIN_GPIO0, "gpio0"),
95 PINCTRL_PIN(AS3722_PIN_GPIO1, "gpio1"),
96 PINCTRL_PIN(AS3722_PIN_GPIO2, "gpio2"),
97 PINCTRL_PIN(AS3722_PIN_GPIO3, "gpio3"),
98 PINCTRL_PIN(AS3722_PIN_GPIO4, "gpio4"),
99 PINCTRL_PIN(AS3722_PIN_GPIO5, "gpio5"),
100 PINCTRL_PIN(AS3722_PIN_GPIO6, "gpio6"),
101 PINCTRL_PIN(AS3722_PIN_GPIO7, "gpio7"),
102};
103
104static const char * const gpio_groups[] = {
105 "gpio0",
106 "gpio1",
107 "gpio2",
108 "gpio3",
109 "gpio4",
110 "gpio5",
111 "gpio6",
112 "gpio7",
113};
114
115enum as3722_pinmux_option {
116 AS3722_PINMUX_GPIO = 0,
117 AS3722_PINMUX_INTERRUPT_OUT = 1,
118 AS3722_PINMUX_VSUB_VBAT_UNDEB_LOW_OUT = 2,
119 AS3722_PINMUX_GPIO_INTERRUPT = 3,
120 AS3722_PINMUX_PWM_INPUT = 4,
121 AS3722_PINMUX_VOLTAGE_IN_STBY = 5,
122 AS3722_PINMUX_OC_PG_SD0 = 6,
123 AS3722_PINMUX_PG_OUT = 7,
124 AS3722_PINMUX_CLK32K_OUT = 8,
125 AS3722_PINMUX_WATCHDOG_INPUT = 9,
126 AS3722_PINMUX_SOFT_RESET_IN = 11,
127 AS3722_PINMUX_PWM_OUTPUT = 12,
128 AS3722_PINMUX_VSUB_VBAT_LOW_DEB_OUT = 13,
129 AS3722_PINMUX_OC_PG_SD6 = 14,
130};
131
132#define FUNCTION_GROUP(fname, mux) \
133 { \
134 .name = #fname, \
135 .groups = gpio_groups, \
136 .ngroups = ARRAY_SIZE(gpio_groups), \
137 .mux_option = AS3722_PINMUX_##mux, \
138 }
139
140static const struct as3722_pin_function as3722_pin_function[] = {
141 FUNCTION_GROUP(gpio, GPIO),
142 FUNCTION_GROUP(interrupt-out, INTERRUPT_OUT),
143 FUNCTION_GROUP(gpio-in-interrupt, GPIO_INTERRUPT),
144 FUNCTION_GROUP(vsup-vbat-low-undebounce-out, VSUB_VBAT_UNDEB_LOW_OUT),
145 FUNCTION_GROUP(vsup-vbat-low-debounce-out, VSUB_VBAT_LOW_DEB_OUT),
146 FUNCTION_GROUP(voltage-in-standby, VOLTAGE_IN_STBY),
147 FUNCTION_GROUP(oc-pg-sd0, OC_PG_SD0),
148 FUNCTION_GROUP(oc-pg-sd6, OC_PG_SD6),
149 FUNCTION_GROUP(powergood-out, PG_OUT),
150 FUNCTION_GROUP(pwm-in, PWM_INPUT),
151 FUNCTION_GROUP(pwm-out, PWM_OUTPUT),
152 FUNCTION_GROUP(clk32k-out, CLK32K_OUT),
153 FUNCTION_GROUP(watchdog-in, WATCHDOG_INPUT),
154 FUNCTION_GROUP(soft-reset-in, SOFT_RESET_IN),
155};
156
157#define AS3722_PINGROUP(pg_name, pin_id) \
158 { \
159 .name = #pg_name, \
160 .pins = {AS3722_PIN_##pin_id}, \
161 .npins = 1, \
162 }
163
164static const struct as3722_pingroup as3722_pingroups[] = {
165 AS3722_PINGROUP(gpio0, GPIO0),
166 AS3722_PINGROUP(gpio1, GPIO1),
167 AS3722_PINGROUP(gpio2, GPIO2),
168 AS3722_PINGROUP(gpio3, GPIO3),
169 AS3722_PINGROUP(gpio4, GPIO4),
170 AS3722_PINGROUP(gpio5, GPIO5),
171 AS3722_PINGROUP(gpio6, GPIO6),
172 AS3722_PINGROUP(gpio7, GPIO7),
173};
174
175static int as3722_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
176{
177 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
178
179 return as_pci->num_pin_groups;
180}
181
182static const char *as3722_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
183 unsigned group)
184{
185 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
186
187 return as_pci->pin_groups[group].name;
188}
189
190static int as3722_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
191 unsigned group, const unsigned **pins, unsigned *num_pins)
192{
193 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
194
195 *pins = as_pci->pin_groups[group].pins;
196 *num_pins = as_pci->pin_groups[group].npins;
197 return 0;
198}
199
200static const struct pinctrl_ops as3722_pinctrl_ops = {
201 .get_groups_count = as3722_pinctrl_get_groups_count,
202 .get_group_name = as3722_pinctrl_get_group_name,
203 .get_group_pins = as3722_pinctrl_get_group_pins,
204 .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
205 .dt_free_map = pinctrl_utils_dt_free_map,
206};
207
208static int as3722_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
209{
210 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
211
212 return as_pci->num_functions;
213}
214
215static const char *as3722_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
216 unsigned function)
217{
218 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
219
220 return as_pci->functions[function].name;
221}
222
223static int as3722_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
224 unsigned function, const char * const **groups,
225 unsigned * const num_groups)
226{
227 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
228
229 *groups = as_pci->functions[function].groups;
230 *num_groups = as_pci->functions[function].ngroups;
231 return 0;
232}
233
234static int as3722_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function,
235 unsigned group)
236{
237 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
238 int gpio_cntr_reg = AS3722_GPIOn_CONTROL_REG(group);
239 u8 val = AS3722_GPIO_IOSF_VAL(as_pci->functions[function].mux_option);
240 int ret;
241
242 dev_dbg(as_pci->dev, "%s(): GPIO %u pin to function %u and val %u\n",
243 __func__, group, function, val);
244
245 ret = as3722_update_bits(as_pci->as3722, gpio_cntr_reg,
246 AS3722_GPIO_IOSF_MASK, val);
247 if (ret < 0) {
248 dev_err(as_pci->dev, "GPIO%d_CTRL_REG update failed %d\n",
249 group, ret);
250 return ret;
251 }
252 as_pci->gpio_control[group].io_function = function;
253 return ret;
254}
255
256static int as3722_pinctrl_gpio_get_mode(unsigned gpio_mode_prop, bool input)
257{
258 if (gpio_mode_prop & AS3722_GPIO_MODE_HIGH_IMPED)
259 return -EINVAL;
260
261 if (gpio_mode_prop & AS3722_GPIO_MODE_OPEN_DRAIN) {
262 if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_UP)
263 return AS3722_GPIO_MODE_IO_OPEN_DRAIN_PULL_UP;
264 return AS3722_GPIO_MODE_IO_OPEN_DRAIN;
265 }
266 if (input) {
267 if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_UP)
268 return AS3722_GPIO_MODE_INPUT_PULL_UP;
269 else if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_DOWN)
270 return AS3722_GPIO_MODE_INPUT_PULL_DOWN;
271 return AS3722_GPIO_MODE_INPUT;
272 }
273 if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_DOWN)
274 return AS3722_GPIO_MODE_OUTPUT_VDDL;
275 return AS3722_GPIO_MODE_OUTPUT_VDDH;
276}
277
278static int as3722_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev,
279 struct pinctrl_gpio_range *range, unsigned offset)
280{
281 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
282
283 if (as_pci->gpio_control[offset].io_function)
284 return -EBUSY;
285 return 0;
286}
287
288static int as3722_pinctrl_gpio_set_direction(struct pinctrl_dev *pctldev,
289 struct pinctrl_gpio_range *range, unsigned offset, bool input)
290{
291 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
292 struct as3722 *as3722 = as_pci->as3722;
293 int mode;
294
295 mode = as3722_pinctrl_gpio_get_mode(
296 as_pci->gpio_control[offset].mode_prop, input);
297 if (mode < 0) {
298 dev_err(as_pci->dev, "%s direction for GPIO %d not supported\n",
299 (input) ? "Input" : "Output", offset);
300 return mode;
301 }
302
303 if (as_pci->gpio_control[offset].enable_gpio_invert)
304 mode |= AS3722_GPIO_INV;
305
306 return as3722_write(as3722, AS3722_GPIOn_CONTROL_REG(offset), mode);
307}
308
309static const struct pinmux_ops as3722_pinmux_ops = {
310 .get_functions_count = as3722_pinctrl_get_funcs_count,
311 .get_function_name = as3722_pinctrl_get_func_name,
312 .get_function_groups = as3722_pinctrl_get_func_groups,
313 .enable = as3722_pinctrl_enable,
314 .gpio_request_enable = as3722_pinctrl_gpio_request_enable,
315 .gpio_set_direction = as3722_pinctrl_gpio_set_direction,
316};
317
318static int as3722_pinconf_get(struct pinctrl_dev *pctldev,
319 unsigned pin, unsigned long *config)
320{
321 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
322 enum pin_config_param param = pinconf_to_config_param(*config);
323 int arg = 0;
324 u16 prop;
325
326 switch (param) {
327 case PIN_CONFIG_BIAS_DISABLE:
328 prop = AS3722_GPIO_MODE_PULL_UP |
329 AS3722_GPIO_MODE_PULL_DOWN;
330 if (!(as_pci->gpio_control[pin].mode_prop & prop))
331 arg = 1;
332 prop = 0;
333 break;
334
335 case PIN_CONFIG_BIAS_PULL_UP:
336 prop = AS3722_GPIO_MODE_PULL_UP;
337 break;
338
339 case PIN_CONFIG_BIAS_PULL_DOWN:
340 prop = AS3722_GPIO_MODE_PULL_DOWN;
341 break;
342
343 case PIN_CONFIG_DRIVE_OPEN_DRAIN:
344 prop = AS3722_GPIO_MODE_OPEN_DRAIN;
345 break;
346
347 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
348 prop = AS3722_GPIO_MODE_HIGH_IMPED;
349 break;
350
351 default:
352 dev_err(as_pci->dev, "Properties not supported\n");
353 return -ENOTSUPP;
354 }
355
356 if (as_pci->gpio_control[pin].mode_prop & prop)
357 arg = 1;
358
359 *config = pinconf_to_config_packed(param, (u16)arg);
360 return 0;
361}
362
363static int as3722_pinconf_set(struct pinctrl_dev *pctldev,
364 unsigned pin, unsigned long *configs,
365 unsigned num_configs)
366{
367 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
368 enum pin_config_param param;
369 int mode_prop;
370 int i;
371
372 for (i = 0; i < num_configs; i++) {
373 param = pinconf_to_config_param(configs[i]);
374 mode_prop = as_pci->gpio_control[pin].mode_prop;
375
376 switch (param) {
377 case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
378 break;
379
380 case PIN_CONFIG_BIAS_DISABLE:
381 mode_prop &= ~(AS3722_GPIO_MODE_PULL_UP |
382 AS3722_GPIO_MODE_PULL_DOWN);
383 break;
384 case PIN_CONFIG_BIAS_PULL_UP:
385 mode_prop |= AS3722_GPIO_MODE_PULL_UP;
386 break;
387
388 case PIN_CONFIG_BIAS_PULL_DOWN:
389 mode_prop |= AS3722_GPIO_MODE_PULL_DOWN;
390 break;
391
392 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
393 mode_prop |= AS3722_GPIO_MODE_HIGH_IMPED;
394 break;
395
396 case PIN_CONFIG_DRIVE_OPEN_DRAIN:
397 mode_prop |= AS3722_GPIO_MODE_OPEN_DRAIN;
398 break;
399
400 default:
401 dev_err(as_pci->dev, "Properties not supported\n");
402 return -ENOTSUPP;
403 }
404
405 as_pci->gpio_control[pin].mode_prop = mode_prop;
406 }
407 return 0;
408}
409
410static const struct pinconf_ops as3722_pinconf_ops = {
411 .pin_config_get = as3722_pinconf_get,
412 .pin_config_set = as3722_pinconf_set,
413};
414
415static struct pinctrl_desc as3722_pinctrl_desc = {
416 .pctlops = &as3722_pinctrl_ops,
417 .pmxops = &as3722_pinmux_ops,
418 .confops = &as3722_pinconf_ops,
419 .owner = THIS_MODULE,
420};
421
422static inline struct as3722_pctrl_info *to_as_pci(struct gpio_chip *chip)
423{
424 return container_of(chip, struct as3722_pctrl_info, gpio_chip);
425}
426
427static int as3722_gpio_get(struct gpio_chip *chip, unsigned offset)
428{
429 struct as3722_pctrl_info *as_pci = to_as_pci(chip);
430 struct as3722 *as3722 = as_pci->as3722;
431 int ret;
432 u32 reg;
433 u32 control;
434 u32 val;
435 int mode;
436 int invert_enable;
437
438 ret = as3722_read(as3722, AS3722_GPIOn_CONTROL_REG(offset), &control);
439 if (ret < 0) {
440 dev_err(as_pci->dev,
441 "GPIO_CONTROL%d_REG read failed: %d\n", offset, ret);
442 return ret;
443 }
444
445 invert_enable = !!(control & AS3722_GPIO_INV);
446 mode = control & AS3722_GPIO_MODE_MASK;
447 switch (mode) {
448 case AS3722_GPIO_MODE_INPUT:
449 case AS3722_GPIO_MODE_INPUT_PULL_UP:
450 case AS3722_GPIO_MODE_INPUT_PULL_DOWN:
451 case AS3722_GPIO_MODE_IO_OPEN_DRAIN:
452 case AS3722_GPIO_MODE_IO_OPEN_DRAIN_PULL_UP:
453 reg = AS3722_GPIO_SIGNAL_IN_REG;
454 break;
455 case AS3722_GPIO_MODE_OUTPUT_VDDH:
456 case AS3722_GPIO_MODE_OUTPUT_VDDL:
457 reg = AS3722_GPIO_SIGNAL_OUT_REG;
458 break;
459 default:
460 return -EINVAL;
461 }
462
463 ret = as3722_read(as3722, reg, &val);
464 if (ret < 0) {
465 dev_err(as_pci->dev,
466 "GPIO_SIGNAL_IN_REG read failed: %d\n", ret);
467 return ret;
468 }
469
470 val = !!(val & AS3722_GPIOn_SIGNAL(offset));
471 return (invert_enable) ? !val : val;
472}
473
474static void as3722_gpio_set(struct gpio_chip *chip, unsigned offset,
475 int value)
476{
477 struct as3722_pctrl_info *as_pci = to_as_pci(chip);
478 struct as3722 *as3722 = as_pci->as3722;
479 int en_invert = as_pci->gpio_control[offset].enable_gpio_invert;
480 u32 val;
481 int ret;
482
483 if (value)
484 val = (en_invert) ? 0 : AS3722_GPIOn_SIGNAL(offset);
485 else
486 val = (en_invert) ? AS3722_GPIOn_SIGNAL(offset) : 0;
487
488 ret = as3722_update_bits(as3722, AS3722_GPIO_SIGNAL_OUT_REG,
489 AS3722_GPIOn_SIGNAL(offset), val);
490 if (ret < 0)
491 dev_err(as_pci->dev,
492 "GPIO_SIGNAL_OUT_REG update failed: %d\n", ret);
493}
494
495static int as3722_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
496{
497 return pinctrl_gpio_direction_input(chip->base + offset);
498}
499
500static int as3722_gpio_direction_output(struct gpio_chip *chip,
501 unsigned offset, int value)
502{
503 as3722_gpio_set(chip, offset, value);
504 return pinctrl_gpio_direction_output(chip->base + offset);
505}
506
507static int as3722_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
508{
509 struct as3722_pctrl_info *as_pci = to_as_pci(chip);
510
511 return as3722_irq_get_virq(as_pci->as3722, offset);
512}
513
514static int as3722_gpio_request(struct gpio_chip *chip, unsigned offset)
515{
516 return pinctrl_request_gpio(chip->base + offset);
517}
518
519static void as3722_gpio_free(struct gpio_chip *chip, unsigned offset)
520{
521 pinctrl_free_gpio(chip->base + offset);
522}
523
524static const struct gpio_chip as3722_gpio_chip = {
525 .label = "as3722-gpio",
526 .owner = THIS_MODULE,
527 .request = as3722_gpio_request,
528 .free = as3722_gpio_free,
529 .get = as3722_gpio_get,
530 .set = as3722_gpio_set,
531 .direction_input = as3722_gpio_direction_input,
532 .direction_output = as3722_gpio_direction_output,
533 .to_irq = as3722_gpio_to_irq,
534 .can_sleep = 1,
535 .ngpio = AS3722_PIN_NUM,
536 .base = -1,
537};
538
539static int as3722_pinctrl_probe(struct platform_device *pdev)
540{
541 struct as3722_pctrl_info *as_pci;
542 int ret;
543 int tret;
544
545 as_pci = devm_kzalloc(&pdev->dev, sizeof(*as_pci), GFP_KERNEL);
546 if (!as_pci)
547 return -ENOMEM;
548
549 as_pci->dev = &pdev->dev;
550 as_pci->dev->of_node = pdev->dev.parent->of_node;
551 as_pci->as3722 = dev_get_drvdata(pdev->dev.parent);
552 platform_set_drvdata(pdev, as_pci);
553
554 as_pci->pins = as3722_pins_desc;
555 as_pci->num_pins = ARRAY_SIZE(as3722_pins_desc);
556 as_pci->functions = as3722_pin_function;
557 as_pci->num_functions = ARRAY_SIZE(as3722_pin_function);
558 as_pci->pin_groups = as3722_pingroups;
559 as_pci->num_pin_groups = ARRAY_SIZE(as3722_pingroups);
560 as3722_pinctrl_desc.name = dev_name(&pdev->dev);
561 as3722_pinctrl_desc.pins = as3722_pins_desc;
562 as3722_pinctrl_desc.npins = ARRAY_SIZE(as3722_pins_desc);
563 as_pci->pctl = pinctrl_register(&as3722_pinctrl_desc,
564 &pdev->dev, as_pci);
565 if (!as_pci->pctl) {
566 dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
567 return -EINVAL;
568 }
569
570 as_pci->gpio_chip = as3722_gpio_chip;
571 as_pci->gpio_chip.dev = &pdev->dev;
572 as_pci->gpio_chip.of_node = pdev->dev.parent->of_node;
573 ret = gpiochip_add(&as_pci->gpio_chip);
574 if (ret < 0) {
575 dev_err(&pdev->dev, "Couldn't register gpiochip, %d\n", ret);
576 goto fail_chip_add;
577 }
578
579 ret = gpiochip_add_pin_range(&as_pci->gpio_chip, dev_name(&pdev->dev),
580 0, 0, AS3722_PIN_NUM);
581 if (ret < 0) {
582 dev_err(&pdev->dev, "Couldn't add pin range, %d\n", ret);
583 goto fail_range_add;
584 }
585
586 return 0;
587
588fail_range_add:
589 tret = gpiochip_remove(&as_pci->gpio_chip);
590 if (tret < 0)
591 dev_warn(&pdev->dev, "Couldn't remove gpio chip, %d\n", tret);
592
593fail_chip_add:
594 pinctrl_unregister(as_pci->pctl);
595 return ret;
596}
597
598static int as3722_pinctrl_remove(struct platform_device *pdev)
599{
600 struct as3722_pctrl_info *as_pci = platform_get_drvdata(pdev);
601 int ret;
602
603 ret = gpiochip_remove(&as_pci->gpio_chip);
604 if (ret < 0)
605 return ret;
606 pinctrl_unregister(as_pci->pctl);
607 return 0;
608}
609
610static struct of_device_id as3722_pinctrl_of_match[] = {
611 { .compatible = "ams,as3722-pinctrl", },
612 { },
613};
614MODULE_DEVICE_TABLE(of, as3722_pinctrl_of_match);
615
616static struct platform_driver as3722_pinctrl_driver = {
617 .driver = {
618 .name = "as3722-pinctrl",
619 .owner = THIS_MODULE,
620 .of_match_table = as3722_pinctrl_of_match,
621 },
622 .probe = as3722_pinctrl_probe,
623 .remove = as3722_pinctrl_remove,
624};
625module_platform_driver(as3722_pinctrl_driver);
626
627MODULE_ALIAS("platform:as3722-pinctrl");
628MODULE_DESCRIPTION("AS3722 pin control and GPIO driver");
629MODULE_AUTHOR("Laxman Dewangan<ldewangan@nvidia.com>");
630MODULE_LICENSE("GPL v2");