SMM: Add option for SPI driver to be available in SMM
- add Kconfig option for CONFIG_SPI_FLASH_SMM - compile subsystem and chip drivers for smm if enabled - change mdelay(1) to udelay(500) since mdelay is not defined in SMM and a 1ms delay is worth avoiding - make flash chip structure non-const so the probe function pointers can be relocated for use in TSEG - Make SMM PCI access possible in southbridge SPI code Change-Id: Icfcbbe8e4e56658769d46af0b5bf6c79a6432641 Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: http://review.coreboot.org/1313 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
		
				
					committed by
					
						
						Ronald G. Minnich
					
				
			
			
				
	
			
			
			
						parent
						
							f5e9ac48c6
						
					
				
				
					commit
					181bbdd51c
				
			@@ -24,6 +24,13 @@ config SPI_FLASH
 | 
				
			|||||||
	  Select this option if your chipset driver needs to store certain
 | 
						  Select this option if your chipset driver needs to store certain
 | 
				
			||||||
	  data in the SPI flash.
 | 
						  data in the SPI flash.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config SPI_FLASH_SMM
 | 
				
			||||||
 | 
						bool "SPI flash driver support in SMM"
 | 
				
			||||||
 | 
						default n
 | 
				
			||||||
 | 
						depends on SPI_FLASH && HAVE_SMI_HANDLER
 | 
				
			||||||
 | 
						help
 | 
				
			||||||
 | 
						  Select this option if you want SPI flash support in SMM.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config SPI_FLASH_EON
 | 
					config SPI_FLASH_EON
 | 
				
			||||||
	bool
 | 
						bool
 | 
				
			||||||
	default y
 | 
						default y
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,3 +10,16 @@ ramstage-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.c
 | 
				
			|||||||
ramstage-$(CONFIG_SPI_FLASH_WINBOND) += winbond.c
 | 
					ramstage-$(CONFIG_SPI_FLASH_WINBOND) += winbond.c
 | 
				
			||||||
ramstage-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.c
 | 
					ramstage-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ifeq ($(CONFIG_SPI_FLASH_SMM),y)
 | 
				
			||||||
 | 
					# SPI flash driver interface
 | 
				
			||||||
 | 
					smm-$(CONFIG_SPI_FLASH) += spi_flash.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# drivers
 | 
				
			||||||
 | 
					smm-$(CONFIG_SPI_FLASH_EON) += eon.c
 | 
				
			||||||
 | 
					smm-$(CONFIG_SPI_FLASH_MACRONIX) += macronix.c
 | 
				
			||||||
 | 
					smm-$(CONFIG_SPI_FLASH_SPANSION) += spansion.c
 | 
				
			||||||
 | 
					smm-$(CONFIG_SPI_FLASH_SST) += sst.c
 | 
				
			||||||
 | 
					smm-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.c
 | 
				
			||||||
 | 
					smm-$(CONFIG_SPI_FLASH_WINBOND) += winbond.c
 | 
				
			||||||
 | 
					smm-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
@@ -12,6 +12,9 @@
 | 
				
			|||||||
#include <spi.h>
 | 
					#include <spi.h>
 | 
				
			||||||
#include <spi_flash.h>
 | 
					#include <spi_flash.h>
 | 
				
			||||||
#include <delay.h>
 | 
					#include <delay.h>
 | 
				
			||||||
 | 
					#ifdef __SMM__
 | 
				
			||||||
 | 
					#include <cpu/x86/smm.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#include "spi_flash_internal.h"
 | 
					#include "spi_flash_internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void spi_flash_addr(u32 addr, u8 *cmd)
 | 
					static void spi_flash_addr(u32 addr, u8 *cmd)
 | 
				
			||||||
@@ -115,7 +118,7 @@ int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
 | 
				
			|||||||
		if ((status & poll_bit) == 0)
 | 
							if ((status & poll_bit) == 0)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mdelay(1);
 | 
							udelay(500);
 | 
				
			||||||
	} while (timebase--);
 | 
						} while (timebase--);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((status & poll_bit) == 0)
 | 
						if ((status & poll_bit) == 0)
 | 
				
			||||||
@@ -206,7 +209,7 @@ out:
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
#define IDCODE_CONT_LEN 0
 | 
					#define IDCODE_CONT_LEN 0
 | 
				
			||||||
#define IDCODE_PART_LEN 5
 | 
					#define IDCODE_PART_LEN 5
 | 
				
			||||||
