From 922064162bb4695a276bd46ba0a928e94825ac8b Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Thu, 3 Mar 2016 10:58:30 -0800 Subject: soc/intel/common/nvm: Allow overriding to_flash_offset() function On apollolake, the flash is memory-mapped differently, and the default MMIO to flash calculation does not produce correct results. While the long-term solution is to rewrite the NVM functionality to keep the flash offset as part of its context, as a temporary measure, allow overriding the to_flash_offset() function by declaring it weak. Change-Id: Ic54baeba2441a08cfe1a47e235747797f6efb59b Signed-off-by: Alexandru Gagniuc Signed-off-by: Andrey Petrov Reviewed-on: https://review.coreboot.org/14247 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin --- src/soc/intel/common/nvm.c | 22 +++++++++++++++++----- src/soc/intel/common/nvm.h | 3 +++ 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'src/soc') diff --git a/src/soc/intel/common/nvm.c b/src/soc/intel/common/nvm.c index fe73408b51..e55638aade 100644 --- a/src/soc/intel/common/nvm.c +++ b/src/soc/intel/common/nvm.c @@ -46,8 +46,20 @@ static int nvm_init(void) return 0; } -/* Convert memory mapped pointer to flash offset. */ -static inline uint32_t to_flash_offset(void *p) +/* + * Convert memory mapped pointer to flash offset. + * + * This is weak because not every platforms memory-maps the NVM media in the + * same manner. This is a stop-gap solution. + * + * The root of the problem is that users of this API work in memory space for + * both reads and writes, but erase and write must be done in flash space. This + * also only works when the media is memory-mapped, which is no longer + * universally true. The long-term approach should be to rewrite this and its + * users to work in flash space, while using rdev_read() instead of rdev_mmap(). + */ +__attribute__((weak)) +uint32_t nvm_mmio_to_flash_offset(void *p) { return CONFIG_ROM_SIZE + (uintptr_t)p; } @@ -70,7 +82,7 @@ int nvm_erase(void *start, size_t size) { if (nvm_init() < 0) return -1; - return flash->erase(flash, to_flash_offset(start), size); + return flash->erase(flash, nvm_mmio_to_flash_offset(start), size); } /* Write data to NVM. Returns 0 on success < 0 on error. */ @@ -78,7 +90,7 @@ int nvm_write(void *start, const void *data, size_t size) { if (nvm_init() < 0) return -1; - return flash->write(flash, to_flash_offset(start), size, data); + return flash->write(flash, nvm_mmio_to_flash_offset(start), size, data); } /* Read flash status register to determine if write protect is active */ @@ -115,7 +127,7 @@ int nvm_protect(void *start, size_t size) #if IS_ENABLED(CONFIG_MRC_SETTINGS_PROTECT) if (nvm_init() < 0) return -1; - return spi_flash_protect(to_flash_offset(start), size); + return spi_flash_protect(nvm_mmio_to_flash_offset(start), size); #else return -1; #endif diff --git a/src/soc/intel/common/nvm.h b/src/soc/intel/common/nvm.h index feae5c3823..074a2ce406 100644 --- a/src/soc/intel/common/nvm.h +++ b/src/soc/intel/common/nvm.h @@ -33,4 +33,7 @@ int nvm_is_write_protected(void); /* Apply protection to a range of flash */ int nvm_protect(void *start, size_t size); +/* Map MMIO address to actual address in flash */ +uint32_t nvm_mmio_to_flash_offset(void *p); + #endif /* _COMMON_NVM_H_ */ -- cgit v1.2.3