pinctrl_ich6.c 5.3 KB

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