diff options
author | Bryan Wu <bryan.wu@analog.com> | 2007-12-05 02:45:13 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-12-05 12:21:19 -0500 |
commit | 5fec5b5a4ec0d6d8b41c56e3cc7de41063cd4736 (patch) | |
tree | 3705b4a2000d9a2ae912a3412b4912358b850840 /drivers/spi/spi_bfin5xx.c | |
parent | cc2f81a695640dd1c0cf12b35ee303460fa6d0bc (diff) |
spi: spi_bfin cleanups, error handling
Cleanup and error handling
- add error handling in SPI bus driver with selecting clients
- use proper defines to access Blackfin MMRs
- remove useless SSYNCs
- cleaner use of portmux calls
Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/spi/spi_bfin5xx.c')
-rw-r--r-- | drivers/spi/spi_bfin5xx.c | 111 |
1 files changed, 47 insertions, 64 deletions
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index 759a6fc9b4d4..803c5b25db50 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c | |||
@@ -59,10 +59,9 @@ MODULE_LICENSE("GPL"); | |||
59 | 59 | ||
60 | #define DEFINE_SPI_REG(reg, off) \ | 60 | #define DEFINE_SPI_REG(reg, off) \ |
61 | static inline u16 read_##reg(void) \ | 61 | static inline u16 read_##reg(void) \ |
62 | { return *(volatile unsigned short*)(SPI0_REGBASE + off); } \ | 62 | { return bfin_read16(SPI0_REGBASE + off); } \ |
63 | static inline void write_##reg(u16 v) \ | 63 | static inline void write_##reg(u16 v) \ |
64 | {*(volatile unsigned short*)(SPI0_REGBASE + off) = v;\ | 64 | {bfin_write16(SPI0_REGBASE + off, v); } |
65 | SSYNC();} | ||
66 | 65 | ||
67 | DEFINE_SPI_REG(CTRL, 0x00) | 66 | DEFINE_SPI_REG(CTRL, 0x00) |
68 | DEFINE_SPI_REG(FLAG, 0x04) | 67 | DEFINE_SPI_REG(FLAG, 0x04) |
@@ -145,7 +144,6 @@ static void bfin_spi_enable(struct driver_data *drv_data) | |||
145 | 144 | ||
146 | cr = read_CTRL(); | 145 | cr = read_CTRL(); |
147 | write_CTRL(cr | BIT_CTL_ENABLE); | 146 | write_CTRL(cr | BIT_CTL_ENABLE); |
148 | SSYNC(); | ||
149 | } | 147 | } |
150 | 148 | ||
151 | static void bfin_spi_disable(struct driver_data *drv_data) | 149 | static void bfin_spi_disable(struct driver_data *drv_data) |
@@ -154,7 +152,6 @@ static void bfin_spi_disable(struct driver_data *drv_data) | |||
154 | 152 | ||
155 | cr = read_CTRL(); | 153 | cr = read_CTRL(); |
156 | write_CTRL(cr & (~BIT_CTL_ENABLE)); | 154 | write_CTRL(cr & (~BIT_CTL_ENABLE)); |
157 | SSYNC(); | ||
158 | } | 155 | } |
159 | 156 | ||
160 | /* Caculate the SPI_BAUD register value based on input HZ */ | 157 | /* Caculate the SPI_BAUD register value based on input HZ */ |
@@ -182,52 +179,44 @@ static int flush(struct driver_data *drv_data) | |||
182 | return limit; | 179 | return limit; |
183 | } | 180 | } |
184 | 181 | ||
182 | #define MAX_SPI0_SSEL 7 | ||
183 | |||
185 | /* stop controller and re-config current chip*/ | 184 | /* stop controller and re-config current chip*/ |
186 | static void restore_state(struct driver_data *drv_data) | 185 | static int restore_state(struct driver_data *drv_data) |
187 | { | 186 | { |
188 | struct chip_data *chip = drv_data->cur_chip; | 187 | struct chip_data *chip = drv_data->cur_chip; |
188 | int ret = 0; | ||
189 | u16 ssel[MAX_SPI0_SSEL] = {P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3, | ||
190 | P_SPI0_SSEL4, P_SPI0_SSEL5, | ||
191 | P_SPI0_SSEL6, P_SPI0_SSEL7,}; | ||
189 | 192 | ||
190 | /* Clear status and disable clock */ | 193 | /* Clear status and disable clock */ |
191 | write_STAT(BIT_STAT_CLR); | 194 | write_STAT(BIT_STAT_CLR); |
192 | bfin_spi_disable(drv_data); | 195 | bfin_spi_disable(drv_data); |
193 | dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n"); | 196 | dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n"); |
194 | 197 | ||
198 | /* Load the registers */ | ||
199 | write_CTRL(chip->ctl_reg); | ||
200 | write_BAUD(chip->baud); | ||
201 | write_FLAG(chip->flag); | ||
202 | |||
195 | if (!chip->chip_select_requested) { | 203 | if (!chip->chip_select_requested) { |
204 | int i = chip->chip_select_num; | ||
196 | 205 | ||
197 | dev_dbg(&drv_data->pdev->dev, | 206 | dev_dbg(&drv_data->pdev->dev, "chip select number is %d\n", i); |
198 | "chip select number is %d\n", chip->chip_select_num); | 207 | |
199 | 208 | if ((i > 0) && (i <= MAX_SPI0_SSEL)) | |
200 | switch (chip->chip_select_num) { | 209 | ret = peripheral_request(ssel[i-1], DRV_NAME); |
201 | case 1: | ||
202 | peripheral_request(P_SPI0_SSEL1, DRV_NAME); | ||
203 | break; | ||
204 | case 2: | ||
205 | peripheral_request(P_SPI0_SSEL2, DRV_NAME); | ||
206 | break; | ||
207 | case 3: | ||
208 | peripheral_request(P_SPI0_SSEL3, DRV_NAME); | ||
209 | break; | ||
210 | case 4: | ||
211 | peripheral_request(P_SPI0_SSEL4, DRV_NAME); | ||
212 | break; | ||
213 | case 5: | ||
214 | peripheral_request(P_SPI0_SSEL5, DRV_NAME); | ||
215 | break; | ||
216 | case 6: | ||
217 | peripheral_request(P_SPI0_SSEL6, DRV_NAME); | ||
218 | break; | ||
219 | case 7: | ||
220 | peripheral_request(P_SPI0_SSEL7, DRV_NAME); | ||
221 | break; | ||
222 | } | ||
223 | 210 | ||
224 | chip->chip_select_requested = 1; | 211 | chip->chip_select_requested = 1; |
225 | } | 212 | } |
226 | 213 | ||
227 | /* Load the registers */ | 214 | if (ret) |
228 | write_CTRL(chip->ctl_reg); | 215 | dev_dbg(&drv_data->pdev->dev, |
229 | write_BAUD(chip->baud); | 216 | ": request chip select number %d failed\n", |
230 | write_FLAG(chip->flag); | 217 | chip->chip_select_num); |
218 | |||
219 | return ret; | ||
231 | } | 220 | } |
232 | 221 | ||
233 | /* used to kick off transfer in rx mode */ | 222 | /* used to kick off transfer in rx mode */ |
@@ -285,7 +274,6 @@ static void u8_cs_chg_writer(struct driver_data *drv_data) | |||
285 | 274 | ||
286 | while (drv_data->tx < drv_data->tx_end) { | 275 | while (drv_data->tx < drv_data->tx_end) { |
287 | write_FLAG(chip->flag); | 276 | write_FLAG(chip->flag); |
288 | SSYNC(); | ||
289 | 277 | ||
290 | write_TDBR(*(u8 *) (drv_data->tx)); | 278 | write_TDBR(*(u8 *) (drv_data->tx)); |
291 | while (read_STAT() & BIT_STAT_TXS) | 279 | while (read_STAT() & BIT_STAT_TXS) |
@@ -293,13 +281,13 @@ static void u8_cs_chg_writer(struct driver_data *drv_data) | |||
293 | while (!(read_STAT() & BIT_STAT_SPIF)) | 281 | while (!(read_STAT() & BIT_STAT_SPIF)) |
294 | continue; | 282 | continue; |
295 | write_FLAG(0xFF00 | chip->flag); | 283 | write_FLAG(0xFF00 | chip->flag); |
296 | SSYNC(); | 284 | |
297 | if (chip->cs_chg_udelay) | 285 | if (chip->cs_chg_udelay) |
298 | udelay(chip->cs_chg_udelay); | 286 | udelay(chip->cs_chg_udelay); |
299 | ++drv_data->tx; | 287 | ++drv_data->tx; |
300 | } | 288 | } |
301 | write_FLAG(0xFF00); | 289 | write_FLAG(0xFF00); |
302 | SSYNC(); | 290 | |
303 | } | 291 | } |
304 | 292 | ||
305 | static void u8_reader(struct driver_data *drv_data) | 293 | static void u8_reader(struct driver_data *drv_data) |
@@ -331,7 +319,6 @@ static void u8_cs_chg_reader(struct driver_data *drv_data) | |||
331 | 319 | ||
332 | while (drv_data->rx < drv_data->rx_end) { | 320 | while (drv_data->rx < drv_data->rx_end) { |
333 | write_FLAG(chip->flag); | 321 | write_FLAG(chip->flag); |
334 | SSYNC(); | ||
335 | 322 | ||
336 | read_RDBR(); /* kick off */ | 323 | read_RDBR(); /* kick off */ |
337 | while (!(read_STAT() & BIT_STAT_RXS)) | 324 | while (!(read_STAT() & BIT_STAT_RXS)) |
@@ -340,13 +327,13 @@ static void u8_cs_chg_reader(struct driver_data *drv_data) | |||
340 | continue; | 327 | continue; |
341 | *(u8 *) (drv_data->rx) = read_SHAW(); | 328 | *(u8 *) (drv_data->rx) = read_SHAW(); |
342 | write_FLAG(0xFF00 | chip->flag); | 329 | write_FLAG(0xFF00 | chip->flag); |
343 | SSYNC(); | 330 | |
344 | if (chip->cs_chg_udelay) | 331 | if (chip->cs_chg_udelay) |
345 | udelay(chip->cs_chg_udelay); | 332 | udelay(chip->cs_chg_udelay); |
346 | ++drv_data->rx; | 333 | ++drv_data->rx; |
347 | } | 334 | } |
348 | write_FLAG(0xFF00); | 335 | write_FLAG(0xFF00); |
349 | SSYNC(); | 336 | |
350 | } | 337 | } |
351 | 338 | ||
352 | static void u8_duplex(struct driver_data *drv_data) | 339 | static void u8_duplex(struct driver_data *drv_data) |
@@ -370,7 +357,7 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data) | |||
370 | 357 | ||
371 | while (drv_data->rx < drv_data->rx_end) { | 358 | while (drv_data->rx < drv_data->rx_end) { |
372 | write_FLAG(chip->flag); | 359 | write_FLAG(chip->flag); |
373 | SSYNC(); | 360 | |
374 | 361 | ||
375 | write_TDBR(*(u8 *) (drv_data->tx)); | 362 | write_TDBR(*(u8 *) (drv_data->tx)); |
376 | while (!(read_STAT() & BIT_STAT_SPIF)) | 363 | while (!(read_STAT() & BIT_STAT_SPIF)) |
@@ -379,14 +366,14 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data) | |||
379 | continue; | 366 | continue; |
380 | *(u8 *) (drv_data->rx) = read_RDBR(); | 367 | *(u8 *) (drv_data->rx) = read_RDBR(); |
381 | write_FLAG(0xFF00 | chip->flag); | 368 | write_FLAG(0xFF00 | chip->flag); |
382 | SSYNC(); | 369 | |
383 | if (chip->cs_chg_udelay) | 370 | if (chip->cs_chg_udelay) |
384 | udelay(chip->cs_chg_udelay); | 371 | udelay(chip->cs_chg_udelay); |
385 | ++drv_data->rx; | 372 | ++drv_data->rx; |
386 | ++drv_data->tx; | 373 | ++drv_data->tx; |
387 | } | 374 | } |
388 | write_FLAG(0xFF00); | 375 | write_FLAG(0xFF00); |
389 | SSYNC(); | 376 | |
390 | } | 377 | } |
391 | 378 | ||
392 | static void u16_writer(struct driver_data *drv_data) | 379 | static void u16_writer(struct driver_data *drv_data) |
@@ -412,7 +399,6 @@ static void u16_cs_chg_writer(struct driver_data *drv_data) | |||
412 | 399 | ||
413 | while (drv_data->tx < drv_data->tx_end) { | 400 | while (drv_data->tx < drv_data->tx_end) { |
414 | write_FLAG(chip->flag); | 401 | write_FLAG(chip->flag); |
415 | SSYNC(); | ||
416 | 402 | ||
417 | write_TDBR(*(u16 *) (drv_data->tx)); | 403 | write_TDBR(*(u16 *) (drv_data->tx)); |
418 | while ((read_STAT() & BIT_STAT_TXS)) | 404 | while ((read_STAT() & BIT_STAT_TXS)) |
@@ -420,13 +406,12 @@ static void u16_cs_chg_writer(struct driver_data *drv_data) | |||
420 | while (!(read_STAT() & BIT_STAT_SPIF)) | 406 | while (!(read_STAT() & BIT_STAT_SPIF)) |
421 | continue; | 407 | continue; |
422 | write_FLAG(0xFF00 | chip->flag); | 408 | write_FLAG(0xFF00 | chip->flag); |
423 | SSYNC(); | 409 | |
424 | if (chip->cs_chg_udelay) | 410 | if (chip->cs_chg_udelay) |
425 | udelay(chip->cs_chg_udelay); | 411 | udelay(chip->cs_chg_udelay); |
426 | drv_data->tx += 2; | 412 | drv_data->tx += 2; |
427 | } | 413 | } |
428 | write_FLAG(0xFF00); | 414 | write_FLAG(0xFF00); |
429 | SSYNC(); | ||
430 | } | 415 | } |
431 | 416 | ||
432 | static void u16_reader(struct driver_data *drv_data) | 417 | static void u16_reader(struct driver_data *drv_data) |
@@ -454,7 +439,6 @@ static void u16_cs_chg_reader(struct driver_data *drv_data) | |||
454 | 439 | ||
455 | while (drv_data->rx < drv_data->rx_end) { | 440 | while (drv_data->rx < drv_data->rx_end) { |
456 | write_FLAG(chip->flag); | 441 | write_FLAG(chip->flag); |
457 | SSYNC(); | ||
458 | 442 | ||
459 | read_RDBR(); /* kick off */ | 443 | read_RDBR(); /* kick off */ |
460 | while (!(read_STAT() & BIT_STAT_RXS)) | 444 | while (!(read_STAT() & BIT_STAT_RXS)) |
@@ -463,13 +447,12 @@ static void u16_cs_chg_reader(struct driver_data *drv_data) | |||
463 | continue; | 447 | continue; |
464 | *(u16 *) (drv_data->rx) = read_SHAW(); | 448 | *(u16 *) (drv_data->rx) = read_SHAW(); |
465 | write_FLAG(0xFF00 | chip->flag); | 449 | write_FLAG(0xFF00 | chip->flag); |
466 | SSYNC(); | 450 | |
467 | if (chip->cs_chg_udelay) | 451 | if (chip->cs_chg_udelay) |
468 | udelay(chip->cs_chg_udelay); | 452 | udelay(chip->cs_chg_udelay); |
469 | drv_data->rx += 2; | 453 | drv_data->rx += 2; |
470 | } | 454 | } |
471 | write_FLAG(0xFF00); | 455 | write_FLAG(0xFF00); |
472 | SSYNC(); | ||
473 | } | 456 | } |
474 | 457 | ||
475 | static void u16_duplex(struct driver_data *drv_data) | 458 | static void u16_duplex(struct driver_data *drv_data) |
@@ -493,7 +476,6 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data) | |||
493 | 476 | ||
494 | while (drv_data->tx < drv_data->tx_end) { | 477 | while (drv_data->tx < drv_data->tx_end) { |
495 | write_FLAG(chip->flag); | 478 | write_FLAG(chip->flag); |
496 | SSYNC(); | ||
497 | 479 | ||
498 | write_TDBR(*(u16 *) (drv_data->tx)); | 480 | write_TDBR(*(u16 *) (drv_data->tx)); |
499 | while (!(read_STAT() & BIT_STAT_SPIF)) | 481 | while (!(read_STAT() & BIT_STAT_SPIF)) |
@@ -502,14 +484,13 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data) | |||
502 | continue; | 484 | continue; |
503 | *(u16 *) (drv_data->rx) = read_RDBR(); | 485 | *(u16 *) (drv_data->rx) = read_RDBR(); |
504 | write_FLAG(0xFF00 | chip->flag); | 486 | write_FLAG(0xFF00 | chip->flag); |
505 | SSYNC(); | 487 | |
506 | if (chip->cs_chg_udelay) | 488 | if (chip->cs_chg_udelay) |
507 | udelay(chip->cs_chg_udelay); | 489 | udelay(chip->cs_chg_udelay); |
508 | drv_data->rx += 2; | 490 | drv_data->rx += 2; |
509 | drv_data->tx += 2; | 491 | drv_data->tx += 2; |
510 | } | 492 | } |
511 | write_FLAG(0xFF00); | 493 | write_FLAG(0xFF00); |
512 | SSYNC(); | ||
513 | } | 494 | } |
514 | 495 | ||
515 | /* test if ther is more transfer to be done */ | 496 | /* test if ther is more transfer to be done */ |
@@ -811,7 +792,6 @@ static void pump_transfers(unsigned long data) | |||
811 | "IO duplex: cr is 0x%x\n", cr); | 792 | "IO duplex: cr is 0x%x\n", cr); |
812 | 793 | ||
813 | write_CTRL(cr); | 794 | write_CTRL(cr); |
814 | SSYNC(); | ||
815 | 795 | ||
816 | drv_data->duplex(drv_data); | 796 | drv_data->duplex(drv_data); |
817 | 797 | ||
@@ -826,7 +806,6 @@ static void pump_transfers(unsigned long data) | |||
826 | "IO write: cr is 0x%x\n", cr); | 806 | "IO write: cr is 0x%x\n", cr); |
827 | 807 | ||
828 | write_CTRL(cr); | 808 | write_CTRL(cr); |
829 | SSYNC(); | ||
830 | 809 | ||
831 | drv_data->write(drv_data); | 810 | drv_data->write(drv_data); |
832 | 811 | ||
@@ -841,7 +820,6 @@ static void pump_transfers(unsigned long data) | |||
841 | "IO read: cr is 0x%x\n", cr); | 820 | "IO read: cr is 0x%x\n", cr); |
842 | 821 | ||
843 | write_CTRL(cr); | 822 | write_CTRL(cr); |
844 | SSYNC(); | ||
845 | 823 | ||
846 | drv_data->read(drv_data); | 824 | drv_data->read(drv_data); |
847 | if (drv_data->rx != drv_data->rx_end) | 825 | if (drv_data->rx != drv_data->rx_end) |
@@ -892,6 +870,14 @@ static void pump_messages(struct work_struct *work) | |||
892 | /* Extract head of queue */ | 870 | /* Extract head of queue */ |
893 | drv_data->cur_msg = list_entry(drv_data->queue.next, | 871 | drv_data->cur_msg = list_entry(drv_data->queue.next, |
894 | struct spi_message, queue); | 872 | struct spi_message, queue); |
873 | |||
874 | /* Setup the SSP using the per chip configuration */ | ||
875 | drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); | ||
876 | if (restore_state(drv_data)) { | ||
877 | spin_unlock_irqrestore(&drv_data->lock, flags); | ||
878 | return; | ||
879 | }; | ||
880 | |||
895 | list_del_init(&drv_data->cur_msg->queue); | 881 | list_del_init(&drv_data->cur_msg->queue); |
896 | 882 | ||
897 | /* Initial message state */ | 883 | /* Initial message state */ |
@@ -899,13 +885,10 @@ static void pump_messages(struct work_struct *work) | |||
899 | drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, | 885 | drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, |
900 | struct spi_transfer, transfer_list); | 886 | struct spi_transfer, transfer_list); |
901 | 887 | ||
902 | /* Setup the SSP using the per chip configuration */ | 888 | dev_dbg(&drv_data->pdev->dev, "got a message to pump, " |
903 | drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); | 889 | "state is set to: baud %d, flag 0x%x, ctl 0x%x\n", |
904 | restore_state(drv_data); | 890 | drv_data->cur_chip->baud, drv_data->cur_chip->flag, |
905 | dev_dbg(&drv_data->pdev->dev, | 891 | drv_data->cur_chip->ctl_reg); |
906 | "got a message to pump, state is set to: baud %d, flag 0x%x, ctl 0x%x\n", | ||
907 | drv_data->cur_chip->baud, drv_data->cur_chip->flag, | ||
908 | drv_data->cur_chip->ctl_reg); | ||
909 | 892 | ||
910 | dev_dbg(&drv_data->pdev->dev, | 893 | dev_dbg(&drv_data->pdev->dev, |
911 | "the first transfer len is %d\n", | 894 | "the first transfer len is %d\n", |