blob: b268139a0ab42bdd477287bea105c472f55bce6c [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
Ivan T. Ivanoveadff302014-10-22 12:58:46 +030054#define PMIC_GPIO_REG_DIG_OUT_CTL 0x45
55#define PMIC_GPIO_REG_EN_CTL 0x46
Fenglin Wu60a05cb2016-07-21 14:32:24 +080056#define PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL 0x4A
Ivan T. Ivanoveadff302014-10-22 12:58:46 +030057
58/* PMIC_GPIO_REG_MODE_CTL */
59#define PMIC_GPIO_REG_MODE_VALUE_SHIFT 0x1
60#define PMIC_GPIO_REG_MODE_FUNCTION_SHIFT 1
61#define PMIC_GPIO_REG_MODE_FUNCTION_MASK 0x7
62#define PMIC_GPIO_REG_MODE_DIR_SHIFT 4
63#define PMIC_GPIO_REG_MODE_DIR_MASK 0x7
64
Fenglin Wu60a05cb2016-07-21 14:32:24 +080065#define PMIC_GPIO_MODE_DIGITAL_INPUT 0
66#define PMIC_GPIO_MODE_DIGITAL_OUTPUT 1
67#define PMIC_GPIO_MODE_DIGITAL_INPUT_OUTPUT 2
68#define PMIC_GPIO_MODE_ANALOG_PASS_THRU 3
69
70#define PMIC_GPIO_REG_LV_MV_MODE_DIR_MASK 0x3
71
Ivan T. Ivanoveadff302014-10-22 12:58:46 +030072/* PMIC_GPIO_REG_DIG_VIN_CTL */
73#define PMIC_GPIO_REG_VIN_SHIFT 0
74#define PMIC_GPIO_REG_VIN_MASK 0x7
75
76/* PMIC_GPIO_REG_DIG_PULL_CTL */
77#define PMIC_GPIO_REG_PULL_SHIFT 0
78#define PMIC_GPIO_REG_PULL_MASK 0x7
79
80#define PMIC_GPIO_PULL_DOWN 4
81#define PMIC_GPIO_PULL_DISABLE 5
82
Fenglin Wu60a05cb2016-07-21 14:32:24 +080083/* PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL for LV/MV */
84#define PMIC_GPIO_LV_MV_OUTPUT_INVERT 0x80
85#define PMIC_GPIO_LV_MV_OUTPUT_INVERT_SHIFT 7
86#define PMIC_GPIO_LV_MV_OUTPUT_SOURCE_SEL_MASK 0xF
87
Ivan T. Ivanoveadff302014-10-22 12:58:46 +030088/* PMIC_GPIO_REG_DIG_OUT_CTL */
89#define PMIC_GPIO_REG_OUT_STRENGTH_SHIFT 0
90#define PMIC_GPIO_REG_OUT_STRENGTH_MASK 0x3
91#define PMIC_GPIO_REG_OUT_TYPE_SHIFT 4
92#define PMIC_GPIO_REG_OUT_TYPE_MASK 0x3
93
94/*
95 * Output type - indicates pin should be configured as push-pull,
96 * open drain or open source.
97 */
98#define PMIC_GPIO_OUT_BUF_CMOS 0
99#define PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS 1
100#define PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS 2
101
102/* PMIC_GPIO_REG_EN_CTL */
103#define PMIC_GPIO_REG_MASTER_EN_SHIFT 7
104
105#define PMIC_GPIO_PHYSICAL_OFFSET 1
106
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800107/* PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL */
108#define PMIC_GPIO_LV_MV_ANA_MUX_SEL_MASK 0x3
109
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300110/* Qualcomm specific pin configurations */
111#define PMIC_GPIO_CONF_PULL_UP (PIN_CONFIG_END + 1)
112#define PMIC_GPIO_CONF_STRENGTH (PIN_CONFIG_END + 2)
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800113#define PMIC_GPIO_CONF_ATEST (PIN_CONFIG_END + 3)
114
115/* The index of each function in pmic_gpio_functions[] array */
116enum pmic_gpio_func_index {
117 PMIC_GPIO_FUNC_INDEX_NORMAL = 0x00,
118 PMIC_GPIO_FUNC_INDEX_PAIRED = 0x01,
119 PMIC_GPIO_FUNC_INDEX_FUNC1 = 0x02,
120 PMIC_GPIO_FUNC_INDEX_FUNC2 = 0x03,
121 PMIC_GPIO_FUNC_INDEX_FUNC3 = 0x04,
122 PMIC_GPIO_FUNC_INDEX_FUNC4 = 0x05,
123 PMIC_GPIO_FUNC_INDEX_DTEST1 = 0x06,
124 PMIC_GPIO_FUNC_INDEX_DTEST2 = 0x07,
125 PMIC_GPIO_FUNC_INDEX_DTEST3 = 0x08,
126 PMIC_GPIO_FUNC_INDEX_DTEST4 = 0x09,
127 PMIC_GPIO_FUNC_INDEX_ANALOG = 0x10,
128};
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300129
130/**
131 * struct pmic_gpio_pad - keep current GPIO settings
132 * @base: Address base in SPMI device.
133 * @irq: IRQ number which this GPIO generate.
134 * @is_enabled: Set to false when GPIO should be put in high Z state.
135 * @out_value: Cached pin output value
136 * @have_buffer: Set to true if GPIO output could be configured in push-pull,
137 * open-drain or open-source mode.
138 * @output_enabled: Set to true if GPIO output logic is enabled.
139 * @input_enabled: Set to true if GPIO input buffer logic is enabled.
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800140 * @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 +0300141 * @num_sources: Number of power-sources supported by this GPIO.
142 * @power_source: Current power-source used.
143 * @buffer_type: Push-pull, open-drain or open-source.
144 * @pullup: Constant current which flow trough GPIO output buffer.
145 * @strength: No, Low, Medium, High
146 * @function: See pmic_gpio_functions[]
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800147 * @atest: the ATEST selection for GPIO analog-pass-through mode
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300148 */
149struct pmic_gpio_pad {
150 u16 base;
151 int irq;
152 bool is_enabled;
153 bool out_value;
154 bool have_buffer;
155 bool output_enabled;
156 bool input_enabled;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800157 bool lv_mv_type;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300158 unsigned int num_sources;
159 unsigned int power_source;
160 unsigned int buffer_type;
161 unsigned int pullup;
162 unsigned int strength;
163 unsigned int function;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800164 unsigned int atest;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300165};
166
167struct pmic_gpio_state {
168 struct device *dev;
169 struct regmap *map;
170 struct pinctrl_dev *ctrl;
171 struct gpio_chip chip;
172};
173
Linus Walleijf684e4a2015-01-12 00:45:55 +0100174static const struct pinconf_generic_params pmic_gpio_bindings[] = {
Soren Brinkmann7382b622015-01-09 07:43:51 -0800175 {"qcom,pull-up-strength", PMIC_GPIO_CONF_PULL_UP, 0},
176 {"qcom,drive-strength", PMIC_GPIO_CONF_STRENGTH, 0},
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800177 {"qcom,atest", PMIC_GPIO_CONF_ATEST, 0},
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300178};
179
Arnd Bergmann4f062662015-01-28 17:08:44 +0100180#ifdef CONFIG_DEBUG_FS
Soren Brinkmann7382b622015-01-09 07:43:51 -0800181static const struct pin_config_item pmic_conf_items[ARRAY_SIZE(pmic_gpio_bindings)] = {
182 PCONFDUMP(PMIC_GPIO_CONF_PULL_UP, "pull up strength", NULL, true),
183 PCONFDUMP(PMIC_GPIO_CONF_STRENGTH, "drive-strength", NULL, true),
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800184 PCONFDUMP(PMIC_GPIO_CONF_ATEST, "atest", NULL, true),
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300185};
Arnd Bergmann4f062662015-01-28 17:08:44 +0100186#endif
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300187
188static const char *const pmic_gpio_groups[] = {
189 "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", "gpio8",
190 "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", "gpio15",
191 "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", "gpio22",
192 "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29",
193 "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", "gpio36",
194};
195
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800196/*
197 * Treat LV/MV GPIO analog-pass-through mode as a function, add it
198 * to the end of the function list. Add placeholder for the reserved
199 * functions defined in LV/MV OUTPUT_SOURCE_SEL register.
200 */
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300201static const char *const pmic_gpio_functions[] = {
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800202 [PMIC_GPIO_FUNC_INDEX_NORMAL] = PMIC_GPIO_FUNC_NORMAL,
203 [PMIC_GPIO_FUNC_INDEX_PAIRED] = PMIC_GPIO_FUNC_PAIRED,
204 [PMIC_GPIO_FUNC_INDEX_FUNC1] = PMIC_GPIO_FUNC_FUNC1,
205 [PMIC_GPIO_FUNC_INDEX_FUNC2] = PMIC_GPIO_FUNC_FUNC2,
206 [PMIC_GPIO_FUNC_INDEX_FUNC3] = PMIC_GPIO_FUNC_FUNC3,
207 [PMIC_GPIO_FUNC_INDEX_FUNC4] = PMIC_GPIO_FUNC_FUNC4,
208 [PMIC_GPIO_FUNC_INDEX_DTEST1] = PMIC_GPIO_FUNC_DTEST1,
209 [PMIC_GPIO_FUNC_INDEX_DTEST2] = PMIC_GPIO_FUNC_DTEST2,
210 [PMIC_GPIO_FUNC_INDEX_DTEST3] = PMIC_GPIO_FUNC_DTEST3,
211 [PMIC_GPIO_FUNC_INDEX_DTEST4] = PMIC_GPIO_FUNC_DTEST4,
212 "reserved-a", "reserved-b", "reserved-c",
213 "reserved-d", "reserved-e", "reserved-f",
214 [PMIC_GPIO_FUNC_INDEX_ANALOG] = PMIC_GPIO_FUNC_ANALOG,
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300215};
216
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300217static int pmic_gpio_read(struct pmic_gpio_state *state,
218 struct pmic_gpio_pad *pad, unsigned int addr)
219{
220 unsigned int val;
221 int ret;
222
223 ret = regmap_read(state->map, pad->base + addr, &val);
224 if (ret < 0)
225 dev_err(state->dev, "read 0x%x failed\n", addr);
226 else
227 ret = val;
228
229 return ret;
230}
231
232static int pmic_gpio_write(struct pmic_gpio_state *state,
233 struct pmic_gpio_pad *pad, unsigned int addr,
234 unsigned int val)
235{
236 int ret;
237
238 ret = regmap_write(state->map, pad->base + addr, val);
239 if (ret < 0)
240 dev_err(state->dev, "write 0x%x failed\n", addr);
241
242 return ret;
243}
244
245static int pmic_gpio_get_groups_count(struct pinctrl_dev *pctldev)
246{
247 /* Every PIN is a group */
248 return pctldev->desc->npins;
249}
250
251static const char *pmic_gpio_get_group_name(struct pinctrl_dev *pctldev,
252 unsigned pin)
253{
254 return pctldev->desc->pins[pin].name;
255}
256
257static int pmic_gpio_get_group_pins(struct pinctrl_dev *pctldev, unsigned pin,
258 const unsigned **pins, unsigned *num_pins)
259{
260 *pins = &pctldev->desc->pins[pin].number;
261 *num_pins = 1;
262 return 0;
263}
264
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300265static const struct pinctrl_ops pmic_gpio_pinctrl_ops = {
266 .get_groups_count = pmic_gpio_get_groups_count,
267 .get_group_name = pmic_gpio_get_group_name,
268 .get_group_pins = pmic_gpio_get_group_pins,
Soren Brinkmann7382b622015-01-09 07:43:51 -0800269 .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
Irina Tirdead32f7fd2016-03-31 14:44:42 +0300270 .dt_free_map = pinctrl_utils_free_map,
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300271};
272
273static int pmic_gpio_get_functions_count(struct pinctrl_dev *pctldev)
274{
275 return ARRAY_SIZE(pmic_gpio_functions);
276}
277
278static const char *pmic_gpio_get_function_name(struct pinctrl_dev *pctldev,
279 unsigned function)
280{
281 return pmic_gpio_functions[function];
282}
283
284static int pmic_gpio_get_function_groups(struct pinctrl_dev *pctldev,
285 unsigned function,
286 const char *const **groups,
287 unsigned *const num_qgroups)
288{
289 *groups = pmic_gpio_groups;
290 *num_qgroups = pctldev->desc->npins;
291 return 0;
292}
293
294static int pmic_gpio_set_mux(struct pinctrl_dev *pctldev, unsigned function,
295 unsigned pin)
296{
297 struct pmic_gpio_state *state = pinctrl_dev_get_drvdata(pctldev);
298 struct pmic_gpio_pad *pad;
299 unsigned int val;
300 int ret;
301
302 pad = pctldev->desc->pins[pin].drv_data;
303
304 pad->function = function;
305
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800306 val = PMIC_GPIO_MODE_DIGITAL_INPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300307 if (pad->output_enabled) {
308 if (pad->input_enabled)
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800309 val = PMIC_GPIO_MODE_DIGITAL_INPUT_OUTPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300310 else
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800311 val = PMIC_GPIO_MODE_DIGITAL_OUTPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300312 }
313
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800314 if (function > PMIC_GPIO_FUNC_INDEX_DTEST4 &&
315 function < PMIC_GPIO_FUNC_INDEX_ANALOG) {
316 pr_err("reserved function: %s hasn't been enabled\n",
317 pmic_gpio_functions[function]);
318 return -EINVAL;
319 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300320
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800321 if (pad->lv_mv_type) {
322 if (pad->function == PMIC_GPIO_FUNC_INDEX_ANALOG) {
323 val = PMIC_GPIO_MODE_ANALOG_PASS_THRU;
324 ret = pmic_gpio_write(state, pad,
325 PMIC_GPIO_REG_MODE_CTL, val);
326 if (ret < 0)
327 return ret;
328
329 ret = pmic_gpio_write(state, pad,
330 PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL,
331 pad->atest);
332 if (ret < 0)
333 return ret;
334 } else {
335 ret = pmic_gpio_write(state, pad,
336 PMIC_GPIO_REG_MODE_CTL, val);
337 if (ret < 0)
338 return ret;
339
340 val = pad->out_value
341 << PMIC_GPIO_LV_MV_OUTPUT_INVERT_SHIFT;
342 val |= pad->function
343 & PMIC_GPIO_LV_MV_OUTPUT_SOURCE_SEL_MASK;
344 ret = pmic_gpio_write(state, pad,
345 PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL, val);
346 if (ret < 0)
347 return ret;
348 }
349 } else {
350 /*
351 * GPIO not of LV/MV subtype doesn't have "func3", "func4"
352 * "analog" functions, and "dtest1" to "dtest4" functions
353 * have register value 2 bits lower than the function index
354 * in pmic_gpio_functions[].
355 */
356 if (function == PMIC_GPIO_FUNC_INDEX_FUNC3
357 || function == PMIC_GPIO_FUNC_INDEX_FUNC4
358 || function == PMIC_GPIO_FUNC_INDEX_ANALOG) {
359 return -EINVAL;
360 } else if (function >= PMIC_GPIO_FUNC_INDEX_DTEST1 &&
361 function <= PMIC_GPIO_FUNC_INDEX_DTEST4) {
362 pad->function -= (PMIC_GPIO_FUNC_INDEX_DTEST1 -
363 PMIC_GPIO_FUNC_INDEX_FUNC3);
364 }
365
366 val = val << PMIC_GPIO_REG_MODE_DIR_SHIFT;
367 val |= pad->function << PMIC_GPIO_REG_MODE_FUNCTION_SHIFT;
368 val |= pad->out_value & PMIC_GPIO_REG_MODE_VALUE_SHIFT;
369
370 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_MODE_CTL, val);
371 if (ret < 0)
372 return ret;
373 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300374
375 val = pad->is_enabled << PMIC_GPIO_REG_MASTER_EN_SHIFT;
376
377 return pmic_gpio_write(state, pad, PMIC_GPIO_REG_EN_CTL, val);
378}
379
380static const struct pinmux_ops pmic_gpio_pinmux_ops = {
381 .get_functions_count = pmic_gpio_get_functions_count,
382 .get_function_name = pmic_gpio_get_function_name,
383 .get_function_groups = pmic_gpio_get_function_groups,
384 .set_mux = pmic_gpio_set_mux,
385};
386
387static int pmic_gpio_config_get(struct pinctrl_dev *pctldev,
388 unsigned int pin, unsigned long *config)
389{
390 unsigned param = pinconf_to_config_param(*config);
391 struct pmic_gpio_pad *pad;
392 unsigned arg;
393
394 pad = pctldev->desc->pins[pin].drv_data;
395
396 switch (param) {
397 case PIN_CONFIG_DRIVE_PUSH_PULL:
398 arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_CMOS;
399 break;
400 case PIN_CONFIG_DRIVE_OPEN_DRAIN:
401 arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS;
402 break;
403 case PIN_CONFIG_DRIVE_OPEN_SOURCE:
404 arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS;
405 break;
406 case PIN_CONFIG_BIAS_PULL_DOWN:
407 arg = pad->pullup == PMIC_GPIO_PULL_DOWN;
408 break;
409 case PIN_CONFIG_BIAS_DISABLE:
410 arg = pad->pullup = PMIC_GPIO_PULL_DISABLE;
411 break;
412 case PIN_CONFIG_BIAS_PULL_UP:
413 arg = pad->pullup == PMIC_GPIO_PULL_UP_30;
414 break;
415 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
416 arg = !pad->is_enabled;
417 break;
418 case PIN_CONFIG_POWER_SOURCE:
419 arg = pad->power_source;
420 break;
421 case PIN_CONFIG_INPUT_ENABLE:
422 arg = pad->input_enabled;
423 break;
424 case PIN_CONFIG_OUTPUT:
425 arg = pad->out_value;
426 break;
427 case PMIC_GPIO_CONF_PULL_UP:
428 arg = pad->pullup;
429 break;
430 case PMIC_GPIO_CONF_STRENGTH:
431 arg = pad->strength;
432 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800433 case PMIC_GPIO_CONF_ATEST:
434 arg = pad->atest;
435 break;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300436 default:
437 return -EINVAL;
438 }
439
440 *config = pinconf_to_config_packed(param, arg);
441 return 0;
442}
443
444static int pmic_gpio_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
445 unsigned long *configs, unsigned nconfs)
446{
447 struct pmic_gpio_state *state = pinctrl_dev_get_drvdata(pctldev);
448 struct pmic_gpio_pad *pad;
449 unsigned param, arg;
450 unsigned int val;
451 int i, ret;
452
453 pad = pctldev->desc->pins[pin].drv_data;
454
455 for (i = 0; i < nconfs; i++) {
456 param = pinconf_to_config_param(configs[i]);
457 arg = pinconf_to_config_argument(configs[i]);
458
459 switch (param) {
460 case PIN_CONFIG_DRIVE_PUSH_PULL:
461 pad->buffer_type = PMIC_GPIO_OUT_BUF_CMOS;
462 break;
463 case PIN_CONFIG_DRIVE_OPEN_DRAIN:
464 if (!pad->have_buffer)
465 return -EINVAL;
466 pad->buffer_type = PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS;
467 break;
468 case PIN_CONFIG_DRIVE_OPEN_SOURCE:
469 if (!pad->have_buffer)
470 return -EINVAL;
471 pad->buffer_type = PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS;
472 break;
473 case PIN_CONFIG_BIAS_DISABLE:
474 pad->pullup = PMIC_GPIO_PULL_DISABLE;
475 break;
476 case PIN_CONFIG_BIAS_PULL_UP:
477 pad->pullup = PMIC_GPIO_PULL_UP_30;
478 break;
479 case PIN_CONFIG_BIAS_PULL_DOWN:
480 if (arg)
481 pad->pullup = PMIC_GPIO_PULL_DOWN;
482 else
483 pad->pullup = PMIC_GPIO_PULL_DISABLE;
484 break;
485 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
486 pad->is_enabled = false;
487 break;
488 case PIN_CONFIG_POWER_SOURCE:
489 if (arg > pad->num_sources)
490 return -EINVAL;
491 pad->power_source = arg;
492 break;
493 case PIN_CONFIG_INPUT_ENABLE:
494 pad->input_enabled = arg ? true : false;
495 break;
496 case PIN_CONFIG_OUTPUT:
497 pad->output_enabled = true;
498 pad->out_value = arg;
499 break;
500 case PMIC_GPIO_CONF_PULL_UP:
501 if (arg > PMIC_GPIO_PULL_UP_1P5_30)
502 return -EINVAL;
503 pad->pullup = arg;
504 break;
505 case PMIC_GPIO_CONF_STRENGTH:
506 if (arg > PMIC_GPIO_STRENGTH_LOW)
507 return -EINVAL;
508 pad->strength = arg;
509 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800510 case PMIC_GPIO_CONF_ATEST:
511 if (arg > PMIC_GPIO_AOUT_ATEST4)
512 return -EINVAL;
513 pad->atest = arg;
514 break;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300515 default:
516 return -EINVAL;
517 }
518 }
519
520 val = pad->power_source << PMIC_GPIO_REG_VIN_SHIFT;
521
522 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_DIG_VIN_CTL, val);
523 if (ret < 0)
524 return ret;
525
526 val = pad->pullup << PMIC_GPIO_REG_PULL_SHIFT;
527
528 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_DIG_PULL_CTL, val);
529 if (ret < 0)
530 return ret;
531
532 val = pad->buffer_type << PMIC_GPIO_REG_OUT_TYPE_SHIFT;
Ivan T. Ivanov982df6a2015-04-09 18:18:35 +0300533 val |= pad->strength << PMIC_GPIO_REG_OUT_STRENGTH_SHIFT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300534
535 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_DIG_OUT_CTL, val);
536 if (ret < 0)
537 return ret;
538
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800539 val = PMIC_GPIO_MODE_DIGITAL_INPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300540 if (pad->output_enabled) {
541 if (pad->input_enabled)
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800542 val = PMIC_GPIO_MODE_DIGITAL_INPUT_OUTPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300543 else
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800544 val = PMIC_GPIO_MODE_DIGITAL_OUTPUT;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300545 }
546
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800547 if (pad->lv_mv_type) {
548 if (pad->function == PMIC_GPIO_FUNC_INDEX_ANALOG) {
549 val = PMIC_GPIO_MODE_ANALOG_PASS_THRU;
550 ret = pmic_gpio_write(state, pad,
551 PMIC_GPIO_REG_MODE_CTL, val);
552 if (ret < 0)
553 return ret;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300554
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800555 ret = pmic_gpio_write(state, pad,
556 PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL,
557 pad->atest);
558 if (ret < 0)
559 return ret;
560 } else {
561 ret = pmic_gpio_write(state, pad,
562 PMIC_GPIO_REG_MODE_CTL, val);
563 if (ret < 0)
564 return ret;
565
566 val = pad->out_value
567 << PMIC_GPIO_LV_MV_OUTPUT_INVERT_SHIFT;
568 val |= pad->function
569 & PMIC_GPIO_LV_MV_OUTPUT_SOURCE_SEL_MASK;
570 ret = pmic_gpio_write(state, pad,
571 PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL, val);
572 if (ret < 0)
573 return ret;
574 }
575 } else {
576 val = val << PMIC_GPIO_REG_MODE_DIR_SHIFT;
577 val |= pad->function << PMIC_GPIO_REG_MODE_FUNCTION_SHIFT;
578 val |= pad->out_value & PMIC_GPIO_REG_MODE_VALUE_SHIFT;
579
580 ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_MODE_CTL, val);
581 if (ret < 0)
582 return ret;
583 }
584
585 return ret;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300586}
587
588static void pmic_gpio_config_dbg_show(struct pinctrl_dev *pctldev,
589 struct seq_file *s, unsigned pin)
590{
591 struct pmic_gpio_state *state = pinctrl_dev_get_drvdata(pctldev);
592 struct pmic_gpio_pad *pad;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800593 int ret, val, function;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300594
595 static const char *const biases[] = {
596 "pull-up 30uA", "pull-up 1.5uA", "pull-up 31.5uA",
597 "pull-up 1.5uA + 30uA boost", "pull-down 10uA", "no pull"
598 };
599 static const char *const buffer_types[] = {
600 "push-pull", "open-drain", "open-source"
601 };
602 static const char *const strengths[] = {
603 "no", "high", "medium", "low"
604 };
605
606 pad = pctldev->desc->pins[pin].drv_data;
607
608 seq_printf(s, " gpio%-2d:", pin + PMIC_GPIO_PHYSICAL_OFFSET);
609
610 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_EN_CTL);
611
612 if (val < 0 || !(val >> PMIC_GPIO_REG_MASTER_EN_SHIFT)) {
613 seq_puts(s, " ---");
614 } else {
615
Ivan T. Ivanov24a66612015-04-09 18:18:36 +0300616 if (pad->input_enabled) {
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300617 ret = pmic_gpio_read(state, pad, PMIC_MPP_REG_RT_STS);
Ivan T. Ivanov24a66612015-04-09 18:18:36 +0300618 if (ret < 0)
619 return;
620
621 ret &= PMIC_MPP_REG_RT_STS_VAL_MASK;
622 pad->out_value = ret;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300623 }
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800624 /*
625 * For GPIO not of LV/MV subtypes, the register value of
626 * the function mapping from "dtest1" to "dtest4" is 2 bits
627 * lower than the function index in pmic_gpio_functions[].
628 */
629 if (!pad->lv_mv_type &&
630 pad->function >= PMIC_GPIO_FUNC_INDEX_FUNC3) {
631 function = pad->function + (PMIC_GPIO_FUNC_INDEX_DTEST1
632 - PMIC_GPIO_FUNC_INDEX_FUNC3);
633 } else {
634 function = pad->function;
635 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300636
637 seq_printf(s, " %-4s", pad->output_enabled ? "out" : "in");
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800638 seq_printf(s, " %-7s", pmic_gpio_functions[function]);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300639 seq_printf(s, " vin-%d", pad->power_source);
640 seq_printf(s, " %-27s", biases[pad->pullup]);
641 seq_printf(s, " %-10s", buffer_types[pad->buffer_type]);
642 seq_printf(s, " %-4s", pad->out_value ? "high" : "low");
643 seq_printf(s, " %-7s", strengths[pad->strength]);
644 }
645}
646
647static const struct pinconf_ops pmic_gpio_pinconf_ops = {
Soren Brinkmann7382b622015-01-09 07:43:51 -0800648 .is_generic = true,
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300649 .pin_config_group_get = pmic_gpio_config_get,
650 .pin_config_group_set = pmic_gpio_config_set,
651 .pin_config_group_dbg_show = pmic_gpio_config_dbg_show,
652};
653
654static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
655{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100656 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300657 unsigned long config;
658
659 config = pinconf_to_config_packed(PIN_CONFIG_INPUT_ENABLE, 1);
660
661 return pmic_gpio_config_set(state->ctrl, pin, &config, 1);
662}
663
664static int pmic_gpio_direction_output(struct gpio_chip *chip,
665 unsigned pin, int val)
666{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100667 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300668 unsigned long config;
669
670 config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, val);
671
672 return pmic_gpio_config_set(state->ctrl, pin, &config, 1);
673}
674
675static int pmic_gpio_get(struct gpio_chip *chip, unsigned pin)
676{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100677 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300678 struct pmic_gpio_pad *pad;
679 int ret;
680
681 pad = state->ctrl->desc->pins[pin].drv_data;
682
683 if (!pad->is_enabled)
684 return -EINVAL;
685
686 if (pad->input_enabled) {
687 ret = pmic_gpio_read(state, pad, PMIC_MPP_REG_RT_STS);
688 if (ret < 0)
689 return ret;
690
691 pad->out_value = ret & PMIC_MPP_REG_RT_STS_VAL_MASK;
692 }
693
Linus Walleij86c1a212015-12-21 16:29:50 +0100694 return !!pad->out_value;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300695}
696
697static void pmic_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
698{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100699 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300700 unsigned long config;
701
702 config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, value);
703
704 pmic_gpio_config_set(state->ctrl, pin, &config, 1);
705}
706
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300707static int pmic_gpio_of_xlate(struct gpio_chip *chip,
708 const struct of_phandle_args *gpio_desc,
709 u32 *flags)
710{
711 if (chip->of_gpio_n_cells < 2)
712 return -EINVAL;
713
714 if (flags)
715 *flags = gpio_desc->args[1];
716
717 return gpio_desc->args[0] - PMIC_GPIO_PHYSICAL_OFFSET;
718}
719
720static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
721{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100722 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300723 struct pmic_gpio_pad *pad;
724
725 pad = state->ctrl->desc->pins[pin].drv_data;
726
727 return pad->irq;
728}
729
730static void pmic_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
731{
Linus Walleijc52d9df2015-12-08 09:51:47 +0100732 struct pmic_gpio_state *state = gpiochip_get_data(chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300733 unsigned i;
734
735 for (i = 0; i < chip->ngpio; i++) {
736 pmic_gpio_config_dbg_show(state->ctrl, s, i);
737 seq_puts(s, "\n");
738 }
739}
740
741static const struct gpio_chip pmic_gpio_gpio_template = {
742 .direction_input = pmic_gpio_direction_input,
743 .direction_output = pmic_gpio_direction_output,
744 .get = pmic_gpio_get,
745 .set = pmic_gpio_set,
Jonas Gorski98c85d52015-10-11 17:34:19 +0200746 .request = gpiochip_generic_request,
747 .free = gpiochip_generic_free,
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300748 .of_xlate = pmic_gpio_of_xlate,
749 .to_irq = pmic_gpio_to_irq,
750 .dbg_show = pmic_gpio_dbg_show,
751};
752
753static int pmic_gpio_populate(struct pmic_gpio_state *state,
754 struct pmic_gpio_pad *pad)
755{
756 int type, subtype, val, dir;
757
758 type = pmic_gpio_read(state, pad, PMIC_GPIO_REG_TYPE);
759 if (type < 0)
760 return type;
761
762 if (type != PMIC_GPIO_TYPE) {
763 dev_err(state->dev, "incorrect block type 0x%x at 0x%x\n",
764 type, pad->base);
765 return -ENODEV;
766 }
767
768 subtype = pmic_gpio_read(state, pad, PMIC_GPIO_REG_SUBTYPE);
769 if (subtype < 0)
770 return subtype;
771
772 switch (subtype) {
773 case PMIC_GPIO_SUBTYPE_GPIO_4CH:
774 pad->have_buffer = true;
775 case PMIC_GPIO_SUBTYPE_GPIOC_4CH:
776 pad->num_sources = 4;
777 break;
778 case PMIC_GPIO_SUBTYPE_GPIO_8CH:
779 pad->have_buffer = true;
780 case PMIC_GPIO_SUBTYPE_GPIOC_8CH:
781 pad->num_sources = 8;
782 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800783 case PMIC_GPIO_SUBTYPE_GPIO_LV:
784 pad->num_sources = 1;
785 pad->have_buffer = true;
786 pad->lv_mv_type = true;
787 break;
788 case PMIC_GPIO_SUBTYPE_GPIO_MV:
789 pad->num_sources = 2;
790 pad->have_buffer = true;
791 pad->lv_mv_type = true;
792 break;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300793 default:
794 dev_err(state->dev, "unknown GPIO type 0x%x\n", subtype);
795 return -ENODEV;
796 }
797
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800798 if (pad->lv_mv_type) {
799 val = pmic_gpio_read(state, pad,
800 PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL);
801 if (val < 0)
802 return val;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300803
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800804 pad->out_value = !!(val & PMIC_GPIO_LV_MV_OUTPUT_INVERT);
805 pad->function = val & PMIC_GPIO_LV_MV_OUTPUT_SOURCE_SEL_MASK;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300806
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800807 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_MODE_CTL);
808 if (val < 0)
809 return val;
810
811 dir = val & PMIC_GPIO_REG_LV_MV_MODE_DIR_MASK;
812 } else {
813 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_MODE_CTL);
814 if (val < 0)
815 return val;
816
817 pad->out_value = val & PMIC_GPIO_REG_MODE_VALUE_SHIFT;
818
819 dir = val >> PMIC_GPIO_REG_MODE_DIR_SHIFT;
820 dir &= PMIC_GPIO_REG_MODE_DIR_MASK;
821 pad->function = val >> PMIC_GPIO_REG_MODE_FUNCTION_SHIFT;
822 pad->function &= PMIC_GPIO_REG_MODE_FUNCTION_MASK;
823 }
824
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300825 switch (dir) {
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800826 case PMIC_GPIO_MODE_DIGITAL_INPUT:
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300827 pad->input_enabled = true;
828 pad->output_enabled = false;
829 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800830 case PMIC_GPIO_MODE_DIGITAL_OUTPUT:
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300831 pad->input_enabled = false;
832 pad->output_enabled = true;
833 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800834 case PMIC_GPIO_MODE_DIGITAL_INPUT_OUTPUT:
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300835 pad->input_enabled = true;
836 pad->output_enabled = true;
837 break;
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800838 case PMIC_GPIO_MODE_ANALOG_PASS_THRU:
839 if (pad->lv_mv_type)
840 pad->function = PMIC_GPIO_FUNC_INDEX_ANALOG;
841 else
842 return -ENODEV;
843 break;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300844 default:
845 dev_err(state->dev, "unknown GPIO direction\n");
846 return -ENODEV;
847 }
848
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300849 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_DIG_VIN_CTL);
850 if (val < 0)
851 return val;
852
853 pad->power_source = val >> PMIC_GPIO_REG_VIN_SHIFT;
854 pad->power_source &= PMIC_GPIO_REG_VIN_MASK;
855
856 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_DIG_PULL_CTL);
857 if (val < 0)
858 return val;
859
860 pad->pullup = val >> PMIC_GPIO_REG_PULL_SHIFT;
861 pad->pullup &= PMIC_GPIO_REG_PULL_MASK;
862
863 val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_DIG_OUT_CTL);
864 if (val < 0)
865 return val;
866
867 pad->strength = val >> PMIC_GPIO_REG_OUT_STRENGTH_SHIFT;
868 pad->strength &= PMIC_GPIO_REG_OUT_STRENGTH_MASK;
869
870 pad->buffer_type = val >> PMIC_GPIO_REG_OUT_TYPE_SHIFT;
871 pad->buffer_type &= PMIC_GPIO_REG_OUT_TYPE_MASK;
872
Fenglin Wu60a05cb2016-07-21 14:32:24 +0800873 if (pad->function == PMIC_GPIO_FUNC_INDEX_ANALOG) {
874 val = pmic_gpio_read(state, pad,
875 PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL);
876 if (val < 0)
877 return val;
878 pad->atest = val & PMIC_GPIO_LV_MV_ANA_MUX_SEL_MASK;
879 }
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300880 /* Pin could be disabled with PIN_CONFIG_BIAS_HIGH_IMPEDANCE */
881 pad->is_enabled = true;
882 return 0;
883}
884
885static int pmic_gpio_probe(struct platform_device *pdev)
886{
887 struct device *dev = &pdev->dev;
888 struct pinctrl_pin_desc *pindesc;
889 struct pinctrl_desc *pctrldesc;
890 struct pmic_gpio_pad *pad, *pads;
891 struct pmic_gpio_state *state;
892 int ret, npins, i;
Stephen Boydab4256c2015-11-18 11:33:17 -0800893 u32 reg;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300894
Stephen Boydab4256c2015-11-18 11:33:17 -0800895 ret = of_property_read_u32(dev->of_node, "reg", &reg);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300896 if (ret < 0) {
Stephen Boydab4256c2015-11-18 11:33:17 -0800897 dev_err(dev, "missing base address");
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300898 return ret;
899 }
900
Stephen Boyda5ea13f2016-01-06 17:37:41 -0800901 npins = platform_irq_count(pdev);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300902 if (!npins)
903 return -EINVAL;
Stephen Boyda5ea13f2016-01-06 17:37:41 -0800904 if (npins < 0)
905 return npins;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300906
907 BUG_ON(npins > ARRAY_SIZE(pmic_gpio_groups));
908
909 state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
910 if (!state)
911 return -ENOMEM;
912
913 platform_set_drvdata(pdev, state);
914
915 state->dev = &pdev->dev;
916 state->map = dev_get_regmap(dev->parent, NULL);
917
918 pindesc = devm_kcalloc(dev, npins, sizeof(*pindesc), GFP_KERNEL);
919 if (!pindesc)
920 return -ENOMEM;
921
922 pads = devm_kcalloc(dev, npins, sizeof(*pads), GFP_KERNEL);
923 if (!pads)
924 return -ENOMEM;
925
926 pctrldesc = devm_kzalloc(dev, sizeof(*pctrldesc), GFP_KERNEL);
927 if (!pctrldesc)
928 return -ENOMEM;
929
930 pctrldesc->pctlops = &pmic_gpio_pinctrl_ops;
931 pctrldesc->pmxops = &pmic_gpio_pinmux_ops;
932 pctrldesc->confops = &pmic_gpio_pinconf_ops;
933 pctrldesc->owner = THIS_MODULE;
934 pctrldesc->name = dev_name(dev);
935 pctrldesc->pins = pindesc;
936 pctrldesc->npins = npins;
Linus Walleijf684e4a2015-01-12 00:45:55 +0100937 pctrldesc->num_custom_params = ARRAY_SIZE(pmic_gpio_bindings);
938 pctrldesc->custom_params = pmic_gpio_bindings;
Arnd Bergmann4f062662015-01-28 17:08:44 +0100939#ifdef CONFIG_DEBUG_FS
Linus Walleijf684e4a2015-01-12 00:45:55 +0100940 pctrldesc->custom_conf_items = pmic_conf_items;
Arnd Bergmann4f062662015-01-28 17:08:44 +0100941#endif
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300942
943 for (i = 0; i < npins; i++, pindesc++) {
944 pad = &pads[i];
945 pindesc->drv_data = pad;
946 pindesc->number = i;
947 pindesc->name = pmic_gpio_groups[i];
948
949 pad->irq = platform_get_irq(pdev, i);
950 if (pad->irq < 0)
951 return pad->irq;
952
Stephen Boydab4256c2015-11-18 11:33:17 -0800953 pad->base = reg + i * PMIC_GPIO_ADDRESS_RANGE;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300954
955 ret = pmic_gpio_populate(state, pad);
956 if (ret < 0)
957 return ret;
958 }
959
960 state->chip = pmic_gpio_gpio_template;
Linus Walleij58383c72015-11-04 09:56:26 +0100961 state->chip.parent = dev;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300962 state->chip.base = -1;
963 state->chip.ngpio = npins;
964 state->chip.label = dev_name(dev);
965 state->chip.of_gpio_n_cells = 2;
966 state->chip.can_sleep = false;
967
Laxman Dewanganb46ddfe2016-02-24 14:44:07 +0530968 state->ctrl = devm_pinctrl_register(dev, pctrldesc, state);
Masahiro Yamada323de9e2015-06-09 13:01:16 +0900969 if (IS_ERR(state->ctrl))
970 return PTR_ERR(state->ctrl);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300971
Linus Walleijc52d9df2015-12-08 09:51:47 +0100972 ret = gpiochip_add_data(&state->chip, state);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300973 if (ret) {
974 dev_err(state->dev, "can't add gpio chip\n");
Laxman Dewanganb46ddfe2016-02-24 14:44:07 +0530975 return ret;
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300976 }
977
978 ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins);
979 if (ret) {
980 dev_err(dev, "failed to add pin range\n");
981 goto err_range;
982 }
983
984 return 0;
985
986err_range:
987 gpiochip_remove(&state->chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300988 return ret;
989}
990
991static int pmic_gpio_remove(struct platform_device *pdev)
992{
993 struct pmic_gpio_state *state = platform_get_drvdata(pdev);
994
995 gpiochip_remove(&state->chip);
Ivan T. Ivanoveadff302014-10-22 12:58:46 +0300996 return 0;
997}
998
999static const struct of_device_id pmic_gpio_of_match[] = {
Ivan T. Ivanov7414b092015-03-31 12:37:18 +03001000 { .compatible = "qcom,pm8916-gpio" }, /* 4 GPIO's */
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001001 { .compatible = "qcom,pm8941-gpio" }, /* 36 GPIO's */
Stephen Boyd016c2f42015-11-17 16:52:32 -08001002 { .compatible = "qcom,pm8994-gpio" }, /* 22 GPIO's */
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001003 { .compatible = "qcom,pma8084-gpio" }, /* 22 GPIO's */
Stephen Boyd94fa6672016-07-11 12:01:09 -07001004 { .compatible = "qcom,spmi-gpio" }, /* Generic */
Ivan T. Ivanoveadff302014-10-22 12:58:46 +03001005 { },
1006};
1007
1008MODULE_DEVICE_TABLE(of, pmic_gpio_of_match);
1009
1010static struct platform_driver pmic_gpio_driver = {
1011 .driver = {
1012 .name = "qcom-spmi-gpio",
1013 .of_match_table = pmic_gpio_of_match,
1014 },
1015 .probe = pmic_gpio_probe,
1016 .remove = pmic_gpio_remove,
1017};
1018
1019module_platform_driver(pmic_gpio_driver);
1020
1021MODULE_AUTHOR("Ivan T. Ivanov <iivanov@mm-sol.com>");
1022MODULE_DESCRIPTION("Qualcomm SPMI PMIC GPIO pin control driver");
1023MODULE_ALIAS("platform:qcom-spmi-gpio");
1024MODULE_LICENSE("GPL v2");