Refactor ITE SuperI/O detection/access. The new code reduces duplications and paves the way for generic SuperI/O detection. Additional cost: We enter/exit the SuperI/O configuration mode twice. Once for detecting which SuperI/O it is, and once for actually changing the settings. Additional benefit: This has the potential of allowing some sort of primitive laptop detection (by way of checking whether an EC or a simple SuperI/O is present).
I have added a call to a not yet implemented Winbond SuperI/O detection function inside #if 0 to make extension more straighforward.
This affects most SiS chipsets and IT87 SPI translation, so tests in verbose mode would be appreciated. In theory, functionality should be unchanged.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: flashrom-superio_ite_refactor/flash.h =================================================================== --- flashrom-superio_ite_refactor/flash.h (Revision 761) +++ flashrom-superio_ite_refactor/flash.h (Arbeitskopie) @@ -388,6 +388,11 @@ #endif
/* internal.c */ +struct superio { + uint16_t vendor; + uint16_t port; + uint16_t model; +}; 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); @@ -395,6 +400,7 @@ uint16_t card_vendor, uint16_t card_device); void get_io_perms(void); void release_io_perms(void); +struct superio probe_superio(void); int internal_init(void); int internal_shutdown(void); void internal_chip_writeb(uint8_t val, chipaddr addr); @@ -611,9 +617,12 @@ int ich_spi_send_multicommand(struct spi_command *cmds);
/* it87spi.c */ +#define SUPERIO_VENDOR_NONE 0x0 +#define SUPERIO_VENDOR_ITE 0x1 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, Index: flashrom-superio_ite_refactor/it87spi.c =================================================================== --- flashrom-superio_ite_refactor/it87spi.c (Revision 761) +++ flashrom-superio_ite_refactor/it87spi.c (Arbeitskopie) @@ -54,19 +54,56 @@ 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; + + i++; + 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,18 +142,26 @@ 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 (!it8716f_flashport) - it8716f_flashport = find_ite_spi_flash_port(ITE_SUPERIO_PORT2); + struct superio superio;
+ superio = probe_superio_ite(); + if (superio.vendor == SUPERIO_VENDOR_NONE) + return 1; + + it8716f_flashport = find_ite_spi_flash_port(superio.port, superio.model); + if (it8716f_flashport) spi_controller = SPI_CONTROLLER_IT87XX;
Index: flashrom-superio_ite_refactor/chipset_enable.c =================================================================== --- flashrom-superio_ite_refactor/chipset_enable.c (Revision 761) +++ flashrom-superio_ite_refactor/chipset_enable.c (Arbeitskopie) @@ -225,37 +225,40 @@ return ret; }
-static int enable_flash_sis630(struct pci_dev *dev, const char *name) +static int enable_flash_decode_superio(void) { + int ret; uint8_t tmp; - uint16_t siobase; - int ret; + struct superio superio;
- ret = enable_flash_sis540(dev, name); - - /* The same thing on SiS 950 Super I/O side... */ - - /* First probe for Super I/O on config port 0x2e. */ - siobase = 0x2e; - enter_conf_mode_ite(siobase); - - if (INB(siobase + 1) != 0x87) { - /* If that failed, try config port 0x4e. */ - siobase = 0x4e; - enter_conf_mode_ite(siobase); - if (INB(siobase + 1) != 0x87) { - printf("Can not find SuperI/O.\n"); - return -1; - } + superio = probe_superio(); + 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; +}
- /* Enable flash mapping. Works for most old ITE style SuperI/O. */ - tmp = sio_read(siobase, 0x24); - tmp |= 0xfc; - sio_write(siobase, 0x24, tmp); +static int enable_flash_sis630(struct pci_dev *dev, const char *name) +{ + int ret;
- exit_conf_mode_ite(siobase); - + ret = enable_flash_sis540(dev, name); + ret |= enable_flash_decode_superio(); return ret; }
Index: flashrom-superio_ite_refactor/internal.c =================================================================== --- flashrom-superio_ite_refactor/internal.c (Revision 761) +++ flashrom-superio_ite_refactor/internal.c (Arbeitskopie) @@ -122,6 +122,18 @@ #endif }
+struct superio probe_superio(void) +{ + struct superio superio; + + 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 + return superio; +} + int internal_init(void) { int ret = 0;