soc/amd/common/block/spi: Add support for common SPI configuration

This change adds support for following SPI configuration functions to
common block SPI driver and exposes them to be used by SoC:
1. fch_spi_early_init(): Sets up SPI ROM base, enables SPI ROM,
enables prefetching, disables 4dw burst mode and sets SPI speed and mode.
2. fch_spi_config_modes(): This allows SoC to configure SPI speed and
mode. It uses SPI settings from soc_amd_common_config to configure the
speed and mode.

These functions expect SoC to include soc_amd_common_config in SoC
chip config and mainboard to configure these settings in device tree.

Signed-off-by: Furquan Shaikh <furquan@google.com>
Change-Id: Ia4f231bab69e8450005dd6abe7a8e014d5eb7261
Reviewed-on: https://review.coreboot.org/c/coreboot/+/41248
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Raul Rangel <rrangel@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Furquan Shaikh 2020-05-09 13:10:30 -07:00
parent 56875113b7
commit 08c524c0b7
5 changed files with 205 additions and 1 deletions

View File

@ -4,7 +4,19 @@
#ifndef __AMDBLOCKS_CHIP_H__
#define __AMDBLOCKS_CHIP_H__
#include <amdblocks/spi.h>
struct soc_amd_common_config {
/*
* SPI configuration
* Default values if not overridden by mainboard:
* Read mode - Normal 33MHz
* Normal speed - 66MHz
* Fast speed - 66MHz
* Alt speed - 66MHz
* TPM speed - 66MHz
*/
struct spi_config spi_config;
};
/*

View File

@ -0,0 +1,97 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* This file is part of the coreboot project. */
#ifndef __AMDBLOCKS_SPI_H__
#define __AMDBLOCKS_SPI_H__
#define SPI_CNTRL0 0x00
#define SPI_BUSY BIT(31)
enum spi_read_mode {
SPI_READ_MODE_NORMAL33M = 0,
/* 1 is reserved. */
SPI_READ_MODE_DUAL112 = 2,
SPI_READ_MODE_QUAD114 = 3,
SPI_READ_MODE_DUAL122 = 4,
SPI_READ_MODE_QUAD144 = 5,
SPI_READ_MODE_NORMAL66M = 6,
SPI_READ_MODE_FAST_READ = 7,
};
/*
* SPI read mode is split into bits 18, 29, 30 such that [30:29:18] correspond to bits [2:0] for
* SpiReadMode.
*/
#define SPI_READ_MODE_MASK (BIT(30) | BIT(29) | BIT(18))
#define SPI_READ_MODE_UPPER_BITS(x) ((((x) >> 1) & 0x3) << 29)
#define SPI_READ_MODE_LOWER_BITS(x) (((x) & 0x1) << 18)
#define SPI_READ_MODE(x) (SPI_READ_MODE_UPPER_BITS(x) | \
SPI_READ_MODE_LOWER_BITS(x))
#define SPI_ACCESS_MAC_ROM_EN BIT(22)
#define SPI100_ENABLE 0x20
#define SPI_USE_SPI100 BIT(0)
/* Use SPI_SPEED_16M-SPI_SPEED_66M below for the southbridge */
#define SPI100_SPEED_CONFIG 0x22
enum spi100_speed {
SPI_SPEED_66M = 0,
SPI_SPEED_33M = 1,
SPI_SPEED_22M = 2,
SPI_SPEED_16M = 3,
SPI_SPEED_100M = 4,
SPI_SPEED_800K = 5,
};
#define SPI_SPEED_MASK 0xf
#define SPI_SPEED_MODE(x, shift) (((x) & SPI_SPEED_MASK) << shift)
#define SPI_NORM_SPEED(x) SPI_SPEED_MODE(x, 12)
#define SPI_FAST_SPEED(x) SPI_SPEED_MODE(x, 8)
#define SPI_ALT_SPEED(x) SPI_SPEED_MODE(x, 4)
#define SPI_TPM_SPEED(x) SPI_SPEED_MODE(x, 0)
#define SPI_SPEED_CFG(n, f, a, t) (SPI_NORM_SPEED(n) | SPI_FAST_SPEED(f) | \
SPI_ALT_SPEED(a) | SPI_TPM_SPEED(t))
#define SPI100_HOST_PREF_CONFIG 0x2c
#define SPI_RD4DW_EN_HOST BIT(15)
#define SPI_FIFO 0x80
#define SPI_FIFO_DEPTH (0xc7 - SPI_FIFO)
struct spi_config {
/*
* Default values if not overridden by mainboard:
* Read mode - Normal 33MHz
* Normal speed - 66MHz
* Fast speed - 66MHz
* Alt speed - 66MHz
* TPM speed - 66MHz
*/
enum spi_read_mode read_mode;
enum spi100_speed normal_speed;
enum spi100_speed fast_speed;
enum spi100_speed altio_speed;
enum spi100_speed tpm_speed;
};
/*
* Perform early SPI initialization:
* 1. Sets SPI ROM base and enables SPI ROM
* 2. Enables SPI ROM prefetching
* 3. Disables 4dw burst
* 4. Configures SPI speed and read mode.
*
* This function expects SoC to include soc_amd_common_config in chip SoC config and uses
* settings from mainboard devicetree to configure speed and read mode.
*/
void fch_spi_early_init(void);
/*
* Configure SPI speed and read mode.
*
* This function expects SoC to include soc_amd_common_config in chip SoC config and uses
* settings from mainboard devicetree to configure speed and read mode.
*/
void fch_spi_config_modes(void);
#endif /* __AMDBLOCKS_SPI_H__ */

