summaryrefslogtreecommitdiff
path: root/firmware/target/arm/as3525
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/as3525')
-rw-r--r--firmware/target/arm/as3525/ata_sd_as3525.c49
-rw-r--r--firmware/target/arm/as3525/dma-pl081.c29
-rw-r--r--firmware/target/arm/as3525/dma-target.h4
3 files changed, 68 insertions, 14 deletions
diff --git a/firmware/target/arm/as3525/ata_sd_as3525.c b/firmware/target/arm/as3525/ata_sd_as3525.c
index b2d8e3c1f3..3ec1892542 100644
--- a/firmware/target/arm/as3525/ata_sd_as3525.c
+++ b/firmware/target/arm/as3525/ata_sd_as3525.c
@@ -129,6 +129,37 @@ static void mci_set_clock_divider(const int drive, int divider)
129 mci_delay(); 129 mci_delay();
130} 130}
131 131
132static void sd_panic(IF_MV2(const int drive,) const int status)
133{
134 char error[32];
135 error[0] = '\0';
136
137#ifdef HAVE_MULTIVOLUME
138 snprintf(error, sizeof(error),
139 (drive == INTERNAL_AS3525) ? "Internal storage : " : "SD Slot : " );
140#endif
141
142 panicf("SD : %s%s%s%s%s%s%s", error,
143 (status & MCI_DATA_CRC_FAIL) ? "DATA CRC FAIL, " : "",
144 (status & MCI_DATA_TIMEOUT) ? "DATA TIMEOUT, " : "",
145 (status & MCI_RX_OVERRUN) ? "RX OVERRUN, " : "",
146 (status & MCI_TX_UNDERRUN) ? "TX UNDERRUN, " : "",
147 (status & MCI_RX_FIFO_FULL) ? "RXR FIFO FULL, " : "",
148 (status & MCI_TX_FIFO_EMPTY) ? "TX FIFO EMPTY" : "");
149}
150
151void INT_NAND(void)
152{
153 sd_panic(IF_MV2(INTERNAL_AS3525,) MCI_STATUS(INTERNAL_AS3525));
154}
155
156#ifdef HAVE_MULTIVOLUME
157void INT_MCI0(void)
158{
159 sd_panic(SD_SLOT_AS3525, MCI_STATUS(SD_SLOT_AS3525));
160}
161#endif
162
132static bool send_cmd(const int drive, const int cmd, const int arg, 163static bool send_cmd(const int drive, const int cmd, const int arg,
133 const int flags, int *response) 164 const int flags, int *response)
134{ 165{
@@ -362,7 +393,14 @@ static void init_pl180_controller(const int drive)
362 MCI_COMMAND(drive) = MCI_DATA_CTRL(drive) = 0; 393 MCI_COMMAND(drive) = MCI_DATA_CTRL(drive) = 0;
363 MCI_CLEAR(drive) = 0x7ff; 394 MCI_CLEAR(drive) = 0x7ff;
364 395
365 MCI_MASK0(drive) = MCI_MASK1(drive) = 0; /* disable all interrupts */ 396 MCI_MASK0(drive) = MCI_MASK1(drive) = MCI_DATA_CRC_FAIL | MCI_DATA_TIMEOUT |
397 MCI_RX_OVERRUN | MCI_TX_UNDERRUN | MCI_RX_FIFO_FULL | MCI_TX_FIFO_EMPTY;
398
399 VIC_INT_ENABLE |= INTERRUPT_NAND
400#ifdef HAVE_MULTIVOLUME
401 | INTERRUPT_MCI0
402#endif
403 ;
366 404
367 MCI_POWER(drive) = MCI_POWER_UP|(10 /*voltage*/ << 2); /* use OF voltage */ 405 MCI_POWER(drive) = MCI_POWER_UP|(10 /*voltage*/ << 2); /* use OF voltage */
368 mci_delay(); 406 mci_delay();
@@ -378,7 +416,6 @@ static void init_pl180_controller(const int drive)
378 /* set MCLK divider */ 416 /* set MCLK divider */
379 mci_set_clock_divider(drive, 417 mci_set_clock_divider(drive,
380 CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ)); 418 CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ));
381
382} 419}
383 420
384int sd_init(void) 421int sd_init(void)
@@ -552,12 +589,12 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
552 589
553 if(write) 590 if(write)
554 dma_enable_channel(0, buf, MCI_FIFO(drive), 591 dma_enable_channel(0, buf, MCI_FIFO(drive),
555 (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT, 592 (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
556 DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8); 593 DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL);
557 else 594 else
558 dma_enable_channel(0, MCI_FIFO(drive), buf, 595 dma_enable_channel(0, MCI_FIFO(drive), buf,
559 (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT, 596 (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
560 DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8); 597 DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL);
561 598
562 MCI_DATA_TIMER(drive) = 0x1000000; /* FIXME: arbitrary */ 599 MCI_DATA_TIMER(drive) = 0x1000000; /* FIXME: arbitrary */
563 MCI_DATA_LENGTH(drive) = transfer * card_info[drive].block_size; 600 MCI_DATA_LENGTH(drive) = transfer * card_info[drive].block_size;
diff --git a/firmware/target/arm/as3525/dma-pl081.c b/firmware/target/arm/as3525/dma-pl081.c
index fbe488ce05..3de4e73c12 100644
--- a/firmware/target/arm/as3525/dma-pl081.c
+++ b/firmware/target/arm/as3525/dma-pl081.c
@@ -27,6 +27,7 @@
27#include "kernel.h" 27#include "kernel.h"
28 28
29static struct wakeup transfer_completion_signal[2]; /* 2 channels */ 29static struct wakeup transfer_completion_signal[2]; /* 2 channels */
30static void (*dma_callback[2])(void); /* 2 channels */
30 31
31inline void dma_wait_transfer(int channel) 32inline void dma_wait_transfer(int channel)
32{ 33{
@@ -45,10 +46,17 @@ void dma_init(void)
45 wakeup_init(&transfer_completion_signal[1]); 46 wakeup_init(&transfer_completion_signal[1]);
46} 47}
47 48
49inline void dma_disable_channel(int channel)
50{
51 DMAC_CH_CONFIGURATION(channel) &= ~(1<<0);
52}
53
48void dma_enable_channel(int channel, void *src, void *dst, int peri, 54void dma_enable_channel(int channel, void *src, void *dst, int peri,
49 int flow_controller, bool src_inc, bool dst_inc, 55 int flow_controller, bool src_inc, bool dst_inc,
50 size_t size, int nwords) 56 size_t size, int nwords, void (*callback)(void))
51{ 57{
58 dma_callback[channel] = callback;
59
52 int control = 0; 60 int control = 0;
53 61
54 DMAC_CH_SRC_ADDR(channel) = (int)src; 62 DMAC_CH_SRC_ADDR(channel) = (int)src;
@@ -92,12 +100,21 @@ void dma_enable_channel(int channel, void *src, void *dst, int peri,
92/* isr */ 100/* isr */
93void INT_DMAC(void) 101void INT_DMAC(void)
94{ 102{
95 int channel = (DMAC_INT_STATUS & (1<<0)) ? 0 : 1; 103 unsigned int channel;
104
105 /* SD channel is serviced first */
106 for(channel = 0; channel < 2; channel++)
107 if(DMAC_INT_STATUS & (1<<channel))
108 {
109 if(DMAC_INT_ERROR_STATUS & (1<<channel))
110 panicf("DMA error, channel %d", channel);
96 111
97 if(DMAC_INT_ERROR_STATUS & (1<<channel)) 112 /* clear terminal count interrupt */
98 panicf("DMA error, channel %d", channel); 113 DMAC_INT_TC_CLEAR |= (1<<channel);
99 114
100 DMAC_INT_TC_CLEAR |= (1<<channel); /* clear terminal count interrupt */ 115 if(dma_callback[channel])
116 dma_callback[channel]();
101 117
102 wakeup_signal(&transfer_completion_signal[channel]); 118 wakeup_signal(&transfer_completion_signal[channel]);
119 }
103} 120}
diff --git a/firmware/target/arm/as3525/dma-target.h b/firmware/target/arm/as3525/dma-target.h
index cd307b7b2a..26037999f0 100644
--- a/firmware/target/arm/as3525/dma-target.h
+++ b/firmware/target/arm/as3525/dma-target.h
@@ -34,6 +34,6 @@
34void dma_init(void); 34void dma_init(void);
35void dma_enable_channel(int channel, void *src, void *dst, int peri, 35void dma_enable_channel(int channel, void *src, void *dst, int peri,
36 int flow_controller, bool src_inc, bool dst_inc, 36 int flow_controller, bool src_inc, bool dst_inc,
37 size_t size, int nwords); 37 size_t size, int nwords, void (*callback)(void));
38 38inline void dma_disable_channel(int channel);
39inline void dma_wait_transfer(int channel); 39inline void dma_wait_transfer(int channel);