diff options
Diffstat (limited to 'bitbang_spi.c')
-rw-r--r-- | bitbang_spi.c | 124 |
1 files changed, 56 insertions, 68 deletions
diff --git a/bitbang_spi.c b/bitbang_spi.c index 5ee52f54..51fc9c60 100644 --- a/bitbang_spi.c +++ b/bitbang_spi.c @@ -25,42 +25,37 @@ #include "programmer.h" #include "spi.h" -/* Length of half a clock period in usecs. */ -static int bitbang_spi_half_period; - -static const struct bitbang_spi_master *bitbang_spi_master = NULL; - /* Note that CS# is active low, so val=0 means the chip is active. */ -static void bitbang_spi_set_cs(int val) +static void bitbang_spi_set_cs(const const struct bitbang_spi_master *master, int val) { - bitbang_spi_master->set_cs(val); + master->set_cs(val); } -static void bitbang_spi_set_sck(int val) +static void bitbang_spi_set_sck(const const struct bitbang_spi_master *master, int val) { - bitbang_spi_master->set_sck(val); + master->set_sck(val); } -static void bitbang_spi_set_mosi(int val) +static void bitbang_spi_set_mosi(const const struct bitbang_spi_master *master, int val) { - bitbang_spi_master->set_mosi(val); + master->set_mosi(val); } -static int bitbang_spi_get_miso(void) +static int bitbang_spi_get_miso(const const struct bitbang_spi_master *master) { - return bitbang_spi_master->get_miso(); + return master->get_miso(); } -static void bitbang_spi_request_bus(void) +static void bitbang_spi_request_bus(const const struct bitbang_spi_master *master) { - if (bitbang_spi_master->request_bus) - bitbang_spi_master->request_bus(); + if (master->request_bus) + master->request_bus(); } -static void bitbang_spi_release_bus(void) +static void bitbang_spi_release_bus(const const struct bitbang_spi_master *master) { - if (bitbang_spi_master->release_bus) - bitbang_spi_master->release_bus(); + if (master->release_bus) + master->release_bus(); } static int bitbang_spi_send_command(struct flashctx *flash, @@ -78,67 +73,59 @@ static const struct spi_programmer spi_programmer_bitbang = { .write_256 = default_spi_write_256, }; -int bitbang_spi_init(const struct bitbang_spi_master *master, int halfperiod) +#if 0 // until it is needed +static int bitbang_spi_shutdown(const struct bitbang_spi_master *master) { + /* FIXME: Run bitbang_spi_release_bus here or per command? */ + return 0; +} +#endif + +int bitbang_spi_init(const struct bitbang_spi_master *master) +{ + struct spi_programmer pgm = spi_programmer_bitbang; /* BITBANG_SPI_INVALID is 0, so if someone forgot to initialize ->type, * we catch it here. Same goes for missing initialization of bitbanging * functions. */ if (!master || master->type == BITBANG_SPI_INVALID || !master->set_cs || - !master->set_sck || !master->set_mosi || !master->get_miso) { + !master->set_sck || !master->set_mosi || !master->get_miso || + (master->request_bus && !master->release_bus) || + (!master->request_bus && master->release_bus)) { msg_perr("Incomplete SPI bitbang master setting!\n" "Please report a bug at flashrom@flashrom.org\n"); - return 1; - } - if (bitbang_spi_master) { - msg_perr("SPI bitbang master already initialized!\n" - "Please report a bug at flashrom@flashrom.org\n"); - return 1; + return ERROR_FLASHROM_BUG; } - bitbang_spi_master = master; - bitbang_spi_half_period = halfperiod; + pgm.data = master; + register_spi_programmer(&pgm); - register_spi_programmer(&spi_programmer_bitbang); - - /* FIXME: Run bitbang_spi_request_bus here or in programmer init? */ - bitbang_spi_set_cs(1); - bitbang_spi_set_sck(0); - bitbang_spi_set_mosi(0); - return 0; -} - -int bitbang_spi_shutdown(const struct bitbang_spi_master *master) -{ - if (!bitbang_spi_master) { - msg_perr("Shutting down an uninitialized SPI bitbang master!\n" - "Please report a bug at flashrom@flashrom.org\n"); - return 1; - } - if (master != bitbang_spi_master) { - msg_perr("Shutting down a mismatched SPI bitbang master!\n" - "Please report a bug at flashrom@flashrom.org\n"); - return 1; - } - - /* FIXME: Run bitbang_spi_release_bus here or per command? */ - bitbang_spi_master = NULL; + /* Only mess with the bus if we're sure nobody else uses it. */ + bitbang_spi_request_bus(master); + bitbang_spi_set_cs(master, 1); + bitbang_spi_set_sck(master, 0); + bitbang_spi_set_mosi(master, 0); + /* FIXME: Release SPI bus here and request it again for each command or + * don't release it now and only release it on programmer shutdown? + */ + bitbang_spi_release_bus(master); return 0; } -static uint8_t bitbang_spi_readwrite_byte(uint8_t val) +static uint8_t bitbang_spi_rw_byte(const struct bitbang_spi_master *master, + uint8_t val) { uint8_t ret = 0; int i; for (i = 7; i >= 0; i--) { - bitbang_spi_set_mosi((val >> i) & 1); - programmer_delay(bitbang_spi_half_period); - bitbang_spi_set_sck(1); + bitbang_spi_set_mosi(master, (val >> i) & 1); + programmer_delay(master->half_period); + bitbang_spi_set_sck(master, 1); ret <<= 1; - ret |= bitbang_spi_get_miso(); - programmer_delay(bitbang_spi_half_period); - bitbang_spi_set_sck(0); + ret |= bitbang_spi_get_miso(master); + programmer_delay(master->half_period); + bitbang_spi_set_sck(master, 0); } return ret; } @@ -149,23 +136,24 @@ static int bitbang_spi_send_command(struct flashctx *flash, unsigned char *readarr) { int i; + const struct bitbang_spi_master *master = flash->pgm->spi.data; /* FIXME: Run bitbang_spi_request_bus here or in programmer init? * Requesting and releasing the SPI bus is handled in here to allow the * programmer to use its own SPI engine for native accesses. */ - bitbang_spi_request_bus(); - bitbang_spi_set_cs(0); + bitbang_spi_request_bus(master); + bitbang_spi_set_cs(master, 0); for (i = 0; i < writecnt; i++) - bitbang_spi_readwrite_byte(writearr[i]); + bitbang_spi_rw_byte(master, writearr[i]); for (i = 0; i < readcnt; i++) - readarr[i] = bitbang_spi_readwrite_byte(0); + readarr[i] = bitbang_spi_rw_byte(master, 0); - programmer_delay(bitbang_spi_half_period); - bitbang_spi_set_cs(1); - programmer_delay(bitbang_spi_half_period); + programmer_delay(master->half_period); + bitbang_spi_set_cs(master, 1); + programmer_delay(master->half_period); /* FIXME: Run bitbang_spi_release_bus here or in programmer init? */ - bitbang_spi_release_bus(); + bitbang_spi_release_bus(master); return 0; } |