diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-26 15:13:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-26 15:13:22 -0400 |
commit | 20e0ec119b2c6cc412addefbe169f4f5e38701e8 (patch) | |
tree | fd8b882f4027f1a60857cbcd3bb85a83261db07f /drivers/spi | |
parent | 829ae2732998e628d762b97627e4e5cc6c1b5625 (diff) | |
parent | 43c640157d4366a3ea9ba01f903ea892f46376ee (diff) |
Merge branch 'spi/next' of git://git.secretlab.ca/git/linux-2.6
* 'spi/next' of git://git.secretlab.ca/git/linux-2.6:
spi/amba-pl022: work in polling or interrupt mode if pl022_dma_probe fails
spi/spi_s3c24xx: Use spi_bitbang_stop instead of spi_unregister_master in s3c24xx_spi_remove
spi/spi_nuc900: Use spi_bitbang_stop instead of spi_unregister_master in nuc900_spi_remove
spi/spi_tegra: use spi_unregister_master() instead of spi_master_put()
spi/spi_sh: use spi_unregister_master instead of spi_master_put in remove path
spi: Use void pointers for data in simple SPI I/O operations
spi/pl022: use cpu_relax in the busy loop
spi/pl022: mark driver non-experimental
spi/pl022: timeout on polled transfer v2
spi/dw_spi: improve the interrupt mode with the batch ops
spi/dw_spi: change poll mode transfer from byte ops to batch ops
spi/dw_spi: remove the un-necessary flush()
spi/dw_spi: unify the low level read/write routines
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/Kconfig | 4 | ||||
-rw-r--r-- | drivers/spi/amba-pl022.c | 35 | ||||
-rw-r--r-- | drivers/spi/dw_spi.c | 202 | ||||
-rw-r--r-- | drivers/spi/dw_spi.h | 2 | ||||
-rw-r--r-- | drivers/spi/spi.c | 4 | ||||
-rw-r--r-- | drivers/spi/spi_nuc900.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi_s3c24xx.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi_sh.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi_tegra.c | 2 |
9 files changed, 96 insertions, 159 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index fc14b8dea0d7..fbd96b29530d 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -271,8 +271,8 @@ config SPI_ORION | |||
271 | This enables using the SPI master controller on the Orion chips. | 271 | This enables using the SPI master controller on the Orion chips. |
272 | 272 | ||
273 | config SPI_PL022 | 273 | config SPI_PL022 |
274 | tristate "ARM AMBA PL022 SSP controller (EXPERIMENTAL)" | 274 | tristate "ARM AMBA PL022 SSP controller" |
275 | depends on ARM_AMBA && EXPERIMENTAL | 275 | depends on ARM_AMBA |
276 | default y if MACH_U300 | 276 | default y if MACH_U300 |
277 | default y if ARCH_REALVIEW | 277 | default y if ARCH_REALVIEW |
278 | default y if INTEGRATOR_IMPD1 | 278 | default y if INTEGRATOR_IMPD1 |
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index 08de58e7f59f..6a9e58dd36c7 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c | |||
@@ -24,11 +24,6 @@ | |||
24 | * GNU General Public License for more details. | 24 | * GNU General Public License for more details. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | /* | ||
28 | * TODO: | ||
29 | * - add timeout on polled transfers | ||
30 | */ | ||
31 | |||
32 | #include <linux/init.h> | 27 | #include <linux/init.h> |
33 | #include <linux/module.h> | 28 | #include <linux/module.h> |
34 | #include <linux/device.h> | 29 | #include <linux/device.h> |
@@ -287,6 +282,8 @@ | |||
287 | 282 | ||
288 | #define CLEAR_ALL_INTERRUPTS 0x3 | 283 | #define CLEAR_ALL_INTERRUPTS 0x3 |
289 | 284 | ||
285 | #define SPI_POLLING_TIMEOUT 1000 | ||
286 | |||
290 | 287 | ||
291 | /* | 288 | /* |
292 | * The type of reading going on on this chip | 289 | * The type of reading going on on this chip |
@@ -1063,7 +1060,7 @@ static int __init pl022_dma_probe(struct pl022 *pl022) | |||
1063 | pl022->master_info->dma_filter, | 1060 | pl022->master_info->dma_filter, |
1064 | pl022->master_info->dma_rx_param); | 1061 | pl022->master_info->dma_rx_param); |
1065 | if (!pl022->dma_rx_channel) { | 1062 | if (!pl022->dma_rx_channel) { |
1066 | dev_err(&pl022->adev->dev, "no RX DMA channel!\n"); | 1063 | dev_dbg(&pl022->adev->dev, "no RX DMA channel!\n"); |
1067 | goto err_no_rxchan; | 1064 | goto err_no_rxchan; |
1068 | } | 1065 | } |
1069 | 1066 | ||
@@ -1071,13 +1068,13 @@ static int __init pl022_dma_probe(struct pl022 *pl022) | |||
1071 | pl022->master_info->dma_filter, | 1068 | pl022->master_info->dma_filter, |
1072 | pl022->master_info->dma_tx_param); | 1069 | pl022->master_info->dma_tx_param); |
1073 | if (!pl022->dma_tx_channel) { | 1070 | if (!pl022->dma_tx_channel) { |
1074 | dev_err(&pl022->adev->dev, "no TX DMA channel!\n"); | 1071 | dev_dbg(&pl022->adev->dev, "no TX DMA channel!\n"); |
1075 | goto err_no_txchan; | 1072 | goto err_no_txchan; |
1076 | } | 1073 | } |
1077 | 1074 | ||
1078 | pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL); | 1075 | pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL); |
1079 | if (!pl022->dummypage) { | 1076 | if (!pl022->dummypage) { |
1080 | dev_err(&pl022->adev->dev, "no DMA dummypage!\n"); | 1077 | dev_dbg(&pl022->adev->dev, "no DMA dummypage!\n"); |
1081 | goto err_no_dummypage; | 1078 | goto err_no_dummypage; |
1082 | } | 1079 | } |
1083 | 1080 | ||
@@ -1093,6 +1090,8 @@ err_no_txchan: | |||
1093 | dma_release_channel(pl022->dma_rx_channel); | 1090 | dma_release_channel(pl022->dma_rx_channel); |
1094 | pl022->dma_rx_channel = NULL; | 1091 | pl022->dma_rx_channel = NULL; |
1095 | err_no_rxchan: | 1092 | err_no_rxchan: |
1093 | dev_err(&pl022->adev->dev, | ||
1094 | "Failed to work in dma mode, work without dma!\n"); | ||
1096 | return -ENODEV; | 1095 | return -ENODEV; |
1097 | } | 1096 | } |
1098 | 1097 | ||
@@ -1378,6 +1377,7 @@ static void do_polling_transfer(struct pl022 *pl022) | |||
1378 | struct spi_transfer *transfer = NULL; | 1377 | struct spi_transfer *transfer = NULL; |
1379 | struct spi_transfer *previous = NULL; | 1378 | struct spi_transfer *previous = NULL; |
1380 | struct chip_data *chip; | 1379 | struct chip_data *chip; |
1380 | unsigned long time, timeout; | ||
1381 | 1381 | ||
1382 | chip = pl022->cur_chip; | 1382 | chip = pl022->cur_chip; |
1383 | message = pl022->cur_msg; | 1383 | message = pl022->cur_msg; |
@@ -1415,9 +1415,19 @@ static void do_polling_transfer(struct pl022 *pl022) | |||
1415 | SSP_CR1(pl022->virtbase)); | 1415 | SSP_CR1(pl022->virtbase)); |
1416 | 1416 | ||
1417 | dev_dbg(&pl022->adev->dev, "polling transfer ongoing ...\n"); | 1417 | dev_dbg(&pl022->adev->dev, "polling transfer ongoing ...\n"); |
1418 | /* FIXME: insert a timeout so we don't hang here indefinitely */ | 1418 | |
1419 | while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) | 1419 | timeout = jiffies + msecs_to_jiffies(SPI_POLLING_TIMEOUT); |
1420 | while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) { | ||
1421 | time = jiffies; | ||
1420 | readwriter(pl022); | 1422 | readwriter(pl022); |
1423 | if (time_after(time, timeout)) { | ||
1424 | dev_warn(&pl022->adev->dev, | ||
1425 | "%s: timeout!\n", __func__); | ||
1426 | message->state = STATE_ERROR; | ||
1427 | goto out; | ||
1428 | } | ||
1429 | cpu_relax(); | ||
1430 | } | ||
1421 | 1431 | ||
1422 | /* Update total byte transferred */ | 1432 | /* Update total byte transferred */ |
1423 | message->actual_length += pl022->cur_transfer->len; | 1433 | message->actual_length += pl022->cur_transfer->len; |
@@ -1426,7 +1436,7 @@ static void do_polling_transfer(struct pl022 *pl022) | |||
1426 | /* Move to next transfer */ | 1436 | /* Move to next transfer */ |
1427 | message->state = next_transfer(pl022); | 1437 | message->state = next_transfer(pl022); |
1428 | } | 1438 | } |
1429 | 1439 | out: | |
1430 | /* Handle end of message */ | 1440 | /* Handle end of message */ |
1431 | if (message->state == STATE_DONE) | 1441 | if (message->state == STATE_DONE) |
1432 | message->status = 0; | 1442 | message->status = 0; |
@@ -2107,7 +2117,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) | |||
2107 | if (platform_info->enable_dma) { | 2117 | if (platform_info->enable_dma) { |
2108 | status = pl022_dma_probe(pl022); | 2118 | status = pl022_dma_probe(pl022); |
2109 | if (status != 0) | 2119 | if (status != 0) |
2110 | goto err_no_dma; | 2120 | platform_info->enable_dma = 0; |
2111 | } | 2121 | } |
2112 | 2122 | ||
2113 | /* Initialize and start queue */ | 2123 | /* Initialize and start queue */ |
@@ -2143,7 +2153,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) | |||
2143 | err_init_queue: | 2153 | err_init_queue: |
2144 | destroy_queue(pl022); | 2154 | destroy_queue(pl022); |
2145 | pl022_dma_remove(pl022); | 2155 | pl022_dma_remove(pl022); |
2146 | err_no_dma: | ||
2147 | free_irq(adev->irq[0], pl022); | 2156 | free_irq(adev->irq[0], pl022); |
2148 | err_no_irq: | 2157 | err_no_irq: |
2149 | clk_put(pl022->clk); | 2158 | clk_put(pl022->clk); |
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c index 871e337c917f..919fa9d9e16b 100644 --- a/drivers/spi/dw_spi.c +++ b/drivers/spi/dw_spi.c | |||
@@ -58,8 +58,6 @@ struct chip_data { | |||
58 | u8 bits_per_word; | 58 | u8 bits_per_word; |
59 | u16 clk_div; /* baud rate divider */ | 59 | u16 clk_div; /* baud rate divider */ |
60 | u32 speed_hz; /* baud rate */ | 60 | u32 speed_hz; /* baud rate */ |
61 | int (*write)(struct dw_spi *dws); | ||
62 | int (*read)(struct dw_spi *dws); | ||
63 | void (*cs_control)(u32 command); | 61 | void (*cs_control)(u32 command); |
64 | }; | 62 | }; |
65 | 63 | ||
@@ -162,107 +160,70 @@ static inline void mrst_spi_debugfs_remove(struct dw_spi *dws) | |||
162 | } | 160 | } |
163 | #endif /* CONFIG_DEBUG_FS */ | 161 | #endif /* CONFIG_DEBUG_FS */ |
164 | 162 | ||
165 | static void wait_till_not_busy(struct dw_spi *dws) | 163 | /* Return the max entries we can fill into tx fifo */ |
164 | static inline u32 tx_max(struct dw_spi *dws) | ||
166 | { | 165 | { |
167 | unsigned long end = jiffies + 1 + usecs_to_jiffies(5000); | 166 | u32 tx_left, tx_room, rxtx_gap; |
168 | 167 | ||
169 | while (time_before(jiffies, end)) { | 168 | tx_left = (dws->tx_end - dws->tx) / dws->n_bytes; |
170 | if (!(dw_readw(dws, sr) & SR_BUSY)) | 169 | tx_room = dws->fifo_len - dw_readw(dws, txflr); |
171 | return; | ||
172 | cpu_relax(); | ||
173 | } | ||
174 | dev_err(&dws->master->dev, | ||
175 | "DW SPI: Status keeps busy for 5000us after a read/write!\n"); | ||
176 | } | ||
177 | |||
178 | static void flush(struct dw_spi *dws) | ||
179 | { | ||
180 | while (dw_readw(dws, sr) & SR_RF_NOT_EMPT) { | ||
181 | dw_readw(dws, dr); | ||
182 | cpu_relax(); | ||
183 | } | ||
184 | |||
185 | wait_till_not_busy(dws); | ||
186 | } | ||
187 | |||
188 | static int null_writer(struct dw_spi *dws) | ||
189 | { | ||
190 | u8 n_bytes = dws->n_bytes; | ||
191 | 170 | ||
192 | if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL) | 171 | /* |
193 | || (dws->tx == dws->tx_end)) | 172 | * Another concern is about the tx/rx mismatch, we |
194 | return 0; | 173 | * though to use (dws->fifo_len - rxflr - txflr) as |
195 | dw_writew(dws, dr, 0); | 174 | * one maximum value for tx, but it doesn't cover the |
196 | dws->tx += n_bytes; | 175 | * data which is out of tx/rx fifo and inside the |
176 | * shift registers. So a control from sw point of | ||
177 | * view is taken. | ||
178 | */ | ||
179 | rxtx_gap = ((dws->rx_end - dws->rx) - (dws->tx_end - dws->tx)) | ||
180 | / dws->n_bytes; | ||
197 | 181 | ||
198 | wait_till_not_busy(dws); | 182 | return min3(tx_left, tx_room, (u32) (dws->fifo_len - rxtx_gap)); |
199 | return 1; | ||
200 | } | 183 | } |
201 | 184 | ||
202 | static int null_reader(struct dw_spi *dws) | 185 | /* Return the max entries we should read out of rx fifo */ |
186 | static inline u32 rx_max(struct dw_spi *dws) | ||
203 | { | 187 | { |
204 | u8 n_bytes = dws->n_bytes; | 188 | u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes; |
205 | 189 | ||
206 | while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT) | 190 | return min(rx_left, (u32)dw_readw(dws, rxflr)); |
207 | && (dws->rx < dws->rx_end)) { | ||
208 | dw_readw(dws, dr); | ||
209 | dws->rx += n_bytes; | ||
210 | } | ||
211 | wait_till_not_busy(dws); | ||
212 | return dws->rx == dws->rx_end; | ||
213 | } | 191 | } |
214 | 192 | ||
215 | static int u8_writer(struct dw_spi *dws) | 193 | static void dw_writer(struct dw_spi *dws) |
216 | { | 194 | { |
217 | if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL) | 195 | u32 max = tx_max(dws); |
218 | || (dws->tx == dws->tx_end)) | 196 | u16 txw = 0; |
219 | return 0; | ||
220 | 197 | ||
221 | dw_writew(dws, dr, *(u8 *)(dws->tx)); | 198 | while (max--) { |
222 | ++dws->tx; | 199 | /* Set the tx word if the transfer's original "tx" is not null */ |
223 | 200 | if (dws->tx_end - dws->len) { | |
224 | wait_till_not_busy(dws); | 201 | if (dws->n_bytes == 1) |
225 | return 1; | 202 | txw = *(u8 *)(dws->tx); |
226 | } | 203 | else |
227 | 204 | txw = *(u16 *)(dws->tx); | |
228 | static int u8_reader(struct dw_spi *dws) | 205 | } |
229 | { | 206 | dw_writew(dws, dr, txw); |
230 | while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT) | 207 | dws->tx += dws->n_bytes; |
231 | && (dws->rx < dws->rx_end)) { | ||
232 | *(u8 *)(dws->rx) = dw_readw(dws, dr); | ||
233 | ++dws->rx; | ||
234 | } | 208 | } |
235 | |||
236 | wait_till_not_busy(dws); | ||
237 | return dws->rx == dws->rx_end; | ||
238 | } | 209 | } |
239 | 210 | ||
240 | static int u16_writer(struct dw_spi *dws) | 211 | static void dw_reader(struct dw_spi *dws) |
241 | { | 212 | { |
242 | if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL) | 213 | u32 max = rx_max(dws); |
243 | || (dws->tx == dws->tx_end)) | 214 | u16 rxw; |
244 | return 0; | ||
245 | 215 | ||
246 | dw_writew(dws, dr, *(u16 *)(dws->tx)); | 216 | while (max--) { |
247 | dws->tx += 2; | 217 | rxw = dw_readw(dws, dr); |
248 | 218 | /* Care rx only if the transfer's original "rx" is not null */ | |
249 | wait_till_not_busy(dws); | 219 | if (dws->rx_end - dws->len) { |
250 | return 1; | 220 | if (dws->n_bytes == 1) |
251 | } | 221 | *(u8 *)(dws->rx) = rxw; |
252 | 222 | else | |
253 | static int u16_reader(struct dw_spi *dws) | 223 | *(u16 *)(dws->rx) = rxw; |
254 | { | 224 | } |
255 | u16 temp; | 225 | dws->rx += dws->n_bytes; |
256 | |||
257 | while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT) | ||
258 | && (dws->rx < dws->rx_end)) { | ||
259 | temp = dw_readw(dws, dr); | ||
260 | *(u16 *)(dws->rx) = temp; | ||
261 | dws->rx += 2; | ||
262 | } | 226 | } |
263 | |||
264 | wait_till_not_busy(dws); | ||
265 | return dws->rx == dws->rx_end; | ||
266 | } | 227 | } |
267 | 228 | ||
268 | static void *next_transfer(struct dw_spi *dws) | 229 | static void *next_transfer(struct dw_spi *dws) |
@@ -334,8 +295,7 @@ static void giveback(struct dw_spi *dws) | |||
334 | 295 | ||
335 | static void int_error_stop(struct dw_spi *dws, const char *msg) | 296 | static void int_error_stop(struct dw_spi *dws, const char *msg) |
336 | { | 297 | { |
337 | /* Stop and reset hw */ | 298 | /* Stop the hw */ |
338 | flush(dws); | ||
339 | spi_enable_chip(dws, 0); | 299 | spi_enable_chip(dws, 0); |
340 | 300 | ||
341 | dev_err(&dws->master->dev, "%s\n", msg); | 301 | dev_err(&dws->master->dev, "%s\n", msg); |
@@ -362,35 +322,28 @@ EXPORT_SYMBOL_GPL(dw_spi_xfer_done); | |||
362 | 322 | ||
363 | static irqreturn_t interrupt_transfer(struct dw_spi *dws) | 323 | static irqreturn_t interrupt_transfer(struct dw_spi *dws) |
364 | { | 324 | { |
365 | u16 irq_status, irq_mask = 0x3f; | 325 | u16 irq_status = dw_readw(dws, isr); |
366 | u32 int_level = dws->fifo_len / 2; | ||
367 | u32 left; | ||
368 | 326 | ||
369 | irq_status = dw_readw(dws, isr) & irq_mask; | ||
370 | /* Error handling */ | 327 | /* Error handling */ |
371 | if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) { | 328 | if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) { |
372 | dw_readw(dws, txoicr); | 329 | dw_readw(dws, txoicr); |
373 | dw_readw(dws, rxoicr); | 330 | dw_readw(dws, rxoicr); |
374 | dw_readw(dws, rxuicr); | 331 | dw_readw(dws, rxuicr); |
375 | int_error_stop(dws, "interrupt_transfer: fifo overrun"); | 332 | int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun"); |
376 | return IRQ_HANDLED; | 333 | return IRQ_HANDLED; |
377 | } | 334 | } |
378 | 335 | ||
336 | dw_reader(dws); | ||
337 | if (dws->rx_end == dws->rx) { | ||
338 | spi_mask_intr(dws, SPI_INT_TXEI); | ||
339 | dw_spi_xfer_done(dws); | ||
340 | return IRQ_HANDLED; | ||
341 | } | ||
379 | if (irq_status & SPI_INT_TXEI) { | 342 | if (irq_status & SPI_INT_TXEI) { |
380 | spi_mask_intr(dws, SPI_INT_TXEI); | 343 | spi_mask_intr(dws, SPI_INT_TXEI); |
381 | 344 | dw_writer(dws); | |
382 | left = (dws->tx_end - dws->tx) / dws->n_bytes; | 345 | /* Enable TX irq always, it will be disabled when RX finished */ |
383 | left = (left > int_level) ? int_level : left; | 346 | spi_umask_intr(dws, SPI_INT_TXEI); |
384 | |||
385 | while (left--) | ||
386 | dws->write(dws); | ||
387 | dws->read(dws); | ||
388 | |||
389 | /* Re-enable the IRQ if there is still data left to tx */ | ||
390 | if (dws->tx_end > dws->tx) | ||
391 | spi_umask_intr(dws, SPI_INT_TXEI); | ||
392 | else | ||
393 | dw_spi_xfer_done(dws); | ||
394 | } | 347 | } |
395 | 348 | ||
396 | return IRQ_HANDLED; | 349 | return IRQ_HANDLED; |
@@ -399,15 +352,13 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws) | |||
399 | static irqreturn_t dw_spi_irq(int irq, void *dev_id) | 352 | static irqreturn_t dw_spi_irq(int irq, void *dev_id) |
400 | { | 353 | { |
401 | struct dw_spi *dws = dev_id; | 354 | struct dw_spi *dws = dev_id; |
402 | u16 irq_status, irq_mask = 0x3f; | 355 | u16 irq_status = dw_readw(dws, isr) & 0x3f; |
403 | 356 | ||
404 | irq_status = dw_readw(dws, isr) & irq_mask; | ||
405 | if (!irq_status) | 357 | if (!irq_status) |
406 | return IRQ_NONE; | 358 | return IRQ_NONE; |
407 | 359 | ||
408 | if (!dws->cur_msg) { | 360 | if (!dws->cur_msg) { |
409 | spi_mask_intr(dws, SPI_INT_TXEI); | 361 | spi_mask_intr(dws, SPI_INT_TXEI); |
410 | /* Never fail */ | ||
411 | return IRQ_HANDLED; | 362 | return IRQ_HANDLED; |
412 | } | 363 | } |
413 | 364 | ||
@@ -417,13 +368,11 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id) | |||
417 | /* Must be called inside pump_transfers() */ | 368 | /* Must be called inside pump_transfers() */ |
418 | static void poll_transfer(struct dw_spi *dws) | 369 | static void poll_transfer(struct dw_spi *dws) |
419 | { | 370 | { |
420 | while (dws->write(dws)) | 371 | do { |
421 | dws->read(dws); | 372 | dw_writer(dws); |
422 | /* | 373 | dw_reader(dws); |
423 | * There is a possibility that the last word of a transaction | 374 | cpu_relax(); |
424 | * will be lost if data is not ready. Re-read to solve this issue. | 375 | } while (dws->rx_end > dws->rx); |
425 | */ | ||
426 | dws->read(dws); | ||
427 | 376 | ||
428 | dw_spi_xfer_done(dws); | 377 | dw_spi_xfer_done(dws); |
429 | } | 378 | } |
@@ -483,8 +432,6 @@ static void pump_transfers(unsigned long data) | |||
483 | dws->tx_end = dws->tx + transfer->len; | 432 | dws->tx_end = dws->tx + transfer->len; |
484 | dws->rx = transfer->rx_buf; | 433 | dws->rx = transfer->rx_buf; |
485 | dws->rx_end = dws->rx + transfer->len; | 434 | dws->rx_end = dws->rx + transfer->len; |
486 | dws->write = dws->tx ? chip->write : null_writer; | ||
487 | dws->read = dws->rx ? chip->read : null_reader; | ||
488 | dws->cs_change = transfer->cs_change; | 435 | dws->cs_change = transfer->cs_change; |
489 | dws->len = dws->cur_transfer->len; | 436 | dws->len = dws->cur_transfer->len; |
490 | if (chip != dws->prev_chip) | 437 | if (chip != dws->prev_chip) |
@@ -518,20 +465,8 @@ static void pump_transfers(unsigned long data) | |||
518 | 465 | ||
519 | switch (bits) { | 466 | switch (bits) { |
520 | case 8: | 467 | case 8: |
521 | dws->n_bytes = 1; | ||
522 | dws->dma_width = 1; | ||
523 | dws->read = (dws->read != null_reader) ? | ||
524 | u8_reader : null_reader; | ||
525 | dws->write = (dws->write != null_writer) ? | ||
526 | u8_writer : null_writer; | ||
527 | break; | ||
528 | case 16: | 468 | case 16: |
529 | dws->n_bytes = 2; | 469 | dws->n_bytes = dws->dma_width = bits >> 3; |
530 | dws->dma_width = 2; | ||
531 | dws->read = (dws->read != null_reader) ? | ||
532 | u16_reader : null_reader; | ||
533 | dws->write = (dws->write != null_writer) ? | ||
534 | u16_writer : null_writer; | ||
535 | break; | 470 | break; |
536 | default: | 471 | default: |
537 | printk(KERN_ERR "MRST SPI0: unsupported bits:" | 472 | printk(KERN_ERR "MRST SPI0: unsupported bits:" |
@@ -575,7 +510,7 @@ static void pump_transfers(unsigned long data) | |||
575 | txint_level = dws->fifo_len / 2; | 510 | txint_level = dws->fifo_len / 2; |
576 | txint_level = (templen > txint_level) ? txint_level : templen; | 511 | txint_level = (templen > txint_level) ? txint_level : templen; |
577 | 512 | ||
578 | imask |= SPI_INT_TXEI; | 513 | imask |= SPI_INT_TXEI | SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI; |
579 | dws->transfer_handler = interrupt_transfer; | 514 | dws->transfer_handler = interrupt_transfer; |
580 | } | 515 | } |
581 | 516 | ||
@@ -733,13 +668,9 @@ static int dw_spi_setup(struct spi_device *spi) | |||
733 | if (spi->bits_per_word <= 8) { | 668 | if (spi->bits_per_word <= 8) { |
734 | chip->n_bytes = 1; | 669 | chip->n_bytes = 1; |
735 | chip->dma_width = 1; | 670 | chip->dma_width = 1; |
736 | chip->read = u8_reader; | ||
737 | chip->write = u8_writer; | ||
738 | } else if (spi->bits_per_word <= 16) { | 671 | } else if (spi->bits_per_word <= 16) { |
739 | chip->n_bytes = 2; | 672 | chip->n_bytes = 2; |
740 | chip->dma_width = 2; | 673 | chip->dma_width = 2; |
741 | chip->read = u16_reader; | ||
742 | chip->write = u16_writer; | ||
743 | } else { | 674 | } else { |
744 | /* Never take >16b case for MRST SPIC */ | 675 | /* Never take >16b case for MRST SPIC */ |
745 | dev_err(&spi->dev, "invalid wordsize\n"); | 676 | dev_err(&spi->dev, "invalid wordsize\n"); |
@@ -851,7 +782,6 @@ static void spi_hw_init(struct dw_spi *dws) | |||
851 | spi_enable_chip(dws, 0); | 782 | spi_enable_chip(dws, 0); |
852 | spi_mask_intr(dws, 0xff); | 783 | spi_mask_intr(dws, 0xff); |
853 | spi_enable_chip(dws, 1); | 784 | spi_enable_chip(dws, 1); |
854 | flush(dws); | ||
855 | 785 | ||
856 | /* | 786 | /* |
857 | * Try to detect the FIFO depth if not set by interface driver, | 787 | * Try to detect the FIFO depth if not set by interface driver, |
diff --git a/drivers/spi/dw_spi.h b/drivers/spi/dw_spi.h index b23e452adaf7..7a5e78d2a5cb 100644 --- a/drivers/spi/dw_spi.h +++ b/drivers/spi/dw_spi.h | |||
@@ -137,8 +137,6 @@ struct dw_spi { | |||
137 | u8 max_bits_per_word; /* maxim is 16b */ | 137 | u8 max_bits_per_word; /* maxim is 16b */ |
138 | u32 dma_width; | 138 | u32 dma_width; |
139 | int cs_change; | 139 | int cs_change; |
140 | int (*write)(struct dw_spi *dws); | ||
141 | int (*read)(struct dw_spi *dws); | ||
142 | irqreturn_t (*transfer_handler)(struct dw_spi *dws); | 140 | irqreturn_t (*transfer_handler)(struct dw_spi *dws); |
143 | void (*cs_control)(u32 command); | 141 | void (*cs_control)(u32 command); |
144 | 142 | ||
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 82b9a428c323..2e13a14bba3f 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -1047,8 +1047,8 @@ static u8 *buf; | |||
1047 | * spi_{async,sync}() calls with dma-safe buffers. | 1047 | * spi_{async,sync}() calls with dma-safe buffers. |
1048 | */ | 1048 | */ |
1049 | int spi_write_then_read(struct spi_device *spi, | 1049 | int spi_write_then_read(struct spi_device *spi, |
1050 | const u8 *txbuf, unsigned n_tx, | 1050 | const void *txbuf, unsigned n_tx, |
1051 | u8 *rxbuf, unsigned n_rx) | 1051 | void *rxbuf, unsigned n_rx) |
1052 | { | 1052 | { |
1053 | static DEFINE_MUTEX(lock); | 1053 | static DEFINE_MUTEX(lock); |
1054 | 1054 | ||
diff --git a/drivers/spi/spi_nuc900.c b/drivers/spi/spi_nuc900.c index d5be18b3078c..3cd15f690f16 100644 --- a/drivers/spi/spi_nuc900.c +++ b/drivers/spi/spi_nuc900.c | |||
@@ -463,7 +463,7 @@ static int __devexit nuc900_spi_remove(struct platform_device *dev) | |||
463 | 463 | ||
464 | platform_set_drvdata(dev, NULL); | 464 | platform_set_drvdata(dev, NULL); |
465 | 465 | ||
466 | spi_unregister_master(hw->master); | 466 | spi_bitbang_stop(&hw->bitbang); |
467 | 467 | ||
468 | clk_disable(hw->clk); | 468 | clk_disable(hw->clk); |
469 | clk_put(hw->clk); | 469 | clk_put(hw->clk); |
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index 151a95e40653..1a5fcabfd565 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c | |||
@@ -668,7 +668,7 @@ static int __exit s3c24xx_spi_remove(struct platform_device *dev) | |||
668 | 668 | ||
669 | platform_set_drvdata(dev, NULL); | 669 | platform_set_drvdata(dev, NULL); |
670 | 670 | ||
671 | spi_unregister_master(hw->master); | 671 | spi_bitbang_stop(&hw->bitbang); |
672 | 672 | ||
673 | clk_disable(hw->clk); | 673 | clk_disable(hw->clk); |
674 | clk_put(hw->clk); | 674 | clk_put(hw->clk); |
diff --git a/drivers/spi/spi_sh.c b/drivers/spi/spi_sh.c index 869a07d375d6..9eedd71ad898 100644 --- a/drivers/spi/spi_sh.c +++ b/drivers/spi/spi_sh.c | |||
@@ -427,10 +427,10 @@ static int __devexit spi_sh_remove(struct platform_device *pdev) | |||
427 | { | 427 | { |
428 | struct spi_sh_data *ss = dev_get_drvdata(&pdev->dev); | 428 | struct spi_sh_data *ss = dev_get_drvdata(&pdev->dev); |
429 | 429 | ||
430 | spi_unregister_master(ss->master); | ||
430 | destroy_workqueue(ss->workqueue); | 431 | destroy_workqueue(ss->workqueue); |
431 | free_irq(ss->irq, ss); | 432 | free_irq(ss->irq, ss); |
432 | iounmap(ss->addr); | 433 | iounmap(ss->addr); |
433 | spi_master_put(ss->master); | ||
434 | 434 | ||
435 | return 0; | 435 | return 0; |
436 | } | 436 | } |
diff --git a/drivers/spi/spi_tegra.c b/drivers/spi/spi_tegra.c index 891e5909038c..6c3aa6ecaade 100644 --- a/drivers/spi/spi_tegra.c +++ b/drivers/spi/spi_tegra.c | |||
@@ -578,6 +578,7 @@ static int __devexit spi_tegra_remove(struct platform_device *pdev) | |||
578 | master = dev_get_drvdata(&pdev->dev); | 578 | master = dev_get_drvdata(&pdev->dev); |
579 | tspi = spi_master_get_devdata(master); | 579 | tspi = spi_master_get_devdata(master); |
580 | 580 | ||
581 | spi_unregister_master(master); | ||
581 | tegra_dma_free_channel(tspi->rx_dma); | 582 | tegra_dma_free_channel(tspi->rx_dma); |
582 | 583 | ||
583 | dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN, | 584 | dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN, |
@@ -586,7 +587,6 @@ static int __devexit spi_tegra_remove(struct platform_device *pdev) | |||
586 | clk_put(tspi->clk); | 587 | clk_put(tspi->clk); |
587 | iounmap(tspi->base); | 588 | iounmap(tspi->base); |
588 | 589 | ||
589 | spi_master_put(master); | ||
590 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 590 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
591 | release_mem_region(r->start, (r->end - r->start) + 1); | 591 | release_mem_region(r->start, (r->end - r->start) + 1); |
592 | 592 | ||