From 05a6f29d32c246569b7a0561d35ccbf49eec1fb8 Mon Sep 17 00:00:00 2001 From: Furquan Shaikh Date: Fri, 31 Mar 2017 14:02:47 -0700 Subject: [PATCH] soc/intel/skylake: Add support for GSPI controller Sky Lake PCH contains two GSPI controllers. Using the common GSPI controller driver implementation for Intel PCH, add support for GSPI controller buses on Sky Lake/Kaby Lake. BUG=b:35583330 Change-Id: I29b1d4d5a6ee4093f2596065ac375c06f17d33ac Signed-off-by: Furquan Shaikh Reviewed-on: https://review.coreboot.org/19099 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin --- src/soc/intel/skylake/Kconfig | 5 ++ src/soc/intel/skylake/Makefile.inc | 4 ++ src/soc/intel/skylake/bootblock/bootblock.c | 2 + src/soc/intel/skylake/chip.h | 4 ++ src/soc/intel/skylake/gspi.c | 70 ++++++++++++++++++++ src/soc/intel/skylake/include/soc/iomap.h | 1 + src/soc/intel/skylake/include/soc/pci_devs.h | 10 +++ src/soc/intel/skylake/spi.c | 28 ++------ 8 files changed, 101 insertions(+), 23 deletions(-) create mode 100644 src/soc/intel/skylake/gspi.c diff --git a/src/soc/intel/skylake/Kconfig b/src/soc/intel/skylake/Kconfig index df8ae2bd2d..82e5d55555 100644 --- a/src/soc/intel/skylake/Kconfig +++ b/src/soc/intel/skylake/Kconfig @@ -50,6 +50,7 @@ config CPU_SPECIFIC_OPTIONS select SOC_INTEL_COMMON select SOC_INTEL_COMMON_ACPI_WAKE_SOURCE select SOC_INTEL_COMMON_BLOCK + select SOC_INTEL_COMMON_BLOCK_GSPI select SOC_INTEL_COMMON_BLOCK_SA select SOC_INTEL_COMMON_BLOCK_XHCI select SOC_INTEL_COMMON_LPSS_I2C @@ -300,4 +301,8 @@ config SOC_INTEL_COMMON_LPSS_CLOCK_MHZ int default 120 +config SOC_INTEL_COMMON_BLOCK_GSPI_MAX + int + default 2 + endif diff --git a/src/soc/intel/skylake/Makefile.inc b/src/soc/intel/skylake/Makefile.inc index f9c267e435..cb8eb89514 100644 --- a/src/soc/intel/skylake/Makefile.inc +++ b/src/soc/intel/skylake/Makefile.inc @@ -19,6 +19,7 @@ bootblock-y += flash_controller.c bootblock-$(CONFIG_UART_DEBUG) += bootblock/uart.c bootblock-$(CONFIG_UART_DEBUG) += uart_debug.c bootblock-y += gpio.c +bootblock-y += gspi.c bootblock-y += monotonic_timer.c bootblock-y += pch.c bootblock-y += pcr.c @@ -27,6 +28,7 @@ bootblock-y += spi.c bootblock-y += tsc_freq.c verstage-y += flash_controller.c +verstage-y += gspi.c verstage-y += monotonic_timer.c verstage-y += pch.c verstage-$(CONFIG_UART_DEBUG) += uart_debug.c @@ -37,6 +39,7 @@ verstage-y += tsc_freq.c romstage-y += flash_controller.c romstage-y += gpio.c +romstage-y += gspi.c romstage-y += bootblock/i2c.c romstage-y += memmap.c romstage-y += monotonic_timer.c @@ -62,6 +65,7 @@ ramstage-y += elog.c ramstage-y += finalize.c ramstage-y += flash_controller.c ramstage-y += gpio.c +ramstage-y += gspi.c ramstage-y += i2c.c ramstage-y += igd.c ramstage-y += irq.c diff --git a/src/soc/intel/skylake/bootblock/bootblock.c b/src/soc/intel/skylake/bootblock/bootblock.c index c11d3d2152..f386f96360 100644 --- a/src/soc/intel/skylake/bootblock/bootblock.c +++ b/src/soc/intel/skylake/bootblock/bootblock.c @@ -14,6 +14,7 @@ */ #include +#include #include asmlinkage void bootblock_c_entry(uint64_t base_timestamp) @@ -48,4 +49,5 @@ void bootblock_soc_init(void) set_max_freq(); pch_early_init(); i2c_early_init(); + gspi_early_bar_init(); } diff --git a/src/soc/intel/skylake/chip.h b/src/soc/intel/skylake/chip.h index 85857d8200..ce5fe22b98 100644 --- a/src/soc/intel/skylake/chip.h +++ b/src/soc/intel/skylake/chip.h @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -208,6 +209,9 @@ struct soc_intel_skylake_config { enum skylake_i2c_voltage i2c_voltage[SKYLAKE_I2C_DEV_MAX]; struct lpss_i2c_bus_config i2c[SKYLAKE_I2C_DEV_MAX]; + /* GSPI */ + struct gspi_cfg gspi[CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX]; + /* Camera */ u8 Cio2Enable; u8 SaImguEnable; diff --git a/src/soc/intel/skylake/gspi.c b/src/soc/intel/skylake/gspi.c new file mode 100644 index 0000000000..e04ae93b52 --- /dev/null +++ b/src/soc/intel/skylake/gspi.c @@ -0,0 +1,70 @@ +/* + * 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 "chip.h" + +const struct gspi_cfg *gspi_get_soc_cfg(void) +{ + ROMSTAGE_CONST struct soc_intel_skylake_config *config; + int devfn = SA_DEVFN_ROOT; + ROMSTAGE_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/skylake/include/soc/iomap.h b/src/soc/intel/skylake/include/soc/iomap.h index a6f7287f3a..e2662cc7c0 100644 --- a/src/soc/intel/skylake/include/soc/iomap.h +++ b/src/soc/intel/skylake/include/soc/iomap.h @@ -53,6 +53,7 @@ #define PCH_PWRM_BASE_SIZE 0x10000 #define SPI_BASE_ADDRESS 0xfe010000 +#define EARLY_GSPI_BASE_ADDRESS 0xfe011000 #define GPIO_BASE_SIZE 0x10000 diff --git a/src/soc/intel/skylake/include/soc/pci_devs.h b/src/soc/intel/skylake/include/soc/pci_devs.h index 469d7e9992..13114f1f95 100644 --- a/src/soc/intel/skylake/include/soc/pci_devs.h +++ b/src/soc/intel/skylake/include/soc/pci_devs.h @@ -186,4 +186,14 @@ static inline int spi_devfn_to_bus(unsigned int devfn) return -1; } +static inline int spi_bus_to_devfn(unsigned int bus) +{ + switch (bus) { + case 0: return PCH_DEVFN_SPI; + case 1: return PCH_DEVFN_GSPI0; + case 2: return PCH_DEVFN_GSPI1; + } + return -1; +} + #endif diff --git a/src/soc/intel/skylake/spi.c b/src/soc/intel/skylake/spi.c index 4a2ae9d8b8..e11e13f763 100644 --- a/src/soc/intel/skylake/spi.c +++ b/src/soc/intel/skylake/spi.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -39,31 +40,12 @@ static const struct spi_ctrlr flash_spi_ctrlr = { .setup = flash_spi_ctrlr_setup, }; -static int gspi_ctrlr_get_config(const struct spi_slave *dev, - struct spi_cfg *cfg) -{ - if (dev->cs != 0) { - printk(BIOS_ERR, "%s: Unsupported device " - "bus=0x%x,cs=0x%x!\n", __func__, dev->bus, dev->cs); - return -1; - } - - cfg->clk_phase = SPI_CLOCK_PHASE_FIRST; - cfg->clk_polarity = SPI_POLARITY_LOW; - cfg->cs_polarity = SPI_POLARITY_LOW; - cfg->wire_mode = SPI_4_WIRE_MODE; - cfg->data_bit_length = 8; - - return 0; -} - -static const struct spi_ctrlr gspi_ctrlr = { - .get_config = gspi_ctrlr_get_config, -}; - const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = { { .ctrlr = &flash_spi_ctrlr, .bus_start = 0, .bus_end = 0 }, - { .ctrlr = &gspi_ctrlr, .bus_start = 1, .bus_end = 2 }, +#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);