blob: 77e9dd7aebc8fb0e801b7ea8a160f911aa78bacf [file] [log] [blame]
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001/*
Fenglin Wu60a05cb2016-07-21 14:32:24 +08002 * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved.
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/gpio.h>
15#include <linux/module.h>
16#include <linux/of.h>
Stephen Boydab4256c2015-11-18 11:33:17 -080017#include <linux/of_irq.h>
Ivan T. Ivanoveadff302014-10-22 12:58:46 +030018#include <linux/pinctrl/pinconf-generic.h>
19#include <linux/pinctrl/pinconf.h>
20#include <linux/pinctrl/pinmux.h>
21#include <linux/platform_device.h>
22#include <linux/regmap.h>
23#include <linux/slab.h>
24#include <linux/types.h>
25
26#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
27
28#include "../core.h"
29#include "../pinctrl-utils.h"
30
31#define PMIC_GPIO_ADDRESS_RANGE 0x100
32
33/* type and subtype registers base address offsets */
34#define PMIC_GPIO_REG_TYPE 0x4
35#define PMIC_GPIO_REG_SUBTYPE 0x5
36
37/* GPIO peripheral type and subtype out_values */
38#define PMIC_GPIO_TYPE 0x10
39#define PMIC_GPIO_SUBTYPE_GPIO_4CH 0x1
40#define PMIC_GPIO_SUBTYPE_GPIOC_4CH 0x5
41#define PMIC_GPIO_SUBTYPE_GPIO_8CH 0x9
42#define PMIC_GPIO_SUBTYPE_GPIOC_8CH 0xd
Fenglin Wu60a05cb2016-07-21 14:32:24 +080043#define PMIC_GPIO_SUBTYPE_GPIO_LV 0x10
44#define PMIC_GPIO_SUBTYPE_GPIO_MV 0x11
Ivan T. Ivanoveadff302014-10-22 12:58:46 +030045
46#define PMIC_MPP_REG_RT_STS 0x10
47#define PMIC_MPP_REG_RT_STS_VAL_MASK 0x1
48
49/* control register base address offsets */
50#define PMIC_GPIO_REG_MODE_CTL 0x40
51#define PMIC_GPIO_REG_DIG_VIN_CTL 0x41
52#define PMIC_GPIO_REG_DIG_PULL_CTL 0x42
Fenglin Wu60a05cb2016-07-21 14:32:24 +080053#define PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL 0x44
Fenglin Wuf6c0e702016-07-21 15:33:03 +080054#define PMIC_GPIO_REG_DIG_IN_CTL 0x43
Ivan T. Ivanoveadff302014-10-22 12:58:46 +030055#define PMIC_GPIO_REG_DIG_OUT_CTL 0x45
56#define PMIC_GPIO_REG_EN_CTL 0x46
Fenglin Wu60a05cb2016-07-21 14:32:24 +080057#define PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL 0x4A
Ivan T. Ivanoveadff302014-10-22 12:58:46 +030058
59/* PMIC_GPIO_REG_MODE_CTL */
60#define PMIC_GPIO_REG_MODE_VALUE_SHIFT 0x1
61#define PMIC_GPIO_REG_MODE_FUNCTION_SHIFT 1
62#define PMIC_GPIO_REG_MODE_FUNCTION_MASK 0x7
63#define PMIC_GPIO_REG_MODE_DIR_SHIFT 4
64#define PMIC_GPIO_REG_MODE_DIR_MASK 0x7
65
Fenglin Wu60a05cb2016-07-21 14:32:24 +080066#define PMIC_GPIO_MODE_DIGITAL_INPUT 0
67#define PMIC_GPIO_MODE_DIGITAL_OUTPUT 1
68#define PMIC_GPIO_MODE_DIGITAL_INPUT_OUTPUT 2
69#define PMIC_GPIO_MODE_ANALOG_PASS_THRU 3
70
71#define PMIC_GPIO_REG_LV_MV_MODE_DIR_MASK 0x3
72
Ivan T. Ivanoveadff302014-10-22 12:58:46 +030073/* PMIC_GPIO_REG_DIG_VIN_CTL */
74#define PMIC_GPIO_REG_VIN_SHIFT 0
75#define PMIC_GPIO_REG_VIN_MASK 0x7
76
77/* PMIC_GPIO_REG_DIG_PULL_CTL */
78#define PMIC_GPIO_REG_PULL_SHIFT 0
79#define PMIC_GPIO_REG_PULL_MASK 0x7
80
81#define PMIC_GPIO_PULL_DOWN 4
82#define PMIC_GPIO_PULL_DISABLE 5
83
Fenglin Wu60a05cb2016-07-21 14:32:24 +080084/* PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL for LV/MV */
85#define PMIC_GPIO_LV_MV_OUTPUT_INVERT 0x80
86#define PMIC_GPIO_LV_MV_OUTPUT_INVERT_SHIFT 7
87#define PMIC_GPIO_LV_MV_OUTPUT_SOURCE_SEL_MASK 0xF
88
Fenglin Wuf6c0e702016-07-21 15:33:03 +080089/* PMIC_GPIO_REG_DIG_IN_CTL */
90#define PMIC_GPIO_LV_MV_DIG_IN_DTEST_EN 0x80
91#define PMIC_GPIO_LV_MV_DIG_IN_DTEST_SEL_MASK 0x7
92#define PMIC_GPIO_DIG_IN_DTEST_SEL_MASK 0xf
93
Ivan T. Ivanoveadff302014-10-22 12:58:46 +030094/* PMIC_GPIO_REG_DIG_OUT_CTL */
95#define PMIC_GPIO_REG_OUT_STRENGTH_SHIFT 0
96#define PMIC_GPIO_REG_OUT_STRENGTH_MASK 0x3
97#define PMIC_GPIO_REG_OUT_TYPE_SHIFT 4
98#define PMIC_GPIO_REG_OUT_TYPE_MASK 0x3
99
100/*
101 * Output type - indicates pin should be configured as push-pull,
102 * open drain or open source.
103 */
104#define PMIC_GPIO_OUT_BUF_CMOS 0
105#define PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS 1
106#define PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS 2
107
108/* PMIC_GPIO_REG_EN_CTL */
109#define PMIC_GPIO_REG_MASTER_EN_SHIFT 7
110
111#define PMIC_GPIO_PHYSICAL_OFFSET 1
112
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800113/* PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL */
114#define PMIC_GPIO_LV_MV_ANA_MUX_SEL_MASK 0x3
115
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300116/* Qualcomm specific pin configurations */
117#define PMIC_GPIO_CONF_PULL_UP (PIN_CONFIG_END + 1)
118#define PMIC_GPIO_CONF_STRENGTH (PIN_CONFIG_END + 2)
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800119#define PMIC_GPIO_CONF_ATEST (PIN_CONFIG_END + 3)
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800120#define PMIC_GPIO_CONF_DTEST_BUFFER (PIN_CONFIG_END + 4)
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800121
122/* The index of each function in pmic_gpio_functions[] array */
123enum pmic_gpio_func_index {
124 PMIC_GPIO_FUNC_INDEX_NORMAL = 0x00,
125 PMIC_GPIO_FUNC_INDEX_PAIRED = 0x01,
126 PMIC_GPIO_FUNC_INDEX_FUNC1 = 0x02,
127 PMIC_GPIO_FUNC_INDEX_FUNC2 = 0x03,
128 PMIC_GPIO_FUNC_INDEX_FUNC3 = 0x04,
129 PMIC_GPIO_FUNC_INDEX_FUNC4 = 0x05,
130 PMIC_GPIO_FUNC_INDEX_DTEST1 = 0x06,
131 PMIC_GPIO_FUNC_INDEX_DTEST2 = 0x07,
132 PMIC_GPIO_FUNC_INDEX_DTEST3 = 0x08,
133 PMIC_GPIO_FUNC_INDEX_DTEST4 = 0x09,
134 PMIC_GPIO_FUNC_INDEX_ANALOG = 0x10,
135};
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300136
137/**
138 * struct pmic_gpio_pad - keep current GPIO settings
139 * @base: Address base in SPMI device.
140 * @irq: IRQ number which this GPIO generate.
141 * @is_enabled: Set to false when GPIO should be put in high Z state.
142 * @out_value: Cached pin output value
143 * @have_buffer: Set to true if GPIO output could be configured in push-pull,
144 * open-drain or open-source mode.
145 * @output_enabled: Set to true if GPIO output logic is enabled.
146 * @input_enabled: Set to true if GPIO input buffer logic is enabled.
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800147 * @lv_mv_type: Set to true if GPIO subtype is GPIO_LV(0x10) or GPIO_MV(0x11).
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300148 * @num_sources: Number of power-sources supported by this GPIO.
149 * @power_source: Current power-source used.
150 * @buffer_type: Push-pull, open-drain or open-source.
151 * @pullup: Constant current which flow trough GPIO output buffer.
152 * @strength: No, Low, Medium, High
153 * @function: See pmic_gpio_functions[]
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800154 * @atest: the ATEST selection for GPIO analog-pass-through mode
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800155 * @dtest_buffer: the DTEST buffer selection for digital input mode,
156 * the default value is INT_MAX if not used.
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300157 */
158struct pmic_gpio_pad {
159 u16 base;
160 int irq;
161 bool is_enabled;
162 bool out_value;
163 bool have_buffer;
164 bool output_enabled;
165 bool input_enabled;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800166 bool lv_mv_type;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300167 unsigned int num_sources;
168 unsigned int power_source;
169 unsigned int buffer_type;
170 unsigned int pullup;
171 unsigned int strength;
172 unsigned int function;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800173 unsigned int atest;
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800174 unsigned int dtest_buffer;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300175};
176
177struct pmic_gpio_state {
178 struct device *dev;
179 struct regmap *map;
180 struct pinctrl_dev *ctrl;
181 struct gpio_chip chip;
182};
183
Linus Walleijf684e4a2015-01-12 00:45:55 +0100184static const struct pinconf_generic_params pmic_gpio_bindings[] = {
Soren Brinkmann7382b622015-01-09 07:43:51 -0800185 {"qcom,pull-up-strength", PMIC_GPIO_CONF_PULL_UP, 0},
186 {"qcom,drive-strength", PMIC_GPIO_CONF_STRENGTH, 0},
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800187 {"qcom,atest", PMIC_GPIO_CONF_ATEST, 0},
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800188 {"qcom,dtest-buffer", PMIC_GPIO_CONF_DTEST_BUFFER, 0},
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300189};
190
Arnd Bergmann4f062662015-01-28 17:08:44 +0100191#ifdef CONFIG_DEBUG_FS
Soren Brinkmann7382b622015-01-09 07:43:51 -0800192static const struct pin_config_item pmic_conf_items[ARRAY_SIZE(pmic_gpio_bindings)] = {
193 PCONFDUMP(PMIC_GPIO_CONF_PULL_UP, "pull up strength", NULL, true),
194 PCONFDUMP(PMIC_GPIO_CONF_STRENGTH, "drive-strength", NULL, true),
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800195 PCONFDUMP(PMIC_GPIO_CONF_ATEST, "atest", NULL, true),
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300196};
Arnd Bergmann4f062662015-01-28 17:08:44 +0100197#endif
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300198
199static const char *const pmic_gpio_groups[] = {
200 "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", "gpio8",
201 "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", "gpio15",
202 "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", "gpio22",
203 "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29",
204 "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", "gpio36",
205};
206
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800207/*
208 * Treat LV/MV GPIO analog-pass-through mode as a function, add it
209 * to the end of the function list. Add placeholder for the reserved
210 * functions defined in LV/MV OUTPUT_SOURCE_SEL register.
211 */
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300212static const char *const pmic_gpio_functions[] = {
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800213 [PMIC_GPIO_FUNC_INDEX_NORMAL] = PMIC_GPIO_FUNC_NORMAL,
214 [PMIC_GPIO_FUNC_INDEX_PAIRED] = PMIC_GPIO_FUNC_PAIRED,
215 [PMIC_GPIO_FUNC_INDEX_FUNC1] = PMIC_GPIO_FUNC_FUNC1,
216 [PMIC_GPIO_FUNC_INDEX_FUNC2] = PMIC_GPIO_FUNC_FUNC2,
217 [PMIC_GPIO_FUNC_INDEX_FUNC3] = PMIC_GPIO_FUNC_FUNC3,
218 [PMIC_GPIO_FUNC_INDEX_FUNC4] = PMIC_GPIO_FUNC_FUNC4,
219 [PMIC_GPIO_FUNC_INDEX_DTEST1] = PMIC_GPIO_FUNC_DTEST1,
220 [PMIC_GPIO_FUNC_INDEX_DTEST2] = PMIC_GPIO_FUNC_DTEST2,
221 [PMIC_GPIO_FUNC_INDEX_DTEST3] = PMIC_GPIO_FUNC_DTEST3,
222 [PMIC_GPIO_FUNC_INDEX_DTEST4] = PMIC_GPIO_FUNC_DTEST4,
223 "reserved-a", "reserved-b", "reserved-c",
224 "reserved-d", "reserved-e", "reserved-f",
225 [PMIC_GPIO_FUNC_INDEX_ANALOG] = PMIC_GPIO_FUNC_ANALOG,
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300226};
227
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300228static int pmic_gpio_read(struct pmic_gpio_state *state,
229 struct pmic_gpio_pad *pad, unsigned int addr)
230{
231 unsigned int val;
232 int ret;
233
234 ret = regmap_read(state->map, pad->base + addr, &val);
235 if (ret < 0)
236 dev_err(state->dev, "read 0x%x failed\n", addr);
237 else
238 ret = val;
239
240 return ret;
241}
242
243static int pmic_gpio_write(struct pmic_gpio_state *state,
244 struct pmic_gpio_pad *pad, unsigned int addr,
245 unsigned int val)
246{
247 int ret;
248
249 ret = regmap_write(state->map, pad->base + addr, val);
250 if (ret < 0)
251 dev_err(state->dev, "write 0x%x failed\n", addr);
252
253 return ret;
254}
255
256static int pmic_gpio_get_groups_count(struct pinctrl_dev *pctldev)
257{
258 /* Every PIN is a group */
259 return pctldev->desc->npins;
260}
261
262static const char *pmic_gpio_get_group_name(struct pinctrl_dev *pctldev,
263 unsigned pin)
264{
265 return pctldev->desc->pins[pin].name;
266}
267
268static int pmic_gpio_get_group_pins(struct pinctrl_dev *pctldev, unsigned pin,
269 const unsigned **pins, unsigned *num_pins)
270{
271 *pins = &pctldev->desc->pins[pin].number;
272 *num_pins = 1;
273 return 0;
274}
275
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300276static const struct pinctrl_ops pmic_gpio_pinctrl_ops = {
277 .get_groups_count = pmic_gpio_get_groups_count,
278 .get_group_name = pmic_gpio_get_group_name,
279 .get_group_pins = pmic_gpio_get_group_pins,
Soren Brinkmann7382b622015-01-09 07:43:51 -0800280 .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
Irina Tirdead32f7fd2016-03-31 14:44:42 +0300281 .dt_free_map = pinctrl_utils_free_map,
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300282};
283
284static int pmic_gpio_get_functions_count(struct pinctrl_dev *pctldev)
285{
286 return ARRAY_SIZE(pmic_gpio_functions);
287}
288
289static const char *pmic_gpio_get_function_name(struct pinctrl_dev *pctldev,
290 unsigned function)
291{
292 return pmic_gpio_functions[function];
293}
294
295static int pmic_gpio_get_function_groups(struct pinctrl_dev *pctldev,
296 unsigned function,
297 const char *const **groups,
298 unsigned *const num_qgroups)
299{
300 *groups = pmic_gpio_groups;
301 *num_qgroups = pctldev->desc->npins;
302 return 0;
303}
304
305static int pmic_gpio_set_mux(struct pinctrl_dev *pctldev, unsigned function,
306 unsigned pin)
307{
308 struct pmic_gpio_state *state = pinctrl_dev_get_drvdata(pctldev);
309 struct pmic_gpio_pad *pad;
310 unsigned int val;
311 int ret;
312
313 pad = pctldev->desc->pins[pin].drv_data;
314
315 pad->function = function;
316
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800317 val = PMIC_GPIO_MODE_DIGITAL_INPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300318 if (pad->output_enabled) {
319 if (pad->input_enabled)
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800320 val = PMIC_GPIO_MODE_DIGITAL_INPUT_OUTPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300321 else
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800322 val = PMIC_GPIO_MODE_DIGITAL_OUTPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300323 }
324
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800325 if (function > PMIC_GPIO_FUNC_INDEX_DTEST4 &&
326 function < PMIC_GPIO_FUNC_INDEX_ANALOG) {
327 pr_err("reserved function: %s hasn't been enabled\n",
328 pmic_gpio_functions[function]);
329 return -EINVAL;
330 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300331
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800332 if (pad->lv_mv_type) {
333 if (pad->function == PMIC_GPIO_FUNC_INDEX_ANALOG) {
334 val = PMIC_GPIO_MODE_ANALOG_PASS_THRU;
335 ret = pmic_gpio_write(state, pad,
336 PMIC_GPIO_REG_MODE_CTL, val);
337 if (ret < 0)
338 return ret;
339
340 ret = pmic_gpio_write(state, pad,
341 PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL,
342 pad->atest);
343 if (ret < 0)
344 return ret;
345 } else {
346 ret = pmic_gpio_write(state, pad,
347 PMIC_GPIO_REG_MODE_CTL, val);
348 if (ret < 0)
349 return ret;
350
351 val = pad->out_value
352 << PMIC_GPIO_LV_MV_OUTPUT_INVERT_SHIFT;
353 val |= pad->function
354 & PMIC_GPIO_LV_MV_OUTPUT_SOURCE_SEL_MASK;
355 ret = pmic_gpio_write(state, pad,
356 PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL, val);
357 if (ret < 0)
358 return ret;
359 }
360 } else {
361 /*
362 * GPIO not of LV/MV subtype doesn't have "func3", "func4"
363 * "analog" functions, and "dtest1" to "dtest4" functions
364 * have register value 2 bits lower than the function index
365 * in pmic_gpio_functions[].
366 */
367 if (function == PMIC_GPIO_FUNC_INDEX_FUNC3
368 || function == PMIC_GPIO_FUNC_INDEX_FUNC4
369 || function == PMIC_GPIO_FUNC_INDEX_ANALOG) {
370 return -EINVAL;
371 } else if (function >= PMIC_GPIO_FUNC_INDEX_DTEST1 &&
372 function <= PMIC_GPIO_FUNC_INDEX_DTEST4) {
373 pad->function -= (PMIC_GPIO_FUNC_INDEX_DTEST1 -
374 PMIC_GPIO_FUNC_INDEX_FUNC3);
375 }
376
377 val = val << PMIC_GPIO_REG_MODE_DIR_SHIFT;
378 val |= pad->function << PMIC_GPIO_REG_MODE_FUNCTION_SHIFT;
379 val |= pad->out_value & PMIC_GPIO_REG_MODE_VALUE_SHIFT;
380
381 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_MODE_CTL, val);
382 if (ret < 0)
383 return ret;
384 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300385
386 val = pad->is_enabled << PMIC_GPIO_REG_MASTER_EN_SHIFT;
387
388 return pmic_gpio_write(state, pad, PMIC_GPIO_REG_EN_CTL, val);
389}
390
391static const struct pinmux_ops pmic_gpio_pinmux_ops = {
392 .get_functions_count = pmic_gpio_get_functions_count,
393 .get_function_name = pmic_gpio_get_function_name,
394 .get_function_groups = pmic_gpio_get_function_groups,
395 .set_mux = pmic_gpio_set_mux,
396};
397
398static int pmic_gpio_config_get(struct pinctrl_dev *pctldev,
399 unsigned int pin, unsigned long *config)
400{
401 unsigned param = pinconf_to_config_param(*config);
402 struct pmic_gpio_pad *pad;
403 unsigned arg;
404
405 pad = pctldev->desc->pins[pin].drv_data;
406
407 switch (param) {
408 case PIN_CONFIG_DRIVE_PUSH_PULL:
409 arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_CMOS;
410 break;
411 case PIN_CONFIG_DRIVE_OPEN_DRAIN:
412 arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS;
413 break;
414 case PIN_CONFIG_DRIVE_OPEN_SOURCE:
415 arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS;
416 break;
417 case PIN_CONFIG_BIAS_PULL_DOWN:
418 arg = pad->pullup == PMIC_GPIO_PULL_DOWN;
419 break;
420 case PIN_CONFIG_BIAS_DISABLE:
421 arg = pad->pullup = PMIC_GPIO_PULL_DISABLE;
422 break;
423 case PIN_CONFIG_BIAS_PULL_UP:
424 arg = pad->pullup == PMIC_GPIO_PULL_UP_30;
425 break;
426 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
427 arg = !pad->is_enabled;
428 break;
429 case PIN_CONFIG_POWER_SOURCE:
430 arg = pad->power_source;
431 break;
432 case PIN_CONFIG_INPUT_ENABLE:
433 arg = pad->input_enabled;
434 break;
435 case PIN_CONFIG_OUTPUT:
436 arg = pad->out_value;
437 break;
438 case PMIC_GPIO_CONF_PULL_UP:
439 arg = pad->pullup;
440 break;
441 case PMIC_GPIO_CONF_STRENGTH:
442 arg = pad->strength;
443 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800444 case PMIC_GPIO_CONF_ATEST:
445 arg = pad->atest;
446 break;
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800447 case PMIC_GPIO_CONF_DTEST_BUFFER:
448 arg = pad->dtest_buffer;
449 break;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300450 default:
451 return -EINVAL;
452 }
453
454 *config = pinconf_to_config_packed(param, arg);
455 return 0;
456}
457
458static int pmic_gpio_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
459 unsigned long *configs, unsigned nconfs)
460{
461 struct pmic_gpio_state *state = pinctrl_dev_get_drvdata(pctldev);
462 struct pmic_gpio_pad *pad;
463 unsigned param, arg;
464 unsigned int val;
465 int i, ret;
466
467 pad = pctldev->desc->pins[pin].drv_data;
468
469 for (i = 0; i < nconfs; i++) {
470 param = pinconf_to_config_param(configs[i]);
471 arg = pinconf_to_config_argument(configs[i]);
472
473 switch (param) {
474 case PIN_CONFIG_DRIVE_PUSH_PULL:
475 pad->buffer_type = PMIC_GPIO_OUT_BUF_CMOS;
476 break;
477 case PIN_CONFIG_DRIVE_OPEN_DRAIN:
478 if (!pad->have_buffer)
479 return -EINVAL;
480 pad->buffer_type = PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS;
481 break;
482 case PIN_CONFIG_DRIVE_OPEN_SOURCE:
483 if (!pad->have_buffer)
484 return -EINVAL;
485 pad->buffer_type = PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS;
486 break;
487 case PIN_CONFIG_BIAS_DISABLE:
488 pad->pullup = PMIC_GPIO_PULL_DISABLE;
489 break;
490 case PIN_CONFIG_BIAS_PULL_UP:
491 pad->pullup = PMIC_GPIO_PULL_UP_30;
492 break;
493 case PIN_CONFIG_BIAS_PULL_DOWN:
494 if (arg)
495 pad->pullup = PMIC_GPIO_PULL_DOWN;
496 else
497 pad->pullup = PMIC_GPIO_PULL_DISABLE;
498 break;
499 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
500 pad->is_enabled = false;
501 break;
502 case PIN_CONFIG_POWER_SOURCE:
Fenglin Wu68c277b2016-08-18 11:41:03 +0800503 if (arg >= pad->num_sources)
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300504 return -EINVAL;
505 pad->power_source = arg;
506 break;
507 case PIN_CONFIG_INPUT_ENABLE:
508 pad->input_enabled = arg ? true : false;
509 break;
510 case PIN_CONFIG_OUTPUT:
511 pad->output_enabled = true;
512 pad->out_value = arg;
513 break;
514 case PMIC_GPIO_CONF_PULL_UP:
515 if (arg > PMIC_GPIO_PULL_UP_1P5_30)
516 return -EINVAL;
517 pad->pullup = arg;
518 break;
519 case PMIC_GPIO_CONF_STRENGTH:
520 if (arg > PMIC_GPIO_STRENGTH_LOW)
521 return -EINVAL;
522 pad->strength = arg;
523 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800524 case PMIC_GPIO_CONF_ATEST:
525 if (arg > PMIC_GPIO_AOUT_ATEST4)
526 return -EINVAL;
527 pad->atest = arg;
528 break;
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800529 case PMIC_GPIO_CONF_DTEST_BUFFER:
530 if ((pad->lv_mv_type && arg > PMIC_GPIO_DIN_DTEST4)
531 || (!pad->lv_mv_type && arg >
532 PMIC_GPIO_DIG_IN_DTEST_SEL_MASK))
533 return -EINVAL;
534 pad->dtest_buffer = arg;
535 break;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300536 default:
537 return -EINVAL;
538 }
539 }
540
541 val = pad->power_source << PMIC_GPIO_REG_VIN_SHIFT;
542
543 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_DIG_VIN_CTL, val);
544 if (ret < 0)
545 return ret;
546
547 val = pad->pullup << PMIC_GPIO_REG_PULL_SHIFT;
548
549 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_DIG_PULL_CTL, val);
550 if (ret < 0)
551 return ret;
552
553 val = pad->buffer_type << PMIC_GPIO_REG_OUT_TYPE_SHIFT;
Ivan T. Ivanov982df6a2015-04-09 18:18:35 +0300554 val |= pad->strength << PMIC_GPIO_REG_OUT_STRENGTH_SHIFT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300555
556 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_DIG_OUT_CTL, val);
557 if (ret < 0)
558 return ret;
559
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800560 val = PMIC_GPIO_MODE_DIGITAL_INPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300561 if (pad->output_enabled) {
562 if (pad->input_enabled)
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800563 val = PMIC_GPIO_MODE_DIGITAL_INPUT_OUTPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300564 else
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800565 val = PMIC_GPIO_MODE_DIGITAL_OUTPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300566 }
567
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800568 if (pad->dtest_buffer != INT_MAX) {
569 val = pad->dtest_buffer;
570 if (pad->lv_mv_type)
571 val |= PMIC_GPIO_LV_MV_DIG_IN_DTEST_EN;
572
573 ret = pmic_gpio_write(state, pad,
574 PMIC_GPIO_REG_DIG_IN_CTL, val);
575 if (ret < 0)
576 return ret;
577 }
578
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800579 if (pad->lv_mv_type) {
580 if (pad->function == PMIC_GPIO_FUNC_INDEX_ANALOG) {
581 val = PMIC_GPIO_MODE_ANALOG_PASS_THRU;
582 ret = pmic_gpio_write(state, pad,
583 PMIC_GPIO_REG_MODE_CTL, val);
584 if (ret < 0)
585 return ret;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300586
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800587 ret = pmic_gpio_write(state, pad,
588 PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL,
589 pad->atest);
590 if (ret < 0)
591 return ret;
592 } else {
593 ret = pmic_gpio_write(state, pad,
594 PMIC_GPIO_REG_MODE_CTL, val);
595 if (ret < 0)
596 return ret;
597
598 val = pad->out_value
599 << PMIC_GPIO_LV_MV_OUTPUT_INVERT_SHIFT;
600 val |= pad->function
601 & PMIC_GPIO_LV_MV_OUTPUT_SOURCE_SEL_MASK;
602 ret = pmic_gpio_write(state, pad,
603 PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL, val);
604 if (ret < 0)
605 return ret;
606 }
607 } else {
608 val = val << PMIC_GPIO_REG_MODE_DIR_SHIFT;
609 val |= pad->function << PMIC_GPIO_REG_MODE_FUNCTION_SHIFT;
610 val |= pad->out_value & PMIC_GPIO_REG_MODE_VALUE_SHIFT;
611
612 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_MODE_CTL, val);
613 if (ret < 0)
614 return ret;
615 }
616
617 return ret;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300618}
619
620static void pmic_gpio_config_dbg_show(struct pinctrl_dev *pctldev,
621 struct seq_file *s, unsigned pin)
622{
623 struct pmic_gpio_state *state = pinctrl_dev_get_drvdata(pctldev);
624 struct pmic_gpio_pad *pad;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800625 int ret, val, function;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300626
627 static const char *const biases[] = {
628 "pull-up 30uA", "pull-up 1.5uA", "pull-up 31.5uA",
629 "pull-up 1.5uA + 30uA boost", "pull-down 10uA", "no pull"
630 };
631 static const char *const buffer_types[] = {
632 "push-pull", "open-drain", "open-source"
633 };
634 static const char *const strengths[] = {
635 "no", "high", "medium", "low"
636 };
637
638 pad = pctldev->desc->pins[pin].drv_data;
639
640 seq_printf(s, " gpio%-2d:", pin + PMIC_GPIO_PHYSICAL_OFFSET);
641
642 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_EN_CTL);
643
644 if (val < 0 || !(val >> PMIC_GPIO_REG_MASTER_EN_SHIFT)) {
645 seq_puts(s, " ---");
646 } else {
647
Ivan T. Ivanov24a66612015-04-09 18:18:36 +0300648 if (pad->input_enabled) {
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300649 ret = pmic_gpio_read(state, pad, PMIC_MPP_REG_RT_STS);
Ivan T. Ivanov24a66612015-04-09 18:18:36 +0300650 if (ret < 0)
651 return;
652
653 ret &= PMIC_MPP_REG_RT_STS_VAL_MASK;
654 pad->out_value = ret;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300655 }
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800656 /*
657 * For GPIO not of LV/MV subtypes, the register value of
658 * the function mapping from "dtest1" to "dtest4" is 2 bits
659 * lower than the function index in pmic_gpio_functions[].
660 */
661 if (!pad->lv_mv_type &&
662 pad->function >= PMIC_GPIO_FUNC_INDEX_FUNC3) {
663 function = pad->function + (PMIC_GPIO_FUNC_INDEX_DTEST1
664 - PMIC_GPIO_FUNC_INDEX_FUNC3);
665 } else {
666 function = pad->function;
667 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300668
669 seq_printf(s, " %-4s", pad->output_enabled ? "out" : "in");
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800670 seq_printf(s, " %-7s", pmic_gpio_functions[function]);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300671 seq_printf(s, " vin-%d", pad->power_source);
672 seq_printf(s, " %-27s", biases[pad->pullup]);
673 seq_printf(s, " %-10s", buffer_types[pad->buffer_type]);
674 seq_printf(s, " %-4s", pad->out_value ? "high" : "low");
675 seq_printf(s, " %-7s", strengths[pad->strength]);
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800676 if (pad->dtest_buffer != INT_MAX)
677 seq_printf(s, " dtest buffer %d", pad->dtest_buffer);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300678 }
679}
680
681static const struct pinconf_ops pmic_gpio_pinconf_ops = {
Soren Brinkmann7382b622015-01-09 07:43:51 -0800682 .is_generic = true,
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300683 .pin_config_group_get = pmic_gpio_config_get,
684 .pin_config_group_set = pmic_gpio_config_set,
685 .pin_config_group_dbg_show = pmic_gpio_config_dbg_show,
686};
687
688static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
689{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100690 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300691 unsigned long config;
692
693 config = pinconf_to_config_packed(PIN_CONFIG_INPUT_ENABLE, 1);
694
695 return pmic_gpio_config_set(state->ctrl, pin, &config, 1);
696}
697
698static int pmic_gpio_direction_output(struct gpio_chip *chip,
699 unsigned pin, int val)
700{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100701 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300702 unsigned long config;
703
704 config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, val);
705
706 return pmic_gpio_config_set(state->ctrl, pin, &config, 1);
707}
708
709static int pmic_gpio_get(struct gpio_chip *chip, unsigned pin)
710{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100711 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300712 struct pmic_gpio_pad *pad;
713 int ret;
714
715 pad = state->ctrl->desc->pins[pin].drv_data;
716
717 if (!pad->is_enabled)
718 return -EINVAL;
719
720 if (pad->input_enabled) {
721 ret = pmic_gpio_read(state, pad, PMIC_MPP_REG_RT_STS);
722 if (ret < 0)
723 return ret;
724
725 pad->out_value = ret & PMIC_MPP_REG_RT_STS_VAL_MASK;
726 }
727
Linus Walleij86c1a212015-12-21 16:29:50 +0100728 return !!pad->out_value;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300729}
730
731static void pmic_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
732{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100733 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300734 unsigned long config;
735
736 config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, value);
737
738 pmic_gpio_config_set(state->ctrl, pin, &config, 1);
739}
740
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300741static int pmic_gpio_of_xlate(struct gpio_chip *chip,
742 const struct of_phandle_args *gpio_desc,
743 u32 *flags)
744{
745 if (chip->of_gpio_n_cells < 2)
746 return -EINVAL;
747
748 if (flags)
749 *flags = gpio_desc->args[1];
750
751 return gpio_desc->args[0] - PMIC_GPIO_PHYSICAL_OFFSET;
752}
753
754static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
755{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100756 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300757 struct pmic_gpio_pad *pad;
758
759 pad = state->ctrl->desc->pins[pin].drv_data;
760
761 return pad->irq;
762}
763
764static void pmic_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
765{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100766 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300767 unsigned i;
768
769 for (i = 0; i < chip->ngpio; i++) {
770 pmic_gpio_config_dbg_show(state->ctrl, s, i);
771 seq_puts(s, "\n");
772 }
773}
774
775static const struct gpio_chip pmic_gpio_gpio_template = {
776 .direction_input = pmic_gpio_direction_input,
777 .direction_output = pmic_gpio_direction_output,
778 .get = pmic_gpio_get,
779 .set = pmic_gpio_set,
Jonas Gorski98c85d52015-10-11 17:34:19 +0200780 .request = gpiochip_generic_request,
781 .free = gpiochip_generic_free,
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300782 .of_xlate = pmic_gpio_of_xlate,
783 .to_irq = pmic_gpio_to_irq,
784 .dbg_show = pmic_gpio_dbg_show,
785};
786
787static int pmic_gpio_populate(struct pmic_gpio_state *state,
788 struct pmic_gpio_pad *pad)
789{
790 int type, subtype, val, dir;
791
792 type = pmic_gpio_read(state, pad, PMIC_GPIO_REG_TYPE);
793 if (type < 0)
794 return type;
795
796 if (type != PMIC_GPIO_TYPE) {
797 dev_err(state->dev, "incorrect block type 0x%x at 0x%x\n",
798 type, pad->base);
799 return -ENODEV;
800 }
801
802 subtype = pmic_gpio_read(state, pad, PMIC_GPIO_REG_SUBTYPE);
803 if (subtype < 0)
804 return subtype;
805
806 switch (subtype) {
807 case PMIC_GPIO_SUBTYPE_GPIO_4CH:
808 pad->have_buffer = true;
809 case PMIC_GPIO_SUBTYPE_GPIOC_4CH:
810 pad->num_sources = 4;
811 break;
812 case PMIC_GPIO_SUBTYPE_GPIO_8CH:
813 pad->have_buffer = true;
814 case PMIC_GPIO_SUBTYPE_GPIOC_8CH:
815 pad->num_sources = 8;
816 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800817 case PMIC_GPIO_SUBTYPE_GPIO_LV:
818 pad->num_sources = 1;
819 pad->have_buffer = true;
820 pad->lv_mv_type = true;
821 break;
822 case PMIC_GPIO_SUBTYPE_GPIO_MV:
823 pad->num_sources = 2;
824 pad->have_buffer = true;
825 pad->lv_mv_type = true;
826 break;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300827 default:
828 dev_err(state->dev, "unknown GPIO type 0x%x\n", subtype);
829 return -ENODEV;
830 }
831
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800832 if (pad->lv_mv_type) {
833 val = pmic_gpio_read(state, pad,
834 PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL);
835 if (val < 0)
836 return val;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300837
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800838 pad->out_value = !!(val & PMIC_GPIO_LV_MV_OUTPUT_INVERT);
839 pad->function = val & PMIC_GPIO_LV_MV_OUTPUT_SOURCE_SEL_MASK;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300840
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800841 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_MODE_CTL);
842 if (val < 0)
843 return val;
844
845 dir = val & PMIC_GPIO_REG_LV_MV_MODE_DIR_MASK;
846 } else {
847 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_MODE_CTL);
848 if (val < 0)
849 return val;
850
851 pad->out_value = val & PMIC_GPIO_REG_MODE_VALUE_SHIFT;
852
853 dir = val >> PMIC_GPIO_REG_MODE_DIR_SHIFT;
854 dir &= PMIC_GPIO_REG_MODE_DIR_MASK;
855 pad->function = val >> PMIC_GPIO_REG_MODE_FUNCTION_SHIFT;
856 pad->function &= PMIC_GPIO_REG_MODE_FUNCTION_MASK;
857 }
858
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300859 switch (dir) {
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800860 case PMIC_GPIO_MODE_DIGITAL_INPUT:
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300861 pad->input_enabled = true;
862 pad->output_enabled = false;
863 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800864 case PMIC_GPIO_MODE_DIGITAL_OUTPUT:
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300865 pad->input_enabled = false;
866 pad->output_enabled = true;
867 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800868 case PMIC_GPIO_MODE_DIGITAL_INPUT_OUTPUT:
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300869 pad->input_enabled = true;
870 pad->output_enabled = true;
871 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800872 case PMIC_GPIO_MODE_ANALOG_PASS_THRU:
873 if (pad->lv_mv_type)
874 pad->function = PMIC_GPIO_FUNC_INDEX_ANALOG;
875 else
876 return -ENODEV;
877 break;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300878 default:
879 dev_err(state->dev, "unknown GPIO direction\n");
880 return -ENODEV;
881 }
882
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300883 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_DIG_VIN_CTL);
884 if (val < 0)
885 return val;
886
887 pad->power_source = val >> PMIC_GPIO_REG_VIN_SHIFT;
888 pad->power_source &= PMIC_GPIO_REG_VIN_MASK;
889
890 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_DIG_PULL_CTL);
891 if (val < 0)
892 return val;
893
894 pad->pullup = val >> PMIC_GPIO_REG_PULL_SHIFT;
895 pad->pullup &= PMIC_GPIO_REG_PULL_MASK;
896
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800897 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_DIG_IN_CTL);
898 if (val < 0)
899 return val;
900
901 if (pad->lv_mv_type && (val & PMIC_GPIO_LV_MV_DIG_IN_DTEST_EN))
902 pad->dtest_buffer = val & PMIC_GPIO_LV_MV_DIG_IN_DTEST_SEL_MASK;
903 else if (!pad->lv_mv_type)
904 pad->dtest_buffer = val & PMIC_GPIO_DIG_IN_DTEST_SEL_MASK;
905 else
906 pad->dtest_buffer = INT_MAX;
907
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300908 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_DIG_OUT_CTL);
909 if (val < 0)
910 return val;
911
912 pad->strength = val >> PMIC_GPIO_REG_OUT_STRENGTH_SHIFT;
913 pad->strength &= PMIC_GPIO_REG_OUT_STRENGTH_MASK;
914
915 pad->buffer_type = val >> PMIC_GPIO_REG_OUT_TYPE_SHIFT;
916 pad->buffer_type &= PMIC_GPIO_REG_OUT_TYPE_MASK;
917
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800918 if (pad->function == PMIC_GPIO_FUNC_INDEX_ANALOG) {
919 val = pmic_gpio_read(state, pad,
920 PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL);
921 if (val < 0)
922 return val;
923 pad->atest = val & PMIC_GPIO_LV_MV_ANA_MUX_SEL_MASK;
924 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300925 /* Pin could be disabled with PIN_CONFIG_BIAS_HIGH_IMPEDANCE */
926 pad->is_enabled = true;
927 return 0;
928}
929
930static int pmic_gpio_probe(struct platform_device *pdev)
931{
932 struct device *dev = &pdev->dev;
933 struct pinctrl_pin_desc *pindesc;
934 struct pinctrl_desc *pctrldesc;
935 struct pmic_gpio_pad *pad, *pads;
936 struct pmic_gpio_state *state;
937 int ret, npins, i;
Stephen Boydab4256c2015-11-18 11:33:17 -0800938 u32 reg;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300939
Stephen Boydab4256c2015-11-18 11:33:17 -0800940 ret = of_property_read_u32(dev->of_node, "reg", &reg);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300941 if (ret < 0) {
Stephen Boydab4256c2015-11-18 11:33:17 -0800942 dev_err(dev, "missing base address");
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300943 return ret;
944 }
945
Stephen Boyda5ea13f2016-01-06 17:37:41 -0800946 npins = platform_irq_count(pdev);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300947 if (!npins)
948 return -EINVAL;
Stephen Boyda5ea13f2016-01-06 17:37:41 -0800949 if (npins < 0)
950 return npins;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300951
952 BUG_ON(npins > ARRAY_SIZE(pmic_gpio_groups));
953
954 state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
955 if (!state)
956 return -ENOMEM;
957
958 platform_set_drvdata(pdev, state);
959
960 state->dev = &pdev->dev;
961 state->map = dev_get_regmap(dev->parent, NULL);
962
963 pindesc = devm_kcalloc(dev, npins, sizeof(*pindesc), GFP_KERNEL);
964 if (!pindesc)
965 return -ENOMEM;
966
967 pads = devm_kcalloc(dev, npins, sizeof(*pads), GFP_KERNEL);
968 if (!pads)
969 return -ENOMEM;
970
971 pctrldesc = devm_kzalloc(dev, sizeof(*pctrldesc), GFP_KERNEL);
972 if (!pctrldesc)
973 return -ENOMEM;
974
975 pctrldesc->pctlops = &pmic_gpio_pinctrl_ops;
976 pctrldesc->pmxops = &pmic_gpio_pinmux_ops;
977 pctrldesc->confops = &pmic_gpio_pinconf_ops;
978 pctrldesc->owner = THIS_MODULE;
979 pctrldesc->name = dev_name(dev);
980 pctrldesc->pins = pindesc;
981 pctrldesc->npins = npins;
Linus Walleijf684e4a2015-01-12 00:45:55 +0100982 pctrldesc->num_custom_params = ARRAY_SIZE(pmic_gpio_bindings);
983 pctrldesc->custom_params = pmic_gpio_bindings;
Arnd Bergmann4f062662015-01-28 17:08:44 +0100984#ifdef CONFIG_DEBUG_FS
Linus Walleijf684e4a2015-01-12 00:45:55 +0100985 pctrldesc->custom_conf_items = pmic_conf_items;
Arnd Bergmann4f062662015-01-28 17:08:44 +0100986#endif
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300987
988 for (i = 0; i < npins; i++, pindesc++) {
989 pad = &pads[i];
990 pindesc->drv_data = pad;
991 pindesc->number = i;
992 pindesc->name = pmic_gpio_groups[i];
993
994 pad->irq = platform_get_irq(pdev, i);
995 if (pad->irq < 0)
996 return pad->irq;
997
Stephen Boydab4256c2015-11-18 11:33:17 -0800998 pad->base = reg + i * PMIC_GPIO_ADDRESS_RANGE;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300999
1000 ret = pmic_gpio_populate(state, pad);
1001 if (ret < 0)
1002 return ret;
1003 }
1004
1005 state->chip = pmic_gpio_gpio_template;
Linus Walleij58383c72015-11-04 09:56:26 +01001006 state->chip.parent = dev;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001007 state->chip.base = -1;
1008 state->chip.ngpio = npins;
1009 state->chip.label = dev_name(dev);
1010 state->chip.of_gpio_n_cells = 2;
1011 state->chip.can_sleep = false;
1012
Laxman Dewanganb46ddfe2016-02-24 14:44:07 +05301013 state->ctrl = devm_pinctrl_register(dev, pctrldesc, state);
Masahiro Yamada323de9e2015-06-09 13:01:16 +09001014 if (IS_ERR(state->ctrl))
1015 return PTR_ERR(state->ctrl);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001016
Linus Walleijc52d9df2015-12-08 09:51:47 +01001017 ret = gpiochip_add_data(&state->chip, state);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001018 if (ret) {
1019 dev_err(state->dev, "can't add gpio chip\n");
Laxman Dewanganb46ddfe2016-02-24 14:44:07 +05301020 return ret;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001021 }
1022
1023 ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins);
1024 if (ret) {
1025 dev_err(dev, "failed to add pin range\n");
1026 goto err_range;
1027 }
1028
1029 return 0;
1030
1031err_range:
1032 gpiochip_remove(&state->chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001033 return ret;
1034}
1035
1036static int pmic_gpio_remove(struct platform_device *pdev)
1037{
1038 struct pmic_gpio_state *state = platform_get_drvdata(pdev);
1039
1040 gpiochip_remove(&state->chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001041 return 0;
1042}
1043
1044static const struct of_device_id pmic_gpio_of_match[] = {
Ivan T. Ivanov7414b092015-03-31 12:37:18 +03001045 { .compatible = "qcom,pm8916-gpio" }, /* 4 GPIO's */
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001046 { .compatible = "qcom,pm8941-gpio" }, /* 36 GPIO's */
Stephen Boyd016c2f42015-11-17 16:52:32 -08001047 { .compatible = "qcom,pm8994-gpio" }, /* 22 GPIO's */
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001048 { .compatible = "qcom,pma8084-gpio" }, /* 22 GPIO's */
Stephen Boyd94fa6672016-07-11 12:01:09 -07001049 { .compatible = "qcom,spmi-gpio" }, /* Generic */
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001050 { },
1051};
1052
1053MODULE_DEVICE_TABLE(of, pmic_gpio_of_match);
1054
1055static struct platform_driver pmic_gpio_driver = {
1056 .driver = {
1057 .name = "qcom-spmi-gpio",
1058 .of_match_table = pmic_gpio_of_match,
1059 },
1060 .probe = pmic_gpio_probe,
1061 .remove = pmic_gpio_remove,
1062};
1063
1064module_platform_driver(pmic_gpio_driver);
1065
1066MODULE_AUTHOR("Ivan T. Ivanov <iivanov@mm-sol.com>");
1067MODULE_DESCRIPTION("Qualcomm SPMI PMIC GPIO pin control driver");
1068MODULE_ALIAS("platform:qcom-spmi-gpio");
1069MODULE_LICENSE("GPL v2");