Fix IDSEL handling in WPCE775X.
- Clean up the code - Check that SHM window 2 is reachable if FWH communication is used - IDSEL is 4 bits, use a mask to extract it correctly - IDSEL setup needs to happen before SHM window 2 is accessed if FWH communication is used
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
diff --git a/wpce775x.c b/wpce775x.c index a659893..1407977 100644 --- a/wpce775x.c +++ b/wpce775x.c @@ -164,12 +164,13 @@ static int nuvoton_get_sio_index(uint16_t *port) /** Call superio to get pre-configured WCB address. * Read LDN 0x0f (SHM) idx:f8-fb (little-endian). */ -static int get_shaw2ba(chipaddr *shaw2ba) +static int get_shaw2ba(chipaddr *shaw2ba, uint8_t *comm_fwh) { uint16_t idx; uint8_t org_ldn; uint8_t win_cfg; uint8_t shm_cfg; + int ret = 0;
if (nuvoton_get_sio_index(&idx) < 0) return -1; @@ -196,27 +197,40 @@ static int get_shaw2ba(chipaddr *shaw2ba) */ win_cfg = sio_read(idx, WPCE775X_WIN_CFG); if (win_cfg & WPCE775X_WIN_CFG_SHWIN_ACC) { - uint8_t idsel; - /* Make sure shared BIOS memory is enabled */ shm_cfg = sio_read(idx, WPCE775X_SHM_CFG); - if ((shm_cfg & WPCE775X_SHM_CFG_BIOS_FWH_EN)) - idsel = 0xf; - else { + if (!(shm_cfg & WPCE775X_SHM_CFG_BIOS_FWH_EN)) { msg_cdbg("Shared BIOS memory is diabled.\n"); msg_cdbg("Please check SHM_CFG:BIOS_FWH_EN.\n"); - goto error; + ret = -1; + goto out; } - - *shaw2ba &= 0x0fffffff; - *shaw2ba |= idsel << 28; + /* FIXME: Check that this is a FWH capable chipset. */ + comm_fwh = 1; + /* Check if bit 24-27 are set. Intel ICH will never issue any + * LPC firmware memory (FWH) cycles with them cleared. + * FWH cycles only have 28 address bits. + */ + if (*shaw2ba & (0xf << 24) != 0xf << 24) { + msg_cerr("WPCE775X shadow window 2 is outside the " + "region addressable with FWH!\n"); + ret = -1; + goto out; + } + /* FWH cycles are only issued for memory mapped to the top + * 16 MB of the 4 GB address space. We could set only the top + * 4 bits since those are ignored by the WPCE775X and we checked + * bits 24-27 to be 0xf above, but setting the top 8 bits makes + * the 16 MB constraint more clear. + */ + *shaw2ba |= 0xff << 24; + } else { + *comm_fwh = 0; } - - sio_write(idx, NUVOTON_SIOCFG_LDN, org_ldn); - return 0; -error: + +out: sio_write(idx, NUVOTON_SIOCFG_LDN, org_ldn); - return -1; + return ret; }
/* Call superio to get pre-configured fwh_id. @@ -232,7 +246,8 @@ static int get_fwh_id(uint8_t *fwh_id)
org_ldn = sio_read(idx, NUVOTON_SIOCFG_LDN); sio_write(idx, NUVOTON_SIOCFG_LDN, NUVOTON_LDN_SHM); - *fwh_id = sio_read(idx, WPCE775X_SHM_CFG); + /* Upper 4 bits of WPCE775X_SHM_CFG store the FWH ID. */ + *fwh_id = sio_read(idx, WPCE775X_SHM_CFG) >> 4; sio_write(idx, NUVOTON_SIOCFG_LDN, org_ldn);
return 0; @@ -402,6 +417,7 @@ int probe_wpce775x(struct flashchip *flash) uint16_t sio_port; uint8_t srid; uint8_t fwh_id; + uint8_t comm_fwh = 0; uint32_t size; chipaddr original_memory; uint32_t original_size; @@ -425,14 +441,29 @@ int probe_wpce775x(struct flashchip *flash) }
/* get the address of Shadow Window 2. */ - if (get_shaw2ba(&wcb_physical_address) < 0) { + if (get_shaw2ba(&wcb_physical_address, &comm_fwh) < 0) { msg_cdbg("Cannot get the address of Shadow Window 2"); return 0; } msg_cdbg("Get the address of WCB(SHA WIN2) at 0x%08x\n", (uint32_t)wcb_physical_address); - wcb = (struct wpce775x_wcb *) - programmer_map_flash_region("WPCE775X WCB", + + /* If we use FWH for Shadow Window 2, we have to set FWH IDSEL in the + * chipset before we try to access Shadow Window 2. + */ + if (comm_fwh) { + if (get_fwh_id(&fwh_id) < 0) { + msg_cdbg("Cannot get fwh_id value.\n"); + return 0; + } + msg_cdbg("get fwh_id: 0x%02x\n", fwh_id); + + /* TODO: set fwh_idsel of chipset. + * Currently, we employ "-p internal:fwh_idsel=0x0000223e". + */ + } + + wcb = (struct wpce775x_wcb *)physmap("WPCE775X WCB", wcb_physical_address, getpagesize() /* min page size */); msg_cdbg("mapped wcb address: %p for physical addr: 0x%08lx\n", wcb, wcb_physical_address); @@ -442,15 +473,6 @@ int probe_wpce775x(struct flashchip *flash) } memset((void*)wcb, 0, sizeof(*wcb));
- if (get_fwh_id(&fwh_id) < 0) { - msg_cdbg("Cannot get fwh_id value.\n"); - return 0; - } - msg_cdbg("get fwh_id: 0x%02x\n", fwh_id); - - /* TODO: set fwh_idsel of chipset. - Currently, we employ "-p internal:fwh_idsel=0x0000223e". */ - /* Initialize the parameters of EC SHM component */ if (InitFlash(0x00)) return 0;