driver-nanofury.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * Copyright 2013 Luke Dashjr
  3. * Copyright 2013 NanoFury
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the Free
  7. * Software Foundation; either version 3 of the License, or (at your option)
  8. * any later version. See COPYING for more details.
  9. */
  10. #include "config.h"
  11. #include <stdbool.h>
  12. #include "deviceapi.h"
  13. #include "logging.h"
  14. #include "lowlevel.h"
  15. #include "mcp2210.h"
  16. #include "miner.h"
  17. #define NANOFURY_USB_PRODUCT "NanoFury"
  18. #define NANOFURY_GP_PIN_LED 0
  19. #define NANOFURY_GP_PIN_SCK_OVR 5
  20. #define NANOFURY_GP_PIN_PWR_EN 6
  21. #define NANOFURY_MAX_BYTES_PER_SPI_TRANSFER 60 // due to MCP2210 limitation
  22. struct device_drv nanofury_drv;
  23. static
  24. bool nanofury_checkport(struct mcp2210_device * const mcp)
  25. {
  26. int i;
  27. const char tmp = 0;
  28. char tmprx;
  29. // default: set everything to input
  30. for (i = 0; i < 9; ++i)
  31. if (MGV_ERROR == mcp2210_get_gpio_input(mcp, i))
  32. goto fail;
  33. // configure the pins that we need:
  34. // LED
  35. if (!mcp2210_set_gpio_output(mcp, NANOFURY_GP_PIN_LED, MGV_HIGH))
  36. goto fail;
  37. // PWR_EN
  38. if (!mcp2210_set_gpio_output(mcp, NANOFURY_GP_PIN_PWR_EN, MGV_HIGH))
  39. goto fail;
  40. // configure SPI
  41. // This is the only place where speed, mode and other settings are configured!!!
  42. if (!mcp2210_configure_spi(mcp, 200000, 0xffff, 0xffef, 0, 0, 0))
  43. goto fail;
  44. if (!mcp2210_set_spimode(mcp, 0))
  45. goto fail;
  46. if (!mcp2210_spi_transfer(mcp, &tmp, &tmprx, 1))
  47. goto fail;
  48. // after this command SCK_OVRRIDE should read the same as current SCK value (which for mode 0 should be 0)
  49. if (mcp2210_get_gpio_input(mcp, NANOFURY_GP_PIN_SCK_OVR) != MGV_LOW)
  50. goto fail;
  51. // switch SCK to polarity (default SCK=1 in mode 2)
  52. if (!mcp2210_set_spimode(mcp, 2))
  53. goto fail;
  54. if (!mcp2210_spi_transfer(mcp, &tmp, &tmprx, 1))
  55. goto fail;
  56. // after this command SCK_OVRRIDE should read the same as current SCK value (which for mode 2 should be 1)
  57. if (mcp2210_get_gpio_input(mcp, NANOFURY_GP_PIN_SCK_OVR) != MGV_HIGH)
  58. goto fail;
  59. // switch SCK to polarity (default SCK=0 in mode 0)
  60. if (!mcp2210_set_spimode(mcp, 0))
  61. goto fail;
  62. if (!mcp2210_spi_transfer(mcp, &tmp, &tmprx, 1))
  63. goto fail;
  64. if (mcp2210_get_gpio_input(mcp, NANOFURY_GP_PIN_SCK_OVR) != MGV_LOW)
  65. goto fail;
  66. return true;
  67. fail:
  68. return false;
  69. }
  70. static
  71. bool nanofury_foundlowl(struct lowlevel_device_info * const info)
  72. {
  73. const char * const product = info->product;
  74. const char * const serial = info->serial;
  75. struct mcp2210_device *mcp;
  76. if (info->lowl != &lowl_mcp2210)
  77. {
  78. applog(LOG_WARNING, "%s: Matched \"%s\" serial \"%s\", but lowlevel driver is not mcp2210!",
  79. __func__, product, serial);
  80. return false;
  81. }
  82. mcp = mcp2210_open(info);
  83. if (!mcp)
  84. {
  85. applog(LOG_WARNING, "%s: Matched \"%s\" serial \"%s\", but mcp2210 lowlevel driver failed to open it",
  86. __func__, product, serial);
  87. return false;
  88. }
  89. if (!nanofury_checkport(mcp))
  90. {
  91. applog(LOG_WARNING, "%s: Matched \"%s\" serial \"%s\", but failed to detect nanofury",
  92. __func__, product, serial);
  93. // TODO: mcp2210_close(mcp);
  94. return false;
  95. }
  96. // TODO: mcp2210_close(mcp);
  97. // TODO: claim device
  98. struct cgpu_info *cgpu;
  99. cgpu = malloc(sizeof(*cgpu));
  100. *cgpu = (struct cgpu_info){
  101. .drv = &nanofury_drv,
  102. .device_data = info,
  103. .threads = 1,
  104. // TODO: .name
  105. // TODO: .device_path
  106. // TODO: .dev_manufacturer/.dev_product/.dev_serial
  107. .deven = DEV_ENABLED,
  108. // TODO: .cutofftemp
  109. };
  110. return add_cgpu(cgpu);
  111. }
  112. static bool nanofury_detect_one(const char *serial)
  113. {
  114. return lowlevel_detect_serial(nanofury_foundlowl, serial);
  115. }
  116. static int nanofury_detect_auto()
  117. {
  118. return lowlevel_detect(nanofury_foundlowl, NANOFURY_USB_PRODUCT);
  119. }
  120. static void nanofury_detect()
  121. {
  122. serial_detect_auto(&nanofury_drv, nanofury_detect_one, nanofury_detect_auto);
  123. }
  124. struct device_drv nanofury_drv = {
  125. .dname = "nanofury",
  126. .name = "NFY",
  127. .drv_detect = nanofury_detect,
  128. // .thread_prepare = nanofury_prepare,
  129. // .thread_init = nanofury_thread_init,
  130. // .minerloop = minerloop_async,
  131. // .poll = nanofury_poll,
  132. // .job_prepare = nanofury_job_prepare,
  133. // .job_start = nanofury_job_start,
  134. // .get_stats = nanofury_get_stats,
  135. // .get_api_extra_device_status = get_nanofury_api_extra_device_status,
  136. // .set_device = nanofury_set_device,
  137. #ifdef HAVE_CURSES
  138. // .proc_wlogprint_status = nanofury_wlogprint_status,
  139. // .proc_tui_wlogprint_choices = nanofury_tui_wlogprint_choices,
  140. // .proc_tui_handle_choice = nanofury_tui_handle_choice,
  141. #endif
  142. };