buspirate_spi.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /*
  2. * This file is part of the flashrom project.
  3. *
  4. * Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; version 2 of the License.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  18. */
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #include <ctype.h>
  23. #include <unistd.h>
  24. #include "flash.h"
  25. #include "programmer.h"
  26. #include "spi.h"
  27. /* Change this to #define if you want to test without a serial implementation */
  28. #undef FAKE_COMMUNICATION
  29. struct buspirate_spispeeds {
  30. const char *name;
  31. const int speed;
  32. };
  33. #ifndef FAKE_COMMUNICATION
  34. static int buspirate_serialport_setup(char *dev)
  35. {
  36. /* 115200bps, 8 databits, no parity, 1 stopbit */
  37. sp_fd = sp_openserport(dev, 115200);
  38. return 0;
  39. }
  40. #else
  41. #define buspirate_serialport_setup(...) 0
  42. #define serialport_shutdown(...) 0
  43. #define serialport_write(...) 0
  44. #define serialport_read(...) 0
  45. #define sp_flush_incoming(...) 0
  46. #endif
  47. static int buspirate_sendrecv(unsigned char *buf, unsigned int writecnt,
  48. unsigned int readcnt)
  49. {
  50. int i, ret = 0;
  51. msg_pspew("%s: write %i, read %i ", __func__, writecnt, readcnt);
  52. if (!writecnt && !readcnt) {
  53. msg_perr("Zero length command!\n");
  54. return 1;
  55. }
  56. msg_pspew("Sending");
  57. for (i = 0; i < writecnt; i++)
  58. msg_pspew(" 0x%02x", buf[i]);
  59. #ifdef FAKE_COMMUNICATION
  60. /* Placate the caller for now. */
  61. if (readcnt) {
  62. buf[0] = 0x01;
  63. memset(buf + 1, 0xff, readcnt - 1);
  64. }
  65. ret = 0;
  66. #else
  67. if (writecnt)
  68. ret = serialport_write(buf, writecnt);
  69. if (ret)
  70. return ret;
  71. if (readcnt)
  72. ret = serialport_read(buf, readcnt);
  73. if (ret)
  74. return ret;
  75. #endif
  76. msg_pspew(", receiving");
  77. for (i = 0; i < readcnt; i++)
  78. msg_pspew(" 0x%02x", buf[i]);
  79. msg_pspew("\n");
  80. return 0;
  81. }
  82. static int buspirate_spi_send_command(const struct flashctx *flash,
  83. unsigned int writecnt,
  84. unsigned int readcnt,
  85. const unsigned char *writearr,
  86. unsigned char *readarr);
  87. static const struct spi_programmer spi_programmer_buspirate = {
  88. .type = SPI_CONTROLLER_BUSPIRATE,
  89. .max_data_read = 12,
  90. .max_data_write = 12,
  91. .command = buspirate_spi_send_command,
  92. .multicommand = default_spi_send_multicommand,
  93. .read = default_spi_read,
  94. .write_256 = default_spi_write_256,
  95. };
  96. static const struct buspirate_spispeeds spispeeds[] = {
  97. {"30k", 0x0},
  98. {"125k", 0x1},
  99. {"250k", 0x2},
  100. {"1M", 0x3},
  101. {"2M", 0x4},
  102. {"2.6M", 0x5},
  103. {"4M", 0x6},
  104. {"8M", 0x7},
  105. {NULL, 0x0},
  106. };
  107. static int buspirate_spi_shutdown(void *data)
  108. {
  109. unsigned char buf[5];
  110. int ret = 0;
  111. /* Exit raw SPI mode (enter raw bitbang mode) */
  112. buf[0] = 0x00;
  113. ret = buspirate_sendrecv(buf, 1, 5);
  114. if (ret)
  115. return ret;
  116. if (memcmp(buf, "BBIO", 4)) {
  117. msg_perr("Entering raw bitbang mode failed!\n");
  118. return 1;
  119. }
  120. msg_pdbg("Raw bitbang mode version %c\n", buf[4]);
  121. if (buf[4] != '1') {
  122. msg_perr("Can't handle raw bitbang mode version %c!\n",
  123. buf[4]);
  124. return 1;
  125. }
  126. /* Reset Bus Pirate (return to user terminal) */
  127. buf[0] = 0x0f;
  128. ret = buspirate_sendrecv(buf, 1, 0);
  129. if (ret)
  130. return ret;
  131. /* Shut down serial port communication */
  132. ret = serialport_shutdown(NULL);
  133. if (ret)
  134. return ret;
  135. msg_pdbg("Bus Pirate shutdown completed.\n");
  136. return 0;
  137. }
  138. int buspirate_spi_init(void)
  139. {
  140. unsigned char buf[512];
  141. char *dev = NULL;
  142. char *speed = NULL;
  143. int spispeed = 0x7;
  144. int ret = 0;
  145. int i;
  146. dev = extract_programmer_param("dev");
  147. if (!dev || !strlen(dev)) {
  148. msg_perr("No serial device given. Use flashrom -p "
  149. "buspirate_spi:dev=/dev/ttyUSB0\n");
  150. return 1;
  151. }
  152. speed = extract_programmer_param("spispeed");
  153. if (speed) {
  154. for (i = 0; spispeeds[i].name; i++)
  155. if (!strncasecmp(spispeeds[i].name, speed,
  156. strlen(spispeeds[i].name))) {
  157. spispeed = spispeeds[i].speed;
  158. break;
  159. }
  160. if (!spispeeds[i].name)
  161. msg_perr("Invalid SPI speed, using default.\n");
  162. }
  163. free(speed);
  164. /* This works because speeds numbering starts at 0 and is contiguous. */
  165. msg_pdbg("SPI speed is %sHz\n", spispeeds[spispeed].name);
  166. ret = buspirate_serialport_setup(dev);
  167. if (ret)
  168. return ret;
  169. free(dev);
  170. if (register_shutdown(buspirate_spi_shutdown, NULL))
  171. return 1;
  172. /* This is the brute force version, but it should work. */
  173. for (i = 0; i < 19; i++) {
  174. /* Enter raw bitbang mode */
  175. buf[0] = 0x00;
  176. /* Send the command, don't read the response. */
  177. ret = buspirate_sendrecv(buf, 1, 0);
  178. if (ret)
  179. return ret;
  180. /* Read any response and discard it. */
  181. sp_flush_incoming();
  182. }
  183. /* USB is slow. The Bus Pirate is even slower. Apparently the flush
  184. * action above is too fast or too early. Some stuff still remains in
  185. * the pipe after the flush above, and one additional flush is not
  186. * sufficient either. Use a 1.5 ms delay inside the loop to make
  187. * mostly sure that at least one USB frame had time to arrive.
  188. * Looping only 5 times is not sufficient and causes the
  189. * occasional failure.
  190. * Folding the delay into the loop above is not reliable either.
  191. */
  192. for (i = 0; i < 10; i++) {
  193. usleep(1500);
  194. /* Read any response and discard it. */
  195. sp_flush_incoming();
  196. }
  197. /* Enter raw bitbang mode */
  198. buf[0] = 0x00;
  199. ret = buspirate_sendrecv(buf, 1, 5);
  200. if (ret)
  201. return ret;
  202. if (memcmp(buf, "BBIO", 4)) {
  203. msg_perr("Entering raw bitbang mode failed!\n");
  204. msg_pdbg("Got %02x%02x%02x%02x%02x\n",
  205. buf[0], buf[1], buf[2], buf[3], buf[4]);
  206. return 1;
  207. }
  208. msg_pdbg("Raw bitbang mode version %c\n", buf[4]);
  209. if (buf[4] != '1') {
  210. msg_perr("Can't handle raw bitbang mode version %c!\n",
  211. buf[4]);
  212. return 1;
  213. }
  214. /* Enter raw SPI mode */
  215. buf[0] = 0x01;
  216. ret = buspirate_sendrecv(buf, 1, 4);
  217. if (ret)
  218. return ret;
  219. if (memcmp(buf, "SPI", 3)) {
  220. msg_perr("Entering raw SPI mode failed!\n");
  221. msg_pdbg("Got %02x%02x%02x%02x\n",
  222. buf[0], buf[1], buf[2], buf[3]);
  223. return 1;
  224. }
  225. msg_pdbg("Raw SPI mode version %c\n", buf[3]);
  226. if (buf[3] != '1') {
  227. msg_perr("Can't handle raw SPI mode version %c!\n",
  228. buf[3]);
  229. return 1;
  230. }
  231. /* Initial setup (SPI peripherals config): Enable power, CS high, AUX */
  232. buf[0] = 0x40 | 0xb;
  233. ret = buspirate_sendrecv(buf, 1, 1);
  234. if (ret)
  235. return 1;
  236. if (buf[0] != 0x01) {
  237. msg_perr("Protocol error while setting power/CS/AUX!\n");
  238. return 1;
  239. }
  240. /* Set SPI speed */
  241. buf[0] = 0x60 | spispeed;
  242. ret = buspirate_sendrecv(buf, 1, 1);
  243. if (ret)
  244. return 1;
  245. if (buf[0] != 0x01) {
  246. msg_perr("Protocol error while setting SPI speed!\n");
  247. return 1;
  248. }
  249. /* Set SPI config: output type, idle, clock edge, sample */
  250. buf[0] = 0x80 | 0xa;
  251. ret = buspirate_sendrecv(buf, 1, 1);
  252. if (ret)
  253. return 1;
  254. if (buf[0] != 0x01) {
  255. msg_perr("Protocol error while setting SPI config!\n");
  256. return 1;
  257. }
  258. /* De-assert CS# */
  259. buf[0] = 0x03;
  260. ret = buspirate_sendrecv(buf, 1, 1);
  261. if (ret)
  262. return 1;
  263. if (buf[0] != 0x01) {
  264. msg_perr("Protocol error while raising CS#!\n");
  265. return 1;
  266. }
  267. register_spi_programmer(&spi_programmer_buspirate);
  268. return 0;
  269. }
  270. static int buspirate_spi_send_command(const struct flashctx *flash,
  271. unsigned int writecnt,
  272. unsigned int readcnt,
  273. const unsigned char *writearr,
  274. unsigned char *readarr)
  275. {
  276. static unsigned char *buf = NULL;
  277. unsigned int i = 0;
  278. int ret = 0;
  279. if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16)
  280. return SPI_INVALID_LENGTH;
  281. /* 3 bytes extra for CS#, len, CS#. */
  282. buf = realloc(buf, writecnt + readcnt + 3);
  283. if (!buf) {
  284. msg_perr("Out of memory!\n");
  285. exit(1); // -1
  286. }
  287. /* Assert CS# */
  288. buf[i++] = 0x02;
  289. buf[i++] = 0x10 | (writecnt + readcnt - 1);
  290. memcpy(buf + i, writearr, writecnt);
  291. i += writecnt;
  292. memset(buf + i, 0, readcnt);
  293. i += readcnt;
  294. /* De-assert CS# */
  295. buf[i++] = 0x03;
  296. ret = buspirate_sendrecv(buf, i, i);
  297. if (ret) {
  298. msg_perr("Bus Pirate communication error!\n");
  299. return SPI_GENERIC_ERROR;
  300. }
  301. if (buf[0] != 0x01) {
  302. msg_perr("Protocol error while lowering CS#!\n");
  303. return SPI_GENERIC_ERROR;
  304. }
  305. if (buf[1] != 0x01) {
  306. msg_perr("Protocol error while reading/writing SPI!\n");
  307. return SPI_GENERIC_ERROR;
  308. }
  309. if (buf[i - 1] != 0x01) {
  310. msg_perr("Protocol error while raising CS#!\n");
  311. return SPI_GENERIC_ERROR;
  312. }
  313. /* Skip CS#, length, writearr. */
  314. memcpy(readarr, buf + 2 + writecnt, readcnt);
  315. return ret;
  316. }