pinmux.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2018 Emlid Limited
  4. */
  5. #include <common.h>
  6. #include <dm.h>
  7. #include <dm/pinctrl.h>
  8. #include <dm/read.h>
  9. #include <regmap.h>
  10. #include <syscon.h>
  11. #include <asm/cpu.h>
  12. #include <asm/scu.h>
  13. #include <linux/io.h>
  14. #define BUFCFG_OFFSET 0x100
  15. #define MRFLD_FAMILY_LEN 0x400
  16. /* These are taken from Linux kernel */
  17. #define MRFLD_PINMODE_MASK 0x07
  18. #define pin_to_bufno(f, p) ((p) - (f)->pin_base)
  19. struct mrfld_family {
  20. unsigned int family_number;
  21. unsigned int pin_base;
  22. size_t npins;
  23. void __iomem *regs;
  24. };
  25. #define MRFLD_FAMILY(b, s, e) \
  26. { \
  27. .family_number = (b), \
  28. .pin_base = (s), \
  29. .npins = (e) - (s) + 1, \
  30. }
  31. /* Now we only support I2C family of pins */
  32. static struct mrfld_family mrfld_families[] = {
  33. MRFLD_FAMILY(7, 101, 114),
  34. };
  35. struct mrfld_pinctrl {
  36. const struct mrfld_family *families;
  37. size_t nfamilies;
  38. };
  39. static const struct mrfld_family *
  40. mrfld_get_family(struct mrfld_pinctrl *mp, unsigned int pin)
  41. {
  42. const struct mrfld_family *family;
  43. unsigned int i;
  44. for (i = 0; i < mp->nfamilies; i++) {
  45. family = &mp->families[i];
  46. if (pin >= family->pin_base &&
  47. pin < family->pin_base + family->npins)
  48. return family;
  49. }
  50. pr_err("failed to find family for pin %u\n", pin);
  51. return NULL;
  52. }
  53. static void __iomem *
  54. mrfld_get_bufcfg(struct mrfld_pinctrl *pinctrl, unsigned int pin)
  55. {
  56. const struct mrfld_family *family;
  57. unsigned int bufno;
  58. family = mrfld_get_family(pinctrl, pin);
  59. if (!family)
  60. return NULL;
  61. bufno = pin_to_bufno(family, pin);
  62. return family->regs + BUFCFG_OFFSET + bufno * 4;
  63. }
  64. static void
  65. mrfld_setup_families(void *base_addr,
  66. struct mrfld_family *families, unsigned int nfam)
  67. {
  68. for (int i = 0; i < nfam; i++) {
  69. struct mrfld_family *family = &families[i];
  70. family->regs = base_addr +
  71. family->family_number * MRFLD_FAMILY_LEN;
  72. }
  73. }
  74. static int mrfld_pinconfig_protected(unsigned int pin, u32 mask, u32 bits)
  75. {
  76. struct mrfld_pinctrl *pinctrl;
  77. struct udevice *dev;
  78. void __iomem *bufcfg;
  79. u32 v, value;
  80. int ret;
  81. ret = syscon_get_by_driver_data(X86_SYSCON_PINCONF, &dev);
  82. if (ret)
  83. return ret;
  84. pinctrl = dev_get_priv(dev);
  85. bufcfg = mrfld_get_bufcfg(pinctrl, pin);
  86. if (!bufcfg)
  87. return -EINVAL;
  88. value = readl(bufcfg);
  89. v = (value & ~mask) | (bits & mask);
  90. debug("scu: v: 0x%x p: 0x%x bits: %d, mask: %d bufcfg: 0x%p\n",
  91. v, (u32)bufcfg, bits, mask, bufcfg);
  92. ret = scu_ipc_raw_command(IPCMSG_INDIRECT_WRITE, 0, &v, 4,
  93. NULL, 0, (u32)bufcfg, 0);
  94. if (ret)
  95. pr_err("Failed to set mode via SCU for pin %u (%d)\n",
  96. pin, ret);
  97. return ret;
  98. }
  99. static int mrfld_pinctrl_cfg_pin(ofnode pin_node)
  100. {
  101. bool is_protected;
  102. int pad_offset;
  103. int mode;
  104. u32 mask;
  105. int ret;
  106. /* For now we only support just protected Family of pins */
  107. is_protected = ofnode_read_bool(pin_node, "protected");
  108. if (!is_protected)
  109. return -ENOTSUPP;
  110. pad_offset = ofnode_read_s32_default(pin_node, "pad-offset", -1);
  111. if (pad_offset == -1)
  112. return -EINVAL;
  113. mode = ofnode_read_s32_default(pin_node, "mode-func", -1);
  114. if (mode == -1)
  115. return -EINVAL;
  116. mask = MRFLD_PINMODE_MASK;
  117. /* We don't support modes not in range 0..7 */
  118. if (mode & ~mask)
  119. return -ENOTSUPP;
  120. ret = mrfld_pinconfig_protected(pad_offset, mask, mode);
  121. return ret;
  122. }
  123. static int tangier_pinctrl_probe(struct udevice *dev)
  124. {
  125. void *base_addr = syscon_get_first_range(X86_SYSCON_PINCONF);
  126. struct mrfld_pinctrl *pinctrl = dev_get_priv(dev);
  127. ofnode pin_node;
  128. int ret;
  129. mrfld_setup_families(base_addr, mrfld_families,
  130. ARRAY_SIZE(mrfld_families));
  131. pinctrl->families = mrfld_families;
  132. pinctrl->nfamilies = ARRAY_SIZE(mrfld_families);
  133. ofnode_for_each_subnode(pin_node, dev_ofnode(dev)) {
  134. ret = mrfld_pinctrl_cfg_pin(pin_node);
  135. if (ret) {
  136. pr_err("%s: invalid configuration for the pin %ld\n",
  137. __func__, pin_node.of_offset);
  138. }
  139. }
  140. return 0;
  141. }
  142. static const struct udevice_id tangier_pinctrl_match[] = {
  143. { .compatible = "intel,pinctrl-tangier", .data = X86_SYSCON_PINCONF },
  144. { /* sentinel */ }
  145. };
  146. U_BOOT_DRIVER(tangier_pinctrl) = {
  147. .name = "tangier_pinctrl",
  148. .id = UCLASS_SYSCON,
  149. .of_match = tangier_pinctrl_match,
  150. .probe = tangier_pinctrl_probe,
  151. .priv_auto_alloc_size = sizeof(struct mrfld_pinctrl),
  152. };