mirror of
				https://review.coreboot.org/flashrom.git
				synced 2025-11-04 07:00:39 +01:00 
			
		
		
		
	ichspi.c: Add support for region 9 and beyond in Meteor Lake
Since Meteor Lake, configuring region access for FREG9 and higher is necessary. This configuration is determined using BIOS_BM registers: BIOS_BM_RAP (Offset 0x118): BIOS Master Read Access Permissions. Each bit [15:0] corresponds to a region [15:0]. A set bit grants BIOS master read access. BIOS_BM_WAP (Offset 0x11c): BIOS Master Write Access Permissions. Each bit [15:0] corresponds to a region [15:0]. A set bit grants BIOS master write/erase access. Move CHIPSET_METEOR_LAKE to the bottom of the ich_chipset list to ensure that all the newer chipsets in the future will use BIOS_BM check by default. BUG=b:319773700, b:304439294 BUG=b:319336080 TEST=On MTL, use flashrom -VV to see correct FREG9 access TEST=On ADL, use flashrom -VV to see not break anything TEST=On APL, use flashrom -VV to see not break anything Change-Id: I1e06e7b3d470423a6014e623826d9234fdebfbf9 Signed-off-by: Hsuan Ting Chen <roccochen@chromium.org> Reviewed-on: https://review.coreboot.org/c/flashrom/+/81357 Reviewed-by: Jamie Ryu <jamie.m.ryu@intel.com> Reviewed-by: Nikolai Artemiev <nartemiev@google.com> Reviewed-by: Anastasia Klimchuk <aklm@chromium.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
		
				
					committed by
					
						
						Anastasia Klimchuk
					
				
			
			
				
	
			
			
			
						parent
						
							3b3e25f1ca
						
					
				
				
					commit
					85b977151b
				
			
							
								
								
									
										84
									
								
								ichspi.c
									
									
									
									
									
								
							
							
						
						
									
										84
									
								
								ichspi.c
									
									
									
									
									
								
							@@ -153,6 +153,9 @@
 | 
				
			|||||||
#define ICH9_FADDR_FLA		0x01ffffff
 | 
					#define ICH9_FADDR_FLA		0x01ffffff
 | 
				
			||||||
#define ICH9_REG_FDATA0		0x10	/* 64 Bytes */
 | 
					#define ICH9_REG_FDATA0		0x10	/* 64 Bytes */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ICH_REG_BIOS_BM_RAP	0x118	/* 16 Bits BIOS Master Read Access Permissions */
 | 
				
			||||||
 | 
					#define ICH_REG_BIOS_BM_WAP	0x11c	/* 16 Bits BIOS Master Write Access Permissions */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ICH9_REG_FRAP		0x50	/* 32 Bytes Flash Region Access Permissions */
 | 
					#define ICH9_REG_FRAP		0x50	/* 32 Bytes Flash Region Access Permissions */
 | 
				
			||||||
