diff options
author | Feng Tang <feng.tang@intel.com> | 2011-03-30 11:09:52 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-03-30 23:31:48 -0400 |
commit | de6efe0a966cf86b3c4039a610b2d4157db707f2 (patch) | |
tree | 1eae388ca7196ea94d5480174d5f69fd1b43d588 /drivers/spi | |
parent | 0ce790e7d736cedc563e1fb4e998babf5a4dbc3d (diff) |
spi/dw_spi: unify the low level read/write routines
The original version has many duplicated codes for null/u8/u16 case,
so unify them to make it cleaner
Signed-off-by: Feng Tang <feng.tang@intel.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/dw_spi.c | 103 | ||||
-rw-r--r-- | drivers/spi/dw_spi.h | 2 |
2 files changed, 26 insertions, 79 deletions
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c index 9a6196461b27..c4fca3d9d45f 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 | ||
@@ -185,80 +183,45 @@ static void flush(struct dw_spi *dws) | |||
185 | wait_till_not_busy(dws); | 183 | wait_till_not_busy(dws); |
186 | } | 184 | } |
187 | 185 | ||
188 | static int null_writer(struct dw_spi *dws) | ||
189 | { | ||
190 | u8 n_bytes = dws->n_bytes; | ||
191 | |||
192 | if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL) | ||
193 | || (dws->tx == dws->tx_end)) | ||
194 | return 0; | ||
195 | dw_writew(dws, dr, 0); | ||
196 | dws->tx += n_bytes; | ||
197 | 186 | ||
198 | wait_till_not_busy(dws); | 187 | static int dw_writer(struct dw_spi *dws) |
199 | return 1; | ||
200 | } | ||
201 | |||
202 | static int null_reader(struct dw_spi *dws) | ||
203 | { | 188 | { |
204 | u8 n_bytes = dws->n_bytes; | 189 | u16 txw = 0; |
205 | 190 | ||
206 | while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT) | ||
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 | } | ||
214 | |||
215 | static int u8_writer(struct dw_spi *dws) | ||
216 | { | ||
217 | if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL) | 191 | if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL) |
218 | || (dws->tx == dws->tx_end)) | 192 | || (dws->tx == dws->tx_end)) |
219 | return 0; | 193 | return 0; |
220 | 194 | ||
221 | dw_writew(dws, dr, *(u8 *)(dws->tx)); | 195 | /* Set the tx word if the transfer's original "tx" is not null */ |
222 | ++dws->tx; | 196 | if (dws->tx_end - dws->len) { |
223 | 197 | if (dws->n_bytes == 1) | |
224 | wait_till_not_busy(dws); | 198 | txw = *(u8 *)(dws->tx); |
225 | return 1; | 199 | else |
226 | } | 200 | txw = *(u16 *)(dws->tx); |
227 | |||
228 | static int u8_reader(struct dw_spi *dws) | ||
229 | { | ||
230 | while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT) | ||
231 | && (dws->rx < dws->rx_end)) { | ||
232 | *(u8 *)(dws->rx) = dw_readw(dws, dr); | ||
233 | ++dws->rx; | ||
234 | } | 201 | } |
235 | 202 | ||
236 | wait_till_not_busy(dws); | 203 | dw_writew(dws, dr, txw); |
237 | return dws->rx == dws->rx_end; | 204 | dws->tx += dws->n_bytes; |
238 | } | ||
239 | |||
240 | static int u16_writer(struct dw_spi *dws) | ||
241 | { | ||
242 | if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL) | ||
243 | || (dws->tx == dws->tx_end)) | ||
244 | return 0; | ||
245 | |||
246 | dw_writew(dws, dr, *(u16 *)(dws->tx)); | ||
247 | dws->tx += 2; | ||
248 | 205 | ||
249 | wait_till_not_busy(dws); | 206 | wait_till_not_busy(dws); |
250 | return 1; | 207 | return 1; |
251 | } | 208 | } |
252 | 209 | ||
253 | static int u16_reader(struct dw_spi *dws) | 210 | static int dw_reader(struct dw_spi *dws) |
254 | { | 211 | { |
255 | u16 temp; | 212 | u16 rxw; |
256 | 213 | ||
257 | while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT) | 214 | while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT) |
258 | && (dws->rx < dws->rx_end)) { | 215 | && (dws->rx < dws->rx_end)) { |
259 | temp = dw_readw(dws, dr); | 216 | rxw = dw_readw(dws, dr); |
260 | *(u16 *)(dws->rx) = temp; | 217 | /* Care rx only if the transfer's original "rx" is not null */ |
261 | dws->rx += 2; | 218 | if (dws->rx_end - dws->len) { |
219 | if (dws->n_bytes == 1) | ||
220 | *(u8 *)(dws->rx) = rxw; | ||
221 | else | ||
222 | *(u16 *)(dws->rx) = rxw; | ||
223 | } | ||
224 | dws->rx += dws->n_bytes; | ||
262 | } | 225 | } |
263 | 226 | ||
264 | wait_till_not_busy(dws); | 227 | wait_till_not_busy(dws); |
@@ -383,8 +346,8 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws) | |||
383 | left = (left > int_level) ? int_level : left; | 346 | left = (left > int_level) ? int_level : left; |
384 | 347 | ||
385 | while (left--) | 348 | while (left--) |
386 | dws->write(dws); | 349 | dw_writer(dws); |
387 | dws->read(dws); | 350 | dw_reader(dws); |
388 | 351 | ||
389 | /* Re-enable the IRQ if there is still data left to tx */ | 352 | /* Re-enable the IRQ if there is still data left to tx */ |
390 | if (dws->tx_end > dws->tx) | 353 | if (dws->tx_end > dws->tx) |
@@ -417,13 +380,13 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id) | |||
417 | /* Must be called inside pump_transfers() */ | 380 | /* Must be called inside pump_transfers() */ |
418 | static void poll_transfer(struct dw_spi *dws) | 381 | static void poll_transfer(struct dw_spi *dws) |
419 | { | 382 | { |
420 | while (dws->write(dws)) | 383 | while (dw_writer(dws)) |
421 | dws->read(dws); | 384 | dw_reader(dws); |
422 | /* | 385 | /* |
423 | * There is a possibility that the last word of a transaction | 386 | * There is a possibility that the last word of a transaction |
424 | * will be lost if data is not ready. Re-read to solve this issue. | 387 | * will be lost if data is not ready. Re-read to solve this issue. |
425 | */ | 388 | */ |
426 | dws->read(dws); | 389 | dw_reader(dws); |
427 | 390 | ||
428 | dw_spi_xfer_done(dws); | 391 | dw_spi_xfer_done(dws); |
429 | } | 392 | } |
@@ -483,8 +446,6 @@ static void pump_transfers(unsigned long data) | |||
483 | dws->tx_end = dws->tx + transfer->len; | 446 | dws->tx_end = dws->tx + transfer->len; |
484 | dws->rx = transfer->rx_buf; | 447 | dws->rx = transfer->rx_buf; |
485 | dws->rx_end = dws->rx + transfer->len; | 448 | 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; | 449 | dws->cs_change = transfer->cs_change; |
489 | dws->len = dws->cur_transfer->len; | 450 | dws->len = dws->cur_transfer->len; |
490 | if (chip != dws->prev_chip) | 451 | if (chip != dws->prev_chip) |
@@ -520,18 +481,10 @@ static void pump_transfers(unsigned long data) | |||
520 | case 8: | 481 | case 8: |
521 | dws->n_bytes = 1; | 482 | dws->n_bytes = 1; |
522 | dws->dma_width = 1; | 483 | 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; | 484 | break; |
528 | case 16: | 485 | case 16: |
529 | dws->n_bytes = 2; | 486 | dws->n_bytes = 2; |
530 | dws->dma_width = 2; | 487 | 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; | 488 | break; |
536 | default: | 489 | default: |
537 | printk(KERN_ERR "MRST SPI0: unsupported bits:" | 490 | printk(KERN_ERR "MRST SPI0: unsupported bits:" |
@@ -733,13 +686,9 @@ static int dw_spi_setup(struct spi_device *spi) | |||
733 | if (spi->bits_per_word <= 8) { | 686 | if (spi->bits_per_word <= 8) { |
734 | chip->n_bytes = 1; | 687 | chip->n_bytes = 1; |
735 | chip->dma_width = 1; | 688 | chip->dma_width = 1; |
736 | chip->read = u8_reader; | ||
737 | chip->write = u8_writer; | ||
738 | } else if (spi->bits_per_word <= 16) { | 689 | } else if (spi->bits_per_word <= 16) { |
739 | chip->n_bytes = 2; | 690 | chip->n_bytes = 2; |
740 | chip->dma_width = 2; | 691 | chip->dma_width = 2; |
741 | chip->read = u16_reader; | ||
742 | chip->write = u16_writer; | ||
743 | } else { | 692 | } else { |
744 | /* Never take >16b case for MRST SPIC */ | 693 | /* Never take >16b case for MRST SPIC */ |
745 | dev_err(&spi->dev, "invalid wordsize\n"); | 694 | dev_err(&spi->dev, "invalid wordsize\n"); |
diff --git a/drivers/spi/dw_spi.h b/drivers/spi/dw_spi.h index fb0bce564844..d8aac1f4c546 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 | ||