From e3e12f52b214121840b44c91de5b3e5af5d3eb84 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 06 Nov 2023 03:04:41 +0000
Subject: [PATCH] rk3568 rt init

---
 kernel/drivers/spi/spi-rockchip.c |  386 +++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 260 insertions(+), 126 deletions(-)

diff --git a/kernel/drivers/spi/spi-rockchip.c b/kernel/drivers/spi/spi-rockchip.c
index 8604291..e55c5c6 100644
--- a/kernel/drivers/spi/spi-rockchip.c
+++ b/kernel/drivers/spi/spi-rockchip.c
@@ -14,6 +14,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/dmaengine.h>
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
@@ -181,6 +182,12 @@
 
 #define ROCKCHIP_SPI_REGISTER_SIZE		0x1000
 
+enum rockchip_spi_xfer_mode {
+	ROCKCHIP_SPI_DMA,
+	ROCKCHIP_SPI_IRQ,
+	ROCKCHIP_SPI_POLL,
+};
+
 struct rockchip_spi_quirks {
 	u32 max_baud_div_in_cpha;
 };
@@ -201,7 +208,9 @@
 	unsigned int rx_left;
 
 	atomic_t state;
+	struct completion xfer_done;
 
+	u32 version;
 	/*depth of the FIFO buffer */
 	u32 fifo_len;
 	/* frequency of spiclk */
@@ -211,11 +220,13 @@
 
 	u8 n_bytes;
 	u8 rsd;
+	u8 csm;
+	bool poll; /* only support transfer data by cpu polling */
 
 	bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM];
 
 	struct pinctrl_state *high_speed_state;
-	bool slave_abort;
+	bool slave_aborted;
 	bool gpio_requested;
 	bool cs_inactive; /* spi slave tansmition stop when cs inactive */
 	struct spi_transfer *xfer; /* Store xfer temporarily */
@@ -231,17 +242,29 @@
 	writel_relaxed((enable ? 1U : 0U), rs->regs + ROCKCHIP_SPI_SSIENR);
 }
 
