[flashrom] [PATCH] Fix IDSEL handling in WPCE775X

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Wed Nov 17 07:54:10 CET 2010


I just noticed that the first patch was corrupt. This one should work.
This patch is for the flashrom-chromium tree.

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 at gmx.net>

diff --git a/wpce775x.c b/wpce775x.c
index a659893..6a71392 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;


-- 
http://www.hailfinger.org/





More information about the flashrom mailing list