summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/common/block/gspi/Kconfig8
-rw-r--r--src/soc/intel/common/block/gspi/gspi.c94
2 files changed, 85 insertions, 17 deletions
diff --git a/src/soc/intel/common/block/gspi/Kconfig b/src/soc/intel/common/block/gspi/Kconfig
index a5455a38db..8fa847a1b8 100644
--- a/src/soc/intel/common/block/gspi/Kconfig
+++ b/src/soc/intel/common/block/gspi/Kconfig
@@ -10,3 +10,11 @@ config SOC_INTEL_COMMON_BLOCK_GSPI_MAX
Maximum number of GSPI controllers supported by the PCH. SoC
must define this config if SOC_INTEL_COMMON_BLOCK_GSPI is
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.
diff --git a/src/soc/intel/common/block/gspi/gspi.c b/src/soc/intel/common/block/gspi/gspi.c
index 8e527ed0b1..2f574a4eb9 100644
--- a/src/soc/intel/common/block/gspi/gspi.c
+++ b/src/soc/intel/common/block/gspi/gspi.c
@@ -92,12 +92,15 @@
#define SSP_REG 0x220 /* SSP Reg */
#define DMA_FINISH_DISABLE (1 << 0)
#define SPI_CS_CONTROL 0x224 /* SPI CS Control */
-#define CS_POLARITY_LOW (0 << 12)
-#define CS_POLARITY_HIGH (1 << 12)
+#define CS_0_POL_SHIFT (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_STATE_LOW (0 << 1)
-#define CS_STATE_HIGH (1 << 1)
-#define CS_STATE_MASK (1 << 1)
+#define CS_STATE_SHIFT (1)
+#define CS_STATE_MASK (1 << CS_STATE_SHIFT)
+#define CS_V1_STATE_LOW (0)
+#define CS_V1_STATE_HIGH (1)
#define CS_MODE_HW (0 << 0)
#define CS_MODE_SW (1 << 0)
@@ -265,20 +268,78 @@ enum cs_assert {
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,
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 &= ~CS_STATE_MASK;
- if (cs_ctrl & CS_POLARITY_HIGH)
- state = (cs_assert == CS_ASSERT) ? CS_STATE_HIGH : CS_STATE_LOW;
- else
- state = (cs_assert == CS_ASSERT) ? CS_STATE_LOW : CS_STATE_HIGH;
-
- cs_ctrl |= state;
+ pol = !!(cs_ctrl & CS_0_POL_MASK);
+ cs_ctrl |= gspi_csctrl_state(pol, cs_assert) << CS_STATE_SHIFT;
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)
{
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;
/* Only chip select 0 is supported. */
@@ -364,10 +425,9 @@ static int gspi_ctrlr_setup(const struct spi_slave *dev)
* - Do not assert CS.
*/
cs_ctrl = CS_MODE_SW | CS_0;
- if (cfg.cs_polarity == SPI_POLARITY_LOW)
- cs_ctrl |= CS_POLARITY_LOW | CS_STATE_HIGH;
- else
- cs_ctrl |= CS_POLARITY_HIGH | CS_STATE_LOW;
+ pol = gspi_csctrl_polarity(cfg.cs_polarity);
+ cs_ctrl |= pol << CS_0_POL_SHIFT;
+ cs_ctrl |= gspi_csctrl_state(pol, CS_DEASSERT);
gspi_write_mmio_reg(p, SPI_CS_CONTROL, cs_ctrl);
/* Disable SPI controller. */