-static inline void wait_for_idle(struct rockchip_spi *rs, bool slave_mode)
+static inline void wait_for_tx_idle(struct rockchip_spi *rs, bool slave_mode)
 {
 	unsigned long timeout = jiffies + msecs_to_jiffies(5);
+	u32 bit_filed = SR_BUSY;
+	u32 idle_val = 0;
+	uint32_t speed, us;
+
+	if (slave_mode && rs->version == ROCKCHIP_SPI_VER2_TYPE2) {
+		bit_filed = SR_SLAVE_TX_BUSY;
+		idle_val = 0;
+	} else if (slave_mode) {
+		bit_filed = SR_TF_EMPTY;
+		idle_val = 1;
+	}
 
 	do {
-		if (slave_mode) {
-			if (!(readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_SLAVE_TX_BUSY))
-				return;
-		} else {
-			if (!(readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_BUSY))
-				return;
+		if ((readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & bit_filed) == idle_val) {
+			if (bit_filed == SR_TF_EMPTY) {
+				speed = rs->speed_hz;
+				us = (8 * 1000000 / speed) * 2;
+				udelay(us);
+			}
+			return;
 		}
 	} while (!time_after(jiffies, timeout));
 
@@ -250,11 +273,7 @@
 
 static u32 get_fifo_len(struct rockchip_spi *rs)
 {
-	u32 ver;
-
-	ver = readl_relaxed(rs->regs + ROCKCHIP_SPI_VERSION);
-
-	switch (ver) {
+	switch (rs->version) {
 	case ROCKCHIP_SPI_VER2_TYPE1:
 	case ROCKCHIP_SPI_VER2_TYPE2:
 		return 64;
@@ -299,6 +318,11 @@
 {
 	struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
 
+	dev_err(rs->dev, "state=%x\n", atomic_read(&rs->state));
+	dev_err(rs->dev, "tx_left=%x\n", rs->tx_left);
+	dev_err(rs->dev, "rx_left=%x\n", rs->rx_left);
+	print_hex_dump(KERN_ERR, "regs ", DUMP_PREFIX_OFFSET, 4, 4, rs->regs, 0x4c, 0);
+
 	/* stop running spi transfer
 	 * this also flushes both rx and tx fifos
 	 */
@@ -313,6 +337,7 @@
 
 	if (atomic_read(&rs->state) & RXDMA)
 		dmaengine_terminate_async(ctlr->dma_rx);
+	atomic_set(&rs->state, 0);
 }
 
 static void rockchip_spi_pio_writer(struct rockchip_spi *rs)
@@ -374,7 +399,7 @@
 	struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
 
 	/* When int_cs_inactive comes, spi slave abort */
-	if (readl_relaxed(rs->regs + ROCKCHIP_SPI_IMR) & INT_CS_INACTIVE) {
+	if (rs->cs_inactive && readl_relaxed(rs->regs + ROCKCHIP_SPI_ISR) & INT_CS_INACTIVE) {
 		ctlr->slave_abort(ctlr);
 		writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR);
 		writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR);
@@ -390,7 +415,7 @@
 		spi_enable_chip(rs, false);
 		writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR);
 		writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR);
-		spi_finalize_current_transfer(ctlr);
+		complete(&rs->xfer_done);
 	}
 
 	return IRQ_HANDLED;
@@ -400,8 +425,6 @@
 				    struct spi_controller *ctlr,
 				    struct spi_transfer *xfer)
 {
-	rs->tx = xfer->tx_buf;
-	rs->rx = xfer->rx_buf;
 	rs->tx_left = rs->tx ? xfer->len / rs->n_bytes : 0;
 	rs->rx_left = xfer->len / rs->n_bytes;
 
@@ -427,14 +450,16 @@
 	struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
 	int state = atomic_fetch_andnot(RXDMA, &rs->state);
 
-	if (state & TXDMA && !rs->slave_abort)
+	if (state & TXDMA && !rs->slave_aborted)
 		return;
 
 	if (rs->cs_inactive)
 		writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR);
 
 	spi_enable_chip(rs, false);
-	spi_finalize_current_transfer(ctlr);
+	writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR);
+	writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR);
+	complete(&rs->xfer_done);
 }
 
 static void rockchip_spi_dma_txcb(void *data)
@@ -443,14 +468,16 @@
 	struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
 	int state = atomic_fetch_andnot(TXDMA, &rs->state);
 
-	if (state & RXDMA && !rs->slave_abort)
+	if (state & RXDMA && !rs->slave_aborted)
 		return;
 
 	/* Wait until the FIFO data completely. */
-	wait_for_idle(rs, ctlr->slave);
+	wait_for_tx_idle(rs, ctlr->slave);
 
 	spi_enable_chip(rs, false);
-	spi_finalize_current_transfer(ctlr);
+	writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR);
+	writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR);
+	complete(&rs->xfer_done);
 }
 
 static u32 rockchip_spi_calc_burst_size(u32 data_len)
@@ -472,9 +499,6 @@
 	struct dma_async_tx_descriptor *rxdesc, *txdesc;
 
 	atomic_set(&rs->state, 0);
-
-	rs->tx = xfer->tx_buf;
-	rs->rx = xfer->rx_buf;
 
 	rxdesc = NULL;
 	if (xfer->rx_buf) {
@@ -545,9 +569,59 @@
 	return 1;
 }
 
