pinctrl_ich6.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2016 Google, Inc
  4. */
  5. #include <common.h>
  6. #include <dm.h>
  7. #include <errno.h>
  8. #include <fdtdec.h>
  9. #include <pch.h>
  10. #include <pci.h>
  11. #include <asm/cpu.h>
  12. #include <asm/gpio.h>
  13. #include <asm/io.h>
  14. #include <asm/pci.h>
  15. #include <dm/pinctrl.h>
  16. DECLARE_GLOBAL_DATA_PTR;
  17. #define GPIO_USESEL_OFFSET(x) (x)
  18. #define GPIO_IOSEL_OFFSET(x) (x + 4)
  19. #define GPIO_LVL_OFFSET(x) ((x) ? (x) + 8 : 0xc)
  20. #define GPI_INV 0x2c
  21. #define IOPAD_MODE_MASK 0x7
  22. #define IOPAD_PULL_ASSIGN_SHIFT 7
  23. #define IOPAD_PULL_ASSIGN_MASK (0x3 << IOPAD_PULL_ASSIGN_SHIFT)
  24. #define IOPAD_PULL_STRENGTH_SHIFT 9
  25. #define IOPAD_PULL_STRENGTH_MASK (0x3 << IOPAD_PULL_STRENGTH_SHIFT)
  26. static int ich6_pinctrl_set_value(uint16_t base, unsigned offset, int value)
  27. {
  28. if (value)
  29. setio_32(base, 1UL << offset);
  30. else
  31. clrio_32(base, 1UL << offset);
  32. return 0;
  33. }
  34. static int ich6_pinctrl_set_function(uint16_t base, unsigned offset, int func)
  35. {
  36. if (func)
  37. setio_32(base, 1UL << offset);
  38. else
  39. clrio_32(base, 1UL << offset);
  40. return 0;
  41. }
  42. static int ich6_pinctrl_set_direction(uint16_t base, unsigned offset, int dir)
  43. {
  44. if (!dir)
  45. setio_32(base, 1UL << offset);
  46. else
  47. clrio_32(base, 1UL << offset);
  48. return 0;
  49. }
  50. static int ich6_pinctrl_cfg_pin(s32 gpiobase, s32 iobase, int pin_node)
  51. {
  52. bool is_gpio, invert;
  53. u32 gpio_offset[2];
  54. int pad_offset;
  55. int dir, val;
  56. int ret;
  57. /*
  58. * GPIO node is not mandatory, so we only do the pinmuxing if the
  59. * node exists.
  60. */
  61. ret = fdtdec_get_int_array(gd->fdt_blob, pin_node, "gpio-offset",
  62. gpio_offset, 2);
  63. if (!ret) {
  64. /* Do we want to force the GPIO mode? */
  65. is_gpio = fdtdec_get_bool(gd->fdt_blob, pin_node, "mode-gpio");
  66. if (is_gpio)
  67. ich6_pinctrl_set_function(GPIO_USESEL_OFFSET(gpiobase) +
  68. gpio_offset[0], gpio_offset[1],
  69. 1);
  70. dir = fdtdec_get_int(gd->fdt_blob, pin_node, "direction", -1);
  71. if (dir != -1)
  72. ich6_pinctrl_set_direction(GPIO_IOSEL_OFFSET(gpiobase) +
  73. gpio_offset[0], gpio_offset[1],
  74. dir);
  75. val = fdtdec_get_int(gd->fdt_blob, pin_node, "output-value",
  76. -1);
  77. if (val != -1)
  78. ich6_pinctrl_set_value(GPIO_LVL_OFFSET(gpiobase) +
  79. gpio_offset[0], gpio_offset[1],
  80. val);
  81. invert = fdtdec_get_bool(gd->fdt_blob, pin_node, "invert");
  82. if (invert)
  83. setio_32(gpiobase + GPI_INV, 1 << gpio_offset[1]);
  84. debug("gpio %#x bit %d, is_gpio %d, dir %d, val %d, invert %d\n",
  85. gpio_offset[0], gpio_offset[1], is_gpio, dir, val,
  86. invert);
  87. }
  88. /* if iobase is present, let's configure the pad */
  89. if (iobase != -1) {
  90. ulong iobase_addr;
  91. /*
  92. * The offset for the same pin for the IOBASE and GPIOBASE are
  93. * different, so instead of maintaining a lookup table,
  94. * the device tree should provide directly the correct
  95. * value for both mapping.
  96. */
  97. pad_offset = fdtdec_get_int(gd->fdt_blob, pin_node,
  98. "pad-offset", -1);
  99. if (pad_offset == -1)
  100. return 0;
  101. /* compute the absolute pad address */
  102. iobase_addr = iobase + pad_offset;
  103. /*
  104. * Do we need to set a specific function mode?
  105. * If someone put also 'mode-gpio', this option will
  106. * be just ignored by the controller
  107. */
  108. val = fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
  109. if (val != -1)
  110. clrsetbits_le32(iobase_addr, IOPAD_MODE_MASK, val);
  111. /* Configure the pull-up/down if needed */
  112. val = fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
  113. if (val != -1)
  114. clrsetbits_le32(iobase_addr,
  115. IOPAD_PULL_ASSIGN_MASK,
  116. val << IOPAD_PULL_ASSIGN_SHIFT);
  117. val = fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength",
  118. -1);
  119. if (val != -1)
  120. clrsetbits_le32(iobase_addr,
  121. IOPAD_PULL_STRENGTH_MASK,
  122. val << IOPAD_PULL_STRENGTH_SHIFT);
  123. debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
  124. readl(iobase_addr));
  125. }
  126. return 0;
  127. }
  128. static int ich6_pinctrl_probe(struct udevice *dev)
  129. {
  130. struct udevice *pch;
  131. int pin_node;
  132. int ret;
  133. u32 gpiobase;
  134. u32 iobase = -1;
  135. debug("%s: start\n", __func__);
  136. ret = uclass_first_device(UCLASS_PCH, &pch);
  137. if (ret)
  138. return ret;
  139. if (!pch)
  140. return -ENODEV;
  141. /*
  142. * Get the memory/io base address to configure every pins.
  143. * IOBASE is used to configure the mode/pads
  144. * GPIOBASE is used to configure the direction and default value
  145. */
  146. ret = pch_get_gpio_base(pch, &gpiobase);
  147. if (ret) {
  148. debug("%s: invalid GPIOBASE address (%08x)\n", __func__,
  149. gpiobase);
  150. return -EINVAL;
  151. }
  152. /*
  153. * Get the IOBASE, this is not mandatory as this is not
  154. * supported by all the CPU
  155. */
  156. ret = pch_get_io_base(pch, &iobase);
  157. if (ret && ret != -ENOSYS) {
  158. debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
  159. return -EINVAL;
  160. }
  161. for (pin_node = fdt_first_subnode(gd->fdt_blob, dev_of_offset(dev));
  162. pin_node > 0;
  163. pin_node = fdt_next_subnode(gd->fdt_blob, pin_node)) {
  164. /* Configure the pin */
  165. ret = ich6_pinctrl_cfg_pin(gpiobase, iobase, pin_node);
  166. if (ret != 0) {
  167. debug("%s: invalid configuration for the pin %d\n",
  168. __func__, pin_node);
  169. return ret;
  170. }
  171. }
  172. debug("%s: done\n", __func__);
  173. return 0;
  174. }
  175. static const struct udevice_id ich6_pinctrl_match[] = {
  176. { .compatible = "intel,x86-pinctrl", .data = X86_SYSCON_PINCONF },
  177. { /* sentinel */ }
  178. };
  179. U_BOOT_DRIVER(ich6_pinctrl) = {
  180. .name = "ich6_pinctrl",
  181. .id = UCLASS_SYSCON,
  182. .of_match = ich6_pinctrl_match,
  183. .probe = ich6_pinctrl_probe,
  184. };