[PATCH] spi: rockchip: Keep master alive when CS asserted

From: Jeffy Chen
Date: Sun Jun 25 2017 - 23:16:04 EST


The cros_ec requires CS line to be active after last message. But the CS
would be toggled when powering off/on rockchip spi, which breaks ec xfer.

Keep spi alive after CS asserted to prevent that.

Suggested-by: Doug Anderson <dianders@xxxxxxxxxxxx>
Signed-off-by: Jeffy Chen <jeffy.chen@xxxxxxxxxxxxxx>

---

drivers/spi/spi-rockchip.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index acf31f3..df016a1 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -264,7 +264,7 @@ static inline u32 rx_max(struct rockchip_spi *rs)

static void rockchip_spi_set_cs(struct spi_device *spi, bool enable)
{
- u32 ser;
+ u32 ser, new_ser;
struct spi_master *master = spi->master;
struct rockchip_spi *rs = spi_master_get_devdata(master);

@@ -288,13 +288,25 @@ static void rockchip_spi_set_cs(struct spi_device *spi, bool enable)
* Note: enable(rockchip_spi_set_cs) = !enable(spi_set_cs)
*/
if (!enable)
- ser |= 1 << spi->chip_select;
+ new_ser = ser | BIT(spi->chip_select);
else
- ser &= ~(1 << spi->chip_select);
+ new_ser = ser & ~BIT(spi->chip_select);

- writel_relaxed(ser, rs->regs + ROCKCHIP_SPI_SER);
+ if (new_ser == ser)
+ goto out;

- pm_runtime_put_sync(rs->dev);
+ writel_relaxed(new_ser, rs->regs + ROCKCHIP_SPI_SER);
+
+ /*
+ * The rockchip spi would stop driving CS when power down.
+ * So we need to keep it alive after CS asserted
+ */
+ if (!enable)
+ return;
+ pm_runtime_put(rs->dev);
+
+out:
+ pm_runtime_put(rs->dev);
}

static int rockchip_spi_prepare_message(struct spi_master *master,
--
2.1.4