-static void rockchip_spi_config(struct rockchip_spi *rs,
+static int rockchip_spi_pio_transfer(struct rockchip_spi *rs,
+		struct spi_controller *ctlr, struct spi_transfer *xfer)
+{
+	unsigned long time, timeout;
+	u32 speed_hz = xfer->speed_hz;
+	unsigned long long ms;
+	int ret = 0;
+
+	if (!speed_hz)
+		speed_hz = 100000;
+
+	ms = 8LL * 1000LL * xfer->len;
+	do_div(ms, speed_hz);
+	ms += ms + 200; /* some tolerance */
+
+	if (ms > UINT_MAX || ctlr->slave)
+		ms = UINT_MAX;
+
+	timeout = jiffies + msecs_to_jiffies(ms);
+	time = jiffies;
+	rs->tx_left = rs->tx ? xfer->len / rs->n_bytes : 0;
+	rs->rx_left = rs->rx ? xfer->len / rs->n_bytes : 0;
+
+	spi_enable_chip(rs, true);
+
+	while (rs->tx_left || rs->rx_left) {
+		if (rs->tx)
+			rockchip_spi_pio_writer(rs);
+
+		if (rs->rx)
+			rockchip_spi_pio_reader(rs);
+
+		cpu_relax();
+
+		if (time_after(time, timeout)) {
+			ret = -EIO;
+			goto out;
+		}
+	};
+
+	/* If tx, wait until the FIFO data completely. */
+	if (rs->tx)
+		wait_for_tx_idle(rs, ctlr->slave);
+
+out:
+	spi_enable_chip(rs, false);
+
+	return ret;
+}
+
+static int rockchip_spi_config(struct rockchip_spi *rs,
 		struct spi_device *spi, struct spi_transfer *xfer,
-		bool use_dma, bool slave_mode)
+		enum rockchip_spi_xfer_mode xfer_mode, bool slave_mode)
 {
 	u32 cr0 = CR0_FRF_SPI  << CR0_FRF_OFFSET
 		| CR0_BHT_8BIT << CR0_BHT_OFFSET
@@ -558,21 +632,33 @@
 
 	if (slave_mode)
 		cr0 |= CR0_OPM_SLAVE << CR0_OPM_OFFSET;
-	rs->slave_abort = false;
+	rs->slave_aborted = false;
 
 	cr0 |= rs->rsd << CR0_RSD_OFFSET;
+	cr0 |= rs->csm << CR0_CSM_OFFSET;
 	cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET;
 	if (spi->mode & SPI_LSB_FIRST)
 		cr0 |= CR0_FBM_LSB << CR0_FBM_OFFSET;
 	if (spi->mode & SPI_CS_HIGH)
 		cr0 |= BIT(spi->chip_select) << CR0_SOI_OFFSET;
 
-	if (xfer->rx_buf && xfer->tx_buf)
+	if (xfer->rx_buf && xfer->tx_buf) {
 		cr0 |= CR0_XFM_TR << CR0_XFM_OFFSET;
-	else if (xfer->rx_buf)
+	} else if (xfer->rx_buf) {
 		cr0 |= CR0_XFM_RO << CR0_XFM_OFFSET;
-	else if (use_dma)
-		cr0 |= CR0_XFM_TO << CR0_XFM_OFFSET;
+	} else if (xfer->tx_buf) {
+		/*
+		 * Use the water line of rx fifo in full duplex mode to trigger
+		 * the interruption of tx irq transmission completion.
+		 */
+		if (xfer_mode == ROCKCHIP_SPI_IRQ)
+			cr0 |= CR0_XFM_TR << CR0_XFM_OFFSET;
+		else
+			cr0 |= CR0_XFM_TO << CR0_XFM_OFFSET;
+	} else {
+		dev_err(rs->dev, "no transmission buffer\n");
+		return -EINVAL;
+	}
 
 	switch (xfer->bits_per_word) {
 	case 4:
@@ -595,7 +681,7 @@
 		unreachable();
 	}
 
-	if (use_dma) {
+	if (xfer_mode == ROCKCHIP_SPI_DMA) {
 		if (xfer->tx_buf)
 			dmacr |= TF_DMA_EN;
 		if (xfer->rx_buf)
@@ -652,6 +738,8 @@
 	writel_relaxed(2 * DIV_ROUND_UP(rs->freq, 2 * xfer->speed_hz),
 			rs->regs + ROCKCHIP_SPI_BAUDR);
 	rs->speed_hz = xfer->speed_hz;
+
+	return 0;
 }
 
 static size_t rockchip_spi_max_transfer_size(struct spi_device *spi)
@@ -663,50 +751,54 @@
 {
 	struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
 	u32 rx_fifo_left;
-	struct dma_tx_state state;
-	enum dma_status status;
 
-	/* Get current dma rx point */
-	if (atomic_read(&rs->state) & RXDMA) {
-		dmaengine_pause(ctlr->dma_rx);
-		status = dmaengine_tx_status(ctlr->dma_rx, ctlr->dma_rx->cookie, &state);
-		if (status == DMA_ERROR) {
-			rs->rx = rs->xfer->rx_buf;
-			rs->xfer->len = 0;
-			rx_fifo_left = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR);
-			for (; rx_fifo_left; rx_fifo_left--)
-				readl_relaxed(rs->regs + ROCKCHIP_SPI_RXDR);
-			goto out;
-		} else {
-			rs->rx += rs->xfer->len - rs->n_bytes * state.residue;
-		}
-	}
+	/* Flush rx fifo */
+	rx_fifo_left = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR);
+	for (; rx_fifo_left; rx_fifo_left--)
+		readl_relaxed(rs->regs + ROCKCHIP_SPI_RXDR);
 
-	/* Get the valid data left in rx fifo and set rs->xfer->len real rx size */
-	if (rs->rx) {
-		rx_fifo_left = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR);
-		for (; rx_fifo_left; rx_fifo_left--) {
-			u32 rxw = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXDR);
+	rs->slave_aborted = true;
+	complete(&rs->xfer_done);
 
-			if (rs->n_bytes == 1)
-				*(u8 *)rs->rx = (u8)rxw;
-			else
-				*(u16 *)rs->rx = (u16)rxw;
-			rs->rx += rs->n_bytes;
+	return 0;
+}
+
+static int rockchip_spi_transfer_wait(struct spi_controller *ctlr,
+				      struct spi_transfer *xfer)
+{
+	struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
+	u32 speed_hz = xfer->speed_hz;
+	unsigned long long ms;
+
+	if (spi_controller_is_slave(ctlr)) {
+		if (wait_for_completion_interruptible(&rs->xfer_done)) {
+			dev_dbg(rs->dev, "RK SPI transfer interrupted\n");
+			return -EINTR;
 		}
 
-		rs->xfer->len = (unsigned int)(rs->rx - rs->xfer->rx_buf);
-	}
+		if (rs->slave_aborted) {
+			dev_err(rs->dev, "RK SPI transfer slave abort\n");
+			return -EIO;
+		}
+	} else {
+		if (!speed_hz)
+			speed_hz = 100000;
 
-out:
-	if (atomic_read(&rs->state) & RXDMA)
-		dmaengine_terminate_sync(ctlr->dma_rx);
-	if (atomic_read(&rs->state) & TXDMA)
-		dmaengine_terminate_sync(ctlr->dma_tx);
-	atomic_set(&rs->state, 0);
-	spi_enable_chip(rs, false);
-	rs->slave_abort = true;
-	complete(&ctlr->xfer_completion);
+		ms = 8LL * 1000LL * xfer->len;
+		do_div(ms, speed_hz);
+		ms += ms + 200; /* some tolerance */
+
+		if (ms > UINT_MAX)
+			ms = UINT_MAX;
+
+		ms = wait_for_completion_timeout(&rs->xfer_done,
+						 msecs_to_jiffies(ms));
+
+		if (ms == 0) {
+			dev_err(rs->dev, "RK SPI transfer timed out\n");
+			return -ETIMEDOUT;
+		}
+	}
 
 	return 0;
 }
