pinctrl-uniphier-core.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. /*
  2. * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
  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 as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <linux/export.h>
  15. #include <linux/mfd/syscon.h>
  16. #include <linux/pinctrl/pinconf.h>
  17. #include <linux/pinctrl/pinconf-generic.h>
  18. #include <linux/pinctrl/pinctrl.h>
  19. #include <linux/pinctrl/pinmux.h>
  20. #include <linux/platform_device.h>
  21. #include <linux/regmap.h>
  22. #include "../core.h"
  23. #include "../pinctrl-utils.h"
  24. #include "pinctrl-uniphier.h"
  25. struct uniphier_pinctrl_priv {
  26. struct pinctrl_dev *pctldev;
  27. struct regmap *regmap;
  28. struct uniphier_pinctrl_socdata *socdata;
  29. };
  30. static int uniphier_pctl_get_groups_count(struct pinctrl_dev *pctldev)
  31. {
  32. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  33. return priv->socdata->groups_count;
  34. }
  35. static const char *uniphier_pctl_get_group_name(struct pinctrl_dev *pctldev,
  36. unsigned selector)
  37. {
  38. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  39. return priv->socdata->groups[selector].name;
  40. }
  41. static int uniphier_pctl_get_group_pins(struct pinctrl_dev *pctldev,
  42. unsigned selector,
  43. const unsigned **pins,
  44. unsigned *num_pins)
  45. {
  46. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  47. *pins = priv->socdata->groups[selector].pins;
  48. *num_pins = priv->socdata->groups[selector].num_pins;
  49. return 0;
  50. }
  51. #ifdef CONFIG_DEBUG_FS
  52. static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
  53. struct seq_file *s, unsigned offset)
  54. {
  55. const struct pinctrl_pin_desc *pin = &pctldev->desc->pins[offset];
  56. const char *pull_dir, *drv_str;
  57. switch (uniphier_pin_get_pull_dir(pin->drv_data)) {
  58. case UNIPHIER_PIN_PULL_UP:
  59. pull_dir = "UP";
  60. break;
  61. case UNIPHIER_PIN_PULL_DOWN:
  62. pull_dir = "DOWN";
  63. break;
  64. case UNIPHIER_PIN_PULL_NONE:
  65. pull_dir = "NONE";
  66. break;
  67. default:
  68. BUG();
  69. }
  70. switch (uniphier_pin_get_drv_str(pin->drv_data)) {
  71. case UNIPHIER_PIN_DRV_4_8:
  72. drv_str = "4/8(mA)";
  73. break;
  74. case UNIPHIER_PIN_DRV_8_12_16_20:
  75. drv_str = "8/12/16/20(mA)";
  76. break;
  77. case UNIPHIER_PIN_DRV_FIXED_4:
  78. drv_str = "4(mA)";
  79. break;
  80. case UNIPHIER_PIN_DRV_FIXED_5:
  81. drv_str = "5(mA)";
  82. break;
  83. case UNIPHIER_PIN_DRV_FIXED_8:
  84. drv_str = "8(mA)";
  85. break;
  86. case UNIPHIER_PIN_DRV_NONE:
  87. drv_str = "NONE";
  88. break;
  89. default:
  90. BUG();
  91. }
  92. seq_printf(s, " PULL_DIR=%s DRV_STR=%s", pull_dir, drv_str);
  93. }
  94. #endif
  95. static const struct pinctrl_ops uniphier_pctlops = {
  96. .get_groups_count = uniphier_pctl_get_groups_count,
  97. .get_group_name = uniphier_pctl_get_group_name,
  98. .get_group_pins = uniphier_pctl_get_group_pins,
  99. #ifdef CONFIG_DEBUG_FS
  100. .pin_dbg_show = uniphier_pctl_pin_dbg_show,
  101. #endif
  102. .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
  103. .dt_free_map = pinctrl_utils_dt_free_map,
  104. };
  105. static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
  106. const struct pinctrl_pin_desc *pin,
  107. enum pin_config_param param)
  108. {
  109. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  110. enum uniphier_pin_pull_dir pull_dir =
  111. uniphier_pin_get_pull_dir(pin->drv_data);
  112. unsigned int pupdctrl, reg, shift, val;
  113. unsigned int expected = 1;
  114. int ret;
  115. switch (param) {
  116. case PIN_CONFIG_BIAS_DISABLE:
  117. if (pull_dir == UNIPHIER_PIN_PULL_NONE)
  118. return 0;
  119. if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED ||
  120. pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED)
  121. return -EINVAL;
  122. expected = 0;
  123. break;
  124. case PIN_CONFIG_BIAS_PULL_UP:
  125. if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED)
  126. return 0;
  127. if (pull_dir != UNIPHIER_PIN_PULL_UP)
  128. return -EINVAL;
  129. break;
  130. case PIN_CONFIG_BIAS_PULL_DOWN:
  131. if (pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED)
  132. return 0;
  133. if (pull_dir != UNIPHIER_PIN_PULL_DOWN)
  134. return -EINVAL;
  135. break;
  136. default:
  137. BUG();
  138. }
  139. pupdctrl = uniphier_pin_get_pupdctrl(pin->drv_data);
  140. reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
  141. shift = pupdctrl % 32;
  142. ret = regmap_read(priv->regmap, reg, &val);
  143. if (ret)
  144. return ret;
  145. val = (val >> shift) & 1;
  146. return (val == expected) ? 0 : -EINVAL;
  147. }
  148. static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
  149. const struct pinctrl_pin_desc *pin,
  150. u16 *strength)
  151. {
  152. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  153. enum uniphier_pin_drv_str drv_str =
  154. uniphier_pin_get_drv_str(pin->drv_data);
  155. const unsigned int strength_4_8[] = {4, 8};
  156. const unsigned int strength_8_12_16_20[] = {8, 12, 16, 20};
  157. const unsigned int *supported_strength;
  158. unsigned int drvctrl, reg, shift, mask, width, val;
  159. int ret;
  160. switch (drv_str) {
  161. case UNIPHIER_PIN_DRV_4_8:
  162. supported_strength = strength_4_8;
  163. width = 1;
  164. break;
  165. case UNIPHIER_PIN_DRV_8_12_16_20:
  166. supported_strength = strength_8_12_16_20;
  167. width = 2;
  168. break;
  169. case UNIPHIER_PIN_DRV_FIXED_4:
  170. *strength = 4;
  171. return 0;
  172. case UNIPHIER_PIN_DRV_FIXED_5:
  173. *strength = 5;
  174. return 0;
  175. case UNIPHIER_PIN_DRV_FIXED_8:
  176. *strength = 8;
  177. return 0;
  178. default:
  179. /* drive strength control is not supported for this pin */
  180. return -EINVAL;
  181. }
  182. drvctrl = uniphier_pin_get_drvctrl(pin->drv_data);
  183. drvctrl *= width;
  184. reg = (width == 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE :
  185. UNIPHIER_PINCTRL_DRVCTRL_BASE;
  186. reg += drvctrl / 32 * 4;
  187. shift = drvctrl % 32;
  188. mask = (1U << width) - 1;
  189. ret = regmap_read(priv->regmap, reg, &val);
  190. if (ret)
  191. return ret;
  192. *strength = supported_strength[(val >> shift) & mask];
  193. return 0;
  194. }
  195. static int uniphier_conf_pin_input_enable_get(struct pinctrl_dev *pctldev,
  196. const struct pinctrl_pin_desc *pin)
  197. {
  198. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  199. unsigned int iectrl = uniphier_pin_get_iectrl(pin->drv_data);
  200. unsigned int val;
  201. int ret;
  202. if (iectrl == UNIPHIER_PIN_IECTRL_NONE)
  203. /* This pin is always input-enabled. */
  204. return 0;
  205. ret = regmap_read(priv->regmap, UNIPHIER_PINCTRL_IECTRL, &val);
  206. if (ret)
  207. return ret;
  208. return val & BIT(iectrl) ? 0 : -EINVAL;
  209. }
  210. static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev,
  211. unsigned pin,
  212. unsigned long *configs)
  213. {
  214. const struct pinctrl_pin_desc *pin_desc = &pctldev->desc->pins[pin];
  215. enum pin_config_param param = pinconf_to_config_param(*configs);
  216. bool has_arg = false;
  217. u16 arg;
  218. int ret;
  219. switch (param) {
  220. case PIN_CONFIG_BIAS_DISABLE:
  221. case PIN_CONFIG_BIAS_PULL_UP:
  222. case PIN_CONFIG_BIAS_PULL_DOWN:
  223. ret = uniphier_conf_pin_bias_get(pctldev, pin_desc, param);
  224. break;
  225. case PIN_CONFIG_DRIVE_STRENGTH:
  226. ret = uniphier_conf_pin_drive_get(pctldev, pin_desc, &arg);
  227. has_arg = true;
  228. break;
  229. case PIN_CONFIG_INPUT_ENABLE:
  230. ret = uniphier_conf_pin_input_enable_get(pctldev, pin_desc);
  231. break;
  232. default:
  233. /* unsupported parameter */
  234. ret = -EINVAL;
  235. break;
  236. }
  237. if (ret == 0 && has_arg)
  238. *configs = pinconf_to_config_packed(param, arg);
  239. return ret;
  240. }
  241. static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
  242. const struct pinctrl_pin_desc *pin,
  243. enum pin_config_param param,
  244. u16 arg)
  245. {
  246. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  247. enum uniphier_pin_pull_dir pull_dir =
  248. uniphier_pin_get_pull_dir(pin->drv_data);
  249. unsigned int pupdctrl, reg, shift;
  250. unsigned int val = 1;
  251. switch (param) {
  252. case PIN_CONFIG_BIAS_DISABLE:
  253. if (pull_dir == UNIPHIER_PIN_PULL_NONE)
  254. return 0;
  255. if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED ||
  256. pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED) {
  257. dev_err(pctldev->dev,
  258. "can not disable pull register for pin %u (%s)\n",
  259. pin->number, pin->name);
  260. return -EINVAL;
  261. }
  262. val = 0;
  263. break;
  264. case PIN_CONFIG_BIAS_PULL_UP:
  265. if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED && arg != 0)
  266. return 0;
  267. if (pull_dir != UNIPHIER_PIN_PULL_UP) {
  268. dev_err(pctldev->dev,
  269. "pull-up is unsupported for pin %u (%s)\n",
  270. pin->number, pin->name);
  271. return -EINVAL;
  272. }
  273. if (arg == 0) {
  274. dev_err(pctldev->dev, "pull-up can not be total\n");
  275. return -EINVAL;
  276. }
  277. break;
  278. case PIN_CONFIG_BIAS_PULL_DOWN:
  279. if (pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED && arg != 0)
  280. return 0;
  281. if (pull_dir != UNIPHIER_PIN_PULL_DOWN) {
  282. dev_err(pctldev->dev,
  283. "pull-down is unsupported for pin %u (%s)\n",
  284. pin->number, pin->name);
  285. return -EINVAL;
  286. }
  287. if (arg == 0) {
  288. dev_err(pctldev->dev, "pull-down can not be total\n");
  289. return -EINVAL;
  290. }
  291. break;
  292. case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
  293. if (pull_dir == UNIPHIER_PIN_PULL_NONE) {
  294. dev_err(pctldev->dev,
  295. "pull-up/down is unsupported for pin %u (%s)\n",
  296. pin->number, pin->name);
  297. return -EINVAL;
  298. }
  299. if (arg == 0)
  300. return 0; /* configuration ingored */
  301. break;
  302. default:
  303. BUG();
  304. }
  305. pupdctrl = uniphier_pin_get_pupdctrl(pin->drv_data);
  306. reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
  307. shift = pupdctrl % 32;
  308. return regmap_update_bits(priv->regmap, reg, 1 << shift, val << shift);
  309. }
  310. static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
  311. const struct pinctrl_pin_desc *pin,
  312. u16 strength)
  313. {
  314. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  315. enum uniphier_pin_drv_str drv_str =
  316. uniphier_pin_get_drv_str(pin->drv_data);
  317. const unsigned int strength_4_8[] = {4, 8, -1};
  318. const unsigned int strength_8_12_16_20[] = {8, 12, 16, 20, -1};
  319. const unsigned int *supported_strength;
  320. unsigned int drvctrl, reg, shift, mask, width, val;
  321. switch (drv_str) {
  322. case UNIPHIER_PIN_DRV_4_8:
  323. supported_strength = strength_4_8;
  324. width = 1;
  325. break;
  326. case UNIPHIER_PIN_DRV_8_12_16_20:
  327. supported_strength = strength_8_12_16_20;
  328. width = 2;
  329. break;
  330. default:
  331. dev_err(pctldev->dev,
  332. "cannot change drive strength for pin %u (%s)\n",
  333. pin->number, pin->name);
  334. return -EINVAL;
  335. }
  336. for (val = 0; supported_strength[val] > 0; val++) {
  337. if (supported_strength[val] > strength)
  338. break;
  339. }
  340. if (val == 0) {
  341. dev_err(pctldev->dev,
  342. "unsupported drive strength %u mA for pin %u (%s)\n",
  343. strength, pin->number, pin->name);
  344. return -EINVAL;
  345. }
  346. val--;
  347. drvctrl = uniphier_pin_get_drvctrl(pin->drv_data);
  348. drvctrl *= width;
  349. reg = (width == 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE :
  350. UNIPHIER_PINCTRL_DRVCTRL_BASE;
  351. reg += drvctrl / 32 * 4;
  352. shift = drvctrl % 32;
  353. mask = (1U << width) - 1;
  354. return regmap_update_bits(priv->regmap, reg,
  355. mask << shift, val << shift);
  356. }
  357. static int uniphier_conf_pin_input_enable(struct pinctrl_dev *pctldev,
  358. const struct pinctrl_pin_desc *pin,
  359. u16 enable)
  360. {
  361. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  362. unsigned int iectrl = uniphier_pin_get_iectrl(pin->drv_data);
  363. if (enable == 0) {
  364. /*
  365. * Multiple pins share one input enable, so per-pin disabling
  366. * is impossible.
  367. */
  368. dev_err(pctldev->dev, "unable to disable input\n");
  369. return -EINVAL;
  370. }
  371. if (iectrl == UNIPHIER_PIN_IECTRL_NONE)
  372. /* This pin is always input-enabled. nothing to do. */
  373. return 0;
  374. return regmap_update_bits(priv->regmap, UNIPHIER_PINCTRL_IECTRL,
  375. BIT(iectrl), BIT(iectrl));
  376. }
  377. static int uniphier_conf_pin_config_set(struct pinctrl_dev *pctldev,
  378. unsigned pin,
  379. unsigned long *configs,
  380. unsigned num_configs)
  381. {
  382. const struct pinctrl_pin_desc *pin_desc = &pctldev->desc->pins[pin];
  383. int i, ret;
  384. for (i = 0; i < num_configs; i++) {
  385. enum pin_config_param param =
  386. pinconf_to_config_param(configs[i]);
  387. u16 arg = pinconf_to_config_argument(configs[i]);
  388. switch (param) {
  389. case PIN_CONFIG_BIAS_DISABLE:
  390. case PIN_CONFIG_BIAS_PULL_UP:
  391. case PIN_CONFIG_BIAS_PULL_DOWN:
  392. case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
  393. ret = uniphier_conf_pin_bias_set(pctldev, pin_desc,
  394. param, arg);
  395. break;
  396. case PIN_CONFIG_DRIVE_STRENGTH:
  397. ret = uniphier_conf_pin_drive_set(pctldev, pin_desc,
  398. arg);
  399. break;
  400. case PIN_CONFIG_INPUT_ENABLE:
  401. ret = uniphier_conf_pin_input_enable(pctldev,
  402. pin_desc, arg);
  403. break;
  404. default:
  405. dev_err(pctldev->dev,
  406. "unsupported configuration parameter %u\n",
  407. param);
  408. return -EINVAL;
  409. }
  410. if (ret)
  411. return ret;
  412. }
  413. return 0;
  414. }
  415. static int uniphier_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
  416. unsigned selector,
  417. unsigned long *configs,
  418. unsigned num_configs)
  419. {
  420. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  421. const unsigned *pins = priv->socdata->groups[selector].pins;
  422. unsigned num_pins = priv->socdata->groups[selector].num_pins;
  423. int i, ret;
  424. for (i = 0; i < num_pins; i++) {
  425. ret = uniphier_conf_pin_config_set(pctldev, pins[i],
  426. configs, num_configs);
  427. if (ret)
  428. return ret;
  429. }
  430. return 0;
  431. }
  432. static const struct pinconf_ops uniphier_confops = {
  433. .is_generic = true,
  434. .pin_config_get = uniphier_conf_pin_config_get,
  435. .pin_config_set = uniphier_conf_pin_config_set,
  436. .pin_config_group_set = uniphier_conf_pin_config_group_set,
  437. };
  438. static int uniphier_pmx_get_functions_count(struct pinctrl_dev *pctldev)
  439. {
  440. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  441. return priv->socdata->functions_count;
  442. }
  443. static const char *uniphier_pmx_get_function_name(struct pinctrl_dev *pctldev,
  444. unsigned selector)
  445. {
  446. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  447. return priv->socdata->functions[selector].name;
  448. }
  449. static int uniphier_pmx_get_function_groups(struct pinctrl_dev *pctldev,
  450. unsigned selector,
  451. const char * const **groups,
  452. unsigned *num_groups)
  453. {
  454. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  455. *groups = priv->socdata->functions[selector].groups;
  456. *num_groups = priv->socdata->functions[selector].num_groups;
  457. return 0;
  458. }
  459. static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
  460. unsigned muxval)
  461. {
  462. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  463. unsigned mux_bits = priv->socdata->mux_bits;
  464. unsigned reg_stride = priv->socdata->reg_stride;
  465. unsigned reg, reg_end, shift, mask;
  466. int ret;
  467. /* some pins need input-enabling */
  468. ret = uniphier_conf_pin_input_enable(pctldev,
  469. &pctldev->desc->pins[pin], 1);
  470. if (ret)
  471. return ret;
  472. reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
  473. reg_end = reg + reg_stride;
  474. shift = pin * mux_bits % 32;
  475. mask = (1U << mux_bits) - 1;
  476. /*
  477. * If reg_stride is greater than 4, the MSB of each pinsel shall be
  478. * stored in the offset+4.
  479. */
  480. for (; reg < reg_end; reg += 4) {
  481. ret = regmap_update_bits(priv->regmap, reg,
  482. mask << shift, muxval << shift);
  483. if (ret)
  484. return ret;
  485. muxval >>= mux_bits;
  486. }
  487. if (priv->socdata->load_pinctrl) {
  488. ret = regmap_write(priv->regmap,
  489. UNIPHIER_PINCTRL_LOAD_PINMUX, 1);
  490. if (ret)
  491. return ret;
  492. }
  493. return 0;
  494. }
  495. static int uniphier_pmx_set_mux(struct pinctrl_dev *pctldev,
  496. unsigned func_selector,
  497. unsigned group_selector)
  498. {
  499. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  500. const struct uniphier_pinctrl_group *grp =
  501. &priv->socdata->groups[group_selector];
  502. int i;
  503. int ret;
  504. for (i = 0; i < grp->num_pins; i++) {
  505. ret = uniphier_pmx_set_one_mux(pctldev, grp->pins[i],
  506. grp->muxvals[i]);
  507. if (ret)
  508. return ret;
  509. }
  510. return 0;
  511. }
  512. static int uniphier_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
  513. struct pinctrl_gpio_range *range,
  514. unsigned offset)
  515. {
  516. struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
  517. const struct uniphier_pinctrl_group *groups = priv->socdata->groups;
  518. int groups_count = priv->socdata->groups_count;
  519. enum uniphier_pinmux_gpio_range_type range_type;
  520. int i, j;
  521. if (strstr(range->name, "irq"))
  522. range_type = UNIPHIER_PINMUX_GPIO_RANGE_IRQ;
  523. else
  524. range_type = UNIPHIER_PINMUX_GPIO_RANGE_PORT;
  525. for (i = 0; i < groups_count; i++) {
  526. if (groups[i].range_type != range_type)
  527. continue;
  528. for (j = 0; j < groups[i].num_pins; j++)
  529. if (groups[i].pins[j] == offset)
  530. goto found;
  531. }
  532. dev_err(pctldev->dev, "pin %u does not support GPIO\n", offset);
  533. return -EINVAL;
  534. found:
  535. return uniphier_pmx_set_one_mux(pctldev, offset, groups[i].muxvals[j]);
  536. }
  537. static const struct pinmux_ops uniphier_pmxops = {
  538. .get_functions_count = uniphier_pmx_get_functions_count,
  539. .get_function_name = uniphier_pmx_get_function_name,
  540. .get_function_groups = uniphier_pmx_get_function_groups,
  541. .set_mux = uniphier_pmx_set_mux,
  542. .gpio_request_enable = uniphier_pmx_gpio_request_enable,
  543. .strict = true,
  544. };
  545. int uniphier_pinctrl_probe(struct platform_device *pdev,
  546. struct pinctrl_desc *desc,
  547. struct uniphier_pinctrl_socdata *socdata)
  548. {
  549. struct device *dev = &pdev->dev;
  550. struct uniphier_pinctrl_priv *priv;
  551. if (!socdata ||
  552. !socdata->groups ||
  553. !socdata->groups_count ||
  554. !socdata->functions ||
  555. !socdata->functions_count ||
  556. !socdata->mux_bits ||
  557. !socdata->reg_stride) {
  558. dev_err(dev, "pinctrl socdata lacks necessary members\n");
  559. return -EINVAL;
  560. }
  561. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  562. if (!priv)
  563. return -ENOMEM;
  564. priv->regmap = syscon_node_to_regmap(dev->of_node);
  565. if (IS_ERR(priv->regmap)) {
  566. dev_err(dev, "failed to get regmap\n");
  567. return PTR_ERR(priv->regmap);
  568. }
  569. priv->socdata = socdata;
  570. desc->pctlops = &uniphier_pctlops;
  571. desc->pmxops = &uniphier_pmxops;
  572. desc->confops = &uniphier_confops;
  573. priv->pctldev = pinctrl_register(desc, dev, priv);
  574. if (IS_ERR(priv->pctldev)) {
  575. dev_err(dev, "failed to register UniPhier pinctrl driver\n");
  576. return PTR_ERR(priv->pctldev);
  577. }
  578. platform_set_drvdata(pdev, priv);
  579. return 0;
  580. }
  581. EXPORT_SYMBOL_GPL(uniphier_pinctrl_probe);
  582. int uniphier_pinctrl_remove(struct platform_device *pdev)
  583. {
  584. struct uniphier_pinctrl_priv *priv = platform_get_drvdata(pdev);
  585. pinctrl_unregister(priv->pctldev);
  586. return 0;
  587. }
  588. EXPORT_SYMBOL_GPL(uniphier_pinctrl_remove);