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:
Duncan Laurie
2012-06-23 16:53:57 -07:00
committed by Ronald G. Minnich
parent f5e9ac48c6
commit 181bbdd51c
5 changed files with 66 additions and 9 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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);