Add configure SPI CS setup/hold/idle delays in terms of clk count support, and use one period of current spi speed as default if setup/hold/idle not indicated. Signed-off-by: Luhua Xu <luhua.xu@xxxxxxxxxxxx> --- drivers/spi/spi-mt65xx.c | 41 +++++++++++++++++++++++++------- include/linux/platform_data/spi-mt65xx.h | 5 ++++ 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index f599cce..98df9d1 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -140,6 +140,9 @@ static const struct mtk_spi_compatible mt8183_compat = { */ static const struct mtk_chip_config mtk_default_chip_info = { .sample_sel = 0, + .setup_cnt = 0, + .hold_cnt = 0, + .idle_cnt = 0, }; static const struct of_device_id mtk_spi_of_match[] = { @@ -281,10 +284,13 @@ static void mtk_spi_set_cs(struct spi_device *spi, bool enable) } static void mtk_spi_prepare_transfer(struct spi_master *master, - struct spi_transfer *xfer) + struct spi_transfer *xfer, + struct spi_device *spi) { u32 spi_clk_hz, div, sck_time, cs_time, reg_val = 0; struct mtk_spi *mdata = spi_master_get_devdata(master); + struct mtk_chip_config *chip_config = spi->controller_data; + u32 cs_setup, cs_hold, cs_idle; spi_clk_hz = clk_get_rate(mdata->spi_clk); if (xfer->speed_hz < spi_clk_hz / 2) @@ -295,29 +301,46 @@ static void mtk_spi_prepare_transfer(struct spi_master *master, sck_time = (div + 1) / 2; cs_time = sck_time * 2; + if (chip_config->setup_cnt) + cs_setup = chip_config->setup_cnt; + else + cs_setup = cs_time; + + if (chip_config->hold_cnt) + cs_hold = chip_config->hold_cnt; + else + cs_hold = cs_time; + + if (chip_config->idle_cnt) + cs_idle = chip_config->idle_cnt; + else + cs_idle = cs_time; + if (mdata->dev_comp->enhance_timing) { - reg_val |= (((sck_time - 1) & 0xffff) + reg_val = (((sck_time - 1) & 0xffff) << SPI_CFG0_SCK_HIGH_OFFSET); reg_val |= (((sck_time - 1) & 0xffff) << SPI_ADJUST_CFG0_SCK_LOW_OFFSET); writel(reg_val, mdata->base + SPI_CFG2_REG); - reg_val |= (((cs_time - 1) & 0xffff) + + reg_val = (((cs_hold - 1) & 0xffff) << SPI_ADJUST_CFG0_CS_HOLD_OFFSET); - reg_val |= (((cs_time - 1) & 0xffff) + reg_val |= (((cs_setup - 1) & 0xffff) << SPI_ADJUST_CFG0_CS_SETUP_OFFSET); writel(reg_val, mdata->base + SPI_CFG0_REG); } else { reg_val |= (((sck_time - 1) & 0xff) << SPI_CFG0_SCK_HIGH_OFFSET); reg_val |= (((sck_time - 1) & 0xff) << SPI_CFG0_SCK_LOW_OFFSET); - reg_val |= (((cs_time - 1) & 0xff) << SPI_CFG0_CS_HOLD_OFFSET); - reg_val |= (((cs_time - 1) & 0xff) << SPI_CFG0_CS_SETUP_OFFSET); + reg_val |= (((cs_hold - 1) & 0xff) << SPI_CFG0_CS_HOLD_OFFSET); + reg_val |= (((cs_setup - 1) & 0xff) + << SPI_CFG0_CS_SETUP_OFFSET); writel(reg_val, mdata->base + SPI_CFG0_REG); } reg_val = readl(mdata->base + SPI_CFG1_REG); reg_val &= ~SPI_CFG1_CS_IDLE_MASK; - reg_val |= (((cs_time - 1) & 0xff) << SPI_CFG1_CS_IDLE_OFFSET); + reg_val |= (((cs_idle - 1) & 0xff) << SPI_CFG1_CS_IDLE_OFFSET); writel(reg_val, mdata->base + SPI_CFG1_REG); } @@ -426,7 +449,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master, mdata->cur_transfer = xfer; mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len); mdata->num_xfered = 0; - mtk_spi_prepare_transfer(master, xfer); + mtk_spi_prepare_transfer(master, xfer, spi); mtk_spi_setup_packet(master); cnt = xfer->len / 4; @@ -458,7 +481,7 @@ static int mtk_spi_dma_transfer(struct spi_master *master, mdata->cur_transfer = xfer; mdata->num_xfered = 0; - mtk_spi_prepare_transfer(master, xfer); + mtk_spi_prepare_transfer(master, xfer, spi); cmd = readl(mdata->base + SPI_CMD_REG); if (xfer->tx_buf) diff --git a/include/linux/platform_data/spi-mt65xx.h b/include/linux/platform_data/spi-mt65xx.h index 65fd5ffd2..80d280e 100644 --- a/include/linux/platform_data/spi-mt65xx.h +++ b/include/linux/platform_data/spi-mt65xx.h @@ -12,5 +12,10 @@ /* Board specific platform_data */ struct mtk_chip_config { u32 sample_sel; + + /* CS timing configuration in terms of clock count */ + u16 setup_cnt; + u16 hold_cnt; + u8 idle_cnt; }; #endif -- 2.6.4