pinctrl-mvebu.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * Copyright (C) 2016 Marvell International Ltd.
  3. *
  4. * SPDX-License-Identifier: GPL-2.0
  5. * https://spdx.org/licenses
  6. */
  7. #include <common.h>
  8. #include <config.h>
  9. #include <fdtdec.h>
  10. #include <errno.h>
  11. #include <dm.h>
  12. #include <dm/pinctrl.h>
  13. #include <dm/root.h>
  14. #include <asm/system.h>
  15. #include <asm/io.h>
  16. #include <asm/arch-armada8k/soc-info.h>
  17. #include "pinctrl-mvebu.h"
  18. DECLARE_GLOBAL_DATA_PTR;
  19. /*
  20. * mvebu_pinctrl_set_state: configure pin functions.
  21. * @dev: the pinctrl device to be configured.
  22. * @config: the state to be configured.
  23. * @return: 0 in success
  24. */
  25. int mvebu_pinctrl_set_state(struct udevice *dev, struct udevice *config)
  26. {
  27. const void *blob = gd->fdt_blob;
  28. int node = config->of_offset;
  29. struct mvebu_pinctrl_priv *priv;
  30. u32 pin_arr[MVEBU_MAX_PINS_PER_BANK];
  31. u32 function;
  32. int i, pin_count;
  33. priv = dev_get_priv(dev);
  34. pin_count = fdtdec_get_int_array_count(blob, node,
  35. "marvell,pins",
  36. pin_arr,
  37. MVEBU_MAX_PINS_PER_BANK);
  38. if (pin_count <= 0) {
  39. debug("Failed reading pins array for pinconfig %s (%d)\n",
  40. config->name, pin_count);
  41. return -EINVAL;
  42. }
  43. function = fdtdec_get_int(blob, node, "marvell,function", 0xff);
  44. for (i = 0; i < pin_count; i++) {
  45. int reg_offset;
  46. int field_offset;
  47. int pin = pin_arr[i];
  48. if (function > priv->max_func) {
  49. debug("Illegal function %d for pinconfig %s\n",
  50. function, config->name);
  51. return -EINVAL;
  52. }
  53. /* Calculate register address and bit in register */
  54. reg_offset = priv->reg_direction * 4 *
  55. (pin >> (PIN_REG_SHIFT));
  56. field_offset = (BITS_PER_PIN) * (pin & PIN_FIELD_MASK);
  57. clrsetbits_le32(priv->base_reg + reg_offset,
  58. PIN_FUNC_MASK << field_offset,
  59. (function & PIN_FUNC_MASK) << field_offset);
  60. }
  61. return 0;
  62. }
  63. /*
  64. * mvebu_pinctrl_set_state_all: configure the entire bank pin functions.
  65. * @dev: the pinctrl device to be configured.
  66. * @config: the state to be configured.
  67. * @return: 0 in success
  68. */
  69. static int mvebu_pinctrl_set_state_all(struct udevice *dev,
  70. struct udevice *config)
  71. {
  72. const void *blob = gd->fdt_blob;
  73. int node = config->of_offset;
  74. struct mvebu_pinctrl_priv *priv;
  75. u32 func_arr[MVEBU_MAX_PINS_PER_BANK];
  76. int pin, err;
  77. priv = dev_get_priv(dev);
  78. err = fdtdec_get_int_array(blob, node, "pin-func",
  79. func_arr, priv->pin_cnt);
  80. if (err) {
  81. debug("Failed reading pin functions for bank %s\n",
  82. priv->bank_name);
  83. return -EINVAL;
  84. }
  85. for (pin = 0; pin < priv->pin_cnt; pin++) {
  86. int reg_offset;
  87. int field_offset;
  88. u32 func = func_arr[pin];
  89. /* Bypass pins with function 0xFF */
  90. if (func == 0xff) {
  91. debug("Warning: pin %d value is not modified ", pin);
  92. debug("(kept as default)\n");
  93. continue;
  94. } else if (func > priv->max_func) {
  95. debug("Illegal function %d for pin %d\n", func, pin);
  96. return -EINVAL;
  97. }
  98. /* Calculate register address and bit in register */
  99. reg_offset = priv->reg_direction * 4 *
  100. (pin >> (PIN_REG_SHIFT));
  101. field_offset = (BITS_PER_PIN) * (pin & PIN_FIELD_MASK);
  102. clrsetbits_le32(priv->base_reg + reg_offset,
  103. PIN_FUNC_MASK << field_offset,
  104. (func & PIN_FUNC_MASK) << field_offset);
  105. }
  106. return 0;
  107. }
  108. int mvebu_pinctl_probe(struct udevice *dev)
  109. {
  110. const void *blob = gd->fdt_blob;
  111. int node = dev->of_offset;
  112. struct mvebu_pinctrl_priv *priv;
  113. priv = dev_get_priv(dev);
  114. if (!priv) {
  115. debug("%s: Failed to get private\n", __func__);
  116. return -EINVAL;
  117. }
  118. priv->base_reg = dev_get_addr_ptr(dev);
  119. if (priv->base_reg == (void *)FDT_ADDR_T_NONE) {
  120. debug("%s: Failed to get base address\n", __func__);
  121. return -EINVAL;
  122. }
  123. priv->pin_cnt = fdtdec_get_int(blob, node, "pin-count",
  124. MVEBU_MAX_PINS_PER_BANK);
  125. priv->max_func = fdtdec_get_int(blob, node, "max-func",
  126. MVEBU_MAX_FUNC);
  127. priv->bank_name = fdt_getprop(blob, node, "bank-name", NULL);
  128. priv->reg_direction = 1;
  129. if (fdtdec_get_bool(blob, node, "reverse-reg"))
  130. priv->reg_direction = -1;
  131. return mvebu_pinctrl_set_state_all(dev, dev);
  132. }
  133. static struct pinctrl_ops mvebu_pinctrl_ops = {
  134. .set_state = mvebu_pinctrl_set_state
  135. };
  136. static const struct udevice_id mvebu_pinctrl_ids[] = {
  137. { .compatible = "marvell,mvebu-pinctrl" },
  138. { .compatible = "marvell,armada-ap806-pinctrl" },
  139. { .compatible = "marvell,a70x0-pinctrl" },
  140. { .compatible = "marvell,a80x0-cp0-pinctrl" },
  141. { .compatible = "marvell,a80x0-cp1-pinctrl" },
  142. { }
  143. };
  144. U_BOOT_DRIVER(pinctrl_mvebu) = {
  145. .name = "mvebu_pinctrl",
  146. .id = UCLASS_PINCTRL,
  147. .of_match = mvebu_pinctrl_ids,
  148. .priv_auto_alloc_size = sizeof(struct mvebu_pinctrl_priv),
  149. .ops = &mvebu_pinctrl_ops,
  150. .probe = mvebu_pinctl_probe
  151. };