mpc85xx_gpio.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. * (C) Copyright 2016
  3. * Mario Six, Guntermann & Drunck GmbH, six@gdsys.de
  4. *
  5. * based on arch/powerpc/include/asm/mpc85xx_gpio.h, which is
  6. *
  7. * Copyright 2010 eXMeritus, A Boeing Company
  8. *
  9. * SPDX-License-Identifier: GPL-2.0+
  10. */
  11. #include <common.h>
  12. #include <dm.h>
  13. #include <asm/gpio.h>
  14. #include <mapmem.h>
  15. DECLARE_GLOBAL_DATA_PTR;
  16. struct ccsr_gpio {
  17. u32 gpdir;
  18. u32 gpodr;
  19. u32 gpdat;
  20. u32 gpier;
  21. u32 gpimr;
  22. u32 gpicr;
  23. };
  24. struct mpc85xx_gpio_data {
  25. /* The bank's register base in memory */
  26. struct ccsr_gpio __iomem *base;
  27. /* The address of the registers; used to identify the bank */
  28. ulong addr;
  29. /* The GPIO count of the bank */
  30. uint gpio_count;
  31. /* The GPDAT register cannot be used to determine the value of output
  32. * pins on MPC8572/MPC8536, so we shadow it and use the shadowed value
  33. * for output pins */
  34. u32 dat_shadow;
  35. };
  36. inline u32 gpio_mask(unsigned gpio) {
  37. return (1U << (31 - (gpio)));
  38. }
  39. static inline u32 mpc85xx_gpio_get_val(struct ccsr_gpio *base, u32 mask)
  40. {
  41. return in_be32(&base->gpdat) & mask;
  42. }
  43. static inline u32 mpc85xx_gpio_get_dir(struct ccsr_gpio *base, u32 mask)
  44. {
  45. return in_be32(&base->gpdir) & mask;
  46. }
  47. static inline void mpc85xx_gpio_set_in(struct ccsr_gpio *base, u32 gpios)
  48. {
  49. clrbits_be32(&base->gpdat, gpios);
  50. /* GPDIR register 0 -> input */
  51. clrbits_be32(&base->gpdir, gpios);
  52. }
  53. static inline void mpc85xx_gpio_set_low(struct ccsr_gpio *base, u32 gpios)
  54. {
  55. clrbits_be32(&base->gpdat, gpios);
  56. /* GPDIR register 1 -> output */
  57. setbits_be32(&base->gpdir, gpios);
  58. }
  59. static inline void mpc85xx_gpio_set_high(struct ccsr_gpio *base, u32 gpios)
  60. {
  61. setbits_be32(&base->gpdat, gpios);
  62. /* GPDIR register 1 -> output */
  63. setbits_be32(&base->gpdir, gpios);
  64. }
  65. static inline int mpc85xx_gpio_open_drain_val(struct ccsr_gpio *base, u32 mask)
  66. {
  67. return in_be32(&base->gpodr) & mask;
  68. }
  69. static inline void mpc85xx_gpio_open_drain_on(struct ccsr_gpio *base, u32
  70. gpios)
  71. {
  72. /* GPODR register 1 -> open drain on */
  73. setbits_be32(&base->gpodr, gpios);
  74. }
  75. static inline void mpc85xx_gpio_open_drain_off(struct ccsr_gpio *base,
  76. u32 gpios)
  77. {
  78. /* GPODR register 0 -> open drain off (actively driven) */
  79. clrbits_be32(&base->gpodr, gpios);
  80. }
  81. static int mpc85xx_gpio_direction_input(struct udevice *dev, unsigned gpio)
  82. {
  83. struct mpc85xx_gpio_data *data = dev_get_priv(dev);
  84. mpc85xx_gpio_set_in(data->base, gpio_mask(gpio));
  85. return 0;
  86. }
  87. static int mpc85xx_gpio_set_value(struct udevice *dev, unsigned gpio,
  88. int value)
  89. {
  90. struct mpc85xx_gpio_data *data = dev_get_priv(dev);
  91. if (value) {
  92. data->dat_shadow |= gpio_mask(gpio);
  93. mpc85xx_gpio_set_high(data->base, gpio_mask(gpio));
  94. } else {
  95. data->dat_shadow &= ~gpio_mask(gpio);
  96. mpc85xx_gpio_set_low(data->base, gpio_mask(gpio));
  97. }
  98. return 0;
  99. }
  100. static int mpc85xx_gpio_direction_output(struct udevice *dev, unsigned gpio,
  101. int value)
  102. {
  103. return mpc85xx_gpio_set_value(dev, gpio, value);
  104. }
  105. static int mpc85xx_gpio_get_value(struct udevice *dev, unsigned gpio)
  106. {
  107. struct mpc85xx_gpio_data *data = dev_get_priv(dev);
  108. if (!!mpc85xx_gpio_get_dir(data->base, gpio_mask(gpio))) {
  109. /* Output -> use shadowed value */
  110. return !!(data->dat_shadow & gpio_mask(gpio));
  111. } else {
  112. /* Input -> read value from GPDAT register */
  113. return !!mpc85xx_gpio_get_val(data->base, gpio_mask(gpio));
  114. }
  115. }
  116. static int mpc85xx_gpio_get_open_drain(struct udevice *dev, unsigned gpio)
  117. {
  118. struct mpc85xx_gpio_data *data = dev_get_priv(dev);
  119. return !!mpc85xx_gpio_open_drain_val(data->base, gpio_mask(gpio));
  120. }
  121. static int mpc85xx_gpio_set_open_drain(struct udevice *dev, unsigned gpio,
  122. int value)
  123. {
  124. struct mpc85xx_gpio_data *data = dev_get_priv(dev);
  125. if (value) {
  126. mpc85xx_gpio_open_drain_on(data->base, gpio_mask(gpio));
  127. } else {
  128. mpc85xx_gpio_open_drain_off(data->base, gpio_mask(gpio));
  129. }
  130. return 0;
  131. }
  132. static int mpc85xx_gpio_get_function(struct udevice *dev, unsigned gpio)
  133. {
  134. struct mpc85xx_gpio_data *data = dev_get_priv(dev);
  135. int dir;
  136. dir = !!mpc85xx_gpio_get_dir(data->base, gpio_mask(gpio));
  137. return dir ? GPIOF_OUTPUT : GPIOF_INPUT;
  138. }
  139. #if CONFIG_IS_ENABLED(OF_CONTROL)
  140. static int mpc85xx_gpio_ofdata_to_platdata(struct udevice *dev) {
  141. struct mpc85xx_gpio_plat *plat = dev_get_platdata(dev);
  142. fdt_addr_t addr;
  143. fdt_size_t size;
  144. addr = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, dev->of_offset,
  145. "reg", 0, &size, false);
  146. plat->addr = addr;
  147. plat->size = size;
  148. plat->ngpios = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
  149. "ngpios", 32);
  150. return 0;
  151. }
  152. #endif
  153. static int mpc85xx_gpio_platdata_to_priv(struct udevice *dev)
  154. {
  155. struct mpc85xx_gpio_data *priv = dev_get_priv(dev);
  156. struct mpc85xx_gpio_plat *plat = dev_get_platdata(dev);
  157. unsigned long size = plat->size;
  158. if (size == 0)
  159. size = 0x100;
  160. priv->addr = plat->addr;
  161. priv->base = map_sysmem(CONFIG_SYS_IMMR + plat->addr, size);
  162. if (!priv->base)
  163. return -ENOMEM;
  164. priv->gpio_count = plat->ngpios;
  165. priv->dat_shadow = 0;
  166. return 0;
  167. }
  168. static int mpc85xx_gpio_probe(struct udevice *dev)
  169. {
  170. struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  171. struct mpc85xx_gpio_data *data = dev_get_priv(dev);
  172. char name[32], *str;
  173. mpc85xx_gpio_platdata_to_priv(dev);
  174. snprintf(name, sizeof(name), "MPC@%lx_", data->addr);
  175. str = strdup(name);
  176. if (!str)
  177. return -ENOMEM;
  178. uc_priv->bank_name = str;
  179. uc_priv->gpio_count = data->gpio_count;
  180. return 0;
  181. }
  182. static const struct dm_gpio_ops gpio_mpc85xx_ops = {
  183. .direction_input = mpc85xx_gpio_direction_input,
  184. .direction_output = mpc85xx_gpio_direction_output,
  185. .get_value = mpc85xx_gpio_get_value,
  186. .set_value = mpc85xx_gpio_set_value,
  187. .get_open_drain = mpc85xx_gpio_get_open_drain,
  188. .set_open_drain = mpc85xx_gpio_set_open_drain,
  189. .get_function = mpc85xx_gpio_get_function,
  190. };
  191. static const struct udevice_id mpc85xx_gpio_ids[] = {
  192. { .compatible = "fsl,pq3-gpio" },
  193. { /* sentinel */ }
  194. };
  195. U_BOOT_DRIVER(gpio_mpc85xx) = {
  196. .name = "gpio_mpc85xx",
  197. .id = UCLASS_GPIO,
  198. .ops = &gpio_mpc85xx_ops,
  199. #if CONFIG_IS_ENABLED(OF_CONTROL)
  200. .ofdata_to_platdata = mpc85xx_gpio_ofdata_to_platdata,
  201. .platdata_auto_alloc_size = sizeof(struct mpc85xx_gpio_plat),
  202. .of_match = mpc85xx_gpio_ids,
  203. #endif
  204. .probe = mpc85xx_gpio_probe,
  205. .priv_auto_alloc_size = sizeof(struct mpc85xx_gpio_data),
  206. };