Author: stefanct Date: Thu Oct 20 14:57:14 2011 New Revision: 1452 URL: http://flashrom.org/trac/flashrom/changeset/1452
Log: ichspi: add (partially) dead support code for Intel Hardware Sequencing
This was done to ease the review. Another patch will hook up (and explain) this code later.
Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at Acked-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Modified: trunk/ich_descriptors.c trunk/ich_descriptors.h trunk/ichspi.c
Modified: trunk/ich_descriptors.c ============================================================================== --- trunk/ich_descriptors.c Fri Oct 14 22:33:14 2011 (r1451) +++ trunk/ich_descriptors.c Thu Oct 20 14:57:14 2011 (r1452) @@ -213,6 +213,34 @@ msg_pdbg2("\n"); }
+/** Returns the integer representation of the component density with index +idx in bytes or 0 if a correct size can not be determined. */ +int getFCBA_component_density(const struct ich_descriptors *desc, uint8_t idx) +{ + uint8_t size_enc; + + switch(idx) { + case 0: + size_enc = desc->component.comp1_density; + break; + case 1: + if (desc->content.NC == 0) + return 0; + size_enc = desc->component.comp2_density; + break; + default: + msg_perr("Only ICH SPI component index 0 or 1 are supported " + "yet.\n"); + return 0; + } + if (size_enc > 5) { + msg_perr("Density of ICH SPI component with index %d is " + "invalid. Encoded density is 0x%x.\n", idx, size_enc); + return 0; + } + return (1 << (19 + size_enc)); +} + static uint32_t read_descriptor_reg(uint8_t section, uint16_t offset, void *spibar) { uint32_t control = 0;
Modified: trunk/ich_descriptors.h ============================================================================== --- trunk/ich_descriptors.h Fri Oct 14 22:33:14 2011 (r1451) +++ trunk/ich_descriptors.h Thu Oct 20 14:57:14 2011 (r1452) @@ -255,6 +255,7 @@ void prettyprint_ich_descriptor_master(const struct ich_desc_master *master);
int read_ich_descriptors_via_fdo(void *spibar, struct ich_descriptors *desc); +int getFCBA_component_density(const struct ich_descriptors *desc, uint8_t idx);
#endif /* __ICH_DESCRIPTORS_H__ */ #endif /* defined(__i386__) || defined(__x86_64__) */
Modified: trunk/ichspi.c ============================================================================== --- trunk/ichspi.c Fri Oct 14 22:33:14 2011 (r1451) +++ trunk/ichspi.c Thu Oct 20 14:57:14 2011 (r1452) @@ -26,6 +26,7 @@ #if defined(__i386__) || defined(__x86_64__)
#include <string.h> +#include <stdlib.h> #include "flash.h" #include "programmer.h" #include "spi.h" @@ -1080,6 +1081,77 @@ return result; }
+#if 0 +/* Sets FLA in FADDR to (addr & 0x01FFFFFF) without touching other bits. */ +static void ich_hwseq_set_addr(uint32_t addr) +{ + uint32_t addr_old = REGREAD32(ICH9_REG_FADDR) & ~0x01FFFFFF; + REGWRITE32(ICH9_REG_FADDR, (addr & 0x01FFFFFF) | addr_old); +} + +/* Sets FADDR.FLA to 'addr' and returns the erase block size in bytes + * of the block containing this address. May return nonsense if the address is + * not valid. The erase block size for a specific address depends on the flash + * partition layout as specified by FPB and the partition properties as defined + * by UVSCC and LVSCC respectively. An alternative to implement this method + * would be by querying FPB and the respective VSCC register directly. + */ +static uint32_t ich_hwseq_get_erase_block_size(unsigned int addr) +{ + uint8_t enc_berase; + static const uint32_t const dec_berase[4] = { + 256, + 4 * 1024, + 8 * 1024, + 64 * 1024 + }; + + ich_hwseq_set_addr(addr); + enc_berase = (REGREAD16(ICH9_REG_HSFS) & HSFS_BERASE) >> + HSFS_BERASE_OFF; + return dec_berase[enc_berase]; +} + +/* Polls for Cycle Done Status, Flash Cycle Error or timeout in 8 us intervals. + Resets all error flags in HSFS. + Returns 0 if the cycle completes successfully without errors within + timeout us, 1 on errors. */ +static int ich_hwseq_wait_for_cycle_complete(unsigned int timeout, + unsigned int len) +{ + uint16_t hsfs; + uint32_t addr; + + timeout /= 8; /* scale timeout duration to counter */ + while ((((hsfs = REGREAD16(ICH9_REG_HSFS)) & + (HSFS_FDONE | HSFS_FCERR)) == 0) && + --timeout) { + programmer_delay(8); + } + REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS)); + if (!timeout) { + addr = REGREAD32(ICH9_REG_FADDR) & 0x01FFFFFF; + msg_perr("Timeout error between offset 0x%08x and " + "0x%08x + %d (=0x%08x)!\n", + addr, addr, len - 1, addr + len - 1); + prettyprint_ich9_reg_hsfs(hsfs); + prettyprint_ich9_reg_hsfc(REGREAD16(ICH9_REG_HSFC)); + return 1; + } + + if (hsfs & HSFS_FCERR) { + addr = REGREAD32(ICH9_REG_FADDR) & 0x01FFFFFF; + msg_perr("Transaction error between offset 0x%08x and " + "0x%08x (=0x%08x + %d)!\n", + addr, addr + len - 1, addr, len - 1); + prettyprint_ich9_reg_hsfs(hsfs); + prettyprint_ich9_reg_hsfc(REGREAD16(ICH9_REG_HSFC)); + return 1; + } + return 0; +} +#endif + static int ich_spi_send_multicommand(struct spi_command *cmds) { int ret = 0; @@ -1250,21 +1322,18 @@ uint8_t old, new; uint16_t spibar_offset, tmp2; uint32_t tmp; - int ichspi_desc = 0; + int desc_valid = 0;
switch (ich_generation) { case 7: - register_spi_programmer(&spi_programmer_ich7); spibar_offset = 0x3020; break; case 8: - register_spi_programmer(&spi_programmer_ich9); spibar_offset = 0x3020; break; case 9: case 10: default: /* Future version might behave the same */ - register_spi_programmer(&spi_programmer_ich9); spibar_offset = 0x3800; break; } @@ -1275,8 +1344,8 @@ /* Assign Virtual Address */ ich_spibar = rcrb + spibar_offset;
- switch (spi_programmer->type) { - case SPI_CONTROLLER_ICH7: + switch (ich_generation) { + case 7: msg_pdbg("0x00: 0x%04x (SPIS)\n", mmio_readw(ich_spibar + 0)); msg_pdbg("0x02: 0x%04x (SPIC)\n", @@ -1313,9 +1382,13 @@ ichspi_lock = 1; } ich_set_bbar(ich_generation, 0); + register_spi_programmer(&spi_programmer_ich7); ich_init_opcodes(); break; - case SPI_CONTROLLER_ICH9: + case 8: + case 9: + case 10: + default: /* Future version might behave the same */ tmp2 = mmio_readw(ich_spibar + ICH9_REG_HSFS); msg_pdbg("0x04: 0x%04x (HSFS)\n", tmp2); prettyprint_ich9_reg_hsfs(tmp2); @@ -1324,8 +1397,8 @@ ichspi_lock = 1; } if (tmp2 & HSFS_FDV) - ichspi_desc = 1; - if (!(tmp2 & HSFS_FDOPSS) && ichspi_desc) + desc_valid = 1; + if (!(tmp2 & HSFS_FDOPSS) && desc_valid) msg_pinfo("The Flash Descriptor Security Override " "Strap-Pin is set. Restrictions implied\n" "by the FRAP and FREG registers are NOT in " @@ -1400,18 +1473,16 @@ }
msg_pdbg("\n"); - if (ichspi_desc) { + if (desc_valid) { struct ich_descriptors desc = {{ 0 }}; if (read_ich_descriptors_via_fdo(ich_spibar, &desc) == ICH_RET_OK) prettyprint_ich_descriptors(CHIPSET_ICH_UNKNOWN, &desc); } + register_spi_programmer(&spi_programmer_ich9); ich_init_opcodes(); break; - default: - /* Nothing */ - break; }
old = pci_read_byte(dev, 0xdc);