sx151x.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * (C) Copyright 2013
  3. * Viktar Palstsiuk, Promwad, viktar.palstsiuk@promwad.com
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. /*
  8. * Driver for Semtech SX151x SPI GPIO Expanders
  9. */
  10. #include <common.h>
  11. #include <spi.h>
  12. #include <sx151x.h>
  13. #ifndef CONFIG_SX151X_SPI_BUS
  14. #define CONFIG_SX151X_SPI_BUS 0
  15. #endif
  16. /*
  17. * The SX151x registers
  18. */
  19. #ifdef CONFIG_SX151X_GPIO_COUNT_8
  20. /* 8bit: SX1511 */
  21. #define SX151X_REG_DIR 0x07
  22. #define SX151X_REG_DATA 0x08
  23. #else
  24. /* 16bit: SX1512 */
  25. #define SX151X_REG_DIR 0x0F
  26. #define SX151X_REG_DATA 0x11
  27. #endif
  28. #define SX151X_REG_RESET 0x7D
  29. static int sx151x_spi_write(int chip, unsigned char reg, unsigned char val)
  30. {
  31. struct spi_slave *slave;
  32. unsigned char buf[2];
  33. int ret;
  34. slave = spi_setup_slave(CONFIG_SX151X_SPI_BUS, chip, 1000000,
  35. SPI_MODE_0);
  36. if (!slave)
  37. return 0;
  38. spi_claim_bus(slave);
  39. buf[0] = reg;
  40. buf[1] = val;
  41. ret = spi_xfer(slave, 16, buf, NULL, SPI_XFER_BEGIN | SPI_XFER_END);
  42. if (ret < 0)
  43. printf("spi%d.%d write fail: can't write %02x to %02x: %d\n",
  44. CONFIG_SX151X_SPI_BUS, chip, val, reg, ret);
  45. else
  46. printf("spi%d.%d write 0x%02x to register 0x%02x\n",
  47. CONFIG_SX151X_SPI_BUS, chip, val, reg);
  48. spi_release_bus(slave);
  49. spi_free_slave(slave);
  50. return ret;
  51. }
  52. static int sx151x_spi_read(int chip, unsigned char reg)
  53. {
  54. struct spi_slave *slave;
  55. int ret;
  56. slave = spi_setup_slave(CONFIG_SX151X_SPI_BUS, chip, 1000000,
  57. SPI_MODE_0);
  58. if (!slave)
  59. return 0;
  60. spi_claim_bus(slave);
  61. ret = spi_w8r8(slave, reg | 0x80);
  62. if (ret < 0)
  63. printf("spi%d.%d read fail: can't read %02x: %d\n",
  64. CONFIG_SX151X_SPI_BUS, chip, reg, ret);
  65. else
  66. printf("spi%d.%d read register 0x%02x: 0x%02x\n",
  67. CONFIG_SX151X_SPI_BUS, chip, reg, ret);
  68. spi_release_bus(slave);
  69. spi_free_slave(slave);
  70. return ret;
  71. }
  72. static inline void sx151x_find_cfg(int gpio, unsigned char *reg, unsigned char *mask)
  73. {
  74. *reg -= gpio / 8;
  75. *mask = 1 << (gpio % 8);
  76. }
  77. static int sx151x_write_cfg(int chip, unsigned char gpio, unsigned char reg, int val)
  78. {
  79. unsigned char mask;
  80. unsigned char data;
  81. int ret;
  82. sx151x_find_cfg(gpio, &reg, &mask);
  83. ret = sx151x_spi_read(chip, reg);
  84. if (ret < 0)
  85. return ret;
  86. else
  87. data = ret;
  88. data &= ~mask;
  89. data |= (val << (gpio % 8)) & mask;
  90. return sx151x_spi_write(chip, reg, data);
  91. }
  92. int sx151x_get_value(int chip, int gpio)
  93. {
  94. unsigned char reg = SX151X_REG_DATA;
  95. unsigned char mask;
  96. int ret;
  97. sx151x_find_cfg(gpio, &reg, &mask);
  98. ret = sx151x_spi_read(chip, reg);
  99. if (ret >= 0)
  100. ret = (ret & mask) != 0 ? 1 : 0;
  101. return ret;
  102. }
  103. int sx151x_set_value(int chip, int gpio, int val)
  104. {
  105. return sx151x_write_cfg(chip, gpio, SX151X_REG_DATA, (val ? 1 : 0));
  106. }
  107. int sx151x_direction_input(int chip, int gpio)
  108. {
  109. return sx151x_write_cfg(chip, gpio, SX151X_REG_DIR, 1);
  110. }
  111. int sx151x_direction_output(int chip, int gpio)
  112. {
  113. return sx151x_write_cfg(chip, gpio, SX151X_REG_DIR, 0);
  114. }
  115. int sx151x_reset(int chip)
  116. {
  117. int err;
  118. err = sx151x_spi_write(chip, SX151X_REG_RESET, 0x12);
  119. if (err < 0)
  120. return err;
  121. err = sx151x_spi_write(chip, SX151X_REG_RESET, 0x34);
  122. return err;
  123. }
  124. #ifdef CONFIG_CMD_SX151X
  125. int do_sx151x(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  126. {
  127. int ret = CMD_RET_USAGE, chip = 0, gpio = 0, val = 0;
  128. if (argc < 3)
  129. return CMD_RET_USAGE;
  130. /* arg2 used as chip number */
  131. chip = simple_strtoul(argv[2], NULL, 10);
  132. if (strcmp(argv[1], "reset") == 0) {
  133. ret = sx151x_reset(chip);
  134. if (!ret) {
  135. printf("Device at spi%d.%d was reset\n",
  136. CONFIG_SX151X_SPI_BUS, chip);
  137. }
  138. return ret;
  139. }
  140. if (argc < 4)
  141. return CMD_RET_USAGE;
  142. /* arg3 used as gpio number */
  143. gpio = simple_strtoul(argv[3], NULL, 10);
  144. if (strcmp(argv[1], "get") == 0) {
  145. ret = sx151x_get_value(chip, gpio);
  146. if (ret < 0)
  147. printf("Failed to get value at spi%d.%d gpio %d\n",
  148. CONFIG_SX151X_SPI_BUS, chip, gpio);
  149. else {
  150. printf("Value at spi%d.%d gpio %d is %d\n",
  151. CONFIG_SX151X_SPI_BUS, chip, gpio, ret);
  152. ret = 0;
  153. }
  154. return ret;
  155. }
  156. if (argc < 5)
  157. return CMD_RET_USAGE;
  158. /* arg4 used as value or direction */
  159. val = simple_strtoul(argv[4], NULL, 10);
  160. if (strcmp(argv[1], "set") == 0) {
  161. ret = sx151x_set_value(chip, gpio, val);
  162. if (ret < 0)
  163. printf("Failed to set value at spi%d.%d gpio %d\n",
  164. CONFIG_SX151X_SPI_BUS, chip, gpio);
  165. else
  166. printf("New value at spi%d.%d gpio %d is %d\n",
  167. CONFIG_SX151X_SPI_BUS, chip, gpio, val);
  168. return ret;
  169. } else if (strcmp(argv[1], "dir") == 0) {
  170. if (val == 0)
  171. ret = sx151x_direction_output(chip, gpio);
  172. else
  173. ret = sx151x_direction_input(chip, gpio);
  174. if (ret < 0)
  175. printf("Failed to set direction of spi%d.%d gpio %d\n",
  176. CONFIG_SX151X_SPI_BUS, chip, gpio);
  177. else
  178. printf("New direction of spi%d.%d gpio %d is %d\n",
  179. CONFIG_SX151X_SPI_BUS, chip, gpio, val);
  180. return ret;
  181. }
  182. printf("Please see usage\n");
  183. return ret;
  184. }
  185. U_BOOT_CMD(
  186. sx151x, 5, 1, do_sx151x,
  187. "sx151x gpio access",
  188. "dir chip gpio 0|1\n"
  189. " - set gpio direction (0 for output, 1 for input)\n"
  190. "sx151x get chip gpio\n"
  191. " - get gpio value\n"
  192. "sx151x set chip gpio 0|1\n"
  193. " - set gpio value\n"
  194. "sx151x reset chip\n"
  195. " - reset chip"
  196. );
  197. #endif /* CONFIG_CMD_SX151X */