diff options
author | Thor Thayer <tthayer@opensource.altera.com> | 2015-03-12 15:19:31 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-03-17 08:27:09 -0400 |
commit | dd11444327ce0fd549cce552b04aa441688ef2d3 (patch) | |
tree | 837d1035ba6b02b54d3691415feb81caeeccbd08 /drivers/spi | |
parent | 2306509605d3cb45b8480089af2d282600650e9e (diff) |
spi: dw-spi: Convert 16bit accesses to 32bit accesses
Altera's Arria10 SoC interconnect requires a 32-bit write for APB
peripherals. The current spi-dw driver uses 16-bit accesses in
some locations. This patch converts all the 16-bit reads and
writes to 32-bit reads and writes.
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)
Request for test with platforms using the DesignWare SPI IP.
Tested On:
Altera CycloneV development kit
Altera Arria10 development kit
Compile tested for build errors on x86_64 (allyesconfigs)
Signed-off-by: Thor Thayer <tthayer@opensource.altera.com>
Reviewed-and-tested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-dw-mid.c | 10 | ||||
-rw-r--r-- | drivers/spi/spi-dw.c | 24 | ||||
-rw-r--r-- | drivers/spi/spi-dw.h | 10 |
3 files changed, 17 insertions, 27 deletions
diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c index d4109f6dd3c0..bb1052e748f2 100644 --- a/drivers/spi/spi-dw-mid.c +++ b/drivers/spi/spi-dw-mid.c | |||
@@ -98,12 +98,12 @@ static void mid_spi_dma_exit(struct dw_spi *dws) | |||
98 | 98 | ||
99 | static irqreturn_t dma_transfer(struct dw_spi *dws) | 99 | static irqreturn_t dma_transfer(struct dw_spi *dws) |
100 | { | 100 | { |
101 | u16 irq_status = dw_readw(dws, DW_SPI_ISR); | 101 | u16 irq_status = dw_readl(dws, DW_SPI_ISR); |
102 | 102 | ||
103 | if (!irq_status) | 103 | if (!irq_status) |
104 | return IRQ_NONE; | 104 | return IRQ_NONE; |
105 | 105 | ||
106 | dw_readw(dws, DW_SPI_ICR); | 106 | dw_readl(dws, DW_SPI_ICR); |
107 | spi_reset_chip(dws); | 107 | spi_reset_chip(dws); |
108 | 108 | ||
109 | dev_err(&dws->master->dev, "%s: FIFO overrun/underrun\n", __func__); | 109 | dev_err(&dws->master->dev, "%s: FIFO overrun/underrun\n", __func__); |
@@ -228,14 +228,14 @@ static int mid_spi_dma_setup(struct dw_spi *dws, struct spi_transfer *xfer) | |||
228 | { | 228 | { |
229 | u16 dma_ctrl = 0; | 229 | u16 dma_ctrl = 0; |
230 | 230 | ||
231 | dw_writew(dws, DW_SPI_DMARDLR, 0xf); | 231 | dw_writel(dws, DW_SPI_DMARDLR, 0xf); |
232 | dw_writew(dws, DW_SPI_DMATDLR, 0x10); | 232 | dw_writel(dws, DW_SPI_DMATDLR, 0x10); |
233 | 233 | ||
234 | if (xfer->tx_buf) | 234 | if (xfer->tx_buf) |
235 | dma_ctrl |= SPI_DMA_TDMAE; | 235 | dma_ctrl |= SPI_DMA_TDMAE; |
236 | if (xfer->rx_buf) | 236 | if (xfer->rx_buf) |
237 | dma_ctrl |= SPI_DMA_RDMAE; | 237 | dma_ctrl |= SPI_DMA_RDMAE; |
238 | dw_writew(dws, DW_SPI_DMACR, dma_ctrl); | 238 | dw_writel(dws, DW_SPI_DMACR, dma_ctrl); |
239 | 239 | ||
240 | /* Set the interrupt mask */ | 240 | /* Set the interrupt mask */ |
241 | spi_umask_intr(dws, SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI); | 241 | spi_umask_intr(dws, SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI); |
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 0f0106933b52..cafac221fbf6 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c | |||
@@ -157,7 +157,7 @@ static inline u32 tx_max(struct dw_spi *dws) | |||
157 | u32 tx_left, tx_room, rxtx_gap; | 157 | u32 tx_left, tx_room, rxtx_gap; |
158 | 158 | ||
159 | tx_left = (dws->tx_end - dws->tx) / dws->n_bytes; | 159 | tx_left = (dws->tx_end - dws->tx) / dws->n_bytes; |
160 | tx_room = dws->fifo_len - dw_readw(dws, DW_SPI_TXFLR); | 160 | tx_room = dws->fifo_len - dw_readl(dws, DW_SPI_TXFLR); |
161 | 161 | ||
162 | /* | 162 | /* |
163 | * Another concern is about the tx/rx mismatch, we | 163 | * Another concern is about the tx/rx mismatch, we |
@@ -178,7 +178,7 @@ static inline u32 rx_max(struct dw_spi *dws) | |||
178 | { | 178 | { |
179 | u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes; | 179 | u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes; |
180 | 180 | ||
181 | return min_t(u32, rx_left, dw_readw(dws, DW_SPI_RXFLR)); | 181 | return min_t(u32, rx_left, dw_readl(dws, DW_SPI_RXFLR)); |
182 | } | 182 | } |
183 | 183 | ||
184 | static void dw_writer(struct dw_spi *dws) | 184 | static void dw_writer(struct dw_spi *dws) |
@@ -194,7 +194,7 @@ static void dw_writer(struct dw_spi *dws) | |||
194 | else | 194 | else |
195 | txw = *(u16 *)(dws->tx); | 195 | txw = *(u16 *)(dws->tx); |
196 | } | 196 | } |
197 | dw_writew(dws, DW_SPI_DR, txw); | 197 | dw_writel(dws, DW_SPI_DR, txw); |
198 | dws->tx += dws->n_bytes; | 198 | dws->tx += dws->n_bytes; |
199 | } | 199 | } |
200 | } | 200 | } |
@@ -205,7 +205,7 @@ static void dw_reader(struct dw_spi *dws) | |||
205 | u16 rxw; | 205 | u16 rxw; |
206 | 206 | ||
207 | while (max--) { | 207 | while (max--) { |
208 | rxw = dw_readw(dws, DW_SPI_DR); | 208 | rxw = dw_readl(dws, DW_SPI_DR); |
209 | /* Care rx only if the transfer's original "rx" is not null */ | 209 | /* Care rx only if the transfer's original "rx" is not null */ |
210 | if (dws->rx_end - dws->len) { | 210 | if (dws->rx_end - dws->len) { |
211 | if (dws->n_bytes == 1) | 211 | if (dws->n_bytes == 1) |
@@ -228,11 +228,11 @@ static void int_error_stop(struct dw_spi *dws, const char *msg) | |||
228 | 228 | ||
229 | static irqreturn_t interrupt_transfer(struct dw_spi *dws) | 229 | static irqreturn_t interrupt_transfer(struct dw_spi *dws) |
230 | { | 230 | { |
231 | u16 irq_status = dw_readw(dws, DW_SPI_ISR); | 231 | u16 irq_status = dw_readl(dws, DW_SPI_ISR); |
232 | 232 | ||
233 | /* Error handling */ | 233 | /* Error handling */ |
234 | if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) { | 234 | if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) { |
235 | dw_readw(dws, DW_SPI_ICR); | 235 | dw_readl(dws, DW_SPI_ICR); |
236 | int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun"); | 236 | int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun"); |
237 | return IRQ_HANDLED; | 237 | return IRQ_HANDLED; |
238 | } | 238 | } |
@@ -257,7 +257,7 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id) | |||
257 | { | 257 | { |
258 | struct spi_master *master = dev_id; | 258 | struct spi_master *master = dev_id; |
259 | struct dw_spi *dws = spi_master_get_devdata(master); | 259 | struct dw_spi *dws = spi_master_get_devdata(master); |
260 | u16 irq_status = dw_readw(dws, DW_SPI_ISR) & 0x3f; | 260 | u16 irq_status = dw_readl(dws, DW_SPI_ISR) & 0x3f; |
261 | 261 | ||
262 | if (!irq_status) | 262 | if (!irq_status) |
263 | return IRQ_NONE; | 263 | return IRQ_NONE; |
@@ -354,7 +354,7 @@ static int dw_spi_transfer_one(struct spi_master *master, | |||
354 | cr0 |= (chip->tmode << SPI_TMOD_OFFSET); | 354 | cr0 |= (chip->tmode << SPI_TMOD_OFFSET); |
355 | } | 355 | } |
356 | 356 | ||
357 | dw_writew(dws, DW_SPI_CTRL0, cr0); | 357 | dw_writel(dws, DW_SPI_CTRL0, cr0); |
358 | 358 | ||
359 | /* Check if current transfer is a DMA transaction */ | 359 | /* Check if current transfer is a DMA transaction */ |
360 | if (master->can_dma && master->can_dma(master, spi, transfer)) | 360 | if (master->can_dma && master->can_dma(master, spi, transfer)) |
@@ -375,7 +375,7 @@ static int dw_spi_transfer_one(struct spi_master *master, | |||
375 | } | 375 | } |
376 | } else if (!chip->poll_mode) { | 376 | } else if (!chip->poll_mode) { |
377 | txlevel = min_t(u16, dws->fifo_len / 2, dws->len / dws->n_bytes); | 377 | txlevel = min_t(u16, dws->fifo_len / 2, dws->len / dws->n_bytes); |
378 | dw_writew(dws, DW_SPI_TXFLTR, txlevel); | 378 | dw_writel(dws, DW_SPI_TXFLTR, txlevel); |
379 | 379 | ||
380 | /* Set the interrupt mask */ | 380 | /* Set the interrupt mask */ |
381 | imask |= SPI_INT_TXEI | SPI_INT_TXOI | | 381 | imask |= SPI_INT_TXEI | SPI_INT_TXOI | |
@@ -499,11 +499,11 @@ static void spi_hw_init(struct device *dev, struct dw_spi *dws) | |||
499 | u32 fifo; | 499 | u32 fifo; |
500 | 500 | ||
501 | for (fifo = 1; fifo < 256; fifo++) { | 501 | for (fifo = 1; fifo < 256; fifo++) { |
502 | dw_writew(dws, DW_SPI_TXFLTR, fifo); | 502 | dw_writel(dws, DW_SPI_TXFLTR, fifo); |
503 | if (fifo != dw_readw(dws, DW_SPI_TXFLTR)) | 503 | if (fifo != dw_readl(dws, DW_SPI_TXFLTR)) |
504 | break; | 504 | break; |
505 | } | 505 | } |
506 | dw_writew(dws, DW_SPI_TXFLTR, 0); | 506 | dw_writel(dws, DW_SPI_TXFLTR, 0); |
507 | 507 | ||
508 | dws->fifo_len = (fifo == 1) ? 0 : fifo; | 508 | dws->fifo_len = (fifo == 1) ? 0 : fifo; |
509 | dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len); | 509 | dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len); |
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h index 41f77e2ccf63..6c91391c1a4f 100644 --- a/drivers/spi/spi-dw.h +++ b/drivers/spi/spi-dw.h | |||
@@ -150,16 +150,6 @@ static inline void dw_writel(struct dw_spi *dws, u32 offset, u32 val) | |||
150 | __raw_writel(val, dws->regs + offset); | 150 | __raw_writel(val, dws->regs + offset); |
151 | } | 151 | } |
152 | 152 | ||
153 | static inline u16 dw_readw(struct dw_spi *dws, u32 offset) | ||
154 | { | ||
155 | return __raw_readw(dws->regs + offset); | ||
156 | } | ||
157 | |||
158 | static inline void dw_writew(struct dw_spi *dws, u32 offset, u16 val) | ||
159 | { | ||
160 | __raw_writew(val, dws->regs + offset); | ||
161 | } | ||
162 | |||
163 | static inline void spi_enable_chip(struct dw_spi *dws, int enable) | 153 | static inline void spi_enable_chip(struct dw_spi *dws, int enable) |
164 | { | 154 | { |
165 | dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0)); | 155 | dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0)); |