diff options
-rw-r--r-- | firmware/target/arm/as3525/ata_sd_as3525.c | 49 | ||||
-rw-r--r-- | firmware/target/arm/as3525/dma-pl081.c | 29 | ||||
-rw-r--r-- | firmware/target/arm/as3525/dma-target.h | 4 |
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 | ||
132 | static 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 | |||
151 | void INT_NAND(void) | ||
152 | { | ||
153 | sd_panic(IF_MV2(INTERNAL_AS3525,) MCI_STATUS(INTERNAL_AS3525)); | ||
154 | } | ||
155 | |||
156 | #ifdef HAVE_MULTIVOLUME | ||
157 | void INT_MCI0(void) | ||
158 | { | ||
159 | sd_panic(SD_SLOT_AS3525, MCI_STATUS(SD_SLOT_AS3525)); | ||
160 | } | ||
161 | #endif | ||
162 | |||
132 | static bool send_cmd(const int drive, const int cmd, const int arg, | 163 | static 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 | ||
384 | int sd_init(void) | 421 | int 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 | ||
29 | static struct wakeup transfer_completion_signal[2]; /* 2 channels */ | 29 | static struct wakeup transfer_completion_signal[2]; /* 2 channels */ |
30 | static void (*dma_callback[2])(void); /* 2 channels */ | ||
30 | 31 | ||
31 | inline void dma_wait_transfer(int channel) | 32 | inline 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 | ||
49 | inline void dma_disable_channel(int channel) | ||
50 | { | ||
51 | DMAC_CH_CONFIGURATION(channel) &= ~(1<<0); | ||
52 | } | ||
53 | |||
48 | void dma_enable_channel(int channel, void *src, void *dst, int peri, | 54 | void 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 */ |
93 | void INT_DMAC(void) | 101 | void 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 @@ | |||
34 | void dma_init(void); | 34 | void dma_init(void); |
35 | void dma_enable_channel(int channel, void *src, void *dst, int peri, | 35 | void 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 | 38 | inline void dma_disable_channel(int channel); | |
39 | inline void dma_wait_transfer(int channel); | 39 | inline void dma_wait_transfer(int channel); |