summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Tauner <stefan.tauner@alumni.tuwien.ac.at>2011-10-20 12:57:14 +0000
committerStefan Tauner <stefan.tauner@alumni.tuwien.ac.at>2011-10-20 12:57:14 +0000
commitd0c5dc23e25f33439dd6166a5798ffbcaabf67f8 (patch)
tree46817260e91768863e9815741486d0f1b0a804bc
parent836b26a423c5dad86646bc6bc24560d444181405 (diff)
downloadflashrom-d0c5dc23e25f33439dd6166a5798ffbcaabf67f8.tar.gz
flashrom-d0c5dc23e25f33439dd6166a5798ffbcaabf67f8.tar.bz2
flashrom-d0c5dc23e25f33439dd6166a5798ffbcaabf67f8.zip
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. Corresponding to flashrom svn r1452. Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at> Acked-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
-rw-r--r--ich_descriptors.c28
-rw-r--r--ich_descriptors.h1
-rw-r--r--ichspi.c97
3 files changed, 113 insertions, 13 deletions
diff --git a/ich_descriptors.c b/ich_descriptors.c
index da1326ee4..125077c64 100644
--- a/ich_descriptors.c
+++ b/ich_descriptors.c
@@ -213,6 +213,34 @@ void prettyprint_ich_descriptor_master(const struct ich_desc_master *mstr)
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;
diff --git a/ich_descriptors.h b/ich_descriptors.h
index 886fc7cf9..4e2ad0a3e 100644
--- a/ich_descriptors.h
+++ b/ich_descriptors.h
@@ -255,6 +255,7 @@ void prettyprint_ich_descriptor_region(const struct ich_descriptors *desc);
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__) */
diff --git a/ichspi.c b/ichspi.c
index e30c26738..afa420b9c 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -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 @@ static int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt,
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 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
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 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
/* 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 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
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 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
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 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
}
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);