driver-knc.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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. #ifdef HAVE_LINUX_I2C_DEV_USER_H
  18. #include <linux/i2c-dev-user.h>
  19. #else
  20. #include <linux/i2c-dev.h>
  21. #endif
  22. #include "deviceapi.h"
  23. struct device_drv knc_drv;
  24. static
  25. bool _check_value(const char * const devpath, const int i, const int32_t r, const uint8_t reg, const int32_t expected)
  26. {
  27. if (expected == r)
  28. return true;
  29. if (r == -1)
  30. applog(LOG_DEBUG, "%s: %s: Error when reading slave %d register 0x%2x: %s",
  31. knc_drv.dname, devpath, i, reg, bfg_strerror(errno, BST_ERRNO));
  32. else
  33. applog(LOG_DEBUG, "%s: %s: Slave %d register 0x%2x is 0x%x, not 0x%x as expected",
  34. knc_drv.dname, devpath, i, reg, r, expected);
  35. return false;
  36. }
  37. static
  38. bool knc_detect_one(const char *devpath)
  39. {
  40. struct cgpu_info *cgpu;
  41. const int first_slave = 16, last_slave = 23;
  42. int procs;
  43. int i;
  44. int32_t r;
  45. const int fd = open(devpath, O_RDWR);
  46. if (unlikely(fd == -1))
  47. {
  48. applog(LOG_DEBUG, "%s: Failed to open %s", knc_drv.dname, devpath);
  49. return false;
  50. }
  51. for (i = first_slave; i <= last_slave; ++i)
  52. {
  53. if (ioctl(fd, I2C_SLAVE, i))
  54. {
  55. applog(LOG_DEBUG, "%s: %s: Failed to select I2C_SLAVE %d",
  56. knc_drv.dname, devpath, i);
  57. continue;
  58. }
  59. r = i2c_smbus_read_byte_data(fd, 0x98);
  60. if (!_check_value(devpath, i, r, 0x98, 0x11))
  61. continue;
  62. r = i2c_smbus_read_word_data(fd, 0xd0);
  63. if (!_check_value(devpath, i, r, 0xd0, 0x10))
  64. continue;
  65. applog(LOG_DEBUG, "%s: %s: Found i2c slave %d",
  66. knc_drv.dname, devpath, i);
  67. procs += 6;
  68. }
  69. if (!procs)
  70. return false;
  71. cgpu = malloc(sizeof(*cgpu));
  72. *cgpu = (struct cgpu_info){
  73. .drv = &knc_drv,
  74. .device_path = strdup(devpath),
  75. .deven = DEV_ENABLED,
  76. .procs = procs,
  77. .threads = 1,
  78. };
  79. return add_cgpu(cgpu);
  80. }
  81. static int knc_detect_auto(void)
  82. {
  83. const int first_bus = 3, last_bus = 8;
  84. char devpath[] = "/dev/i2c-N";
  85. int found = 0, i;
  86. for (i = first_bus; i <= last_bus; ++i)
  87. {
  88. devpath[9] = '0' + i;
  89. if (knc_detect_one(devpath))
  90. ++found;
  91. }
  92. return found;
  93. }
  94. static void knc_detect(void)
  95. {
  96. generic_detect(&knc_drv, knc_detect_one, knc_detect_auto, GDF_REQUIRE_DNAME | GDF_DEFAULT_NOAUTO);
  97. }
  98. struct device_drv knc_drv = {
  99. .dname = "knc",
  100. .name = "KNC",
  101. .drv_detect = knc_detect,
  102. };