blob: d7695dbe77b8c6050d1b205fd1afc44372e19d86 [file] [log] [blame]
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301/*
2 * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
3 *
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>
17#include <linux/pinctrl/pinconf-generic.h>
18#include <linux/pinctrl/pinconf.h>
19#include <linux/pinctrl/pinmux.h>
20#include <linux/platform_device.h>
21#include <linux/regmap.h>
22#include <linux/slab.h>
23#include <linux/types.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053024#include <asoc/wcd934x_registers.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053025
Laxminath Kasam605b42f2017-08-01 22:02:15 +053026#include "core.h"
27#include "pinctrl-utils.h"
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053028
29#define WCD_REG_DIR_CTL WCD934X_CHIP_TIER_CTRL_GPIO_CTL_OE
30#define WCD_REG_VAL_CTL WCD934X_CHIP_TIER_CTRL_GPIO_CTL_DATA
31#define WCD_GPIO_PULL_UP 1
32#define WCD_GPIO_PULL_DOWN 2
33#define WCD_GPIO_BIAS_DISABLE 3
34#define WCD_GPIO_STRING_LEN 20
35
36/**
37 * struct wcd_gpio_pad - keep current GPIO settings
38 * @offset: offset of gpio.
39 * @is_valid: Set to false, when GPIO in high Z state.
40 * @value: value of a pin
41 * @output_enabled: Set to true if GPIO is output and false if it is input
42 * @pullup: Constant current which flow through GPIO output buffer.
43 * @strength: Drive strength of a pin
44 */
45struct wcd_gpio_pad {
46 u16 offset;
47 bool is_valid;
48 bool value;
49 bool output_enabled;
50 unsigned int pullup;
51 unsigned int strength;
52};
53
54struct wcd_gpio_priv {
55 struct device *dev;
56 struct regmap *map;
57 struct pinctrl_dev *ctrl;
58 struct gpio_chip chip;
59};
60
61static int wcd_gpio_read(struct wcd_gpio_priv *priv_data,
62 struct wcd_gpio_pad *pad, unsigned int addr)
63{
64 unsigned int val;
65 int ret;
66
67 ret = regmap_read(priv_data->map, addr, &val);
68 if (ret < 0)
69 dev_err(priv_data->dev, "%s: read 0x%x failed\n",
70 __func__, addr);
71 else
72 ret = (val >> pad->offset);
73
74 return ret;
75}
76
77static int wcd_gpio_write(struct wcd_gpio_priv *priv_data,
78 struct wcd_gpio_pad *pad, unsigned int addr,
79 unsigned int val)
80{
81 int ret;
82
83 ret = regmap_update_bits(priv_data->map, addr, (1 << pad->offset),
84 val << pad->offset);
85 if (ret < 0)
86 dev_err(priv_data->dev, "write 0x%x failed\n", addr);
87
88 return ret;
89}
90
91static int wcd_get_groups_count(struct pinctrl_dev *pctldev)
92{
93 return pctldev->desc->npins;
94}
95
96static const char *wcd_get_group_name(struct pinctrl_dev *pctldev,
97 unsigned int pin)
98{
99 return pctldev->desc->pins[pin].name;
100}
101
102static int wcd_get_group_pins(struct pinctrl_dev *pctldev, unsigned int pin,
103 const unsigned int **pins, unsigned int *num_pins)
104{
105 *pins = &pctldev->desc->pins[pin].number;
106 *num_pins = 1;
107 return 0;
108}
109
110static const struct pinctrl_ops wcd_pinctrl_ops = {
111 .get_groups_count = wcd_get_groups_count,
112 .get_group_name = wcd_get_group_name,
113 .get_group_pins = wcd_get_group_pins,
114 .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
115 .dt_free_map = pinctrl_utils_free_map,
116};
117
118static int wcd_config_get(struct pinctrl_dev *pctldev,
119 unsigned int pin, unsigned long *config)
120{
121 unsigned int param = pinconf_to_config_param(*config);
122 struct wcd_gpio_pad *pad;
123 unsigned int arg;
124
125 pad = pctldev->desc->pins[pin].drv_data;
126
127 switch (param) {
128 case PIN_CONFIG_BIAS_PULL_DOWN:
129 arg = pad->pullup == WCD_GPIO_PULL_DOWN;
130 break;
131 case PIN_CONFIG_BIAS_DISABLE:
132 arg = pad->pullup = WCD_GPIO_BIAS_DISABLE;
133 break;
134 case PIN_CONFIG_BIAS_PULL_UP:
135 arg = pad->pullup == WCD_GPIO_PULL_UP;
136 break;
137 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
138 arg = !pad->is_valid;
139 break;
140 case PIN_CONFIG_INPUT_ENABLE:
141 arg = pad->output_enabled;
142 break;
143 case PIN_CONFIG_OUTPUT:
144 arg = pad->value;
145 break;
146 default:
147 return -EINVAL;
148 }
149
150 *config = pinconf_to_config_packed(param, arg);
151 return 0;
152}
153
154static int wcd_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
155 unsigned long *configs, unsigned int nconfs)
156{
157 struct wcd_gpio_priv *priv_data = pinctrl_dev_get_drvdata(pctldev);
158 struct wcd_gpio_pad *pad;
159 unsigned int param, arg;
160 int i, ret;
161
162 pad = pctldev->desc->pins[pin].drv_data;
163
164 for (i = 0; i < nconfs; i++) {
165 param = pinconf_to_config_param(configs[i]);
166 arg = pinconf_to_config_argument(configs[i]);
167
168 dev_dbg(priv_data->dev, "%s: param: %d arg: %d",
169 __func__, param, arg);
170
171 switch (param) {
172 case PIN_CONFIG_BIAS_DISABLE:
173 pad->pullup = WCD_GPIO_BIAS_DISABLE;
174 break;
175 case PIN_CONFIG_BIAS_PULL_UP:
176 pad->pullup = WCD_GPIO_PULL_UP;
177 break;
178 case PIN_CONFIG_BIAS_PULL_DOWN:
179 pad->pullup = WCD_GPIO_PULL_DOWN;
180 break;
181 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
182 pad->is_valid = false;
183 break;
184 case PIN_CONFIG_INPUT_ENABLE:
185 pad->output_enabled = false;
186 break;
187 case PIN_CONFIG_OUTPUT:
188 pad->output_enabled = true;
189 pad->value = arg;
190 break;
191 case PIN_CONFIG_DRIVE_STRENGTH:
192 pad->strength = arg;
193 break;
194 default:
195 ret = -EINVAL;
196 goto done;
197 }
198 }
199
200 if (pad->output_enabled) {
201 ret = wcd_gpio_write(priv_data, pad, WCD_REG_DIR_CTL,
202 pad->output_enabled);
203 if (ret < 0)
204 goto done;
205 ret = wcd_gpio_write(priv_data, pad, WCD_REG_VAL_CTL,
206 pad->value);
207 } else
208 ret = wcd_gpio_write(priv_data, pad, WCD_REG_DIR_CTL,
209 pad->output_enabled);
210done:
211 return ret;
212}
213
214static const struct pinconf_ops wcd_pinconf_ops = {
215 .is_generic = true,
216 .pin_config_group_get = wcd_config_get,
217 .pin_config_group_set = wcd_config_set,
218};
219
220static int wcd_gpio_direction_input(struct gpio_chip *chip, unsigned int pin)
221{
222 struct wcd_gpio_priv *priv_data = gpiochip_get_data(chip);
223 unsigned long config;
224
225 config = pinconf_to_config_packed(PIN_CONFIG_INPUT_ENABLE, 1);
226
227 return wcd_config_set(priv_data->ctrl, pin, &config, 1);
228}
229
230static int wcd_gpio_direction_output(struct gpio_chip *chip,
231 unsigned int pin, int val)
232{
233 struct wcd_gpio_priv *priv_data = gpiochip_get_data(chip);
234 unsigned long config;
235
236 config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, val);
237
238 return wcd_config_set(priv_data->ctrl, pin, &config, 1);
239}
240
241static int wcd_gpio_get(struct gpio_chip *chip, unsigned int pin)
242{
243 struct wcd_gpio_priv *priv_data = gpiochip_get_data(chip);
244 struct wcd_gpio_pad *pad;
245 int value;
246
247 pad = priv_data->ctrl->desc->pins[pin].drv_data;
248
249 if (!pad->is_valid)
250 return -EINVAL;
251
252 value = wcd_gpio_read(priv_data, pad, WCD_REG_VAL_CTL);
253 return value;
254}
255
256static void wcd_gpio_set(struct gpio_chip *chip, unsigned int pin, int value)
257{
258 struct wcd_gpio_priv *priv_data = gpiochip_get_data(chip);
259 unsigned long config;
260
261 config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, value);
262
263 wcd_config_set(priv_data->ctrl, pin, &config, 1);
264}
265
266static const struct gpio_chip wcd_gpio_chip = {
267 .direction_input = wcd_gpio_direction_input,
268 .direction_output = wcd_gpio_direction_output,
269 .get = wcd_gpio_get,
270 .set = wcd_gpio_set,
271};
272
273static int wcd_pinctrl_probe(struct platform_device *pdev)
274{
275 struct device *dev = &pdev->dev;
276 struct pinctrl_pin_desc *pindesc;
277 struct pinctrl_desc *pctrldesc;
278 struct wcd_gpio_pad *pad, *pads;
279 struct wcd_gpio_priv *priv_data;
280 int ret, i, j;
281 u32 npins;
282 char **name;
283
284 ret = of_property_read_u32(dev->of_node, "qcom,num-gpios", &npins);
285 if (ret) {
286 dev_err(dev, "%s: Looking up %s property in node %s failed\n",
287 __func__, "qcom,num-gpios", dev->of_node->full_name);
288 ret = -EINVAL;
289 goto err_priv_alloc;
290 }
291 if (!npins) {
292 dev_err(dev, "%s: no.of pins are 0\n", __func__);
293 ret = -EINVAL;
294 goto err_priv_alloc;
295 }
296
297 priv_data = devm_kzalloc(dev, sizeof(*priv_data), GFP_KERNEL);
298 if (!priv_data) {
299 ret = -ENOMEM;
300 goto err_priv_alloc;
301 }
302
303 priv_data->dev = dev;
304 priv_data->map = dev_get_regmap(dev->parent, NULL);
305 if (!priv_data->map) {
306 dev_err(dev, "%s: failed to get regmap\n", __func__);
307 ret = -EINVAL;
308 goto err_regmap;
309 }
310
311 pindesc = devm_kcalloc(dev, npins, sizeof(*pindesc), GFP_KERNEL);
312 if (!pindesc) {
313 ret = -ENOMEM;
314 goto err_pinsec_alloc;
315 }
316
317 pads = devm_kcalloc(dev, npins, sizeof(*pads), GFP_KERNEL);
318 if (!pads) {
319 ret = -ENOMEM;
320 goto err_pads_alloc;
321 }
322
323 pctrldesc = devm_kzalloc(dev, sizeof(*pctrldesc), GFP_KERNEL);
324 if (!pctrldesc) {
325 ret = -ENOMEM;
326 goto err_pinctrl_alloc;
327 }
328
329 pctrldesc->pctlops = &wcd_pinctrl_ops;
330 pctrldesc->confops = &wcd_pinconf_ops;
331 pctrldesc->owner = THIS_MODULE;
332 pctrldesc->name = dev_name(dev);
333 pctrldesc->pins = pindesc;
334 pctrldesc->npins = npins;
335
336 name = devm_kcalloc(dev, npins, sizeof(char *), GFP_KERNEL);
337 if (!name) {
338 ret = -ENOMEM;
339 goto err_name_alloc;
340 }
341 for (i = 0; i < npins; i++, pindesc++) {
342 name[i] = devm_kzalloc(dev, sizeof(char) * WCD_GPIO_STRING_LEN,
343 GFP_KERNEL);
344 if (!name[i]) {
345 ret = -ENOMEM;
346 goto err_pin;
347 }
348 pad = &pads[i];
349 pindesc->drv_data = pad;
350 pindesc->number = i;
351 snprintf(name[i], (WCD_GPIO_STRING_LEN - 1), "gpio%d", (i+1));
352 pindesc->name = name[i];
353 pad->offset = i;
354 pad->is_valid = true;
355 }
356
357 priv_data->chip = wcd_gpio_chip;
358 priv_data->chip.parent = dev;
359 priv_data->chip.base = -1;
360 priv_data->chip.ngpio = npins;
361 priv_data->chip.label = dev_name(dev);
362 priv_data->chip.of_gpio_n_cells = 2;
363 priv_data->chip.can_sleep = false;
364
365 priv_data->ctrl = devm_pinctrl_register(dev, pctrldesc, priv_data);
366 if (IS_ERR(priv_data->ctrl)) {
367 dev_err(dev, "%s: failed to register to pinctrl\n", __func__);
368 ret = PTR_ERR(priv_data->ctrl);
369 goto err_pin;
370 }
371
372 ret = gpiochip_add_data(&priv_data->chip, priv_data);
373 if (ret) {
374 dev_err(dev, "%s: can't add gpio chip\n", __func__);
375 goto err_pin;
376 }
377
378 ret = gpiochip_add_pin_range(&priv_data->chip, dev_name(dev), 0, 0,
379 npins);
380 if (ret) {
381 dev_err(dev, "%s: failed to add pin range\n", __func__);
382 goto err_range;
383 }
384 platform_set_drvdata(pdev, priv_data);
385
386 return 0;
387
388err_range:
389 gpiochip_remove(&priv_data->chip);
390err_pin:
391 for (j = 0; j < i; j++)
392 devm_kfree(dev, name[j]);
393 devm_kfree(dev, name);
394err_name_alloc:
395 devm_kfree(dev, pctrldesc);
396err_pinctrl_alloc:
397 devm_kfree(dev, pads);
398err_pads_alloc:
399 devm_kfree(dev, pindesc);
400err_pinsec_alloc:
401err_regmap:
402 devm_kfree(dev, priv_data);
403err_priv_alloc:
404 return ret;
405}
406
407static int wcd_pinctrl_remove(struct platform_device *pdev)
408{
409 struct wcd_gpio_priv *priv_data = platform_get_drvdata(pdev);
410
411 gpiochip_remove(&priv_data->chip);
412
413 return 0;
414}
415
416static const struct of_device_id wcd_pinctrl_of_match[] = {
417 { .compatible = "qcom,wcd-pinctrl" },
418 { },
419};
420
421MODULE_DEVICE_TABLE(of, wcd_pinctrl_of_match);
422
423static struct platform_driver wcd_pinctrl_driver = {
424 .driver = {
425 .name = "qcom-wcd-pinctrl",
426 .of_match_table = wcd_pinctrl_of_match,
427 },
428 .probe = wcd_pinctrl_probe,
429 .remove = wcd_pinctrl_remove,
430};
431
432module_platform_driver(wcd_pinctrl_driver);
433
434MODULE_DESCRIPTION("Qualcomm Technologies, Inc WCD GPIO pin control driver");
435MODULE_LICENSE("GPL v2");