From 321111774ce013b35641fe6d0e03e693974b4a28 Mon Sep 17 00:00:00 2001 From: Lijian Zhao Date: Wed, 16 Aug 2017 11:40:03 -0700 Subject: soc/intel/cannonlake: Add SPI flash controller driver Add SPI driver code for the SPI flash controller, including both fast_spi and generic_spi. Change-Id: Ie45146721f39d3cec20ff5136adf8925c75da1cd Signed-off-by: Lijian Zhao Reviewed-on: https://review.coreboot.org/21052 Tested-by: build bot (Jenkins) Reviewed-by: Pratikkumar Prajapati Reviewed-by: Aaron Durbin --- src/soc/intel/cannonlake/Kconfig | 9 ++++ src/soc/intel/cannonlake/Makefile.inc | 7 +++ src/soc/intel/cannonlake/chip.h | 3 ++ src/soc/intel/cannonlake/gspi.c | 71 +++++++++++++++++++++++++ src/soc/intel/cannonlake/include/soc/pci_devs.h | 2 + src/soc/intel/cannonlake/spi.c | 71 +++++++++++++++++++++++++ 6 files changed, 163 insertions(+) create mode 100644 src/soc/intel/cannonlake/gspi.c create mode 100644 src/soc/intel/cannonlake/spi.c (limited to 'src') diff --git a/src/soc/intel/cannonlake/Kconfig b/src/soc/intel/cannonlake/Kconfig index 311cfb8a8c..1b6759cd9b 100644 --- a/src/soc/intel/cannonlake/Kconfig +++ b/src/soc/intel/cannonlake/Kconfig @@ -11,6 +11,8 @@ config CPU_SPECIFIC_OPTIONS select ARCH_RAMSTAGE_X86_32 select ARCH_ROMSTAGE_X86_32 select ARCH_VERSTAGE_X86_32 + select BOOT_DEVICE_SPI_FLASH_RW_NOMMAP_EARLY if BOOT_DEVICE_SPI_FLASH + select BOOT_DEVICE_SUPPORTS_WRITES select C_ENVIRONMENT_BOOTBLOCK select CPU_INTEL_FIRMWARE_INTERFACE_TABLE select HAVE_HARD_RESET @@ -29,6 +31,7 @@ config CPU_SPECIFIC_OPTIONS select SOC_INTEL_COMMON_BLOCK_CSE select SOC_INTEL_COMMON_BLOCK_FAST_SPI select SOC_INTEL_COMMON_BLOCK_GPIO + select SOC_INTEL_COMMON_BLOCK_GSPI select SOC_INTEL_COMMON_BLOCK_LPSS select SOC_INTEL_COMMON_BLOCK_PCR select SOC_INTEL_COMMON_BLOCK_RTC @@ -38,6 +41,7 @@ config CPU_SPECIFIC_OPTIONS select SOC_INTEL_COMMON_BLOCK_SMM_IO_TRAP select SOC_INTEL_COMMON_BLOCK_TIMER select SOC_INTEL_COMMON_BLOCK_UART + select SOC_INTEL_COMMON_SPI_FLASH_PROTECT select SOC_INTEL_COMMON_RESET select SUPPORT_CPU_UCODE_IN_CBFS select TSC_CONSTANT_RATE @@ -78,6 +82,11 @@ config CPU_BCLK_MHZ int default 100 + +config SOC_INTEL_COMMON_BLOCK_GSPI_MAX + int + default 3 + # Clock divider parameters for 115200 baud rate config SOC_INTEL_COMMON_LPSS_UART_CLK_M_VAL hex diff --git a/src/soc/intel/cannonlake/Makefile.inc b/src/soc/intel/cannonlake/Makefile.inc index 297d34f176..8a83eb0578 100644 --- a/src/soc/intel/cannonlake/Makefile.inc +++ b/src/soc/intel/cannonlake/Makefile.inc @@ -11,20 +11,27 @@ bootblock-y += bootblock/cpu.c bootblock-y += bootblock/pch.c bootblock-y += bootblock/report_platform.c bootblock-y += gpio.c +bootblock-y += gspi.c bootblock-y += memmap.c +bootblock-y += spi.c bootblock-$(CONFIG_UART_DEBUG) += uart.c +romstage-y += gspi.c romstage-y += memmap.c romstage-y += reset.c +romstage-y += spi.c romstage-$(CONFIG_UART_DEBUG) += uart.c ramstage-y += chip.c +ramstage-y += gspi.c ramstage-y += memmap.c ramstage-$(CONFIG_PLATFORM_USES_FSP2_0) += reset.c +ramstage-y += spi.c ramstage-y += systemagent.c ramstage-$(CONFIG_UART_DEBUG) += uart.c postcar-y += memmap.c +postcar-y += spi.c postcar-$(CONFIG_UART_DEBUG) += uart.c CPPFLAGS_common += -I$(src)/soc/intel/cannonlake/include/fsp20 diff --git a/src/soc/intel/cannonlake/chip.h b/src/soc/intel/cannonlake/chip.h index bbc58808a3..67be85dd25 100644 --- a/src/soc/intel/cannonlake/chip.h +++ b/src/soc/intel/cannonlake/chip.h @@ -18,9 +18,12 @@ #ifndef _SOC_CHIP_H_ #define _SOC_CHIP_H_ +#include #include struct soc_intel_cannonlake_config { + /* GSPI */ + struct gspi_cfg gspi[CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX]; }; typedef struct soc_intel_cannonlake_config config_t; diff --git a/src/soc/intel/cannonlake/gspi.c b/src/soc/intel/cannonlake/gspi.c new file mode 100644 index 0000000000..a1ebfba162 --- /dev/null +++ b/src/soc/intel/cannonlake/gspi.c @@ -0,0 +1,71 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2017 Google Inc. + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 +#include +#include +#include +#include +#include "chip.h" + +const struct gspi_cfg *gspi_get_soc_cfg(void) +{ + DEVTREE_CONST struct soc_intel_cannonlake_config *config; + int devfn = SA_DEVFN_ROOT; + DEVTREE_CONST struct device *dev = dev_find_slot(0, devfn); + + if (!dev || !dev->chip_info) { + printk(BIOS_ERR, "%s: Could not find SoC devicetree config!\n", + __func__); + return NULL; + } + + config = dev->chip_info; + + return &config->gspi[0]; +} + +uintptr_t gspi_get_soc_early_base(void) +{ + return EARLY_GSPI_BASE_ADDRESS; +} + +/* + * SPI Bus 0 is Fast SPI and GSPI starts from SPI bus # 1 onwards. Thus, adjust + * the bus # accordingly when referring to SPI / GSPI bus numbers. + */ +#define GSPI_TO_SPI_BUS(x) ((x) + 1) +#define SPI_TO_GSPI_BUS(x) ((x) - 1) + +int gspi_soc_spi_to_gspi_bus(unsigned int spi_bus, unsigned int *gspi_bus) +{ + if (spi_bus == 0) + return -1; + + *gspi_bus = SPI_TO_GSPI_BUS(spi_bus); + if (*gspi_bus >= CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX) + return -1; + + return 0; +} + +int gspi_soc_bus_to_devfn(unsigned int gspi_bus) +{ + if (gspi_bus >= CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX) + return -1; + + return spi_bus_to_devfn(GSPI_TO_SPI_BUS(gspi_bus)); +} diff --git a/src/soc/intel/cannonlake/include/soc/pci_devs.h b/src/soc/intel/cannonlake/include/soc/pci_devs.h index f00ea1f6bc..ed6b67030b 100644 --- a/src/soc/intel/cannonlake/include/soc/pci_devs.h +++ b/src/soc/intel/cannonlake/include/soc/pci_devs.h @@ -173,6 +173,7 @@ static inline int spi_devfn_to_bus(unsigned int devfn) case PCH_DEVFN_SPI: return 0; case PCH_DEVFN_GSPI0: return 1; case PCH_DEVFN_GSPI1: return 2; + case PCH_DEVFN_GSPI2: return 3; } return -1; } @@ -183,6 +184,7 @@ static inline int spi_bus_to_devfn(unsigned int bus) case 0: return PCH_DEVFN_SPI; case 1: return PCH_DEVFN_GSPI0; case 2: return PCH_DEVFN_GSPI1; + case 3: return PCH_DEVFN_GSPI2; } return -1; } diff --git a/src/soc/intel/cannonlake/spi.c b/src/soc/intel/cannonlake/spi.c new file mode 100644 index 0000000000..1d65dee31a --- /dev/null +++ b/src/soc/intel/cannonlake/spi.c @@ -0,0 +1,71 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2017 Google Inc. + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = { + { .ctrlr = &fast_spi_flash_ctrlr, .bus_start = 0, .bus_end = 0 }, +#if !ENV_SMM + { .ctrlr = &gspi_ctrlr, .bus_start = 1, + .bus_end = 1 + (CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX - 1)}, +#endif +}; + +const size_t spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map); + +#if ENV_RAMSTAGE + +static int spi_dev_to_bus(struct device *dev) +{ + return spi_devfn_to_bus(dev->path.pci.devfn); +} + +static struct spi_bus_operations spi_bus_ops = { + .dev_to_bus = &spi_dev_to_bus, +}; + +static struct device_operations spi_dev_ops = { + .read_resources = &pci_dev_read_resources, + .set_resources = &pci_dev_set_resources, + .enable_resources = &pci_dev_enable_resources, + .scan_bus = &scan_generic_bus, + .ops_spi_bus = &spi_bus_ops, +}; + +static const unsigned short pci_device_ids[] = { + PCI_DEVICE_ID_INTEL_CNL_HWSEQ_SPI, + PCI_DEVICE_ID_INTEL_CNL_SPI0, + PCI_DEVICE_ID_INTEL_CNL_SPI1, + PCI_DEVICE_ID_INTEL_CNL_SPI2, + 0 +}; + +static const struct pci_driver pch_spi __pci_driver = { + .ops = &spi_dev_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; +#endif -- cgit v1.2.3