static const struct {
 | 
					static struct {
 | 
				
			||||||
	const u8 shift;
 | 
						const u8 shift;
 | 
				
			||||||
	const u8 idcode;
 | 
						const u8 idcode;
 | 
				
			||||||
	struct spi_flash *(*probe) (struct spi_slave *spi, u8 *idcode);
 | 
						struct spi_flash *(*probe) (struct spi_slave *spi, u8 *idcode);
 | 
				
			||||||
@@ -275,6 +278,10 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
 | 
				
			|||||||
	/* search the table for matches in shift and id */
 | 
						/* search the table for matches in shift and id */
 | 
				
			||||||
	for (i = 0; i < ARRAY_SIZE(flashes); ++i)
 | 
						for (i = 0; i < ARRAY_SIZE(flashes); ++i)
 | 
				
			||||||
		if (flashes[i].shift == shift && flashes[i].idcode == *idp) {
 | 
							if (flashes[i].shift == shift && flashes[i].idcode == *idp) {
 | 
				
			||||||
 | 
					#ifdef __SMM__
 | 
				
			||||||
 | 
								/* Need to relocate this function */
 | 
				
			||||||
 | 
								tseg_relocate((void **)&flashes[i].probe);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
			/* we have a match, call probe */
 | 
								/* we have a match, call probe */
 | 
				
			||||||
			flash = flashes[i].probe(spi, idp);
 | 
								flash = flashes[i].probe(spi, idp);
 | 
				
			||||||
			if (flash)
 | 
								if (flash)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,6 +33,7 @@ ramstage-y += reset.c
 | 
				
			|||||||
ramstage-y += watchdog.c
 | 
					ramstage-y += watchdog.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ramstage-y += spi.c
 | 
					ramstage-y += spi.c
 | 
				
			||||||
 | 
					smm-$(CONFIG_SPI_FLASH_SMM) += spi.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smi.c
 | 
					ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smi.c
 | 
				
			||||||
smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c me.c me_8.x.c finalize.c
 | 
					smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c me.c me_8.x.c finalize.c
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,20 +27,45 @@
 | 
				
			|||||||
#include <delay.h>
 | 
					#include <delay.h>
 | 
				
			||||||
#include <arch/io.h>
 | 
					#include <arch/io.h>
 | 
				
			||||||
#include <console/console.h>
 | 
					#include <console/console.h>
 | 
				
			||||||
#include <device/pci.h>
 | 
					 | 
				
			||||||
#include <device/pci_ids.h>
 | 
					#include <device/pci_ids.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <spi.h>
 | 
					#include <spi.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define min(a, b) ((a)<(b)?(a):(b))
 | 
					#define min(a, b) ((a)<(b)?(a):(b))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __SMM__
 | 
				
			||||||
 | 
					#include <arch/romcc_io.h>
 | 
				
			||||||
 | 
					#include <northbridge/intel/sandybridge/pcie_config.c>
 | 
				
			||||||
typedef device_t pci_dev_t;
 | 
					typedef device_t pci_dev_t;
 | 
				
			||||||
#define pci_read_config_byte(dev, reg, targ) *(targ) = pci_read_config8(dev, reg)
 | 
					#define pci_read_config_byte(dev, reg, targ)\
 | 
				
			||||||
#define pci_read_config_word(dev, reg, targ) *(targ) = pci_read_config16(dev, reg)
 | 
						*(targ) = pcie_read_config8(dev, reg)
 | 
				
			||||||
#define pci_read_config_dword(dev, reg, targ) *(targ) = pci_read_config32(dev, reg)
 | 
					#define pci_read_config_word(dev, reg, targ)\
 | 
				
			||||||
#define pci_write_config_byte(dev, reg, val) pci_write_config8(dev, reg, val)
 | 
						*(targ) = pcie_read_config16(dev, reg)
 | 
				
			||||||
#define pci_write_config_word(dev, reg, val) pci_write_config16(dev, reg, val)
 | 
					#define pci_read_config_dword(dev, reg, targ)\
 | 
				
			||||||
#define pci_write_config_dword(dev, reg, val) pci_write_config32(dev, reg, val)
 | 
						*(targ) = pcie_read_config32(dev, reg)
 | 
				
			||||||
 | 
					#define pci_write_config_byte(dev, reg, val)\
 | 
				
			||||||
 | 
						pcie_write_config8(dev, reg, val)
 | 
				
			||||||
 | 
					#define pci_write_config_word(dev, reg, val)\
 | 
				
			||||||
 | 
						pcie_write_config16(dev, reg, val)
 | 
				
			||||||
 | 
					#define pci_write_config_dword(dev, reg, val)\
 | 
				
			||||||
 | 
						pcie_write_config32(dev, reg, val)
 | 
				
			||||||
 | 
					#else /* !__SMM__ */
 | 
				
			||||||
 | 
					#include <device/device.h>
 | 
				
			||||||
 | 
					#include <device/pci.h>
 | 
				
			||||||
 | 
					typedef device_t pci_dev_t;
 | 
				
			||||||
 | 
					#define pci_read_config_byte(dev, reg, targ)\
 | 
				
			||||||
 | 
						*(targ) = pci_read_config8(dev, reg)
 | 
				
			||||||
 | 
					#define pci_read_config_word(dev, reg, targ)\
 | 
				
			||||||
 | 
						*(targ) = pci_read_config16(dev, reg)
 | 
				
			||||||
 | 
					#define pci_read_config_dword(dev, reg, targ)\
 | 
				
			||||||
 | 
						*(targ) = pci_read_config32(dev, reg)
 | 
				
			||||||
 | 
					#define pci_write_config_byte(dev, reg, val)\
 | 
				
			||||||
 | 
						pci_write_config8(dev, reg, val)
 | 
				
			||||||
 | 
					#define pci_write_config_word(dev, reg, val)\
 | 
				
			||||||
 | 
						pci_write_config16(dev, reg, val)
 | 
				
			||||||
 | 
					#define pci_write_config_dword(dev, reg, val)\
 | 
				
			||||||
 | 
						pci_write_config32(dev, reg, val)
 | 
				
			||||||
 | 
					#endif /* !__SMM__ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct spi_slave ich_spi_slave;
 | 
					typedef struct spi_slave ich_spi_slave;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -310,7 +335,11 @@ void spi_init(void)
 | 
				
			|||||||
	uint32_t ids;
 | 
						uint32_t ids;
 | 
				
			||||||
	uint16_t vendor_id, device_id;
 | 
						uint16_t vendor_id, device_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __SMM__
 | 
				
			||||||
 | 
						dev = PCI_DEV(0, 31, 0);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
	dev = dev_find_slot(0, PCI_DEVFN(31, 0));
 | 
						dev = dev_find_slot(0, PCI_DEVFN(31, 0));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	pci_read_config_dword(dev, 0, &ids);
 | 
						pci_read_config_dword(dev, 0, &ids);
 | 
				
			||||||
	vendor_id = ids;
 | 
						vendor_id = ids;
 | 
				
			||||||
	device_id = (ids >> 16);
 | 
						device_id = (ids >> 16);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user