bcm2835_gpio.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * Copyright (C) 2012 Vikram Narayananan
  3. * <vikram186@gmail.com>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <dm.h>
  9. #include <errno.h>
  10. #include <asm/gpio.h>
  11. #include <asm/io.h>
  12. #include <fdtdec.h>
  13. struct bcm2835_gpios {
  14. struct bcm2835_gpio_regs *reg;
  15. };
  16. static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio)
  17. {
  18. struct bcm2835_gpios *gpios = dev_get_priv(dev);
  19. unsigned val;
  20. val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
  21. val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio));
  22. val |= (BCM2835_GPIO_INPUT << BCM2835_GPIO_FSEL_SHIFT(gpio));
  23. writel(val, &gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
  24. return 0;
  25. }
  26. static int bcm2835_gpio_direction_output(struct udevice *dev, unsigned gpio,
  27. int value)
  28. {
  29. struct bcm2835_gpios *gpios = dev_get_priv(dev);
  30. unsigned val;
  31. gpio_set_value(gpio, value);
  32. val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
  33. val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio));
  34. val |= (BCM2835_GPIO_OUTPUT << BCM2835_GPIO_FSEL_SHIFT(gpio));
  35. writel(val, &gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
  36. return 0;
  37. }
  38. static int bcm2835_get_value(const struct bcm2835_gpios *gpios, unsigned gpio)
  39. {
  40. unsigned val;
  41. val = readl(&gpios->reg->gplev[BCM2835_GPIO_COMMON_BANK(gpio)]);
  42. return (val >> BCM2835_GPIO_COMMON_SHIFT(gpio)) & 0x1;
  43. }
  44. static int bcm2835_gpio_get_value(struct udevice *dev, unsigned gpio)
  45. {
  46. const struct bcm2835_gpios *gpios = dev_get_priv(dev);
  47. return bcm2835_get_value(gpios, gpio);
  48. }
  49. static int bcm2835_gpio_set_value(struct udevice *dev, unsigned gpio,
  50. int value)
  51. {
  52. struct bcm2835_gpios *gpios = dev_get_priv(dev);
  53. u32 *output_reg = value ? gpios->reg->gpset : gpios->reg->gpclr;
  54. writel(1 << BCM2835_GPIO_COMMON_SHIFT(gpio),
  55. &output_reg[BCM2835_GPIO_COMMON_BANK(gpio)]);
  56. return 0;
  57. }
  58. int bcm2835_gpio_get_func_id(struct udevice *dev, unsigned gpio)
  59. {
  60. struct bcm2835_gpios *gpios = dev_get_priv(dev);
  61. u32 val;
  62. val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
  63. return (val >> BCM2835_GPIO_FSEL_SHIFT(gpio) & BCM2835_GPIO_FSEL_MASK);
  64. }
  65. static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset)
  66. {
  67. int funcid = bcm2835_gpio_get_func_id(dev, offset);
  68. switch (funcid) {
  69. case BCM2835_GPIO_OUTPUT:
  70. return GPIOF_OUTPUT;
  71. case BCM2835_GPIO_INPUT:
  72. return GPIOF_INPUT;
  73. default:
  74. return GPIOF_FUNC;
  75. }
  76. }
  77. static const struct dm_gpio_ops gpio_bcm2835_ops = {
  78. .direction_input = bcm2835_gpio_direction_input,
  79. .direction_output = bcm2835_gpio_direction_output,
  80. .get_value = bcm2835_gpio_get_value,
  81. .set_value = bcm2835_gpio_set_value,
  82. .get_function = bcm2835_gpio_get_function,
  83. };
  84. static int bcm2835_gpio_probe(struct udevice *dev)
  85. {
  86. struct bcm2835_gpios *gpios = dev_get_priv(dev);
  87. struct bcm2835_gpio_platdata *plat = dev_get_platdata(dev);
  88. struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  89. uc_priv->bank_name = "GPIO";
  90. uc_priv->gpio_count = BCM2835_GPIO_COUNT;
  91. gpios->reg = (struct bcm2835_gpio_regs *)plat->base;
  92. return 0;
  93. }
  94. #if CONFIG_IS_ENABLED(OF_CONTROL)
  95. static const struct udevice_id bcm2835_gpio_id[] = {
  96. {.compatible = "brcm,bcm2835-gpio"},
  97. {}
  98. };
  99. static int bcm2835_gpio_ofdata_to_platdata(struct udevice *dev)
  100. {
  101. struct bcm2835_gpio_platdata *plat = dev_get_platdata(dev);
  102. fdt_addr_t addr;
  103. addr = dev_get_addr(dev);
  104. if (addr == FDT_ADDR_T_NONE)
  105. return -EINVAL;
  106. plat->base = addr;
  107. return 0;
  108. }
  109. #endif
  110. U_BOOT_DRIVER(gpio_bcm2835) = {
  111. .name = "gpio_bcm2835",
  112. .id = UCLASS_GPIO,
  113. .of_match = of_match_ptr(bcm2835_gpio_id),
  114. .ofdata_to_platdata = of_match_ptr(bcm2835_gpio_ofdata_to_platdata),
  115. .platdata_auto_alloc_size = sizeof(struct bcm2835_gpio_platdata),
  116. .ops = &gpio_bcm2835_ops,
  117. .probe = bcm2835_gpio_probe,
  118. .flags = DM_FLAG_PRE_RELOC,
  119. .priv_auto_alloc_size = sizeof(struct bcm2835_gpios),
  120. };