pinctrl-starfive.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Pinctrl / GPIO driver for StarFive JH7100 SoC
  4. *
  5. * Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
  6. * Author: Lee Kuan Lim <kuanlim.lee@starfivetech.com>
  7. * Author: Jianlong Huang <jianlong.huang@starfivetech.com>
  8. */
  9. #include <common.h>
  10. #include <clk.h>
  11. #include <dm.h>
  12. #include <dm/device-internal.h>
  13. #include <dm/lists.h>
  14. #include <dm/pinctrl.h>
  15. #include <asm-generic/gpio.h>
  16. #include <linux/bitops.h>
  17. #include <linux/io.h>
  18. #include <linux/ioport.h>
  19. #include <dm/device_compat.h>
  20. #include <dt-bindings/pinctrl/pinctrl-starfive-jh7110.h>
  21. #include "pinctrl-starfive.h"
  22. /* pad control bits */
  23. #define STARFIVE_PADCFG_POS BIT(7)
  24. #define STARFIVE_PADCFG_SMT BIT(6)
  25. #define STARFIVE_PADCFG_SLEW BIT(5)
  26. #define STARFIVE_PADCFG_PD BIT(4)
  27. #define STARFIVE_PADCFG_PU BIT(3)
  28. #define STARFIVE_PADCFG_BIAS (STARFIVE_PADCFG_PD | STARFIVE_PADCFG_PU)
  29. #define STARFIVE_PADCFG_DS_MASK GENMASK(2, 1)
  30. #define STARFIVE_PADCFG_DS_2MA (0U << 1)
  31. #define STARFIVE_PADCFG_DS_4MA (1U << 1)
  32. #define STARFIVE_PADCFG_DS_8MA (2U << 1)
  33. #define STARFIVE_PADCFG_DS_12MA (3U << 1)
  34. #define STARFIVE_PADCFG_IE BIT(0)
  35. #define GPIO_NUM_PER_WORD 32
  36. /*
  37. * The packed pinmux values from the device tree look like this:
  38. *
  39. * | 31 - 24 | 23 - 16 | 15 - 10 | 9 - 8 | 7 - 0 |
  40. * | din | dout | doen | function | pin |
  41. */
  42. static unsigned int starfive_pinmux_din(u32 v)
  43. {
  44. return (v & GENMASK(31, 24)) >> 24;
  45. }
  46. static u32 starfive_pinmux_dout(u32 v)
  47. {
  48. return (v & GENMASK(23, 16)) >> 16;
  49. }
  50. static u32 starfive_pinmux_doen(u32 v)
  51. {
  52. return (v & GENMASK(15, 10)) >> 10;
  53. }
  54. static u32 starfive_pinmux_function(u32 v)
  55. {
  56. return (v & GENMASK(9, 8)) >> 8;
  57. }
  58. static unsigned int starfive_pinmux_pin(u32 v)
  59. {
  60. return v & GENMASK(7, 0);
  61. }
  62. void starfive_set_gpiomux(struct udevice *dev, unsigned int pin,
  63. unsigned int din, u32 dout, u32 doen)
  64. {
  65. struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
  66. const struct starfive_pinctrl_soc_info *info = priv->info;
  67. unsigned int offset = 4 * (pin / 4);
  68. unsigned int shift = 8 * (pin % 4);
  69. u32 dout_mask = info->dout_mask << shift;
  70. u32 done_mask = info->doen_mask << shift;
  71. u32 ival, imask;
  72. void __iomem *reg_dout;
  73. void __iomem *reg_doen;
  74. void __iomem *reg_din;
  75. reg_dout = priv->base + info->dout_reg_base + offset;
  76. reg_doen = priv->base + info->doen_reg_base + offset;
  77. dout <<= shift;
  78. doen <<= shift;
  79. if (din != GPI_NONE) {
  80. unsigned int ioffset = 4 * (din / 4);
  81. unsigned int ishift = 8 * (din % 4);
  82. reg_din = priv->base + info->gpi_reg_base + ioffset;
  83. ival = (pin + 2) << ishift;
  84. imask = info->gpi_mask << ishift;
  85. } else {
  86. reg_din = NULL;
  87. }
  88. dout |= readl(reg_dout) & ~dout_mask;
  89. writel(dout, reg_dout);
  90. doen |= readl(reg_doen) & ~done_mask;
  91. writel(doen, reg_doen);
  92. if (reg_din) {
  93. ival |= readl(reg_din) & ~imask;
  94. writel(ival, reg_din);
  95. }
  96. }
  97. static int starfive_pinctrl_set_state_subnode(struct udevice *dev,
  98. ofnode node)
  99. {
  100. struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
  101. struct starfive_pinctrl_soc_info *info = priv->info;
  102. int ret, i;
  103. int npins;
  104. u32 *pinmux;
  105. npins = ofnode_read_size(node, "pinmux") / sizeof(u32);
  106. if (npins < 1)
  107. return -EINVAL;
  108. pinmux = kcalloc(npins, sizeof(*pinmux), GFP_KERNEL);
  109. if (!pinmux)
  110. return -ENOMEM;
  111. ret = ofnode_read_u32_array(node, "pinmux", pinmux, npins);
  112. if (ret < 0)
  113. return ret;
  114. for (i = 0; i < npins; i++) {
  115. u32 v = pinmux[i];
  116. if (info->set_one_pinmux)
  117. info->set_one_pinmux(dev,
  118. starfive_pinmux_pin(v),
  119. starfive_pinmux_din(v),
  120. starfive_pinmux_dout(v),
  121. starfive_pinmux_doen(v),
  122. starfive_pinmux_function(v));
  123. }
  124. return 0;
  125. }
  126. /*
  127. * starfive_pinctrl_set_state: configure a pin state.
  128. * @dev: pin controller device
  129. * @config: pseudo device pointing to config node
  130. */
  131. int starfive_pinctrl_set_state(struct udevice *dev, struct udevice *config)
  132. {
  133. ofnode node;
  134. int ret;
  135. dev_for_each_subnode(node, config) {
  136. ret = starfive_pinctrl_set_state_subnode(dev, node);
  137. if (ret)
  138. return ret;
  139. }
  140. return 0;
  141. }
  142. static const struct pinconf_param starfive_pinconf_params[] = {
  143. { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
  144. { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
  145. { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
  146. { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
  147. { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
  148. { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
  149. { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
  150. { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
  151. { "slew-rate", PIN_CONFIG_SLEW_RATE, 0 },
  152. };
  153. static const u8 starfive_drive_strength_mA[4] = { 2, 4, 8, 12 };
  154. static u32 starfive_padcfg_ds_from_mA(u32 v)
  155. {
  156. int i;
  157. for (i = 0; i < 3; i++) {
  158. if (v <= starfive_drive_strength_mA[i])
  159. break;
  160. }
  161. return i << 1;
  162. }
  163. static void starfive_padcfg_rmw(struct udevice *dev,
  164. unsigned int pin, u32 mask, u32 value)
  165. {
  166. struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
  167. struct starfive_pinctrl_soc_info *info = priv->info;
  168. void __iomem *reg;
  169. int padcfg_base;
  170. if (!info->get_padcfg_base)
  171. return;
  172. padcfg_base = info->get_padcfg_base(dev, pin);
  173. if (padcfg_base < 0)
  174. return;
  175. reg = priv->base + padcfg_base + 4 * pin;
  176. value &= mask;
  177. value |= readl(reg) & ~mask;
  178. writel(value, reg);
  179. }
  180. static int starfive_pinconf_set(struct udevice *dev, unsigned int pin,
  181. unsigned int param, unsigned int arg)
  182. {
  183. u16 mask = 0;
  184. u16 value = 0;
  185. switch (param) {
  186. case PIN_CONFIG_BIAS_DISABLE:
  187. mask |= STARFIVE_PADCFG_BIAS;
  188. value &= ~STARFIVE_PADCFG_BIAS;
  189. break;
  190. case PIN_CONFIG_BIAS_PULL_DOWN:
  191. if (arg == 0)
  192. return -ENOTSUPP;
  193. mask |= STARFIVE_PADCFG_BIAS;
  194. value = (value & ~STARFIVE_PADCFG_BIAS) | STARFIVE_PADCFG_PD;
  195. break;
  196. case PIN_CONFIG_BIAS_PULL_UP:
  197. if (arg == 0)
  198. return -ENOTSUPP;
  199. mask |= STARFIVE_PADCFG_BIAS;
  200. value = (value & ~STARFIVE_PADCFG_BIAS) | STARFIVE_PADCFG_PU;
  201. break;
  202. case PIN_CONFIG_DRIVE_STRENGTH:
  203. mask |= STARFIVE_PADCFG_DS_MASK;
  204. value = (value & ~STARFIVE_PADCFG_DS_MASK) |
  205. starfive_padcfg_ds_from_mA(arg);
  206. break;
  207. case PIN_CONFIG_INPUT_ENABLE:
  208. mask |= STARFIVE_PADCFG_IE;
  209. if (arg)
  210. value |= STARFIVE_PADCFG_IE;
  211. else
  212. value &= ~STARFIVE_PADCFG_IE;
  213. break;
  214. case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
  215. mask |= STARFIVE_PADCFG_SMT;
  216. if (arg)
  217. value |= STARFIVE_PADCFG_SMT;
  218. else
  219. value &= ~STARFIVE_PADCFG_SMT;
  220. break;
  221. case PIN_CONFIG_SLEW_RATE:
  222. mask |= STARFIVE_PADCFG_SLEW;
  223. if (arg)
  224. value |= STARFIVE_PADCFG_SLEW;
  225. else
  226. value &= ~STARFIVE_PADCFG_SLEW;
  227. break;
  228. default:
  229. return -ENOTSUPP;
  230. }
  231. starfive_padcfg_rmw(dev, pin, mask, value);
  232. return 0;
  233. }
  234. const struct pinctrl_ops starfive_pinctrl_ops = {
  235. .set_state = starfive_pinctrl_set_state,
  236. .pinconf_num_params = ARRAY_SIZE(starfive_pinconf_params),
  237. .pinconf_params = starfive_pinconf_params,
  238. .pinconf_set = starfive_pinconf_set,
  239. };
  240. static int starfive_gpio_get_direction(struct udevice *dev, unsigned int off)
  241. {
  242. struct udevice *pdev = dev->parent;
  243. struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
  244. struct starfive_pinctrl_soc_info *info = priv->info;
  245. unsigned int offset = 4 * (off / 4);
  246. unsigned int shift = 8 * (off % 4);
  247. u32 doen = readl(priv->base + info->doen_reg_base + offset);
  248. doen = (doen >> shift) & info->doen_mask;
  249. return doen == GPOEN_ENABLE ? GPIOF_OUTPUT : GPIOF_INPUT;
  250. }
  251. static int starfive_gpio_direction_input(struct udevice *dev, unsigned int off)
  252. {
  253. struct udevice *pdev = dev->parent;
  254. struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
  255. struct starfive_pinctrl_soc_info *info = priv->info;
  256. /* enable input and schmitt trigger */
  257. starfive_padcfg_rmw(pdev, off,
  258. STARFIVE_PADCFG_IE | STARFIVE_PADCFG_SMT,
  259. STARFIVE_PADCFG_IE | STARFIVE_PADCFG_SMT);
  260. if (info->set_one_pinmux)
  261. info->set_one_pinmux(pdev, off,
  262. GPI_NONE, GPOUT_LOW, GPOEN_DISABLE, 0);
  263. return 0;
  264. }
  265. static int starfive_gpio_direction_output(struct udevice *dev,
  266. unsigned int off, int val)
  267. {
  268. struct udevice *pdev = dev->parent;
  269. struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
  270. struct starfive_pinctrl_soc_info *info = priv->info;
  271. if (info->set_one_pinmux)
  272. info->set_one_pinmux(pdev, off,
  273. GPI_NONE, val ? GPOUT_HIGH : GPOUT_LOW,
  274. GPOEN_ENABLE, 0);
  275. /* disable input, schmitt trigger and bias */
  276. starfive_padcfg_rmw(pdev, off,
  277. STARFIVE_PADCFG_IE | STARFIVE_PADCFG_SMT
  278. | STARFIVE_PADCFG_BIAS,
  279. 0);
  280. return 0;
  281. }
  282. static int starfive_gpio_get_value(struct udevice *dev, unsigned int off)
  283. {
  284. struct udevice *pdev = dev->parent;
  285. struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
  286. struct starfive_pinctrl_soc_info *info = priv->info;
  287. void __iomem *reg = priv->base + info->gpioin_reg_base
  288. + 4 * (off / GPIO_NUM_PER_WORD);
  289. return !!(readl(reg) & BIT(off % GPIO_NUM_PER_WORD));
  290. }
  291. static int starfive_gpio_set_value(struct udevice *dev,
  292. unsigned int off, int val)
  293. {
  294. struct udevice *pdev = dev->parent;
  295. struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
  296. struct starfive_pinctrl_soc_info *info = priv->info;
  297. unsigned int offset = 4 * (off / 4);
  298. unsigned int shift = 8 * (off % 4);
  299. void __iomem *reg_dout = priv->base + info->dout_reg_base + offset;
  300. u32 dout = (val ? GPOUT_HIGH : GPOUT_LOW) << shift;
  301. u32 mask = info->dout_mask << shift;
  302. dout |= readl(reg_dout) & ~mask;
  303. writel(dout, reg_dout);
  304. return 0;
  305. }
  306. static int starfive_gpio_probe(struct udevice *dev)
  307. {
  308. struct gpio_dev_priv *uc_priv;
  309. struct udevice *pdev = dev->parent;
  310. struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
  311. struct starfive_pinctrl_soc_info *info = priv->info;
  312. uc_priv = dev_get_uclass_priv(dev);
  313. uc_priv->bank_name = info->gpio_bank_name;
  314. uc_priv->gpio_count = info->ngpios;
  315. if (!info->gpio_init_hw)
  316. return -ENXIO;
  317. info->gpio_init_hw(pdev);
  318. return 0;
  319. }
  320. static const struct dm_gpio_ops starfive_gpio_ops = {
  321. .get_function = starfive_gpio_get_direction,
  322. .direction_input = starfive_gpio_direction_input,
  323. .direction_output = starfive_gpio_direction_output,
  324. .get_value = starfive_gpio_get_value,
  325. .set_value = starfive_gpio_set_value,
  326. };
  327. static struct driver starfive_gpio_driver = {
  328. .name = "starfive_gpio",
  329. .id = UCLASS_GPIO,
  330. .probe = starfive_gpio_probe,
  331. .ops = &starfive_gpio_ops,
  332. };
  333. static int starfive_gpiochip_register(struct udevice *parent)
  334. {
  335. struct uclass_driver *drv;
  336. struct udevice *dev;
  337. int ret;
  338. ofnode node;
  339. drv = lists_uclass_lookup(UCLASS_GPIO);
  340. if (!drv)
  341. return -ENOENT;
  342. node = dev_ofnode(parent);
  343. ret = device_bind_with_driver_data(parent, &starfive_gpio_driver,
  344. "starfive_gpio", 0, node, &dev);
  345. if (ret)
  346. return ret;
  347. return 0;
  348. }
  349. int starfive_pinctrl_probe(struct udevice *dev,
  350. const struct starfive_pinctrl_soc_info *info)
  351. {
  352. struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
  353. int ret;
  354. /* Bind pinctrl_info from .data to priv */
  355. priv->info =
  356. (struct starfive_pinctrl_soc_info *)dev_get_driver_data(dev);
  357. if (!priv->info)
  358. return -EINVAL;
  359. priv->base = dev_read_addr_ptr(dev);
  360. if (IS_ERR(priv->base))
  361. return PTR_ERR(priv->base);
  362. /* gpiochip register */
  363. ret = starfive_gpiochip_register(dev);
  364. if (ret)
  365. return ret;
  366. dev_info(dev, "StarFive GPIO chip registered %d GPIOs\n",
  367. priv->info->ngpios);
  368. return 0;
  369. }