Commit 5dc349ec authored by Chunyan Zhang's avatar Chunyan Zhang Committed by Mark Brown

spi: sprd: Pass offset instead of physical address to adi_read/_write()

The register offset would be added a physical address base and then pass to
the function sprd_adt_read()/_write() each time before calling them. So we
can do that within these two functions instead, that would make the code
more clear.
Signed-off-by: default avatarChunyan Zhang <chunyan.zhang@unisoc.com>
Link: https://lore.kernel.org/r/20210824070212.2089255-1-zhang.lyra@gmail.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 745649c5
...@@ -117,24 +117,18 @@ struct sprd_adi { ...@@ -117,24 +117,18 @@ struct sprd_adi {
struct notifier_block restart_handler; struct notifier_block restart_handler;
}; };
static int sprd_adi_check_paddr(struct sprd_adi *sadi, u32 paddr) static int sprd_adi_check_addr(struct sprd_adi *sadi, u32 reg)
{ {
if (paddr < sadi->slave_pbase || paddr > if (reg > ADI_SLAVE_ADDR_SIZE) {
(sadi->slave_pbase + ADI_SLAVE_ADDR_SIZE)) {
dev_err(sadi->dev, dev_err(sadi->dev,
"slave physical address is incorrect, addr = 0x%x\n", "slave address offset is incorrect, reg = 0x%x\n",
paddr); reg);
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
} }
static unsigned long sprd_adi_to_vaddr(struct sprd_adi *sadi, u32 paddr)
{
return (paddr - sadi->slave_pbase + sadi->slave_vbase);
}
static int sprd_adi_drain_fifo(struct sprd_adi *sadi) static int sprd_adi_drain_fifo(struct sprd_adi *sadi)
{ {
u32 timeout = ADI_FIFO_DRAIN_TIMEOUT; u32 timeout = ADI_FIFO_DRAIN_TIMEOUT;
...@@ -161,11 +155,11 @@ static int sprd_adi_fifo_is_full(struct sprd_adi *sadi) ...@@ -161,11 +155,11 @@ static int sprd_adi_fifo_is_full(struct sprd_adi *sadi)
return readl_relaxed(sadi->base + REG_ADI_ARM_FIFO_STS) & BIT_FIFO_FULL; return readl_relaxed(sadi->base + REG_ADI_ARM_FIFO_STS) & BIT_FIFO_FULL;
} }
static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) static int sprd_adi_read(struct sprd_adi *sadi, u32 reg, u32 *read_val)
{ {
int read_timeout = ADI_READ_TIMEOUT; int read_timeout = ADI_READ_TIMEOUT;
unsigned long flags; unsigned long flags;
u32 val, rd_addr; u32 val, rd_addr, paddr;
int ret = 0; int ret = 0;
if (sadi->hwlock) { if (sadi->hwlock) {
...@@ -178,11 +172,16 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) ...@@ -178,11 +172,16 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val)
} }
} }
ret = sprd_adi_check_addr(sadi, reg);
if (ret)
goto out;
/* /*
* Set the physical register address need to read into RD_CMD register, * Set the physical register address need to read into RD_CMD register,
* then ADI controller will start to transfer automatically. * then ADI controller will start to transfer automatically.
*/ */
writel_relaxed(reg_paddr, sadi->base + REG_ADI_RD_CMD); paddr = sadi->slave_pbase + reg;
writel_relaxed(paddr, sadi->base + REG_ADI_RD_CMD);
/* /*
* Wait read operation complete, the BIT_RD_CMD_BUSY will be set * Wait read operation complete, the BIT_RD_CMD_BUSY will be set
...@@ -212,9 +211,9 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) ...@@ -212,9 +211,9 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val)
*/ */
rd_addr = (val & RD_ADDR_MASK) >> RD_ADDR_SHIFT; rd_addr = (val & RD_ADDR_MASK) >> RD_ADDR_SHIFT;
if (rd_addr != (reg_paddr & REG_ADDR_LOW_MASK)) { if (rd_addr != (paddr & REG_ADDR_LOW_MASK)) {
dev_err(sadi->dev, "read error, reg addr = 0x%x, val = 0x%x\n", dev_err(sadi->dev, "read error, reg addr = 0x%x, val = 0x%x\n",
reg_paddr, val); paddr, val);
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
...@@ -227,9 +226,8 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) ...@@ -227,9 +226,8 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val)
return ret; return ret;
} }
static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val) static int sprd_adi_write(struct sprd_adi *sadi, u32 reg, u32 val)
{ {
unsigned long reg = sprd_adi_to_vaddr(sadi, reg_paddr);
u32 timeout = ADI_FIFO_DRAIN_TIMEOUT; u32 timeout = ADI_FIFO_DRAIN_TIMEOUT;
unsigned long flags; unsigned long flags;
int ret; int ret;
...@@ -244,6 +242,10 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val) ...@@ -244,6 +242,10 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val)
} }
} }
ret = sprd_adi_check_addr(sadi, reg);
if (ret)
goto out;
ret = sprd_adi_drain_fifo(sadi); ret = sprd_adi_drain_fifo(sadi);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -254,7 +256,8 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val) ...@@ -254,7 +256,8 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val)
*/ */
do { do {
if (!sprd_adi_fifo_is_full(sadi)) { if (!sprd_adi_fifo_is_full(sadi)) {
writel_relaxed(val, (void __iomem *)reg); /* we need virtual register address to write. */
writel_relaxed(val, (void __iomem *)(sadi->slave_vbase + reg));
break; break;
} }
...@@ -277,44 +280,24 @@ static int sprd_adi_transfer_one(struct spi_controller *ctlr, ...@@ -277,44 +280,24 @@ static int sprd_adi_transfer_one(struct spi_controller *ctlr,
struct spi_transfer *t) struct spi_transfer *t)
{ {
struct sprd_adi *sadi = spi_controller_get_devdata(ctlr); struct sprd_adi *sadi = spi_controller_get_devdata(ctlr);
u32 phy_reg, val; u32 reg, val;
int ret; int ret;
if (t->rx_buf) { if (t->rx_buf) {
phy_reg = *(u32 *)t->rx_buf + sadi->slave_pbase; reg = *(u32 *)t->rx_buf;
ret = sprd_adi_read(sadi, reg, &val);
ret = sprd_adi_check_paddr(sadi, phy_reg);
if (ret)
return ret;
ret = sprd_adi_read(sadi, phy_reg, &val);
if (ret)
return ret;
*(u32 *)t->rx_buf = val; *(u32 *)t->rx_buf = val;
} else if (t->tx_buf) { } else if (t->tx_buf) {
u32 *p = (u32 *)t->tx_buf; u32 *p = (u32 *)t->tx_buf;
reg = *p++;
/*
* Get the physical register address need to write and convert
* the physical address to virtual address. Since we need
* virtual register address to write.
*/
phy_reg = *p++ + sadi->slave_pbase;
ret = sprd_adi_check_paddr(sadi, phy_reg);
if (ret)
return ret;
val = *p; val = *p;
ret = sprd_adi_write(sadi, phy_reg, val); ret = sprd_adi_write(sadi, reg, val);
if (ret)
return ret;
} else { } else {
dev_err(sadi->dev, "no buffer for transfer\n"); dev_err(sadi->dev, "no buffer for transfer\n");
return -EINVAL; ret = -EINVAL;
} }
return 0; return ret;
} }
static void sprd_adi_set_wdt_rst_mode(struct sprd_adi *sadi) static void sprd_adi_set_wdt_rst_mode(struct sprd_adi *sadi)
...@@ -323,9 +306,9 @@ static void sprd_adi_set_wdt_rst_mode(struct sprd_adi *sadi) ...@@ -323,9 +306,9 @@ static void sprd_adi_set_wdt_rst_mode(struct sprd_adi *sadi)
u32 val; u32 val;
/* Set default watchdog reboot mode */ /* Set default watchdog reboot mode */
sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val); sprd_adi_read(sadi, PMIC_RST_STATUS, &val);
val |= HWRST_STATUS_WATCHDOG; val |= HWRST_STATUS_WATCHDOG;
sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val); sprd_adi_write(sadi, PMIC_RST_STATUS, val);
#endif #endif
} }
...@@ -366,40 +349,40 @@ static int sprd_adi_restart_handler(struct notifier_block *this, ...@@ -366,40 +349,40 @@ static int sprd_adi_restart_handler(struct notifier_block *this,
reboot_mode = HWRST_STATUS_NORMAL; reboot_mode = HWRST_STATUS_NORMAL;
/* Record the reboot mode */ /* Record the reboot mode */
sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val); sprd_adi_read(sadi, PMIC_RST_STATUS, &val);
val &= ~HWRST_STATUS_WATCHDOG; val &= ~HWRST_STATUS_WATCHDOG;
val |= reboot_mode; val |= reboot_mode;
sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val); sprd_adi_write(sadi, PMIC_RST_STATUS, val);
/* Enable the interface clock of the watchdog */ /* Enable the interface clock of the watchdog */
sprd_adi_read(sadi, sadi->slave_pbase + PMIC_MODULE_EN, &val); sprd_adi_read(sadi, PMIC_MODULE_EN, &val);
val |= BIT_WDG_EN; val |= BIT_WDG_EN;
sprd_adi_write(sadi, sadi->slave_pbase + PMIC_MODULE_EN, val); sprd_adi_write(sadi, PMIC_MODULE_EN, val);
/* Enable the work clock of the watchdog */ /* Enable the work clock of the watchdog */
sprd_adi_read(sadi, sadi->slave_pbase + PMIC_CLK_EN, &val); sprd_adi_read(sadi, PMIC_CLK_EN, &val);
val |= BIT_WDG_EN; val |= BIT_WDG_EN;
sprd_adi_write(sadi, sadi->slave_pbase + PMIC_CLK_EN, val); sprd_adi_write(sadi, PMIC_CLK_EN, val);
/* Unlock the watchdog */ /* Unlock the watchdog */
sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOCK, WDG_UNLOCK_KEY); sprd_adi_write(sadi, REG_WDG_LOCK, WDG_UNLOCK_KEY);
sprd_adi_read(sadi, sadi->slave_pbase + REG_WDG_CTRL, &val); sprd_adi_read(sadi, REG_WDG_CTRL, &val);
val |= BIT_WDG_NEW; val |= BIT_WDG_NEW;
sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_CTRL, val); sprd_adi_write(sadi, REG_WDG_CTRL, val);
/* Load the watchdog timeout value, 50ms is always enough. */ /* Load the watchdog timeout value, 50ms is always enough. */
sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_HIGH, 0); sprd_adi_write(sadi, REG_WDG_LOAD_HIGH, 0);
sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_LOW, sprd_adi_write(sadi, REG_WDG_LOAD_LOW,
WDG_LOAD_VAL & WDG_LOAD_MASK); WDG_LOAD_VAL & WDG_LOAD_MASK);
/* Start the watchdog to reset system */ /* Start the watchdog to reset system */
sprd_adi_read(sadi, sadi->slave_pbase + REG_WDG_CTRL, &val); sprd_adi_read(sadi, REG_WDG_CTRL, &val);
val |= BIT_WDG_RUN | BIT_WDG_RST; val |= BIT_WDG_RUN | BIT_WDG_RST;
sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_CTRL, val); sprd_adi_write(sadi, REG_WDG_CTRL, val);
/* Lock the watchdog */ /* Lock the watchdog */
sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOCK, ~WDG_UNLOCK_KEY); sprd_adi_write(sadi, REG_WDG_LOCK, ~WDG_UNLOCK_KEY);
mdelay(1000); mdelay(1000);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment