mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-26 22:52:34 +02:00

Mostly by changing to `unsigned` types where applicable, sometimes `signed` types, and casting as a last resort. Change-Id: I08895543ffb7a48058bcf91ef6500ca113f2d305 Signed-off-by: Nico Huber <nico.h@gmx.de> Reviewed-on: https://review.coreboot.org/c/flashrom/+/30409 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Jacob Garber <jgarber1@ualberta.ca>
221 lines
5.5 KiB
C
221 lines
5.5 KiB
C
/*
|
|
* This file is part of the flashrom project.
|
|
*
|
|
* Copyright (C) 2012 James Laird <jhl@mafipulation.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; version 2 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
/*
|
|
* Device should be connected as per "active serial" mode:
|
|
*
|
|
* +---------+------+-----------+
|
|
* | SPI | Pin | Altera |
|
|
* +---------+------+-----------+
|
|
* | SCLK | 1 | DCLK |
|
|
* | GND | 2,10 | GND |
|
|
* | VCC | 4 | VCC(TRGT) |
|
|
* | MISO | 7 | DATAOUT |
|
|
* | /CS | 8 | nCS |
|
|
* | MOSI | 9 | ASDI |
|
|
* +---------+------+-----------+
|
|
*
|
|
* See also the USB-Blaster Download Cable User Guide: http://www.altera.com/literature/ug/ug_usb_blstr.pdf
|
|
*/
|
|
|
|
#if CONFIG_USBBLASTER_SPI == 1
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <ftdi.h>
|
|
#include "flash.h"
|
|
#include "programmer.h"
|
|
#include "spi.h"
|
|
|
|
/* Please keep sorted by vendor ID, then device ID. */
|
|
#define ALTERA_VID 0x09fb
|
|
#define ALTERA_USBBLASTER_PID 0x6001
|
|
|
|
const struct dev_entry devs_usbblasterspi[] = {
|
|
{ALTERA_VID, ALTERA_USBBLASTER_PID, OK, "Altera", "USB-Blaster"},
|
|
|
|
{}
|
|
};
|
|
|
|
static const struct spi_master spi_master_usbblaster;
|
|
|
|
static struct ftdi_context ftdic;
|
|
|
|
// command bytes
|
|
#define BIT_BYTE (1<<7) // byte mode (rather than bitbang)
|
|
#define BIT_READ (1<<6) // read request
|
|
#define BIT_LED (1<<5)
|
|
#define BIT_CS (1<<3)
|
|
#define BIT_TMS (1<<1)
|
|
#define BIT_CLK (1<<0)
|
|
|
|
#define BUF_SIZE 64
|
|
|
|
/* The programmer shifts bits in the wrong order for SPI, so we use this method to reverse the bits when needed.
|
|
* http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits */
|
|
static uint8_t reverse(uint8_t b)
|
|
{
|
|
return ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
|
|
}
|
|
|
|
|
|
/* Returns 0 upon success, a negative number upon errors. */
|
|
int usbblaster_spi_init(void)
|
|
{
|
|
uint8_t buf[BUF_SIZE + 1];
|
|
|
|
if (ftdi_init(&ftdic) < 0)
|
|
return -1;
|
|
|
|
if (ftdi_usb_open(&ftdic, ALTERA_VID, ALTERA_USBBLASTER_PID) < 0) {
|
|
msg_perr("Failed to open USB-Blaster: %s\n", ftdic.error_str);
|
|
return -1;
|
|
}
|
|
|
|
if (ftdi_usb_reset(&ftdic) < 0) {
|
|
msg_perr("USB-Blaster reset failed\n");
|
|
return -1;
|
|
}
|
|
|
|
if (ftdi_set_latency_timer(&ftdic, 2) < 0) {
|
|
msg_perr("USB-Blaster set latency timer failed\n");
|
|
return -1;
|
|
}
|
|
|
|
if (ftdi_write_data_set_chunksize(&ftdic, 4096) < 0 ||
|
|
ftdi_read_data_set_chunksize(&ftdic, BUF_SIZE) < 0) {
|
|
msg_perr("USB-Blaster set chunk size failed\n");
|
|
return -1;
|
|
}
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
buf[sizeof(buf)-1] = BIT_LED | BIT_CS;
|
|
if (ftdi_write_data(&ftdic, buf, sizeof(buf)) < 0) {
|
|
msg_perr("USB-Blaster reset write failed\n");
|
|
return -1;
|
|
}
|
|
if (ftdi_read_data(&ftdic, buf, sizeof(buf)) < 0) {
|
|
msg_perr("USB-Blaster reset read failed\n");
|
|
return -1;
|
|
}
|
|
|
|
register_spi_master(&spi_master_usbblaster);
|
|
return 0;
|
|
}
|
|
|
|
static int send_write(unsigned int writecnt, const unsigned char *writearr)
|
|
{
|
|
uint8_t buf[BUF_SIZE];
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
while (writecnt) {
|
|
unsigned int i;
|
|
unsigned int n_write = min(writecnt, BUF_SIZE - 1);
|
|
msg_pspew("writing %d-byte packet\n", n_write);
|
|
|
|
buf[0] = BIT_BYTE | (uint8_t)n_write;
|
|
for (i = 0; i < n_write; i++) {
|
|
buf[i+1] = reverse(writearr[i]);
|
|
}
|
|
if (ftdi_write_data(&ftdic, buf, n_write + 1) < 0) {
|
|
msg_perr("USB-Blaster write failed\n");
|
|
return -1;
|
|
}
|
|
|
|
writearr += n_write;
|
|
writecnt -= n_write;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int send_read(unsigned int readcnt, unsigned char *readarr)
|
|
{
|
|
int i;
|
|
unsigned int n_read;
|
|
uint8_t buf[BUF_SIZE];
|
|
memset(buf, 0, sizeof(buf));
|
|
|
|
n_read = readcnt;
|
|
while (n_read) {
|
|
unsigned int payload_size = min(n_read, BUF_SIZE - 1);
|
|
msg_pspew("reading %d-byte packet\n", payload_size);
|
|
|
|
buf[0] = BIT_BYTE | BIT_READ | (uint8_t)payload_size;
|
|
if (ftdi_write_data(&ftdic, buf, payload_size + 1) < 0) {
|
|
msg_perr("USB-Blaster write failed\n");
|
|
return -1;
|
|
}
|
|
n_read -= payload_size;
|
|
};
|
|
|
|
n_read = readcnt;
|
|
while (n_read) {
|
|
int ret = ftdi_read_data(&ftdic, readarr, n_read);
|
|
if (ret < 0) {
|
|
msg_perr("USB-Blaster read failed\n");
|
|
return -1;
|
|
}
|
|
for (i = 0; i < ret; i++) {
|
|
readarr[i] = reverse(readarr[i]);
|
|
}
|
|
n_read -= ret;
|
|
readarr += ret;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Returns 0 upon success, a negative number upon errors. */
|
|
static int usbblaster_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
|
|
const unsigned char *writearr, unsigned char *readarr)
|
|
{
|
|
uint8_t cmd;
|
|
int ret = 0;
|
|
|
|
cmd = BIT_LED; // asserts /CS
|
|
if (ftdi_write_data(&ftdic, &cmd, 1) < 0) {
|
|
msg_perr("USB-Blaster enable chip select failed\n");
|
|
ret = -1;
|
|
}
|
|
|
|
if (!ret && writecnt)
|
|
ret = send_write(writecnt, writearr);
|
|
|
|
if (!ret && readcnt)
|
|
ret = send_read(readcnt, readarr);
|
|
|
|
cmd = BIT_CS;
|
|
if (ftdi_write_data(&ftdic, &cmd, 1) < 0) {
|
|
msg_perr("USB-Blaster disable chip select failed\n");
|
|
ret = -1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static const struct spi_master spi_master_usbblaster = {
|
|
.max_data_read = 256,
|
|
.max_data_write = 256,
|
|
.command = usbblaster_spi_send_command,
|
|
.multicommand = default_spi_send_multicommand,
|
|
.read = default_spi_read,
|
|
.write_256 = default_spi_write_256,
|
|
.write_aai = default_spi_write_aai,
|
|
};
|
|
|
|
#endif
|