2022-02-11 06:50:20

by Jon Lin

[permalink] [raw]
Subject: [RFC PATCH v1 0/6] New support and problem adjustment of SPI rockchip




Jon Lin (5):
spi: rockchip: Stop spi slave dma receiver when cs inactive
spi: rockchip: Preset cs-high and clk polarity in setup progress
spi: rockchip: Fix error in getting num-cs property
spi: rockchip: terminate dma transmission when slave abort
spi: rockchip: clear interrupt status in error handler

shengfei Xu (1):
spi: rockchip: Suspend and resume the bus during NOIRQ_SYSTEM_SLEEP_PM
ops

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

--
2.17.1



2022-02-11 07:14:01

by Jon Lin

[permalink] [raw]
Subject: [RFC PATCH v1 6/6] spi: rockchip: clear interrupt status in error handler

The interrupt status bit of the previous error data transmition will
affect the next operation and cause continuous SPI transmission failure.

Signed-off-by: Jon Lin <[email protected]>
---

drivers/spi/spi-rockchip.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 3d4e95eda4a6..bc547b79a2a1 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -278,8 +278,9 @@ static void rockchip_spi_handle_err(struct spi_controller *ctlr,
*/
spi_enable_chip(rs, false);

- /* make sure all interrupts are masked */
+ /* make sure all interrupts are masked and status cleared */
writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR);
+ writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR);

if (atomic_read(&rs->state) & TXDMA)
dmaengine_terminate_async(ctlr->dma_tx);
--
2.17.1


2022-02-11 08:50:27

by Jon Lin

[permalink] [raw]
Subject: [RFC PATCH v1 5/6] spi: rockchip: terminate dma transmission when slave abort

After slave abort, all DMA should be stopped, or it will affect the
next transmission:

