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