pinctrl_stm32.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #include <common.h>
  2. #include <dm.h>
  3. #include <dm/pinctrl.h>
  4. #include <asm/arch/gpio.h>
  5. #include <asm/gpio.h>
  6. #include <asm/io.h>
  7. DECLARE_GLOBAL_DATA_PTR;
  8. #define MAX_PINS_ONE_IP 70
  9. #define MODE_BITS_MASK 3
  10. #define OSPEED_MASK 3
  11. #define PUPD_MASK 3
  12. #define OTYPE_MSK 1
  13. #define AFR_MASK 0xF
  14. static int stm32_gpio_config(struct gpio_desc *desc,
  15. const struct stm32_gpio_ctl *ctl)
  16. {
  17. struct stm32_gpio_priv *priv = dev_get_priv(desc->dev);
  18. struct stm32_gpio_regs *regs = priv->regs;
  19. u32 index;
  20. if (!ctl || ctl->af > 15 || ctl->mode > 3 || ctl->otype > 1 ||
  21. ctl->pupd > 2 || ctl->speed > 3)
  22. return -EINVAL;
  23. index = (desc->offset & 0x07) * 4;
  24. clrsetbits_le32(&regs->afr[desc->offset >> 3], AFR_MASK << index,
  25. ctl->af << index);
  26. index = desc->offset * 2;
  27. clrsetbits_le32(&regs->moder, MODE_BITS_MASK << index,
  28. ctl->mode << index);
  29. clrsetbits_le32(&regs->ospeedr, OSPEED_MASK << index,
  30. ctl->speed << index);
  31. clrsetbits_le32(&regs->pupdr, PUPD_MASK << index, ctl->pupd << index);
  32. index = desc->offset;
  33. clrsetbits_le32(&regs->otyper, OTYPE_MSK << index, ctl->otype << index);
  34. return 0;
  35. }
  36. static int prep_gpio_dsc(struct stm32_gpio_dsc *gpio_dsc, u32 port_pin)
  37. {
  38. gpio_dsc->port = (port_pin & 0xF000) >> 12;
  39. gpio_dsc->pin = (port_pin & 0x0F00) >> 8;
  40. debug("%s: GPIO:port= %d, pin= %d\n", __func__, gpio_dsc->port,
  41. gpio_dsc->pin);
  42. return 0;
  43. }
  44. static int prep_gpio_ctl(struct stm32_gpio_ctl *gpio_ctl, u32 gpio_fn, int node)
  45. {
  46. gpio_fn &= 0x00FF;
  47. gpio_ctl->af = 0;
  48. switch (gpio_fn) {
  49. case 0:
  50. gpio_ctl->mode = STM32_GPIO_MODE_IN;
  51. break;
  52. case 1 ... 16:
  53. gpio_ctl->mode = STM32_GPIO_MODE_AF;
  54. gpio_ctl->af = gpio_fn - 1;
  55. break;
  56. case 17:
  57. gpio_ctl->mode = STM32_GPIO_MODE_AN;
  58. break;
  59. default:
  60. gpio_ctl->mode = STM32_GPIO_MODE_OUT;
  61. break;
  62. }
  63. gpio_ctl->speed = fdtdec_get_int(gd->fdt_blob, node, "slew-rate", 0);
  64. if (fdtdec_get_bool(gd->fdt_blob, node, "drive-open-drain"))
  65. gpio_ctl->otype = STM32_GPIO_OTYPE_OD;
  66. else
  67. gpio_ctl->otype = STM32_GPIO_OTYPE_PP;
  68. if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-up"))
  69. gpio_ctl->pupd = STM32_GPIO_PUPD_UP;
  70. else if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-down"))
  71. gpio_ctl->pupd = STM32_GPIO_PUPD_DOWN;
  72. else
  73. gpio_ctl->pupd = STM32_GPIO_PUPD_NO;
  74. debug("%s: gpio fn= %d, slew-rate= %x, op type= %x, pull-upd is = %x\n",
  75. __func__, gpio_fn, gpio_ctl->speed, gpio_ctl->otype,
  76. gpio_ctl->pupd);
  77. return 0;
  78. }
  79. static int stm32_pinctrl_config(int offset)
  80. {
  81. u32 pin_mux[MAX_PINS_ONE_IP];
  82. int rv, len;
  83. /*
  84. * check for "pinmux" property in each subnode (e.g. pins1 and pins2 for
  85. * usart1) of pin controller phandle "pinctrl-0"
  86. * */
  87. fdt_for_each_subnode(offset, gd->fdt_blob, offset) {
  88. struct stm32_gpio_dsc gpio_dsc;
  89. struct stm32_gpio_ctl gpio_ctl;
  90. int i;
  91. len = fdtdec_get_int_array_count(gd->fdt_blob, offset,
  92. "pinmux", pin_mux,
  93. ARRAY_SIZE(pin_mux));
  94. debug("%s: no of pinmux entries= %d\n", __func__, len);
  95. if (len < 0)
  96. return -EINVAL;
  97. for (i = 0; i < len; i++) {
  98. struct gpio_desc desc;
  99. debug("%s: pinmux = %x\n", __func__, *(pin_mux + i));
  100. prep_gpio_dsc(&gpio_dsc, *(pin_mux + i));
  101. prep_gpio_ctl(&gpio_ctl, *(pin_mux + i), offset);
  102. rv = uclass_get_device_by_seq(UCLASS_GPIO,
  103. gpio_dsc.port, &desc.dev);
  104. if (rv)
  105. return rv;
  106. desc.offset = gpio_dsc.pin;
  107. rv = stm32_gpio_config(&desc, &gpio_ctl);
  108. debug("%s: rv = %d\n\n", __func__, rv);
  109. if (rv)
  110. return rv;
  111. }
  112. }
  113. return 0;
  114. }
  115. #if CONFIG_IS_ENABLED(PINCTRL_FULL)
  116. static int stm32_pinctrl_set_state(struct udevice *dev, struct udevice *config)
  117. {
  118. return stm32_pinctrl_config(dev_of_offset(config));
  119. }
  120. #else /* PINCTRL_FULL */
  121. static int stm32_pinctrl_set_state_simple(struct udevice *dev,
  122. struct udevice *periph)
  123. {
  124. const void *fdt = gd->fdt_blob;
  125. const fdt32_t *list;
  126. uint32_t phandle;
  127. int config_node;
  128. int size, i, ret;
  129. list = fdt_getprop(fdt, dev_of_offset(periph), "pinctrl-0", &size);
  130. if (!list)
  131. return -EINVAL;
  132. debug("%s: periph->name = %s\n", __func__, periph->name);
  133. size /= sizeof(*list);
  134. for (i = 0; i < size; i++) {
  135. phandle = fdt32_to_cpu(*list++);
  136. config_node = fdt_node_offset_by_phandle(fdt, phandle);
  137. if (config_node < 0) {
  138. pr_err("prop pinctrl-0 index %d invalid phandle\n", i);
  139. return -EINVAL;
  140. }
  141. ret = stm32_pinctrl_config(config_node);
  142. if (ret)
  143. return ret;
  144. }
  145. return 0;
  146. }
  147. #endif /* PINCTRL_FULL */
  148. static struct pinctrl_ops stm32_pinctrl_ops = {
  149. #if CONFIG_IS_ENABLED(PINCTRL_FULL)
  150. .set_state = stm32_pinctrl_set_state,
  151. #else /* PINCTRL_FULL */
  152. .set_state_simple = stm32_pinctrl_set_state_simple,
  153. #endif /* PINCTRL_FULL */
  154. };
  155. static const struct udevice_id stm32_pinctrl_ids[] = {
  156. { .compatible = "st,stm32f746-pinctrl" },
  157. { .compatible = "st,stm32h743-pinctrl" },
  158. { }
  159. };
  160. U_BOOT_DRIVER(pinctrl_stm32) = {
  161. .name = "pinctrl_stm32",
  162. .id = UCLASS_PINCTRL,
  163. .of_match = stm32_pinctrl_ids,
  164. .ops = &stm32_pinctrl_ops,
  165. .bind = dm_scan_fdt_dev,
  166. };