blob: 2ecbd22edbfa05e4958b7ced1c1ceb304a0c2bf2 [file] [log] [blame]
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001/*
Fenglin Wueeb73e82017-09-01 15:11:51 +08002 * Copyright (c) 2012-2014, 2016-2017 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.
Fenglin Wucf7a1932017-03-24 16:55:11 +0800141 * @gpio_idx: The index in GPIO's hardware number space (1-based)
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300142 * @is_enabled: Set to false when GPIO should be put in high Z state.
143 * @out_value: Cached pin output value
144 * @have_buffer: Set to true if GPIO output could be configured in push-pull,
145 * open-drain or open-source mode.
146 * @output_enabled: Set to true if GPIO output logic is enabled.
147 * @input_enabled: Set to true if GPIO input buffer logic is enabled.
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800148 * @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 +0300149 * @num_sources: Number of power-sources supported by this GPIO.
150 * @power_source: Current power-source used.
151 * @buffer_type: Push-pull, open-drain or open-source.
152 * @pullup: Constant current which flow trough GPIO output buffer.
153 * @strength: No, Low, Medium, High
154 * @function: See pmic_gpio_functions[]
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800155 * @atest: the ATEST selection for GPIO analog-pass-through mode
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800156 * @dtest_buffer: the DTEST buffer selection for digital input mode,
157 * the default value is INT_MAX if not used.
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300158 */
159struct pmic_gpio_pad {
160 u16 base;
161 int irq;
Fenglin Wucf7a1932017-03-24 16:55:11 +0800162 int gpio_idx;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300163 bool is_enabled;
164 bool out_value;
165 bool have_buffer;
166 bool output_enabled;
167 bool input_enabled;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800168 bool lv_mv_type;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300169 unsigned int num_sources;
170 unsigned int power_source;
171 unsigned int buffer_type;
172 unsigned int pullup;
173 unsigned int strength;
174 unsigned int function;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800175 unsigned int atest;
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800176 unsigned int dtest_buffer;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300177};
178
179struct pmic_gpio_state {
180 struct device *dev;
181 struct regmap *map;
182 struct pinctrl_dev *ctrl;
183 struct gpio_chip chip;
Fenglin Wucf7a1932017-03-24 16:55:11 +0800184 const char **gpio_groups;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300185};
186
Linus Walleijf684e4a2015-01-12 00:45:55 +0100187static const struct pinconf_generic_params pmic_gpio_bindings[] = {
Soren Brinkmann7382b622015-01-09 07:43:51 -0800188 {"qcom,pull-up-strength", PMIC_GPIO_CONF_PULL_UP, 0},
189 {"qcom,drive-strength", PMIC_GPIO_CONF_STRENGTH, 0},
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800190 {"qcom,atest", PMIC_GPIO_CONF_ATEST, 0},
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800191 {"qcom,dtest-buffer", PMIC_GPIO_CONF_DTEST_BUFFER, 0},
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300192};
193
Arnd Bergmann4f062662015-01-28 17:08:44 +0100194#ifdef CONFIG_DEBUG_FS
Soren Brinkmann7382b622015-01-09 07:43:51 -0800195static const struct pin_config_item pmic_conf_items[ARRAY_SIZE(pmic_gpio_bindings)] = {
196 PCONFDUMP(PMIC_GPIO_CONF_PULL_UP, "pull up strength", NULL, true),
197 PCONFDUMP(PMIC_GPIO_CONF_STRENGTH, "drive-strength", NULL, true),
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800198 PCONFDUMP(PMIC_GPIO_CONF_ATEST, "atest", NULL, true),
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300199};
Arnd Bergmann4f062662015-01-28 17:08:44 +0100200#endif
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300201
202static const char *const pmic_gpio_groups[] = {
203 "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", "gpio8",
204 "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", "gpio15",
205 "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", "gpio22",
206 "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29",
207 "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", "gpio36",
208};
209
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800210/*
211 * Treat LV/MV GPIO analog-pass-through mode as a function, add it
212 * to the end of the function list. Add placeholder for the reserved
213 * functions defined in LV/MV OUTPUT_SOURCE_SEL register.
214 */
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300215static const char *const pmic_gpio_functions[] = {
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800216 [PMIC_GPIO_FUNC_INDEX_NORMAL] = PMIC_GPIO_FUNC_NORMAL,
217 [PMIC_GPIO_FUNC_INDEX_PAIRED] = PMIC_GPIO_FUNC_PAIRED,
218 [PMIC_GPIO_FUNC_INDEX_FUNC1] = PMIC_GPIO_FUNC_FUNC1,
219 [PMIC_GPIO_FUNC_INDEX_FUNC2] = PMIC_GPIO_FUNC_FUNC2,
220 [PMIC_GPIO_FUNC_INDEX_FUNC3] = PMIC_GPIO_FUNC_FUNC3,
221 [PMIC_GPIO_FUNC_INDEX_FUNC4] = PMIC_GPIO_FUNC_FUNC4,
222 [PMIC_GPIO_FUNC_INDEX_DTEST1] = PMIC_GPIO_FUNC_DTEST1,
223 [PMIC_GPIO_FUNC_INDEX_DTEST2] = PMIC_GPIO_FUNC_DTEST2,
224 [PMIC_GPIO_FUNC_INDEX_DTEST3] = PMIC_GPIO_FUNC_DTEST3,
225 [PMIC_GPIO_FUNC_INDEX_DTEST4] = PMIC_GPIO_FUNC_DTEST4,
226 "reserved-a", "reserved-b", "reserved-c",
227 "reserved-d", "reserved-e", "reserved-f",
228 [PMIC_GPIO_FUNC_INDEX_ANALOG] = PMIC_GPIO_FUNC_ANALOG,
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300229};
230
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300231static int pmic_gpio_read(struct pmic_gpio_state *state,
232 struct pmic_gpio_pad *pad, unsigned int addr)
233{
234 unsigned int val;
235 int ret;
236
237 ret = regmap_read(state->map, pad->base + addr, &val);
238 if (ret < 0)
239 dev_err(state->dev, "read 0x%x failed\n", addr);
240 else
241 ret = val;
242
243 return ret;
244}
245
246static int pmic_gpio_write(struct pmic_gpio_state *state,
247 struct pmic_gpio_pad *pad, unsigned int addr,
248 unsigned int val)
249{
250 int ret;
251
252 ret = regmap_write(state->map, pad->base + addr, val);
253 if (ret < 0)
254 dev_err(state->dev, "write 0x%x failed\n", addr);
255
256 return ret;
257}
258
259static int pmic_gpio_get_groups_count(struct pinctrl_dev *pctldev)
260{
261 /* Every PIN is a group */
262 return pctldev->desc->npins;
263}
264
265static const char *pmic_gpio_get_group_name(struct pinctrl_dev *pctldev,
266 unsigned pin)
267{
268 return pctldev->desc->pins[pin].name;
269}
270
271static int pmic_gpio_get_group_pins(struct pinctrl_dev *pctldev, unsigned pin,
272 const unsigned **pins, unsigned *num_pins)
273{
274 *pins = &pctldev->desc->pins[pin].number;
275 *num_pins = 1;
276 return 0;
277}
278
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300279static const struct pinctrl_ops pmic_gpio_pinctrl_ops = {
280 .get_groups_count = pmic_gpio_get_groups_count,
281 .get_group_name = pmic_gpio_get_group_name,
282 .get_group_pins = pmic_gpio_get_group_pins,
Soren Brinkmann7382b622015-01-09 07:43:51 -0800283 .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
Irina Tirdead32f7fd2016-03-31 14:44:42 +0300284 .dt_free_map = pinctrl_utils_free_map,
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300285};
286
287static int pmic_gpio_get_functions_count(struct pinctrl_dev *pctldev)
288{
289 return ARRAY_SIZE(pmic_gpio_functions);
290}
291
292static const char *pmic_gpio_get_function_name(struct pinctrl_dev *pctldev,
293 unsigned function)
294{
295 return pmic_gpio_functions[function];
296}
297
298static int pmic_gpio_get_function_groups(struct pinctrl_dev *pctldev,
299 unsigned function,
300 const char *const **groups,
301 unsigned *const num_qgroups)
302{
Fenglin Wucf7a1932017-03-24 16:55:11 +0800303 struct pmic_gpio_state *state = pinctrl_dev_get_drvdata(pctldev);
304
305 *groups = state->gpio_groups;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300306 *num_qgroups = pctldev->desc->npins;
307 return 0;
308}
309
310static int pmic_gpio_set_mux(struct pinctrl_dev *pctldev, unsigned function,
311 unsigned pin)
312{
313 struct pmic_gpio_state *state = pinctrl_dev_get_drvdata(pctldev);
314 struct pmic_gpio_pad *pad;
315 unsigned int val;
316 int ret;
317
318 pad = pctldev->desc->pins[pin].drv_data;
319
320 pad->function = function;
321
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800322 val = PMIC_GPIO_MODE_DIGITAL_INPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300323 if (pad->output_enabled) {
324 if (pad->input_enabled)
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800325 val = PMIC_GPIO_MODE_DIGITAL_INPUT_OUTPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300326 else
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800327 val = PMIC_GPIO_MODE_DIGITAL_OUTPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300328 }
329
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800330 if (function > PMIC_GPIO_FUNC_INDEX_DTEST4 &&
331 function < PMIC_GPIO_FUNC_INDEX_ANALOG) {
332 pr_err("reserved function: %s hasn't been enabled\n",
333 pmic_gpio_functions[function]);
334 return -EINVAL;
335 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300336
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800337 if (pad->lv_mv_type) {
338 if (pad->function == PMIC_GPIO_FUNC_INDEX_ANALOG) {
339 val = PMIC_GPIO_MODE_ANALOG_PASS_THRU;
340 ret = pmic_gpio_write(state, pad,
341 PMIC_GPIO_REG_MODE_CTL, val);
342 if (ret < 0)
343 return ret;
344
345 ret = pmic_gpio_write(state, pad,
346 PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL,
347 pad->atest);
348 if (ret < 0)
349 return ret;
350 } else {
351 ret = pmic_gpio_write(state, pad,
352 PMIC_GPIO_REG_MODE_CTL, val);
353 if (ret < 0)
354 return ret;
355
356 val = pad->out_value
357 << PMIC_GPIO_LV_MV_OUTPUT_INVERT_SHIFT;
358 val |= pad->function
359 & PMIC_GPIO_LV_MV_OUTPUT_SOURCE_SEL_MASK;
360 ret = pmic_gpio_write(state, pad,
361 PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL, val);
362 if (ret < 0)
363 return ret;
364 }
365 } else {
366 /*
367 * GPIO not of LV/MV subtype doesn't have "func3", "func4"
368 * "analog" functions, and "dtest1" to "dtest4" functions
369 * have register value 2 bits lower than the function index
370 * in pmic_gpio_functions[].
371 */
372 if (function == PMIC_GPIO_FUNC_INDEX_FUNC3
373 || function == PMIC_GPIO_FUNC_INDEX_FUNC4
374 || function == PMIC_GPIO_FUNC_INDEX_ANALOG) {
375 return -EINVAL;
376 } else if (function >= PMIC_GPIO_FUNC_INDEX_DTEST1 &&
377 function <= PMIC_GPIO_FUNC_INDEX_DTEST4) {
378 pad->function -= (PMIC_GPIO_FUNC_INDEX_DTEST1 -
379 PMIC_GPIO_FUNC_INDEX_FUNC3);
380 }
381
382 val = val << PMIC_GPIO_REG_MODE_DIR_SHIFT;
383 val |= pad->function << PMIC_GPIO_REG_MODE_FUNCTION_SHIFT;
384 val |= pad->out_value & PMIC_GPIO_REG_MODE_VALUE_SHIFT;
385
386 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_MODE_CTL, val);
387 if (ret < 0)
388 return ret;
389 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300390
391 val = pad->is_enabled << PMIC_GPIO_REG_MASTER_EN_SHIFT;
392
393 return pmic_gpio_write(state, pad, PMIC_GPIO_REG_EN_CTL, val);
394}
395
396static const struct pinmux_ops pmic_gpio_pinmux_ops = {
397 .get_functions_count = pmic_gpio_get_functions_count,
398 .get_function_name = pmic_gpio_get_function_name,
399 .get_function_groups = pmic_gpio_get_function_groups,
400 .set_mux = pmic_gpio_set_mux,
401};
402
403static int pmic_gpio_config_get(struct pinctrl_dev *pctldev,
404 unsigned int pin, unsigned long *config)
405{
406 unsigned param = pinconf_to_config_param(*config);
407 struct pmic_gpio_pad *pad;
408 unsigned arg;
409
410 pad = pctldev->desc->pins[pin].drv_data;
411
412 switch (param) {
413 case PIN_CONFIG_DRIVE_PUSH_PULL:
414 arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_CMOS;
415 break;
416 case PIN_CONFIG_DRIVE_OPEN_DRAIN:
417 arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS;
418 break;
419 case PIN_CONFIG_DRIVE_OPEN_SOURCE:
420 arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS;
421 break;
422 case PIN_CONFIG_BIAS_PULL_DOWN:
423 arg = pad->pullup == PMIC_GPIO_PULL_DOWN;
424 break;
425 case PIN_CONFIG_BIAS_DISABLE:
426 arg = pad->pullup = PMIC_GPIO_PULL_DISABLE;
427 break;
428 case PIN_CONFIG_BIAS_PULL_UP:
429 arg = pad->pullup == PMIC_GPIO_PULL_UP_30;
430 break;
431 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
432 arg = !pad->is_enabled;
433 break;
434 case PIN_CONFIG_POWER_SOURCE:
435 arg = pad->power_source;
436 break;
437 case PIN_CONFIG_INPUT_ENABLE:
438 arg = pad->input_enabled;
439 break;
440 case PIN_CONFIG_OUTPUT:
441 arg = pad->out_value;
442 break;
443 case PMIC_GPIO_CONF_PULL_UP:
444 arg = pad->pullup;
445 break;
446 case PMIC_GPIO_CONF_STRENGTH:
447 arg = pad->strength;
448 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800449 case PMIC_GPIO_CONF_ATEST:
450 arg = pad->atest;
451 break;
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800452 case PMIC_GPIO_CONF_DTEST_BUFFER:
453 arg = pad->dtest_buffer;
454 break;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300455 default:
456 return -EINVAL;
457 }
458
459 *config = pinconf_to_config_packed(param, arg);
460 return 0;
461}
462
463static int pmic_gpio_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
464 unsigned long *configs, unsigned nconfs)
465{
466 struct pmic_gpio_state *state = pinctrl_dev_get_drvdata(pctldev);
467 struct pmic_gpio_pad *pad;
468 unsigned param, arg;
469 unsigned int val;
470 int i, ret;
471
472 pad = pctldev->desc->pins[pin].drv_data;
473
Fenglin Wueeb73e82017-09-01 15:11:51 +0800474 pad->is_enabled = true;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300475 for (i = 0; i < nconfs; i++) {
476 param = pinconf_to_config_param(configs[i]);
477 arg = pinconf_to_config_argument(configs[i]);
478
479 switch (param) {
480 case PIN_CONFIG_DRIVE_PUSH_PULL:
481 pad->buffer_type = PMIC_GPIO_OUT_BUF_CMOS;
482 break;
483 case PIN_CONFIG_DRIVE_OPEN_DRAIN:
484 if (!pad->have_buffer)
485 return -EINVAL;
486 pad->buffer_type = PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS;
487 break;
488 case PIN_CONFIG_DRIVE_OPEN_SOURCE:
489 if (!pad->have_buffer)
490 return -EINVAL;
491 pad->buffer_type = PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS;
492 break;
493 case PIN_CONFIG_BIAS_DISABLE:
494 pad->pullup = PMIC_GPIO_PULL_DISABLE;
495 break;
496 case PIN_CONFIG_BIAS_PULL_UP:
497 pad->pullup = PMIC_GPIO_PULL_UP_30;
498 break;
499 case PIN_CONFIG_BIAS_PULL_DOWN:
500 if (arg)
501 pad->pullup = PMIC_GPIO_PULL_DOWN;
502 else
503 pad->pullup = PMIC_GPIO_PULL_DISABLE;
504 break;
505 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
506 pad->is_enabled = false;
507 break;
508 case PIN_CONFIG_POWER_SOURCE:
Fenglin Wu68c277b2016-08-18 11:41:03 +0800509 if (arg >= pad->num_sources)
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300510 return -EINVAL;
511 pad->power_source = arg;
512 break;
513 case PIN_CONFIG_INPUT_ENABLE:
514 pad->input_enabled = arg ? true : false;
515 break;
516 case PIN_CONFIG_OUTPUT:
517 pad->output_enabled = true;
518 pad->out_value = arg;
519 break;
520 case PMIC_GPIO_CONF_PULL_UP:
521 if (arg > PMIC_GPIO_PULL_UP_1P5_30)
522 return -EINVAL;
523 pad->pullup = arg;
524 break;
525 case PMIC_GPIO_CONF_STRENGTH:
526 if (arg > PMIC_GPIO_STRENGTH_LOW)
527 return -EINVAL;
528 pad->strength = arg;
529 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800530 case PMIC_GPIO_CONF_ATEST:
531 if (arg > PMIC_GPIO_AOUT_ATEST4)
532 return -EINVAL;
533 pad->atest = arg;
534 break;
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800535 case PMIC_GPIO_CONF_DTEST_BUFFER:
536 if ((pad->lv_mv_type && arg > PMIC_GPIO_DIN_DTEST4)
537 || (!pad->lv_mv_type && arg >
538 PMIC_GPIO_DIG_IN_DTEST_SEL_MASK))
539 return -EINVAL;
540 pad->dtest_buffer = arg;
541 break;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300542 default:
543 return -EINVAL;
544 }
545 }
546
547 val = pad->power_source << PMIC_GPIO_REG_VIN_SHIFT;
548
549 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_DIG_VIN_CTL, val);
550 if (ret < 0)
551 return ret;
552
553 val = pad->pullup << PMIC_GPIO_REG_PULL_SHIFT;
554
555 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_DIG_PULL_CTL, val);
556 if (ret < 0)
557 return ret;
558
559 val = pad->buffer_type << PMIC_GPIO_REG_OUT_TYPE_SHIFT;
Ivan T. Ivanov982df6a2015-04-09 18:18:35 +0300560 val |= pad->strength << PMIC_GPIO_REG_OUT_STRENGTH_SHIFT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300561
562 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_DIG_OUT_CTL, val);
563 if (ret < 0)
564 return ret;
565
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800566 val = PMIC_GPIO_MODE_DIGITAL_INPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300567 if (pad->output_enabled) {
568 if (pad->input_enabled)
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800569 val = PMIC_GPIO_MODE_DIGITAL_INPUT_OUTPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300570 else
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800571 val = PMIC_GPIO_MODE_DIGITAL_OUTPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300572 }
573
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800574 if (pad->dtest_buffer != INT_MAX) {
575 val = pad->dtest_buffer;
576 if (pad->lv_mv_type)
577 val |= PMIC_GPIO_LV_MV_DIG_IN_DTEST_EN;
578
579 ret = pmic_gpio_write(state, pad,
580 PMIC_GPIO_REG_DIG_IN_CTL, val);
581 if (ret < 0)
582 return ret;
583 }
584
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800585 if (pad->lv_mv_type) {
586 if (pad->function == PMIC_GPIO_FUNC_INDEX_ANALOG) {
587 val = PMIC_GPIO_MODE_ANALOG_PASS_THRU;
588 ret = pmic_gpio_write(state, pad,
589 PMIC_GPIO_REG_MODE_CTL, val);
590 if (ret < 0)
591 return ret;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300592
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800593 ret = pmic_gpio_write(state, pad,
594 PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL,
595 pad->atest);
596 if (ret < 0)
597 return ret;
598 } else {
599 ret = pmic_gpio_write(state, pad,
600 PMIC_GPIO_REG_MODE_CTL, val);
601 if (ret < 0)
602 return ret;
603
604 val = pad->out_value
605 << PMIC_GPIO_LV_MV_OUTPUT_INVERT_SHIFT;
606 val |= pad->function
607 & PMIC_GPIO_LV_MV_OUTPUT_SOURCE_SEL_MASK;
608 ret = pmic_gpio_write(state, pad,
609 PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL, val);
610 if (ret < 0)
611 return ret;
612 }
613 } else {
614 val = val << PMIC_GPIO_REG_MODE_DIR_SHIFT;
615 val |= pad->function << PMIC_GPIO_REG_MODE_FUNCTION_SHIFT;
616 val |= pad->out_value & PMIC_GPIO_REG_MODE_VALUE_SHIFT;
617
618 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_MODE_CTL, val);
619 if (ret < 0)
620 return ret;
621 }
622
Fenglin Wueeb73e82017-09-01 15:11:51 +0800623 val = pad->is_enabled << PMIC_GPIO_REG_MASTER_EN_SHIFT;
624
625 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_EN_CTL, val);
626
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800627 return ret;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300628}
629
630static void pmic_gpio_config_dbg_show(struct pinctrl_dev *pctldev,
631 struct seq_file *s, unsigned pin)
632{
633 struct pmic_gpio_state *state = pinctrl_dev_get_drvdata(pctldev);
634 struct pmic_gpio_pad *pad;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800635 int ret, val, function;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300636
637 static const char *const biases[] = {
638 "pull-up 30uA", "pull-up 1.5uA", "pull-up 31.5uA",
639 "pull-up 1.5uA + 30uA boost", "pull-down 10uA", "no pull"
640 };
641 static const char *const buffer_types[] = {
642 "push-pull", "open-drain", "open-source"
643 };
644 static const char *const strengths[] = {
645 "no", "high", "medium", "low"
646 };
647
648 pad = pctldev->desc->pins[pin].drv_data;
649
Fenglin Wucf7a1932017-03-24 16:55:11 +0800650 seq_printf(s, " gpio%-2d:", pad->gpio_idx);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300651
652 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_EN_CTL);
653
654 if (val < 0 || !(val >> PMIC_GPIO_REG_MASTER_EN_SHIFT)) {
655 seq_puts(s, " ---");
656 } else {
657
Ivan T. Ivanov24a66612015-04-09 18:18:36 +0300658 if (pad->input_enabled) {
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300659 ret = pmic_gpio_read(state, pad, PMIC_MPP_REG_RT_STS);
Ivan T. Ivanov24a66612015-04-09 18:18:36 +0300660 if (ret < 0)
661 return;
662
663 ret &= PMIC_MPP_REG_RT_STS_VAL_MASK;
664 pad->out_value = ret;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300665 }
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800666 /*
667 * For GPIO not of LV/MV subtypes, the register value of
668 * the function mapping from "dtest1" to "dtest4" is 2 bits
669 * lower than the function index in pmic_gpio_functions[].
670 */
671 if (!pad->lv_mv_type &&
672 pad->function >= PMIC_GPIO_FUNC_INDEX_FUNC3) {
673 function = pad->function + (PMIC_GPIO_FUNC_INDEX_DTEST1
674 - PMIC_GPIO_FUNC_INDEX_FUNC3);
675 } else {
676 function = pad->function;
677 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300678
679 seq_printf(s, " %-4s", pad->output_enabled ? "out" : "in");
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800680 seq_printf(s, " %-7s", pmic_gpio_functions[function]);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300681 seq_printf(s, " vin-%d", pad->power_source);
682 seq_printf(s, " %-27s", biases[pad->pullup]);
683 seq_printf(s, " %-10s", buffer_types[pad->buffer_type]);
684 seq_printf(s, " %-4s", pad->out_value ? "high" : "low");
685 seq_printf(s, " %-7s", strengths[pad->strength]);
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800686 if (pad->dtest_buffer != INT_MAX)
687 seq_printf(s, " dtest buffer %d", pad->dtest_buffer);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300688 }
689}
690
691static const struct pinconf_ops pmic_gpio_pinconf_ops = {
Soren Brinkmann7382b622015-01-09 07:43:51 -0800692 .is_generic = true,
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300693 .pin_config_group_get = pmic_gpio_config_get,
694 .pin_config_group_set = pmic_gpio_config_set,
695 .pin_config_group_dbg_show = pmic_gpio_config_dbg_show,
696};
697
698static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
699{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100700 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300701 unsigned long config;
702
703 config = pinconf_to_config_packed(PIN_CONFIG_INPUT_ENABLE, 1);
704
705 return pmic_gpio_config_set(state->ctrl, pin, &config, 1);
706}
707
708static int pmic_gpio_direction_output(struct gpio_chip *chip,
709 unsigned pin, int val)
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 unsigned long config;
713
714 config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, val);
715
716 return pmic_gpio_config_set(state->ctrl, pin, &config, 1);
717}
718
719static int pmic_gpio_get(struct gpio_chip *chip, unsigned pin)
720{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100721 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300722 struct pmic_gpio_pad *pad;
723 int ret;
724
725 pad = state->ctrl->desc->pins[pin].drv_data;
726
727 if (!pad->is_enabled)
728 return -EINVAL;
729
730 if (pad->input_enabled) {
731 ret = pmic_gpio_read(state, pad, PMIC_MPP_REG_RT_STS);
732 if (ret < 0)
733 return ret;
734
735 pad->out_value = ret & PMIC_MPP_REG_RT_STS_VAL_MASK;
736 }
737
Linus Walleij86c1a212015-12-21 16:29:50 +0100738 return !!pad->out_value;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300739}
740
741static void pmic_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
742{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100743 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300744 unsigned long config;
745
746 config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, value);
747
748 pmic_gpio_config_set(state->ctrl, pin, &config, 1);
749}
750
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300751static int pmic_gpio_of_xlate(struct gpio_chip *chip,
752 const struct of_phandle_args *gpio_desc,
753 u32 *flags)
754{
Fenglin Wucf7a1932017-03-24 16:55:11 +0800755 int i;
756 struct pmic_gpio_state *state = gpiochip_get_data(chip);
757 struct pinctrl_desc *desc = state->ctrl->desc;
758 struct pmic_gpio_pad *pad;
759
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300760 if (chip->of_gpio_n_cells < 2)
761 return -EINVAL;
762
763 if (flags)
764 *flags = gpio_desc->args[1];
765
Fenglin Wucf7a1932017-03-24 16:55:11 +0800766 for (i = 0; i < chip->ngpio; i++) {
767 pad = desc->pins[i].drv_data;
768 if (pad->gpio_idx == gpio_desc->args[0]) {
769 dev_dbg(state->dev, "gpio%-2d xlate to pin%-2d\n",
770 gpio_desc->args[0], i);
771 return i;
772 }
773 }
774
775 dev_err(state->dev, "Couldn't find pin for gpio %d\n",
776 gpio_desc->args[0]);
777 return -ENODEV;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300778}
779
780static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
781{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100782 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300783 struct pmic_gpio_pad *pad;
784
785 pad = state->ctrl->desc->pins[pin].drv_data;
786
787 return pad->irq;
788}
789
790static void pmic_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
791{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100792 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300793 unsigned i;
794
795 for (i = 0; i < chip->ngpio; i++) {
796 pmic_gpio_config_dbg_show(state->ctrl, s, i);
797 seq_puts(s, "\n");
798 }
799}
800
801static const struct gpio_chip pmic_gpio_gpio_template = {
802 .direction_input = pmic_gpio_direction_input,
803 .direction_output = pmic_gpio_direction_output,
804 .get = pmic_gpio_get,
805 .set = pmic_gpio_set,
Jonas Gorski98c85d52015-10-11 17:34:19 +0200806 .request = gpiochip_generic_request,
807 .free = gpiochip_generic_free,
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300808 .of_xlate = pmic_gpio_of_xlate,
809 .to_irq = pmic_gpio_to_irq,
810 .dbg_show = pmic_gpio_dbg_show,
811};
812
813static int pmic_gpio_populate(struct pmic_gpio_state *state,
814 struct pmic_gpio_pad *pad)
815{
816 int type, subtype, val, dir;
817
818 type = pmic_gpio_read(state, pad, PMIC_GPIO_REG_TYPE);
819 if (type < 0)
820 return type;
821
822 if (type != PMIC_GPIO_TYPE) {
823 dev_err(state->dev, "incorrect block type 0x%x at 0x%x\n",
824 type, pad->base);
825 return -ENODEV;
826 }
827
828 subtype = pmic_gpio_read(state, pad, PMIC_GPIO_REG_SUBTYPE);
829 if (subtype < 0)
830 return subtype;
831
832 switch (subtype) {
833 case PMIC_GPIO_SUBTYPE_GPIO_4CH:
834 pad->have_buffer = true;
835 case PMIC_GPIO_SUBTYPE_GPIOC_4CH:
836 pad->num_sources = 4;
837 break;
838 case PMIC_GPIO_SUBTYPE_GPIO_8CH:
839 pad->have_buffer = true;
840 case PMIC_GPIO_SUBTYPE_GPIOC_8CH:
841 pad->num_sources = 8;
842 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800843 case PMIC_GPIO_SUBTYPE_GPIO_LV:
844 pad->num_sources = 1;
845 pad->have_buffer = true;
846 pad->lv_mv_type = true;
847 break;
848 case PMIC_GPIO_SUBTYPE_GPIO_MV:
849 pad->num_sources = 2;
850 pad->have_buffer = true;
851 pad->lv_mv_type = true;
852 break;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300853 default:
854 dev_err(state->dev, "unknown GPIO type 0x%x\n", subtype);
855 return -ENODEV;
856 }
857
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800858 if (pad->lv_mv_type) {
859 val = pmic_gpio_read(state, pad,
860 PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL);
861 if (val < 0)
862 return val;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300863
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800864 pad->out_value = !!(val & PMIC_GPIO_LV_MV_OUTPUT_INVERT);
865 pad->function = val & PMIC_GPIO_LV_MV_OUTPUT_SOURCE_SEL_MASK;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300866
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800867 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_MODE_CTL);
868 if (val < 0)
869 return val;
870
871 dir = val & PMIC_GPIO_REG_LV_MV_MODE_DIR_MASK;
872 } else {
873 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_MODE_CTL);
874 if (val < 0)
875 return val;
876
877 pad->out_value = val & PMIC_GPIO_REG_MODE_VALUE_SHIFT;
878
879 dir = val >> PMIC_GPIO_REG_MODE_DIR_SHIFT;
880 dir &= PMIC_GPIO_REG_MODE_DIR_MASK;
881 pad->function = val >> PMIC_GPIO_REG_MODE_FUNCTION_SHIFT;
882 pad->function &= PMIC_GPIO_REG_MODE_FUNCTION_MASK;
883 }
884
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300885 switch (dir) {
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800886 case PMIC_GPIO_MODE_DIGITAL_INPUT:
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300887 pad->input_enabled = true;
888 pad->output_enabled = false;
889 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800890 case PMIC_GPIO_MODE_DIGITAL_OUTPUT:
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300891 pad->input_enabled = false;
892 pad->output_enabled = true;
893 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800894 case PMIC_GPIO_MODE_DIGITAL_INPUT_OUTPUT:
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300895 pad->input_enabled = true;
896 pad->output_enabled = true;
897 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800898 case PMIC_GPIO_MODE_ANALOG_PASS_THRU:
899 if (pad->lv_mv_type)
900 pad->function = PMIC_GPIO_FUNC_INDEX_ANALOG;
901 else
902 return -ENODEV;
903 break;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300904 default:
905 dev_err(state->dev, "unknown GPIO direction\n");
906 return -ENODEV;
907 }
908
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300909 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_DIG_VIN_CTL);
910 if (val < 0)
911 return val;
912
913 pad->power_source = val >> PMIC_GPIO_REG_VIN_SHIFT;
914 pad->power_source &= PMIC_GPIO_REG_VIN_MASK;
915
916 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_DIG_PULL_CTL);
917 if (val < 0)
918 return val;
919
920 pad->pullup = val >> PMIC_GPIO_REG_PULL_SHIFT;
921 pad->pullup &= PMIC_GPIO_REG_PULL_MASK;
922
Fenglin Wuf6c0e702016-07-21 15:33:03 +0800923 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_DIG_IN_CTL);
924 if (val < 0)
925 return val;
926
927 if (pad->lv_mv_type && (val & PMIC_GPIO_LV_MV_DIG_IN_DTEST_EN))
928 pad->dtest_buffer = val & PMIC_GPIO_LV_MV_DIG_IN_DTEST_SEL_MASK;
929 else if (!pad->lv_mv_type)
930 pad->dtest_buffer = val & PMIC_GPIO_DIG_IN_DTEST_SEL_MASK;
931 else
932 pad->dtest_buffer = INT_MAX;
933
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300934 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_DIG_OUT_CTL);
935 if (val < 0)
936 return val;
937
938 pad->strength = val >> PMIC_GPIO_REG_OUT_STRENGTH_SHIFT;
939 pad->strength &= PMIC_GPIO_REG_OUT_STRENGTH_MASK;
940
941 pad->buffer_type = val >> PMIC_GPIO_REG_OUT_TYPE_SHIFT;
942 pad->buffer_type &= PMIC_GPIO_REG_OUT_TYPE_MASK;
943
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800944 if (pad->function == PMIC_GPIO_FUNC_INDEX_ANALOG) {
945 val = pmic_gpio_read(state, pad,
946 PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL);
947 if (val < 0)
948 return val;
949 pad->atest = val & PMIC_GPIO_LV_MV_ANA_MUX_SEL_MASK;
950 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300951 /* Pin could be disabled with PIN_CONFIG_BIAS_HIGH_IMPEDANCE */
952 pad->is_enabled = true;
953 return 0;
954}
955
956static int pmic_gpio_probe(struct platform_device *pdev)
957{
958 struct device *dev = &pdev->dev;
959 struct pinctrl_pin_desc *pindesc;
960 struct pinctrl_desc *pctrldesc;
961 struct pmic_gpio_pad *pad, *pads;
962 struct pmic_gpio_state *state;
Fenglin Wucf7a1932017-03-24 16:55:11 +0800963 int ret, npins, ngpios, i, j, pin_idx;
964 int disallowed_count = 0;
965 u32 reg[2], start, size;
966 u32 *disallowed = NULL;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300967
Fenglin Wucf7a1932017-03-24 16:55:11 +0800968 ret = of_property_read_u32_array(dev->of_node, "reg", reg, 2);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300969 if (ret < 0) {
Fenglin Wucf7a1932017-03-24 16:55:11 +0800970 dev_err(dev, "reg property reading failed\n");
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300971 return ret;
972 }
Fenglin Wucf7a1932017-03-24 16:55:11 +0800973 start = reg[0];
974 size = reg[1];
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300975
Fenglin Wucf7a1932017-03-24 16:55:11 +0800976 ngpios = size / PMIC_GPIO_ADDRESS_RANGE;
977 if (ngpios == 0) {
978 dev_err(dev, "no gpios assigned\n");
979 return -ENODEV;
980 }
981
982 if (ngpios > ARRAY_SIZE(pmic_gpio_groups)) {
983 dev_err(dev, "reg property defines %d gpios, but only %d are allowed\n",
984 ngpios, (int)ARRAY_SIZE(pmic_gpio_groups));
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300985 return -EINVAL;
Fenglin Wucf7a1932017-03-24 16:55:11 +0800986 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300987
Fenglin Wucf7a1932017-03-24 16:55:11 +0800988 if (of_find_property(dev->of_node, "qcom,gpios-disallowed",
989 &disallowed_count)) {
990 disallowed_count /= sizeof(u32);
991 if (disallowed_count == 0) {
992 dev_err(dev, "No data in gpios-disallowed\n");
993 return -EINVAL;
994 }
995
996 disallowed = kcalloc(disallowed_count, sizeof(u32), GFP_KERNEL);
997 if (disallowed == NULL)
998 return -ENOMEM;
999
1000 ret = of_property_read_u32_array(dev->of_node,
1001 "qcom,gpios-disallowed",
1002 disallowed, disallowed_count);
1003 if (ret < 0) {
1004 dev_err(dev, "qcom,gpios-disallowed property reading failed, ret=%d\n",
1005 ret);
1006 goto err_free;
1007 }
1008
1009 for (i = 0; i < disallowed_count; i++) {
1010 if (disallowed[i] >= ngpios + PMIC_GPIO_PHYSICAL_OFFSET
1011 || disallowed[i] < PMIC_GPIO_PHYSICAL_OFFSET) {
1012 dev_err(dev, "invalid gpio = %d specified in qcom,gpios-disallowed, supported values: %d to %d\n",
1013 disallowed[i],
1014 PMIC_GPIO_PHYSICAL_OFFSET,
1015 ngpios - 1 + PMIC_GPIO_PHYSICAL_OFFSET);
1016 ret = -EINVAL;
1017 goto err_free;
1018 }
1019 for (j = 0; j < i; j++) {
1020 if (disallowed[i] == disallowed[j]) {
1021 dev_err(dev, "duplicate gpio = %d listed in qcom,gpios-disallowed\n",
1022 disallowed[i]);
1023 ret = -EINVAL;
1024 goto err_free;
1025 }
1026 }
1027 dev_dbg(dev, "gpio %d NOT supported\n", disallowed[i]);
1028 }
1029 } else {
1030 disallowed_count = 0;
1031 }
1032
1033 npins = ngpios - disallowed_count;
1034 if (npins <= 0) {
1035 dev_err(dev, "No pins assigned\n");
1036 ret = -ENODEV;
1037 goto err_free;
1038 }
1039 if (platform_irq_count(pdev) != npins) {
1040 dev_err(dev, "%d IRQs defined but %d expected\n",
1041 platform_irq_count(pdev), npins);
1042 ret = -EINVAL;
1043 goto err_free;
1044 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001045
1046 state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
Fenglin Wucf7a1932017-03-24 16:55:11 +08001047 if (!state) {
1048 ret = -ENOMEM;
1049 goto err_free;
1050 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001051
1052 platform_set_drvdata(pdev, state);
1053
1054 state->dev = &pdev->dev;
1055 state->map = dev_get_regmap(dev->parent, NULL);
1056
Fenglin Wucf7a1932017-03-24 16:55:11 +08001057 state->gpio_groups = devm_kcalloc(dev, sizeof(*state->gpio_groups),
1058 npins, GFP_KERNEL);
1059 if (!state->gpio_groups) {
1060 ret = -ENOMEM;
1061 goto err_free;
1062 }
1063
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001064 pindesc = devm_kcalloc(dev, npins, sizeof(*pindesc), GFP_KERNEL);
Fenglin Wucf7a1932017-03-24 16:55:11 +08001065 if (!pindesc) {
1066 ret = -ENOMEM;
1067 goto err_free;
1068 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001069
1070 pads = devm_kcalloc(dev, npins, sizeof(*pads), GFP_KERNEL);
Fenglin Wucf7a1932017-03-24 16:55:11 +08001071 if (!pads) {
1072 ret = -ENOMEM;
1073 goto err_free;
1074 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001075
1076 pctrldesc = devm_kzalloc(dev, sizeof(*pctrldesc), GFP_KERNEL);
Fenglin Wucf7a1932017-03-24 16:55:11 +08001077 if (!pctrldesc) {
1078 ret = -ENOMEM;
1079 goto err_free;
1080 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001081
1082 pctrldesc->pctlops = &pmic_gpio_pinctrl_ops;
1083 pctrldesc->pmxops = &pmic_gpio_pinmux_ops;
1084 pctrldesc->confops = &pmic_gpio_pinconf_ops;
1085 pctrldesc->owner = THIS_MODULE;
1086 pctrldesc->name = dev_name(dev);
1087 pctrldesc->pins = pindesc;
1088 pctrldesc->npins = npins;
Linus Walleijf684e4a2015-01-12 00:45:55 +01001089 pctrldesc->num_custom_params = ARRAY_SIZE(pmic_gpio_bindings);
1090 pctrldesc->custom_params = pmic_gpio_bindings;
Arnd Bergmann4f062662015-01-28 17:08:44 +01001091#ifdef CONFIG_DEBUG_FS
Linus Walleijf684e4a2015-01-12 00:45:55 +01001092 pctrldesc->custom_conf_items = pmic_conf_items;
Arnd Bergmann4f062662015-01-28 17:08:44 +01001093#endif
Fenglin Wucf7a1932017-03-24 16:55:11 +08001094 for (pin_idx = 0, i = 0; i < ngpios; i++) {
1095 for (j = 0; j < disallowed_count; j++) {
1096 if (i + PMIC_GPIO_PHYSICAL_OFFSET == disallowed[j])
1097 break;
1098 }
1099 if (j != disallowed_count)
1100 continue;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001101
Fenglin Wucf7a1932017-03-24 16:55:11 +08001102 pad = &pads[pin_idx];
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001103 pindesc->drv_data = pad;
Fenglin Wucf7a1932017-03-24 16:55:11 +08001104 pindesc->number = pin_idx;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001105 pindesc->name = pmic_gpio_groups[i];
1106
Fenglin Wucf7a1932017-03-24 16:55:11 +08001107 pad->gpio_idx = i + PMIC_GPIO_PHYSICAL_OFFSET;
1108 pad->irq = platform_get_irq(pdev, pin_idx);
1109 if (pad->irq < 0) {
1110 dev_err(state->dev,
1111 "failed to get irq for gpio %d (pin %d), ret=%d\n",
1112 pad->gpio_idx, pin_idx, pad->irq);
1113 ret = pad->irq;
1114 goto err_free;
1115 }
1116 /* Every pin is a group */
1117 state->gpio_groups[pin_idx] = pmic_gpio_groups[i];
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001118
Fenglin Wucf7a1932017-03-24 16:55:11 +08001119 pad->base = start + i * PMIC_GPIO_ADDRESS_RANGE;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001120
1121 ret = pmic_gpio_populate(state, pad);
Fenglin Wucf7a1932017-03-24 16:55:11 +08001122 if (ret < 0) {
1123 dev_err(state->dev,
1124 "failed to populate gpio %d, ret=%d\n",
1125 i, ret);
1126 goto err_free;
1127 }
1128 pindesc++;
1129 pin_idx++;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001130 }
1131
1132 state->chip = pmic_gpio_gpio_template;
Linus Walleij58383c72015-11-04 09:56:26 +01001133 state->chip.parent = dev;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001134 state->chip.base = -1;
1135 state->chip.ngpio = npins;
1136 state->chip.label = dev_name(dev);
1137 state->chip.of_gpio_n_cells = 2;
1138 state->chip.can_sleep = false;
1139
Laxman Dewanganb46ddfe2016-02-24 14:44:07 +05301140 state->ctrl = devm_pinctrl_register(dev, pctrldesc, state);
Fenglin Wucf7a1932017-03-24 16:55:11 +08001141 if (IS_ERR(state->ctrl)) {
1142 ret = PTR_ERR(state->ctrl);
1143 dev_err(state->dev, "failed to register pinctrl device, ret=%d\n",
1144 ret);
1145 goto err_free;
1146 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001147
Linus Walleijc52d9df2015-12-08 09:51:47 +01001148 ret = gpiochip_add_data(&state->chip, state);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001149 if (ret) {
Fenglin Wucf7a1932017-03-24 16:55:11 +08001150 dev_err(state->dev, "can't add gpio chip, ret=%d\n", ret);
1151 goto err_free;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001152 }
1153
1154 ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins);
1155 if (ret) {
Fenglin Wucf7a1932017-03-24 16:55:11 +08001156 dev_err(dev, "failed to add pin range\n, ret=%d\n", ret);
1157 gpiochip_remove(&state->chip);
1158 goto err_free;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001159 }
1160
Fenglin Wucf7a1932017-03-24 16:55:11 +08001161err_free:
1162 kfree(disallowed);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001163
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001164 return ret;
1165}
1166
1167static int pmic_gpio_remove(struct platform_device *pdev)
1168{
1169 struct pmic_gpio_state *state = platform_get_drvdata(pdev);
1170
1171 gpiochip_remove(&state->chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001172 return 0;
1173}
1174
1175static const struct of_device_id pmic_gpio_of_match[] = {
Ivan T. Ivanov7414b092015-03-31 12:37:18 +03001176 { .compatible = "qcom,pm8916-gpio" }, /* 4 GPIO's */
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001177 { .compatible = "qcom,pm8941-gpio" }, /* 36 GPIO's */
Stephen Boyd016c2f42015-11-17 16:52:32 -08001178 { .compatible = "qcom,pm8994-gpio" }, /* 22 GPIO's */
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001179 { .compatible = "qcom,pma8084-gpio" }, /* 22 GPIO's */
Stephen Boyd94fa6672016-07-11 12:01:09 -07001180 { .compatible = "qcom,spmi-gpio" }, /* Generic */
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001181 { },
1182};
1183
1184MODULE_DEVICE_TABLE(of, pmic_gpio_of_match);
1185
1186static struct platform_driver pmic_gpio_driver = {
1187 .driver = {
1188 .name = "qcom-spmi-gpio",
1189 .of_match_table = pmic_gpio_of_match,
1190 },
1191 .probe = pmic_gpio_probe,
1192 .remove = pmic_gpio_remove,
1193};
1194
1195module_platform_driver(pmic_gpio_driver);
1196
1197MODULE_AUTHOR("Ivan T. Ivanov <iivanov@mm-sol.com>");
1198MODULE_DESCRIPTION("Qualcomm SPMI PMIC GPIO pin control driver");
1199MODULE_ALIAS("platform:qcom-spmi-gpio");
1200MODULE_LICENSE("GPL v2");