nmk_gpio.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /* Copyright (C) 2019 Stephan Gerhold */
  3. #include <common.h>
  4. #include <dm.h>
  5. #include <asm/gpio.h>
  6. #include <asm/io.h>
  7. struct nmk_gpio_regs {
  8. u32 dat; /* data */
  9. u32 dats; /* data set */
  10. u32 datc; /* data clear */
  11. u32 pdis; /* pull disable */
  12. u32 dir; /* direction */
  13. u32 dirs; /* direction set */
  14. u32 dirc; /* direction clear */
  15. u32 slpm; /* sleep mode */
  16. u32 afsla; /* alternate function select A */
  17. u32 afslb; /* alternate function select B */
  18. u32 lowemi; /* low EMI mode */
  19. };
  20. struct nmk_gpio {
  21. struct nmk_gpio_regs *regs;
  22. };
  23. static int nmk_gpio_get_value(struct udevice *dev, unsigned offset)
  24. {
  25. struct nmk_gpio *priv = dev_get_priv(dev);
  26. return !!(readl(&priv->regs->dat) & BIT(offset));
  27. }
  28. static int nmk_gpio_set_value(struct udevice *dev, unsigned offset, int value)
  29. {
  30. struct nmk_gpio *priv = dev_get_priv(dev);
  31. if (value)
  32. writel(BIT(offset), &priv->regs->dats);
  33. else
  34. writel(BIT(offset), &priv->regs->datc);
  35. return 0;
  36. }
  37. static int nmk_gpio_get_function(struct udevice *dev, unsigned offset)
  38. {
  39. struct nmk_gpio *priv = dev_get_priv(dev);
  40. if (readl(&priv->regs->afsla) & BIT(offset) ||
  41. readl(&priv->regs->afslb) & BIT(offset))
  42. return GPIOF_FUNC;
  43. if (readl(&priv->regs->dir) & BIT(offset))
  44. return GPIOF_OUTPUT;
  45. else
  46. return GPIOF_INPUT;
  47. }
  48. static int nmk_gpio_direction_input(struct udevice *dev, unsigned offset)
  49. {
  50. struct nmk_gpio *priv = dev_get_priv(dev);
  51. writel(BIT(offset), &priv->regs->dirc);
  52. return 0;
  53. }
  54. static int nmk_gpio_direction_output(struct udevice *dev, unsigned offset,
  55. int value)
  56. {
  57. struct nmk_gpio *priv = dev_get_priv(dev);
  58. writel(BIT(offset), &priv->regs->dirs);
  59. return nmk_gpio_set_value(dev, offset, value);
  60. }
  61. static const struct dm_gpio_ops nmk_gpio_ops = {
  62. .get_value = nmk_gpio_get_value,
  63. .set_value = nmk_gpio_set_value,
  64. .get_function = nmk_gpio_get_function,
  65. .direction_input = nmk_gpio_direction_input,
  66. .direction_output = nmk_gpio_direction_output,
  67. };
  68. static int nmk_gpio_probe(struct udevice *dev)
  69. {
  70. struct nmk_gpio *priv = dev_get_priv(dev);
  71. struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  72. char buf[20];
  73. u32 bank;
  74. int ret;
  75. priv->regs = dev_read_addr_ptr(dev);
  76. if (!priv->regs)
  77. return -EINVAL;
  78. ret = dev_read_u32(dev, "gpio-bank", &bank);
  79. if (ret < 0) {
  80. printf("nmk_gpio(%s): Failed to read gpio-bank\n", dev->name);
  81. return ret;
  82. }
  83. sprintf(buf, "nmk%u-gpio", bank);
  84. uc_priv->bank_name = strdup(buf);
  85. if (!uc_priv->bank_name)
  86. return -ENOMEM;
  87. uc_priv->gpio_count = sizeof(priv->regs->dat) * BITS_PER_BYTE;
  88. return 0;
  89. }
  90. static const struct udevice_id nmk_gpio_ids[] = {
  91. { .compatible = "st,nomadik-gpio" },
  92. { }
  93. };
  94. U_BOOT_DRIVER(gpio_nmk) = {
  95. .name = "nmk_gpio",
  96. .id = UCLASS_GPIO,
  97. .of_match = nmk_gpio_ids,
  98. .probe = nmk_gpio_probe,
  99. .ops = &nmk_gpio_ops,
  100. .priv_auto = sizeof(struct nmk_gpio),
  101. };