diff options
author | Werner Zeh <werner.zeh@siemens.com> | 2016-07-06 11:59:10 +0200 |
---|---|---|
committer | Werner Zeh <werner.zeh@siemens.com> | 2016-07-07 06:20:16 +0200 |
commit | e1d6aa6e4195f5fce6cb65d39d36289e6786fa36 (patch) | |
tree | 2f1e7fe5036d828b62452606c90bb2e3dc96488d /src/mainboard/siemens/mc_bdx1/mainboard.c | |
parent | 93db5a5eeea78423ca763bff013d3610655e3776 (diff) | |
download | coreboot-e1d6aa6e4195f5fce6cb65d39d36289e6786fa36.tar.xz |
siemens/mc_bdx1: Set up opcode menu for SPI controller
Since SPI controller opcode registers are locked by FSP, they need to be
initialized to a known good state before ReadyToBoot event and after
every SPI flash access (e.g. for MRC cache) has been finished in order
to enable the OS to use SPI controller without constraints.
Change-Id: I0a66344cd44e036c3999ae98d539072299cf5112
Signed-off-by: Werner Zeh <werner.zeh@siemens.com>
Reviewed-on: https://review.coreboot.org/15547
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/mainboard/siemens/mc_bdx1/mainboard.c')
-rw-r--r-- | src/mainboard/siemens/mc_bdx1/mainboard.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/src/mainboard/siemens/mc_bdx1/mainboard.c b/src/mainboard/siemens/mc_bdx1/mainboard.c index af886a9b5b..bad072b96e 100644 --- a/src/mainboard/siemens/mc_bdx1/mainboard.c +++ b/src/mainboard/siemens/mc_bdx1/mainboard.c @@ -31,9 +31,57 @@ #include <boot/coreboot_tables.h> #include <hwilib.h> #include <i210.h> +#include <soc/pci_devs.h> #define MAX_PATH_DEPTH 12 #define MAX_NUM_MAPPINGS 10 + +/* + * SPI Opcode Menu setup for SPIBAR lock down + * should support most common flash chips. + */ +#define SPI_OPMENU_0 0x01 /* WRSR: Write Status Register */ +#define SPI_OPTYPE_0 0x01 /* Write, no address */ + +#define SPI_OPMENU_1 0x02 /* BYPR: Byte Program */ +#define SPI_OPTYPE_1 0x03 /* Write, address required */ + +#define SPI_OPMENU_2 0x03 /* READ: Read Data */ +#define SPI_OPTYPE_2 0x02 /* Read, address required */ + +#define SPI_OPMENU_3 0x05 /* RDSR: Read Status Register */ +#define SPI_OPTYPE_3 0x00 /* Read, no address */ + +#define SPI_OPMENU_4 0x20 /* SE20: Sector Erase 0x20 */ +#define SPI_OPTYPE_4 0x03 /* Write, address required */ + +#define SPI_OPMENU_5 0x9f /* RDID: Read ID */ +#define SPI_OPTYPE_5 0x00 /* Read, no address */ + +#define SPI_OPMENU_6 0xd8 /* BED8: Block Erase 0xd8 */ +#define SPI_OPTYPE_6 0x03 /* Write, address required */ + +#define SPI_OPMENU_7 0x0b /* FAST: Fast Read */ +#define SPI_OPTYPE_7 0x02 /* Read, address required */ + +#define SPI_OPMENU_UPPER ((SPI_OPMENU_7 << 24) | (SPI_OPMENU_6 << 16) | \ + (SPI_OPMENU_5 << 8) | SPI_OPMENU_4) +#define SPI_OPMENU_LOWER ((SPI_OPMENU_3 << 24) | (SPI_OPMENU_2 << 16) | \ + (SPI_OPMENU_1 << 8) | SPI_OPMENU_0) + +#define SPI_OPTYPE ((SPI_OPTYPE_7 << 14) | (SPI_OPTYPE_6 << 12) | \ + (SPI_OPTYPE_5 << 10) | (SPI_OPTYPE_4 << 8) | \ + (SPI_OPTYPE_3 << 6) | (SPI_OPTYPE_2 << 4) | \ + (SPI_OPTYPE_1 << 2) | (SPI_OPTYPE_0)) + +#define SPI_OPPREFIX ((0x50 << 8) | 0x06) /* EWSR and WREN */ + +#define SPIBAR_OFFSET 0x3800 +#define SPI_REG_PREOP 0x94 +#define SPI_REG_OPTYPE 0x96 +#define SPI_REG_OPMENU_L 0x98 +#define SPI_REG_OPMENU_H 0x9c + /* * mainboard_enable is executed as first thing after enumerate_buses(). * This is the earliest point to add customization. @@ -42,6 +90,25 @@ static void mainboard_enable(device_t dev) { } + +static void mainboard_final(void *chip_info) +{ + void *spi_base = NULL; + uint32_t rcba = 0; + device_t dev = dev_find_slot(0, PCI_DEVFN(LPC_DEV, LPC_FUNC)); + + /* Get address of SPI controller. */ + rcba = (pci_read_config32(dev, 0xf0) & 0xffffc000); + if (!rcba) + return; + spi_base = (void *)(rcba + SPIBAR_OFFSET); + /* Setup OPCODE menu */ + write16((spi_base + SPI_REG_PREOP), SPI_OPPREFIX); + write16((spi_base + SPI_REG_OPTYPE), SPI_OPTYPE); + write32((spi_base + SPI_REG_OPMENU_L), SPI_OPMENU_LOWER); + write32((spi_base + SPI_REG_OPMENU_H), SPI_OPMENU_UPPER); +} + /** \brief This function can decide if a given MAC address is valid or not. * Currently, addresses filled with 0xff or 0x00 are not valid. * @param mac Buffer to the MAC address to check @@ -116,4 +183,5 @@ enum cb_err mainboard_get_mac_address(struct device *dev, uint8_t mac[6]) struct chip_operations mainboard_ops = { .enable_dev = mainboard_enable, + .final = mainboard_final }; |