[U-Boot] [PATCH 5/5] DW SPI: use 32 bit access instead of 16 and 32 bit mix
Eugeniy Paltsev
Eugeniy.Paltsev at synopsys.com
Mon Mar 5 13:17:19 UTC 2018
Current DW SPI driver uses 32 bit access for some registers and
16 bit access for others. So if DW SPI IP is connected via bus
which doesn't support 16 bit access we will get bus error.
Fix that by switching to 32 bit access only instead of 16 and 32 bit mix
Additional Documentation to Support this Change:
The DW_apb_ssi databook states:
"All registers in the DW_apb_ssi are addressed at 32-bit boundaries
to remain consistent with the AHB bus. Where the physical size of
any register is less than 32-bits wide, the upper unused bits of
the 32-bit boundary are reserved. Writing to these bits has no
effect; reading from these bits returns 0." [1]
[1] Section 6.1 of dw_apb_ssi.pdf (version 3.22a)
Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev at synopsys.com>
---
drivers/spi/designware_spi.c | 44 +++++++++++++++++---------------------------
1 file changed, 17 insertions(+), 27 deletions(-)
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 099c9c4d03..24034c79b3 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -113,26 +113,16 @@ struct dw_spi_priv {
void *rx_end;
};
-static inline u32 dw_readl(struct dw_spi_priv *priv, u32 offset)
+static inline u32 dw_read(struct dw_spi_priv *priv, u32 offset)
{
return __raw_readl(priv->regs + offset);
}
-static inline void dw_writel(struct dw_spi_priv *priv, u32 offset, u32 val)
+static inline void dw_write(struct dw_spi_priv *priv, u32 offset, u32 val)
{
__raw_writel(val, priv->regs + offset);
}
-static inline u16 dw_readw(struct dw_spi_priv *priv, u32 offset)
-{
- return __raw_readw(priv->regs + offset);
-}
-
-static inline void dw_writew(struct dw_spi_priv *priv, u32 offset, u16 val)
-{
- __raw_writew(val, priv->regs + offset);
-}
-
static int request_gpio_cs(struct udevice *bus)
{
#if defined(CONFIG_DM_GPIO) && !defined(CONFIG_SPL_BUILD)
@@ -178,14 +168,14 @@ static int dw_spi_ofdata_to_platdata(struct udevice *bus)
static inline void spi_enable_chip(struct dw_spi_priv *priv, int enable)
{
- dw_writel(priv, DW_SPI_SSIENR, (enable ? 1 : 0));
+ dw_write(priv, DW_SPI_SSIENR, (enable ? 1 : 0));
}
/* Restart the controller, disable all interrupts, clean rx fifo */
static void spi_hw_init(struct dw_spi_priv *priv)
{
spi_enable_chip(priv, 0);
- dw_writel(priv, DW_SPI_IMR, 0xff);
+ dw_write(priv, DW_SPI_IMR, 0xff);
spi_enable_chip(priv, 1);
/*
@@ -196,13 +186,13 @@ static void spi_hw_init(struct dw_spi_priv *priv)
u32 fifo;
for (fifo = 1; fifo < 256; fifo++) {
- dw_writew(priv, DW_SPI_TXFLTR, fifo);
- if (fifo != dw_readw(priv, DW_SPI_TXFLTR))
+ dw_write(priv, DW_SPI_TXFLTR, fifo);
+ if (fifo != dw_read(priv, DW_SPI_TXFLTR))
break;
}
priv->fifo_len = (fifo == 1) ? 0 : fifo;
- dw_writew(priv, DW_SPI_TXFLTR, 0);
+ dw_write(priv, DW_SPI_TXFLTR, 0);
}
debug("%s: fifo_len=%d\n", __func__, priv->fifo_len);
}
@@ -271,7 +261,7 @@ static inline u32 tx_max(struct dw_spi_priv *priv)
u32 tx_left, tx_room, rxtx_gap;
tx_left = (priv->tx_end - priv->tx) / (priv->bits_per_word >> 3);
- tx_room = priv->fifo_len - dw_readw(priv, DW_SPI_TXFLR);
+ tx_room = priv->fifo_len - dw_read(priv, DW_SPI_TXFLR);
/*
* Another concern is about the tx/rx mismatch, we
@@ -292,7 +282,7 @@ static inline u32 rx_max(struct dw_spi_priv *priv)
{
u32 rx_left = (priv->rx_end - priv->rx) / (priv->bits_per_word >> 3);
- return min_t(u32, rx_left, dw_readw(priv, DW_SPI_RXFLR));
+ return min_t(u32, rx_left, dw_read(priv, DW_SPI_RXFLR));
}
static void dw_writer(struct dw_spi_priv *priv)
@@ -308,7 +298,7 @@ static void dw_writer(struct dw_spi_priv *priv)
else
txw = *(u16 *)(priv->tx);
}
- dw_writew(priv, DW_SPI_DR, txw);
+ dw_write(priv, DW_SPI_DR, txw);
debug("%s: tx=0x%02x\n", __func__, txw);
priv->tx += priv->bits_per_word >> 3;
}
@@ -320,7 +310,7 @@ static void dw_reader(struct dw_spi_priv *priv)
u16 rxw;
while (max--) {
- rxw = dw_readw(priv, DW_SPI_DR);
+ rxw = dw_read(priv, DW_SPI_DR);
debug("%s: rx=0x%02x\n", __func__, rxw);
/* Care about rx if the transfer's original "rx" is not null */
@@ -409,8 +399,8 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
debug("%s: cr0=%08x\n", __func__, cr0);
/* Reprogram cr0 only if changed */
- if (dw_readw(priv, DW_SPI_CTRL0) != cr0)
- dw_writew(priv, DW_SPI_CTRL0, cr0);
+ if (dw_read(priv, DW_SPI_CTRL0) != cr0)
+ dw_write(priv, DW_SPI_CTRL0, cr0);
/*
* Configure the desired SS (slave select 0...3) in the controller
@@ -418,7 +408,7 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
* automatically. So no cs_activate() etc is needed in this driver.
*/
cs = spi_chip_select(dev);
- dw_writel(priv, DW_SPI_SER, 1 << cs);
+ dw_write(priv, DW_SPI_SER, 1 << cs);
/* Enable controller after writing control registers */
spi_enable_chip(priv, 1);
@@ -434,8 +424,8 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
* in the beginning of new transfer.
*/
start = get_timer(0);
- while (!(dw_readl(priv, DW_SPI_SR) & SR_TF_EMPT) ||
- (dw_readl(priv, DW_SPI_SR) & SR_BUSY)) {
+ while (!(dw_read(priv, DW_SPI_SR) & SR_TF_EMPT) ||
+ (dw_read(priv, DW_SPI_SR) & SR_BUSY)) {
if (get_timer(start) > RX_TIMEOUT) {
ret = -ETIMEDOUT;
break;
@@ -464,7 +454,7 @@ static int dw_spi_set_speed(struct udevice *bus, uint speed)
/* clk_div doesn't support odd number */
clk_div = priv->bus_clk_rate / speed;
clk_div = (clk_div + 1) & 0xfffe;
- dw_writel(priv, DW_SPI_BAUDR, clk_div);
+ dw_write(priv, DW_SPI_BAUDR, clk_div);
/* Enable controller after writing control registers */
spi_enable_chip(priv, 1);
--
2.14.3
More information about the U-Boot
mailing list