[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.dehttp://www.coresystems.de/
Registergericht: Amtsgericht Freiburg • HRB 7656
Geschäftsführer: Stefan Reinauer • Ust-IdNr.: DE245674866





More information about the flashrom mailing list