[flashrom] [PATCH] Create spi programmer struct
Stefan Reinauer
stepan at coresystems.de
Wed Jul 22 16:21:35 CEST 2009
On 7/22/09 4:17 PM, Carl-Daniel Hailfinger wrote:
> Replace most of the switch cases in the spi code with lookup on a struct
> instead. This brings the SPI code in line with the generic programmer
> infrastructure.
>
> This patch is a reworked version of a patch by Jakob Bornecrantz.
>
> Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>
>
I like this idea.
Acked-by: Stefan Reinauer <stepan at coresystems.de>
> Index: flashrom-spi_programmer_struct/flash.h
> ===================================================================
> --- flashrom-spi_programmer_struct/flash.h (Revision 656)
> +++ flashrom-spi_programmer_struct/flash.h (Arbeitskopie)
> @@ -420,8 +420,18 @@
> const unsigned char *writearr;
> unsigned char *readarr;
> };
> +struct spi_programmer {
> + int (*command)(unsigned int writecnt, unsigned int readcnt,
> + const unsigned char *writearr, unsigned char *readarr);
> + int (*multicommand)(struct spi_command *spicommands);
>
> + /* Optimized functions for this programmer */
> + int (*read)(struct flashchip *flash, uint8_t *buf, int start, int len);
> + int (*write_256)(struct flashchip *flash, uint8_t *buf);
> +};
> +
> extern enum spi_controller spi_controller;
> +extern const struct spi_programmer spi_programmer[];
> extern void *spibar;
> int probe_spi_rdid(struct flashchip *flash);
> int probe_spi_rdid4(struct flashchip *flash);
> @@ -452,6 +462,9 @@
> int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int start, int len, int chunksize);
> int spi_aai_write(struct flashchip *flash, uint8_t *buf);
> uint32_t spi_get_valid_read_addr(void);
> +int default_spi_send_command(unsigned int writecnt, unsigned int readcnt,
> + const unsigned char *writearr, unsigned char *readarr);
> +int default_spi_send_multicommand(struct spi_command *spicommands);
>
> /* 82802ab.c */
> int probe_82802ab(struct flashchip *flash);
> @@ -477,6 +490,7 @@
> const unsigned char *writearr, unsigned char *readarr);
> int ich_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len);
> int ich_spi_write_256(struct flashchip *flash, uint8_t * buf);
> +int ich_spi_send_multicommand(struct spi_command *spicommands);
>
> /* it87spi.c */
> extern char *it87opts;
> Index: flashrom-spi_programmer_struct/spi.c
> ===================================================================
> --- flashrom-spi_programmer_struct/spi.c (Revision 656)
> +++ flashrom-spi_programmer_struct/spi.c (Arbeitskopie)
> @@ -32,61 +32,125 @@
>
> void spi_prettyprint_status_register(struct flashchip *flash);
>
> +const struct spi_programmer spi_programmer[] = {
> + { /* SPI_CONTROLLER_NONE */
> + .command = NULL,
> + .multicommand = NULL,
> + .read = NULL,
> + .write_256 = NULL,
> + },
> +
> + { /* SPI_CONTROLLER_ICH7 */
> + .command = ich_spi_send_command,
> + .multicommand = ich_spi_send_multicommand,
> + .read = ich_spi_read,
> + .write_256 = ich_spi_write_256,
> + },
> +
> + { /* SPI_CONTROLLER_ICH9 */
> + .command = ich_spi_send_command,
> + .multicommand = ich_spi_send_multicommand,
> + .read = ich_spi_read,
> + .write_256 = ich_spi_write_256,
> + },
> +
> + { /* SPI_CONTROLLER_IT87XX */
> + .command = it8716f_spi_send_command,
> + .multicommand = default_spi_send_multicommand,
> + .read = it8716f_spi_chip_read,
> + .write_256 = it8716f_spi_chip_write_256,
> + },
> +
> + { /* SPI_CONTROLLER_SB600 */
> + .command = sb600_spi_send_command,
> + .multicommand = default_spi_send_multicommand,
> + .read = sb600_spi_read,
> + .write_256 = sb600_spi_write_1,
> + },
> +
> + { /* SPI_CONTROLLER_VIA */
> + .command = ich_spi_send_command,
> + .multicommand = ich_spi_send_multicommand,
> + .read = ich_spi_read,
> + .write_256 = ich_spi_write_256,
> + },
> +
> + { /* SPI_CONTROLLER_WBSIO */
> + .command = wbsio_spi_send_command,
> + .multicommand = default_spi_send_multicommand,
> + .read = wbsio_spi_read,
> + .write_256 = wbsio_spi_write_1,
> + },
> +
> + { /* SPI_CONTROLLER_FT2232 */
> + .command = ft2232_spi_send_command,
> + .multicommand = default_spi_send_multicommand,
> + .read = ft2232_spi_read,
> + .write_256 = ft2232_spi_write_256,
> + },
> +
> + { /* SPI_CONTROLLER_DUMMY */
> + .command = dummy_spi_send_command,
> + .multicommand = default_spi_send_multicommand,
> + .read = NULL,
> + .write_256 = NULL,
> + },
> +};
> +
> +
> int spi_send_command(unsigned int writecnt, unsigned int readcnt,
> const unsigned char *writearr, unsigned char *readarr)
> {
> - switch (spi_controller) {
> - case SPI_CONTROLLER_IT87XX:
> - return it8716f_spi_send_command(writecnt, readcnt, writearr,
> - readarr);
> - case SPI_CONTROLLER_ICH7:
> - case SPI_CONTROLLER_ICH9:
> - case SPI_CONTROLLER_VIA:
> - return ich_spi_send_command(writecnt, readcnt, writearr, readarr);
> - case SPI_CONTROLLER_SB600:
> - return sb600_spi_send_command(writecnt, readcnt, writearr, readarr);
> - case SPI_CONTROLLER_WBSIO:
> - return wbsio_spi_send_command(writecnt, readcnt, writearr, readarr);
> - case SPI_CONTROLLER_FT2232:
> - return ft2232_spi_send_command(writecnt, readcnt, writearr, readarr);
> - case SPI_CONTROLLER_DUMMY:
> - return dummy_spi_send_command(writecnt, readcnt, writearr, readarr);
> - default:
> - printf_debug
> - ("%s called, but no SPI chipset/strapping detected\n",
> - __FUNCTION__);
> + if (!spi_programmer[spi_controller].command) {
> + fprintf(stderr, "%s called, but SPI is unsupported on this "
> + "hardware. Please report a bug.\n", __func__);
> + return 1;
> }
> - return 1;
> +
> + return spi_programmer[spi_controller].command(writecnt, readcnt,
> + writearr, readarr);
> }
>
> int spi_send_multicommand(struct spi_command *spicommands)
> {
> - int ret = 0;
> - while ((spicommands->writecnt || spicommands->readcnt) && !ret) {
> - ret = spi_send_command(spicommands->writecnt, spicommands->readcnt,
> - spicommands->writearr, spicommands->readarr);
> - /* This awful hack needs to be replaced with a multicommand
> - * capable ICH/VIA SPI driver.
> - */
> - if ((ret == SPI_INVALID_OPCODE) &&
> - ((spicommands->writearr[0] == JEDEC_WREN) ||
> - (spicommands->writearr[0] == JEDEC_EWSR))) {
> - switch (spi_controller) {
> - case SPI_CONTROLLER_ICH7:
> - case SPI_CONTROLLER_ICH9:
> - case SPI_CONTROLLER_VIA:
> - printf_debug(" due to SPI master limitation, ignoring"
> - " and hoping it will be run as PREOP\n");
> - ret = 0;
> - default:
> - break;
> - }
> - }
> - spicommands++;
> + if (!spi_programmer[spi_controller].multicommand) {
> + fprintf(stderr, "%s called, but SPI is unsupported on this "
> + "hardware. Please report a bug.\n", __func__);
> + return 1;
> }
> - return ret;
> +
> + return spi_programmer[spi_controller].multicommand(spicommands);
> }
>
> +int default_spi_send_command(unsigned int writecnt, unsigned int readcnt,
> + const unsigned char *writearr, unsigned char *readarr)
> +{
> + struct spi_command cmd[] = {
> + {
> + .writecnt = writecnt,
> + .readcnt = readcnt,
> + .writearr = writearr,
> + .readarr = readarr,
> + }, {
> + .writecnt = 0,
> + .writearr = NULL,
> + .readcnt = 0,
> + .readarr = NULL,
> + }};
> +
> + return spi_send_multicommand(cmd);
> +}
> +
> +int default_spi_send_multicommand(struct spi_command *spicommands)
> +{
> + int result = 0;
> + while ((spicommands->writecnt || spicommands->readcnt) && !result) {
> + result = spi_send_command(spicommands->writecnt, spicommands->readcnt,
> + spicommands->writearr, spicommands->readarr);
> + }
> + return result;
> +}
> +
> static int spi_rdid(unsigned char *readarr, int bytes)
> {
> const unsigned char cmd[JEDEC_RDID_OUTSIZE] = { JEDEC_RDID };
> @@ -298,18 +362,18 @@
> uint8_t spi_read_status_register(void)
> {
> const unsigned char cmd[JEDEC_RDSR_OUTSIZE] = { JEDEC_RDSR };
> + /* FIXME: No workarounds for driver/hardware bugs in generic code. */
> unsigned char readarr[2]; /* JEDEC_RDSR_INSIZE=1 but wbsio needs 2 */
> int ret;
>
> /* Read Status Register */
> - if (spi_controller == SPI_CONTROLLER_SB600) {
> - /* SB600 uses a different way to read status register. */
> + if (spi_controller == SPI_CONTROLLER_SB600) { /* FIXME */
> + /* Workaround for SB600 hardware bug. Can be killed later. */
> return sb600_read_status_register();
> - } else {
> - ret = spi_send_command(sizeof(cmd), sizeof(readarr), cmd, readarr);
> - if (ret)
> - printf_debug("RDSR failed!\n");
> }
> + ret = spi_send_command(sizeof(cmd), sizeof(readarr), cmd, readarr);
> + if (ret)
> + printf_debug("RDSR failed!\n");
>
> return readarr[0];
> }
> @@ -875,26 +939,13 @@
>
> int spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len)
> {
> - switch (spi_controller) {
> - case SPI_CONTROLLER_IT87XX:
> - return it8716f_spi_chip_read(flash, buf, start, len);
> - case SPI_CONTROLLER_SB600:
> - return sb600_spi_read(flash, buf, start, len);
> - case SPI_CONTROLLER_ICH7:
> - case SPI_CONTROLLER_ICH9:
> - case SPI_CONTROLLER_VIA:
> - return ich_spi_read(flash, buf, start, len);
> - case SPI_CONTROLLER_WBSIO:
> - return wbsio_spi_read(flash, buf, start, len);
> - case SPI_CONTROLLER_FT2232:
> - return ft2232_spi_read(flash, buf, start, len);
> - default:
> - printf_debug
> - ("%s called, but no SPI chipset/strapping detected\n",
> - __FUNCTION__);
> + if (!spi_programmer[spi_controller].read) {
> + fprintf(stderr, "%s called, but SPI read is unsupported on this"
> + " hardware. Please report a bug.\n", __func__);
> + return 1;
> }
>
> - return 1;
> + return spi_programmer[spi_controller].read(flash, buf, start, len);
> }
>
> /*
> @@ -924,26 +975,13 @@
> */
> int spi_chip_write_256(struct flashchip *flash, uint8_t *buf)
> {
> - switch (spi_controller) {
> - case SPI_CONTROLLER_IT87XX:
> - return it8716f_spi_chip_write_256(flash, buf);
> - case SPI_CONTROLLER_SB600:
> - return sb600_spi_write_1(flash, buf);
> - case SPI_CONTROLLER_ICH7:
> - case SPI_CONTROLLER_ICH9:
> - case SPI_CONTROLLER_VIA:
> - return ich_spi_write_256(flash, buf);
> - case SPI_CONTROLLER_WBSIO:
> - return wbsio_spi_write_1(flash, buf);
> - case SPI_CONTROLLER_FT2232:
> - return ft2232_spi_write_256(flash, buf);
> - default:
> - printf_debug
> - ("%s called, but no SPI chipset/strapping detected\n",
> - __FUNCTION__);
> + if (!spi_programmer[spi_controller].write_256) {
> + fprintf(stderr, "%s called, but SPI page write is unsupported "
> + " on this hardware. Please report a bug.\n", __func__);
> + return 1;
> }
>
> - return 1;
> + return spi_programmer[spi_controller].write_256(flash, buf);
> }
>
> uint32_t spi_get_valid_read_addr(void)
> Index: flashrom-spi_programmer_struct/ichspi.c
> ===================================================================
> --- flashrom-spi_programmer_struct/ichspi.c (Revision 656)
> +++ flashrom-spi_programmer_struct/ichspi.c (Arbeitskopie)
> @@ -742,3 +742,23 @@
>
> return result;
> }
> +
> +int ich_spi_send_multicommand(struct spi_command *spicommands)
> +{
> + int ret = 0;
> + while ((spicommands->writecnt || spicommands->readcnt) && !ret) {
> + ret = ich_spi_send_command(spicommands->writecnt, spicommands->readcnt,
> + spicommands->writearr, spicommands->readarr);
> + /* This awful hack needs to be smarter.
> + */
> + if ((ret == SPI_INVALID_OPCODE) &&
> + ((spicommands->writearr[0] == JEDEC_WREN) ||
> + (spicommands->writearr[0] == JEDEC_EWSR))) {
> + printf_debug(" due to SPI master limitation, ignoring"
> + " and hoping it will be run as PREOP\n");
> + ret = 0;
> + }
> + spicommands++;
> + }
> + return ret;
> +}
>
>
>
--
coresystems GmbH • Brahmsstr. 16 • D-79104 Freiburg i. Br.
Tel.: +49 761 7668825 • Fax: +49 761 7664613
Email: info at coresystems.de • http://www.coresystems.de/
Registergericht: Amtsgericht Freiburg • HRB 7656
Geschäftsführer: Stefan Reinauer • Ust-IdNr.: DE245674866
More information about the flashrom
mailing list