pinctrl-wcd.c 10 KB

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