[Bugfix][T106BUG-616]SPI set to slave mode for read will get stuck start
Only Configure :No
Affected branch: master
Affected module: SPI
Is it affected on both ZXIC and MTK:only ZXIC
Self-test: Yes
Doc Update: No
Change-Id: I7ec80158e6c9fb2dc247009adbf33e1cd9e05697
diff --git a/cap/zx297520v3/zxic_code/zxic_source/linux-5.10/drivers/spi/spi-zx29.c b/cap/zx297520v3/zxic_code/zxic_source/linux-5.10/drivers/spi/spi-zx29.c
index 546be32..9d3f781 100755
--- a/cap/zx297520v3/zxic_code/zxic_source/linux-5.10/drivers/spi/spi-zx29.c
+++ b/cap/zx297520v3/zxic_code/zxic_source/linux-5.10/drivers/spi/spi-zx29.c
@@ -44,6 +44,10 @@
#include "spi-zx29.h"
#include "pub_debug_info.h"
+/* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck start */
+#include <linux/wait.h>
+#include <linux/suspend.h>
+/* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck end */
struct zx29_ssp_device_of_data {
enum zx29_ssp_device_mode mode;
@@ -386,6 +390,10 @@
struct wake_lock psm_lock;
#endif
struct semaphore sema_dma;
+/* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck start */
+ wait_queue_head_t wait;
+ int trans_done;
+/* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck end */
u8 iface_mode;
#define SPI_MOTO_FORMAT 0x00
#define SPI_TI_FORMAT 0x01
@@ -866,7 +874,16 @@
{
struct zx29_spi *zx29spi = (struct zx29_spi *)data;
//printk(KERN_INFO "spi:dma transfer complete. %X-%X-%x\n", zx29spi->dma_running, readl((SPI_INTR_SR_OFFSET+zx29spi->virtbase)),readl((SPI_FIFO_SR_OFFSET+zx29spi->virtbase)));
- up(&zx29spi->sema_dma);
+ /* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck start */
+ //up(&zx29spi->sema_dma);
+ if(zx29spi->master->slave == true){
+ wake_up(&zx29spi->wait);
+ zx29spi->trans_done = true;
+ }else
+ {
+ up(&zx29spi->sema_dma);
+ }
+ /* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck end */
}
/*
@@ -1295,6 +1312,70 @@
return;
}
+/* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck start */
+#define SSP1_PARA_BASE_ADDR 0x1400048
+
+#define SSP_MASK_SW_WRST (0x1L << 9)
+#define SSP_MASK_SW_PRST (0x1L << 8)
+
+static int zx29_slave_ctrl_reset(struct zx29_spi *zx29spi) {
+ void __iomem *addr = NULL;
+ ktime_t k_time_start = 0;
+ ktime_t diff_ns = 0;
+ volatile unsigned int val = 0;
+
+ addr = ioremap(SSP1_PARA_BASE_ADDR, 0x1000);
+
+ if (addr) {
+ val = *(volatile unsigned int *)addr;
+ *(volatile unsigned int *)addr = val & (~(SSP_MASK_SW_WRST | SSP_MASK_SW_PRST));
+
+ k_time_start = ktime_get();
+ do {
+ diff_ns = ktime_sub(ktime_get(), k_time_start);
+ val = readl((SPI_COM_CTRL_OFFSET + zx29spi->virtbase)) >> 1 & 0x1;
+ cpu_relax();
+ } while (val && diff_ns < 100000000); // 100ms
+
+ if (diff_ns >= 100000000)
+ dev_info(&zx29spi->pdev->dev, "zx29_slave_assert_ctrl failed!!! \n");
+ else
+ dev_info(&zx29spi->pdev->dev, "zx29_slave_assert_ctrl success! \n");
+
+ val = *(volatile unsigned int *)addr;
+ *(volatile unsigned int *)addr = val | (SSP_MASK_SW_WRST | SSP_MASK_SW_PRST);
+ udelay(500);
+ }
+
+ return 0;
+}
+
+static int zx29_slave_ctrl_reinit(struct zx29_spi *zx29spi) {
+ volatile unsigned int regval;
+
+ zx29_slave_ctrl_reset(zx29spi);
+
+ /* Disable SPI */
+ regval = readl((SPI_COM_CTRL_OFFSET + zx29spi->virtbase)) & (~SPI_COM_CTRL_MASK_SSPE);
+ writel(regval, (SPI_COM_CTRL_OFFSET + zx29spi->virtbase));
+
+ load_spi_default_config(zx29spi);
+ writel(0, (SPI_TIMING_OFFSET + zx29spi->virtbase));
+
+ if (!strcmp(zx29spi->pdev->name, "1410000.ssp")) {
+ regval = readl((SPI_FMT_CTRL_OFFSET + zx29spi->virtbase)) & (~(0x1 << 12));
+ writel(regval, (SPI_FMT_CTRL_OFFSET + zx29spi->virtbase));
+ dev_info(&zx29spi->pdev->dev, "%s set non-camera mode regval:0x%x \n", zx29spi->pdev->name, regval);
+ }
+
+ writel(readl((SPI_COM_CTRL_OFFSET + zx29spi->virtbase)) | SPI_COM_CTRL_MASK_SSPE, (SPI_COM_CTRL_OFFSET + zx29spi->virtbase));
+ while (((readl((SPI_COM_CTRL_OFFSET + zx29spi->virtbase)) >> 4) & 0x1) == 0);
+
+ dev_info(&zx29spi->pdev->dev, "ssp enabled \n", regval);
+
+ return 0;
+}
+/* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck end */
static int zx29_slave_do_interrupt_dma_transfer(struct zx29_spi *zx29spi)
{
@@ -1324,6 +1405,7 @@
/* If we're using DMA, set up DMA here */
if (zx29spi->cur_chip->enable_dma) {
/* Configure DMA transfer */
+ zx29spi->trans_done = false; //yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck
ret = configure_dma(zx29spi);
if (ret) {
dev_err(&zx29spi->pdev->dev, "configuration of DMA failed, fall back to interrupt mode\n");
@@ -1336,7 +1418,17 @@
extern void spi_dev_send_dma_cfg_down(struct spi_device *spi);
struct spi_device *spi = zx29spi->cur_msg->spi;
spi_dev_send_dma_cfg_down(spi);
- down(&zx29spi->sema_dma);
+ /* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck start */
+ //down(&zx29spi->sema_dma);
+ ret = wait_event_freezable(zx29spi->wait, zx29spi->trans_done);
+ if(ret){
+ terminate_dma(zx29spi);
+ disable_irq_nosync(zx29spi->irq);
+ zx29spi->dma_running = 0;
+ zx29_slave_ctrl_reinit(zx29spi);
+ goto err_config_dma;
+ }
+ /* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck end */
//printk("COM=0x%x,FMT=0x%x,FIFO_CTL=0x%x,FIFO_SR=0x%x\n",readl((SPI_COM_CTRL_OFFSET+zx29spi->virtbase)),readl((SPI_FMT_CTRL_OFFSET+zx29spi->virtbase)),readl((SPI_FIFO_CTRL_OFFSET+zx29spi->virtbase)),readl((SPI_FIFO_SR_OFFSET+zx29spi->virtbase)));
@@ -2819,6 +2911,10 @@
zx29spi->mode = ZX29_SSP_MASTER_TYPE;
zx29spi->zx29_flush_rxfifo = zx29_flush_rxfifo;
sema_init(&zx29spi->sema_dma, 0);
+ /* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck start */
+ init_waitqueue_head(&zx29spi->wait);
+ zx29spi->trans_done = false;
+ /* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck end */
dev_set_drvdata(&pdev->dev, zx29spi);
device_init_wakeup(&pdev->dev, true);
/*
@@ -2991,7 +3087,11 @@
zx29spi->vendor = &vendor_arm;
zx29spi->mode = ZX29_SSP_SLAVE_TYPE;
zx29spi->zx29_flush_rxfifo = zx29_flush_rxfifo;
- sema_init(&zx29spi->sema_dma, 0);
+ sema_init(&zx29spi->sema_dma, 0);
+ /* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck start */
+ init_waitqueue_head(&zx29spi->wait);
+ zx29spi->trans_done = false;
+ /* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck end */
dev_set_drvdata(&pdev->dev, zx29spi);
/*
* Bus Number Which has been Assigned to this SSP controller