[2/2] spi: mediatek: add cs timing configuration support
diff mbox series

Message ID 1574053037-26721-3-git-send-email-luhua.xu@mediatek.com
State New
Headers show
Series
  • spi CS customization support
Related show

Commit Message

luhua xu Nov. 18, 2019, 4:57 a.m. UTC
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@mediatek.com>
---
 drivers/spi/spi-mt65xx.c                 | 41 +++++++++++++++++++++++++-------
 include/linux/platform_data/spi-mt65xx.h |  5 ++++
 2 files changed, 37 insertions(+), 9 deletions(-)

Comments

Mark Brown Nov. 19, 2019, 6:19 p.m. UTC | #1
On Mon, Nov 18, 2019 at 12:57:17PM +0800, Luhua Xu wrote:
> 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.

We have added a generic way to specify delays like this via the
set_cs_timing() operation and related fields in the spi_device struct
which operate in terms of spi_delay - Alexandru Ardelean added them
recently.  This supports both times and clock cycles as units so should
fit with what your hardware can do, the interface is new though so there
may be soem rough edges to worry about.
luhua xu Nov. 20, 2019, 9:31 a.m. UTC | #2
On Tue, 2019-11-19 at 18:19 +0000, Mark Brown wrote:
> On Mon, Nov 18, 2019 at 12:57:17PM +0800, Luhua Xu wrote:
> > 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.
> 
> We have added a generic way to specify delays like this via the
> set_cs_timing() operation and related fields in the spi_device struct
> which operate in terms of spi_delay - Alexandru Ardelean added them
> recently.  This supports both times and clock cycles as units so should
> fit with what your hardware can do, the interface is new though so there
> may be soem rough edges to worry about.

I find the patch today. It's really a better idear.

Patch
diff mbox series

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