summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2011-12-20 00:19:29 +0000
committerCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2011-12-20 00:19:29 +0000
commitc40cff7b86848f5b248d7fcf20f7d517b60c385d (patch)
tree7f9db61c7b4868e513c4702cfe57bb35ae695266
parent8a3c60cdd0e5632173567923ae1927763e31e857 (diff)
downloadast2050-flashrom-c40cff7b86848f5b248d7fcf20f7d517b60c385d.zip
ast2050-flashrom-c40cff7b86848f5b248d7fcf20f7d517b60c385d.tar.gz
Have all programmer init functions register bus masters/programmers
All programmer types (Parallel, SPI, Opaque) now register themselves into a generic programmer list and probing is now programmer-centric instead of chip-centric. Registering multiple SPI/... masters at the same time is now possible without any problems. Handling multiple flash chips is still unchanged, but now we have the infrastructure to deal with "dual BIOS" and "one flash behind southbridge and one flash behind EC" sanely. A nice side effect is that this patch kills quite a few global variables and improves the situation for libflashrom. Hint for developers: struct {spi,par,opaque}_programmer now have a void *data pointer to store any additional programmer-specific data, e.g. hardware configuration info. Note: flashrom -f -c FOO -r forced_read.bin does not work anymore. We have to find an architecturally clean way to solve this. Corresponding to flashrom svn r1475. Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Acked-by: Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>
-rw-r--r--bitbang_spi.c124
-rw-r--r--cli_classic.c26
-rw-r--r--flash.h12
-rw-r--r--flashrom.c39
-rw-r--r--ichspi.c12
-rw-r--r--mcp6x_spi.c4
-rw-r--r--nicintel_spi.c4
-rw-r--r--ogp_spi.c4
-rw-r--r--opaque.c59
-rw-r--r--programmer.c69
-rw-r--r--programmer.h32
-rw-r--r--rayer_spi.c4
-rw-r--r--spi.c75
-rw-r--r--spi25.c4
14 files changed, 217 insertions, 251 deletions
diff --git a/bitbang_spi.c b/bitbang_spi.c
index 5ee52f5..51fc9c6 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;
}
diff --git a/cli_classic.c b/cli_classic.c
index bb8c29f..543b644 100644
--- a/cli_classic.c
+++ b/cli_classic.c
@@ -172,7 +172,7 @@ int main(int argc, char *argv[])
struct flashctx flashes[3];
struct flashctx *fill_flash;
const char *name;
- int namelen, opt, i;
+ int namelen, opt, i, j;
int startchip = 0, chipcount = 0, option_index = 0, force = 0;
#if CONFIG_PRINT_WIKI == 1
int list_supported_wiki = 0;
@@ -444,17 +444,21 @@ int main(int argc, char *argv[])
ret = 1;
goto out_shutdown;
}
- tempstr = flashbuses_to_text(buses_supported);
- msg_pdbg("This programmer supports the following protocols: %s.\n",
+ tempstr = flashbuses_to_text(get_buses_supported());
+ msg_pdbg("The following protocols are supported: %s.\n",
tempstr);
free(tempstr);
- for (i = 0; i < ARRAY_SIZE(flashes); i++) {
- startchip = probe_flash(startchip, &flashes[i], 0);
- if (startchip == -1)
- break;
- chipcount++;
- startchip++;
+ for (j = 0; j < registered_programmer_count; j++) {
+ startchip = 0;
+ for (i = 0; i < ARRAY_SIZE(flashes); i++) {
+ startchip = probe_flash(&registered_programmers[j],
+ startchip, &flashes[i], 0);
+ if (startchip == -1)
+ break;
+ chipcount++;
+ startchip++;
+ }
}
if (chipcount > 1) {
@@ -472,6 +476,7 @@ int main(int argc, char *argv[])
printf("Note: flashrom can never write if the flash "
"chip isn't found automatically.\n");
}
+#if 0 // FIXME: What happens for a forced chip read if multiple compatible programmers are registered?
if (force && read_it && chip_to_probe) {
printf("Force read (-f -r -c) requested, pretending "
"the chip is there:\n");
@@ -486,6 +491,7 @@ int main(int argc, char *argv[])
"contain garbage.\n");
return read_flash_to_file(&flashes[0], filename);
}
+#endif
ret = 1;
goto out_shutdown;
} else if (!chip_to_probe) {
@@ -502,7 +508,7 @@ int main(int argc, char *argv[])
check_chip_supported(fill_flash);
size = fill_flash->total_size * 1024;
- if (check_max_decode((buses_supported & fill_flash->bustype), size) &&
+ if (check_max_decode(fill_flash->pgm->buses_supported & fill_flash->bustype, size) &&
(!force)) {
fprintf(stderr, "Chip is too big for this programmer "
"(-V gives details). Use --force to override.\n");
diff --git a/flash.h b/flash.h
index 29ba193..e21a986 100644
--- a/flash.h
+++ b/flash.h
@@ -171,6 +171,7 @@ struct flashctx {
chipaddr virtual_memory;
/* Some flash devices have an additional register space. */
chipaddr virtual_registers;
+ struct registered_programmer *pgm;
};
#define TEST_UNTESTED 0
@@ -224,14 +225,13 @@ enum write_granularity {
write_gran_1byte,
write_gran_256bytes,
};
-extern enum chipbustype buses_supported;
extern int verbose;
extern const char flashrom_version[];
extern char *chip_to_probe;
void map_flash_registers(struct flashctx *flash);
int read_memmapped(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
int erase_flash(struct flashctx *flash);
-int probe_flash(int startchip, struct flashctx *fill_flash, int force);
+int probe_flash(struct registered_programmer *pgm, int startchip, struct flashctx *fill_flash, int force);
int read_flash_to_file(struct flashctx *flash, const char *filename);
int min(int a, int b);
int max(int a, int b);
@@ -256,6 +256,13 @@ int write_buf_to_file(unsigned char *buf, unsigned long size, const char *filena
/* Something happened that shouldn't happen, we'll abort. */
#define ERROR_FATAL -0xee
+#define ERROR_FLASHROM_BUG -200
+/* We reached one of the hardcoded limits of flashrom. This can be fixed by
+ * increasing the limit of a compile-time allocation or by switching to dynamic
+ * allocation.
+ * Note: If this warning is triggered, check first for runaway registrations.
+ */
+#define ERROR_FLASHROM_LIMIT -201
/* cli_output.c */
/* Let gcc and clang check for correct printf-style format strings. */
@@ -297,4 +304,5 @@ int spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int
int spi_send_multicommand(struct flashctx *flash, struct spi_command *cmds);
uint32_t spi_get_valid_read_addr(struct flashctx *flash);
+enum chipbustype get_buses_supported(void);
#endif /* !__FLASH_H__ */
diff --git a/flashrom.c b/flashrom.c
index f7a17d1..f1a6165 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -46,9 +46,6 @@ static enum programmer programmer = PROGRAMMER_INVALID;
static char *programmer_param = NULL;
-/* Supported buses for the current programmer. */
-enum chipbustype buses_supported;
-
/*
* Programmers supporting multiple buses can have differing size limits on
* each bus. Store the limits for each bus in a common struct.
@@ -314,7 +311,6 @@ int programmer_init(enum programmer prog, char *param)
.fwh = 0xffffffff,
.spi = 0xffffffff,
};
- buses_supported = BUS_NONE;
/* Default to top aligned flash at 4 GB. */
flashbase = 0;
/* Registering shutdown functions is now allowed. */
@@ -361,44 +357,44 @@ void programmer_unmap_flash_region(void *virt_addr, size_t len)
void chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr)
{
- par_programmer->chip_writeb(flash, val, addr);
+ flash->pgm->par.chip_writeb(flash, val, addr);
}
void chip_writew(const struct flashctx *flash, uint16_t val, chipaddr addr)
{
- par_programmer->chip_writew(flash, val, addr);
+ flash->pgm->par.chip_writew(flash, val, addr);
}
void chip_writel(const struct flashctx *flash, uint32_t val, chipaddr addr)
{
- par_programmer->chip_writel(flash, val, addr);
+ flash->pgm->par.chip_writel(flash, val, addr);
}
void chip_writen(const struct flashctx *flash, uint8_t *buf, chipaddr addr,
size_t len)
{
- par_programmer->chip_writen(flash, buf, addr, len);
+ flash->pgm->par.chip_writen(flash, buf, addr, len);
}
uint8_t chip_readb(const struct flashctx *flash, const chipaddr addr)
{
- return par_programmer->chip_readb(flash, addr);
+ return flash->pgm->par.chip_readb(flash, addr);
}
uint16_t chip_readw(const struct flashctx *flash, const chipaddr addr)
{
- return par_programmer->chip_readw(flash, addr);
+ return flash->pgm->par.chip_readw(flash, addr);
}
uint32_t chip_readl(const struct flashctx *flash, const chipaddr addr)
{
- return par_programmer->chip_readl(flash, addr);
+ return flash->pgm->par.chip_readl(flash, addr);
}
void chip_readn(const struct flashctx *flash, uint8_t *buf, chipaddr addr,
size_t len)
{
- par_programmer->chip_readn(flash, buf, addr, len);
+ flash->pgm->par.chip_readn(flash, buf, addr, len);
}
void programmer_delay(int usecs)
@@ -942,7 +938,8 @@ int check_max_decode(enum chipbustype buses, uint32_t size)
return 1;
}
-int probe_flash(int startchip, struct flashctx *fill_flash, int force)
+int probe_flash(struct registered_programmer *pgm, int startchip,
+ struct flashctx *fill_flash, int force)
{
const struct flashchip *flash;
unsigned long base = 0;
@@ -954,20 +951,9 @@ int probe_flash(int startchip, struct flashctx *fill_flash, int force)
for (flash = flashchips + startchip; flash && flash->name; flash++) {
if (chip_to_probe && strcmp(flash->name, chip_to_probe) != 0)
continue;
- buses_common = buses_supported & flash->bustype;
- if (!buses_common) {
- msg_gspew("Probing for %s %s, %d kB: skipped. ",
- flash->vendor, flash->name, flash->total_size);
- tmp = flashbuses_to_text(buses_supported);
- msg_gspew("Host bus type %s ", tmp);
- free(tmp);
- tmp = flashbuses_to_text(flash->bustype);
- msg_gspew("and chip bus type %s are incompatible.",
- tmp);
- free(tmp);
- msg_gspew("\n");
+ buses_common = pgm->buses_supported & flash->bustype;
+ if (!buses_common)
continue;
- }
msg_gdbg("Probing for %s %s, %d kB: ",
flash->vendor, flash->name, flash->total_size);
if (!flash->probe && !force) {
@@ -981,6 +967,7 @@ int probe_flash(int startchip, struct flashctx *fill_flash, int force)
/* Start filling in the dynamic data. */
memcpy(fill_flash, flash, sizeof(struct flashchip));
+ fill_flash->pgm = pgm;
base = flashbase ? flashbase : (0xffffffff - size + 1);
fill_flash->virtual_memory = (chipaddr)programmer_map_flash_region("flash chip", base, size);
diff --git a/ichspi.c b/ichspi.c
index 6bcea45..163ecf1 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -635,7 +635,7 @@ static void ich_set_bbar(uint32_t min_addr)
/* Read len bytes from the fdata/spid register into the data array.
*
- * Note that using len > spi_programmer->max_data_read will return garbage or
+ * Note that using len > flash->pgm->spi.max_data_read will return garbage or
* may even crash.
*/
static void ich_read_data(uint8_t *data, int len, int reg0_off)
@@ -653,7 +653,7 @@ static void ich_read_data(uint8_t *data, int len, int reg0_off)
/* Fill len bytes from the data array into the fdata/spid registers.
*
- * Note that using len > spi_programmer->max_data_write will trash the registers
+ * Note that using len > flash->pgm->spi.max_data_write will trash the registers
* following the data registers.
*/
static void ich_fill_data(const uint8_t *data, int len, int reg0_off)
@@ -960,9 +960,9 @@ static int run_opcode(const struct flashctx *flash, OPCODE op, uint32_t offset,
uint8_t datalength, uint8_t * data)
{
/* max_data_read == max_data_write for all Intel/VIA SPI masters */
- uint8_t maxlength = spi_programmer->max_data_read;
+ uint8_t maxlength = flash->pgm->spi.max_data_read;
- if (spi_programmer->type == SPI_CONTROLLER_NONE) {
+ if (ich_generation == CHIPSET_ICH_UNKNOWN) {
msg_perr("%s: unsupported chipset\n", __func__);
return -1;
}
@@ -1297,7 +1297,7 @@ static int ich_hwseq_read(struct flashctx *flash, uint8_t *buf,
REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
while (len > 0) {
- block_len = min(len, opaque_programmer->max_data_read);
+ block_len = min(len, flash->pgm->opaque.max_data_read);
ich_hwseq_set_addr(addr);
hsfc = REGREAD16(ICH9_REG_HSFC);
hsfc &= ~HSFC_FCYCLE; /* set read operation */
@@ -1336,7 +1336,7 @@ static int ich_hwseq_write(struct flashctx *flash, uint8_t *buf,
while (len > 0) {
ich_hwseq_set_addr(addr);
- block_len = min(len, opaque_programmer->max_data_write);
+ block_len = min(len, flash->pgm->opaque.max_data_write);
ich_fill_data(buf, block_len, ICH9_REG_FDATA0);
hsfc = REGREAD16(ICH9_REG_HSFC);
hsfc &= ~HSFC_FCYCLE; /* clear operation */
diff --git a/mcp6x_spi.c b/mcp6x_spi.c
index d2c31be..23f39a5 100644
--- a/mcp6x_spi.c
+++ b/mcp6x_spi.c
@@ -98,6 +98,7 @@ static const struct bitbang_spi_master bitbang_spi_master_mcp6x = {
.get_miso = mcp6x_bitbang_get_miso,
.request_bus = mcp6x_request_spibus,
.release_bus = mcp6x_release_spibus,
+ .half_period = 0,
};
int mcp6x_spi_init(int want_spi)
@@ -159,8 +160,7 @@ int mcp6x_spi_init(int want_spi)
(status >> MCP6X_SPI_GRANT) & 0x1);
mcp_gpiostate = status & 0xff;
- /* Zero halfperiod delay. */
- if (bitbang_spi_init(&bitbang_spi_master_mcp6x, 0)) {
+ if (bitbang_spi_init(&bitbang_spi_master_mcp6x)) {
/* This should never happen. */
msg_perr("MCP6X bitbang SPI master init failed!\n");
return 1;
diff --git a/nicintel_spi.c b/nicintel_spi.c
index aacd68c..f9432ec 100644
--- a/nicintel_spi.c
+++ b/nicintel_spi.c
@@ -137,6 +137,7 @@ static const struct bitbang_spi_master bitbang_spi_master_nicintel = {
.get_miso = nicintel_bitbang_get_miso,
.request_bus = nicintel_request_spibus,
.release_bus = nicintel_release_spibus,
+ .half_period = 1,
};
static int nicintel_spi_shutdown(void *data)
@@ -181,8 +182,7 @@ int nicintel_spi_init(void)
if (register_shutdown(nicintel_spi_shutdown, NULL))
return 1;
- /* 1 usec halfperiod delay for now. */
- if (bitbang_spi_init(&bitbang_spi_master_nicintel, 1))
+ if (bitbang_spi_init(&bitbang_spi_master_nicintel))
return 1;
return 0;
diff --git a/ogp_spi.c b/ogp_spi.c
index dbaa57a..812420c 100644
--- a/ogp_spi.c
+++ b/ogp_spi.c
@@ -91,6 +91,7 @@ static const struct bitbang_spi_master bitbang_spi_master_ogp = {
.get_miso = ogp_bitbang_get_miso,
.request_bus = ogp_request_spibus,
.release_bus = ogp_release_spibus,
+ .half_period = 0,
};
static int ogp_spi_shutdown(void *data)
@@ -136,8 +137,7 @@ int ogp_spi_init(void)
if (register_shutdown(ogp_spi_shutdown, NULL))
return 1;
- /* no delay for now. */
- if (bitbang_spi_init(&bitbang_spi_master_ogp, 0))
+ if (bitbang_spi_init(&bitbang_spi_master_ogp))
return 1;
return 0;
diff --git a/opaque.c b/opaque.c
index 43ddb07..6acaa63 100644
--- a/opaque.c
+++ b/opaque.c
@@ -30,70 +30,37 @@
#include "chipdrivers.h"
#include "programmer.h"
-const struct opaque_programmer opaque_programmer_none = {
- .max_data_read = MAX_DATA_UNSPECIFIED,
- .max_data_write = MAX_DATA_UNSPECIFIED,
- .probe = NULL,
- .read = NULL,
- .write = NULL,
- .erase = NULL,
-};
-
-const struct opaque_programmer *opaque_programmer = &opaque_programmer_none;
-
int probe_opaque(struct flashctx *flash)
{
- if (!opaque_programmer->probe) {
- msg_perr("%s called before register_opaque_programmer. "
- "Please report a bug at flashrom@flashrom.org\n",
- __func__);
- return 0;
- }
-
- return opaque_programmer->probe(flash);
+ return flash->pgm->opaque.probe(flash);
}
int read_opaque(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
{
- if (!opaque_programmer->read) {
- msg_perr("%s called before register_opaque_programmer. "
- "Please report a bug at flashrom@flashrom.org\n",
- __func__);
- return 1;
- }
- return opaque_programmer->read(flash, buf, start, len);
+ return flash->pgm->opaque.read(flash, buf, start, len);
}
int write_opaque(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
{
- if (!opaque_programmer->write) {
- msg_perr("%s called before register_opaque_programmer. "
- "Please report a bug at flashrom@flashrom.org\n",
- __func__);
- return 1;
- }
- return opaque_programmer->write(flash, buf, start, len);
+ return flash->pgm->opaque.write(flash, buf, start, len);
}
int erase_opaque(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen)
{
- if (!opaque_programmer->erase) {
- msg_perr("%s called before register_opaque_programmer. "
- "Please report a bug at flashrom@flashrom.org\n",
- __func__);
- return 1;
- }
- return opaque_programmer->erase(flash, blockaddr, blocklen);
+ return flash->pgm->opaque.erase(flash, blockaddr, blocklen);
}
-void register_opaque_programmer(const struct opaque_programmer *pgm)
+int register_opaque_programmer(const struct opaque_programmer *pgm)
{
+ struct registered_programmer rpgm;
+
if (!pgm->probe || !pgm->read || !pgm->write || !pgm->erase) {
- msg_perr("%s called with one of probe/read/write/erase being "
- "NULL. Please report a bug at flashrom@flashrom.org\n",
+ msg_perr("%s called with incomplete programmer definition. "
+ "Please report a bug at flashrom@flashrom.org\n",
__func__);
- return;
+ return ERROR_FLASHROM_BUG;
}
- opaque_programmer = pgm;
- buses_supported |= BUS_PROG;
+ rpgm.buses_supported = BUS_PROG;
+ rpgm.opaque = *pgm;
+ return register_programmer(&rpgm);
}
diff --git a/programmer.c b/programmer.c
index 2928d68..3b4def0 100644
--- a/programmer.c
+++ b/programmer.c
@@ -21,19 +21,6 @@
#include "flash.h"
#include "programmer.h"
-static const struct par_programmer par_programmer_none = {
- .chip_readb = noop_chip_readb,
- .chip_readw = fallback_chip_readw,
- .chip_readl = fallback_chip_readl,
- .chip_readn = fallback_chip_readn,
- .chip_writeb = noop_chip_writeb,
- .chip_writew = fallback_chip_writew,
- .chip_writel = fallback_chip_writel,
- .chip_writen = fallback_chip_writen,
-};
-
-const struct par_programmer *par_programmer = &par_programmer_none;
-
/* No-op shutdown() for programmers which don't need special handling */
int noop_shutdown(void)
{
@@ -52,13 +39,7 @@ void fallback_unmap(void *virt_addr, size_t len)
{
}
-/* No-op chip_writeb() for drivers not supporting addr/data pair accesses */
-uint8_t noop_chip_readb(const struct flashctx *flash, const chipaddr addr)
-{
- return 0xff;
-}
-
-/* No-op chip_writeb() for drivers not supporting addr/data pair accesses */
+/* No-op chip_writeb() for parallel style drivers not supporting writes */
void noop_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr)
{
}
@@ -115,8 +96,50 @@ void fallback_chip_readn(const struct flashctx *flash, uint8_t *buf,
return;
}
-void register_par_programmer(const struct par_programmer *pgm, const enum chipbustype buses)
+int register_par_programmer(const struct par_programmer *pgm,
+ const enum chipbustype buses)
+{
+ struct registered_programmer rpgm;
+ if (!pgm->chip_writeb || !pgm->chip_writew || !pgm->chip_writel ||
+ !pgm->chip_writen || !pgm->chip_readb || !pgm->chip_readw ||
+ !pgm->chip_readl || !pgm->chip_readn) {
+ msg_perr("%s called with incomplete programmer definition. "
+ "Please report a bug at flashrom@flashrom.org\n",
+ __func__);
+ return ERROR_FLASHROM_BUG;
+ }
+
+ rpgm.buses_supported = buses;
+ rpgm.par = *pgm;
+ return register_programmer(&rpgm);
+}
+
+/* The limit of 4 is totally arbitrary. */
+#define PROGRAMMERS_MAX 4
+struct registered_programmer registered_programmers[PROGRAMMERS_MAX];
+int registered_programmer_count = 0;
+
+/* This function copies the struct registered_programmer parameter. */
+int register_programmer(struct registered_programmer *pgm)
+{
+ if (registered_programmer_count >= PROGRAMMERS_MAX) {
+ msg_perr("Tried to register more than %i programmer "
+ "interfaces.\n", PROGRAMMERS_MAX);
+ return ERROR_FLASHROM_LIMIT;
+ }
+ registered_programmers[registered_programmer_count] = *pgm;
+ registered_programmer_count++;
+
+ return 0;
+}
+
+enum chipbustype get_buses_supported(void)
{
- par_programmer = pgm;
- buses_supported |= buses;
+ int i;
+ enum chipbustype ret = BUS_NONE;
+
+ for (i = 0; i < registered_programmer_count; i++)
+ ret |= registered_programmers[i].buses_supported;
+
+ return ret;
}
diff --git a/programmer.h b/programmer.h
index 9942686..a40d037 100644
--- a/programmer.h
+++ b/programmer.h
@@ -133,6 +133,8 @@ struct bitbang_spi_master {
int (*get_miso) (void);
void (*request_bus) (void);
void (*release_bus) (void);
+ /* Length of half a clock period in usecs. */
+ unsigned int half_period;
};
#if CONFIG_INTERNAL == 1
@@ -208,6 +210,7 @@ void internal_delay(int usecs);
#if NEED_PCI == 1
/* pcidev.c */
+// FIXME: These need to be local, not global
extern uint32_t io_base_addr;
extern struct pci_access *pacc;
extern struct pci_dev *pcidev_dev;
@@ -427,8 +430,7 @@ int rayer_spi_init(void);
#endif
/* bitbang_spi.c */
-int bitbang_spi_init(const struct bitbang_spi_master *master, int halfperiod);
-int bitbang_spi_shutdown(const struct bitbang_spi_master *master);
+int bitbang_spi_init(const struct bitbang_spi_master *master);
/* buspirate_spi.c */
#if CONFIG_BUSPIRATE_SPI == 1
@@ -452,6 +454,7 @@ struct decode_sizes {
uint32_t fwh;
uint32_t spi;
};
+// FIXME: These need to be local, not global
extern struct decode_sizes max_rom_decode;
extern int programmer_may_write;
extern unsigned long flashbase;
@@ -498,7 +501,6 @@ enum spi_controller {
SPI_CONTROLLER_SERPROG,
#endif
};
-extern const int spi_programmer_count;
#define MAX_DATA_UNSPECIFIED 0
#define MAX_DATA_READ_UNLIMITED 64 * 1024
@@ -514,15 +516,15 @@ struct spi_programmer {
/* Optimized functions for this programmer */
int (*read)(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
int (*write_256)(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
+ const void *data;
};
-extern const struct spi_programmer *spi_programmer;
int default_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr);
int default_spi_send_multicommand(struct flashctx *flash, struct spi_command *cmds);
int default_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
int default_spi_write_256(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
-void register_spi_programmer(const struct spi_programmer *programmer);
+int register_spi_programmer(const struct spi_programmer *programmer);
/* ichspi.c */
#if CONFIG_INTERNAL == 1
@@ -570,15 +572,14 @@ struct opaque_programmer {
int (*read) (struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
int (*write) (struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
int (*erase) (struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen);
+ const void *data;
};
-extern const struct opaque_programmer *opaque_programmer;
-void register_opaque_programmer(const struct opaque_programmer *pgm);
+int register_opaque_programmer(const struct opaque_programmer *pgm);
/* programmer.c */
int noop_shutdown(void);
void *fallback_map(const char *descr, unsigned long phys_addr, size_t len);
void fallback_unmap(void *virt_addr, size_t len);
-uint8_t noop_chip_readb(const struct flashctx *flash, const chipaddr addr);
void noop_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr);
void fallback_chip_writew(const struct flashctx *flash, uint16_t val, chipaddr addr);
void fallback_chip_writel(const struct flashctx *flash, uint32_t val, chipaddr addr);
@@ -595,9 +596,20 @@ struct par_programmer {
uint16_t (*chip_readw) (const struct flashctx *flash, const chipaddr addr);
uint32_t (*chip_readl) (const struct flashctx *flash, const chipaddr addr);
void (*chip_readn) (const struct flashctx *flash, uint8_t *buf, const chipaddr addr, size_t len);
+ const void *data;
};
-extern const struct par_programmer *par_programmer;
-void register_par_programmer(const struct par_programmer *pgm, const enum chipbustype buses);
+int register_par_programmer(const struct par_programmer *pgm, const enum chipbustype buses);
+struct registered_programmer {
+ enum chipbustype buses_supported;
+ union {
+ struct par_programmer par;
+ struct spi_programmer spi;
+ struct opaque_programmer opaque;
+ };
+};
+extern struct registered_programmer registered_programmers[];
+extern int registered_programmer_count;
+int register_programmer(struct registered_programmer *pgm);
/* serprog.c */
#if CONFIG_SERPROG == 1
diff --git a/rayer_spi.c b/rayer_spi.c
index 417fde9..0011bc0 100644
--- a/rayer_spi.c
+++ b/rayer_spi.c
@@ -92,6 +92,7 @@ static const struct bitbang_spi_master bitbang_spi_master_rayer = {
.set_sck = rayer_bitbang_set_sck,
.set_mosi = rayer_bitbang_set_mosi,
.get_miso = rayer_bitbang_get_miso,
+ .half_period = 0,
};
int rayer_spi_init(void)
@@ -171,8 +172,7 @@ int rayer_spi_init(void)
/* Get the initial value before writing to any line. */
lpt_outbyte = INB(lpt_iobase);
- /* Zero halfperiod delay. */
- if (bitbang_spi_init(&bitbang_spi_master_rayer, 0))
+ if (bitbang_spi_init(&bitbang_spi_master_rayer))
return 1;
return 0;
diff --git a/spi.c b/spi.c
index 02c83f7..b2d3eb0 100644
--- a/spi.c
+++ b/spi.c
@@ -1,7 +1,7 @@
/*
* This file is part of the flashrom project.
*
- * Copyright (C) 2007, 2008, 2009 Carl-Daniel Hailfinger
+ * Copyright (C) 2007, 2008, 2009, 2010, 2011 Carl-Daniel Hailfinger
* Copyright (C) 2008 coresystems GmbH
*
* This program is free software; you can redistribute it and/or modify
@@ -30,43 +30,17 @@
#include "programmer.h"
#include "spi.h"
-const struct spi_programmer spi_programmer_none = {
- .type = SPI_CONTROLLER_NONE,
- .max_data_read = MAX_DATA_UNSPECIFIED,
- .max_data_write = MAX_DATA_UNSPECIFIED,
- .command = NULL,
- .multicommand = NULL,
- .read = NULL,
- .write_256 = NULL,
-};
-
-const struct spi_programmer *spi_programmer = &spi_programmer_none;
-
int spi_send_command(struct flashctx *flash, unsigned int writecnt,
unsigned int readcnt, const unsigned char *writearr,
unsigned char *readarr)
{
- if (!spi_programmer->command) {
- msg_perr("%s called, but SPI is unsupported on this "
- "hardware. Please report a bug at "
- "flashrom@flashrom.org\n", __func__);
- return 1;
- }
-
- return spi_programmer->command(flash, writecnt, readcnt, writearr,
+ return flash->pgm->spi.command(flash, writecnt, readcnt, writearr,
readarr);
}
int spi_send_multicommand(struct flashctx *flash, struct spi_command *cmds)
{
- if (!spi_programmer->multicommand) {
- msg_perr("%s called, but SPI is unsupported on this "
- "hardware. Please report a bug at "
- "flashrom@flashrom.org\n", __func__);
- return 1;
- }
-
- return spi_programmer->multicommand(flash, cmds);
+ return flash->pgm->spi.multicommand(flash, cmds);
}
int default_spi_send_command(struct flashctx *flash, unsigned int writecnt,
@@ -104,7 +78,7 @@ int default_spi_send_multicommand(struct flashctx *flash,
int default_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start,
unsigned int len)
{
- unsigned int max_data = spi_programmer->max_data_read;
+ unsigned int max_data = flash->pgm->spi.max_data_read;
if (max_data == MAX_DATA_UNSPECIFIED) {
msg_perr("%s called, but SPI read chunk size not defined "
"on this hardware. Please report a bug at "
@@ -117,7 +91,7 @@ int default_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start,
int default_spi_write_256(struct flashctx *flash, uint8_t *buf,
unsigned int start, unsigned int len)
{
- unsigned int max_data = spi_programmer->max_data_write;
+ unsigned int max_data = flash->pgm->spi.max_data_write;
if (max_data == MAX_DATA_UNSPECIFIED) {
msg_perr("%s called, but SPI write chunk size not defined "
"on this hardware. Please report a bug at "
@@ -131,12 +105,6 @@ int spi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start,
unsigned int len)
{
unsigned int addrbase = 0;
- if (!spi_programmer->read) {
- msg_perr("%s called, but SPI read is unsupported on this "
- "hardware. Please report a bug at "
- "flashrom@flashrom.org\n", __func__);
- return 1;
- }
/* Check if the chip fits between lowest valid and highest possible
* address. Highest possible address with the current SPI implementation
@@ -157,7 +125,7 @@ int spi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start,
"access window.\n");
msg_perr("Read will probably return garbage.\n");
}
- return spi_programmer->read(flash, buf, addrbase + start, len);
+ return flash->pgm->spi.read(flash, buf, addrbase + start, len);
}
/*
@@ -170,14 +138,7 @@ int spi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start,
int spi_chip_write_256(struct flashctx *flash, uint8_t *buf, unsigned int start,
unsigned int len)
{
- if (!spi_programmer->write_256) {
- msg_perr("%s called, but SPI page write is unsupported on this "
- "hardware. Please report a bug at "
- "flashrom@flashrom.org\n", __func__);
- return 1;
- }
-
- return spi_programmer->write_256(flash, buf, start, len);
+ return flash->pgm->spi.write_256(flash, buf, start, len);
}
/*
@@ -187,7 +148,7 @@ int spi_chip_write_256(struct flashctx *flash, uint8_t *buf, unsigned int start,
*/
uint32_t spi_get_valid_read_addr(struct flashctx *flash)
{
- switch (spi_programmer->type) {
+ switch (flash->pgm->spi.type) {
#if CONFIG_INTERNAL == 1
#if defined(__i386__) || defined(__x86_64__)
case SPI_CONTROLLER_ICH7:
@@ -200,8 +161,22 @@ uint32_t spi_get_valid_read_addr(struct flashctx *flash)
}
}
-void register_spi_programmer(const struct spi_programmer *pgm)
+int register_spi_programmer(const struct spi_programmer *pgm)
{
- spi_programmer = pgm;
- buses_supported |= BUS_SPI;
+ struct registered_programmer rpgm;
+
+ if (!pgm->write_256 || !pgm->read || !pgm->command ||
+ !pgm->multicommand ||
+ ((pgm->command == default_spi_send_command) &&
+ (pgm->multicommand == default_spi_send_multicommand))) {
+ msg_perr("%s called with incomplete programmer definition. "
+ "Please report a bug at flashrom@flashrom.org\n",
+ __func__);
+ return ERROR_FLASHROM_BUG;
+ }
+
+
+ rpgm.buses_supported = BUS_SPI;
+ rpgm.spi = *pgm;
+ return register_programmer(&rpgm);
}
diff --git a/spi25.c b/spi25.c
index 1e3bed9..3ce7f08 100644
--- a/spi25.c
+++ b/spi25.c
@@ -179,7 +179,7 @@ int probe_spi_rdid4(struct flashctx *flash)
/* Some SPI controllers do not support commands with writecnt=1 and
* readcnt=4.
*/
- switch (spi_programmer->type) {
+ switch (flash->pgm->spi.type) {
#if CONFIG_INTERNAL == 1
#if defined(__i386__) || defined(__x86_64__)
case SPI_CONTROLLER_IT87XX:
@@ -1120,7 +1120,7 @@ int spi_aai_write(struct flashctx *flash, uint8_t *buf, unsigned int start,
.readarr = NULL,
}};
- switch (spi_programmer->type) {
+ switch (flash->pgm->spi.type) {
#if CONFIG_INTERNAL == 1
#if defined(__i386__) || defined(__x86_64__)
case SPI_CONTROLLER_IT87XX:
OpenPOWER on IntegriCloud