summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ich_descriptors.c37
-rw-r--r--ich_descriptors.h4
-rw-r--r--ichspi.c279
3 files changed, 233 insertions, 87 deletions
diff --git a/ich_descriptors.c b/ich_descriptors.c
index a12022c6c..1fc8835ea 100644
--- a/ich_descriptors.c
+++ b/ich_descriptors.c
@@ -824,6 +824,7 @@ int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors
case CHIPSET_8_SERIES_WELLSBURG:
case CHIPSET_9_SERIES_WILDCAT_POINT:
case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
+ case CHIPSET_100_SERIES_SUNRISE_POINT:
if (idx == 0) {
size_enc = desc->component.dens_new.comp1_density;
} else {
@@ -849,16 +850,22 @@ int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors
/* Only used by ichspi.c */
#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
-static uint32_t read_descriptor_reg(uint8_t section, uint16_t offset, void *spibar)
+static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
{
uint32_t control = 0;
control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
- mmio_le_writel(control, spibar + ICH9_REG_FDOC);
- return mmio_le_readl(spibar + ICH9_REG_FDOD);
+ if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
+ mmio_le_writel(control, spibar + PCH100_REG_FDOC);
+ return mmio_le_readl(spibar + PCH100_REG_FDOD);
+ } else {
+ mmio_le_writel(control, spibar + ICH9_REG_FDOC);
+ return mmio_le_readl(spibar + ICH9_REG_FDOD);
+ }
+
}
-int read_ich_descriptors_via_fdo(void *spibar, struct ich_descriptors *desc)
+int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
{
uint8_t i;
uint8_t nr;
@@ -888,15 +895,15 @@ int read_ich_descriptors_via_fdo(void *spibar, struct ich_descriptors *desc)
msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
/* content section */
- desc->content.FLVALSIG = read_descriptor_reg(0, 0, spibar);
- desc->content.FLMAP0 = read_descriptor_reg(0, 1, spibar);
- desc->content.FLMAP1 = read_descriptor_reg(0, 2, spibar);
- desc->content.FLMAP2 = read_descriptor_reg(0, 3, spibar);
+ desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
+ desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
+ desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
+ desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
/* component section */
- desc->component.FLCOMP = read_descriptor_reg(1, 0, spibar);
- desc->component.FLILL = read_descriptor_reg(1, 1, spibar);
- desc->component.FLPB = read_descriptor_reg(1, 2, spibar);
+ desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
+ desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
+ desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
/* region section */
nr = desc->content.NR + 1;
@@ -906,12 +913,12 @@ int read_ich_descriptors_via_fdo(void *spibar, struct ich_descriptors *desc)
return ICH_RET_ERR;
}
for (i = 0; i < 5; i++)
- desc->region.FLREGs[i] = read_descriptor_reg(2, i, spibar);
+ desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
/* master section */
- desc->master.FLMSTR1 = read_descriptor_reg(3, 0, spibar);
- desc->master.FLMSTR2 = read_descriptor_reg(3, 1, spibar);
- desc->master.FLMSTR3 = read_descriptor_reg(3, 2, spibar);
+ desc->master.FLMSTR1 = read_descriptor_reg(cs, 3, 0, spibar);
+ desc->master.FLMSTR2 = read_descriptor_reg(cs, 3, 1, spibar);
+ desc->master.FLMSTR3 = read_descriptor_reg(cs, 3, 2, spibar);
/* Accessing the strap section via FDOC/D is only possible on ICH8 and
* reading the upper map is impossible on all chipsets, so don't bother.
diff --git a/ich_descriptors.h b/ich_descriptors.h
index ecf44bf8e..831341a64 100644
--- a/ich_descriptors.h
+++ b/ich_descriptors.h
@@ -33,6 +33,7 @@
#define ICH_RET_OOB -4
#define ICH9_REG_FDOC 0xB0 /* 32 Bits Flash Descriptor Observability Control */
+#define PCH100_REG_FDOC 0xB4 /* New offset from Sunrise Point on */
/* 0-1: reserved */
#define FDOC_FDSI_OFF 2 /* 2-11: Flash Descriptor Section Index */
#define FDOC_FDSI (0x3f << FDOC_FDSI_OFF)
@@ -41,6 +42,7 @@
/* 15-31: reserved */
#define ICH9_REG_FDOD 0xB4 /* 32 Bits Flash Descriptor Observability Data */
+#define PCH100_REG_FDOD 0xB8 /* New offset from Sunrise Point on */
/* Field locations and semantics for LVSCC, UVSCC and related words in the flash
* descriptor are equal therefore they all share the same macros below. */
@@ -581,7 +583,7 @@ void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc);
int read_ich_descriptors_from_dump(const uint32_t *dump, unsigned int len, struct ich_descriptors *desc);
-int read_ich_descriptors_via_fdo(void *spibar, struct ich_descriptors *desc);
+int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc);
int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx);
int layout_from_ich_descriptors(struct ich_layout *, const void *dump, size_t len);
diff --git a/ichspi.c b/ichspi.c
index be13f915e..ecf0c4212 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -33,6 +33,60 @@
#include "spi.h"
#include "ich_descriptors.h"
+/* Sunrise Point */
+
+/* Added HSFS Status bits */
+#define HSFS_WRSDIS_OFF 11 /* 11: Flash Configuration Lock-Down */
+#define HSFS_WRSDIS (0x1 << HSFS_WRSDIS_OFF)
+#define HSFS_PRR34_LOCKDN_OFF 12 /* 12: PRR3 PRR4 Lock-Down */
+#define HSFS_PRR34_LOCKDN (0x1 << HSFS_PRR34_LOCKDN_OFF)
+/* HSFS_BERASE vanished */
+
+/*
+ * HSFC and HSFS 16-bit registers are combined into the 32-bit
+ * BIOS_HSFSTS_CTL register in the Sunrise Point datasheet,
+ * however we still treat them separately in order to reuse code.
+ */
+
+/* Changed HSFC Control bits */
+#define PCH100_HSFC_FCYCLE_OFF (17 - 16) /* 1-4: FLASH Cycle */
+#define PCH100_HSFC_FCYCLE (0xf << PCH100_HSFC_FCYCLE_OFF)
+/* New HSFC Control bit */
+#define HSFC_WET_OFF (21 - 16) /* 5: Write Enable Type */
+#define HSFC_WET (0x1 << HSFC_WET_OFF)
+
+#define PCH100_FADDR_FLA 0x07ffffff
+
+#define PCH100_REG_DLOCK 0x0c /* 32 Bits Discrete Lock Bits */
+#define DLOCK_BMWAG_LOCKDN_OFF 0
+#define DLOCK_BMWAG_LOCKDN (0x1 << DLOCK_BMWAG_LOCKDN_OFF)
+#define DLOCK_BMRAG_LOCKDN_OFF 1
+#define DLOCK_BMRAG_LOCKDN (0x1 << DLOCK_BMRAG_LOCKDN_OFF)
+#define DLOCK_SBMWAG_LOCKDN_OFF 2
+#define DLOCK_SBMWAG_LOCKDN (0x1 << DLOCK_SBMWAG_LOCKDN_OFF)
+#define DLOCK_SBMRAG_LOCKDN_OFF 3
+#define DLOCK_SBMRAG_LOCKDN (0x1 << DLOCK_SBMRAG_LOCKDN_OFF)
+#define DLOCK_PR0_LOCKDN_OFF 8
+#define DLOCK_PR0_LOCKDN (0x1 << DLOCK_PR0_LOCKDN_OFF)
+#define DLOCK_PR1_LOCKDN_OFF 9
+#define DLOCK_PR1_LOCKDN (0x1 << DLOCK_PR1_LOCKDN_OFF)
+#define DLOCK_PR2_LOCKDN_OFF 10
+#define DLOCK_PR2_LOCKDN (0x1 << DLOCK_PR2_LOCKDN_OFF)
+#define DLOCK_PR3_LOCKDN_OFF 11
+#define DLOCK_PR3_LOCKDN (0x1 << DLOCK_PR3_LOCKDN_OFF)
+#define DLOCK_PR4_LOCKDN_OFF 12
+#define DLOCK_PR4_LOCKDN (0x1 << DLOCK_PR4_LOCKDN_OFF)
+#define DLOCK_SSEQ_LOCKDN_OFF 16
+#define DLOCK_SSEQ_LOCKDN (0x1 << DLOCK_SSEQ_LOCKDN_OFF)
+
+#define PCH100_REG_FPR0 0x84 /* 32 Bits Protected Range 0 */
+#define PCH100_REG_GPR0 0x98 /* 32 Bits Global Protected Range 0 */
+
+#define PCH100_REG_SSFSC 0xA0 /* 32 Bits Status (8) + Control (24) */
+#define PCH100_REG_PREOP 0xA4 /* 16 Bits */
+#define PCH100_REG_OPTYPE 0xA6 /* 16 Bits */
+#define PCH100_REG_OPMENU 0xA8 /* 64 Bits */
+
/* ICH9 controller register definition */
#define ICH9_REG_HSFS 0x04 /* 16 Bits Hardware Sequencing Flash Status */
#define HSFS_FDONE_OFF 0 /* 0: Flash Cycle Done */
@@ -66,6 +120,7 @@
#define HSFC_SME (0x1 << HSFC_SME_OFF)
#define ICH9_REG_FADDR 0x08 /* 32 Bits */
+#define ICH9_FADDR_FLA 0x01ffffff
#define ICH9_REG_FDATA0 0x10 /* 64 Bytes */
#define ICH9_REG_FRAP 0x50 /* 32 Bytes Flash Region Access Permissions */
@@ -325,7 +380,8 @@ static void prettyprint_opcodes(OPCODES *ops)
ops->preop[1]);
}
-#define pprint_reg(reg, bit, val, sep) msg_pdbg("%s=%d" sep, #bit, (val & reg##_##bit)>>reg##_##bit##_OFF)
+#define _pprint_reg(bit, mask, off, val, sep) msg_pdbg("%s=%d" sep, #bit, (val & mask) >> off)
+#define pprint_reg(reg, bit, val, sep) _pprint_reg(bit, reg##_##bit, reg##_##bit##_OFF, val, sep)
static void prettyprint_ich9_reg_hsfs(uint16_t reg_val)
{
@@ -333,8 +389,14 @@ static void prettyprint_ich9_reg_hsfs(uint16_t reg_val)
pprint_reg(HSFS, FDONE, reg_val, ", ");
pprint_reg(HSFS, FCERR, reg_val, ", ");
pprint_reg(HSFS, AEL, reg_val, ", ");
- pprint_reg(HSFS, BERASE, reg_val, ", ");
+ if (ich_generation != CHIPSET_100_SERIES_SUNRISE_POINT) {
+ pprint_reg(HSFS, BERASE, reg_val, ", ");
+ }
pprint_reg(HSFS, SCIP, reg_val, ", ");
+ if (ich_generation == CHIPSET_100_SERIES_SUNRISE_POINT) {
+ pprint_reg(HSFS, PRR34_LOCKDN, reg_val, ", ");
+ pprint_reg(HSFS, WRSDIS, reg_val, ", ");
+ }
pprint_reg(HSFS, FDOPSS, reg_val, ", ");
pprint_reg(HSFS, FDV, reg_val, ", ");
pprint_reg(HSFS, FLOCKDN, reg_val, "\n");
@@ -344,7 +406,12 @@ static void prettyprint_ich9_reg_hsfc(uint16_t reg_val)
{
msg_pdbg("HSFC: ");
pprint_reg(HSFC, FGO, reg_val, ", ");
- pprint_reg(HSFC, FCYCLE, reg_val, ", ");
+ if (ich_generation != CHIPSET_100_SERIES_SUNRISE_POINT) {
+ pprint_reg(HSFC, FCYCLE, reg_val, ", ");
+ } else {
+ _pprint_reg(HSFC, PCH100_HSFC_FCYCLE, PCH100_HSFC_FCYCLE_OFF, reg_val, ", ");
+ pprint_reg(HSFC, WET, reg_val, ", ");
+ }
pprint_reg(HSFC, FDBC, reg_val, ", ");
pprint_reg(HSFC, SME, reg_val, "\n");
}
@@ -370,6 +437,28 @@ static void prettyprint_ich9_reg_ssfc(uint32_t reg_val)
pprint_reg(SSFC, SCF, reg_val, "\n");
}
+static void prettyprint_pch100_reg_dlock(const uint32_t reg_val)
+{
+ msg_pdbg("DLOCK: ");
+ pprint_reg(DLOCK, BMWAG_LOCKDN, reg_val, ", ");
+ pprint_reg(DLOCK, BMRAG_LOCKDN, reg_val, ", ");
+ pprint_reg(DLOCK, SBMWAG_LOCKDN, reg_val, ", ");
+ pprint_reg(DLOCK, SBMRAG_LOCKDN, reg_val, ",\n ");
+ pprint_reg(DLOCK, PR0_LOCKDN, reg_val, ", ");
+ pprint_reg(DLOCK, PR1_LOCKDN, reg_val, ", ");
+ pprint_reg(DLOCK, PR2_LOCKDN, reg_val, ", ");
+ pprint_reg(DLOCK, PR3_LOCKDN, reg_val, ", ");
+ pprint_reg(DLOCK, PR4_LOCKDN, reg_val, ",\n ");
+ pprint_reg(DLOCK, SSEQ_LOCKDN, reg_val, "\n");
+}
+
+static struct {
+ size_t reg_ssfsc;
+ size_t reg_preop;
+ size_t reg_optype;
+ size_t reg_opmenu;
+} swseq_data;
+
static uint8_t lookup_spi_type(uint8_t opcode)
{
int a;
@@ -475,10 +564,10 @@ static int generate_opcodes(OPCODES * op)
break;
case CHIPSET_ICH8:
default: /* Future version might behave the same */
- preop = REGREAD16(ICH9_REG_PREOP);
- optype = REGREAD16(ICH9_REG_OPTYPE);
- opmenu[0] = REGREAD32(ICH9_REG_OPMENU);
- opmenu[1] = REGREAD32(ICH9_REG_OPMENU + 4);
+ preop = REGREAD16(swseq_data.reg_preop);
+ optype = REGREAD16(swseq_data.reg_optype);
+ opmenu[0] = REGREAD32(swseq_data.reg_opmenu);
+ opmenu[1] = REGREAD32(swseq_data.reg_opmenu + 4);
break;
}
@@ -558,15 +647,15 @@ static int program_opcodes(OPCODES *op, int enable_undo)
default: /* Future version might behave the same */
/* Register undo only for enable_undo=1, i.e. first call. */
if (enable_undo) {
- rmmio_valw(ich_spibar + ICH9_REG_PREOP);
- rmmio_valw(ich_spibar + ICH9_REG_OPTYPE);
- rmmio_vall(ich_spibar + ICH9_REG_OPMENU);
- rmmio_vall(ich_spibar + ICH9_REG_OPMENU + 4);
+ rmmio_valw(ich_spibar + swseq_data.reg_preop);
+ rmmio_valw(ich_spibar + swseq_data.reg_optype);
+ rmmio_vall(ich_spibar + swseq_data.reg_opmenu);
+ rmmio_vall(ich_spibar + swseq_data.reg_opmenu + 4);
}
- mmio_writew(preop, ich_spibar + ICH9_REG_PREOP);
- mmio_writew(optype, ich_spibar + ICH9_REG_OPTYPE);
- mmio_writel(opmenu[0], ich_spibar + ICH9_REG_OPMENU);
- mmio_writel(opmenu[1], ich_spibar + ICH9_REG_OPMENU + 4);
+ mmio_writew(preop, ich_spibar + swseq_data.reg_preop);
+ mmio_writew(optype, ich_spibar + swseq_data.reg_optype);
+ mmio_writel(opmenu[0], ich_spibar + swseq_data.reg_opmenu);
+ mmio_writel(opmenu[1], ich_spibar + swseq_data.reg_opmenu + 4);
break;
}
@@ -853,7 +942,7 @@ static int ich9_run_opcode(OPCODE op, uint32_t offset,
}
timeout = 100 * 60; /* 60 ms are 9.6 million cycles at 16 MHz. */
- while ((REGREAD8(ICH9_REG_SSFS) & SSFS_SCIP) && --timeout) {
+ while ((REGREAD8(swseq_data.reg_ssfsc) & SSFS_SCIP) && --timeout) {
programmer_delay(10);
}
if (!timeout) {
@@ -871,12 +960,12 @@ static int ich9_run_opcode(OPCODE op, uint32_t offset,
ich_fill_data(data, datalength, ICH9_REG_FDATA0);
/* Assemble SSFS + SSFC */
- temp32 = REGREAD32(ICH9_REG_SSFS);
+ temp32 = REGREAD32(swseq_data.reg_ssfsc);
/* Keep reserved bits only */
temp32 &= SSFS_RESERVED_MASK | SSFC_RESERVED_MASK;
/* Clear cycle done and cycle error status registers */
temp32 |= (SSFS_FDONE | SSFS_FCERR);
- REGWRITE32(ICH9_REG_SSFS, temp32);
+ REGWRITE32(swseq_data.reg_ssfsc, temp32);
/* Use 20 MHz */
temp32 |= SSFC_SCF_20MHZ;
@@ -930,21 +1019,21 @@ static int ich9_run_opcode(OPCODE op, uint32_t offset,
temp32 |= SSFC_SCGO;
/* write it */
- REGWRITE32(ICH9_REG_SSFS, temp32);
+ REGWRITE32(swseq_data.reg_ssfsc, temp32);
/* Wait for Cycle Done Status or Flash Cycle Error. */
- while (((REGREAD32(ICH9_REG_SSFS) & (SSFS_FDONE | SSFS_FCERR)) == 0) &&
+ while (((REGREAD32(swseq_data.reg_ssfsc) & (SSFS_FDONE | SSFS_FCERR)) == 0) &&
--timeout) {
programmer_delay(10);
}
if (!timeout) {
- msg_perr("timeout, ICH9_REG_SSFS=0x%08x\n",
- REGREAD32(ICH9_REG_SSFS));
+ msg_perr("timeout, REG_SSFS=0x%08x\n",
+ REGREAD32(swseq_data.reg_ssfsc));
return 1;
}
/* FIXME make sure we do not needlessly cause transaction errors. */
- temp32 = REGREAD32(ICH9_REG_SSFS);
+ temp32 = REGREAD32(swseq_data.reg_ssfsc);
if (temp32 & SSFS_FCERR) {
msg_perr("Transaction error!\n");
prettyprint_ich9_reg_ssfs(temp32);
@@ -952,7 +1041,7 @@ static int ich9_run_opcode(OPCODE op, uint32_t offset,
/* keep reserved bits */
temp32 &= SSFS_RESERVED_MASK | SSFC_RESERVED_MASK;
/* Clear the transaction error. */
- REGWRITE32(ICH9_REG_SSFS, temp32 | SSFS_FCERR);
+ REGWRITE32(swseq_data.reg_ssfsc, temp32 | SSFS_FCERR);
return 1;
}
@@ -1117,13 +1206,16 @@ static int ich_spi_send_command(struct flashctx *flash, unsigned int writecnt,
static struct hwseq_data {
uint32_t size_comp0;
uint32_t size_comp1;
+ uint32_t addr_mask;
+ bool only_4k;
+ uint32_t hsfc_fcycle;
} hwseq_data;
-/* Sets FLA in FADDR to (addr & 0x01FFFFFF) without touching other bits. */
+/* Sets FLA in FADDR to (addr & hwseq_data.addr_mask) 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);
+ uint32_t addr_old = REGREAD32(ICH9_REG_FADDR) & ~hwseq_data.addr_mask;
+ REGWRITE32(ICH9_REG_FADDR, (addr & hwseq_data.addr_mask) | addr_old);
}
/* Sets FADDR.FLA to 'addr' and returns the erase block size in bytes
@@ -1135,18 +1227,21 @@ static void ich_hwseq_set_addr(uint32_t addr)
*/
static uint32_t ich_hwseq_get_erase_block_size(unsigned int addr)
{
- uint8_t enc_berase;
- static const uint32_t dec_berase[4] = {
- 256,
- 4 * 1024,
- 8 * 1024,
- 64 * 1024
- };
+ if (hwseq_data.only_4k) {
+ return 4 * 1024;
+ } else {
+ uint8_t enc_berase;
+ static const uint32_t 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];
+ 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.
@@ -1167,7 +1262,7 @@ static int ich_hwseq_wait_for_cycle_complete(unsigned int timeout,
}
REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
if (!timeout) {
- addr = REGREAD32(ICH9_REG_FADDR) & 0x01FFFFFF;
+ addr = REGREAD32(ICH9_REG_FADDR) & hwseq_data.addr_mask;
msg_perr("Timeout error between offset 0x%08x and "
"0x%08x (= 0x%08x + %d)!\n",
addr, addr + len - 1, addr, len - 1);
@@ -1177,7 +1272,7 @@ static int ich_hwseq_wait_for_cycle_complete(unsigned int timeout,
}
if (hsfs & HSFS_FCERR) {
- addr = REGREAD32(ICH9_REG_FADDR) & 0x01FFFFFF;
+ addr = REGREAD32(ICH9_REG_FADDR) & hwseq_data.addr_mask;
msg_perr("Transaction error between offset 0x%08x and "
"0x%08x (= 0x%08x + %d)!\n",
addr, addr + len - 1, addr, len - 1);
@@ -1205,7 +1300,10 @@ static int ich_hwseq_probe(struct flashctx *flash)
flash->chip->total_size = total_size / 1024;
eraser = &(flash->chip->block_erasers[0]);
- boundary = (REGREAD32(ICH9_REG_FPB) & FPB_FPBA) << 12;
+ if (!hwseq_data.only_4k)
+ boundary = (REGREAD32(ICH9_REG_FPB) & FPB_FPBA) << 12;
+ else
+ boundary = 0;
size_high = total_size - boundary;
erase_size_high = ich_hwseq_get_erase_block_size(boundary);
@@ -1279,7 +1377,7 @@ static int ich_hwseq_block_erase(struct flashctx *flash, unsigned int addr,
REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
hsfc = REGREAD16(ICH9_REG_HSFC);
- hsfc &= ~HSFC_FCYCLE; /* clear operation */
+ hsfc &= ~hwseq_data.hsfc_fcycle; /* clear operation */
hsfc |= (0x3 << HSFC_FCYCLE_OFF); /* set erase operation */
hsfc |= HSFC_FGO; /* start */
msg_pdbg("HSFC used for block erasing: ");
@@ -1316,7 +1414,7 @@ static int ich_hwseq_read(struct flashctx *flash, uint8_t *buf,
ich_hwseq_set_addr(addr);
hsfc = REGREAD16(ICH9_REG_HSFC);
- hsfc &= ~HSFC_FCYCLE; /* set read operation */
+ hsfc &= ~hwseq_data.hsfc_fcycle; /* set read operation */
hsfc &= ~HSFC_FDBC; /* clear byte count */
/* set byte count */
hsfc |= (((block_len - 1) << HSFC_FDBC_OFF) & HSFC_FDBC);
@@ -1357,7 +1455,7 @@ static int ich_hwseq_write(struct flashctx *flash, const uint8_t *buf, unsigned
block_len = min(block_len, 256 - (addr & 0xFF));
ich_fill_data(buf, block_len, ICH9_REG_FDATA0);
hsfc = REGREAD16(ICH9_REG_HSFC);
- hsfc &= ~HSFC_FCYCLE; /* clear operation */
+ hsfc &= ~hwseq_data.hsfc_fcycle; /* clear operation */
hsfc |= (0x2 << HSFC_FCYCLE_OFF); /* set write operation */
hsfc &= ~HSFC_FDBC; /* clear byte count */
/* set byte count */
@@ -1449,6 +1547,8 @@ static int ich9_handle_frap(uint32_t frap, int i)
"Flash Descriptor", "BIOS", "Management Engine",
"Gigabit Ethernet", "Platform Data"
};
+ const char *const region_name = i < ARRAY_SIZE(region_names) ? region_names[i] : "unknown";
+
uint32_t base, limit;
int rwperms = (((ICH_BRWA(frap) >> i) & 1) << 1) |
(((ICH_BRRA(frap) >> i) & 1) << 0);
@@ -1460,19 +1560,19 @@ static int ich9_handle_frap(uint32_t frap, int i)
if (base > limit || (freg == 0 && i > 0)) {
/* this FREG is disabled */
msg_pdbg2("0x%02X: 0x%08x FREG%i: %s region is unused.\n",
- offset, freg, i, region_names[i]);
+ offset, freg, i, region_name);
return 0;
}
msg_pdbg("0x%02X: 0x%08x ", offset, freg);
if (rwperms == 0x3) {
msg_pdbg("FREG%i: %s region (0x%08x-0x%08x) is %s.\n", i,
- region_names[i], base, (limit | 0x0fff),
+ region_name, base, (limit | 0x0fff),
access_names[rwperms]);
return 0;
}
msg_pwarn("FREG%i: Warning: %s region (0x%08x-0x%08x) is %s.\n", i,
- region_names[i], base, (limit | 0x0fff),
+ region_name, base, (limit | 0x0fff),
access_names[rwperms]);
return 1;
}
@@ -1487,31 +1587,36 @@ static int ich9_handle_frap(uint32_t frap, int i)
((~((pr) >> PR_WP_OFF) & 1) << 1))
/* returns 0 if range is unused (i.e. r/w) */
-static int ich9_handle_pr(int i)
+static int ich9_handle_pr(const size_t reg_pr0, int i)
{
static const char *const access_names[3] = {
"locked", "read-only", "write-only"
};
- uint8_t off = ICH9_REG_PR0 + (i * 4);
+ uint8_t off = reg_pr0 + (i * 4);
uint32_t pr = mmio_readl(ich_spibar + off);
unsigned int rwperms = ICH_PR_PERMS(pr);
+ /* From 5 on we have GPR registers and start from 0 again. */
+ const char *const prefix = i >= 5 ? "G" : "";
+ if (i >= 5)
+ i -= 5;
+
if (rwperms == 0x3) {
- msg_pdbg2("0x%02X: 0x%08x (PR%u is unused)\n", off, pr, i);
+ msg_pdbg2("0x%02X: 0x%08x (%sPR%u is unused)\n", off, pr, prefix, i);
return 0;
}
msg_pdbg("0x%02X: 0x%08x ", off, pr);
- msg_pwarn("PR%u: Warning: 0x%08x-0x%08x is %s.\n", i, ICH_FREG_BASE(pr),
+ msg_pwarn("%sPR%u: Warning: 0x%08x-0x%08x is %s.\n", prefix, i, ICH_FREG_BASE(pr),
ICH_FREG_LIMIT(pr) | 0x0fff, access_names[rwperms]);
return 1;
}
/* Set/Clear the read and write protection enable bits of PR register @i
* according to @read_prot and @write_prot. */
-static void ich9_set_pr(int i, int read_prot, int write_prot)
+static void ich9_set_pr(const size_t reg_pr0, int i, int read_prot, int write_prot)
{
- void *addr = ich_spibar + ICH9_REG_PR0 + (i * 4);
+ void *addr = ich_spibar + reg_pr0 + (i * 4);
uint32_t old = mmio_readl(addr);
uint32_t new;
@@ -1576,10 +1681,36 @@ int ich_init_spi(void *spibar, enum ich_chipset ich_gen)
ich_hwseq,
ich_swseq
} ich_spi_mode = ich_auto;
+ size_t num_freg, num_pr, reg_pr0;
ich_generation = ich_gen;
ich_spibar = spibar;
+ /* Moving registers / bits */
+ if (ich_generation == CHIPSET_100_SERIES_SUNRISE_POINT) {
+ num_freg = 10;
+ num_pr = 6;
+ reg_pr0 = PCH100_REG_FPR0;
+ swseq_data.reg_ssfsc = PCH100_REG_SSFSC;
+ swseq_data.reg_preop = PCH100_REG_PREOP;
+ swseq_data.reg_optype = PCH100_REG_OPTYPE;
+ swseq_data.reg_opmenu = PCH100_REG_OPMENU;
+ hwseq_data.addr_mask = PCH100_FADDR_FLA;
+ hwseq_data.only_4k = true;
+ hwseq_data.hsfc_fcycle = PCH100_HSFC_FCYCLE;
+ } else {
+ num_freg = 5;
+ num_pr = 5;
+ reg_pr0 = ICH9_REG_PR0;
+ swseq_data.reg_ssfsc = ICH9_REG_SSFS;
+ swseq_data.reg_preop = ICH9_REG_PREOP;
+ swseq_data.reg_optype = ICH9_REG_OPTYPE;
+ swseq_data.reg_opmenu = ICH9_REG_OPMENU;
+ hwseq_data.addr_mask = ICH9_FADDR_FLA;
+ hwseq_data.only_4k = false;
+ hwseq_data.hsfc_fcycle = HSFC_FCYCLE;
+ }
+
switch (ich_generation) {
case CHIPSET_ICH7:
case CHIPSET_TUNNEL_CREEK:
@@ -1679,6 +1810,12 @@ int ich_init_spi(void *spibar, enum ich_chipset ich_gen)
tmp = mmio_readl(ich_spibar + ICH9_REG_FADDR);
msg_pdbg2("0x08: 0x%08x (FADDR)\n", tmp);
+ if (ich_gen == CHIPSET_100_SERIES_SUNRISE_POINT) {
+ const uint32_t dlock = mmio_readl(ich_spibar + PCH100_REG_DLOCK);
+ msg_pdbg("0x0c: 0x%08x (DLOCK)\n", dlock);
+ prettyprint_pch100_reg_dlock(dlock);
+ }
+
if (desc_valid) {
tmp = mmio_readl(ich_spibar + ICH9_REG_FRAP);
msg_pdbg("0x50: 0x%08x (FRAP)\n", tmp);
@@ -1688,7 +1825,7 @@ int ich_init_spi(void *spibar, enum ich_chipset ich_gen)
msg_pdbg("BRRA 0x%02x\n", ICH_BRRA(tmp));
/* Handle FREGx and FRAP registers */
- for (i = 0; i < 5; i++)
+ for (i = 0; i < num_freg; i++)
ich_spi_rw_restricted |= ich9_handle_frap(tmp, i);
if (ich_spi_rw_restricted)
msg_pwarn("Not all flash regions are freely accessible by flashrom. This is "
@@ -1697,11 +1834,11 @@ int ich_init_spi(void *spibar, enum ich_chipset ich_gen)
}
/* Handle PR registers */
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < num_pr; i++) {
/* if not locked down try to disable PR locks first */
if (!ichspi_lock)
- ich9_set_pr(i, 0, 0);
- ich_spi_rw_restricted |= ich9_handle_pr(i);
+ ich9_set_pr(reg_pr0, i, 0, 0);
+ ich_spi_rw_restricted |= ich9_handle_pr(reg_pr0, i);
}
if (ich_spi_rw_restricted) {
@@ -1716,30 +1853,30 @@ int ich_init_spi(void *spibar, enum ich_chipset ich_gen)
msg_pinfo("Continuing with write support because the user forced us to!\n");
}
- tmp = mmio_readl(ich_spibar + ICH9_REG_SSFS);
- msg_pdbg("0x90: 0x%02x (SSFS)\n", tmp & 0xff);
+ tmp = mmio_readl(ich_spibar + swseq_data.reg_ssfsc);
+ msg_pdbg("0x%zx: 0x%02x (SSFS)\n", swseq_data.reg_ssfsc, tmp & 0xff);
prettyprint_ich9_reg_ssfs(tmp);
if (tmp & SSFS_FCERR) {
msg_pdbg("Clearing SSFS.FCERR\n");
- mmio_writeb(SSFS_FCERR, ich_spibar + ICH9_REG_SSFS);
+ mmio_writeb(SSFS_FCERR, ich_spibar + swseq_data.reg_ssfsc);
}
- msg_pdbg("0x91: 0x%06x (SSFC)\n", tmp >> 8);
+ msg_pdbg("0x%zx: 0x%06x (SSFC)\n", swseq_data.reg_ssfsc + 1, tmp >> 8);
prettyprint_ich9_reg_ssfc(tmp);
- msg_pdbg("0x94: 0x%04x (PREOP)\n",
- mmio_readw(ich_spibar + ICH9_REG_PREOP));
- msg_pdbg("0x96: 0x%04x (OPTYPE)\n",
- mmio_readw(ich_spibar + ICH9_REG_OPTYPE));
- msg_pdbg("0x98: 0x%08x (OPMENU)\n",
- mmio_readl(ich_spibar + ICH9_REG_OPMENU));
- msg_pdbg("0x9C: 0x%08x (OPMENU+4)\n",
- mmio_readl(ich_spibar + ICH9_REG_OPMENU + 4));
+ msg_pdbg("0x%zx: 0x%04x (PREOP)\n",
+ swseq_data.reg_preop, mmio_readw(ich_spibar + swseq_data.reg_preop));
+ msg_pdbg("0x%zx: 0x%04x (OPTYPE)\n",
+ swseq_data.reg_optype, mmio_readw(ich_spibar + swseq_data.reg_optype));
+ msg_pdbg("0x%zx: 0x%08x (OPMENU)\n",
+ swseq_data.reg_opmenu, mmio_readl(ich_spibar + swseq_data.reg_opmenu));
+ msg_pdbg("0x%zx: 0x%08x (OPMENU+4)\n",
+ swseq_data.reg_opmenu + 4, mmio_readl(ich_spibar + swseq_data.reg_opmenu + 4));
if (ich_generation == CHIPSET_ICH8 && desc_valid) {
tmp = mmio_readl(ich_spibar + ICH8_REG_VSCC);
msg_pdbg("0xC1: 0x%08x (VSCC)\n", tmp);
msg_pdbg("VSCC: ");
prettyprint_ich_reg_vscc(tmp, FLASHROM_MSG_DEBUG, true);
- } else {
+ } else if (ich_generation != CHIPSET_100_SERIES_SUNRISE_POINT) {
if (ich_generation != CHIPSET_BAYTRAIL && desc_valid) {
ichspi_bbar = mmio_readl(ich_spibar + ICH9_REG_BBAR);
msg_pdbg("0xA0: 0x%08x (BBAR)\n",
@@ -1764,7 +1901,7 @@ int ich_init_spi(void *spibar, enum ich_chipset ich_gen)
}
if (desc_valid) {
- if (read_ich_descriptors_via_fdo(ich_spibar, &desc) == ICH_RET_OK)
+ if (read_ich_descriptors_via_fdo(ich_gen, ich_spibar, &desc) == ICH_RET_OK)
prettyprint_ich_descriptors(ich_gen, &desc);
/* If the descriptor is valid and indicates multiple