View File

@ -9,4 +9,13 @@ ifeq ($(CONFIG_SPI_FLASH_SMM),y)
smm-y += fch_spi_ctrl.c
endif
bootblock-y += fch_spi.c
romstage-y += fch_spi.c
postcar-y += fch_spi.c
ramstage-y += fch_spi.c
verstage-y += fch_spi.c
ifeq ($(CONFIG_SPI_FLASH_SMM),y)
smm-y += fch_spi.c
endif
endif

View File

@ -0,0 +1,86 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* This file is part of the coreboot project. */
#include <amdblocks/chip.h>
#include <amdblocks/lpc.h>
#include <amdblocks/spi.h>
#include <arch/mmio.h>
#include <console/console.h>
#include <soc/iomap.h>
#include <stdint.h>
static uintptr_t fch_spi_base(void)
{
uintptr_t base;
base = lpc_get_spibase();
if (base)
return base;
lpc_set_spibase(SPI_BASE_ADDRESS);
lpc_enable_spi_rom(SPI_ROM_ENABLE);
return SPI_BASE_ADDRESS;
}
static void fch_spi_set_spi100(int norm, int fast, int alt, int tpm)
{
uintptr_t base = fch_spi_base();
write16((void *)(base + SPI100_SPEED_CONFIG), SPI_SPEED_CFG(norm, fast, alt, tpm));
write16((void *)(base + SPI100_ENABLE), SPI_USE_SPI100);
}
static void fch_spi_disable_4dw_burst(void)
{
uintptr_t base = fch_spi_base();
uint16_t val = read16((void *)(base + SPI100_HOST_PREF_CONFIG));
write16((void *)(base + SPI100_HOST_PREF_CONFIG), val & ~SPI_RD4DW_EN_HOST);
}
static void fch_spi_set_read_mode(u32 mode)
{
uintptr_t base = fch_spi_base();
uint32_t val = read32((void *)(base + SPI_CNTRL0)) & ~SPI_READ_MODE_MASK;
write32((void *)(base + SPI_CNTRL0), val | SPI_READ_MODE(mode));
}
static void fch_spi_config_mb_modes(void)
{
const struct soc_amd_common_config *cfg = soc_get_common_config();
if (!cfg)
die("Common config structure is NULL!\n");
const struct spi_config *spi_cfg = &cfg->spi_config;
fch_spi_set_read_mode(spi_cfg->read_mode);
fch_spi_set_spi100(spi_cfg->normal_speed, spi_cfg->fast_speed,
spi_cfg->altio_speed, spi_cfg->tpm_speed);
}
static void fch_spi_config_em100_modes(void)
{
fch_spi_set_read_mode(SPI_READ_MODE_NORMAL33M);
fch_spi_set_spi100(SPI_SPEED_16M, SPI_SPEED_16M, SPI_SPEED_16M, SPI_SPEED_16M);
}
void fch_spi_config_modes(void)
{
if (CONFIG(EM100))
fch_spi_config_em100_modes();
else
fch_spi_config_mb_modes();
}
void fch_spi_early_init(void)
{
lpc_set_spibase(SPI_BASE_ADDRESS);
lpc_enable_spi_rom(SPI_ROM_ENABLE);
lpc_enable_spi_prefetch();
fch_spi_disable_4dw_burst();
fch_spi_config_modes();
}

View File

@ -2,9 +2,9 @@
#include <console/console.h>
#include <spi_flash.h>
#include <soc/southbridge.h>
#include <soc/pci_devs.h>
#include <amdblocks/lpc.h>
#include <amdblocks/spi.h>
#include <device/pci_ops.h>
#include <lib.h>
#include <timer.h>