aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Street <stephen@streetfiresound.com>2006-05-20 18:00:19 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-05-21 15:59:20 -0400
commit5daa3ba0c6a41a8bb4ba17ad8d5514172e103504 (patch)
treeb1b55ad5fb5feca7455112d6a95547c4e9913585
parent7fba53402eb0fb4209c74469814c583b6455e096 (diff)
[PATCH] pxa2xx-spi update
Fix some outstanding issues with the pxa2xx_spi driver when running on a PXA270: - Wrong timeout calculation in the setup function due to different peripheral clock rates in the PXAxxx family. - Bad handling of SSSR_TFS interrupts in interrupt_transfer function. - Added locking to interface between the pump_messages workqueue and the pump_transfers tasklet. Much thanks to Juergen Beisert for the extensive testing on the PXA270. Signed-off-by: Stephen Street <stephen@streetfiresound.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Cc: Russell King <rmk@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/spi/pxa2xx_spi.c93
-rw-r--r--include/asm-arm/arch-pxa/pxa2xx_spi.h3
2 files changed, 59 insertions, 37 deletions
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 596bf820b70c..29aec77f98be 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -363,25 +363,30 @@ static void unmap_dma_buffers(struct driver_data *drv_data)
363} 363}
364 364
365/* caller already set message->status; dma and pio irqs are blocked */ 365/* caller already set message->status; dma and pio irqs are blocked */
366static void giveback(struct spi_message *message, struct driver_data *drv_data) 366static void giveback(struct driver_data *drv_data)
367{ 367{
368 struct spi_transfer* last_transfer; 368 struct spi_transfer* last_transfer;
369 unsigned long flags;
370 struct spi_message *msg;
369 371
370 last_transfer = list_entry(message->transfers.prev, 372 spin_lock_irqsave(&drv_data->lock, flags);
373 msg = drv_data->cur_msg;
374 drv_data->cur_msg = NULL;
375 drv_data->cur_transfer = NULL;
376 drv_data->cur_chip = NULL;
377 queue_work(drv_data->workqueue, &drv_data->pump_messages);
378 spin_unlock_irqrestore(&drv_data->lock, flags);
379
380 last_transfer = list_entry(msg->transfers.prev,
371 struct spi_transfer, 381 struct spi_transfer,
372 transfer_list); 382 transfer_list);
373 383
374 if (!last_transfer->cs_change) 384 if (!last_transfer->cs_change)
375 drv_data->cs_control(PXA2XX_CS_DEASSERT); 385 drv_data->cs_control(PXA2XX_CS_DEASSERT);
376 386
377 message->state = NULL; 387 msg->state = NULL;
378 if (message->complete) 388 if (msg->complete)
379 message->complete(message->context); 389 msg->complete(msg->context);
380
381 drv_data->cur_msg = NULL;
382 drv_data->cur_transfer = NULL;
383 drv_data->cur_chip = NULL;
384 queue_work(drv_data->workqueue, &drv_data->pump_messages);
385} 390}
386 391
387static int wait_ssp_rx_stall(void *ioaddr) 392static int wait_ssp_rx_stall(void *ioaddr)
@@ -415,10 +420,11 @@ static void dma_handler(int channel, void *data, struct pt_regs *regs)
415 if (irq_status & DCSR_BUSERR) { 420 if (irq_status & DCSR_BUSERR) {
416 421
417 /* Disable interrupts, clear status and reset DMA */ 422 /* Disable interrupts, clear status and reset DMA */
423 write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
424 write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
418 if (drv_data->ssp_type != PXA25x_SSP) 425 if (drv_data->ssp_type != PXA25x_SSP)
419 write_SSTO(0, reg); 426 write_SSTO(0, reg);
420 write_SSSR(drv_data->clear_sr, reg); 427 write_SSSR(drv_data->clear_sr, reg);
421 write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
422 DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; 428 DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
423 DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; 429 DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
424 430
@@ -454,8 +460,8 @@ static void dma_handler(int channel, void *data, struct pt_regs *regs)
454 "dma_handler: ssp rx stall failed\n"); 460 "dma_handler: ssp rx stall failed\n");
455 461
456 /* Clear and disable interrupts on SSP and DMA channels*/ 462 /* Clear and disable interrupts on SSP and DMA channels*/
457 write_SSSR(drv_data->clear_sr, reg);
458 write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); 463 write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
464 write_SSSR(drv_data->clear_sr, reg);
459 DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; 465 DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
460 DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; 466 DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
461 if (wait_dma_channel_stop(drv_data->rx_channel) == 0) 467 if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
@@ -497,10 +503,11 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
497 irq_status = read_SSSR(reg) & drv_data->mask_sr; 503 irq_status = read_SSSR(reg) & drv_data->mask_sr;
498 if (irq_status & SSSR_ROR) { 504 if (irq_status & SSSR_ROR) {
499 /* Clear and disable interrupts on SSP and DMA channels*/ 505 /* Clear and disable interrupts on SSP and DMA channels*/
506 write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
507 write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
500 if (drv_data->ssp_type != PXA25x_SSP) 508 if (drv_data->ssp_type != PXA25x_SSP)
501 write_SSTO(0, reg); 509 write_SSTO(0, reg);
502 write_SSSR(drv_data->clear_sr, reg); 510 write_SSSR(drv_data->clear_sr, reg);
503 write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
504 DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; 511 DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
505 DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; 512 DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
506 unmap_dma_buffers(drv_data); 513 unmap_dma_buffers(drv_data);
@@ -526,10 +533,10 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
526 if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) { 533 if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
527 534
528 /* Clear and disable interrupts on SSP and DMA channels*/ 535 /* Clear and disable interrupts on SSP and DMA channels*/
536 write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
529 if (drv_data->ssp_type != PXA25x_SSP) 537 if (drv_data->ssp_type != PXA25x_SSP)
530 write_SSTO(0, reg); 538 write_SSTO(0, reg);
531 write_SSSR(drv_data->clear_sr, reg); 539 write_SSSR(drv_data->clear_sr, reg);
532 write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
533 DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; 540 DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
534 DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; 541 DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
535 542
@@ -572,26 +579,30 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
572 579
573static irqreturn_t interrupt_transfer(struct driver_data *drv_data) 580static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
574{ 581{
575 u32 irq_status;
576 struct spi_message *msg = drv_data->cur_msg; 582 struct spi_message *msg = drv_data->cur_msg;
577 void *reg = drv_data->ioaddr; 583 void *reg = drv_data->ioaddr;
578 irqreturn_t handled = IRQ_NONE;
579 unsigned long limit = loops_per_jiffy << 1; 584 unsigned long limit = loops_per_jiffy << 1;
585 u32 irq_status;
586 u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ?
587 drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
580 588
581 while ((irq_status = (read_SSSR(reg) & drv_data->mask_sr))) { 589 while ((irq_status = read_SSSR(reg) & irq_mask)) {
582 590
583 if (irq_status & SSSR_ROR) { 591 if (irq_status & SSSR_ROR) {
584 592
585 /* Clear and disable interrupts */ 593 /* Clear and disable interrupts */
594 write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
595 write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
586 if (drv_data->ssp_type != PXA25x_SSP) 596 if (drv_data->ssp_type != PXA25x_SSP)
587 write_SSTO(0, reg); 597 write_SSTO(0, reg);
588 write_SSSR(drv_data->clear_sr, reg); 598 write_SSSR(drv_data->clear_sr, reg);
589 write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
590 599
591 if (flush(drv_data) == 0) 600 if (flush(drv_data) == 0)
592 dev_err(&drv_data->pdev->dev, 601 dev_err(&drv_data->pdev->dev,
593 "interrupt_transfer: flush fail\n"); 602 "interrupt_transfer: flush fail\n");
594 603
604 /* Stop the SSP */
605
595 dev_warn(&drv_data->pdev->dev, 606 dev_warn(&drv_data->pdev->dev,
596 "interrupt_transfer: fifo overun\n"); 607 "interrupt_transfer: fifo overun\n");
597 608
@@ -613,6 +624,7 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
613 if (drv_data->tx == drv_data->tx_end) { 624 if (drv_data->tx == drv_data->tx_end) {
614 /* Disable tx interrupt */ 625 /* Disable tx interrupt */
615 write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg); 626 write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg);
627 irq_mask = drv_data->mask_sr & ~SSSR_TFS;
616 628
617 /* PXA25x_SSP has no timeout, read trailing bytes */ 629 /* PXA25x_SSP has no timeout, read trailing bytes */
618 if (drv_data->ssp_type == PXA25x_SSP) { 630 if (drv_data->ssp_type == PXA25x_SSP) {
@@ -630,10 +642,10 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
630 || (drv_data->rx == drv_data->rx_end)) { 642 || (drv_data->rx == drv_data->rx_end)) {
631 643
632 /* Clear timeout */ 644 /* Clear timeout */
645 write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
633 if (drv_data->ssp_type != PXA25x_SSP) 646 if (drv_data->ssp_type != PXA25x_SSP)
634 write_SSTO(0, reg); 647 write_SSTO(0, reg);
635 write_SSSR(drv_data->clear_sr, reg); 648 write_SSSR(drv_data->clear_sr, reg);
636 write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
637 649
638 /* Update total byte transfered */ 650 /* Update total byte transfered */
639 msg->actual_length += drv_data->len; 651 msg->actual_length += drv_data->len;
@@ -648,24 +660,29 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
648 660
649 /* Schedule transfer tasklet */ 661 /* Schedule transfer tasklet */
650 tasklet_schedule(&drv_data->pump_transfers); 662 tasklet_schedule(&drv_data->pump_transfers);
651
652 return IRQ_HANDLED;
653 } 663 }
654
655 /* We did something */
656 handled = IRQ_HANDLED;
657 } 664 }
658 665
659 return handled; 666 /* We did something */
667 return IRQ_HANDLED;
660} 668}
661 669
662static irqreturn_t ssp_int(int irq, void *dev_id, struct pt_regs *regs) 670static irqreturn_t ssp_int(int irq, void *dev_id, struct pt_regs *regs)
663{ 671{
664 struct driver_data *drv_data = (struct driver_data *)dev_id; 672 struct driver_data *drv_data = (struct driver_data *)dev_id;
673 void *reg = drv_data->ioaddr;
665 674
666 if (!drv_data->cur_msg) { 675 if (!drv_data->cur_msg) {
676
677 write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
678 write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
679 if (drv_data->ssp_type != PXA25x_SSP)
680 write_SSTO(0, reg);
681 write_SSSR(drv_data->clear_sr, reg);
682
667 dev_err(&drv_data->pdev->dev, "bad message state " 683 dev_err(&drv_data->pdev->dev, "bad message state "
668 "in interrupt handler\n"); 684 "in interrupt handler");
685
669 /* Never fail */ 686 /* Never fail */
670 return IRQ_HANDLED; 687 return IRQ_HANDLED;
671 } 688 }
@@ -694,14 +711,14 @@ static void pump_transfers(unsigned long data)
694 /* Handle for abort */ 711 /* Handle for abort */
695 if (message->state == ERROR_STATE) { 712 if (message->state == ERROR_STATE) {
696 message->status = -EIO; 713 message->status = -EIO;
697 giveback(message, drv_data); 714 giveback(drv_data);
698 return; 715 return;
699 } 716 }
700 717
701 /* Handle end of message */ 718 /* Handle end of message */
702 if (message->state == DONE_STATE) { 719 if (message->state == DONE_STATE) {
703 message->status = 0; 720 message->status = 0;
704 giveback(message, drv_data); 721 giveback(drv_data);
705 return; 722 return;
706 } 723 }
707 724
@@ -718,7 +735,7 @@ static void pump_transfers(unsigned long data)
718 if (flush(drv_data) == 0) { 735 if (flush(drv_data) == 0) {
719 dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n"); 736 dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
720 message->status = -EIO; 737 message->status = -EIO;
721 giveback(message, drv_data); 738 giveback(drv_data);
722 return; 739 return;
723 } 740 }
724 drv_data->n_bytes = chip->n_bytes; 741 drv_data->n_bytes = chip->n_bytes;
@@ -782,7 +799,7 @@ static void pump_transfers(unsigned long data)
782 799
783 cr0 = clk_div 800 cr0 = clk_div
784 | SSCR0_Motorola 801 | SSCR0_Motorola
785 | SSCR0_DataSize(bits & 0x0f) 802 | SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
786 | SSCR0_SSE 803 | SSCR0_SSE
787 | (bits > 16 ? SSCR0_EDSS : 0); 804 | (bits > 16 ? SSCR0_EDSS : 0);
788 805
@@ -890,8 +907,6 @@ static void pump_messages(void *data)
890 drv_data->cur_msg = list_entry(drv_data->queue.next, 907 drv_data->cur_msg = list_entry(drv_data->queue.next,
891 struct spi_message, queue); 908 struct spi_message, queue);
892 list_del_init(&drv_data->cur_msg->queue); 909 list_del_init(&drv_data->cur_msg->queue);
893 drv_data->busy = 1;
894 spin_unlock_irqrestore(&drv_data->lock, flags);
895 910
896 /* Initial message state*/ 911 /* Initial message state*/
897 drv_data->cur_msg->state = START_STATE; 912 drv_data->cur_msg->state = START_STATE;
@@ -905,6 +920,9 @@ static void pump_messages(void *data)
905 920
906 /* Mark as busy and launch transfers */ 921 /* Mark as busy and launch transfers */
907 tasklet_schedule(&drv_data->pump_transfers); 922 tasklet_schedule(&drv_data->pump_transfers);
923
924 drv_data->busy = 1;
925 spin_unlock_irqrestore(&drv_data->lock, flags);
908} 926}
909 927
910static int transfer(struct spi_device *spi, struct spi_message *msg) 928static int transfer(struct spi_device *spi, struct spi_message *msg)
@@ -958,7 +976,7 @@ static int setup(struct spi_device *spi)
958 976
959 chip->cs_control = null_cs_control; 977 chip->cs_control = null_cs_control;
960 chip->enable_dma = 0; 978 chip->enable_dma = 0;
961 chip->timeout = 5; 979 chip->timeout = SSP_TIMEOUT(1000);
962 chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1); 980 chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1);
963 chip->dma_burst_size = drv_data->master_info->enable_dma ? 981 chip->dma_burst_size = drv_data->master_info->enable_dma ?
964 DCMD_BURST8 : 0; 982 DCMD_BURST8 : 0;
@@ -971,7 +989,7 @@ static int setup(struct spi_device *spi)
971 if (chip_info->cs_control) 989 if (chip_info->cs_control)
972 chip->cs_control = chip_info->cs_control; 990 chip->cs_control = chip_info->cs_control;
973 991
974 chip->timeout = (chip_info->timeout_microsecs * 10000) / 2712; 992 chip->timeout = SSP_TIMEOUT(chip_info->timeout_microsecs);
975 993
976 chip->threshold = SSCR1_RxTresh(chip_info->rx_threshold) 994 chip->threshold = SSCR1_RxTresh(chip_info->rx_threshold)
977 | SSCR1_TxTresh(chip_info->tx_threshold); 995 | SSCR1_TxTresh(chip_info->tx_threshold);
@@ -1013,7 +1031,8 @@ static int setup(struct spi_device *spi)
1013 1031
1014 chip->cr0 = clk_div 1032 chip->cr0 = clk_div
1015 | SSCR0_Motorola 1033 | SSCR0_Motorola
1016 | SSCR0_DataSize(spi->bits_per_word & 0x0f) 1034 | SSCR0_DataSize(spi->bits_per_word > 16 ?
1035 spi->bits_per_word - 16 : spi->bits_per_word)
1017 | SSCR0_SSE 1036 | SSCR0_SSE
1018 | (spi->bits_per_word > 16 ? SSCR0_EDSS : 0); 1037 | (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
1019 chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) << 4) 1038 chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) << 4)
@@ -1196,7 +1215,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
1196 goto out_error_master_alloc; 1215 goto out_error_master_alloc;
1197 } 1216 }
1198 1217
1199 drv_data->ioaddr = (void *)io_p2v(memory_resource->start); 1218 drv_data->ioaddr = (void *)io_p2v((unsigned long)(memory_resource->start));
1200 drv_data->ssdr_physical = memory_resource->start + 0x00000010; 1219 drv_data->ssdr_physical = memory_resource->start + 0x00000010;
1201 if (platform_info->ssp_type == PXA25x_SSP) { 1220 if (platform_info->ssp_type == PXA25x_SSP) {
1202 drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE; 1221 drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE;
@@ -1218,7 +1237,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
1218 goto out_error_master_alloc; 1237 goto out_error_master_alloc;
1219 } 1238 }
1220 1239
1221 status = request_irq(irq, ssp_int, SA_INTERRUPT, dev->bus_id, drv_data); 1240 status = request_irq(irq, ssp_int, 0, dev->bus_id, drv_data);
1222 if (status < 0) { 1241 if (status < 0) {
1223 dev_err(&pdev->dev, "can not get IRQ\n"); 1242 dev_err(&pdev->dev, "can not get IRQ\n");
1224 goto out_error_master_alloc; 1243 goto out_error_master_alloc;
diff --git a/include/asm-arm/arch-pxa/pxa2xx_spi.h b/include/asm-arm/arch-pxa/pxa2xx_spi.h
index 1e70908b816f..915590c391c8 100644
--- a/include/asm-arm/arch-pxa/pxa2xx_spi.h
+++ b/include/asm-arm/arch-pxa/pxa2xx_spi.h
@@ -27,13 +27,16 @@
27#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/2/(x+1))<<8)&0x0000ff00) 27#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/2/(x+1))<<8)&0x0000ff00)
28#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) 28#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
29#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) 29#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
30#define SSP_TIMEOUT_SCALE (2712)
30#elif defined(CONFIG_PXA27x) 31#elif defined(CONFIG_PXA27x)
31#define CLOCK_SPEED_HZ 13000000 32#define CLOCK_SPEED_HZ 13000000
32#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) 33#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
33#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) 34#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
34#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) 35#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
36#define SSP_TIMEOUT_SCALE (769)
35#endif 37#endif
36 38
39#define SSP_TIMEOUT(x) ((x*10000)/SSP_TIMEOUT_SCALE)
37#define SSP1_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(1))))) 40#define SSP1_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(1)))))
38#define SSP2_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(2))))) 41#define SSP2_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(2)))))
39#define SSP3_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(3))))) 42#define SSP3_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(3)))))