fdt_gpio_starfive.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2022 Starfive
  5. *
  6. * Authors:
  7. * Minda.chen <Minda.chen@starfivetech.com>
  8. */
  9. #include <sbi/riscv_io.h>
  10. #include <sbi/sbi_error.h>
  11. #include <sbi/sbi_console.h>
  12. #include <sbi_utils/fdt/fdt_helper.h>
  13. #include <sbi_utils/gpio/fdt_gpio.h>
  14. #define STARFIVE_GPIO_CHIP_MAX 2
  15. #define STARFIVE_GPIO_PINS_DEF 64
  16. #define STARFIVE_GPIO_OUTVAL 0x40
  17. #define STARFIVE_GPIO_MASK 0xff
  18. #define STARFIVE_GPIO_REG_SHIFT_MASK 0x3
  19. #define STARFIVE_GPIO_SHIFT_BITS 0x3
  20. struct starfive_gpio_chip {
  21. unsigned long addr;
  22. struct gpio_chip chip;
  23. };
  24. static unsigned int starfive_gpio_chip_count;
  25. static struct starfive_gpio_chip starfive_gpio_chip_array[STARFIVE_GPIO_CHIP_MAX];
  26. static int starfive_gpio_direction_output(struct gpio_pin *gp, int value)
  27. {
  28. u32 val;
  29. unsigned long reg_addr;
  30. u32 bit_mask, shift_bits;
  31. struct starfive_gpio_chip *chip =
  32. container_of(gp->chip, struct starfive_gpio_chip, chip);
  33. /* set out en*/
  34. reg_addr = chip->addr + gp->offset;
  35. reg_addr &= ~(STARFIVE_GPIO_REG_SHIFT_MASK);
  36. val = readl((void *)(reg_addr));
  37. shift_bits = (gp->offset & STARFIVE_GPIO_REG_SHIFT_MASK)
  38. << STARFIVE_GPIO_SHIFT_BITS;
  39. bit_mask = STARFIVE_GPIO_MASK << shift_bits;
  40. val = readl((void *)reg_addr);
  41. val &= ~bit_mask;
  42. writel(val, (void *)reg_addr);
  43. return 0;
  44. }
  45. static void starfive_gpio_set(struct gpio_pin *gp, int value)
  46. {
  47. u32 val;
  48. unsigned long reg_addr;
  49. u32 bit_mask, shift_bits;
  50. struct starfive_gpio_chip *chip =
  51. container_of(gp->chip, struct starfive_gpio_chip, chip);
  52. reg_addr = chip->addr + gp->offset;
  53. reg_addr &= ~(STARFIVE_GPIO_REG_SHIFT_MASK);
  54. shift_bits = (gp->offset & STARFIVE_GPIO_REG_SHIFT_MASK)
  55. << STARFIVE_GPIO_SHIFT_BITS;
  56. bit_mask = STARFIVE_GPIO_MASK << shift_bits;
  57. /* set output value */
  58. val = readl((void *)(reg_addr + STARFIVE_GPIO_OUTVAL));
  59. val &= ~bit_mask;
  60. val |= value << shift_bits;
  61. writel(val, (void *)(reg_addr + STARFIVE_GPIO_OUTVAL));
  62. }
  63. extern struct fdt_gpio fdt_gpio_starfive;
  64. static int starfive_gpio_init(void *fdt, int nodeoff, u32 phandle,
  65. const struct fdt_match *match)
  66. {
  67. int rc;
  68. struct starfive_gpio_chip *chip;
  69. u64 addr;
  70. if (starfive_gpio_chip_count >= STARFIVE_GPIO_CHIP_MAX)
  71. return SBI_ENOSPC;
  72. chip = &starfive_gpio_chip_array[starfive_gpio_chip_count];
  73. rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL);
  74. if (rc)
  75. return rc;
  76. chip->addr = addr;
  77. chip->chip.driver = &fdt_gpio_starfive;
  78. chip->chip.id = phandle;
  79. chip->chip.ngpio = STARFIVE_GPIO_PINS_DEF;
  80. chip->chip.direction_output = starfive_gpio_direction_output;
  81. chip->chip.set = starfive_gpio_set;
  82. rc = gpio_chip_add(&chip->chip);
  83. if (rc)
  84. return rc;
  85. starfive_gpio_chip_count++;
  86. return 0;
  87. }
  88. static const struct fdt_match starfive_gpio_match[] = {
  89. { .compatible = "starfive,jh7110-sys-pinctrl" },
  90. { .compatible = "starfive,iomux-pinctrl" },
  91. { },
  92. };
  93. struct fdt_gpio fdt_gpio_starfive = {
  94. .match_table = starfive_gpio_match,
  95. .xlate = fdt_gpio_simple_xlate,
  96. .init = starfive_gpio_init,
  97. };