pinctrl-exynos.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Exynos pinctrl driver common code.
  4. * Copyright (C) 2016 Samsung Electronics
  5. * Thomas Abraham <thomas.ab@samsung.com>
  6. */
  7. #include <common.h>
  8. #include <dm.h>
  9. #include <errno.h>
  10. #include <asm/io.h>
  11. #include "pinctrl-exynos.h"
  12. DECLARE_GLOBAL_DATA_PTR;
  13. /**
  14. * exynos_pinctrl_setup_peri: setup pinctrl for a peripheral.
  15. * conf: soc specific pin configuration data array
  16. * num_conf: number of configurations in the conf array.
  17. * base: base address of the pin controller.
  18. */
  19. void exynos_pinctrl_setup_peri(struct exynos_pinctrl_config_data *conf,
  20. unsigned int num_conf, unsigned long base)
  21. {
  22. unsigned int idx, val;
  23. for (idx = 0; idx < num_conf; idx++) {
  24. val = readl(base + conf[idx].offset);
  25. val &= ~(conf[idx].mask);
  26. val |= conf[idx].value;
  27. writel(val, base + conf[idx].offset);
  28. }
  29. }
  30. /* given a pin-name, return the address of pin config registers */
  31. static unsigned long pin_to_bank_base(struct udevice *dev, const char *pin_name,
  32. u32 *pin)
  33. {
  34. struct exynos_pinctrl_priv *priv = dev_get_priv(dev);
  35. const struct samsung_pin_ctrl *pin_ctrl = priv->pin_ctrl;
  36. const struct samsung_pin_bank_data *bank_data = pin_ctrl->pin_banks;
  37. u32 nr_banks = pin_ctrl->nr_banks, idx = 0;
  38. char bank[10];
  39. /*
  40. * The format of the pin name is <bank name>-<pin_number>.
  41. * Example: gpa0-4 (gpa0 is the bank name and 4 is the pin number.
  42. */
  43. while (pin_name[idx] != '-') {
  44. bank[idx] = pin_name[idx];
  45. idx++;
  46. }
  47. bank[idx] = '\0';
  48. *pin = pin_name[++idx] - '0';
  49. /* lookup the pin bank data using the pin bank name */
  50. for (idx = 0; idx < nr_banks; idx++)
  51. if (!strcmp(bank, bank_data[idx].name))
  52. break;
  53. return priv->base + bank_data[idx].offset;
  54. }
  55. /**
  56. * exynos_pinctrl_set_state: configure a pin state.
  57. * dev: the pinctrl device to be configured.
  58. * config: the state to be configured.
  59. */
  60. int exynos_pinctrl_set_state(struct udevice *dev, struct udevice *config)
  61. {
  62. const void *fdt = gd->fdt_blob;
  63. int node = dev_of_offset(config);
  64. unsigned int count, idx, pin_num;
  65. unsigned int pinfunc, pinpud, pindrv;
  66. unsigned long reg, value;
  67. const char *name;
  68. /*
  69. * refer to the following document for the pinctrl bindings
  70. * linux/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
  71. */
  72. count = fdt_stringlist_count(fdt, node, "samsung,pins");
  73. if (count <= 0)
  74. return -EINVAL;
  75. pinfunc = fdtdec_get_int(fdt, node, "samsung,pin-function", -1);
  76. pinpud = fdtdec_get_int(fdt, node, "samsung,pin-pud", -1);
  77. pindrv = fdtdec_get_int(fdt, node, "samsung,pin-drv", -1);
  78. for (idx = 0; idx < count; idx++) {
  79. name = fdt_stringlist_get(fdt, node, "samsung,pins", idx, NULL);
  80. if (!name)
  81. continue;
  82. reg = pin_to_bank_base(dev, name, &pin_num);
  83. if (pinfunc != -1) {
  84. value = readl(reg + PIN_CON);
  85. value &= ~(0xf << (pin_num << 2));
  86. value |= (pinfunc << (pin_num << 2));
  87. writel(value, reg + PIN_CON);
  88. }
  89. if (pinpud != -1) {
  90. value = readl(reg + PIN_PUD);
  91. value &= ~(0x3 << (pin_num << 1));
  92. value |= (pinpud << (pin_num << 1));
  93. writel(value, reg + PIN_PUD);
  94. }
  95. if (pindrv != -1) {
  96. value = readl(reg + PIN_DRV);
  97. value &= ~(0x3 << (pin_num << 1));
  98. value |= (pindrv << (pin_num << 1));
  99. writel(value, reg + PIN_DRV);
  100. }
  101. }
  102. return 0;
  103. }
  104. int exynos_pinctrl_probe(struct udevice *dev)
  105. {
  106. struct exynos_pinctrl_priv *priv;
  107. fdt_addr_t base;
  108. priv = dev_get_priv(dev);
  109. if (!priv)
  110. return -EINVAL;
  111. base = devfdt_get_addr(dev);
  112. if (base == FDT_ADDR_T_NONE)
  113. return -EINVAL;
  114. priv->base = base;
  115. priv->pin_ctrl = (struct samsung_pin_ctrl *)dev_get_driver_data(dev) +
  116. dev->req_seq;
  117. return 0;
  118. }