mpc8xxx_gpio.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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 <mapmem.h>
  14. #include <asm/gpio.h>
  15. struct ccsr_gpio {
  16. u32 gpdir;
  17. u32 gpodr;
  18. u32 gpdat;
  19. u32 gpier;
  20. u32 gpimr;
  21. u32 gpicr;
  22. };
  23. struct mpc8xxx_gpio_data {
  24. /* The bank's register base in memory */
  25. struct ccsr_gpio __iomem *base;
  26. /* The address of the registers; used to identify the bank */
  27. ulong addr;
  28. /* The GPIO count of the bank */
  29. uint gpio_count;
  30. /* The GPDAT register cannot be used to determine the value of output
  31. * pins on MPC8572/MPC8536, so we shadow it and use the shadowed value
  32. * for output pins
  33. */
  34. u32 dat_shadow;
  35. ulong type;
  36. };
  37. enum {
  38. MPC8XXX_GPIO_TYPE,
  39. MPC5121_GPIO_TYPE,
  40. };
  41. inline u32 gpio_mask(uint gpio)
  42. {
  43. return (1U << (31 - (gpio)));
  44. }
  45. static inline u32 mpc8xxx_gpio_get_val(struct ccsr_gpio *base, u32 mask)
  46. {
  47. return in_be32(&base->gpdat) & mask;
  48. }
  49. static inline u32 mpc8xxx_gpio_get_dir(struct ccsr_gpio *base, u32 mask)
  50. {
  51. return in_be32(&base->gpdir) & mask;
  52. }
  53. static inline void mpc8xxx_gpio_set_in(struct ccsr_gpio *base, u32 gpios)
  54. {
  55. clrbits_be32(&base->gpdat, gpios);
  56. /* GPDIR register 0 -> input */
  57. clrbits_be32(&base->gpdir, gpios);
  58. }
  59. static inline void mpc8xxx_gpio_set_low(struct ccsr_gpio *base, u32 gpios)
  60. {
  61. clrbits_be32(&base->gpdat, gpios);
  62. /* GPDIR register 1 -> output */
  63. setbits_be32(&base->gpdir, gpios);
  64. }
  65. static inline void mpc8xxx_gpio_set_high(struct ccsr_gpio *base, u32 gpios)
  66. {
  67. setbits_be32(&base->gpdat, gpios);
  68. /* GPDIR register 1 -> output */
  69. setbits_be32(&base->gpdir, gpios);
  70. }
  71. static inline int mpc8xxx_gpio_open_drain_val(struct ccsr_gpio *base, u32 mask)
  72. {
  73. return in_be32(&base->gpodr) & mask;
  74. }
  75. static inline void mpc8xxx_gpio_open_drain_on(struct ccsr_gpio *base, u32
  76. gpios)
  77. {
  78. /* GPODR register 1 -> open drain on */
  79. setbits_be32(&base->gpodr, gpios);
  80. }
  81. static inline void mpc8xxx_gpio_open_drain_off(struct ccsr_gpio *base,
  82. u32 gpios)
  83. {
  84. /* GPODR register 0 -> open drain off (actively driven) */
  85. clrbits_be32(&base->gpodr, gpios);
  86. }
  87. static int mpc8xxx_gpio_direction_input(struct udevice *dev, uint gpio)
  88. {
  89. struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
  90. mpc8xxx_gpio_set_in(data->base, gpio_mask(gpio));
  91. return 0;
  92. }
  93. static int mpc8xxx_gpio_set_value(struct udevice *dev, uint gpio, int value)
  94. {
  95. struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
  96. if (value) {
  97. data->dat_shadow |= gpio_mask(gpio);
  98. mpc8xxx_gpio_set_high(data->base, gpio_mask(gpio));
  99. } else {
  100. data->dat_shadow &= ~gpio_mask(gpio);
  101. mpc8xxx_gpio_set_low(data->base, gpio_mask(gpio));
  102. }
  103. return 0;
  104. }
  105. static int mpc8xxx_gpio_direction_output(struct udevice *dev, uint gpio,
  106. int value)
  107. {
  108. struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
  109. /* GPIO 28..31 are input only on MPC5121 */
  110. if (data->type == MPC5121_GPIO_TYPE && gpio >= 28)
  111. return -EINVAL;
  112. return mpc8xxx_gpio_set_value(dev, gpio, value);
  113. }
  114. static int mpc8xxx_gpio_get_value(struct udevice *dev, uint gpio)
  115. {
  116. struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
  117. if (!!mpc8xxx_gpio_get_dir(data->base, gpio_mask(gpio))) {
  118. /* Output -> use shadowed value */
  119. return !!(data->dat_shadow & gpio_mask(gpio));
  120. }
  121. /* Input -> read value from GPDAT register */
  122. return !!mpc8xxx_gpio_get_val(data->base, gpio_mask(gpio));
  123. }
  124. static int mpc8xxx_gpio_get_open_drain(struct udevice *dev, uint gpio)
  125. {
  126. struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
  127. return !!mpc8xxx_gpio_open_drain_val(data->base, gpio_mask(gpio));
  128. }
  129. static int mpc8xxx_gpio_set_open_drain(struct udevice *dev, uint gpio,
  130. int value)
  131. {
  132. struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
  133. if (value)
  134. mpc8xxx_gpio_open_drain_on(data->base, gpio_mask(gpio));
  135. else
  136. mpc8xxx_gpio_open_drain_off(data->base, gpio_mask(gpio));
  137. return 0;
  138. }
  139. static int mpc8xxx_gpio_get_function(struct udevice *dev, uint gpio)
  140. {
  141. struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
  142. int dir;
  143. dir = !!mpc8xxx_gpio_get_dir(data->base, gpio_mask(gpio));
  144. return dir ? GPIOF_OUTPUT : GPIOF_INPUT;
  145. }
  146. #if CONFIG_IS_ENABLED(OF_CONTROL)
  147. static int mpc8xxx_gpio_ofdata_to_platdata(struct udevice *dev)
  148. {
  149. struct mpc8xxx_gpio_plat *plat = dev_get_platdata(dev);
  150. fdt_addr_t addr;
  151. u32 reg[2];
  152. dev_read_u32_array(dev, "reg", reg, 2);
  153. addr = dev_translate_address(dev, reg);
  154. plat->addr = addr;
  155. plat->size = reg[1];
  156. plat->ngpios = dev_read_u32_default(dev, "ngpios", 32);
  157. return 0;
  158. }
  159. #endif
  160. static int mpc8xxx_gpio_platdata_to_priv(struct udevice *dev)
  161. {
  162. struct mpc8xxx_gpio_data *priv = dev_get_priv(dev);
  163. struct mpc8xxx_gpio_plat *plat = dev_get_platdata(dev);
  164. unsigned long size = plat->size;
  165. ulong driver_data = dev_get_driver_data(dev);
  166. if (size == 0)
  167. size = 0x100;
  168. priv->addr = plat->addr;
  169. priv->base = map_sysmem(plat->addr, size);
  170. if (!priv->base)
  171. return -ENOMEM;
  172. priv->gpio_count = plat->ngpios;
  173. priv->dat_shadow = 0;
  174. priv->type = driver_data;
  175. return 0;
  176. }
  177. static int mpc8xxx_gpio_probe(struct udevice *dev)
  178. {
  179. struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  180. struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
  181. char name[32], *str;
  182. mpc8xxx_gpio_platdata_to_priv(dev);
  183. snprintf(name, sizeof(name), "MPC@%lx_", data->addr);
  184. str = strdup(name);
  185. if (!str)
  186. return -ENOMEM;
  187. uc_priv->bank_name = str;
  188. uc_priv->gpio_count = data->gpio_count;
  189. return 0;
  190. }
  191. static const struct dm_gpio_ops gpio_mpc8xxx_ops = {
  192. .direction_input = mpc8xxx_gpio_direction_input,
  193. .direction_output = mpc8xxx_gpio_direction_output,
  194. .get_value = mpc8xxx_gpio_get_value,
  195. .set_value = mpc8xxx_gpio_set_value,
  196. .get_open_drain = mpc8xxx_gpio_get_open_drain,
  197. .set_open_drain = mpc8xxx_gpio_set_open_drain,
  198. .get_function = mpc8xxx_gpio_get_function,
  199. };
  200. static const struct udevice_id mpc8xxx_gpio_ids[] = {
  201. { .compatible = "fsl,pq3-gpio", .data = MPC8XXX_GPIO_TYPE },
  202. { .compatible = "fsl,mpc8308-gpio", .data = MPC8XXX_GPIO_TYPE },
  203. { .compatible = "fsl,mpc8349-gpio", .data = MPC8XXX_GPIO_TYPE },
  204. { .compatible = "fsl,mpc8572-gpio", .data = MPC8XXX_GPIO_TYPE},
  205. { .compatible = "fsl,mpc8610-gpio", .data = MPC8XXX_GPIO_TYPE},
  206. { .compatible = "fsl,mpc5121-gpio", .data = MPC5121_GPIO_TYPE, },
  207. { .compatible = "fsl,qoriq-gpio", .data = MPC8XXX_GPIO_TYPE },
  208. { /* sentinel */ }
  209. };
  210. U_BOOT_DRIVER(gpio_mpc8xxx) = {
  211. .name = "gpio_mpc8xxx",
  212. .id = UCLASS_GPIO,
  213. .ops = &gpio_mpc8xxx_ops,
  214. #if CONFIG_IS_ENABLED(OF_CONTROL)
  215. .ofdata_to_platdata = mpc8xxx_gpio_ofdata_to_platdata,
  216. .platdata_auto_alloc_size = sizeof(struct mpc8xxx_gpio_plat),
  217. .of_match = mpc8xxx_gpio_ids,
  218. #endif
  219. .probe = mpc8xxx_gpio_probe,
  220. .priv_auto_alloc_size = sizeof(struct mpc8xxx_gpio_data),
  221. };