diff options
author | Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> | 2009-12-22 23:42:04 +0000 |
---|---|---|
committer | Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> | 2009-12-22 23:42:04 +0000 |
commit | 14e100c9335e310b3e84763f29306392574a14f4 (patch) | |
tree | 78dd44d70ae4c3bd0a80fbb959499d06becaa42f | |
parent | 72a9a02b3864fb730ae9a8cff35266633842e324 (diff) | |
download | flashrom-14e100c9335e310b3e84763f29306392574a14f4.tar.gz flashrom-14e100c9335e310b3e84763f29306392574a14f4.tar.bz2 flashrom-14e100c9335e310b3e84763f29306392574a14f4.zip |
SuperI/O detection now happens unconditionally and before the chipset enable
We could run it after chipset enable, but it definitely has to happen
before board enable because the board enable usually accesses the
SuperI/O. With this patch, it is possible to add a struct superio to the
board enable table for more accurate matching in case subsystem IDs are
ambiguous. This patch focuses on the generic infrastructure aspect and
on support for IT8712F/IT8716F.
Thanks go to Adrian Glaubitz and Ward Vandewege for testing.
Corresponding to flashrom svn r813.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Acked-by: Luc Verhaegen <libv@skynet.be>
Acked-by: Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
-rw-r--r-- | board_enable.c | 29 | ||||
-rw-r--r-- | flash.h | 10 | ||||
-rw-r--r-- | internal.c | 14 | ||||
-rw-r--r-- | it87spi.c | 64 |
4 files changed, 106 insertions, 11 deletions
diff --git a/board_enable.c b/board_enable.c index 9dd299ea7..716b77e46 100644 --- a/board_enable.c +++ b/board_enable.c @@ -66,6 +66,35 @@ void sio_mask(uint16_t port, uint8_t reg, uint8_t data, uint8_t mask) OUTB(tmp | (data & mask), port + 1); } +/* Not used yet. */ +#if 0 +static int enable_flash_decode_superio(void) +{ + int ret; + uint8_t tmp; + + switch (superio.vendor) { + case SUPERIO_VENDOR_NONE: + ret = -1; + break; + case SUPERIO_VENDOR_ITE: + enter_conf_mode_ite(superio.port); + /* Enable flash mapping. Works for most old ITE style SuperI/O. */ + tmp = sio_read(superio.port, 0x24); + tmp |= 0xfc; + sio_write(superio.port, 0x24, tmp); + exit_conf_mode_ite(superio.port); + ret = 0; + break; + default: + printf_debug("Unhandled SuperI/O type!\n"); + ret = -1; + break; + } + return ret; +} +#endif + /** * Winbond W83627HF: Raise GPIO24. * @@ -331,6 +331,14 @@ extern int partvendor_from_cbtable; /* internal.c */ #if NEED_PCI == 1 +struct superio { + uint16_t vendor; + uint16_t port; + uint16_t model; +}; +extern struct superio superio; +#define SUPERIO_VENDOR_NONE 0x0 +#define SUPERIO_VENDOR_ITE 0x1 struct pci_dev *pci_dev_find_filter(struct pci_filter filter); struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t class); struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device); @@ -340,6 +348,7 @@ struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device, void get_io_perms(void); void release_io_perms(void); #if INTERNAL_SUPPORT == 1 +void probe_superio(void); int internal_init(void); int internal_shutdown(void); void internal_chip_writeb(uint8_t val, chipaddr addr); @@ -544,6 +553,7 @@ int ich_spi_send_multicommand(struct spi_command *cmds); extern uint16_t it8716f_flashport; void enter_conf_mode_ite(uint16_t port); void exit_conf_mode_ite(uint16_t port); +struct superio probe_superio_ite(void); int it87spi_init(void); int it87xx_probe_spi_flash(const char *name); int it8716f_spi_send_command(unsigned int writecnt, unsigned int readcnt, diff --git a/internal.c b/internal.c index cfb83d758..69624a0d4 100644 --- a/internal.c +++ b/internal.c @@ -125,6 +125,17 @@ void release_io_perms(void) } #if INTERNAL_SUPPORT == 1 +struct superio superio = {}; + +void probe_superio(void) +{ + superio = probe_superio_ite(); +#if 0 /* Winbond SuperI/O code is not yet available. */ + if (superio.vendor == SUPERIO_VENDOR_NONE) + superio = probe_superio_winbond(); +#endif +} + int internal_init(void) { int ret = 0; @@ -142,6 +153,9 @@ int internal_init(void) */ coreboot_init(); + /* Probe for the SuperI/O chip and fill global struct superio. */ + probe_superio(); + /* try to enable it. Failure IS an option, since not all motherboards * really need this to be done, etc., etc. */ @@ -54,19 +54,55 @@ void exit_conf_mode_ite(uint16_t port) sio_write(port, 0x02, 0x02); } -static uint16_t find_ite_spi_flash_port(uint16_t port) +uint16_t probe_id_ite(uint16_t port) { - uint8_t tmp = 0; - char *portpos = NULL; - uint16_t id, flashport = 0; + uint16_t id; enter_conf_mode_ite(port); - id = sio_read(port, CHIP_ID_BYTE1_REG) << 8; id |= sio_read(port, CHIP_ID_BYTE2_REG); + exit_conf_mode_ite(port); - /* TODO: Handle more IT87xx if they support flash translation */ - if (0x8716 == id || 0x8718 == id) { + return id; +} + +struct superio probe_superio_ite(void) +{ + struct superio ret = {}; + uint16_t ite_ports[] = {ITE_SUPERIO_PORT1, ITE_SUPERIO_PORT2, 0}; + uint16_t *i = ite_ports; + + ret.vendor = SUPERIO_VENDOR_ITE; + for (; *i; i++) { + ret.port = *i; + ret.model = probe_id_ite(ret.port); + switch (ret.model >> 8) { + case 0x82: + case 0x86: + case 0x87: + printf_debug("Found ITE SuperI/O, id %04hx\n", + ret.model); + return ret; + } + } + + /* No good ID found. */ + ret.vendor = SUPERIO_VENDOR_NONE; + ret.port = 0; + ret.model = 0; + return ret; +} + +static uint16_t find_ite_spi_flash_port(uint16_t port, uint16_t id) +{ + uint8_t tmp = 0; + char *portpos = NULL; + uint16_t flashport = 0; + + switch (id) { + case 0x8716: + case 0x8718: + enter_conf_mode_ite(port); /* NOLDN, reg 0x24, mask out lowest bit (suspend) */ tmp = sio_read(port, 0x24) & 0xFE; printf("Serial flash segment 0x%08x-0x%08x %sabled\n", @@ -105,17 +141,21 @@ static uint16_t find_ite_spi_flash_port(uint16_t port) sio_write(port, 0x64, (flashport >> 8)); sio_write(port, 0x65, (flashport & 0xff)); } + exit_conf_mode_ite(port); + break; + /* TODO: Handle more IT87xx if they support flash translation */ + default: + printf("SuperI/O ID %04hx is not on the controller list.\n", id); } - exit_conf_mode_ite(port); return flashport; } int it87spi_common_init(void) { - it8716f_flashport = find_ite_spi_flash_port(ITE_SUPERIO_PORT1); + if (superio.vendor != SUPERIO_VENDOR_ITE) + return 1; - if (!it8716f_flashport) - it8716f_flashport = find_ite_spi_flash_port(ITE_SUPERIO_PORT2); + it8716f_flashport = find_ite_spi_flash_port(superio.port, superio.model); if (it8716f_flashport) spi_controller = SPI_CONTROLLER_IT87XX; @@ -129,6 +169,8 @@ int it87spi_init(void) int ret; get_io_perms(); + /* Probe for the SuperI/O chip and fill global struct superio. */ + probe_superio(); ret = it87spi_common_init(); if (!ret) { buses_supported = CHIP_BUSTYPE_SPI; |