#define ICH9_REG_FREG0		0x54	/* 32 Bytes Flash Region 0 */
 | 
					#define ICH9_REG_FREG0		0x54	/* 32 Bytes Flash Region 0 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1834,8 +1837,52 @@ static const char *const access_names[] = {
 | 
				
			|||||||
	"read-write", "write-only", "read-only", "locked"
 | 
						"read-write", "write-only", "read-only", "locked"
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static enum ich_access_protection ich9_handle_frap(struct fd_region *fd_regions,
 | 
					static void ich_get_bios_region_access(uint16_t *region_read_access,
 | 
				
			||||||
						   uint32_t frap, unsigned int i)
 | 
									       uint16_t *region_write_access)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t tmp;
 | 
				
			||||||
 | 
						*region_read_access = 0;
 | 
				
			||||||
 | 
						*region_write_access = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ich_generation >= CHIPSET_METEOR_LAKE) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Starting from Meteor Lake, we need to fetch the region
 | 
				
			||||||
 | 
							 * read/write access permissions from the BIOS_BM registers
 | 
				
			||||||
 | 
							 * because we need to support FREG9 or above.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							*region_read_access = mmio_readw(ich_spibar + ICH_REG_BIOS_BM_RAP);
 | 
				
			||||||
 | 
							*region_write_access = mmio_readw(ich_spibar + ICH_REG_BIOS_BM_WAP);
 | 
				
			||||||
 | 
							msg_pdbg("0x118: 0x%04"PRIx16" (BIOS_BM_RAP)\n", *region_read_access);
 | 
				
			||||||
 | 
							msg_pdbg("0x11a: 0x%04"PRIx16" (BIOS_BM_WAP)\n", *region_write_access);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * FRAP - Flash Regions Access Permissions Register
 | 
				
			||||||
 | 
							 * Bit Descriptions:
 | 
				
			||||||
 | 
							 * 31:24 BIOS Master Write Access Grant (BMWAG)
 | 
				
			||||||
 | 
							 * 23:16 BIOS Master Read Access Grant (BMRAG)
 | 
				
			||||||
 | 
							 * 15:8 BIOS Region Write Access (BRWA)
 | 
				
			||||||
 | 
							 * 7:0 BIOS Region Read Access (BRRA)
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							tmp = mmio_readl(ich_spibar + ICH9_REG_FRAP);
 | 
				
			||||||
 | 
							msg_pdbg("0x50: 0x%08"PRIx32" (FRAP)\n", tmp);
 | 
				
			||||||
 | 
							msg_pdbg("BMWAG 0x%02"PRIx32", ", ICH_BMWAG(tmp));
 | 
				
			||||||
 | 
							msg_pdbg("BMRAG 0x%02"PRIx32", ", ICH_BMRAG(tmp));
 | 
				
			||||||
 | 
							msg_pdbg("BRWA 0x%02"PRIx32", ", ICH_BRWA(tmp));
 | 
				
			||||||
 | 
							msg_pdbg("BRRA 0x%02"PRIx32"\n", ICH_BRRA(tmp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*region_read_access = (uint16_t)ICH_BRRA(tmp);
 | 
				
			||||||
 | 
							*region_write_access = (uint16_t)ICH_BRWA(tmp);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned int ich_get_defined_region_count(void) {
 | 
				
			||||||
 | 
						return (ich_generation >= CHIPSET_METEOR_LAKE) ? 16 : 8;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static enum ich_access_protection ich9_handle_region_access(struct fd_region *fd_regions,
 | 
				
			||||||
 | 
												    uint16_t region_read_access,
 | 
				
			||||||
 | 
												    uint16_t region_write_access,
 | 
				
			||||||
 | 
												    unsigned int i)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static const char *const region_names[] = {
 | 
						static const char *const region_names[] = {
 | 
				
			||||||
		"Flash Descriptor", "BIOS", "Management Engine",
 | 
							"Flash Descriptor", "BIOS", "Management Engine",
 | 
				
			||||||
@@ -1863,12 +1910,12 @@ static enum ich_access_protection ich9_handle_frap(struct fd_region *fd_regions,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	msg_pdbg("0x%02X: 0x%08"PRIx32" ", offset, freg);
 | 
						msg_pdbg("0x%02X: 0x%08"PRIx32" ", offset, freg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (i < 8) {
 | 
						if (i < ich_get_defined_region_count()) {
 | 
				
			||||||
		rwperms_idx = (((ICH_BRWA(frap) >> i) & 1) << 1) |
 | 
							rwperms_idx = (((region_write_access >> i) & 1) << 1) |
 | 
				
			||||||
			      (((ICH_BRRA(frap) >> i) & 1) << 0);
 | 
								      (((region_read_access >> i) & 1) << 0);
 | 
				
			||||||
		rwperms = access_perms_to_protection[rwperms_idx];
 | 
							rwperms = access_perms_to_protection[rwperms_idx];
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		/* Datasheets don't define any access bits for regions > 7. We
 | 
							/* Datasheets might not define all the access bits for regions. We
 | 
				
			||||||
		   can't rely on the actual descriptor settings either as there
 | 
							   can't rely on the actual descriptor settings either as there
 | 
				
			||||||
		   are several overrides for them (those by other masters are
 | 
							   are several overrides for them (those by other masters are
 | 
				
			||||||
		   not even readable by us, *shrug*). */
 | 
							   not even readable by us, *shrug*). */
 | 
				
			||||||
@@ -2059,11 +2106,11 @@ static void init_chipset_properties(struct swseq_data *swseq, struct hwseq_data
 | 
				
			|||||||
	case CHIPSET_400_SERIES_COMET_POINT:
 | 
						case CHIPSET_400_SERIES_COMET_POINT:
 | 
				
			||||||
	case CHIPSET_500_SERIES_TIGER_POINT:
 | 
						case CHIPSET_500_SERIES_TIGER_POINT:
 | 
				
			||||||
	case CHIPSET_600_SERIES_ALDER_POINT:
 | 
						case CHIPSET_600_SERIES_ALDER_POINT:
 | 
				
			||||||
	case CHIPSET_METEOR_LAKE:
 | 
					 | 
				
			||||||
	case CHIPSET_APOLLO_LAKE:
 | 
						case CHIPSET_APOLLO_LAKE:
 | 
				
			||||||
	case CHIPSET_GEMINI_LAKE:
 | 
						case CHIPSET_GEMINI_LAKE:
 | 
				
			||||||
	case CHIPSET_JASPER_LAKE:
 | 
						case CHIPSET_JASPER_LAKE:
 | 
				
			||||||
	case CHIPSET_ELKHART_LAKE:
 | 
						case CHIPSET_ELKHART_LAKE:
 | 
				
			||||||
 | 
						case CHIPSET_METEOR_LAKE:
 | 
				
			||||||
		*num_pr			= 6;	/* Includes GPR0 */
 | 
							*num_pr			= 6;	/* Includes GPR0 */
 | 
				
			||||||
		*reg_pr0		= PCH100_REG_FPR0;
 | 
							*reg_pr0		= PCH100_REG_FPR0;
 | 
				
			||||||
		swseq->reg_ssfsc	= PCH100_REG_SSFSC;
 | 
							swseq->reg_ssfsc	= PCH100_REG_SSFSC;
 | 
				
			||||||
@@ -2099,11 +2146,11 @@ static void init_chipset_properties(struct swseq_data *swseq, struct hwseq_data
 | 
				
			|||||||
	case CHIPSET_400_SERIES_COMET_POINT:
 | 
						case CHIPSET_400_SERIES_COMET_POINT:
 | 
				
			||||||
	case CHIPSET_500_SERIES_TIGER_POINT:
 | 
						case CHIPSET_500_SERIES_TIGER_POINT:
 | 
				
			||||||
	case CHIPSET_600_SERIES_ALDER_POINT:
 | 
						case CHIPSET_600_SERIES_ALDER_POINT:
 | 
				
			||||||
	case CHIPSET_METEOR_LAKE:
 | 
					 | 
				
			||||||
	case CHIPSET_APOLLO_LAKE:
 | 
						case CHIPSET_APOLLO_LAKE:
 | 
				
			||||||
	case CHIPSET_GEMINI_LAKE:
 | 
						case CHIPSET_GEMINI_LAKE:
 | 
				
			||||||
	case CHIPSET_JASPER_LAKE:
 | 
						case CHIPSET_JASPER_LAKE:
 | 
				
			||||||
	case CHIPSET_ELKHART_LAKE:
 | 
						case CHIPSET_ELKHART_LAKE:
 | 
				
			||||||
 | 
						case CHIPSET_METEOR_LAKE:
 | 
				
			||||||
		*num_freg = 16;
 | 
							*num_freg = 16;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
@@ -2161,11 +2208,11 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum
 | 
				
			|||||||
	case CHIPSET_400_SERIES_COMET_POINT:
 | 
						case CHIPSET_400_SERIES_COMET_POINT:
 | 
				
			||||||
	case CHIPSET_500_SERIES_TIGER_POINT:
 | 
						case CHIPSET_500_SERIES_TIGER_POINT:
 | 
				
			||||||
	case CHIPSET_600_SERIES_ALDER_POINT:
 | 
						case CHIPSET_600_SERIES_ALDER_POINT:
 | 
				
			||||||
	case CHIPSET_METEOR_LAKE:
 | 
					 | 
				
			||||||
	case CHIPSET_APOLLO_LAKE:
 | 
						case CHIPSET_APOLLO_LAKE:
 | 
				
			||||||
	case CHIPSET_GEMINI_LAKE:
 | 
						case CHIPSET_GEMINI_LAKE:
 | 
				
			||||||
	case CHIPSET_JASPER_LAKE:
 | 
						case CHIPSET_JASPER_LAKE:
 | 
				
			||||||
	case CHIPSET_ELKHART_LAKE:
 | 
						case CHIPSET_ELKHART_LAKE:
 | 
				
			||||||
 | 
						case CHIPSET_METEOR_LAKE:
 | 
				
			||||||
		tmp = mmio_readl(spibar + PCH100_REG_DLOCK);
 | 
							tmp = mmio_readl(spibar + PCH100_REG_DLOCK);
 | 
				
			||||||
		msg_pdbg("0x0c: 0x%08"PRIx32" (DLOCK)\n", tmp);
 | 
							msg_pdbg("0x0c: 0x%08"PRIx32" (DLOCK)\n", tmp);
 | 
				
			||||||
		prettyprint_pch100_reg_dlock(tmp);
 | 
							prettyprint_pch100_reg_dlock(tmp);
 | 
				
			||||||
@@ -2175,16 +2222,15 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (desc_valid) {
 | 
						if (desc_valid) {
 | 
				
			||||||
		tmp = mmio_readl(spibar + ICH9_REG_FRAP);
 | 
							/* Get the region access data from FRAP/BIOS_BM */
 | 
				
			||||||
		msg_pdbg("0x50: 0x%08"PRIx32" (FRAP)\n", tmp);
 | 
							uint16_t region_read_access, region_write_access;
 | 
				
			||||||
		msg_pdbg("BMWAG 0x%02"PRIx32", ", ICH_BMWAG(tmp));
 | 
							ich_get_bios_region_access(®ion_read_access, ®ion_write_access);
 | 
				
			||||||
		msg_pdbg("BMRAG 0x%02"PRIx32", ", ICH_BMRAG(tmp));
 | 
					 | 
				
			||||||
		msg_pdbg("BRWA 0x%02"PRIx32", ", ICH_BRWA(tmp));
 | 
					 | 
				
			||||||
		msg_pdbg("BRRA 0x%02"PRIx32"\n", ICH_BRRA(tmp));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Handle FREGx and FRAP registers */
 | 
							/* Handle FREGx and region access registers */
 | 
				
			||||||
		for (i = 0; i < num_freg; i++)
 | 
							for (i = 0; i < num_freg; i++)
 | 
				
			||||||
			ich_spi_rw_restricted |= ich9_handle_frap(hwseq_data.fd_regions, tmp, i);
 | 
								ich_spi_rw_restricted |= ich9_handle_region_access(hwseq_data.fd_regions,
 | 
				
			||||||
 | 
														   region_read_access,
 | 
				
			||||||
 | 
														   region_write_access, i);
 | 
				
			||||||
		if (ich_spi_rw_restricted)
 | 
							if (ich_spi_rw_restricted)
 | 
				
			||||||
			msg_pinfo("Not all flash regions are freely accessible by flashrom. This is "
 | 
								msg_pinfo("Not all flash regions are freely accessible by flashrom. This is "
 | 
				
			||||||
				  "most likely\ndue to an active ME. Please see "
 | 
									  "most likely\ndue to an active ME. Please see "
 | 
				
			||||||
@@ -2242,12 +2288,12 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum
 | 
				
			|||||||
		case CHIPSET_400_SERIES_COMET_POINT:
 | 
							case CHIPSET_400_SERIES_COMET_POINT:
 | 
				
			||||||
		case CHIPSET_500_SERIES_TIGER_POINT:
 | 
							case CHIPSET_500_SERIES_TIGER_POINT:
 | 
				
			||||||
		case CHIPSET_600_SERIES_ALDER_POINT:
 | 
							case CHIPSET_600_SERIES_ALDER_POINT:
 | 
				
			||||||
		case CHIPSET_METEOR_LAKE:
 | 
					 | 
				
			||||||
		case CHIPSET_APOLLO_LAKE:
 | 
							case CHIPSET_APOLLO_LAKE:
 | 
				
			||||||
		case CHIPSET_GEMINI_LAKE:
 | 
							case CHIPSET_GEMINI_LAKE:
 | 
				
			||||||
		case CHIPSET_JASPER_LAKE:
 | 
							case CHIPSET_JASPER_LAKE:
 | 
				
			||||||
		case CHIPSET_BAYTRAIL:
 | 
							case CHIPSET_BAYTRAIL:
 | 
				
			||||||
		case CHIPSET_ELKHART_LAKE:
 | 
							case CHIPSET_ELKHART_LAKE:
 | 
				
			||||||
 | 
							case CHIPSET_METEOR_LAKE:
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			ichspi_bbar = mmio_readl(spibar + ICH9_REG_BBAR);
 | 
								ichspi_bbar = mmio_readl(spibar + ICH9_REG_BBAR);
 | 
				
			||||||
@@ -2282,11 +2328,11 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum
 | 
				
			|||||||
		case CHIPSET_400_SERIES_COMET_POINT:
 | 
							case CHIPSET_400_SERIES_COMET_POINT:
 | 
				
			||||||
		case CHIPSET_500_SERIES_TIGER_POINT:
 | 
							case CHIPSET_500_SERIES_TIGER_POINT:
 | 
				
			||||||
		case CHIPSET_600_SERIES_ALDER_POINT:
 | 
							case CHIPSET_600_SERIES_ALDER_POINT:
 | 
				
			||||||
		case CHIPSET_METEOR_LAKE:
 | 
					 | 
				
			||||||
		case CHIPSET_APOLLO_LAKE:
 | 
							case CHIPSET_APOLLO_LAKE:
 | 
				
			||||||
		case CHIPSET_GEMINI_LAKE:
 | 
							case CHIPSET_GEMINI_LAKE:
 | 
				
			||||||
		case CHIPSET_JASPER_LAKE:
 | 
							case CHIPSET_JASPER_LAKE:
 | 
				
			||||||
		case CHIPSET_ELKHART_LAKE:
 | 
							case CHIPSET_ELKHART_LAKE:
 | 
				
			||||||
 | 
							case CHIPSET_METEOR_LAKE:
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			tmp = mmio_readl(spibar + ICH9_REG_FPB);
 | 
								tmp = mmio_readl(spibar + ICH9_REG_FPB);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -357,11 +357,12 @@ enum ich_chipset {
 | 
				
			|||||||
	CHIPSET_400_SERIES_COMET_POINT,
 | 
						CHIPSET_400_SERIES_COMET_POINT,
 | 
				
			||||||
	CHIPSET_500_SERIES_TIGER_POINT,
 | 
						CHIPSET_500_SERIES_TIGER_POINT,
 | 
				
			||||||
	CHIPSET_600_SERIES_ALDER_POINT,
 | 
						CHIPSET_600_SERIES_ALDER_POINT,
 | 
				
			||||||
	CHIPSET_METEOR_LAKE,
 | 
					 | 
				
			||||||
	CHIPSET_APOLLO_LAKE,
 | 
						CHIPSET_APOLLO_LAKE,
 | 
				
			||||||
	CHIPSET_GEMINI_LAKE,
 | 
						CHIPSET_GEMINI_LAKE,
 | 
				
			||||||
	CHIPSET_JASPER_LAKE,
 | 
						CHIPSET_JASPER_LAKE,
 | 
				
			||||||
	CHIPSET_ELKHART_LAKE,
 | 
						CHIPSET_ELKHART_LAKE,
 | 
				
			||||||
 | 
						/* All chipsets after METEOR_LAKE should support checking BIOS_BM to get read/write access to of FREG0~15 */
 | 
				
			||||||
 | 
						CHIPSET_METEOR_LAKE,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ichspi.c */
 | 
					/* ichspi.c */
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user