A1-board-selector-CCR.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*
  2. * board selector support for TCA9535 used in Bitmine's CoinCraft Desk
  3. *
  4. * Copyright 2014 Zefir Kurtisi <zefir.kurtisi@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the Free
  8. * Software Foundation; either version 3 of the License, or (at your option)
  9. * any later version. See COPYING for more details.
  10. */
  11. #include "miner.h"
  12. #include "A1-board-selector.h"
  13. #include "i2c-context.h"
  14. static struct board_selector ccr_selector;
  15. static struct i2c_ctx *U1_tca9548;
  16. static struct i2c_ctx *U3_tca9535;
  17. static struct i2c_ctx *U4_tca9535;
  18. static uint8_t active_chain;
  19. static pthread_mutex_t lock;
  20. struct chain_mapping {
  21. uint8_t chain_id;
  22. uint8_t U1;
  23. uint8_t U3p0;
  24. uint8_t U3p1;
  25. };
  26. static const struct chain_mapping chain_mapping[CCR_MAX_CHAINS] = {
  27. { 0, 0x01, 0x01, 0x00, },
  28. { 1, 0x01, 0x00, 0x80, },
  29. { 2, 0x02, 0x02, 0x00, },
  30. { 3, 0x02, 0x00, 0x40, },
  31. { 4, 0x04, 0x04, 0x00, },
  32. { 5, 0x04, 0x00, 0x20, },
  33. { 6, 0x08, 0x08, 0x00, },
  34. { 7, 0x08, 0x00, 0x10, },
  35. { 8, 0x10, 0x10, 0x00, },
  36. { 9, 0x10, 0x00, 0x08, },
  37. { 10, 0x20, 0x20, 0x00, },
  38. { 11, 0x20, 0x00, 0x04, },
  39. { 12, 0x40, 0x40, 0x00, },
  40. { 13, 0x40, 0x00, 0x02, },
  41. { 14, 0x80, 0x80, 0x00, },
  42. { 15, 0x80, 0x00, 0x01, },
  43. };
  44. static void ccr_unlock(void)
  45. {
  46. mutex_unlock(&lock);
  47. }
  48. static void ccr_exit(void)
  49. {
  50. if (U1_tca9548 != NULL)
  51. U1_tca9548->exit(U1_tca9548);
  52. if (U3_tca9535 != NULL)
  53. U3_tca9535->exit(U3_tca9535);
  54. if (U4_tca9535 != NULL)
  55. U4_tca9535->exit(U4_tca9535);
  56. }
  57. extern struct board_selector *ccr_board_selector_init(void)
  58. {
  59. mutex_init(&lock);
  60. applog(LOG_INFO, "ccr_board_selector_init()");
  61. /* detect all i2c slaves */
  62. U1_tca9548 = i2c_slave_open(I2C_BUS, 0x70);
  63. U3_tca9535 = i2c_slave_open(I2C_BUS, 0x23);
  64. U4_tca9535 = i2c_slave_open(I2C_BUS, 0x22);
  65. if (U1_tca9548 == NULL || U3_tca9535 == NULL || U4_tca9535 == NULL)
  66. goto fail;
  67. /* init I2C multiplexer */
  68. bool res = U1_tca9548->write(U1_tca9548, 0x00, 0x00) &&
  69. /* init reset selector */
  70. U3_tca9535->write(U3_tca9535, 0x06, 0x00) &&
  71. U3_tca9535->write(U3_tca9535, 0x07, 0x00) &&
  72. U3_tca9535->write(U3_tca9535, 0x02, 0x00) &&
  73. U3_tca9535->write(U3_tca9535, 0x03, 0x00) &&
  74. /* init chain selector */
  75. U4_tca9535->write(U4_tca9535, 0x06, 0x00) &&
  76. U4_tca9535->write(U4_tca9535, 0x07, 0x00) &&
  77. U4_tca9535->write(U4_tca9535, 0x02, 0x00) &&
  78. U4_tca9535->write(U4_tca9535, 0x03, 0x00);
  79. if (!res)
  80. goto fail;
  81. return &ccr_selector;
  82. fail:
  83. ccr_exit();
  84. return NULL;
  85. }
  86. static bool ccr_select(uint8_t chain)
  87. {
  88. if (chain >= CCR_MAX_CHAINS)
  89. return false;
  90. mutex_lock(&lock);
  91. if (active_chain == chain)
  92. return true;
  93. active_chain = chain;
  94. const struct chain_mapping *cm = &chain_mapping[chain];
  95. if (!U1_tca9548->write(U1_tca9548, cm->U1, cm->U1))
  96. return false;
  97. if (!U4_tca9535->write(U4_tca9535, 0x02, cm->U3p0) ||
  98. !U4_tca9535->write(U4_tca9535, 0x03, cm->U3p1))
  99. return false;
  100. /* sanity check: ensure i2c command has been written before we leave */
  101. uint8_t tmp;
  102. if (!U4_tca9535->read(U4_tca9535, 0x02, &tmp) || tmp != cm->U3p0) {
  103. applog(LOG_ERR, "ccr_select: wrote 0x%02x, read 0x%02x",
  104. cm->U3p0, tmp);
  105. }
  106. applog(LOG_DEBUG, "selected chain %d", chain);
  107. return true;
  108. }
  109. static bool __ccr_board_selector_reset(uint8_t p0, uint8_t p1)
  110. {
  111. if (!U3_tca9535->write(U3_tca9535, 0x02, p0) ||
  112. !U3_tca9535->write(U3_tca9535, 0x03, p1))
  113. return false;
  114. cgsleep_ms(RESET_LOW_TIME_MS);
  115. if (!U3_tca9535->write(U3_tca9535, 0x02, 0x00) ||
  116. !U3_tca9535->write(U3_tca9535, 0x03, 0x00))
  117. return false;
  118. cgsleep_ms(RESET_HI_TIME_MS);
  119. return true;
  120. }
  121. // we assume we are already holding the mutex
  122. static bool ccr_reset(void)
  123. {
  124. const struct chain_mapping *cm = &chain_mapping[active_chain];
  125. applog(LOG_DEBUG, "resetting chain %d", cm->chain_id);
  126. bool retval = __ccr_board_selector_reset(cm->U3p0, cm->U3p1);
  127. return retval;
  128. }
  129. static bool ccr_reset_all(void)
  130. {
  131. mutex_lock(&lock);
  132. bool retval = __ccr_board_selector_reset(0xff, 0xff);
  133. mutex_unlock(&lock);
  134. return retval;
  135. }
  136. static uint8_t ccr_get_temp(uint8_t sensor_id)
  137. {
  138. if ((active_chain & 1) != 0 || sensor_id != 0)
  139. return 0;
  140. struct i2c_ctx *U7 = i2c_slave_open(I2C_BUS, 0x4c);
  141. if (U7 == NULL)
  142. return 0;
  143. uint8_t retval = 0;
  144. if (!U7->read(U7, 0, &retval))
  145. retval = 0;
  146. U7->exit(U7);
  147. return retval;
  148. }
  149. static struct board_selector ccr_selector = {
  150. .select = ccr_select,
  151. .release = ccr_unlock,
  152. .exit = ccr_exit,
  153. .reset = ccr_reset,
  154. .reset_all = ccr_reset_all,
  155. .get_temp = ccr_get_temp,
  156. };