blob: 0d1392fc32dd1b5bf43a594bb825f88acbd6f979 [file] [log] [blame]
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -07001/*
2 * Copyright (c) 2015, Sony Mobile Communications AB.
3 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 and
7 * only version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/module.h>
16#include <linux/platform_device.h>
17#include <linux/pinctrl/pinctrl.h>
18#include <linux/pinctrl/pinmux.h>
19#include <linux/pinctrl/pinconf.h>
20#include <linux/pinctrl/pinconf-generic.h>
21#include <linux/slab.h>
22#include <linux/regmap.h>
23#include <linux/gpio.h>
24#include <linux/interrupt.h>
25#include <linux/of_device.h>
Stephen Boydab4256c2015-11-18 11:33:17 -080026#include <linux/of_irq.h>
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -070027
28#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
29
30#include "../core.h"
31#include "../pinctrl-utils.h"
32
33/* MPP registers */
34#define SSBI_REG_ADDR_MPP_BASE 0x50
35#define SSBI_REG_ADDR_MPP(n) (SSBI_REG_ADDR_MPP_BASE + n)
36
37/* MPP Type: type */
38#define PM8XXX_MPP_TYPE_D_INPUT 0
39#define PM8XXX_MPP_TYPE_D_OUTPUT 1
40#define PM8XXX_MPP_TYPE_D_BI_DIR 2
41#define PM8XXX_MPP_TYPE_A_INPUT 3
42#define PM8XXX_MPP_TYPE_A_OUTPUT 4
43#define PM8XXX_MPP_TYPE_SINK 5
44#define PM8XXX_MPP_TYPE_DTEST_SINK 6
45#define PM8XXX_MPP_TYPE_DTEST_OUTPUT 7
46
47/* Digital Input: control */
48#define PM8XXX_MPP_DIN_TO_INT 0
49#define PM8XXX_MPP_DIN_TO_DBUS1 1
50#define PM8XXX_MPP_DIN_TO_DBUS2 2
51#define PM8XXX_MPP_DIN_TO_DBUS3 3
52
53/* Digital Output: control */
54#define PM8XXX_MPP_DOUT_CTRL_LOW 0
55#define PM8XXX_MPP_DOUT_CTRL_HIGH 1
56#define PM8XXX_MPP_DOUT_CTRL_MPP 2
57#define PM8XXX_MPP_DOUT_CTRL_INV_MPP 3
58
59/* Bidirectional: control */
60#define PM8XXX_MPP_BI_PULLUP_1KOHM 0
61#define PM8XXX_MPP_BI_PULLUP_OPEN 1
62#define PM8XXX_MPP_BI_PULLUP_10KOHM 2
63#define PM8XXX_MPP_BI_PULLUP_30KOHM 3
64
65/* Analog Output: control */
66#define PM8XXX_MPP_AOUT_CTRL_DISABLE 0
67#define PM8XXX_MPP_AOUT_CTRL_ENABLE 1
68#define PM8XXX_MPP_AOUT_CTRL_MPP_HIGH_EN 2
69#define PM8XXX_MPP_AOUT_CTRL_MPP_LOW_EN 3
70
71/* Current Sink: control */
72#define PM8XXX_MPP_CS_CTRL_DISABLE 0
73#define PM8XXX_MPP_CS_CTRL_ENABLE 1
74#define PM8XXX_MPP_CS_CTRL_MPP_HIGH_EN 2
75#define PM8XXX_MPP_CS_CTRL_MPP_LOW_EN 3
76
77/* DTEST Current Sink: control */
78#define PM8XXX_MPP_DTEST_CS_CTRL_EN1 0
79#define PM8XXX_MPP_DTEST_CS_CTRL_EN2 1
80#define PM8XXX_MPP_DTEST_CS_CTRL_EN3 2
81#define PM8XXX_MPP_DTEST_CS_CTRL_EN4 3
82
83/* DTEST Digital Output: control */
84#define PM8XXX_MPP_DTEST_DBUS1 0
85#define PM8XXX_MPP_DTEST_DBUS2 1
86#define PM8XXX_MPP_DTEST_DBUS3 2
87#define PM8XXX_MPP_DTEST_DBUS4 3
88
89/* custom pinconf parameters */
90#define PM8XXX_CONFIG_AMUX (PIN_CONFIG_END + 1)
91#define PM8XXX_CONFIG_DTEST_SELECTOR (PIN_CONFIG_END + 2)
92#define PM8XXX_CONFIG_ALEVEL (PIN_CONFIG_END + 3)
93#define PM8XXX_CONFIG_PAIRED (PIN_CONFIG_END + 4)
94
95/**
96 * struct pm8xxx_pin_data - dynamic configuration for a pin
97 * @reg: address of the control register
98 * @irq: IRQ from the PMIC interrupt controller
99 * @mode: operating mode for the pin (digital, analog or current sink)
100 * @input: pin is input
101 * @output: pin is output
102 * @high_z: pin is floating
103 * @paired: mpp operates in paired mode
104 * @output_value: logical output value of the mpp
105 * @power_source: selected power source
106 * @dtest: DTEST route selector
107 * @amux: input muxing in analog mode
108 * @aout_level: selector of the output in analog mode
109 * @drive_strength: drive strength of the current sink
110 * @pullup: pull up value, when in digital bidirectional mode
111 */
112struct pm8xxx_pin_data {
113 unsigned reg;
114 int irq;
115
116 u8 mode;
117
118 bool input;
119 bool output;
120 bool high_z;
121 bool paired;
122 bool output_value;
123
124 u8 power_source;
125 u8 dtest;
126 u8 amux;
127 u8 aout_level;
128 u8 drive_strength;
129 unsigned pullup;
130};
131
132struct pm8xxx_mpp {
133 struct device *dev;
134 struct regmap *regmap;
135 struct pinctrl_dev *pctrl;
136 struct gpio_chip chip;
137
138 struct pinctrl_desc desc;
139 unsigned npins;
140};
141
142static const struct pinconf_generic_params pm8xxx_mpp_bindings[] = {
143 {"qcom,amux-route", PM8XXX_CONFIG_AMUX, 0},
144 {"qcom,analog-level", PM8XXX_CONFIG_ALEVEL, 0},
145 {"qcom,dtest", PM8XXX_CONFIG_DTEST_SELECTOR, 0},
146 {"qcom,paired", PM8XXX_CONFIG_PAIRED, 0},
147};
148
149#ifdef CONFIG_DEBUG_FS
150static const struct pin_config_item pm8xxx_conf_items[] = {
151 PCONFDUMP(PM8XXX_CONFIG_AMUX, "analog mux", NULL, true),
152 PCONFDUMP(PM8XXX_CONFIG_ALEVEL, "analog level", NULL, true),
153 PCONFDUMP(PM8XXX_CONFIG_DTEST_SELECTOR, "dtest", NULL, true),
154 PCONFDUMP(PM8XXX_CONFIG_PAIRED, "paired", NULL, false),
155};
156#endif
157
158#define PM8XXX_MAX_MPPS 12
159static const char * const pm8xxx_groups[PM8XXX_MAX_MPPS] = {
160 "mpp1", "mpp2", "mpp3", "mpp4", "mpp5", "mpp6", "mpp7", "mpp8",
161 "mpp9", "mpp10", "mpp11", "mpp12",
162};
163
164#define PM8XXX_MPP_DIGITAL 0
165#define PM8XXX_MPP_ANALOG 1
166#define PM8XXX_MPP_SINK 2
167
168static const char * const pm8xxx_mpp_functions[] = {
169 "digital", "analog", "sink",
170};
171
172static int pm8xxx_mpp_update(struct pm8xxx_mpp *pctrl,
173 struct pm8xxx_pin_data *pin)
174{
175 unsigned level;
176 unsigned ctrl;
177 unsigned type;
178 int ret;
179 u8 val;
180
181 switch (pin->mode) {
182 case PM8XXX_MPP_DIGITAL:
183 if (pin->dtest) {
184 type = PM8XXX_MPP_TYPE_DTEST_OUTPUT;
185 ctrl = pin->dtest - 1;
186 } else if (pin->input && pin->output) {
187 type = PM8XXX_MPP_TYPE_D_BI_DIR;
188 if (pin->high_z)
189 ctrl = PM8XXX_MPP_BI_PULLUP_OPEN;
190 else if (pin->pullup == 600)
191 ctrl = PM8XXX_MPP_BI_PULLUP_1KOHM;
192 else if (pin->pullup == 10000)
193 ctrl = PM8XXX_MPP_BI_PULLUP_10KOHM;
194 else
195 ctrl = PM8XXX_MPP_BI_PULLUP_30KOHM;
196 } else if (pin->input) {
197 type = PM8XXX_MPP_TYPE_D_INPUT;
198 if (pin->dtest)
199 ctrl = pin->dtest;
200 else
201 ctrl = PM8XXX_MPP_DIN_TO_INT;
202 } else {
203 type = PM8XXX_MPP_TYPE_D_OUTPUT;
204 ctrl = !!pin->output_value;
205 if (pin->paired)
206 ctrl |= BIT(1);
207 }
208
209 level = pin->power_source;
210 break;
211 case PM8XXX_MPP_ANALOG:
212 if (pin->output) {
213 type = PM8XXX_MPP_TYPE_A_OUTPUT;
214 level = pin->aout_level;
215 ctrl = pin->output_value;
216 if (pin->paired)
217 ctrl |= BIT(1);
218 } else {
219 type = PM8XXX_MPP_TYPE_A_INPUT;
220 level = pin->amux;
221 ctrl = 0;
222 }
223 break;
224 case PM8XXX_MPP_SINK:
225 level = (pin->drive_strength / 5) - 1;
226 if (pin->dtest) {
227 type = PM8XXX_MPP_TYPE_DTEST_SINK;
228 ctrl = pin->dtest - 1;
229 } else {
230 type = PM8XXX_MPP_TYPE_SINK;
231 ctrl = pin->output_value;
232 if (pin->paired)
233 ctrl |= BIT(1);
234 }
235 break;
236 default:
237 return -EINVAL;
238 }
239
240 val = type << 5 | level << 2 | ctrl;
241 ret = regmap_write(pctrl->regmap, pin->reg, val);
242 if (ret)
243 dev_err(pctrl->dev, "failed to write register\n");
244
245 return ret;
246}
247
248static int pm8xxx_get_groups_count(struct pinctrl_dev *pctldev)
249{
250 struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);
251
252 return pctrl->npins;
253}
254
255static const char *pm8xxx_get_group_name(struct pinctrl_dev *pctldev,
256 unsigned group)
257{
258 return pm8xxx_groups[group];
259}
260
261
262static int pm8xxx_get_group_pins(struct pinctrl_dev *pctldev,
263 unsigned group,
264 const unsigned **pins,
265 unsigned *num_pins)
266{
267 struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);
268
269 *pins = &pctrl->desc.pins[group].number;
270 *num_pins = 1;
271
272 return 0;
273}
274
275static const struct pinctrl_ops pm8xxx_pinctrl_ops = {
276 .get_groups_count = pm8xxx_get_groups_count,
277 .get_group_name = pm8xxx_get_group_name,
278 .get_group_pins = pm8xxx_get_group_pins,
279 .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
Irina Tirdead32f7fd2016-03-31 14:44:42 +0300280 .dt_free_map = pinctrl_utils_free_map,
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700281};
282
283static int pm8xxx_get_functions_count(struct pinctrl_dev *pctldev)
284{
285 return ARRAY_SIZE(pm8xxx_mpp_functions);
286}
287
288static const char *pm8xxx_get_function_name(struct pinctrl_dev *pctldev,
289 unsigned function)
290{
291 return pm8xxx_mpp_functions[function];
292}
293
294static int pm8xxx_get_function_groups(struct pinctrl_dev *pctldev,
295 unsigned function,
296 const char * const **groups,
297 unsigned * const num_groups)
298{
299 struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);
300
301 *groups = pm8xxx_groups;
302 *num_groups = pctrl->npins;
303 return 0;
304}
305
306static int pm8xxx_pinmux_set_mux(struct pinctrl_dev *pctldev,
307 unsigned function,
308 unsigned group)
309{
310 struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);
311 struct pm8xxx_pin_data *pin = pctrl->desc.pins[group].drv_data;
312
313 pin->mode = function;
314 pm8xxx_mpp_update(pctrl, pin);
315
316 return 0;
317}
318
319static const struct pinmux_ops pm8xxx_pinmux_ops = {
320 .get_functions_count = pm8xxx_get_functions_count,
321 .get_function_name = pm8xxx_get_function_name,
322 .get_function_groups = pm8xxx_get_function_groups,
323 .set_mux = pm8xxx_pinmux_set_mux,
324};
325
326static int pm8xxx_pin_config_get(struct pinctrl_dev *pctldev,
327 unsigned int offset,
328 unsigned long *config)
329{
330 struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);
331 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
332 unsigned param = pinconf_to_config_param(*config);
333 unsigned arg;
334
335 switch (param) {
336 case PIN_CONFIG_BIAS_PULL_UP:
337 arg = pin->pullup;
338 break;
339 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
340 arg = pin->high_z;
341 break;
342 case PIN_CONFIG_INPUT_ENABLE:
343 arg = pin->input;
344 break;
345 case PIN_CONFIG_OUTPUT:
346 arg = pin->output_value;
347 break;
348 case PIN_CONFIG_POWER_SOURCE:
349 arg = pin->power_source;
350 break;
351 case PIN_CONFIG_DRIVE_STRENGTH:
352 arg = pin->drive_strength;
353 break;
354 case PM8XXX_CONFIG_DTEST_SELECTOR:
355 arg = pin->dtest;
356 break;
357 case PM8XXX_CONFIG_AMUX:
358 arg = pin->amux;
359 break;
360 case PM8XXX_CONFIG_ALEVEL:
361 arg = pin->aout_level;
362 break;
363 case PM8XXX_CONFIG_PAIRED:
364 arg = pin->paired;
365 break;
366 default:
367 return -EINVAL;
368 }
369
370 *config = pinconf_to_config_packed(param, arg);
371
372 return 0;
373}
374
375static int pm8xxx_pin_config_set(struct pinctrl_dev *pctldev,
376 unsigned int offset,
377 unsigned long *configs,
378 unsigned num_configs)
379{
380 struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);
381 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
382 unsigned param;
383 unsigned arg;
384 unsigned i;
385
386 for (i = 0; i < num_configs; i++) {
387 param = pinconf_to_config_param(configs[i]);
388 arg = pinconf_to_config_argument(configs[i]);
389
390 switch (param) {
391 case PIN_CONFIG_BIAS_PULL_UP:
392 pin->pullup = arg;
393 break;
394 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
395 pin->high_z = true;
396 break;
397 case PIN_CONFIG_INPUT_ENABLE:
398 pin->input = true;
399 break;
400 case PIN_CONFIG_OUTPUT:
401 pin->output = true;
402 pin->output_value = !!arg;
403 break;
404 case PIN_CONFIG_POWER_SOURCE:
405 pin->power_source = arg;
406 break;
407 case PIN_CONFIG_DRIVE_STRENGTH:
408 pin->drive_strength = arg;
409 break;
410 case PM8XXX_CONFIG_DTEST_SELECTOR:
411 pin->dtest = arg;
412 break;
413 case PM8XXX_CONFIG_AMUX:
414 pin->amux = arg;
415 break;
416 case PM8XXX_CONFIG_ALEVEL:
417 pin->aout_level = arg;
418 break;
419 case PM8XXX_CONFIG_PAIRED:
420 pin->paired = !!arg;
421 break;
422 default:
423 dev_err(pctrl->dev,
424 "unsupported config parameter: %x\n",
425 param);
426 return -EINVAL;
427 }
428 }
429
430 pm8xxx_mpp_update(pctrl, pin);
431
432 return 0;
433}
434
435static const struct pinconf_ops pm8xxx_pinconf_ops = {
436 .is_generic = true,
437 .pin_config_group_get = pm8xxx_pin_config_get,
438 .pin_config_group_set = pm8xxx_pin_config_set,
439};
440
441static struct pinctrl_desc pm8xxx_pinctrl_desc = {
442 .name = "pm8xxx_mpp",
443 .pctlops = &pm8xxx_pinctrl_ops,
444 .pmxops = &pm8xxx_pinmux_ops,
445 .confops = &pm8xxx_pinconf_ops,
446 .owner = THIS_MODULE,
447};
448
449static int pm8xxx_mpp_direction_input(struct gpio_chip *chip,
450 unsigned offset)
451{
Linus Walleijed479412015-12-08 10:13:53 +0100452 struct pm8xxx_mpp *pctrl = gpiochip_get_data(chip);
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700453 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
454
455 switch (pin->mode) {
456 case PM8XXX_MPP_DIGITAL:
457 pin->input = true;
458 break;
459 case PM8XXX_MPP_ANALOG:
460 pin->input = true;
461 pin->output = true;
462 break;
463 case PM8XXX_MPP_SINK:
464 return -EINVAL;
465 }
466
467 pm8xxx_mpp_update(pctrl, pin);
468
469 return 0;
470}
471
472static int pm8xxx_mpp_direction_output(struct gpio_chip *chip,
473 unsigned offset,
474 int value)
475{
Linus Walleijed479412015-12-08 10:13:53 +0100476 struct pm8xxx_mpp *pctrl = gpiochip_get_data(chip);
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700477 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
478
479 switch (pin->mode) {
480 case PM8XXX_MPP_DIGITAL:
481 pin->output = true;
482 break;
483 case PM8XXX_MPP_ANALOG:
484 pin->input = false;
485 pin->output = true;
486 break;
487 case PM8XXX_MPP_SINK:
488 pin->input = false;
489 pin->output = true;
490 break;
491 }
492
493 pm8xxx_mpp_update(pctrl, pin);
494
495 return 0;
496}
497
498static int pm8xxx_mpp_get(struct gpio_chip *chip, unsigned offset)
499{
Linus Walleijed479412015-12-08 10:13:53 +0100500 struct pm8xxx_mpp *pctrl = gpiochip_get_data(chip);
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700501 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
502 bool state;
503 int ret;
504
505 if (!pin->input)
Linus Walleijb9164f042015-12-21 16:36:17 +0100506 return !!pin->output_value;
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700507
508 ret = irq_get_irqchip_state(pin->irq, IRQCHIP_STATE_LINE_LEVEL, &state);
509 if (!ret)
510 ret = !!state;
511
512 return ret;
513}
514
515static void pm8xxx_mpp_set(struct gpio_chip *chip, unsigned offset, int value)
516{
Linus Walleijed479412015-12-08 10:13:53 +0100517 struct pm8xxx_mpp *pctrl = gpiochip_get_data(chip);
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700518 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
519
520 pin->output_value = !!value;
521
522 pm8xxx_mpp_update(pctrl, pin);
523}
524
525static int pm8xxx_mpp_of_xlate(struct gpio_chip *chip,
526 const struct of_phandle_args *gpio_desc,
527 u32 *flags)
528{
529 if (chip->of_gpio_n_cells < 2)
530 return -EINVAL;
531
532 if (flags)
533 *flags = gpio_desc->args[1];
534
535 return gpio_desc->args[0] - 1;
536}
537
538
539static int pm8xxx_mpp_to_irq(struct gpio_chip *chip, unsigned offset)
540{
Linus Walleijed479412015-12-08 10:13:53 +0100541 struct pm8xxx_mpp *pctrl = gpiochip_get_data(chip);
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700542 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
543
544 return pin->irq;
545}
546
547#ifdef CONFIG_DEBUG_FS
548#include <linux/seq_file.h>
549
550static void pm8xxx_mpp_dbg_show_one(struct seq_file *s,
551 struct pinctrl_dev *pctldev,
552 struct gpio_chip *chip,
553 unsigned offset,
554 unsigned gpio)
555{
Linus Walleijed479412015-12-08 10:13:53 +0100556 struct pm8xxx_mpp *pctrl = gpiochip_get_data(chip);
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700557 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
558
559 static const char * const aout_lvls[] = {
560 "1v25", "1v25_2", "0v625", "0v3125", "mpp", "abus1", "abus2",
561 "abus3"
562 };
563
564 static const char * const amuxs[] = {
565 "amux5", "amux6", "amux7", "amux8", "amux9", "abus1", "abus2",
566 "abus3",
567 };
568
569 seq_printf(s, " mpp%-2d:", offset + 1);
570
571 switch (pin->mode) {
572 case PM8XXX_MPP_DIGITAL:
573 seq_puts(s, " digital ");
574 if (pin->dtest) {
575 seq_printf(s, "dtest%d\n", pin->dtest);
576 } else if (pin->input && pin->output) {
577 if (pin->high_z)
578 seq_puts(s, "bi-dir high-z");
579 else
580 seq_printf(s, "bi-dir %dOhm", pin->pullup);
581 } else if (pin->input) {
582 if (pin->dtest)
583 seq_printf(s, "in dtest%d", pin->dtest);
584 else
585 seq_puts(s, "in gpio");
586 } else if (pin->output) {
587 seq_puts(s, "out ");
588
589 if (!pin->paired) {
590 seq_puts(s, pin->output_value ?
591 "high" : "low");
592 } else {
593 seq_puts(s, pin->output_value ?
594 "inverted" : "follow");
595 }
596 }
597 break;
598 case PM8XXX_MPP_ANALOG:
599 seq_puts(s, " analog ");
600 if (pin->output) {
601 seq_printf(s, "out %s ", aout_lvls[pin->aout_level]);
602 if (!pin->paired) {
603 seq_puts(s, pin->output_value ?
604 "high" : "low");
605 } else {
606 seq_puts(s, pin->output_value ?
607 "inverted" : "follow");
608 }
609 } else {
610 seq_printf(s, "input mux %s", amuxs[pin->amux]);
611 }
612 break;
613 case PM8XXX_MPP_SINK:
614 seq_printf(s, " sink %dmA ", pin->drive_strength);
615 if (pin->dtest) {
616 seq_printf(s, "dtest%d", pin->dtest);
617 } else {
618 if (!pin->paired) {
619 seq_puts(s, pin->output_value ?
620 "high" : "low");
621 } else {
622 seq_puts(s, pin->output_value ?
623 "inverted" : "follow");
624 }
625 }
626 break;
627 }
628
629}
630
631static void pm8xxx_mpp_dbg_show(struct seq_file *s, struct gpio_chip *chip)
632{
633 unsigned gpio = chip->base;
634 unsigned i;
635
636 for (i = 0; i < chip->ngpio; i++, gpio++) {
637 pm8xxx_mpp_dbg_show_one(s, NULL, chip, i, gpio);
638 seq_puts(s, "\n");
639 }
640}
641
642#else
Jonas Gorski11091fb2015-10-11 17:39:31 +0200643#define pm8xxx_mpp_dbg_show NULL
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700644#endif
645
646static struct gpio_chip pm8xxx_mpp_template = {
647 .direction_input = pm8xxx_mpp_direction_input,
648 .direction_output = pm8xxx_mpp_direction_output,
649 .get = pm8xxx_mpp_get,
650 .set = pm8xxx_mpp_set,
651 .of_xlate = pm8xxx_mpp_of_xlate,
652 .to_irq = pm8xxx_mpp_to_irq,
653 .dbg_show = pm8xxx_mpp_dbg_show,
654 .owner = THIS_MODULE,
655};
656
657static int pm8xxx_pin_populate(struct pm8xxx_mpp *pctrl,
658 struct pm8xxx_pin_data *pin)
659{
660 unsigned int val;
661 unsigned level;
662 unsigned ctrl;
663 unsigned type;
664 int ret;
665
666 ret = regmap_read(pctrl->regmap, pin->reg, &val);
667 if (ret) {
668 dev_err(pctrl->dev, "failed to read register\n");
669 return ret;
670 }
671
672 type = (val >> 5) & 7;
673 level = (val >> 2) & 7;
674 ctrl = (val) & 3;
675
676 switch (type) {
677 case PM8XXX_MPP_TYPE_D_INPUT:
678 pin->mode = PM8XXX_MPP_DIGITAL;
679 pin->input = true;
680 pin->power_source = level;
681 pin->dtest = ctrl;
682 break;
683 case PM8XXX_MPP_TYPE_D_OUTPUT:
684 pin->mode = PM8XXX_MPP_DIGITAL;
685 pin->output = true;
686 pin->power_source = level;
687 pin->output_value = !!(ctrl & BIT(0));
688 pin->paired = !!(ctrl & BIT(1));
689 break;
690 case PM8XXX_MPP_TYPE_D_BI_DIR:
691 pin->mode = PM8XXX_MPP_DIGITAL;
692 pin->input = true;
693 pin->output = true;
694 pin->power_source = level;
695 switch (ctrl) {
696 case PM8XXX_MPP_BI_PULLUP_1KOHM:
697 pin->pullup = 600;
698 break;
699 case PM8XXX_MPP_BI_PULLUP_OPEN:
700 pin->high_z = true;
701 break;
702 case PM8XXX_MPP_BI_PULLUP_10KOHM:
703 pin->pullup = 10000;
704 break;
705 case PM8XXX_MPP_BI_PULLUP_30KOHM:
706 pin->pullup = 30000;
707 break;
708 }
709 break;
710 case PM8XXX_MPP_TYPE_A_INPUT:
711 pin->mode = PM8XXX_MPP_ANALOG;
712 pin->input = true;
713 pin->amux = level;
714 break;
715 case PM8XXX_MPP_TYPE_A_OUTPUT:
716 pin->mode = PM8XXX_MPP_ANALOG;
717 pin->output = true;
718 pin->aout_level = level;
719 pin->output_value = !!(ctrl & BIT(0));
720 pin->paired = !!(ctrl & BIT(1));
721 break;
722 case PM8XXX_MPP_TYPE_SINK:
723 pin->mode = PM8XXX_MPP_SINK;
724 pin->drive_strength = 5 * (level + 1);
725 pin->output_value = !!(ctrl & BIT(0));
726 pin->paired = !!(ctrl & BIT(1));
727 break;
728 case PM8XXX_MPP_TYPE_DTEST_SINK:
729 pin->mode = PM8XXX_MPP_SINK;
730 pin->dtest = ctrl + 1;
731 pin->drive_strength = 5 * (level + 1);
732 break;
733 case PM8XXX_MPP_TYPE_DTEST_OUTPUT:
734 pin->mode = PM8XXX_MPP_DIGITAL;
735 pin->power_source = level;
736 if (ctrl >= 1)
737 pin->dtest = ctrl;
738 break;
739 }
740
741 return 0;
742}
743
744static const struct of_device_id pm8xxx_mpp_of_match[] = {
Stephen Boydab4256c2015-11-18 11:33:17 -0800745 { .compatible = "qcom,pm8018-mpp" },
746 { .compatible = "qcom,pm8038-mpp" },
Linus Walleij38c1e5e2016-06-03 13:55:00 +0200747 { .compatible = "qcom,pm8058-mpp" },
Stephen Boydab4256c2015-11-18 11:33:17 -0800748 { .compatible = "qcom,pm8917-mpp" },
749 { .compatible = "qcom,pm8821-mpp" },
750 { .compatible = "qcom,pm8921-mpp" },
751 { .compatible = "qcom,ssbi-mpp" },
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700752 { },
753};
754MODULE_DEVICE_TABLE(of, pm8xxx_mpp_of_match);
755
756static int pm8xxx_mpp_probe(struct platform_device *pdev)
757{
758 struct pm8xxx_pin_data *pin_data;
759 struct pinctrl_pin_desc *pins;
760 struct pm8xxx_mpp *pctrl;
761 int ret;
Stephen Boyda5ea13f2016-01-06 17:37:41 -0800762 int i, npins;
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700763
764 pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
765 if (!pctrl)
766 return -ENOMEM;
767
768 pctrl->dev = &pdev->dev;
Stephen Boyda5ea13f2016-01-06 17:37:41 -0800769 npins = platform_irq_count(pdev);
770 if (!npins)
Stephen Boydab4256c2015-11-18 11:33:17 -0800771 return -EINVAL;
Stephen Boyda5ea13f2016-01-06 17:37:41 -0800772 if (npins < 0)
773 return npins;
774 pctrl->npins = npins;
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700775
776 pctrl->regmap = dev_get_regmap(pdev->dev.parent, NULL);
777 if (!pctrl->regmap) {
778 dev_err(&pdev->dev, "parent regmap unavailable\n");
779 return -ENXIO;
780 }
781
782 pctrl->desc = pm8xxx_pinctrl_desc;
783 pctrl->desc.npins = pctrl->npins;
784
785 pins = devm_kcalloc(&pdev->dev,
786 pctrl->desc.npins,
787 sizeof(struct pinctrl_pin_desc),
788 GFP_KERNEL);
789 if (!pins)
790 return -ENOMEM;
791
792 pin_data = devm_kcalloc(&pdev->dev,
793 pctrl->desc.npins,
794 sizeof(struct pm8xxx_pin_data),
795 GFP_KERNEL);
796 if (!pin_data)
797 return -ENOMEM;
798
799 for (i = 0; i < pctrl->desc.npins; i++) {
800 pin_data[i].reg = SSBI_REG_ADDR_MPP(i);
801 pin_data[i].irq = platform_get_irq(pdev, i);
802 if (pin_data[i].irq < 0) {
803 dev_err(&pdev->dev,
804 "missing interrupts for pin %d\n", i);
805 return pin_data[i].irq;
806 }
807
808 ret = pm8xxx_pin_populate(pctrl, &pin_data[i]);
809 if (ret)
810 return ret;
811
812 pins[i].number = i;
813 pins[i].name = pm8xxx_groups[i];
814 pins[i].drv_data = &pin_data[i];
815 }
816 pctrl->desc.pins = pins;
817
818 pctrl->desc.num_custom_params = ARRAY_SIZE(pm8xxx_mpp_bindings);
819 pctrl->desc.custom_params = pm8xxx_mpp_bindings;
820#ifdef CONFIG_DEBUG_FS
821 pctrl->desc.custom_conf_items = pm8xxx_conf_items;
822#endif
823
Laxman Dewangan5f5e1112016-02-24 14:44:07 +0530824 pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl);
Julia Lawalld259ec22015-08-24 23:12:26 +0200825 if (IS_ERR(pctrl->pctrl)) {
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700826 dev_err(&pdev->dev, "couldn't register pm8xxx mpp driver\n");
Julia Lawalld259ec22015-08-24 23:12:26 +0200827 return PTR_ERR(pctrl->pctrl);
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700828 }
829
830 pctrl->chip = pm8xxx_mpp_template;
831 pctrl->chip.base = -1;
Linus Walleij58383c782015-11-04 09:56:26 +0100832 pctrl->chip.parent = &pdev->dev;
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700833 pctrl->chip.of_node = pdev->dev.of_node;
834 pctrl->chip.of_gpio_n_cells = 2;
835 pctrl->chip.label = dev_name(pctrl->dev);
836 pctrl->chip.ngpio = pctrl->npins;
Linus Walleijed479412015-12-08 10:13:53 +0100837 ret = gpiochip_add_data(&pctrl->chip, pctrl);
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700838 if (ret) {
839 dev_err(&pdev->dev, "failed register gpiochip\n");
Laxman Dewangan5f5e1112016-02-24 14:44:07 +0530840 return ret;
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700841 }
842
843 ret = gpiochip_add_pin_range(&pctrl->chip,
844 dev_name(pctrl->dev),
845 0, 0, pctrl->chip.ngpio);
846 if (ret) {
847 dev_err(pctrl->dev, "failed to add pin range\n");
848 goto unregister_gpiochip;
849 }
850
851 platform_set_drvdata(pdev, pctrl);
852
853 dev_dbg(&pdev->dev, "Qualcomm pm8xxx mpp driver probed\n");
854
855 return 0;
856
857unregister_gpiochip:
858 gpiochip_remove(&pctrl->chip);
859
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700860 return ret;
861}
862
863static int pm8xxx_mpp_remove(struct platform_device *pdev)
864{
865 struct pm8xxx_mpp *pctrl = platform_get_drvdata(pdev);
866
867 gpiochip_remove(&pctrl->chip);
868
Bjorn Anderssonb4c45fe2015-07-14 23:40:35 -0700869 return 0;
870}
871
872static struct platform_driver pm8xxx_mpp_driver = {
873 .driver = {
874 .name = "qcom-ssbi-mpp",
875 .of_match_table = pm8xxx_mpp_of_match,
876 },
877 .probe = pm8xxx_mpp_probe,
878 .remove = pm8xxx_mpp_remove,
879};
880
881module_platform_driver(pm8xxx_mpp_driver);
882
883MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
884MODULE_DESCRIPTION("Qualcomm PM8xxx MPP driver");
885MODULE_LICENSE("GPL v2");