dwapb_gpio.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * (C) Copyright 2015 Marek Vasut <marex@denx.de>
  3. *
  4. * DesignWare APB GPIO driver
  5. *
  6. * SPDX-License-Identifier: GPL-2.0+
  7. */
  8. #include <common.h>
  9. #include <malloc.h>
  10. #include <asm/arch/gpio.h>
  11. #include <asm/gpio.h>
  12. #include <asm/io.h>
  13. #include <dm.h>
  14. #include <dm/device-internal.h>
  15. #include <dm/lists.h>
  16. #include <dm/root.h>
  17. #include <errno.h>
  18. DECLARE_GLOBAL_DATA_PTR;
  19. #define GPIO_SWPORT_DR(p) (0x00 + (p) * 0xc)
  20. #define GPIO_SWPORT_DDR(p) (0x04 + (p) * 0xc)
  21. #define GPIO_INTEN 0x30
  22. #define GPIO_INTMASK 0x34
  23. #define GPIO_INTTYPE_LEVEL 0x38
  24. #define GPIO_INT_POLARITY 0x3c
  25. #define GPIO_INTSTATUS 0x40
  26. #define GPIO_PORTA_DEBOUNCE 0x48
  27. #define GPIO_PORTA_EOI 0x4c
  28. #define GPIO_EXT_PORT(p) (0x50 + (p) * 4)
  29. struct gpio_dwapb_platdata {
  30. const char *name;
  31. int bank;
  32. int pins;
  33. fdt_addr_t base;
  34. };
  35. static int dwapb_gpio_direction_input(struct udevice *dev, unsigned pin)
  36. {
  37. struct gpio_dwapb_platdata *plat = dev_get_platdata(dev);
  38. clrbits_le32(plat->base + GPIO_SWPORT_DDR(plat->bank), 1 << pin);
  39. return 0;
  40. }
  41. static int dwapb_gpio_direction_output(struct udevice *dev, unsigned pin,
  42. int val)
  43. {
  44. struct gpio_dwapb_platdata *plat = dev_get_platdata(dev);
  45. setbits_le32(plat->base + GPIO_SWPORT_DDR(plat->bank), 1 << pin);
  46. if (val)
  47. setbits_le32(plat->base + GPIO_SWPORT_DR(plat->bank), 1 << pin);
  48. else
  49. clrbits_le32(plat->base + GPIO_SWPORT_DR(plat->bank), 1 << pin);
  50. return 0;
  51. }
  52. static int dwapb_gpio_get_value(struct udevice *dev, unsigned pin)
  53. {
  54. struct gpio_dwapb_platdata *plat = dev_get_platdata(dev);
  55. return !!(readl(plat->base + GPIO_EXT_PORT(plat->bank)) & (1 << pin));
  56. }
  57. static int dwapb_gpio_set_value(struct udevice *dev, unsigned pin, int val)
  58. {
  59. struct gpio_dwapb_platdata *plat = dev_get_platdata(dev);
  60. if (val)
  61. setbits_le32(plat->base + GPIO_SWPORT_DR(plat->bank), 1 << pin);
  62. else
  63. clrbits_le32(plat->base + GPIO_SWPORT_DR(plat->bank), 1 << pin);
  64. return 0;
  65. }
  66. static const struct dm_gpio_ops gpio_dwapb_ops = {
  67. .direction_input = dwapb_gpio_direction_input,
  68. .direction_output = dwapb_gpio_direction_output,
  69. .get_value = dwapb_gpio_get_value,
  70. .set_value = dwapb_gpio_set_value,
  71. };
  72. static int gpio_dwapb_probe(struct udevice *dev)
  73. {
  74. struct gpio_dev_priv *priv = dev_get_uclass_priv(dev);
  75. struct gpio_dwapb_platdata *plat = dev->platdata;
  76. if (!plat)
  77. return 0;
  78. priv->gpio_count = plat->pins;
  79. priv->bank_name = plat->name;
  80. return 0;
  81. }
  82. static int gpio_dwapb_bind(struct udevice *dev)
  83. {
  84. struct gpio_dwapb_platdata *plat = dev_get_platdata(dev);
  85. const void *blob = gd->fdt_blob;
  86. struct udevice *subdev;
  87. fdt_addr_t base;
  88. int ret, node, bank = 0;
  89. /* If this is a child device, there is nothing to do here */
  90. if (plat)
  91. return 0;
  92. base = fdtdec_get_addr(blob, dev->of_offset, "reg");
  93. if (base == FDT_ADDR_T_NONE) {
  94. debug("Can't get the GPIO register base address\n");
  95. return -ENXIO;
  96. }
  97. for (node = fdt_first_subnode(blob, dev->of_offset);
  98. node > 0;
  99. node = fdt_next_subnode(blob, node)) {
  100. if (!fdtdec_get_bool(blob, node, "gpio-controller"))
  101. continue;
  102. plat = NULL;
  103. plat = calloc(1, sizeof(*plat));
  104. if (!plat)
  105. return -ENOMEM;
  106. plat->base = base;
  107. plat->bank = bank;
  108. plat->pins = fdtdec_get_int(blob, node, "snps,nr-gpios", 0);
  109. plat->name = fdt_stringlist_get(blob, node, "bank-name", 0,
  110. NULL);
  111. if (ret)
  112. goto err;
  113. ret = device_bind(dev, dev->driver, plat->name,
  114. plat, -1, &subdev);
  115. if (ret)
  116. goto err;
  117. subdev->of_offset = node;
  118. bank++;
  119. }
  120. return 0;
  121. err:
  122. free(plat);
  123. return ret;
  124. }
  125. static const struct udevice_id gpio_dwapb_ids[] = {
  126. { .compatible = "snps,dw-apb-gpio" },
  127. { }
  128. };
  129. U_BOOT_DRIVER(gpio_dwapb) = {
  130. .name = "gpio-dwapb",
  131. .id = UCLASS_GPIO,
  132. .of_match = gpio_dwapb_ids,
  133. .ops = &gpio_dwapb_ops,
  134. .bind = gpio_dwapb_bind,
  135. .probe = gpio_dwapb_probe,
  136. };