[ 31.693877] Unable to handle kernel paging request at virtual address ffffff8105a2a7c0
[ 31.694643] Mem abort info:
[ 31.694898] ESR = 0x96000045
[ 31.695179] EC = 0x25: DABT (current EL), IL = 32 bits
[ 31.695653] SET = 0, FnV = 0
[ 31.695931] EA = 0, S1PTW = 0
[ 31.696218] Data abort info:
[ 31.696485] ISV = 0, ISS = 0x00000045
[ 31.696832] CM = 0, WnR = 1
[ 31.697112] swapper pgtable: 4k pages, 39-bit VAs, pgdp=000000000142f000
[ 31.697713] [ffffff8105a2a7c0] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000
[ 31.698502] Internal error: Oops: 96000045 [#1] SMP
[ 31.698943] Modules linked in:
[ 31.699235] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 5.10.43 #8
[ 31.699895] Hardware name: Rockchip RK3588 EVB1 LP4 V10 Board (DT)
[ 31.700455] pstate: 60400089 (nZCv daIf +PAN -UAO -TCO BTYPE=--)
[ 31.701000] pc : rockchip_spi_slave_abort+0x150/0x18c
[ 31.701456] lr : rockchip_spi_slave_abort+0x78/0x18c

Signed-off-by: Jon Lin <[email protected]>
---

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

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 5457af616a44..3d4e95eda4a6 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -617,8 +617,6 @@ static int rockchip_spi_slave_abort(struct spi_controller *ctlr)
if (atomic_read(&rs->state) & RXDMA) {
dmaengine_pause(ctlr->dma_rx);
status = dmaengine_tx_status(ctlr->dma_rx, ctlr->dma_rx->cookie, &state);
- dmaengine_terminate_sync(ctlr->dma_rx);
- atomic_set(&rs->state, 0);
if (status == DMA_ERROR) {
rs->rx = rs->xfer->rx_buf;
rs->xfer->len = 0;
@@ -648,6 +646,11 @@ static int rockchip_spi_slave_abort(struct spi_controller *ctlr)
}

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;
spi_finalize_current_transfer(ctlr);
--
2.17.1


2022-02-11 09:40:28

by Jon Lin

[permalink] [raw]
Subject: [RFC PATCH v1 4/6] spi: rockchip: Suspend and resume the bus during NOIRQ_SYSTEM_SLEEP_PM ops

From: shengfei Xu <[email protected]>

the wakeup interrupt handler which is guaranteed not to run while
@resume noirq() is being executed. the patch can help to avoid the
wakeup source try to access spi when the spi is in suspend mode.

Signed-off-by: shengfei Xu <[email protected]>
Signed-off-by: Jon Lin <[email protected]>
---

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

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 5f6a70664871..5457af616a44 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -959,14 +959,14 @@ 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;

- ret = pm_runtime_force_suspend(dev);
- if (ret < 0)
- return ret;
+ clk_disable_unprepare(rs->spiclk);
+ clk_disable_unprepare(rs->apb_pclk);

pinctrl_pm_select_sleep_state(dev);

@@ -981,10 +981,14 @@ static int rockchip_spi_resume(struct device *dev)

pinctrl_pm_select_default_state(dev);

- ret = pm_runtime_force_resume(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);
@@ -1026,7 +1030,7 @@ static int rockchip_spi_runtime_resume(struct device *dev)
#endif /* CONFIG_PM */

static const struct dev_pm_ops rockchip_spi_pm = {
- SET_SYSTEM_SLEEP_PM_OPS(rockchip_spi_suspend, rockchip_spi_resume)
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rockchip_spi_suspend, rockchip_spi_resume)
SET_RUNTIME_PM_OPS(rockchip_spi_runtime_suspend,
rockchip_spi_runtime_resume, NULL)
};
--
2.17.1


2022-02-11 10:49:20

by Jon Lin

[permalink] [raw]
Subject: [RFC PATCH v1 2/6] spi: rockchip: Preset cs-high and clk polarity in setup progress

After power up, the cs and clock is in default status, and the cs-high
and clock polarity dts property configuration will take no effect until
the calling of rockchip_spi_config in the first transmission.
So preset them to make sure a correct voltage before the first
transmission coming.

Signed-off-by: Jon Lin <[email protected]>
---

drivers/spi/spi-rockchip.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 7ac07569e103..1738a2611a2b 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -711,6 +711,26 @@ static bool rockchip_spi_can_dma(struct spi_controller *ctlr,
return xfer->len / bytes_per_word >= rs->fifo_len;
}

+static int rockchip_spi_setup(struct spi_device *spi)
+{
+ struct rockchip_spi *rs = spi_controller_get_devdata(spi->controller);
+ u32 cr0;
+
+ pm_runtime_get_sync(rs->dev);
+
+ cr0 = readl_relaxed(rs->regs + ROCKCHIP_SPI_CTRLR0);
+
+ cr0 |= ((spi->mode & 0x3) << CR0_SCPH_OFFSET);
+ if (spi->mode & SPI_CS_HIGH)
+ cr0 |= BIT(spi->chip_select) << CR0_SOI_OFFSET;
+
+ writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0);
+
+ pm_runtime_put(rs->dev);
+
+ return 0;
+}
+
static int rockchip_spi_probe(struct platform_device *pdev)
{
int ret;
@@ -837,6 +857,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
ctlr->min_speed_hz = rs->freq / BAUDR_SCKDV_MAX;
ctlr->max_speed_hz = min(rs->freq / BAUDR_SCKDV_MIN, MAX_SCLK_OUT);

+ ctlr->setup = rockchip_spi_setup;
ctlr->set_cs = rockchip_spi_set_cs;
ctlr->transfer_one = rockchip_spi_transfer_one;
ctlr->max_transfer_size = rockchip_spi_max_transfer_size;
--
2.17.1


2022-02-11 16:53:39

by Jon Lin

[permalink] [raw]
Subject: [RFC PATCH v1 3/6] spi: rockchip: Fix error in getting num-cs property

Get num-cs u32 from dts of_node property rather than u16.

Signed-off-by: Jon Lin <[email protected]>
---

drivers/spi/spi-rockchip.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 1738a2611a2b..5f6a70664871 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -738,7 +738,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
struct spi_controller *ctlr;
struct resource *mem;
struct device_node *np = pdev->dev.of_node;
- u32 rsd_nsecs;
+ u32 rsd_nsecs, num_cs;
bool slave_mode;

slave_mode = of_property_read_bool(np, "spi-slave");
@@ -848,8 +848,9 @@ static int rockchip_spi_probe(struct platform_device *pdev)
* rk spi0 has two native cs, spi1..5 one cs only
* if num-cs is missing in the dts, default to 1
*/
- if (of_property_read_u16(np, "num-cs", &ctlr->num_chipselect))
- ctlr->num_chipselect = 1;
+ if (of_property_read_u32(np, "num-cs", &num_cs))
+ num_cs = 1;
+ ctlr->num_chipselect = num_cs;
ctlr->use_gpio_descriptors = true;
}
ctlr->dev.of_node = pdev->dev.of_node;
--
2.17.1