soc/intel/common/block/gspi: Add SOC_INTEL_COMMON_BLOCK_GSPI_VERSION_2

Even though kaby lake and cannon lake are using the same GSPI
controller, bit meanings (for polarity and state) in SPI_CS_CONTROL
register are significantly different. This change provides a new
Kconfig option that can be selected by SoCs using these new bit
definitions of SPI_CS_CONTROL. Common code takes care of setting the
right value for polarity and state field depending upon the version
selected by SoC.

BUG=b:70628116

Change-Id: Ic69321483a58bb29f939b0d8b37f33ca30eb53b8
Signed-off-by: Furquan Shaikh <furquan@google.com>
Reviewed-on: https://review.coreboot.org/22954
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Shelley Chen <shchen@google.com>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
This commit is contained in:
Furquan Shaikh 2017-12-20 11:06:19 -08:00
parent 261b893b7c
commit 58a8c779b3
2 changed files with 85 additions and 17 deletions

View File

@ -10,3 +10,11 @@ config SOC_INTEL_COMMON_BLOCK_GSPI_MAX
Maximum number of GSPI controllers supported by the PCH. SoC Maximum number of GSPI controllers supported by the PCH. SoC
must define this config if SOC_INTEL_COMMON_BLOCK_GSPI is must define this config if SOC_INTEL_COMMON_BLOCK_GSPI is
selected. selected.
config SOC_INTEL_COMMON_BLOCK_GSPI_VERSION_2
bool
default n
select SOC_INTEL_COMMON_BLOCK_GSPI
help
Intel Processor Common GSPI support with quirks to handle
SPI_CS_CONTROL changes introduced in CNL.

View File

