driver-knc.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. /*
  2. * Copyright 2013 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 <stddef.h>
  12. #include <stdint.h>
  13. #include <sys/ioctl.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <fcntl.h>
  17. #include <math.h>
  18. #ifdef HAVE_LINUX_I2C_DEV_USER_H
  19. #include <linux/i2c-dev-user.h>
  20. #else
  21. #include <linux/i2c-dev.h>
  22. #endif
  23. #include <linux/spi/spidev.h>
  24. #include <uthash.h>
  25. #include "deviceapi.h"
  26. #include "logging.h"
  27. #include "miner.h"
  28. #include "spidevc.h"
  29. #define KNC_POLL_INTERVAL_US 10000
  30. #define KNC_SPI_SPEED 3000000
  31. #define KNC_SPI_DELAY 0
  32. #define KNC_SPI_MODE (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH)
  33. #define KNC_SPI_BITS 8
  34. static const char * const i2cpath = "/dev/i2c-2";
  35. #define KNC_I2C_TEMPLATE "/dev/i2c-%d"
  36. enum knc_request_cmd {
  37. KNC_REQ_SUBMIT_WORK = 2,
  38. KNC_REQ_FLUSH_QUEUE = 3,
  39. };
  40. enum knc_reply_type {
  41. KNC_REPLY_NONCE_FOUND = 1,
  42. KNC_REPLY_WORK_DONE = 2,
  43. };
  44. struct device_drv knc_drv;
  45. struct knc_device {
  46. int i2c;
  47. struct spi_port *spi;
  48. struct cgpu_info *cgpu;
  49. bool need_flush;
  50. struct work *workqueue;
  51. int workqueue_size;
  52. int workqueue_max;
  53. int next_id;
  54. struct work *devicework;
  55. };
  56. struct knc_core {
  57. int asicno;
  58. int coreno;
  59. float volt;
  60. float current;
  61. };
  62. static
  63. bool knc_detect_one(const char *devpath)
  64. {
  65. static struct cgpu_info *prev_cgpu = NULL;
  66. struct cgpu_info *cgpu;
  67. int i;
  68. const int fd = open(i2cpath, O_RDWR);
  69. char *leftover = NULL;
  70. const int i2cslave = strtol(devpath, &leftover, 0);
  71. uint8_t buf[0x20];
  72. if (leftover && leftover[0])
  73. return false;
  74. if (unlikely(fd == -1))
  75. {
  76. applog(LOG_DEBUG, "%s: Failed to open %s", __func__, i2cpath);
  77. return false;
  78. }
  79. if (ioctl(fd, I2C_SLAVE, i2cslave))
  80. {
  81. close(fd);
  82. applog(LOG_DEBUG, "%s: Failed to select i2c slave 0x%x",
  83. __func__, i2cslave);
  84. return false;
  85. }
  86. i = i2c_smbus_read_i2c_block_data(fd, 0, 0x20, buf);
  87. close(fd);
  88. if (-1 == i)
  89. {
  90. applog(LOG_DEBUG, "%s: 0x%x: Failed to read i2c block data",
  91. __func__, i2cslave);
  92. return false;
  93. }
  94. for (i = 0; ; ++i)
  95. {
  96. if (buf[i] == 3)
  97. break;
  98. if (i == 0x1f)
  99. return false;
  100. }
  101. cgpu = malloc(sizeof(*cgpu));
  102. *cgpu = (struct cgpu_info){
  103. .drv = &knc_drv,
  104. .device_path = strdup(devpath),
  105. .deven = DEV_ENABLED,
  106. .procs = 192,
  107. .threads = prev_cgpu ? 0 : 1,
  108. };
  109. const bool rv = add_cgpu_slave(cgpu, prev_cgpu);
  110. prev_cgpu = cgpu;
  111. return rv;
  112. }
  113. static int knc_detect_auto(void)
  114. {
  115. const int first = 0x20, last = 0x26;
  116. char devpath[4];
  117. int found = 0, i;
  118. for (i = first; i <= last; ++i)
  119. {
  120. sprintf(devpath, "%d", i);
  121. if (knc_detect_one(devpath))
  122. ++found;
  123. }
  124. return found;
  125. }
  126. static void knc_detect(void)
  127. {
  128. generic_detect(&knc_drv, knc_detect_one, knc_detect_auto, GDF_REQUIRE_DNAME | GDF_DEFAULT_NOAUTO);
  129. }
  130. static
  131. bool knc_spi_open(const char *repr, struct spi_port * const spi)
  132. {
  133. const char * const spipath = "/dev/spidev1.0";
  134. const int fd = open(spipath, O_RDWR);
  135. const uint8_t lsbfirst = 0;
  136. if (fd == -1)
  137. return false;
  138. if (ioctl(fd, SPI_IOC_WR_MODE , &spi->mode )) goto fail;
  139. if (ioctl(fd, SPI_IOC_WR_LSB_FIRST , &lsbfirst )) goto fail;
  140. if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spi->bits )) goto fail;
  141. if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ , &spi->speed)) goto fail;
  142. spi->fd = fd;
  143. return true;
  144. fail:
  145. close(fd);
  146. spi->fd = -1;
  147. applog(LOG_WARNING, "%s: Failed to open %s", repr, spipath);
  148. return false;
  149. }
  150. static
  151. bool knc_spi_txrx(struct spi_port * const spi)
  152. {
  153. const void * const wrbuf = spi_gettxbuf(spi);
  154. void * const rdbuf = spi_getrxbuf(spi);
  155. const size_t bufsz = spi_getbufsz(spi);
  156. const int fd = spi->fd;
  157. struct spi_ioc_transfer xf = {
  158. .tx_buf = (uintptr_t) wrbuf,
  159. .rx_buf = (uintptr_t) rdbuf,
  160. .len = bufsz,
  161. .delay_usecs = spi->delay,
  162. .speed_hz = spi->speed,
  163. .bits_per_word = spi->bits,
  164. };
  165. return (ioctl(fd, SPI_IOC_MESSAGE(1), &xf) > 0);
  166. }
  167. static
  168. void knc_clean_flush(struct spi_port * const spi)
  169. {
  170. const uint8_t flushcmd = KNC_REQ_FLUSH_QUEUE << 4;
  171. const size_t spi_req_sz = 0x1000;
  172. spi_clear_buf(spi);
  173. spi_emit_buf(spi, &flushcmd, 1);
  174. spi_emit_nop(spi, spi_req_sz - spi_getbufsz(spi));
  175. applog(LOG_DEBUG, "%s: Issuing flush command to clear out device queues", knc_drv.dname);
  176. spi_txrx(spi);
  177. }
  178. static
  179. bool knc_init(struct thr_info * const thr)
  180. {
  181. const int max_cores = 192;
  182. struct thr_info *mythr;
  183. struct cgpu_info * const cgpu = thr->cgpu, *proc;
  184. struct knc_device *knc;
  185. struct knc_core *knccore;
  186. struct spi_port *spi;
  187. const int i2c = open(i2cpath, O_RDWR);
  188. int i2cslave, i, j;
  189. uint8_t buf[0x20];
  190. if (unlikely(i2c == -1))
  191. {
  192. applog(LOG_DEBUG, "%s: Failed to open %s", __func__, i2cpath);
  193. return false;
  194. }
  195. knc = malloc(sizeof(*knc));
  196. for (proc = cgpu; proc; )
  197. {
  198. if (proc->device != proc)
  199. {
  200. applog(LOG_WARNING, "%"PRIpreprv": Extra processor?", proc->proc_repr);
  201. continue;
  202. }
  203. i2cslave = atoi(proc->device_path);
  204. if (ioctl(i2c, I2C_SLAVE, i2cslave))
  205. {
  206. applog(LOG_DEBUG, "%s: Failed to select i2c slave 0x%x",
  207. __func__, i2cslave);
  208. return false;
  209. }
  210. for (i = 0; i < max_cores; i += 0x20)
  211. {
  212. i2c_smbus_read_i2c_block_data(i2c, i, 0x20, buf);
  213. for (j = 0; j < 0x20; ++j)
  214. {
  215. mythr = proc->thr[0];
  216. mythr->cgpu_data = knccore = malloc(sizeof(*knccore));
  217. *knccore = (struct knc_core){
  218. .asicno = i2cslave - 0x20,
  219. .coreno = i + j,
  220. };
  221. proc->device_data = knc;
  222. if (buf[j] != 3)
  223. proc->deven = DEV_DISABLED;
  224. proc = proc->next_proc;
  225. if ((!proc) || proc->device == proc)
  226. goto nomorecores;
  227. }
  228. }
  229. nomorecores: ;
  230. }
  231. spi = malloc(sizeof(*spi));
  232. *knc = (struct knc_device){
  233. .i2c = i2c,
  234. .spi = spi,
  235. .cgpu = cgpu,
  236. .workqueue_max = 1,
  237. };
  238. *spi = (struct spi_port){
  239. .txrx = knc_spi_txrx,
  240. .cgpu = cgpu,
  241. .repr = knc_drv.dname,
  242. .logprio = LOG_ERR,
  243. .speed = KNC_SPI_SPEED,
  244. .delay = KNC_SPI_DELAY,
  245. .mode = KNC_SPI_MODE,
  246. .bits = KNC_SPI_BITS,
  247. };
  248. if (!knc_spi_open(cgpu->dev_repr, spi))
  249. return false;
  250. knc_clean_flush(spi);
  251. timer_set_now(&thr->tv_poll);
  252. return true;
  253. }
  254. static
  255. void knc_set_queue_full(struct knc_device * const knc)
  256. {
  257. const bool full = (knc->workqueue_size >= knc->workqueue_max);
  258. struct cgpu_info *proc;
  259. for (proc = knc->cgpu; proc; proc = proc->next_proc)
  260. {
  261. struct thr_info * const thr = proc->thr[0];
  262. thr->queue_full = full;
  263. }
  264. }
  265. static
  266. void knc_remove_local_queue(struct knc_device * const knc, struct work * const work)
  267. {
  268. DL_DELETE(knc->workqueue, work);
  269. free_work(work);
  270. --knc->workqueue_size;
  271. }
  272. static
  273. void knc_prune_local_queue(struct thr_info *thr)
  274. {
  275. struct cgpu_info * const cgpu = thr->cgpu;
  276. struct knc_device * const knc = cgpu->device_data;
  277. struct work *work, *tmp;
  278. DL_FOREACH_SAFE(knc->workqueue, work, tmp)
  279. {
  280. if (stale_work(work, false))
  281. knc_remove_local_queue(knc, work);
  282. }
  283. knc_set_queue_full(knc);
  284. }
  285. static
  286. bool knc_queue_append(struct thr_info * const thr, struct work * const work)
  287. {
  288. struct cgpu_info * const cgpu = thr->cgpu;
  289. struct knc_device * const knc = cgpu->device_data;
  290. if (knc->workqueue_size >= knc->workqueue_max)
  291. {
  292. knc_prune_local_queue(thr);
  293. if (thr->queue_full)
  294. return false;
  295. }
  296. DL_APPEND(knc->workqueue, work);
  297. ++knc->workqueue_size;
  298. knc_set_queue_full(knc);
  299. if (thr->queue_full)
  300. knc_prune_local_queue(thr);
  301. return true;
  302. }
  303. #define HASH_LAST_ADDED(head, out) \
  304. (out = (head) ? (ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail)) : NULL)
  305. static
  306. void knc_queue_flush(struct thr_info * const thr)
  307. {
  308. struct cgpu_info * const cgpu = thr->cgpu;
  309. struct knc_device * const knc = cgpu->device_data;
  310. struct work *work, *tmp;
  311. if (knc->cgpu != cgpu)
  312. return;
  313. DL_FOREACH_SAFE(knc->workqueue, work, tmp)
  314. {
  315. knc_remove_local_queue(knc, work);
  316. }
  317. knc_set_queue_full(knc);
  318. HASH_LAST_ADDED(knc->devicework, work);
  319. if (work && stale_work(work, true))
  320. {
  321. knc->need_flush = true;
  322. timer_set_now(&thr->tv_poll);
  323. }
  324. }
  325. static inline
  326. uint16_t get_u16be(const void * const p)
  327. {
  328. const uint8_t * const b = p;
  329. return (((uint16_t)b[0]) << 8) | b[1];
  330. }
  331. static inline
  332. uint32_t get_u32be(const void * const p)
  333. {
  334. const uint8_t * const b = p;
  335. return (((uint32_t)b[0]) << 0x18)
  336. | (((uint32_t)b[1]) << 0x10)
  337. | (((uint32_t)b[2]) << 8)
  338. | b[3];
  339. }
  340. static
  341. void knc_poll(struct thr_info * const thr)
  342. {
  343. struct thr_info *mythr;
  344. struct cgpu_info * const cgpu = thr->cgpu, *proc;
  345. struct knc_device * const knc = cgpu->device_data;
  346. struct spi_port * const spi = knc->spi;
  347. struct knc_core *knccore;
  348. struct work *work, *tmp;
  349. uint8_t buf[0x30], *rxbuf;
  350. int works_sent = 0, asicno, i;
  351. uint16_t workaccept;
  352. int workid = knc->next_id;
  353. uint32_t nonce, coreno;
  354. size_t spi_req_sz = 0x1000;
  355. unsigned long delay_usecs = KNC_POLL_INTERVAL_US;
  356. knc_prune_local_queue(thr);
  357. spi_clear_buf(spi);
  358. if (knc->need_flush)
  359. {
  360. applog(LOG_NOTICE, "%s: Abandoning stale searches to restart", knc_drv.dname);
  361. buf[0] = KNC_REQ_FLUSH_QUEUE << 4;
  362. spi_emit_buf(spi, buf, sizeof(buf));
  363. }
  364. DL_FOREACH(knc->workqueue, work)
  365. {
  366. buf[0] = KNC_REQ_SUBMIT_WORK << 4;
  367. buf[1] = 0;
  368. buf[2] = (workid >> 8) & 0x7f;
  369. buf[3] = workid & 0xff;
  370. for (i = 0; i < 0x20; ++i)
  371. buf[4 + i] = work->midstate[0x1f - i];
  372. for (i = 0; i < 0xc; ++i)
  373. buf[0x24 + i] = work->data[0x4b - i];
  374. spi_emit_buf(spi, buf, sizeof(buf));
  375. ++works_sent;
  376. ++workid;
  377. }
  378. spi_emit_nop(spi, spi_req_sz - spi_getbufsz(spi));
  379. spi_txrx(spi);
  380. rxbuf = spi_getrxbuf(spi);
  381. if (rxbuf[3] & 1)
  382. applog(LOG_DEBUG, "%s: Receive buffer overflow reported", knc_drv.dname);
  383. workaccept = get_u16be(&rxbuf[6]);
  384. applog(LOG_DEBUG, "%s: %lu/%d jobs accepted to queue (max=%d)",
  385. knc_drv.dname, (unsigned long)workaccept, works_sent, knc->workqueue_max);
  386. while (true)
  387. {
  388. rxbuf += 0xc;
  389. spi_req_sz -= 0xc;
  390. if (spi_req_sz < 0xc)
  391. break;
  392. const int rtype = rxbuf[0] >> 6;
  393. if (rtype && opt_debug)
  394. {
  395. char x[(0xc * 2) + 1];
  396. bin2hex(x, rxbuf, 0xc);
  397. applog(LOG_DEBUG, "%s: RECV: %s", knc_drv.dname, x);
  398. }
  399. if (rtype != KNC_REPLY_NONCE_FOUND && rtype != KNC_REPLY_WORK_DONE)
  400. continue;
  401. asicno = (rxbuf[0] & 0x38) >> 3;
  402. coreno = get_u32be(&rxbuf[8]);
  403. proc = cgpu;
  404. while (true)
  405. {
  406. knccore = proc->thr[0]->cgpu_data;
  407. if (knccore->asicno == asicno)
  408. break;
  409. do {
  410. proc = proc->next_proc;
  411. } while(proc != proc->device);
  412. }
  413. for (i = 0; i < coreno; ++i)
  414. proc = proc->next_proc;
  415. mythr = proc->thr[0];
  416. i = get_u16be(&rxbuf[2]);
  417. HASH_FIND_INT(knc->devicework, &i, work);
  418. if (!work)
  419. {
  420. const char * const msgtype = (rtype == KNC_REPLY_NONCE_FOUND) ? "nonce found" : "work done";
  421. applog(LOG_WARNING, "%"PRIpreprv": Got %s message about unknown work 0x%04x",
  422. proc->proc_repr, msgtype, i);
  423. if (KNC_REPLY_NONCE_FOUND == rtype)
  424. {
  425. nonce = get_u32be(&rxbuf[4]);
  426. nonce = le32toh(nonce);
  427. inc_hw_errors2(mythr, NULL, &nonce);
  428. }
  429. else
  430. inc_hw_errors2(mythr, NULL, NULL);
  431. continue;
  432. }
  433. switch (rtype)
  434. {
  435. case KNC_REPLY_NONCE_FOUND:
  436. nonce = get_u32be(&rxbuf[4]);
  437. nonce = le32toh(nonce);
  438. submit_nonce(mythr, work, nonce);
  439. break;
  440. case KNC_REPLY_WORK_DONE:
  441. HASH_DEL(knc->devicework, work);
  442. free_work(work);
  443. hashes_done2(mythr, 0x100000000, NULL);
  444. break;
  445. }
  446. }
  447. if (knc->need_flush)
  448. {
  449. knc->need_flush = false;
  450. HASH_ITER(hh, knc->devicework, work, tmp)
  451. {
  452. HASH_DEL(knc->devicework, work);
  453. free_work(work);
  454. }
  455. delay_usecs = 0;
  456. }
  457. if (workaccept)
  458. {
  459. if (workaccept >= knc->workqueue_max)
  460. {
  461. knc->workqueue_max = workaccept;
  462. delay_usecs = 0;
  463. }
  464. DL_FOREACH_SAFE(knc->workqueue, work, tmp)
  465. {
  466. --knc->workqueue_size;
  467. DL_DELETE(knc->workqueue, work);
  468. work->device_id = knc->next_id++ & 0x7fff;
  469. HASH_ADD_INT(knc->devicework, device_id, work);
  470. if (!--workaccept)
  471. break;
  472. }
  473. knc_set_queue_full(knc);
  474. }
  475. timer_set_delay_from_now(&thr->tv_poll, delay_usecs);
  476. }
  477. static
  478. bool _knc_core_setstatus(struct thr_info * const thr, uint8_t val)
  479. {
  480. struct cgpu_info * const proc = thr->cgpu;
  481. struct knc_device * const knc = proc->device_data;
  482. struct knc_core * const knccore = thr->cgpu_data;
  483. const int i2c = knc->i2c;
  484. const int i2cslave = 0x20 + knccore->asicno;
  485. if (ioctl(i2c, I2C_SLAVE, i2cslave))
  486. {
  487. applog(LOG_DEBUG, "%"PRIpreprv": %s: Failed to select i2c slave 0x%x",
  488. proc->proc_repr, __func__, i2cslave);
  489. return false;
  490. }
  491. return (-1 != i2c_smbus_write_byte_data(i2c, knccore->coreno, val));
  492. }
  493. static
  494. void knc_core_disable(struct thr_info * const thr)
  495. {
  496. _knc_core_setstatus(thr, 0);
  497. }
  498. static
  499. void knc_core_enable(struct thr_info * const thr)
  500. {
  501. _knc_core_setstatus(thr, 1);
  502. }
  503. static
  504. float knc_dcdc_decode_5_11(uint16_t raw)
  505. {
  506. if (raw == 0)
  507. return 0.0;
  508. int dcdc_vin_exp = (raw & 0xf800) >> 11;
  509. float dcdc_vin_man = raw & 0x07ff;
  510. if (dcdc_vin_exp >= 16)
  511. dcdc_vin_exp = -32 + dcdc_vin_exp;
  512. float dcdc_vin = dcdc_vin_man * exp2(dcdc_vin_exp);
  513. return dcdc_vin;
  514. }
  515. static
  516. bool knc_get_stats(struct cgpu_info * const cgpu)
  517. {
  518. if (cgpu->device != cgpu)
  519. return true;
  520. struct thr_info *thr = cgpu->thr[0];
  521. struct knc_core *knccore = thr->cgpu_data;
  522. struct cgpu_info *proc;
  523. const int i2cdev = knccore->asicno + 3;
  524. const int i2cslave_temp = 0x48;
  525. const int i2cslave_dcdc[] = {0x10, 0x12, 0x14, 0x17};
  526. int die, i;
  527. int i2c;
  528. int32_t rawtemp, rawvolt, rawcurrent;
  529. float temp, volt, current;
  530. bool rv = false;
  531. char i2cpath[sizeof(KNC_I2C_TEMPLATE)];
  532. sprintf(i2cpath, KNC_I2C_TEMPLATE, i2cdev);
  533. i2c = open(i2cpath, O_RDWR);
  534. if (i2c == -1)
  535. {
  536. applog(LOG_DEBUG, "%s: %s: Failed to open %s",
  537. cgpu->dev_repr, __func__, i2cpath);
  538. return false;
  539. }
  540. if (ioctl(i2c, I2C_SLAVE, i2cslave_temp))
  541. {
  542. applog(LOG_DEBUG, "%s: %s: Failed to select i2c slave 0x%x",
  543. cgpu->dev_repr, __func__, i2cslave_temp);
  544. goto out;
  545. }
  546. rawtemp = i2c_smbus_read_word_data(i2c, 0);
  547. if (rawtemp == -1)
  548. goto out;
  549. temp = ((float)(rawtemp & 0xff));
  550. if (rawtemp & 0x8000)
  551. temp += 0.5;
  552. /* DCDC i2c slaves are on 0x10 + [0-7]
  553. 8 DCDC boards have all populated
  554. 4 DCDC boards only have 0,2,4,7 populated
  555. Only 0,2,4,7 are used
  556. Each DCDC powers one die in the chip, each die has 48 cores
  557. Datasheet at http://www.lineagepower.com/oem/pdf/MDT040A0X.pdf
  558. */
  559. for (proc = cgpu, i = 0; proc && proc->device == cgpu; proc = proc->next_proc, ++i)
  560. {
  561. thr = proc->thr[0];
  562. knccore = thr->cgpu_data;
  563. die = i / 0x30;
  564. if (0 == i % 0x30)
  565. {
  566. if (ioctl(i2c, I2C_SLAVE, i2cslave_dcdc[die]))
  567. {
  568. applog(LOG_DEBUG, "%s: %s: Failed to select i2c slave 0x%x",
  569. cgpu->dev_repr, __func__, i2cslave_dcdc[die]);
  570. goto out;
  571. }
  572. rawvolt = i2c_smbus_read_word_data(i2c, 0x8b); // VOUT
  573. if (rawvolt == -1)
  574. goto out;
  575. rawcurrent = i2c_smbus_read_word_data(i2c, 0x8c); // IOUT
  576. if (rawcurrent == -1)
  577. goto out;
  578. volt = (float)rawvolt * exp2(-10);
  579. current = (float)knc_dcdc_decode_5_11(rawcurrent);
  580. applog(LOG_DEBUG, "%s: die %d %6.3fV %5.2fA",
  581. cgpu->dev_repr, die, volt, current);
  582. }
  583. proc->temp = temp;
  584. knccore->volt = volt;
  585. knccore->current = current;
  586. }
  587. rv = true;
  588. out:
  589. close(i2c);
  590. return rv;
  591. }
  592. static
  593. struct api_data *knc_api_extra_device_status(struct cgpu_info * const cgpu)
  594. {
  595. struct api_data *root = NULL;
  596. struct thr_info * const thr = cgpu->thr[0];
  597. struct knc_core * const knccore = thr->cgpu_data;
  598. root = api_add_volts(root, "Voltage", &knccore->volt, false);
  599. root = api_add_volts(root, "DCDC Current", &knccore->current, false);
  600. return root;
  601. }
  602. #ifdef HAVE_CURSES
  603. static
  604. void knc_wlogprint_status(struct cgpu_info * const cgpu)
  605. {
  606. struct thr_info * const thr = cgpu->thr[0];
  607. struct knc_core * const knccore = thr->cgpu_data;
  608. wlogprint("Voltage: %.3f DCDC Current: %.3f\n",
  609. knccore->volt, knccore->current);
  610. }
  611. #endif
  612. struct device_drv knc_drv = {
  613. .dname = "knc",
  614. .name = "KNC",
  615. .drv_detect = knc_detect,
  616. .thread_init = knc_init,
  617. .thread_disable = knc_core_disable,
  618. .thread_enable = knc_core_enable,
  619. .minerloop = minerloop_queue,
  620. .queue_append = knc_queue_append,
  621. .queue_flush = knc_queue_flush,
  622. .poll = knc_poll,
  623. .get_stats = knc_get_stats,
  624. .get_api_extra_device_status = knc_api_extra_device_status,
  625. #ifdef HAVE_CURSES
  626. .proc_wlogprint_status = knc_wlogprint_status,
  627. #endif
  628. };