driver-aan.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * Copyright 2014 Luke Dashjr
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the Free
  6. * Software Foundation; either version 3 of the License, or (at your option)
  7. * any later version. See COPYING for more details.
  8. */
  9. #include "config.h"
  10. #include <stdbool.h>
  11. #include <stdint.h>
  12. #include <string.h>
  13. #include "driver-aan.h"
  14. #include "logging.h"
  15. #include "lowl-spi.h"
  16. #include "miner.h"
  17. #include "util.h"
  18. #define AAN_PROBE_TIMEOUT_US 3750000
  19. enum aan_cmd {
  20. AAN_BIST_START = 0x01,
  21. AAN_BIST_FIX = 0x03,
  22. AAN_RESET = 0x04,
  23. AAN_WRITE_JOB = 0x07,
  24. AAN_READ_RESULT = 0x08,
  25. AAN_WRITE_REG = 0x09,
  26. AAN_READ_REG = 0x0a,
  27. AAN_READ_REG_RESP = 0x1a,
  28. };
  29. static void aan_spi_parse_rx(struct spi_port *);
  30. static
  31. void aan_spi_cmd_queue(struct spi_port * const spi, const uint8_t cmd, const uint8_t chip, const void * const data, const size_t datalen)
  32. {
  33. const struct aan_hooks * const hooks = spi->userp;
  34. const uint8_t cmdbuf[2] = {cmd, chip};
  35. hooks->precmd(spi);
  36. spi_emit_buf(spi, cmdbuf, sizeof(cmdbuf));
  37. if (datalen)
  38. spi_emit_buf(spi, data, datalen);
  39. }
  40. static
  41. bool aan_spi_txrx(struct spi_port * const spi)
  42. {
  43. if (unlikely(!spi_txrx(spi)))
  44. return false;
  45. aan_spi_parse_rx(spi);
  46. return true;
  47. }
  48. static
  49. bool aan_spi_cmd_send(struct spi_port * const spi, const uint8_t cmd, const uint8_t chip, const void * const data, const size_t datalen)
  50. {
  51. aan_spi_cmd_queue(spi, cmd, chip, data, datalen);
  52. return aan_spi_txrx(spi);
  53. }
  54. static
  55. bool aan_spi_cmd_resp(struct spi_port * const spi, const uint8_t cmd, const uint8_t chip, const struct timeval * const tvp_timeout)
  56. {
  57. const uint8_t cmdbuf[2] = {cmd, chip};
  58. uint8_t * const rx = spi_getrxbuf(spi);
  59. while (true)
  60. {
  61. spi_emit_nop(spi, 2);
  62. if (unlikely(!spi_txrx(spi)))
  63. return false;
  64. if (!memcmp(rx, cmdbuf, 2))
  65. break;
  66. aan_spi_parse_rx(spi);
  67. if (unlikely(tvp_timeout && timer_passed(tvp_timeout, NULL)))
  68. return false;
  69. }
  70. spi_clear_buf(spi);
  71. return true;
  72. }
  73. static
  74. bool aan_spi_cmd(struct spi_port * const spi, const uint8_t cmd, const uint8_t chip, const void * const data, const size_t datalen, const struct timeval * const tvp_timeout)
  75. {
  76. if (!aan_spi_cmd_send(spi, cmd, chip, data, datalen))
  77. return false;
  78. if (!aan_spi_cmd_resp(spi, cmd, chip, tvp_timeout))
  79. return false;
  80. return true;
  81. }
  82. int aan_detect_spi(int * const out_chipcount, struct spi_port * const * const spi_a, const int spi_n)
  83. {
  84. struct timeval tv_timeout;
  85. timer_set_delay_from_now(&tv_timeout, AAN_PROBE_TIMEOUT_US);
  86. int state[spi_n];
  87. int completed = 0;
  88. for (int i = 0; i < spi_n; ++i)
  89. {
  90. struct spi_port * const spi = spi_a[i];
  91. aan_spi_cmd_send(spi, state[i] = AAN_RESET, AAN_ALL_CHIPS, NULL, 0);
  92. out_chipcount[i] = -1;
  93. }
  94. do {
  95. for (int i = 0; i < spi_n; ++i)
  96. {
  97. if (state[i] == -1)
  98. continue;
  99. struct spi_port * const spi = spi_a[i];
  100. spi_emit_nop(spi, 2);
  101. if (unlikely(!spi_txrx(spi)))
  102. {
  103. spifail:
  104. state[i] = -1;
  105. continue;
  106. }
  107. uint8_t * const rx = spi_getrxbuf(spi);
  108. if (rx[0] == state[i] && rx[1] == AAN_ALL_CHIPS)
  109. {
  110. switch (state[i])
  111. {
  112. case AAN_RESET:
  113. applog(LOG_DEBUG, "%s: Reset complete", spi->repr);
  114. spi_clear_buf(spi);
  115. aan_spi_cmd_send(spi, state[i] = AAN_BIST_START, AAN_ALL_CHIPS, NULL, 0);
  116. spi_emit_nop(spi, 2);
  117. break;
  118. case AAN_BIST_START:
  119. if (unlikely(!spi_txrx(spi)))
  120. goto spifail;
  121. out_chipcount[i] = rx[1];
  122. state[i] = -1;
  123. ++completed;
  124. applog(LOG_DEBUG, "%s: BIST_START complete (%d chips)", spi->repr, rx[1]);
  125. break;
  126. }
  127. spi_clear_buf(spi);
  128. continue;
  129. }
  130. aan_spi_parse_rx(spi);
  131. }
  132. } while (completed < spi_n && likely(!timer_passed(&tv_timeout, NULL)));
  133. applog(LOG_DEBUG, "%s completed for %d out of %d SPI ports", __func__, completed, spi_n);
  134. return completed;
  135. }
  136. static
  137. void aan_spi_parse_rx(struct spi_port * const spi)
  138. {
  139. spi_clear_buf(spi);
  140. }