@@ -717,11 +809,13 @@
 		struct spi_transfer *xfer)
 {
 	struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
+	int ret;
 	bool use_dma;
+	enum rockchip_spi_xfer_mode xfer_mode;
 
 	/* Zero length transfers won't trigger an interrupt on completion */
 	if (!xfer->len) {
-		spi_finalize_current_transfer(ctlr);
+		complete(&rs->xfer_done);
 		return 1;
 	}
 
@@ -740,14 +834,40 @@
 
 	rs->n_bytes = xfer->bits_per_word <= 8 ? 1 : 2;
 	rs->xfer = xfer;
-	use_dma = ctlr->can_dma ? ctlr->can_dma(ctlr, spi, xfer) : false;
+	if (rs->poll) {
+		xfer_mode = ROCKCHIP_SPI_POLL;
+	} else {
+		use_dma = ctlr->can_dma ? ctlr->can_dma(ctlr, spi, xfer) : false;
+		if (use_dma)
+			xfer_mode = ROCKCHIP_SPI_DMA;
+		else
+			xfer_mode = ROCKCHIP_SPI_IRQ;
+	}
 
-	rockchip_spi_config(rs, spi, xfer, use_dma, ctlr->slave);
+	ret = rockchip_spi_config(rs, spi, xfer, xfer_mode, ctlr->slave);
+	if (ret)
+		return ret;
 
-	if (use_dma)
-		return rockchip_spi_prepare_dma(rs, ctlr, xfer);
+	rs->tx = xfer->tx_buf;
+	rs->rx = xfer->rx_buf;
 
-	return rockchip_spi_prepare_irq(rs, ctlr, xfer);
+	reinit_completion(&rs->xfer_done);
+
+	switch (xfer_mode) {
+	case ROCKCHIP_SPI_POLL:
+		ret = rockchip_spi_pio_transfer(rs, ctlr, xfer);
+		break;
+	case ROCKCHIP_SPI_DMA:
+		ret = rockchip_spi_prepare_dma(rs, ctlr, xfer);
+		break;
+	default:
+		ret = rockchip_spi_prepare_irq(rs, ctlr, xfer);
+	}
+
+	if (ret > 0)
+		ret = rockchip_spi_transfer_wait(ctlr, xfer);
+
+	return ret;
 }
 
 static bool rockchip_spi_can_dma(struct spi_controller *ctlr,
@@ -879,7 +999,7 @@
 	struct spi_controller *ctlr;
 	struct resource *mem;
 	struct device_node *np = pdev->dev.of_node;
-	u32 rsd_nsecs;
+	u32 rsd_nsecs, csm;
 	bool slave_mode;
 	struct pinctrl *pinctrl = NULL;
 	const struct rockchip_spi_quirks *quirks_cfg;
@@ -968,6 +1088,16 @@
 		rs->rsd = rsd;
 	}
 
