pinctrl-sunxi.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. /*
  2. * Allwinner A1X SoCs pinctrl driver.
  3. *
  4. * Copyright (C) 2012 Maxime Ripard
  5. *
  6. * Maxime Ripard <maxime.ripard@free-electrons.com>
  7. *
  8. * This file is licensed under the terms of the GNU General Public
  9. * License version 2. This program is licensed "as is" without any
  10. * warranty of any kind, whether express or implied.
  11. */
  12. #include <linux/io.h>
  13. #include <linux/module.h>
  14. #include <linux/of.h>
  15. #include <linux/of_address.h>
  16. #include <linux/of_device.h>
  17. #include <linux/pinctrl/consumer.h>
  18. #include <linux/pinctrl/machine.h>
  19. #include <linux/pinctrl/pinctrl.h>
  20. #include <linux/pinctrl/pinconf-generic.h>
  21. #include <linux/pinctrl/pinmux.h>
  22. #include <linux/platform_device.h>
  23. #include <linux/slab.h>
  24. #include "core.h"
  25. #include "pinctrl-sunxi.h"
  26. static struct sunxi_pinctrl_group *
  27. sunxi_pinctrl_find_group_by_name(struct sunxi_pinctrl *pctl, const char *group)
  28. {
  29. int i;
  30. for (i = 0; i < pctl->ngroups; i++) {
  31. struct sunxi_pinctrl_group *grp = pctl->groups + i;
  32. if (!strcmp(grp->name, group))
  33. return grp;
  34. }
  35. return NULL;
  36. }
  37. static struct sunxi_pinctrl_function *
  38. sunxi_pinctrl_find_function_by_name(struct sunxi_pinctrl *pctl,
  39. const char *name)
  40. {
  41. struct sunxi_pinctrl_function *func = pctl->functions;
  42. int i;
  43. for (i = 0; i < pctl->nfunctions; i++) {
  44. if (!func[i].name)
  45. break;
  46. if (!strcmp(func[i].name, name))
  47. return func + i;
  48. }
  49. return NULL;
  50. }
  51. static struct sunxi_desc_function *
  52. sunxi_pinctrl_desc_find_function_by_name(struct sunxi_pinctrl *pctl,
  53. const char *pin_name,
  54. const char *func_name)
  55. {
  56. int i;
  57. for (i = 0; i < pctl->desc->npins; i++) {
  58. const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
  59. if (!strcmp(pin->pin.name, pin_name)) {
  60. struct sunxi_desc_function *func = pin->functions;
  61. while (func->name) {
  62. if (!strcmp(func->name, func_name))
  63. return func;
  64. func++;
  65. }
  66. }
  67. }
  68. return NULL;
  69. }
  70. static int sunxi_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
  71. {
  72. struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
  73. return pctl->ngroups;
  74. }
  75. static const char *sunxi_pctrl_get_group_name(struct pinctrl_dev *pctldev,
  76. unsigned group)
  77. {
  78. struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
  79. return pctl->groups[group].name;
  80. }
  81. static int sunxi_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
  82. unsigned group,
  83. const unsigned **pins,
  84. unsigned *num_pins)
  85. {
  86. struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
  87. *pins = (unsigned *)&pctl->groups[group].pin;
  88. *num_pins = 1;
  89. return 0;
  90. }
  91. static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
  92. struct device_node *node,
  93. struct pinctrl_map **map,
  94. unsigned *num_maps)
  95. {
  96. struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
  97. unsigned long *pinconfig;
  98. struct property *prop;
  99. const char *function;
  100. const char *group;
  101. int ret, nmaps, i = 0;
  102. u32 val;
  103. *map = NULL;
  104. *num_maps = 0;
  105. ret = of_property_read_string(node, "allwinner,function", &function);
  106. if (ret) {
  107. dev_err(pctl->dev,
  108. "missing allwinner,function property in node %s\n",
  109. node->name);
  110. return -EINVAL;
  111. }
  112. nmaps = of_property_count_strings(node, "allwinner,pins") * 2;
  113. if (nmaps < 0) {
  114. dev_err(pctl->dev,
  115. "missing allwinner,pins property in node %s\n",
  116. node->name);
  117. return -EINVAL;
  118. }
  119. *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL);
  120. if (!map)
  121. return -ENOMEM;
  122. of_property_for_each_string(node, "allwinner,pins", prop, group) {
  123. struct sunxi_pinctrl_group *grp =
  124. sunxi_pinctrl_find_group_by_name(pctl, group);
  125. int j = 0, configlen = 0;
  126. if (!grp) {
  127. dev_err(pctl->dev, "unknown pin %s", group);
  128. continue;
  129. }
  130. if (!sunxi_pinctrl_desc_find_function_by_name(pctl,
  131. grp->name,
  132. function)) {
  133. dev_err(pctl->dev, "unsupported function %s on pin %s",
  134. function, group);
  135. continue;
  136. }
  137. (*map)[i].type = PIN_MAP_TYPE_MUX_GROUP;
  138. (*map)[i].data.mux.group = group;
  139. (*map)[i].data.mux.function = function;
  140. i++;
  141. (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP;
  142. (*map)[i].data.configs.group_or_pin = group;
  143. if (of_find_property(node, "allwinner,drive", NULL))
  144. configlen++;
  145. if (of_find_property(node, "allwinner,pull", NULL))
  146. configlen++;
  147. pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL);
  148. if (!of_property_read_u32(node, "allwinner,drive", &val)) {
  149. u16 strength = (val + 1) * 10;
  150. pinconfig[j++] =
  151. pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH,
  152. strength);
  153. }
  154. if (!of_property_read_u32(node, "allwinner,pull", &val)) {
  155. enum pin_config_param pull = PIN_CONFIG_END;
  156. if (val == 1)
  157. pull = PIN_CONFIG_BIAS_PULL_UP;
  158. else if (val == 2)
  159. pull = PIN_CONFIG_BIAS_PULL_DOWN;
  160. pinconfig[j++] = pinconf_to_config_packed(pull, 0);
  161. }
  162. (*map)[i].data.configs.configs = pinconfig;
  163. (*map)[i].data.configs.num_configs = configlen;
  164. i++;
  165. }
  166. *num_maps = nmaps;
  167. return 0;
  168. }
  169. static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev,
  170. struct pinctrl_map *map,
  171. unsigned num_maps)
  172. {
  173. int i;
  174. for (i = 0; i < num_maps; i++) {
  175. if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
  176. kfree(map[i].data.configs.configs);
  177. }
  178. kfree(map);
  179. }
  180. static struct pinctrl_ops sunxi_pctrl_ops = {
  181. .dt_node_to_map = sunxi_pctrl_dt_node_to_map,
  182. .dt_free_map = sunxi_pctrl_dt_free_map,
  183. .get_groups_count = sunxi_pctrl_get_groups_count,
  184. .get_group_name = sunxi_pctrl_get_group_name,
  185. .get_group_pins = sunxi_pctrl_get_group_pins,
  186. };
  187. static int sunxi_pconf_group_get(struct pinctrl_dev *pctldev,
  188. unsigned group,
  189. unsigned long *config)
  190. {
  191. struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
  192. *config = pctl->groups[group].config;
  193. return 0;
  194. }
  195. static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
  196. unsigned group,
  197. unsigned long config)
  198. {
  199. struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
  200. struct sunxi_pinctrl_group *g = &pctl->groups[group];
  201. u32 val, mask;
  202. u16 strength;
  203. u8 dlevel;
  204. switch (pinconf_to_config_param(config)) {
  205. case PIN_CONFIG_DRIVE_STRENGTH:
  206. strength = pinconf_to_config_argument(config);
  207. if (strength > 40)
  208. return -EINVAL;
  209. /*
  210. * We convert from mA to what the register expects:
  211. * 0: 10mA
  212. * 1: 20mA
  213. * 2: 30mA
  214. * 3: 40mA
  215. */
  216. dlevel = strength / 10 - 1;
  217. val = readl(pctl->membase + sunxi_dlevel_reg(g->pin));
  218. mask = DLEVEL_PINS_MASK << sunxi_dlevel_offset(g->pin);
  219. writel((val & ~mask) | dlevel << sunxi_dlevel_offset(g->pin),
  220. pctl->membase + sunxi_dlevel_reg(g->pin));
  221. break;
  222. case PIN_CONFIG_BIAS_PULL_UP:
  223. val = readl(pctl->membase + sunxi_pull_reg(g->pin));
  224. mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
  225. writel((val & ~mask) | 1 << sunxi_pull_offset(g->pin),
  226. pctl->membase + sunxi_pull_reg(g->pin));
  227. break;
  228. case PIN_CONFIG_BIAS_PULL_DOWN:
  229. val = readl(pctl->membase + sunxi_pull_reg(g->pin));
  230. mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
  231. writel((val & ~mask) | 2 << sunxi_pull_offset(g->pin),
  232. pctl->membase + sunxi_pull_reg(g->pin));
  233. break;
  234. default:
  235. break;
  236. }
  237. /* cache the config value */
  238. g->config = config;
  239. return 0;
  240. }
  241. static struct pinconf_ops sunxi_pconf_ops = {
  242. .pin_config_group_get = sunxi_pconf_group_get,
  243. .pin_config_group_set = sunxi_pconf_group_set,
  244. };
  245. static int sunxi_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
  246. {
  247. struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
  248. return pctl->nfunctions;
  249. }
  250. static const char *sunxi_pmx_get_func_name(struct pinctrl_dev *pctldev,
  251. unsigned function)
  252. {
  253. struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
  254. return pctl->functions[function].name;
  255. }
  256. static int sunxi_pmx_get_func_groups(struct pinctrl_dev *pctldev,
  257. unsigned function,
  258. const char * const **groups,
  259. unsigned * const num_groups)
  260. {
  261. struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
  262. *groups = pctl->functions[function].groups;
  263. *num_groups = pctl->functions[function].ngroups;
  264. return 0;
  265. }
  266. static void sunxi_pmx_set(struct pinctrl_dev *pctldev,
  267. unsigned pin,
  268. u8 config)
  269. {
  270. struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
  271. u32 val = readl(pctl->membase + sunxi_mux_reg(pin));
  272. u32 mask = MUX_PINS_MASK << sunxi_mux_offset(pin);
  273. writel((val & ~mask) | config << sunxi_mux_offset(pin),
  274. pctl->membase + sunxi_mux_reg(pin));
  275. }
  276. static int sunxi_pmx_enable(struct pinctrl_dev *pctldev,
  277. unsigned function,
  278. unsigned group)
  279. {
  280. struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
  281. struct sunxi_pinctrl_group *g = pctl->groups + group;
  282. struct sunxi_pinctrl_function *func = pctl->functions + function;
  283. struct sunxi_desc_function *desc =
  284. sunxi_pinctrl_desc_find_function_by_name(pctl,
  285. g->name,
  286. func->name);
  287. if (!desc)
  288. return -EINVAL;
  289. sunxi_pmx_set(pctldev, g->pin, desc->muxval);
  290. return 0;
  291. }
  292. static struct pinmux_ops sunxi_pmx_ops = {
  293. .get_functions_count = sunxi_pmx_get_funcs_cnt,
  294. .get_function_name = sunxi_pmx_get_func_name,
  295. .get_function_groups = sunxi_pmx_get_func_groups,
  296. .enable = sunxi_pmx_enable,
  297. };
  298. static struct pinctrl_desc sunxi_pctrl_desc = {
  299. .confops = &sunxi_pconf_ops,
  300. .pctlops = &sunxi_pctrl_ops,
  301. .pmxops = &sunxi_pmx_ops,
  302. };
  303. static struct of_device_id sunxi_pinctrl_match[] = {
  304. {}
  305. };
  306. MODULE_DEVICE_TABLE(of, sunxi_pinctrl_match);
  307. static int sunxi_pinctrl_add_function(struct sunxi_pinctrl *pctl,
  308. const char *name)
  309. {
  310. struct sunxi_pinctrl_function *func = pctl->functions;
  311. while (func->name) {
  312. /* function already there */
  313. if (strcmp(func->name, name) == 0) {
  314. func->ngroups++;
  315. return -EEXIST;
  316. }
  317. func++;
  318. }
  319. func->name = name;
  320. func->ngroups = 1;
  321. pctl->nfunctions++;
  322. return 0;
  323. }
  324. static int sunxi_pinctrl_build_state(struct platform_device *pdev)
  325. {
  326. struct sunxi_pinctrl *pctl = platform_get_drvdata(pdev);
  327. int i;
  328. pctl->ngroups = pctl->desc->npins;
  329. /* Allocate groups */
  330. pctl->groups = devm_kzalloc(&pdev->dev,
  331. pctl->ngroups * sizeof(*pctl->groups),
  332. GFP_KERNEL);
  333. if (!pctl->groups)
  334. return -ENOMEM;
  335. for (i = 0; i < pctl->desc->npins; i++) {
  336. const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
  337. struct sunxi_pinctrl_group *group = pctl->groups + i;
  338. group->name = pin->pin.name;
  339. group->pin = pin->pin.number;
  340. }
  341. /*
  342. * We suppose that we won't have any more functions than pins,
  343. * we'll reallocate that later anyway
  344. */
  345. pctl->functions = devm_kzalloc(&pdev->dev,
  346. pctl->desc->npins * sizeof(*pctl->functions),
  347. GFP_KERNEL);
  348. if (!pctl->functions)
  349. return -ENOMEM;
  350. /* Count functions and their associated groups */
  351. for (i = 0; i < pctl->desc->npins; i++) {
  352. const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
  353. struct sunxi_desc_function *func = pin->functions;
  354. while (func->name) {
  355. sunxi_pinctrl_add_function(pctl, func->name);
  356. func++;
  357. }
  358. }
  359. pctl->functions = krealloc(pctl->functions,
  360. pctl->nfunctions * sizeof(*pctl->functions),
  361. GFP_KERNEL);
  362. for (i = 0; i < pctl->desc->npins; i++) {
  363. const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
  364. struct sunxi_desc_function *func = pin->functions;
  365. while (func->name) {
  366. struct sunxi_pinctrl_function *func_item;
  367. const char **func_grp;
  368. func_item = sunxi_pinctrl_find_function_by_name(pctl,
  369. func->name);
  370. if (!func_item)
  371. return -EINVAL;
  372. if (!func_item->groups) {
  373. func_item->groups =
  374. devm_kzalloc(&pdev->dev,
  375. func_item->ngroups * sizeof(*func_item->groups),
  376. GFP_KERNEL);
  377. if (!func_item->groups)
  378. return -ENOMEM;
  379. }
  380. func_grp = func_item->groups;
  381. while (*func_grp)
  382. func_grp++;
  383. *func_grp = pin->pin.name;
  384. func++;
  385. }
  386. }
  387. return 0;
  388. }
  389. static int sunxi_pinctrl_probe(struct platform_device *pdev)
  390. {
  391. struct device_node *node = pdev->dev.of_node;
  392. const struct of_device_id *device;
  393. struct pinctrl_pin_desc *pins;
  394. struct sunxi_pinctrl *pctl;
  395. int i, ret;
  396. pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
  397. if (!pctl)
  398. return -ENOMEM;
  399. platform_set_drvdata(pdev, pctl);
  400. pctl->membase = of_iomap(node, 0);
  401. if (!pctl->membase)
  402. return -ENOMEM;
  403. device = of_match_device(sunxi_pinctrl_match, &pdev->dev);
  404. if (!device)
  405. return -ENODEV;
  406. pctl->desc = (struct sunxi_pinctrl_desc *)device->data;
  407. ret = sunxi_pinctrl_build_state(pdev);
  408. if (ret) {
  409. dev_err(&pdev->dev, "dt probe failed: %d\n", ret);
  410. return ret;
  411. }
  412. pins = devm_kzalloc(&pdev->dev,
  413. pctl->desc->npins * sizeof(*pins),
  414. GFP_KERNEL);
  415. if (!pins)
  416. return -ENOMEM;
  417. for (i = 0; i < pctl->desc->npins; i++)
  418. pins[i] = pctl->desc->pins[i].pin;
  419. sunxi_pctrl_desc.name = dev_name(&pdev->dev);
  420. sunxi_pctrl_desc.owner = THIS_MODULE;
  421. sunxi_pctrl_desc.pins = pins;
  422. sunxi_pctrl_desc.npins = pctl->desc->npins;
  423. pctl->dev = &pdev->dev;
  424. pctl->pctl_dev = pinctrl_register(&sunxi_pctrl_desc,
  425. &pdev->dev, pctl);
  426. if (!pctl->pctl_dev) {
  427. dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
  428. return -EINVAL;
  429. }
  430. dev_info(&pdev->dev, "initialized sunXi pin control driver\n");
  431. return 0;
  432. }
  433. static struct platform_driver sunxi_pinctrl_driver = {
  434. .probe = sunxi_pinctrl_probe,
  435. .driver = {
  436. .name = "sunxi-pinctrl",
  437. .owner = THIS_MODULE,
  438. .of_match_table = sunxi_pinctrl_match,
  439. },
  440. };
  441. module_platform_driver(sunxi_pinctrl_driver);
  442. MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
  443. MODULE_DESCRIPTION("Allwinner A1X pinctrl driver");
  444. MODULE_LICENSE("GPL");