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 | |
| 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
| -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 | ||||
| -rw-r--r-- | include/linux/spi/spi.h | 8 |
10 files changed, 100 insertions, 163 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 | ||
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index b4d7710bc38d..bb4f5fbbbd8e 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h | |||
| @@ -581,7 +581,7 @@ extern int spi_bus_unlock(struct spi_master *master); | |||
| 581 | * Callable only from contexts that can sleep. | 581 | * Callable only from contexts that can sleep. |
| 582 | */ | 582 | */ |
| 583 | static inline int | 583 | static inline int |
| 584 | spi_write(struct spi_device *spi, const u8 *buf, size_t len) | 584 | spi_write(struct spi_device *spi, const void *buf, size_t len) |
| 585 | { | 585 | { |
| 586 | struct spi_transfer t = { | 586 | struct spi_transfer t = { |
| 587 | .tx_buf = buf, | 587 | .tx_buf = buf, |
| @@ -605,7 +605,7 @@ spi_write(struct spi_device *spi, const u8 *buf, size_t len) | |||
| 605 | * Callable only from contexts that can sleep. | 605 | * Callable only from contexts that can sleep. |
| 606 | */ | 606 | */ |
| 607 | static inline int | 607 | static inline int |
| 608 | spi_read(struct spi_device *spi, u8 *buf, size_t len) | 608 | spi_read(struct spi_device *spi, void *buf, size_t len) |
| 609 | { | 609 | { |
| 610 | struct spi_transfer t = { | 610 | struct spi_transfer t = { |
| 611 | .rx_buf = buf, | 611 | .rx_buf = buf, |
| @@ -620,8 +620,8 @@ spi_read(struct spi_device *spi, u8 *buf, size_t len) | |||
| 620 | 620 | ||
| 621 | /* this copies txbuf and rxbuf data; for small transfers only! */ | 621 | /* this copies txbuf and rxbuf data; for small transfers only! */ |
| 622 | extern int spi_write_then_read(struct spi_device *spi, | 622 | extern int spi_write_then_read(struct spi_device *spi, |
| 623 | const u8 *txbuf, unsigned n_tx, | 623 | const void *txbuf, unsigned n_tx, |
| 624 | u8 *rxbuf, unsigned n_rx); | 624 | void *rxbuf, unsigned n_rx); |
| 625 | 625 | ||
| 626 | /** | 626 | /** |
| 627 | * spi_w8r8 - SPI synchronous 8 bit write followed by 8 bit read | 627 | * spi_w8r8 - SPI synchronous 8 bit write followed by 8 bit read |