+	if (!device_property_read_u32(&pdev->dev, "csm", &csm)) {
+		if (csm > CR0_CSM_ONE)	{
+			dev_warn(rs->dev, "The csm value %u exceeds the limit, clamping at %u\n",
+				 csm, CR0_CSM_ONE);
+			csm = CR0_CSM_ONE;
+		}
+		rs->csm = csm;
+	}
+
+	rs->version = readl_relaxed(rs->regs + ROCKCHIP_SPI_VERSION);
 	rs->fifo_len = get_fifo_len(rs);
 	if (!rs->fifo_len) {
 		dev_err(&pdev->dev, "Failed to get fifo length\n");
@@ -1030,10 +1160,18 @@
 		ctlr->can_dma = rockchip_spi_can_dma;
 	}
 
-	switch (readl_relaxed(rs->regs + ROCKCHIP_SPI_VERSION)) {
+	rs->poll = device_property_read_bool(&pdev->dev, "rockchip,poll-only");
+	init_completion(&rs->xfer_done);
+	if (rs->poll && slave_mode) {
+		dev_err(rs->dev, "only support rockchip,poll-only property in master mode\n");
+		ret = -EINVAL;
+		goto err_free_dma_rx;
+	}
+
+	switch (rs->version) {
 	case ROCKCHIP_SPI_VER2_TYPE1:
 	case ROCKCHIP_SPI_VER2_TYPE2:
-		if (ctlr->can_dma && slave_mode)
+		if (slave_mode)
 			rs->cs_inactive = true;
 		else
 			rs->cs_inactive = false;
@@ -1041,7 +1179,6 @@
 	default:
 		rs->cs_inactive = false;
 	}
-
 	pinctrl = devm_pinctrl_get(&pdev->dev);
 	if (!IS_ERR(pinctrl)) {
 		rs->high_speed_state = pinctrl_lookup_state(pinctrl, "high_speed");
@@ -1072,6 +1209,8 @@
 		else
 			dev_info(&pdev->dev, "register misc device %s\n", misc_name);
 	}
+
+	dev_info(rs->dev, "probed, poll=%d, rsd=%d\n", rs->poll, rs->rsd);
 
 	return 0;
 
@@ -1120,51 +1259,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int rockchip_spi_suspend(struct device *dev)
-{
-	int ret;
-	struct spi_controller *ctlr = dev_get_drvdata(dev);
-	struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
-
-	ret = spi_controller_suspend(ctlr);
-	if (ret < 0)
-		return ret;
-
-	clk_disable_unprepare(rs->spiclk);
-	clk_disable_unprepare(rs->apb_pclk);
-
-	pinctrl_pm_select_sleep_state(dev);
-
-	return 0;
-}
-
-static int rockchip_spi_resume(struct device *dev)
-{
-	int ret;
-	struct spi_controller *ctlr = dev_get_drvdata(dev);
-	struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
-
-	pinctrl_pm_select_default_state(dev);
-
-	ret = clk_prepare_enable(rs->apb_pclk);
-	if (ret < 0)
-		return ret;
-
-	ret = clk_prepare_enable(rs->spiclk);
-	if (ret < 0)
-		clk_disable_unprepare(rs->apb_pclk);
-
-	ret = spi_controller_resume(ctlr);
-	if (ret < 0) {
-		clk_disable_unprepare(rs->spiclk);
-		clk_disable_unprepare(rs->apb_pclk);
-	}
-
-	return 0;
-}
-#endif /* CONFIG_PM_SLEEP */
-
 #ifdef CONFIG_PM
 static int rockchip_spi_runtime_suspend(struct device *dev)
 {
@@ -1195,6 +1289,46 @@
 }
 #endif /* CONFIG_PM */
 
+#ifdef CONFIG_PM_SLEEP
+static int rockchip_spi_suspend(struct device *dev)
+{
+	int ret;
+	struct spi_controller *ctlr = dev_get_drvdata(dev);
+
+	ret = spi_controller_suspend(ctlr);
+	if (ret < 0)
+		return ret;
+
+	/* Avoid redundant clock disable */
+	if (!pm_runtime_status_suspended(dev))
+		rockchip_spi_runtime_suspend(dev);
+
+	pinctrl_pm_select_sleep_state(dev);
+
+	return 0;
+}
+
+static int rockchip_spi_resume(struct device *dev)
+{
+	int ret;
+	struct spi_controller *ctlr = dev_get_drvdata(dev);
+
+	pinctrl_pm_select_default_state(dev);
+
+	if (!pm_runtime_status_suspended(dev)) {
+		ret = rockchip_spi_runtime_resume(dev);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = spi_controller_resume(ctlr);
+	if (ret < 0)
+		rockchip_spi_runtime_suspend(dev);
+
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
 static const struct dev_pm_ops rockchip_spi_pm = {
 	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rockchip_spi_suspend, rockchip_spi_resume)
 	SET_RUNTIME_PM_OPS(rockchip_spi_runtime_suspend,

--
Gitblit v1.6.2