diff options
Diffstat (limited to 'firmware/target/arm/as3525/sd-as3525.c')
-rw-r--r-- | firmware/target/arm/as3525/sd-as3525.c | 944 |
1 files changed, 944 insertions, 0 deletions
diff --git a/firmware/target/arm/as3525/sd-as3525.c b/firmware/target/arm/as3525/sd-as3525.c new file mode 100644 index 0000000000..0afe735e53 --- /dev/null +++ b/firmware/target/arm/as3525/sd-as3525.c | |||
@@ -0,0 +1,944 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 Daniel Ankers | ||
11 | * Copyright © 2008-2009 Rafaël Carré | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
19 | * KIND, either express or implied. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | |||
23 | /* Driver for the ARM PL180 SD/MMC controller inside AS3525 SoC */ | ||
24 | |||
25 | /* TODO: Find the real capacity of >2GB models (will be useful for USB) */ | ||
26 | |||
27 | #include "config.h" /* for HAVE_MULTIDRIVE & AMS_OF_SIZE */ | ||
28 | #include "fat.h" | ||
29 | #include "thread.h" | ||
30 | #include "led.h" | ||
31 | #include "hotswap.h" | ||
32 | #include "system.h" | ||
33 | #include "cpu.h" | ||
34 | #include <stdio.h> | ||
35 | #include <stdlib.h> | ||
36 | #include <string.h> | ||
37 | #include "as3525.h" | ||
38 | #include "pl180.h" /* SD controller */ | ||
39 | #include "pl081.h" /* DMA controller */ | ||
40 | #include "dma-target.h" /* DMA request lines */ | ||
41 | #include "clock-target.h" | ||
42 | #include "panic.h" | ||
43 | #ifdef HAVE_BUTTON_LIGHT | ||
44 | #include "backlight-target.h" | ||
45 | #endif | ||
46 | #include "stdbool.h" | ||
47 | #include "ata_idle_notify.h" | ||
48 | #include "sd.h" | ||
49 | #include "usb.h" | ||
50 | |||
51 | #ifdef HAVE_HOTSWAP | ||
52 | #include "disk.h" | ||
53 | #endif | ||
54 | |||
55 | /* command flags */ | ||
56 | #define MCI_NO_FLAGS (0<<0) | ||
57 | #define MCI_RESP (1<<0) | ||
58 | #define MCI_LONG_RESP (1<<1) | ||
59 | #define MCI_ARG (1<<2) | ||
60 | |||
61 | /* ARM PL180 registers */ | ||
62 | #define MCI_POWER(i) (*(volatile unsigned char *) (pl180_base[i]+0x00)) | ||
63 | #define MCI_CLOCK(i) (*(volatile unsigned long *) (pl180_base[i]+0x04)) | ||
64 | #define MCI_ARGUMENT(i) (*(volatile unsigned long *) (pl180_base[i]+0x08)) | ||
65 | #define MCI_COMMAND(i) (*(volatile unsigned long *) (pl180_base[i]+0x0C)) | ||
66 | #define MCI_RESPCMD(i) (*(volatile unsigned long *) (pl180_base[i]+0x10)) | ||
67 | #define MCI_RESP0(i) (*(volatile unsigned long *) (pl180_base[i]+0x14)) | ||
68 | #define MCI_RESP1(i) (*(volatile unsigned long *) (pl180_base[i]+0x18)) | ||
69 | #define MCI_RESP2(i) (*(volatile unsigned long *) (pl180_base[i]+0x1C)) | ||
70 | #define MCI_RESP3(i) (*(volatile unsigned long *) (pl180_base[i]+0x20)) | ||
71 | #define MCI_DATA_TIMER(i) (*(volatile unsigned long *) (pl180_base[i]+0x24)) | ||
72 | #define MCI_DATA_LENGTH(i) (*(volatile unsigned short*) (pl180_base[i]+0x28)) | ||
73 | #define MCI_DATA_CTRL(i) (*(volatile unsigned char *) (pl180_base[i]+0x2C)) | ||
74 | #define MCI_DATA_CNT(i) (*(volatile unsigned short*) (pl180_base[i]+0x30)) | ||
75 | #define MCI_STATUS(i) (*(volatile unsigned long *) (pl180_base[i]+0x34)) | ||
76 | #define MCI_CLEAR(i) (*(volatile unsigned long *) (pl180_base[i]+0x38)) | ||
77 | #define MCI_MASK0(i) (*(volatile unsigned long *) (pl180_base[i]+0x3C)) | ||
78 | #define MCI_MASK1(i) (*(volatile unsigned long *) (pl180_base[i]+0x40)) | ||
79 | #define MCI_SELECT(i) (*(volatile unsigned long *) (pl180_base[i]+0x44)) | ||
80 | #define MCI_FIFO_CNT(i) (*(volatile unsigned long *) (pl180_base[i]+0x48)) | ||
81 | |||
82 | #define MCI_DATA_ERROR \ | ||
83 | ( MCI_DATA_CRC_FAIL \ | ||
84 | | MCI_DATA_TIMEOUT \ | ||
85 | | MCI_TX_UNDERRUN \ | ||
86 | | MCI_RX_OVERRUN \ | ||
87 | | MCI_START_BIT_ERR) | ||
88 | |||
89 | #define MCI_RESPONSE_ERROR \ | ||
90 | ( MCI_CMD_TIMEOUT \ | ||
91 | | MCI_CMD_CRC_FAIL) | ||
92 | |||
93 | #define MCI_FIFO(i) ((unsigned long *) (pl180_base[i]+0x80)) | ||
94 | /* volumes */ | ||
95 | #define INTERNAL_AS3525 0 /* embedded SD card */ | ||
96 | #define SD_SLOT_AS3525 1 /* SD slot if present */ | ||
97 | |||
98 | static const int pl180_base[NUM_DRIVES] = { | ||
99 | NAND_FLASH_BASE | ||
100 | #ifdef HAVE_MULTIDRIVE | ||
101 | , SD_MCI_BASE | ||
102 | #endif | ||
103 | }; | ||
104 | |||
105 | static int sd_wait_for_state(const int drive, unsigned int state); | ||
106 | static int sd_select_bank(signed char bank); | ||
107 | static int sd_init_card(const int drive); | ||
108 | static void init_pl180_controller(const int drive); | ||
109 | |||
110 | #define BLOCKS_PER_BANK 0x7a7800 | ||
111 | |||
112 | static tCardInfo card_info[NUM_DRIVES]; | ||
113 | |||
114 | /* maximum timeouts recommanded in the SD Specification v2.00 */ | ||
115 | #define SD_MAX_READ_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 100) /* 100 ms */ | ||
116 | #define SD_MAX_WRITE_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 250) /* 250 ms */ | ||
117 | |||
118 | /* for compatibility */ | ||
119 | static long last_disk_activity = -1; | ||
120 | |||
121 | #define MIN_YIELD_PERIOD 5 /* ticks */ | ||
122 | static long next_yield = 0; | ||
123 | |||
124 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; | ||
125 | static const char sd_thread_name[] = "ata/sd"; | ||
126 | static struct mutex sd_mtx; | ||
127 | static struct event_queue sd_queue; | ||
128 | #ifndef BOOTLOADER | ||
129 | bool sd_enabled = false; | ||
130 | #endif | ||
131 | |||
132 | #if defined(HAVE_MULTIDRIVE) | ||
133 | static bool hs_card = false; | ||
134 | #endif | ||
135 | |||
136 | static struct wakeup transfer_completion_signal; | ||
137 | static volatile unsigned int transfer_error[NUM_VOLUMES]; | ||
138 | #define PL180_MAX_TRANSFER_ERRORS 10 | ||
139 | |||
140 | #define UNALIGNED_NUM_SECTORS 10 | ||
141 | static unsigned char aligned_buffer[UNALIGNED_NUM_SECTORS* SD_BLOCK_SIZE] __attribute__((aligned(32))); /* align on cache line size */ | ||
142 | static unsigned char *uncached_buffer = UNCACHED_ADDR(&aligned_buffer[0]); | ||
143 | |||
144 | static inline void mci_delay(void) | ||
145 | { | ||
146 | int i = 0xffff; | ||
147 | do { | ||
148 | asm volatile("nop\n"); | ||
149 | } while (--i); | ||
150 | } | ||
151 | |||
152 | |||
153 | static inline bool card_detect_target(void) | ||
154 | { | ||
155 | #if defined(HAVE_MULTIDRIVE) | ||
156 | return !(GPIOA_PIN(2)); | ||
157 | #else | ||
158 | return false; | ||
159 | #endif | ||
160 | } | ||
161 | |||
162 | #ifdef HAVE_HOTSWAP | ||
163 | static int sd1_oneshot_callback(struct timeout *tmo) | ||
164 | { | ||
165 | (void)tmo; | ||
166 | |||
167 | /* This is called only if the state was stable for 300ms - check state | ||
168 | * and post appropriate event. */ | ||
169 | if (card_detect_target()) | ||
170 | { | ||
171 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | ||
172 | } | ||
173 | else | ||
174 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | void INT_GPIOA(void) | ||
180 | { | ||
181 | static struct timeout sd1_oneshot; | ||
182 | /* acknowledge interrupt */ | ||
183 | GPIOA_IC = (1<<2); | ||
184 | timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0); | ||
185 | } | ||
186 | #endif /* HAVE_HOTSWAP */ | ||
187 | |||
188 | void INT_NAND(void) | ||
189 | { | ||
190 | const int status = MCI_STATUS(INTERNAL_AS3525); | ||
191 | |||
192 | transfer_error[INTERNAL_AS3525] = status & MCI_DATA_ERROR; | ||
193 | |||
194 | wakeup_signal(&transfer_completion_signal); | ||
195 | MCI_CLEAR(INTERNAL_AS3525) = status; | ||
196 | } | ||
197 | |||
198 | #ifdef HAVE_MULTIDRIVE | ||
199 | void INT_MCI0(void) | ||
200 | { | ||
201 | const int status = MCI_STATUS(SD_SLOT_AS3525); | ||
202 | |||
203 | transfer_error[SD_SLOT_AS3525] = status & MCI_DATA_ERROR; | ||
204 | |||
205 | wakeup_signal(&transfer_completion_signal); | ||
206 | MCI_CLEAR(SD_SLOT_AS3525) = status; | ||
207 | } | ||
208 | #endif | ||
209 | |||
210 | static bool send_cmd(const int drive, const int cmd, const int arg, | ||
211 | const int flags, long *response) | ||
212 | { | ||
213 | int status; | ||
214 | |||
215 | /* Clear old status flags */ | ||
216 | MCI_CLEAR(drive) = 0x7ff; | ||
217 | |||
218 | /* Load command argument or clear if none */ | ||
219 | MCI_ARGUMENT(drive) = (flags & MCI_ARG) ? arg : 0; | ||
220 | |||
221 | /* Construct MCI_COMMAND & enable CPSM */ | ||
222 | MCI_COMMAND(drive) = | ||
223 | /*b0:5*/ cmd | ||
224 | /* b6 */| ((flags & (MCI_RESP|MCI_LONG_RESP)) ? MCI_COMMAND_RESPONSE : 0) | ||
225 | /* b7 */| ((flags & MCI_LONG_RESP) ? MCI_COMMAND_LONG_RESPONSE : 0) | ||
226 | /* b8 | MCI_COMMAND_INTERRUPT */ | ||
227 | /* b9 | MCI_COMMAND_PENDING */ /*Only used with stream data transfer*/ | ||
228 | /* b10*/| MCI_COMMAND_ENABLE; /* Enables CPSM */ | ||
229 | |||
230 | /* Wait while cmd completes then disable CPSM */ | ||
231 | while(MCI_STATUS(drive) & MCI_CMD_ACTIVE); | ||
232 | MCI_COMMAND(drive) = 0; | ||
233 | |||
234 | status = MCI_STATUS(drive); | ||
235 | |||
236 | /* Handle command responses */ | ||
237 | if(flags & MCI_RESP) /* CMD expects response */ | ||
238 | { | ||
239 | response[0] = MCI_RESP0(drive); /* Always prepare short response */ | ||
240 | |||
241 | if(status & MCI_RESPONSE_ERROR) /* timeout or crc failure */ | ||
242 | return false; | ||
243 | |||
244 | if(status & MCI_CMD_RESP_END) /*Response passed CRC check */ | ||
245 | { | ||
246 | if(flags & MCI_LONG_RESP) | ||
247 | { /* replace short response with long response */ | ||
248 | /* store the response in reverse words order */ | ||
249 | response[0] = MCI_RESP3(drive); | ||
250 | response[1] = MCI_RESP2(drive); | ||
251 | response[2] = MCI_RESP1(drive); | ||
252 | response[3] = MCI_RESP0(drive); | ||
253 | } | ||
254 | return true; | ||
255 | } | ||
256 | } | ||
257 | else if(status & MCI_CMD_SENT) /* CMD sent, no response required */ | ||
258 | return true; | ||
259 | |||
260 | return false; | ||
261 | } | ||
262 | |||
263 | #define MCI_FULLSPEED (MCI_CLOCK_ENABLE | MCI_CLOCK_BYPASS) /* MCLK */ | ||
264 | #define MCI_HALFSPEED (MCI_CLOCK_ENABLE) /* MCLK/2 */ | ||
265 | #define MCI_QUARTERSPEED (MCI_CLOCK_ENABLE | 1) /* MCLK/4 */ | ||
266 | #define MCI_IDENTSPEED (MCI_CLOCK_ENABLE | AS3525_SD_IDENT_DIV) /* IDENT */ | ||
267 | |||
268 | static int sd_init_card(const int drive) | ||
269 | { | ||
270 | unsigned long response; | ||
271 | long init_timeout; | ||
272 | bool sd_v2 = false; | ||
273 | unsigned long temp_reg[4]; | ||
274 | int i; | ||
275 | |||
276 | |||
277 | /* MCLCK on and set to 400kHz ident frequency */ | ||
278 | MCI_CLOCK(drive) = MCI_IDENTSPEED; | ||
279 | |||
280 | /* 100 - 400kHz clock required for Identification Mode */ | ||
281 | /* Start of Card Identification Mode ************************************/ | ||
282 | |||
283 | /* CMD0 Go Idle */ | ||
284 | if(!send_cmd(drive, SD_GO_IDLE_STATE, 0, MCI_NO_FLAGS, NULL)) | ||
285 | return -1; | ||
286 | mci_delay(); | ||
287 | |||
288 | /* CMD8 Check for v2 sd card. Must be sent before using ACMD41 | ||
289 | Non v2 cards will not respond to this command*/ | ||
290 | if(send_cmd(drive, SD_SEND_IF_COND, 0x1AA, MCI_RESP|MCI_ARG, &response)) | ||
291 | if((response & 0xFFF) == 0x1AA) | ||
292 | sd_v2 = true; | ||
293 | |||
294 | /* timeout for initialization is 1sec, from SD Specification 2.00 */ | ||
295 | init_timeout = current_tick + HZ; | ||
296 | |||
297 | do { | ||
298 | /* this timeout is the only valid error for this loop*/ | ||
299 | if(TIME_AFTER(current_tick, init_timeout)) | ||
300 | return -2; | ||
301 | |||
302 | /* app_cmd */ | ||
303 | send_cmd(drive, SD_APP_CMD, 0, MCI_RESP|MCI_ARG, &response); | ||
304 | |||
305 | /* ACMD41 For v2 cards set HCS bit[30] & send host voltage range to all */ | ||
306 | send_cmd(drive, SD_APP_OP_COND, (0x00FF8000 | (sd_v2 ? 1<<30 : 0)), | ||
307 | MCI_RESP|MCI_ARG, &card_info[drive].ocr); | ||
308 | |||
309 | } while(!(card_info[drive].ocr & (1<<31))); | ||
310 | |||
311 | /* CMD2 send CID */ | ||
312 | if(!send_cmd(drive, SD_ALL_SEND_CID, 0, MCI_RESP|MCI_LONG_RESP|MCI_ARG, | ||
313 | temp_reg)) | ||
314 | return -3; | ||
315 | |||
316 | for(i=0; i<4; i++) | ||
317 | card_info[drive].cid[3-i] = temp_reg[i]; | ||
318 | |||
319 | /* CMD3 send RCA */ | ||
320 | if(!send_cmd(drive, SD_SEND_RELATIVE_ADDR, 0, MCI_RESP|MCI_ARG, | ||
321 | &card_info[drive].rca)) | ||
322 | return -4; | ||
323 | |||
324 | /* End of Card Identification Mode ************************************/ | ||
325 | |||
326 | #ifdef HAVE_MULTIDRIVE /* The internal SDs are v1 */ | ||
327 | |||
328 | /* Try to switch V2 cards to HS timings, non HS seem to ignore this */ | ||
329 | if(sd_v2) | ||
330 | { | ||
331 | /* CMD7 w/rca: Select card to put it in TRAN state */ | ||
332 | if(!send_cmd(drive, SD_SELECT_CARD, card_info[drive].rca, MCI_ARG, NULL)) | ||
333 | return -5; | ||
334 | mci_delay(); | ||
335 | |||
336 | if(sd_wait_for_state(drive, SD_TRAN)) | ||
337 | return -6; | ||
338 | /* CMD6 */ | ||
339 | if(!send_cmd(drive, SD_SWITCH_FUNC, 0x80fffff1, MCI_ARG, NULL)) | ||
340 | return -7; | ||
341 | mci_delay(); | ||
342 | |||
343 | /* go back to STBY state so we can read csd */ | ||
344 | /* CMD7 w/rca=0: Deselect card to put it in STBY state */ | ||
345 | if(!send_cmd(drive, SD_DESELECT_CARD, 0, MCI_ARG, NULL)) | ||
346 | return -8; | ||
347 | mci_delay(); | ||
348 | } | ||
349 | #endif /* HAVE_MULTIDRIVE */ | ||
350 | |||
351 | /* CMD9 send CSD */ | ||
352 | if(!send_cmd(drive, SD_SEND_CSD, card_info[drive].rca, | ||
353 | MCI_RESP|MCI_LONG_RESP|MCI_ARG, temp_reg)) | ||
354 | return -9; | ||
355 | |||
356 | for(i=0; i<4; i++) | ||
357 | card_info[drive].csd[3-i] = temp_reg[i]; | ||
358 | |||
359 | sd_parse_csd(&card_info[drive]); | ||
360 | |||
361 | #if defined(HAVE_MULTIDRIVE) | ||
362 | hs_card = (card_info[drive].speed == 50000000); | ||
363 | #endif | ||
364 | |||
365 | /* Boost MCICLK to operating speed */ | ||
366 | if(drive == INTERNAL_AS3525) | ||
367 | MCI_CLOCK(drive) = MCI_HALFSPEED; /* MCICLK = IDE_CLK/2 = 25 MHz */ | ||
368 | #if defined(HAVE_MULTIDRIVE) | ||
369 | else | ||
370 | /* MCICLK = PCLK/2 = 31MHz(HS) or PCLK/4 = 15.5 Mhz (STD)*/ | ||
371 | MCI_CLOCK(drive) = (hs_card ? MCI_HALFSPEED : MCI_QUARTERSPEED); | ||
372 | #endif | ||
373 | |||
374 | /* CMD7 w/rca: Select card to put it in TRAN state */ | ||
375 | if(!send_cmd(drive, SD_SELECT_CARD, card_info[drive].rca, MCI_ARG, NULL)) | ||
376 | return -10; | ||
377 | mci_delay(); | ||
378 | |||
379 | /* | ||
380 | * enable bank switching | ||
381 | * without issuing this command, we only have access to 1/4 of the blocks | ||
382 | * of the first bank (0x1E9E00 blocks, which is the size reported in the | ||
383 | * CSD register) | ||
384 | */ | ||
385 | if(drive == INTERNAL_AS3525) | ||
386 | { | ||
387 | const int ret = sd_select_bank(-1); | ||
388 | if(ret < 0) | ||
389 | return ret -16; | ||
390 | } | ||
391 | |||
392 | card_info[drive].initialized = 1; | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | static void sd_thread(void) __attribute__((noreturn)); | ||
398 | static void sd_thread(void) | ||
399 | { | ||
400 | struct queue_event ev; | ||
401 | bool idle_notified = false; | ||
402 | |||
403 | while (1) | ||
404 | { | ||
405 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | ||
406 | |||
407 | switch ( ev.id ) | ||
408 | { | ||
409 | #ifdef HAVE_HOTSWAP | ||
410 | case SYS_HOTSWAP_INSERTED: | ||
411 | case SYS_HOTSWAP_EXTRACTED: | ||
412 | { | ||
413 | int microsd_init = 1; | ||
414 | fat_lock(); /* lock-out FAT activity first - | ||
415 | prevent deadlocking via disk_mount that | ||
416 | would cause a reverse-order attempt with | ||
417 | another thread */ | ||
418 | mutex_lock(&sd_mtx); /* lock-out card activity - direct calls | ||
419 | into driver that bypass the fat cache */ | ||
420 | |||
421 | /* We now have exclusive control of fat cache and ata */ | ||
422 | |||
423 | disk_unmount(SD_SLOT_AS3525); /* release "by force", ensure file | ||
424 | descriptors aren't leaked and any busy | ||
425 | ones are invalid if mounting */ | ||
426 | |||
427 | /* Force card init for new card, re-init for re-inserted one or | ||
428 | * clear if the last attempt to init failed with an error. */ | ||
429 | card_info[SD_SLOT_AS3525].initialized = 0; | ||
430 | |||
431 | if (ev.id == SYS_HOTSWAP_INSERTED) | ||
432 | { | ||
433 | sd_enable(true); | ||
434 | init_pl180_controller(SD_SLOT_AS3525); | ||
435 | microsd_init = sd_init_card(SD_SLOT_AS3525); | ||
436 | if (microsd_init < 0) /* initialisation failed */ | ||
437 | panicf("microSD init failed : %d", microsd_init); | ||
438 | |||
439 | microsd_init = disk_mount(SD_SLOT_AS3525); /* 0 if fail */ | ||
440 | } | ||
441 | |||
442 | /* | ||
443 | * Mount succeeded, or this was an EXTRACTED event, | ||
444 | * in both cases notify the system about the changed filesystems | ||
445 | */ | ||
446 | if (microsd_init) | ||
447 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
448 | |||
449 | /* Access is now safe */ | ||
450 | mutex_unlock(&sd_mtx); | ||
451 | fat_unlock(); | ||
452 | sd_enable(false); | ||
453 | } | ||
454 | break; | ||
455 | #endif | ||
456 | case SYS_TIMEOUT: | ||
457 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | ||
458 | { | ||
459 | idle_notified = false; | ||
460 | } | ||
461 | else | ||
462 | { | ||
463 | /* never let a timer wrap confuse us */ | ||
464 | next_yield = current_tick; | ||
465 | |||
466 | if (!idle_notified) | ||
467 | { | ||
468 | call_storage_idle_notifys(false); | ||
469 | idle_notified = true; | ||
470 | } | ||
471 | } | ||
472 | break; | ||
473 | |||
474 | case SYS_USB_CONNECTED: | ||
475 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
476 | /* Wait until the USB cable is extracted again */ | ||
477 | usb_wait_for_disconnect(&sd_queue); | ||
478 | |||
479 | break; | ||
480 | case SYS_USB_DISCONNECTED: | ||
481 | usb_acknowledge(SYS_USB_DISCONNECTED_ACK); | ||
482 | break; | ||
483 | } | ||
484 | } | ||
485 | } | ||
486 | |||
487 | static void init_pl180_controller(const int drive) | ||
488 | { | ||
489 | MCI_COMMAND(drive) = MCI_DATA_CTRL(drive) = 0; | ||
490 | MCI_CLEAR(drive) = 0x7ff; | ||
491 | |||
492 | MCI_MASK0(drive) = MCI_DATA_ERROR | MCI_DATA_END; | ||
493 | MCI_MASK1(drive) = 0; | ||
494 | #ifdef HAVE_MULTIDRIVE | ||
495 | VIC_INT_ENABLE = | ||
496 | (drive == INTERNAL_AS3525) ? INTERRUPT_NAND : INTERRUPT_MCI0; | ||
497 | |||
498 | /* setup isr for microsd monitoring */ | ||
499 | VIC_INT_ENABLE = (INTERRUPT_GPIOA); | ||
500 | /* clear previous irq */ | ||
501 | GPIOA_IC = (1<<2); | ||
502 | /* enable edge detecting */ | ||
503 | GPIOA_IS &= ~(1<<2); | ||
504 | /* detect both raising and falling edges */ | ||
505 | GPIOA_IBE |= (1<<2); | ||
506 | |||
507 | #else | ||
508 | VIC_INT_ENABLE = INTERRUPT_NAND; | ||
509 | #endif | ||
510 | |||
511 | MCI_POWER(drive) = MCI_POWER_UP | (MCI_VDD_3_0); /* OF Setting */ | ||
512 | mci_delay(); | ||
513 | |||
514 | MCI_POWER(drive) |= MCI_POWER_ON; | ||
515 | mci_delay(); | ||
516 | |||
517 | MCI_SELECT(drive) = 0; | ||
518 | |||
519 | /* Pl180 clocks get turned on at start of card init */ | ||
520 | } | ||
521 | |||
522 | int sd_init(void) | ||
523 | { | ||
524 | int ret; | ||
525 | CGU_IDE = (1<<6) /* enable non AHB interface*/ | ||
526 | | (AS3525_IDE_DIV << 2) | ||
527 | | AS3525_CLK_PLLA; /* clock source = PLLA */ | ||
528 | |||
529 | CGU_PERI |= CGU_NAF_CLOCK_ENABLE; | ||
530 | #ifdef HAVE_MULTIDRIVE | ||
531 | CGU_PERI |= CGU_MCI_CLOCK_ENABLE; | ||
532 | CCU_IO &= ~(1<<3); /* bits 3:2 = 01, xpd is SD interface */ | ||
533 | CCU_IO |= (1<<2); | ||
534 | #endif | ||
535 | |||
536 | wakeup_init(&transfer_completion_signal); | ||
537 | |||
538 | init_pl180_controller(INTERNAL_AS3525); | ||
539 | ret = sd_init_card(INTERNAL_AS3525); | ||
540 | if(ret < 0) | ||
541 | return ret; | ||
542 | #ifdef HAVE_MULTIDRIVE | ||
543 | init_pl180_controller(SD_SLOT_AS3525); | ||
544 | #endif | ||
545 | |||
546 | /* init mutex */ | ||
547 | mutex_init(&sd_mtx); | ||
548 | |||
549 | queue_init(&sd_queue, true); | ||
550 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0, | ||
551 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); | ||
552 | |||
553 | #ifndef BOOTLOADER | ||
554 | sd_enabled = true; | ||
555 | sd_enable(false); | ||
556 | #endif | ||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | #ifdef HAVE_HOTSWAP | ||
561 | bool sd_removable(IF_MD_NONVOID(int drive)) | ||
562 | { | ||
563 | return (drive==1); | ||
564 | } | ||
565 | |||
566 | bool sd_present(IF_MD_NONVOID(int drive)) | ||
567 | { | ||
568 | return (drive == 0) ? true : card_detect_target(); | ||
569 | } | ||
570 | #endif /* HAVE_HOTSWAP */ | ||
571 | |||
572 | static int sd_wait_for_state(const int drive, unsigned int state) | ||
573 | { | ||
574 | unsigned long response = 0; | ||
575 | unsigned int timeout = current_tick + 100; /* 100 ticks timeout */ | ||
576 | |||
577 | while (1) | ||
578 | { | ||
579 | if(!send_cmd(drive, SD_SEND_STATUS, card_info[drive].rca, | ||
580 | MCI_RESP|MCI_ARG, &response)) | ||
581 | return -1; | ||
582 | |||
583 | if (((response >> 9) & 0xf) == state) | ||
584 | return 0; | ||
585 | |||
586 | if(TIME_AFTER(current_tick, timeout)) | ||
587 | return -2; | ||
588 | |||
589 | if (TIME_AFTER(current_tick, next_yield)) | ||
590 | { | ||
591 | yield(); | ||
592 | next_yield = current_tick + MIN_YIELD_PERIOD; | ||
593 | } | ||
594 | } | ||
595 | } | ||
596 | |||
597 | static int sd_select_bank(signed char bank) | ||
598 | { | ||
599 | int ret; | ||
600 | unsigned loops = 0; | ||
601 | |||
602 | do { | ||
603 | if(loops++ > PL180_MAX_TRANSFER_ERRORS) | ||
604 | panicf("SD bank %d error : 0x%x", bank, | ||
605 | transfer_error[INTERNAL_AS3525]); | ||
606 | |||
607 | ret = sd_wait_for_state(INTERNAL_AS3525, SD_TRAN); | ||
608 | if (ret < 0) | ||
609 | return ret - 2; | ||
610 | |||
611 | if(!send_cmd(INTERNAL_AS3525, SD_SWITCH_FUNC, 0x80ffffef, MCI_ARG, NULL)) | ||
612 | return -1; | ||
613 | |||
614 | mci_delay(); | ||
615 | |||
616 | if(!send_cmd(INTERNAL_AS3525, 35, 0, MCI_NO_FLAGS, NULL)) | ||
617 | return -2; | ||
618 | |||
619 | mci_delay(); | ||
620 | |||
621 | memset(uncached_buffer, 0, 512); | ||
622 | if(bank == -1) | ||
623 | { /* enable bank switching */ | ||
624 | uncached_buffer[0] = 16; | ||
625 | uncached_buffer[1] = 1; | ||
626 | uncached_buffer[2] = 10; | ||
627 | } | ||
628 | else | ||
629 | uncached_buffer[0] = bank; | ||
630 | |||
631 | dma_retain(); | ||
632 | /* we don't use the uncached buffer here, because we need the | ||
633 | * physical memory address for DMA transfers */ | ||
634 | dma_enable_channel(0, aligned_buffer, MCI_FIFO(INTERNAL_AS3525), | ||
635 | DMA_PERI_SD, DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, | ||
636 | NULL); | ||
637 | |||
638 | MCI_DATA_TIMER(INTERNAL_AS3525) = SD_MAX_WRITE_TIMEOUT; | ||
639 | MCI_DATA_LENGTH(INTERNAL_AS3525) = 512; | ||
640 | MCI_DATA_CTRL(INTERNAL_AS3525) = (1<<0) /* enable */ | | ||
641 | (0<<1) /* transfer direction */ | | ||
642 | (1<<3) /* DMA */ | | ||
643 | (9<<4) /* 2^9 = 512 */ ; | ||
644 | |||
645 | /* Wakeup signal from NAND/MCIO isr on MCI_DATA_ERROR | MCI_DATA_END */ | ||
646 | wakeup_wait(&transfer_completion_signal, TIMEOUT_BLOCK); | ||
647 | |||
648 | /* Wait for FIFO to empty, card may still be in PRG state */ | ||
649 | while(MCI_STATUS(INTERNAL_AS3525) & MCI_TX_ACTIVE ); | ||
650 | |||
651 | dma_release(); | ||
652 | |||
653 | } while(transfer_error[INTERNAL_AS3525]); | ||
654 | |||
655 | card_info[INTERNAL_AS3525].current_bank = (bank == -1) ? 0 : bank; | ||
656 | |||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, | ||
661 | int count, void* buf, const bool write) | ||
662 | { | ||
663 | #ifndef HAVE_MULTIDRIVE | ||
664 | const int drive = 0; | ||
665 | #endif | ||
666 | int ret = 0; | ||
667 | unsigned loops = 0; | ||
668 | |||
669 | /* skip SanDisk OF */ | ||
670 | if (drive == INTERNAL_AS3525) | ||
671 | start += AMS_OF_SIZE; | ||
672 | |||
673 | mutex_lock(&sd_mtx); | ||
674 | #ifndef BOOTLOADER | ||
675 | sd_enable(true); | ||
676 | led(true); | ||
677 | #endif | ||
678 | |||
679 | if (card_info[drive].initialized <= 0) | ||
680 | { | ||
681 | ret = sd_init_card(drive); | ||
682 | if (!(card_info[drive].initialized)) | ||
683 | goto sd_transfer_error; | ||
684 | } | ||
685 | |||
686 | last_disk_activity = current_tick; | ||
687 | |||
688 | dma_retain(); | ||
689 | |||
690 | while(count) | ||
691 | { | ||
692 | /* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH | ||
693 | * register, so we have to transfer maximum 127 sectors at a time. */ | ||
694 | unsigned int transfer = (count >= 128) ? 127 : count; /* sectors */ | ||
695 | void *dma_buf; | ||
696 | const int cmd = | ||
697 | write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK; | ||
698 | unsigned long bank_start = start; | ||
699 | |||
700 | /* Only switch banks for internal storage */ | ||
701 | if(drive == INTERNAL_AS3525) | ||
702 | { | ||
703 | unsigned int bank = start / BLOCKS_PER_BANK; /* Current bank */ | ||
704 | |||
705 | /* Switch bank if needed */ | ||
706 | if(card_info[INTERNAL_AS3525].current_bank != bank) | ||
707 | { | ||
708 | ret = sd_select_bank(bank); | ||
709 | if (ret < 0) | ||
710 | { | ||
711 | ret -= 20; | ||
712 | goto sd_transfer_error; | ||
713 | } | ||
714 | } | ||
715 | |||
716 | /* Adjust start block in current bank */ | ||
717 | bank_start -= bank * BLOCKS_PER_BANK; | ||
718 | |||
719 | /* Do not cross a bank boundary in a single transfer loop */ | ||
720 | if((transfer + bank_start) > BLOCKS_PER_BANK) | ||
721 | transfer = BLOCKS_PER_BANK - bank_start; | ||
722 | } | ||
723 | |||
724 | /* Set bank_start to the correct unit (blocks or bytes) */ | ||
725 | if(!(card_info[drive].ocr & (1<<30))) /* not SDHC */ | ||
726 | bank_start *= SD_BLOCK_SIZE; | ||
727 | |||
728 | dma_buf = aligned_buffer; | ||
729 | if(transfer > UNALIGNED_NUM_SECTORS) | ||
730 | transfer = UNALIGNED_NUM_SECTORS; | ||
731 | |||
732 | if(write) | ||
733 | memcpy(uncached_buffer, buf, transfer * SD_BLOCK_SIZE); | ||
734 | |||
735 | ret = sd_wait_for_state(drive, SD_TRAN); | ||
736 | if (ret < 0) | ||
737 | { | ||
738 | ret -= 2*20; | ||
739 | goto sd_transfer_error; | ||
740 | } | ||
741 | |||
742 | if(!send_cmd(drive, cmd, bank_start, MCI_ARG, NULL)) | ||
743 | { | ||
744 | ret -= 3*20; | ||
745 | goto sd_transfer_error; | ||
746 | } | ||
747 | |||
748 | if(write) | ||
749 | { | ||
750 | dma_enable_channel(0, dma_buf, MCI_FIFO(drive), | ||
751 | (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT, | ||
752 | DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL); | ||
753 | |||
754 | /*Small delay for writes prevents data crc failures at lower freqs*/ | ||
755 | #ifdef HAVE_MULTIDRIVE | ||
756 | if((drive == SD_SLOT_AS3525) && !hs_card) | ||
757 | { | ||
758 | int write_delay = 125; | ||
759 | while(write_delay--); | ||
760 | } | ||
761 | #endif | ||
762 | } | ||
763 | else | ||
764 | dma_enable_channel(0, MCI_FIFO(drive), dma_buf, | ||
765 | (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT, | ||
766 | DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL); | ||
767 | |||
768 | MCI_DATA_TIMER(drive) = write ? | ||
769 | SD_MAX_WRITE_TIMEOUT : SD_MAX_READ_TIMEOUT; | ||
770 | MCI_DATA_LENGTH(drive) = transfer * SD_BLOCK_SIZE; | ||
771 | MCI_DATA_CTRL(drive) = (1<<0) /* enable */ | | ||
772 | (!write<<1) /* transfer direction */ | | ||
773 | (1<<3) /* DMA */ | | ||
774 | (9<<4) /* 2^9 = 512 */ ; | ||
775 | |||
776 | /* Wakeup signal from NAND/MCIO isr on MCI_DATA_ERROR | MCI_DATA_END */ | ||
777 | wakeup_wait(&transfer_completion_signal, TIMEOUT_BLOCK); | ||
778 | |||
779 | /* Wait for FIFO to empty, card may still be in PRG state for writes */ | ||
780 | while(MCI_STATUS(drive) & MCI_TX_ACTIVE); | ||
781 | |||
782 | last_disk_activity = current_tick; | ||
783 | |||
784 | if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_NO_FLAGS, NULL)) | ||
785 | { | ||
786 | ret = -4*20; | ||
787 | goto sd_transfer_error; | ||
788 | } | ||
789 | |||
790 | if(!transfer_error[drive]) | ||
791 | { | ||
792 | if(!write) | ||
793 | memcpy(buf, uncached_buffer, transfer * SD_BLOCK_SIZE); | ||
794 | buf += transfer * SD_BLOCK_SIZE; | ||
795 | start += transfer; | ||
796 | count -= transfer; | ||
797 | loops = 0; /* reset errors counter */ | ||
798 | } | ||
799 | else if(loops++ > PL180_MAX_TRANSFER_ERRORS) | ||
800 | panicf("SD Xfer %s err:0x%x Disk%d", (write? "write": "read"), | ||
801 | transfer_error[drive], drive); | ||
802 | } | ||
803 | |||
804 | ret = 0; /* success */ | ||
805 | |||
806 | sd_transfer_error: | ||
807 | |||
808 | dma_release(); | ||
809 | |||
810 | #ifndef BOOTLOADER | ||
811 | led(false); | ||
812 | sd_enable(false); | ||
813 | #endif | ||
814 | |||
815 | if (ret) /* error */ | ||
816 | card_info[drive].initialized = 0; | ||
817 | |||
818 | mutex_unlock(&sd_mtx); | ||
819 | return ret; | ||
820 | } | ||
821 | |||
822 | int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count, | ||
823 | void* buf) | ||
824 | { | ||
825 | return sd_transfer_sectors(IF_MD2(drive,) start, count, buf, false); | ||
826 | } | ||
827 | |||
828 | int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count, | ||
829 | const void* buf) | ||
830 | { | ||
831 | |||
832 | #ifdef BOOTLOADER /* we don't need write support in bootloader */ | ||
833 | #ifdef HAVE_MULTIDRIVE | ||
834 | (void) drive; | ||
835 | #endif | ||
836 | (void) start; | ||
837 | (void) count; | ||
838 | (void) buf; | ||
839 | return -1; | ||
840 | #else | ||
841 | return sd_transfer_sectors(IF_MD2(drive,) start, count, (void*)buf, true); | ||
842 | #endif | ||
843 | } | ||
844 | |||
845 | #ifndef BOOTLOADER | ||
846 | long sd_last_disk_activity(void) | ||
847 | { | ||
848 | return last_disk_activity; | ||
849 | } | ||
850 | |||
851 | void sd_enable(bool on) | ||
852 | { | ||
853 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) | ||
854 | extern int buttonlight_is_on; | ||
855 | #endif | ||
856 | |||
857 | #if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) | ||
858 | static bool cpu_boosted = false; | ||
859 | #endif | ||
860 | |||
861 | if (sd_enabled == on) | ||
862 | return; /* nothing to do */ | ||
863 | if(on) | ||
864 | { | ||
865 | /* Enable both NAF_CLOCK & IDE clk for internal SD */ | ||
866 | CGU_PERI |= CGU_NAF_CLOCK_ENABLE; | ||
867 | CGU_IDE |= (1<<6); /* enable non AHB interface*/ | ||
868 | #ifdef HAVE_MULTIDRIVE | ||
869 | /* Enable MCI clk for uSD */ | ||
870 | CGU_PERI |= CGU_MCI_CLOCK_ENABLE; | ||
871 | #ifdef HAVE_BUTTON_LIGHT | ||
872 | /* buttonlight AMSes need a bit of special handling for the buttonlight | ||
873 | * here due to the dual mapping of GPIOD and XPD */ | ||
874 | CCU_IO |= (1<<2); /* XPD is SD-MCI interface (b3:2 = 01) */ | ||
875 | if (buttonlight_is_on) | ||
876 | GPIOD_DIR &= ~(1<<7); | ||
877 | else | ||
878 | _buttonlight_off(); | ||
879 | #endif /* HAVE_BUTTON_LIGHT */ | ||
880 | #endif /* HAVE_MULTIDRIVE */ | ||
881 | sd_enabled = true; | ||
882 | |||
883 | #if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) | ||
884 | if(card_detect_target()) /* If SD card present Boost cpu for voltage */ | ||
885 | { | ||
886 | cpu_boosted = true; | ||
887 | cpu_boost(true); | ||
888 | } | ||
889 | #endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */ | ||
890 | } | ||
891 | else | ||
892 | { | ||
893 | #if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) | ||
894 | if(cpu_boosted) | ||
895 | { | ||
896 | cpu_boost(false); | ||
897 | cpu_boosted = false; | ||
898 | } | ||
899 | #endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */ | ||
900 | |||
901 | sd_enabled = false; | ||
902 | |||
903 | #ifdef HAVE_MULTIDRIVE | ||
904 | #ifdef HAVE_BUTTON_LIGHT | ||
905 | CCU_IO &= ~(1<<2); /* XPD is general purpose IO (b3:2 = 00) */ | ||
906 | if (buttonlight_is_on) | ||
907 | _buttonlight_on(); | ||
908 | #endif /* HAVE_BUTTON_LIGHT */ | ||
909 | /* Disable MCI clk for uSD */ | ||
910 | CGU_PERI &= ~CGU_MCI_CLOCK_ENABLE; | ||
911 | #endif /* HAVE_MULTIDRIVE */ | ||
912 | |||
913 | /* Disable both NAF_CLOCK & IDE clk for internal SD */ | ||
914 | CGU_PERI &= ~CGU_NAF_CLOCK_ENABLE; | ||
915 | CGU_IDE &= ~(1<<6); /* disable non AHB interface*/ | ||
916 | } | ||
917 | } | ||
918 | |||
919 | tCardInfo *card_get_info_target(int card_no) | ||
920 | { | ||
921 | return &card_info[card_no]; | ||
922 | } | ||
923 | |||
924 | #ifdef HAVE_HOTSWAP | ||
925 | void card_enable_monitoring_target(bool on) | ||
926 | { | ||
927 | if (on) /* enable interrupt */ | ||
928 | GPIOA_IE |= (1<<2); | ||
929 | else /* disable interrupt */ | ||
930 | GPIOA_IE &= ~(1<<2); | ||
931 | } | ||
932 | #endif /* HAVE_HOTSWAP */ | ||
933 | |||
934 | #endif /* !BOOTLOADER */ | ||
935 | |||
936 | #ifdef CONFIG_STORAGE_MULTI | ||
937 | int sd_num_drives(int first_drive) | ||
938 | { | ||
939 | /* We don't care which logical drive number(s) we have been assigned */ | ||
940 | (void)first_drive; | ||
941 | |||
942 | return NUM_DRIVES; | ||
943 | } | ||
944 | #endif /* CONFIG_STORAGE_MULTI */ | ||