diff options
author | Barnali Sarkar <barnali.sarkar@intel.com> | 2017-02-16 17:22:37 +0530 |
---|---|---|
committer | Martin Roth <martinroth@google.com> | 2017-05-01 16:26:26 +0200 |
commit | 89331cd4c877397adf6b35002d864ac105dfc827 (patch) | |
tree | bcef0ac94cb98df6a3ff127dd2fa2cdcfda2e6f5 /src/soc/intel/common/block/fast_spi/fast_spi.c | |
parent | 281ccca373c3b7c96452f35815fcf11274678117 (diff) |
soc/intel/common/block: Add Intel common FAST_SPI code
Create Intel Common FAST_SPI Controller code.
This code contains the code for SPI initialization which has
the following programming -
* Get BIOS Rom Region Size
* Enable SPIBAR
* Disable the BIOS write protect so write commands are allowed
* Enable SPI Prefetching and Caching.
* SPI Controller register offsets in the common header fast_spi.h
* Implement FAST_SPI read, write, erase APIs.
Change-Id: I046e3b30c8efb172851dd17f49565c9ec4cb38cb
Signed-off-by: Barnali Sarkar <barnali.sarkar@intel.com>
Reviewed-on: https://review.coreboot.org/18557
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
Diffstat (limited to 'src/soc/intel/common/block/fast_spi/fast_spi.c')
-rw-r--r-- | src/soc/intel/common/block/fast_spi/fast_spi.c | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/fast_spi/fast_spi.c b/src/soc/intel/common/block/fast_spi/fast_spi.c new file mode 100644 index 0000000000..603af16881 --- /dev/null +++ b/src/soc/intel/common/block/fast_spi/fast_spi.c @@ -0,0 +1,205 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2017 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/io.h> +#include <assert.h> +#include <device/pci_def.h> +#include <commonlib/helpers.h> +#include <console/console.h> +#include <fast_spi_def.h> +#include <intelblocks/fast_spi.h> +#include <soc/intel/common/spi_flash.h> +#include <soc/pci_devs.h> +#include <spi_flash.h> +#include <spi-generic.h> +#include <stdlib.h> +#include <string.h> + +/* + * Get the FAST_SPIBAR. + */ +void *fast_spi_get_bar(void) +{ + device_t dev = PCH_DEV_SPI; + uintptr_t bar; + + bar = pci_read_config32(dev, PCI_BASE_ADDRESS_0); + assert(bar != 0); + /* + * Bits 31-12 are the base address as per EDS for SPI, + * Don't care about 0-11 bit + */ + return (void *)(bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK); +} + +/* + * Disable the BIOS write protect and Enable Prefetching and Caching. + */ +void fast_spi_init(void) +{ + device_t dev = PCH_DEV_SPI; + uint8_t bios_cntl; + + bios_cntl = pci_read_config8(dev, SPIBAR_BIOS_CONTROL); + + /* Disable the BIOS write protect so write commands are allowed. */ + bios_cntl &= ~SPIBAR_BIOS_CONTROL_EISS; + bios_cntl |= SPIBAR_BIOS_CONTROL_WPD; + /* Enable Prefetching and caching. */ + bios_cntl |= SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE; + bios_cntl &= ~SPIBAR_BIOS_CONTROL_CACHE_DISABLE; + + pci_write_config8(dev, SPIBAR_BIOS_CONTROL, bios_cntl); +} + +/* + * Set FAST_SPIBAR BIOS Control BILD bit. + */ +static void fast_spi_set_bios_control_reg(uint8_t bios_cntl_bit) +{ + device_t dev = PCH_DEV_SPI; + uint8_t bc_cntl; + + assert((bios_cntl_bit & (bios_cntl_bit - 1)) == 0); + bc_cntl = pci_read_config8(dev, SPIBAR_BIOS_CONTROL); + bc_cntl |= bios_cntl_bit; + pci_write_config8(dev, SPIBAR_BIOS_CONTROL, bc_cntl); +} + +/* + * Set FAST_SPIBAR BIOS Control BILD bit. + */ +void fast_spi_set_bios_interface_lock_down(void) +{ + fast_spi_set_bios_control_reg(SPIBAR_BIOS_CONTROL_BILD); +} + +/* + * Set FAST_SPIBAR BIOS Control LE bit. + */ +void fast_spi_set_lock_enable(void) +{ + fast_spi_set_bios_control_reg(SPIBAR_BIOS_CONTROL_LOCK_ENABLE); +} + +/* + * Set FAST_SPIBAR BIOS Control EISS bit. + */ +void fast_spi_set_eiss(void) +{ + fast_spi_set_bios_control_reg(SPIBAR_BIOS_CONTROL_EISS); +} + +/* + * Set FAST_SPI opcode menu. + */ +void fast_spi_set_opcode_menu(void) +{ + void *spibar = fast_spi_get_bar(); + + write16(spibar + SPIBAR_PREOP, SPI_OPPREFIX); + write16(spibar + SPIBAR_OPTYPE, SPI_OPTYPE); + write32(spibar + SPIBAR_OPMENU_LOWER, SPI_OPMENU_LOWER); + write32(spibar + SPIBAR_OPMENU_UPPER, SPI_OPMENU_UPPER); +} + +/* + * Lock FAST_SPIBAR. + */ +void fast_spi_lock_bar(void) +{ + void *spibar = fast_spi_get_bar(); + uint32_t hsfs; + + hsfs = read32(spibar + SPIBAR_HSFSTS_CTL); + hsfs |= SPIBAR_HSFSTS_FLOCKDN; + write32(spibar + SPIBAR_HSFSTS_CTL, hsfs); +} + +/* + * Set FAST_SPIBAR Soft Reset Data Register value. + */ +void fast_spi_set_strap_msg_data(uint32_t soft_reset_data) +{ + void *spibar = fast_spi_get_bar(); + uint32_t ssl, ssms; + + /* Set Strap Lock Disable */ + ssl = read32(spibar + SPIBAR_RESET_LOCK); + ssl &= ~SPIBAR_RESET_LOCK_ENABLE; + write32(spibar + SPIBAR_RESET_LOCK, ssl); + + /* Write Soft Reset Data register at SPIBAR0 offset 0xF8[0:15] */ + write32(spibar + SPIBAR_RESET_DATA, soft_reset_data); + + /* Set Strap Mux Select set to '1' */ + ssms = read32(spibar + SPIBAR_RESET_CTRL); + ssms |= SPIBAR_RESET_CTRL_SSMC; + write32(spibar + SPIBAR_RESET_CTRL, ssms); + + /* Set Strap Lock Enable */ + ssl = read32(spibar + SPIBAR_RESET_LOCK); + ssl |= SPIBAR_RESET_LOCK_ENABLE; + write32(spibar + SPIBAR_RESET_LOCK, ssl); +} + +/* + * Returns bios_start and fills in size of the BIOS region. + */ +size_t fast_spi_get_bios_region(size_t *bios_size) +{ + size_t bios_start, bios_end; + /* + * BIOS_BFPREG provides info about BIOS Flash Primary Region + * Base and Limit. + * Base and Limit fields are in units of 4KiB. + */ + uint32_t val = read32(fast_spi_get_bar() + SPIBAR_BFPREG); + + bios_start = (val & SPIBAR_BFPREG_PRB_MASK) * 4 * KiB; + bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >> + SPIBAR_BFPREG_PRL_SHIFT) + 1) * 4 * KiB; + *bios_size = bios_end - bios_start; + return bios_start; +} + +/* + * Program temporary BAR for SPI in case any of the stages before ramstage need + * to access FAST_SPI MMIO regs. Ramstage will assign a new BAR during PCI + * enumeration. + */ +void fast_spi_early_init(uintptr_t spi_base_address) +{ + device_t dev = PCH_DEV_SPI; + uint8_t pcireg; + + /* Assign Resources to SPI Controller */ + /* Clear BIT 1-2 SPI Command Register */ + pcireg = pci_read_config8(dev, PCI_COMMAND); + pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); + pci_write_config8(dev, PCI_COMMAND, pcireg); + + /* Program Temporary BAR for SPI */ + pci_write_config32(dev, PCI_BASE_ADDRESS_0, + spi_base_address | PCI_BASE_ADDRESS_SPACE_MEMORY); + + /* Enable Bus Master and MMIO Space */ + pcireg = pci_read_config8(dev, PCI_COMMAND); + pcireg |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config8(dev, PCI_COMMAND, pcireg); + + /* Initialize SPI to allow BIOS to write/erase on flash. */ + fast_spi_init(); +} |