@ -92,12 +92,15 @@
#define SSP_REG 0x220 /* SSP Reg */ #define SSP_REG 0x220 /* SSP Reg */
#define DMA_FINISH_DISABLE (1 << 0) #define DMA_FINISH_DISABLE (1 << 0)
#define SPI_CS_CONTROL 0x224 /* SPI CS Control */ #define SPI_CS_CONTROL 0x224 /* SPI CS Control */
#define CS_POLARITY_LOW (0 << 12) #define CS_0_POL_SHIFT (12)
#define CS_POLARITY_HIGH (1 << 12) #define CS_0_POL_MASK (1 << CS_0_POL_SHIFT)
#define CS_POL_LOW (0)
#define CS_POL_HIGH (1)
#define CS_0 (0 << 8) #define CS_0 (0 << 8)
#define CS_STATE_LOW (0 << 1) #define CS_STATE_SHIFT (1)
#define CS_STATE_HIGH (1 << 1) #define CS_STATE_MASK (1 << CS_STATE_SHIFT)
#define CS_STATE_MASK (1 << 1) #define CS_V1_STATE_LOW (0)
#define CS_V1_STATE_HIGH (1)
#define CS_MODE_HW (0 << 0) #define CS_MODE_HW (0 << 0)
#define CS_MODE_SW (1 << 0) #define CS_MODE_SW (1 << 0)
@ -265,20 +268,78 @@ enum cs_assert {
CS_DEASSERT, CS_DEASSERT,
}; };
/*
* SPI_CS_CONTROL bit definitions based on GSPI_VERSION_x:
*
* VERSION_2 (CNL GSPI controller):
* Polarity: Indicates inactive polarity of chip-select
* State : Indicates assert/de-assert of chip-select
*
* Default (SKL/KBL GSPI controller):
* Polarity: Indicates active polarity of chip-select
* State : Indicates low/high output state of chip-select
*/
static uint32_t gspi_csctrl_state_v2(uint32_t pol, enum cs_assert cs_assert)
{
return cs_assert;
}
static uint32_t gspi_csctrl_state_v1(uint32_t pol, enum cs_assert cs_assert)
{
uint32_t state;
if (pol == CS_POL_HIGH)
state = (cs_assert == CS_ASSERT) ? CS_V1_STATE_HIGH :
CS_V1_STATE_LOW;
else
state = (cs_assert == CS_ASSERT) ? CS_V1_STATE_LOW :
CS_V1_STATE_HIGH;
return state;
}
static uint32_t gspi_csctrl_state(uint32_t pol, enum cs_assert cs_assert)
{
if (IS_ENABLED(CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_VERSION_2))
return gspi_csctrl_state_v2(pol, cs_assert);
return gspi_csctrl_state_v1(pol, cs_assert);
}
static uint32_t gspi_csctrl_polarity_v2(enum spi_polarity active_pol)
{
/* Polarity field indicates cs inactive polarity */
if (active_pol == SPI_POLARITY_LOW)
return CS_POL_HIGH;
return CS_POL_LOW;
}
static uint32_t gspi_csctrl_polarity_v1(enum spi_polarity active_pol)
{
/* Polarity field indicates cs active polarity */
if (active_pol == SPI_POLARITY_LOW)
return CS_POL_LOW;
return CS_POL_HIGH;
}
static uint32_t gspi_csctrl_polarity(enum spi_polarity active_pol)
{
if (IS_ENABLED(CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_VERSION_2))
return gspi_csctrl_polarity_v2(active_pol);
return gspi_csctrl_polarity_v1(active_pol);
}
static void __gspi_cs_change(const struct gspi_ctrlr_params *p, static void __gspi_cs_change(const struct gspi_ctrlr_params *p,
enum cs_assert cs_assert) enum cs_assert cs_assert)
{ {
uint32_t cs_ctrl, state; uint32_t cs_ctrl, pol;
cs_ctrl = gspi_read_mmio_reg(p, SPI_CS_CONTROL); cs_ctrl = gspi_read_mmio_reg(p, SPI_CS_CONTROL);
cs_ctrl &= ~CS_STATE_MASK; cs_ctrl &= ~CS_STATE_MASK;
if (cs_ctrl & CS_POLARITY_HIGH) pol = !!(cs_ctrl & CS_0_POL_MASK);
state = (cs_assert == CS_ASSERT) ? CS_STATE_HIGH : CS_STATE_LOW; cs_ctrl |= gspi_csctrl_state(pol, cs_assert) << CS_STATE_SHIFT;
else
state = (cs_assert == CS_ASSERT) ? CS_STATE_LOW : CS_STATE_HIGH;
cs_ctrl |= state;
gspi_write_mmio_reg(p, SPI_CS_CONTROL, cs_ctrl); gspi_write_mmio_reg(p, SPI_CS_CONTROL, cs_ctrl);
} }
@ -330,7 +391,7 @@ static uint32_t gspi_get_clk_div(unsigned int gspi_bus)
static int gspi_ctrlr_setup(const struct spi_slave *dev) static int gspi_ctrlr_setup(const struct spi_slave *dev)
{ {
struct spi_cfg cfg; struct spi_cfg cfg;
uint32_t cs_ctrl, sscr0, sscr1, clocks, sitf, sirf; uint32_t cs_ctrl, sscr0, sscr1, clocks, sitf, sirf, pol;
struct gspi_ctrlr_params params, *p = &params; struct gspi_ctrlr_params params, *p = &params;
/* Only chip select 0 is supported. */ /* Only chip select 0 is supported. */
@ -364,10 +425,9 @@ static int gspi_ctrlr_setup(const struct spi_slave *dev)
* - Do not assert CS. * - Do not assert CS.
*/ */
cs_ctrl = CS_MODE_SW | CS_0; cs_ctrl = CS_MODE_SW | CS_0;
if (cfg.cs_polarity == SPI_POLARITY_LOW) pol = gspi_csctrl_polarity(cfg.cs_polarity);
cs_ctrl |= CS_POLARITY_LOW | CS_STATE_HIGH; cs_ctrl |= pol << CS_0_POL_SHIFT;
else cs_ctrl |= gspi_csctrl_state(pol, CS_DEASSERT);
cs_ctrl |= CS_POLARITY_HIGH | CS_STATE_LOW;
gspi_write_mmio_reg(p, SPI_CS_CONTROL, cs_ctrl); gspi_write_mmio_reg(p, SPI_CS_CONTROL, cs_ctrl);
/* Disable SPI controller. */ /* Disable SPI controller. */