74x164_gpio.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * Take drivers/gpio/gpio-74x164.c as reference.
  3. *
  4. * 74Hx164 - Generic serial-in/parallel-out 8-bits shift register GPIO driver
  5. *
  6. * Copyright (C) 2016 Peng Fan <van.freenix@gmail.com>
  7. *
  8. * SPDX-License-Identifier: GPL-2.0+
  9. *
  10. */
  11. #include <common.h>
  12. #include <errno.h>
  13. #include <dm.h>
  14. #include <fdtdec.h>
  15. #include <malloc.h>
  16. #include <asm/gpio.h>
  17. #include <asm/io.h>
  18. #include <dt-bindings/gpio/gpio.h>
  19. #include <spi.h>
  20. DECLARE_GLOBAL_DATA_PTR;
  21. /*
  22. * struct gen_74x164_chip - Data for 74Hx164
  23. *
  24. * @oe: OE pin
  25. * @nregs: number of registers
  26. * @buffer: buffer for chained chips
  27. */
  28. #define GEN_74X164_NUMBER_GPIOS 8
  29. struct gen_74x164_priv {
  30. struct gpio_desc oe;
  31. u32 nregs;
  32. /*
  33. * Since the nregs are chained, every byte sent will make
  34. * the previous byte shift to the next register in the
  35. * chain. Thus, the first byte sent will end up in the last
  36. * register at the end of the transfer. So, to have a logical
  37. * numbering, store the bytes in reverse order.
  38. */
  39. u8 *buffer;
  40. };
  41. static int gen_74x164_write_conf(struct udevice *dev)
  42. {
  43. struct gen_74x164_priv *priv = dev_get_priv(dev);
  44. int ret;
  45. ret = dm_spi_claim_bus(dev);
  46. if (ret)
  47. return ret;
  48. ret = dm_spi_xfer(dev, priv->nregs * 8, priv->buffer, NULL,
  49. SPI_XFER_BEGIN | SPI_XFER_END);
  50. dm_spi_release_bus(dev);
  51. return ret;
  52. }
  53. static int gen_74x164_get_value(struct udevice *dev, unsigned offset)
  54. {
  55. struct gen_74x164_priv *priv = dev_get_priv(dev);
  56. uint bank = priv->nregs - 1 - offset / 8;
  57. uint pin = offset % 8;
  58. return (priv->buffer[bank] >> pin) & 0x1;
  59. }
  60. static int gen_74x164_set_value(struct udevice *dev, unsigned offset,
  61. int value)
  62. {
  63. struct gen_74x164_priv *priv = dev_get_priv(dev);
  64. uint bank = priv->nregs - 1 - offset / 8;
  65. uint pin = offset % 8;
  66. int ret;
  67. if (value)
  68. priv->buffer[bank] |= 1 << pin;
  69. else
  70. priv->buffer[bank] &= ~(1 << pin);
  71. ret = gen_74x164_write_conf(dev);
  72. if (ret)
  73. return ret;
  74. return 0;
  75. }
  76. static int gen_74x164_direction_input(struct udevice *dev, unsigned offset)
  77. {
  78. return -ENOSYS;
  79. }
  80. static int gen_74x164_direction_output(struct udevice *dev, unsigned offset,
  81. int value)
  82. {
  83. return gen_74x164_set_value(dev, offset, value);
  84. }
  85. static int gen_74x164_get_function(struct udevice *dev, unsigned offset)
  86. {
  87. return GPIOF_OUTPUT;
  88. }
  89. static int gen_74x164_xlate(struct udevice *dev, struct gpio_desc *desc,
  90. struct fdtdec_phandle_args *args)
  91. {
  92. desc->offset = args->args[0];
  93. desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
  94. return 0;
  95. }
  96. static const struct dm_gpio_ops gen_74x164_ops = {
  97. .direction_input = gen_74x164_direction_input,
  98. .direction_output = gen_74x164_direction_output,
  99. .get_value = gen_74x164_get_value,
  100. .set_value = gen_74x164_set_value,
  101. .get_function = gen_74x164_get_function,
  102. .xlate = gen_74x164_xlate,
  103. };
  104. static int gen_74x164_probe(struct udevice *dev)
  105. {
  106. struct gen_74x164_priv *priv = dev_get_priv(dev);
  107. struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  108. char *str, name[32];
  109. int ret;
  110. const void *fdt = gd->fdt_blob;
  111. int node = dev->of_offset;
  112. snprintf(name, sizeof(name), "%s_", dev->name);
  113. str = strdup(name);
  114. if (!str)
  115. return -ENOMEM;
  116. /*
  117. * See Linux kernel:
  118. * Documentation/devicetree/bindings/gpio/gpio-74x164.txt
  119. */
  120. priv->nregs = fdtdec_get_int(fdt, node, "registers-number", 1);
  121. priv->buffer = calloc(priv->nregs, sizeof(u8));
  122. if (!priv->buffer) {
  123. ret = -ENOMEM;
  124. goto free_str;
  125. }
  126. ret = fdtdec_get_byte_array(fdt, node, "registers-default",
  127. priv->buffer, priv->nregs);
  128. if (ret)
  129. dev_dbg(dev, "No registers-default property\n");
  130. ret = gpio_request_by_name(dev, "oe-gpios", 0, &priv->oe,
  131. GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
  132. if (ret) {
  133. dev_err(dev, "No oe-pins property\n");
  134. goto free_buf;
  135. }
  136. uc_priv->bank_name = str;
  137. uc_priv->gpio_count = priv->nregs * 8;
  138. ret = gen_74x164_write_conf(dev);
  139. if (ret)
  140. goto free_buf;
  141. dev_dbg(dev, "%s is ready\n", dev->name);
  142. return 0;
  143. free_buf:
  144. free(priv->buffer);
  145. free_str:
  146. free(str);
  147. return ret;
  148. }
  149. static const struct udevice_id gen_74x164_ids[] = {
  150. { .compatible = "fairchild,74hc595" },
  151. { }
  152. };
  153. U_BOOT_DRIVER(74x164) = {
  154. .name = "74x164",
  155. .id = UCLASS_GPIO,
  156. .ops = &gen_74x164_ops,
  157. .probe = gen_74x164_probe,
  158. .priv_auto_alloc_size = sizeof(struct gen_74x164_priv),
  159. .of_match = gen_74x164_ids,
  160. };