diff options
author | Mark Arigo <markarigo@gmail.com> | 2008-05-13 01:53:19 +0000 |
---|---|---|
committer | Mark Arigo <markarigo@gmail.com> | 2008-05-13 01:53:19 +0000 |
commit | 76567482215b9d786ba329072b715729ea506b7e (patch) | |
tree | 18632252c5d0c0edd71cb76ad6d39dc26c33861f /firmware/target/arm/ata-sd-pp.c | |
parent | 1ab5caff29de51c09cd1c77de06610e199739967 (diff) | |
download | rockbox-76567482215b9d786ba329072b715729ea506b7e.tar.gz rockbox-76567482215b9d786ba329072b715729ea506b7e.zip |
Preparing for the Philips SA9200 part 1. Move the Sansa ADC & ATA drivers up one level.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17487 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/ata-sd-pp.c')
-rw-r--r-- | firmware/target/arm/ata-sd-pp.c | 1325 |
1 files changed, 1325 insertions, 0 deletions
diff --git a/firmware/target/arm/ata-sd-pp.c b/firmware/target/arm/ata-sd-pp.c new file mode 100644 index 0000000000..8c7ebcddc7 --- /dev/null +++ b/firmware/target/arm/ata-sd-pp.c | |||
@@ -0,0 +1,1325 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 Daniel Ankers | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include "fat.h" | ||
20 | #include "hotswap.h" | ||
21 | #ifdef BOOTLOADER | ||
22 | #include "ata-sd-target.h" | ||
23 | #endif | ||
24 | #include "ata_idle_notify.h" | ||
25 | #include "system.h" | ||
26 | #include <string.h> | ||
27 | #include "thread.h" | ||
28 | #include "led.h" | ||
29 | #include "disk.h" | ||
30 | #include "cpu.h" | ||
31 | #include "panic.h" | ||
32 | #include "usb.h" | ||
33 | |||
34 | #define BLOCK_SIZE 512 | ||
35 | #define SECTOR_SIZE 512 | ||
36 | #define BLOCKS_PER_BANK 0x7a7800 | ||
37 | |||
38 | #define STATUS_REG (*(volatile unsigned int *)(0x70008204)) | ||
39 | #define REG_1 (*(volatile unsigned int *)(0x70008208)) | ||
40 | #define UNKNOWN (*(volatile unsigned int *)(0x70008210)) | ||
41 | #define BLOCK_SIZE_REG (*(volatile unsigned int *)(0x7000821c)) | ||
42 | #define BLOCK_COUNT_REG (*(volatile unsigned int *)(0x70008220)) | ||
43 | #define REG_5 (*(volatile unsigned int *)(0x70008224)) | ||
44 | #define CMD_REG0 (*(volatile unsigned int *)(0x70008228)) | ||
45 | #define CMD_REG1 (*(volatile unsigned int *)(0x7000822c)) | ||
46 | #define CMD_REG2 (*(volatile unsigned int *)(0x70008230)) | ||
47 | #define RESPONSE_REG (*(volatile unsigned int *)(0x70008234)) | ||
48 | #define SD_STATE_REG (*(volatile unsigned int *)(0x70008238)) | ||
49 | #define REG_11 (*(volatile unsigned int *)(0x70008240)) | ||
50 | #define REG_12 (*(volatile unsigned int *)(0x70008244)) | ||
51 | #define DATA_REG (*(volatile unsigned int *)(0x70008280)) | ||
52 | |||
53 | /* STATUS_REG bits */ | ||
54 | #define DATA_DONE (1 << 12) | ||
55 | #define CMD_DONE (1 << 13) | ||
56 | #define ERROR_BITS (0x3f) | ||
57 | #define READY_FOR_DATA (1 << 8) | ||
58 | #define FIFO_FULL (1 << 7) | ||
59 | #define FIFO_EMPTY (1 << 6) | ||
60 | |||
61 | #define CMD_OK 0x0 /* Command was successful */ | ||
62 | #define CMD_ERROR_2 0x2 /* SD did not respond to command (either it doesn't | ||
63 | understand the command or is not inserted) */ | ||
64 | |||
65 | /* SD States */ | ||
66 | #define IDLE 0 | ||
67 | #define READY 1 | ||
68 | #define IDENT 2 | ||
69 | #define STBY 3 | ||
70 | #define TRAN 4 | ||
71 | #define DATA 5 | ||
72 | #define RCV 6 | ||
73 | #define PRG 7 | ||
74 | #define DIS 8 | ||
75 | |||
76 | #define FIFO_LEN 16 /* FIFO is 16 words deep */ | ||
77 | |||
78 | /* SD Commands */ | ||
79 | #define GO_IDLE_STATE 0 | ||
80 | #define ALL_SEND_CID 2 | ||
81 | #define SEND_RELATIVE_ADDR 3 | ||
82 | #define SET_DSR 4 | ||
83 | #define SWITCH_FUNC 6 | ||
84 | #define SELECT_CARD 7 | ||
85 | #define DESELECT_CARD 7 | ||
86 | #define SEND_IF_COND 8 | ||
87 | #define SEND_CSD 9 | ||
88 | #define SEND_CID 10 | ||
89 | #define STOP_TRANSMISSION 12 | ||
90 | #define SEND_STATUS 13 | ||
91 | #define GO_INACTIVE_STATE 15 | ||
92 | #define SET_BLOCKLEN 16 | ||
93 | #define READ_SINGLE_BLOCK 17 | ||
94 | #define READ_MULTIPLE_BLOCK 18 | ||
95 | #define SEND_NUM_WR_BLOCKS 22 | ||
96 | #define WRITE_BLOCK 24 | ||
97 | #define WRITE_MULTIPLE_BLOCK 25 | ||
98 | #define ERASE_WR_BLK_START 32 | ||
99 | #define ERASE_WR_BLK_END 33 | ||
100 | #define ERASE 38 | ||
101 | #define APP_CMD 55 | ||
102 | |||
103 | #define EC_OK 0 | ||
104 | #define EC_FAILED 1 | ||
105 | #define EC_NOCARD 2 | ||
106 | #define EC_WAIT_STATE_FAILED 3 | ||
107 | #define EC_CHECK_TIMEOUT_FAILED 4 | ||
108 | #define EC_POWER_UP 5 | ||
109 | #define EC_READ_TIMEOUT 6 | ||
110 | #define EC_WRITE_TIMEOUT 7 | ||
111 | #define EC_TRAN_SEL_BANK 8 | ||
112 | #define EC_TRAN_READ_ENTRY 9 | ||
113 | #define EC_TRAN_READ_EXIT 10 | ||
114 | #define EC_TRAN_WRITE_ENTRY 11 | ||
115 | #define EC_TRAN_WRITE_EXIT 12 | ||
116 | #define EC_FIFO_SEL_BANK_EMPTY 13 | ||
117 | #define EC_FIFO_SEL_BANK_DONE 14 | ||
118 | #define EC_FIFO_ENA_BANK_EMPTY 15 | ||
119 | #define EC_FIFO_READ_FULL 16 | ||
120 | #define EC_FIFO_WR_EMPTY 17 | ||
121 | #define EC_FIFO_WR_DONE 18 | ||
122 | #define EC_COMMAND 19 | ||
123 | #define NUM_EC 20 | ||
124 | |||
125 | /* Application Specific commands */ | ||
126 | #define SET_BUS_WIDTH 6 | ||
127 | #define SD_APP_OP_COND 41 | ||
128 | |||
129 | /** global, exported variables **/ | ||
130 | #ifdef HAVE_HOTSWAP | ||
131 | #define NUM_VOLUMES 2 | ||
132 | #else | ||
133 | #define NUM_VOLUMES 1 | ||
134 | #endif | ||
135 | |||
136 | /* for compatibility */ | ||
137 | int ata_spinup_time = 0; | ||
138 | |||
139 | long last_disk_activity = -1; | ||
140 | |||
141 | /** static, private data **/ | ||
142 | static bool initialized = false; | ||
143 | |||
144 | static long next_yield = 0; | ||
145 | #define MIN_YIELD_PERIOD 1000 | ||
146 | |||
147 | static tSDCardInfo card_info[2]; | ||
148 | static tSDCardInfo *currcard = NULL; /* current active card */ | ||
149 | |||
150 | struct sd_card_status | ||
151 | { | ||
152 | int retry; | ||
153 | int retry_max; | ||
154 | }; | ||
155 | |||
156 | static struct sd_card_status sd_status[NUM_VOLUMES] = | ||
157 | { | ||
158 | { 0, 1 }, | ||
159 | #ifdef HAVE_HOTSWAP | ||
160 | { 0, 10 } | ||
161 | #endif | ||
162 | }; | ||
163 | |||
164 | /* Shoot for around 75% usage */ | ||
165 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)]; | ||
166 | static const char sd_thread_name[] = "ata/sd"; | ||
167 | static struct mutex sd_mtx SHAREDBSS_ATTR; | ||
168 | static struct event_queue sd_queue; | ||
169 | |||
170 | /* Posted when card plugged status has changed */ | ||
171 | #define SD_HOTSWAP 1 | ||
172 | /* Actions taken by sd_thread when card status has changed */ | ||
173 | enum sd_thread_actions | ||
174 | { | ||
175 | SDA_NONE = 0x0, | ||
176 | SDA_UNMOUNTED = 0x1, | ||
177 | SDA_MOUNTED = 0x2 | ||
178 | }; | ||
179 | |||
180 | /* Private Functions */ | ||
181 | |||
182 | static unsigned int check_time[NUM_EC]; | ||
183 | |||
184 | static inline bool sd_check_timeout(long timeout, int id) | ||
185 | { | ||
186 | return !TIME_AFTER(USEC_TIMER, check_time[id] + timeout); | ||
187 | } | ||
188 | |||
189 | static bool sd_poll_status(unsigned int trigger, long timeout) | ||
190 | { | ||
191 | long t = USEC_TIMER; | ||
192 | |||
193 | while ((STATUS_REG & trigger) == 0) | ||
194 | { | ||
195 | long time = USEC_TIMER; | ||
196 | |||
197 | if (TIME_AFTER(time, next_yield)) | ||
198 | { | ||
199 | long ty = USEC_TIMER; | ||
200 | yield(); | ||
201 | timeout += USEC_TIMER - ty; | ||
202 | next_yield = ty + MIN_YIELD_PERIOD; | ||
203 | } | ||
204 | |||
205 | if (TIME_AFTER(time, t + timeout)) | ||
206 | return false; | ||
207 | } | ||
208 | |||
209 | return true; | ||
210 | } | ||
211 | |||
212 | static int sd_command(unsigned int cmd, unsigned long arg1, | ||
213 | unsigned int *response, unsigned int type) | ||
214 | { | ||
215 | int i, words; /* Number of 16 bit words to read from RESPONSE_REG */ | ||
216 | unsigned int data[9]; | ||
217 | |||
218 | CMD_REG0 = cmd; | ||
219 | CMD_REG1 = (unsigned int)((arg1 & 0xffff0000) >> 16); | ||
220 | CMD_REG2 = (unsigned int)((arg1 & 0xffff)); | ||
221 | UNKNOWN = type; | ||
222 | |||
223 | if (!sd_poll_status(CMD_DONE, 100000)) | ||
224 | return -EC_COMMAND; | ||
225 | |||
226 | if ((STATUS_REG & ERROR_BITS) != CMD_OK) | ||
227 | /* Error sending command */ | ||
228 | return -EC_COMMAND - (STATUS_REG & ERROR_BITS)*100; | ||
229 | |||
230 | if (cmd == GO_IDLE_STATE) | ||
231 | return 0; /* no response here */ | ||
232 | |||
233 | words = (type == 2) ? 9 : 3; | ||
234 | |||
235 | for (i = 0; i < words; i++) /* RESPONSE_REG is read MSB first */ | ||
236 | data[i] = RESPONSE_REG; /* Read most significant 16-bit word */ | ||
237 | |||
238 | if (response == NULL) | ||
239 | { | ||
240 | /* response discarded */ | ||
241 | } | ||
242 | else if (type == 2) | ||
243 | { | ||
244 | /* Response type 2 has the following structure: | ||
245 | * [135:135] Start Bit - '0' | ||
246 | * [134:134] Transmission bit - '0' | ||
247 | * [133:128] Reserved - '111111' | ||
248 | * [127:001] CID or CSD register including internal CRC7 | ||
249 | * [000:000] End Bit - '1' | ||
250 | */ | ||
251 | response[3] = (data[0]<<24) + (data[1]<<8) + (data[2]>>8); | ||
252 | response[2] = (data[2]<<24) + (data[3]<<8) + (data[4]>>8); | ||
253 | response[1] = (data[4]<<24) + (data[5]<<8) + (data[6]>>8); | ||
254 | response[0] = (data[6]<<24) + (data[7]<<8) + (data[8]>>8); | ||
255 | } | ||
256 | else | ||
257 | { | ||
258 | /* Response types 1, 1b, 3, 6, 7 have the following structure: | ||
259 | * Types 4 and 5 are not supported. | ||
260 | * | ||
261 | * [47] Start bit - '0' | ||
262 | * [46] Transmission bit - '0' | ||
263 | * [45:40] R1, R1b, R6, R7: Command index | ||
264 | * R3: Reserved - '111111' | ||
265 | * [39:8] R1, R1b: Card Status | ||
266 | * R3: OCR Register | ||
267 | * R6: [31:16] RCA | ||
268 | * [15: 0] Card Status Bits 23, 22, 19, 12:0 | ||
269 | * [23] COM_CRC_ERROR | ||
270 | * [22] ILLEGAL_COMMAND | ||
271 | * [19] ERROR | ||
272 | * [12:9] CURRENT_STATE | ||
273 | * [8] READY_FOR_DATA | ||
274 | * [7:6] | ||
275 | * [5] APP_CMD | ||
276 | * [4] | ||
277 | * [3] AKE_SEQ_ERROR | ||
278 | * [2] Reserved | ||
279 | * [1:0] Reserved for test mode | ||
280 | * R7: [19:16] Voltage accepted | ||
281 | * [15:8] echo-back of check pattern | ||
282 | * [7:1] R1, R1b: CRC7 | ||
283 | * R3: Reserved - '1111111' | ||
284 | * [0] End Bit - '1' | ||
285 | */ | ||
286 | response[0] = (data[0]<<24) + (data[1]<<8) + (data[2]>>8); | ||
287 | } | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int sd_wait_for_state(unsigned int state, int id) | ||
293 | { | ||
294 | unsigned int response = 0; | ||
295 | unsigned int timeout = 0x80000; | ||
296 | |||
297 | check_time[id] = USEC_TIMER; | ||
298 | |||
299 | while (1) | ||
300 | { | ||
301 | int ret = sd_command(SEND_STATUS, currcard->rca, &response, 1); | ||
302 | long us; | ||
303 | |||
304 | if (ret < 0) | ||
305 | return ret*100 - id; | ||
306 | |||
307 | if (((response >> 9) & 0xf) == state) | ||
308 | { | ||
309 | SD_STATE_REG = state; | ||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | if (!sd_check_timeout(timeout, id)) | ||
314 | return -EC_WAIT_STATE_FAILED*100 - id; | ||
315 | |||
316 | us = USEC_TIMER; | ||
317 | if (TIME_AFTER(us, next_yield)) | ||
318 | { | ||
319 | yield(); | ||
320 | timeout += USEC_TIMER - us; | ||
321 | next_yield = us + MIN_YIELD_PERIOD; | ||
322 | } | ||
323 | } | ||
324 | } | ||
325 | |||
326 | static inline void copy_read_sectors_fast(unsigned char **buf) | ||
327 | { | ||
328 | /* Copy one chunk of 16 words using best method for start alignment */ | ||
329 | switch ( (intptr_t)*buf & 3 ) | ||
330 | { | ||
331 | case 0: | ||
332 | asm volatile ( | ||
333 | "ldmia %[data], { r2-r9 } \r\n" | ||
334 | "orr r2, r2, r3, lsl #16 \r\n" | ||
335 | "orr r4, r4, r5, lsl #16 \r\n" | ||
336 | "orr r6, r6, r7, lsl #16 \r\n" | ||
337 | "orr r8, r8, r9, lsl #16 \r\n" | ||
338 | "stmia %[buf]!, { r2, r4, r6, r8 } \r\n" | ||
339 | "ldmia %[data], { r2-r9 } \r\n" | ||
340 | "orr r2, r2, r3, lsl #16 \r\n" | ||
341 | "orr r4, r4, r5, lsl #16 \r\n" | ||
342 | "orr r6, r6, r7, lsl #16 \r\n" | ||
343 | "orr r8, r8, r9, lsl #16 \r\n" | ||
344 | "stmia %[buf]!, { r2, r4, r6, r8 } \r\n" | ||
345 | : [buf]"+&r"(*buf) | ||
346 | : [data]"r"(&DATA_REG) | ||
347 | : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" | ||
348 | ); | ||
349 | break; | ||
350 | case 1: | ||
351 | asm volatile ( | ||
352 | "ldmia %[data], { r2-r9 } \r\n" | ||
353 | "orr r3, r2, r3, lsl #16 \r\n" | ||
354 | "strb r3, [%[buf]], #1 \r\n" | ||
355 | "mov r3, r3, lsr #8 \r\n" | ||
356 | "strh r3, [%[buf]], #2 \r\n" | ||
357 | "mov r3, r3, lsr #16 \r\n" | ||
358 | "orr r3, r3, r4, lsl #8 \r\n" | ||
359 | "orr r3, r3, r5, lsl #24 \r\n" | ||
360 | "mov r5, r5, lsr #8 \r\n" | ||
361 | "orr r5, r5, r6, lsl #8 \r\n" | ||
362 | "orr r5, r5, r7, lsl #24 \r\n" | ||
363 | "mov r7, r7, lsr #8 \r\n" | ||
364 | "orr r7, r7, r8, lsl #8 \r\n" | ||
365 | "orr r7, r7, r9, lsl #24 \r\n" | ||
366 | "mov r2, r9, lsr #8 \r\n" | ||
367 | "stmia %[buf]!, { r3, r5, r7 } \r\n" | ||
368 | "ldmia %[data], { r3-r10 } \r\n" | ||
369 | "orr r2, r2, r3, lsl #8 \r\n" | ||
370 | "orr r2, r2, r4, lsl #24 \r\n" | ||
371 | "mov r4, r4, lsr #8 \r\n" | ||
372 | "orr r4, r4, r5, lsl #8 \r\n" | ||
373 | "orr r4, r4, r6, lsl #24 \r\n" | ||
374 | "mov r6, r6, lsr #8 \r\n" | ||
375 | "orr r6, r6, r7, lsl #8 \r\n" | ||
376 | "orr r6, r6, r8, lsl #24 \r\n" | ||
377 | "mov r8, r8, lsr #8 \r\n" | ||
378 | "orr r8, r8, r9, lsl #8 \r\n" | ||
379 | "orr r8, r8, r10, lsl #24 \r\n" | ||
380 | "mov r10, r10, lsr #8 \r\n" | ||
381 | "stmia %[buf]!, { r2, r4, r6, r8 } \r\n" | ||
382 | "strb r10, [%[buf]], #1 \r\n" | ||
383 | : [buf]"+&r"(*buf) | ||
384 | : [data]"r"(&DATA_REG) | ||
385 | : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" | ||
386 | ); | ||
387 | break; | ||
388 | case 2: | ||
389 | asm volatile ( | ||
390 | "ldmia %[data], { r2-r9 } \r\n" | ||
391 | "strh r2, [%[buf]], #2 \r\n" | ||
392 | "orr r3, r3, r4, lsl #16 \r\n" | ||
393 | "orr r5, r5, r6, lsl #16 \r\n" | ||
394 | "orr r7, r7, r8, lsl #16 \r\n" | ||
395 | "stmia %[buf]!, { r3, r5, r7 } \r\n" | ||
396 | "ldmia %[data], { r2-r8, r10 } \r\n" | ||
397 | "orr r2, r9, r2, lsl #16 \r\n" | ||
398 | "orr r3, r3, r4, lsl #16 \r\n" | ||
399 | "orr r5, r5, r6, lsl #16 \r\n" | ||
400 | "orr r7, r7, r8, lsl #16 \r\n" | ||
401 | "stmia %[buf]!, { r2, r3, r5, r7 } \r\n" | ||
402 | "strh r10, [%[buf]], #2 \r\n" | ||
403 | : [buf]"+&r"(*buf) | ||
404 | : [data]"r"(&DATA_REG) | ||
405 | : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" | ||
406 | ); | ||
407 | break; | ||
408 | case 3: | ||
409 | asm volatile ( | ||
410 | "ldmia %[data], { r2-r9 } \r\n" | ||
411 | "orr r3, r2, r3, lsl #16 \r\n" | ||
412 | "strb r3, [%[buf]], #1 \r\n" | ||
413 | "mov r3, r3, lsr #8 \r\n" | ||
414 | "orr r3, r3, r4, lsl #24 \r\n" | ||
415 | "mov r4, r4, lsr #8 \r\n" | ||
416 | "orr r5, r4, r5, lsl #8 \r\n" | ||
417 | "orr r5, r5, r6, lsl #24 \r\n" | ||
418 | "mov r6, r6, lsr #8 \r\n" | ||
419 | "orr r7, r6, r7, lsl #8 \r\n" | ||
420 | "orr r7, r7, r8, lsl #24 \r\n" | ||
421 | "mov r8, r8, lsr #8 \r\n" | ||
422 | "orr r2, r8, r9, lsl #8 \r\n" | ||
423 | "stmia %[buf]!, { r3, r5, r7 } \r\n" | ||
424 | "ldmia %[data], { r3-r10 } \r\n" | ||
425 | "orr r2, r2, r3, lsl #24 \r\n" | ||
426 | "mov r3, r3, lsr #8 \r\n" | ||
427 | "orr r4, r3, r4, lsl #8 \r\n" | ||
428 | "orr r4, r4, r5, lsl #24 \r\n" | ||
429 | "mov r5, r5, lsr #8 \r\n" | ||
430 | "orr r6, r5, r6, lsl #8 \r\n" | ||
431 | "orr r6, r6, r7, lsl #24 \r\n" | ||
432 | "mov r7, r7, lsr #8 \r\n" | ||
433 | "orr r8, r7, r8, lsl #8 \r\n" | ||
434 | "orr r8, r8, r9, lsl #24 \r\n" | ||
435 | "mov r9, r9, lsr #8 \r\n" | ||
436 | "orr r10, r9, r10, lsl #8 \r\n" | ||
437 | "stmia %[buf]!, { r2, r4, r6, r8 } \r\n" | ||
438 | "strh r10, [%[buf]], #2 \r\n" | ||
439 | "mov r10, r10, lsr #16 \r\n" | ||
440 | "strb r10, [%[buf]], #1 \r\n" | ||
441 | : [buf]"+&r"(*buf) | ||
442 | : [data]"r"(&DATA_REG) | ||
443 | : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" | ||
444 | ); | ||
445 | break; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | static inline void copy_read_sectors_slow(unsigned char** buf) | ||
450 | { | ||
451 | int cnt = FIFO_LEN; | ||
452 | int t; | ||
453 | |||
454 | /* Copy one chunk of 16 words */ | ||
455 | asm volatile ( | ||
456 | "1: \r\n" | ||
457 | "ldrh %[t], [%[data]] \r\n" | ||
458 | "strb %[t], [%[buf]], #1 \r\n" | ||
459 | "mov %[t], %[t], lsr #8 \r\n" | ||
460 | "strb %[t], [%[buf]], #1 \r\n" | ||
461 | "subs %[cnt], %[cnt], #1 \r\n" | ||
462 | "bgt 1b \r\n" | ||
463 | : [cnt]"+&r"(cnt), [buf]"+&r"(*buf), | ||
464 | [t]"=&r"(t) | ||
465 | : [data]"r"(&DATA_REG) | ||
466 | ); | ||
467 | } | ||
468 | |||
469 | /* Writes have to be kept slow for now */ | ||
470 | static inline void copy_write_sectors(const unsigned char** buf) | ||
471 | { | ||
472 | int cnt = FIFO_LEN; | ||
473 | unsigned t; | ||
474 | |||
475 | do | ||
476 | { | ||
477 | t = *(*buf)++; | ||
478 | t |= *(*buf)++ << 8; | ||
479 | DATA_REG = t; | ||
480 | } while (--cnt > 0); /* tail loop is faster */ | ||
481 | } | ||
482 | |||
483 | static int sd_select_bank(unsigned char bank) | ||
484 | { | ||
485 | unsigned char card_data[512]; | ||
486 | const unsigned char* write_buf; | ||
487 | int i, ret; | ||
488 | |||
489 | memset(card_data, 0, 512); | ||
490 | |||
491 | ret = sd_wait_for_state(TRAN, EC_TRAN_SEL_BANK); | ||
492 | if (ret < 0) | ||
493 | return ret; | ||
494 | |||
495 | BLOCK_SIZE_REG = 512; | ||
496 | BLOCK_COUNT_REG = 1; | ||
497 | |||
498 | ret = sd_command(35, 0, NULL, 0x1c0d); /* CMD35 is vendor specific */ | ||
499 | if (ret < 0) | ||
500 | return ret; | ||
501 | |||
502 | SD_STATE_REG = PRG; | ||
503 | |||
504 | card_data[0] = bank; | ||
505 | |||
506 | /* Write the card data */ | ||
507 | write_buf = card_data; | ||
508 | for (i = 0; i < BLOCK_SIZE/2; i += FIFO_LEN) | ||
509 | { | ||
510 | /* Wait for the FIFO to empty */ | ||
511 | if (sd_poll_status(FIFO_EMPTY, 10000)) | ||
512 | { | ||
513 | copy_write_sectors(&write_buf); /* Copy one chunk of 16 words */ | ||
514 | continue; | ||
515 | } | ||
516 | |||
517 | return -EC_FIFO_SEL_BANK_EMPTY; | ||
518 | } | ||
519 | |||
520 | if (!sd_poll_status(DATA_DONE, 10000)) | ||
521 | return -EC_FIFO_SEL_BANK_DONE; | ||
522 | |||
523 | currcard->current_bank = bank; | ||
524 | |||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | static void sd_card_mux(int card_no) | ||
529 | { | ||
530 | /* Set the current card mux */ | ||
531 | #ifdef SANSA_E200 | ||
532 | if (card_no == 0) | ||
533 | { | ||
534 | GPO32_VAL |= 0x4; | ||
535 | |||
536 | GPIO_CLEAR_BITWISE(GPIOA_ENABLE, 0x7a); | ||
537 | GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x7a); | ||
538 | GPIO_SET_BITWISE(GPIOD_ENABLE, 0x1f); | ||
539 | GPIO_SET_BITWISE(GPIOD_OUTPUT_VAL, 0x1f); | ||
540 | GPIO_SET_BITWISE(GPIOD_OUTPUT_EN, 0x1f); | ||
541 | |||
542 | outl((inl(0x70000014) & ~(0x3ffff)) | 0x255aa, 0x70000014); | ||
543 | } | ||
544 | else | ||
545 | { | ||
546 | GPO32_VAL &= ~0x4; | ||
547 | |||
548 | GPIO_CLEAR_BITWISE(GPIOD_ENABLE, 0x1f); | ||
549 | GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_EN, 0x1f); | ||
550 | GPIO_SET_BITWISE(GPIOA_ENABLE, 0x7a); | ||
551 | GPIO_SET_BITWISE(GPIOA_OUTPUT_VAL, 0x7a); | ||
552 | GPIO_SET_BITWISE( GPIOA_OUTPUT_EN, 0x7a); | ||
553 | |||
554 | outl(inl(0x70000014) & ~(0x3ffff), 0x70000014); | ||
555 | } | ||
556 | #else /* SANSA_C200 */ | ||
557 | if (card_no == 0) | ||
558 | { | ||
559 | GPO32_VAL |= 0x4; | ||
560 | |||
561 | GPIO_CLEAR_BITWISE(GPIOD_ENABLE, 0x1f); | ||
562 | GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_EN, 0x1f); | ||
563 | GPIO_SET_BITWISE(GPIOA_ENABLE, 0x7a); | ||
564 | GPIO_SET_BITWISE(GPIOA_OUTPUT_VAL, 0x7a); | ||
565 | GPIO_SET_BITWISE( GPIOA_OUTPUT_EN, 0x7a); | ||
566 | |||
567 | outl(inl(0x70000014) & ~(0x3ffff), 0x70000014); | ||
568 | } | ||
569 | else | ||
570 | { | ||
571 | GPO32_VAL &= ~0x4; | ||
572 | |||
573 | GPIO_CLEAR_BITWISE(GPIOA_ENABLE, 0x7a); | ||
574 | GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x7a); | ||
575 | GPIO_SET_BITWISE(GPIOD_ENABLE, 0x1f); | ||
576 | GPIO_SET_BITWISE(GPIOD_OUTPUT_VAL, 0x1f); | ||
577 | GPIO_SET_BITWISE(GPIOD_OUTPUT_EN, 0x1f); | ||
578 | |||
579 | outl((inl(0x70000014) & ~(0x3ffff)) | 0x255aa, 0x70000014); | ||
580 | } | ||
581 | #endif | ||
582 | } | ||
583 | |||
584 | static void sd_init_device(int card_no) | ||
585 | { | ||
586 | /* SD Protocol registers */ | ||
587 | #ifdef HAVE_HOTSWAP | ||
588 | unsigned int response = 0; | ||
589 | #endif | ||
590 | unsigned int i; | ||
591 | unsigned int c_size; | ||
592 | unsigned long c_mult; | ||
593 | unsigned char carddata[512]; | ||
594 | unsigned char *dataptr; | ||
595 | int ret; | ||
596 | |||
597 | /* Enable and initialise controller */ | ||
598 | REG_1 = 6; | ||
599 | |||
600 | /* Initialise card data as blank */ | ||
601 | memset(currcard, 0, sizeof(*currcard)); | ||
602 | |||
603 | /* Switch card mux to card to initialize */ | ||
604 | sd_card_mux(card_no); | ||
605 | |||
606 | /* Init NAND */ | ||
607 | REG_11 |= (1 << 15); | ||
608 | REG_12 |= (1 << 15); | ||
609 | REG_12 &= ~(3 << 12); | ||
610 | REG_12 |= (1 << 13); | ||
611 | REG_11 &= ~(3 << 12); | ||
612 | REG_11 |= (1 << 13); | ||
613 | |||
614 | DEV_EN |= DEV_ATA; /* Enable controller */ | ||
615 | DEV_RS |= DEV_ATA; /* Reset controller */ | ||
616 | DEV_RS &=~DEV_ATA; /* Clear Reset */ | ||
617 | |||
618 | SD_STATE_REG = TRAN; | ||
619 | |||
620 | REG_5 = 0xf; | ||
621 | |||
622 | ret = sd_command(GO_IDLE_STATE, 0, NULL, 256); | ||
623 | if (ret < 0) | ||
624 | goto card_init_error; | ||
625 | |||
626 | check_time[EC_POWER_UP] = USEC_TIMER; | ||
627 | |||
628 | #ifdef HAVE_HOTSWAP | ||
629 | /* Check for SDHC: | ||
630 | - non-SDHC cards simply ignore SEND_IF_COND (CMD8) and we get error -219, | ||
631 | which we can just ignore and assume we're dealing with standard SD. | ||
632 | - SDHC cards echo back the argument into the response. This is how we | ||
633 | tell if the card is SDHC. | ||
634 | */ | ||
635 | ret = sd_command(SEND_IF_COND,0x1aa, &response,7); | ||
636 | if ( (ret < 0) && (ret!=-219) ) | ||
637 | goto card_init_error; | ||
638 | #endif | ||
639 | |||
640 | while ((currcard->ocr & (1 << 31)) == 0) /* until card is powered up */ | ||
641 | { | ||
642 | ret = sd_command(APP_CMD, currcard->rca, NULL, 1); | ||
643 | if (ret < 0) | ||
644 | goto card_init_error; | ||
645 | |||
646 | #ifdef HAVE_HOTSWAP | ||
647 | if(response == 0x1aa) | ||
648 | { | ||
649 | /* SDHC */ | ||
650 | ret = sd_command(SD_APP_OP_COND, (1<<30)|0x100000, | ||
651 | &currcard->ocr, 3); | ||
652 | } | ||
653 | else | ||
654 | #endif /* HAVE_HOTSWAP */ | ||
655 | { | ||
656 | /* SD Standard */ | ||
657 | ret = sd_command(SD_APP_OP_COND, 0x100000, &currcard->ocr, 3); | ||
658 | } | ||
659 | |||
660 | if (ret < 0) | ||
661 | goto card_init_error; | ||
662 | |||
663 | if (!sd_check_timeout(5000000, EC_POWER_UP)) | ||
664 | { | ||
665 | ret = -EC_POWER_UP; | ||
666 | goto card_init_error; | ||
667 | } | ||
668 | } | ||
669 | |||
670 | ret = sd_command(ALL_SEND_CID, 0, currcard->cid, 2); | ||
671 | if (ret < 0) | ||
672 | goto card_init_error; | ||
673 | |||
674 | ret = sd_command(SEND_RELATIVE_ADDR, 0, &currcard->rca, 1); | ||
675 | if (ret < 0) | ||
676 | goto card_init_error; | ||
677 | |||
678 | ret = sd_command(SEND_CSD, currcard->rca, currcard->csd, 2); | ||
679 | if (ret < 0) | ||
680 | goto card_init_error; | ||
681 | |||
682 | /* These calculations come from the Sandisk SD card product manual */ | ||
683 | if( (currcard->csd[3]>>30) == 0) | ||
684 | { | ||
685 | /* CSD version 1.0 */ | ||
686 | c_size = ((currcard->csd[2] & 0x3ff) << 2) + (currcard->csd[1]>>30) + 1; | ||
687 | c_mult = 4 << ((currcard->csd[1] >> 15) & 7); | ||
688 | currcard->max_read_bl_len = 1 << ((currcard->csd[2] >> 16) & 15); | ||
689 | currcard->block_size = BLOCK_SIZE; /* Always use 512 byte blocks */ | ||
690 | currcard->numblocks = c_size * c_mult * (currcard->max_read_bl_len/512); | ||
691 | currcard->capacity = currcard->numblocks * currcard->block_size; | ||
692 | } | ||
693 | #ifdef HAVE_HOTSWAP | ||
694 | else if( (currcard->csd[3]>>30) == 1) | ||
695 | { | ||
696 | /* CSD version 2.0 */ | ||
697 | c_size = ((currcard->csd[2] & 0x3f) << 16) + (currcard->csd[1]>>16) + 1; | ||
698 | currcard->max_read_bl_len = 1 << ((currcard->csd[2] >> 16) & 0xf); | ||
699 | currcard->block_size = BLOCK_SIZE; /* Always use 512 byte blocks */ | ||
700 | currcard->numblocks = c_size << 10; | ||
701 | currcard->capacity = currcard->numblocks * currcard->block_size; | ||
702 | } | ||
703 | #endif /* HAVE_HOTSWAP */ | ||
704 | |||
705 | REG_1 = 0; | ||
706 | |||
707 | ret = sd_command(SELECT_CARD, currcard->rca, NULL, 129); | ||
708 | if (ret < 0) | ||
709 | goto card_init_error; | ||
710 | |||
711 | ret = sd_command(APP_CMD, currcard->rca, NULL, 1); | ||
712 | if (ret < 0) | ||
713 | goto card_init_error; | ||
714 | |||
715 | ret = sd_command(SET_BUS_WIDTH, currcard->rca | 2, NULL, 1); /* 4 bit */ | ||
716 | if (ret < 0) | ||
717 | goto card_init_error; | ||
718 | |||
719 | ret = sd_command(SET_BLOCKLEN, currcard->block_size, NULL, 1); | ||
720 | if (ret < 0) | ||
721 | goto card_init_error; | ||
722 | |||
723 | BLOCK_SIZE_REG = currcard->block_size; | ||
724 | |||
725 | /* If this card is >4GB & not SDHC, then we need to enable bank switching */ | ||
726 | if( (currcard->numblocks >= BLOCKS_PER_BANK) && | ||
727 | ((currcard->ocr & (1<<30)) == 0) ) | ||
728 | { | ||
729 | SD_STATE_REG = TRAN; | ||
730 | BLOCK_COUNT_REG = 1; | ||
731 | |||
732 | ret = sd_command(SWITCH_FUNC, 0x80ffffef, NULL, 0x1c05); | ||
733 | if (ret < 0) | ||
734 | goto card_init_error; | ||
735 | |||
736 | /* Read 512 bytes from the card. | ||
737 | The first 512 bits contain the status information | ||
738 | TODO: Do something useful with this! */ | ||
739 | dataptr = carddata; | ||
740 | for (i = 0; i < BLOCK_SIZE/2; i += FIFO_LEN) | ||
741 | { | ||
742 | /* Wait for the FIFO to be full */ | ||
743 | if (sd_poll_status(FIFO_FULL, 100000)) | ||
744 | { | ||
745 | copy_read_sectors_slow(&dataptr); | ||
746 | continue; | ||
747 | } | ||
748 | |||
749 | ret = -EC_FIFO_ENA_BANK_EMPTY; | ||
750 | goto card_init_error; | ||
751 | } | ||
752 | } | ||
753 | |||
754 | currcard->initialized = 1; | ||
755 | return; | ||
756 | |||
757 | /* Card failed to initialize so disable it */ | ||
758 | card_init_error: | ||
759 | currcard->initialized = ret; | ||
760 | } | ||
761 | |||
762 | /* lock must already be aquired */ | ||
763 | static void sd_select_device(int card_no) | ||
764 | { | ||
765 | currcard = &card_info[card_no]; | ||
766 | |||
767 | if (card_no == 0) | ||
768 | { | ||
769 | /* Main card always gets a chance */ | ||
770 | sd_status[0].retry = 0; | ||
771 | } | ||
772 | |||
773 | if (currcard->initialized > 0) | ||
774 | { | ||
775 | /* This card is already initialized - switch to it */ | ||
776 | sd_card_mux(card_no); | ||
777 | return; | ||
778 | } | ||
779 | |||
780 | if (currcard->initialized == 0) | ||
781 | { | ||
782 | /* Card needs (re)init */ | ||
783 | sd_init_device(card_no); | ||
784 | } | ||
785 | } | ||
786 | |||
787 | /* API Functions */ | ||
788 | |||
789 | static void ata_led(bool onoff) | ||
790 | { | ||
791 | led(onoff); | ||
792 | } | ||
793 | |||
794 | int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, | ||
795 | void* inbuf) | ||
796 | { | ||
797 | #ifndef HAVE_HOTSWAP | ||
798 | const int drive = 0; | ||
799 | #endif | ||
800 | int ret; | ||
801 | unsigned char *buf, *buf_end; | ||
802 | int bank; | ||
803 | |||
804 | /* TODO: Add DMA support. */ | ||
805 | |||
806 | mutex_lock(&sd_mtx); | ||
807 | |||
808 | ata_led(true); | ||
809 | |||
810 | ata_read_retry: | ||
811 | if (drive != 0 && !card_detect_target()) | ||
812 | { | ||
813 | /* no external sd-card inserted */ | ||
814 | ret = -EC_NOCARD; | ||
815 | goto ata_read_error; | ||
816 | } | ||
817 | |||
818 | sd_select_device(drive); | ||
819 | |||
820 | if (currcard->initialized < 0) | ||
821 | { | ||
822 | ret = currcard->initialized; | ||
823 | goto ata_read_error; | ||
824 | } | ||
825 | |||
826 | last_disk_activity = current_tick; | ||
827 | |||
828 | /* Only switch banks with non-SDHC cards */ | ||
829 | if((currcard->ocr & (1<<30))==0) | ||
830 | { | ||
831 | bank = start / BLOCKS_PER_BANK; | ||
832 | |||
833 | if (currcard->current_bank != bank) | ||
834 | { | ||
835 | ret = sd_select_bank(bank); | ||
836 | if (ret < 0) | ||
837 | goto ata_read_error; | ||
838 | } | ||
839 | |||
840 | start -= bank * BLOCKS_PER_BANK; | ||
841 | } | ||
842 | |||
843 | ret = sd_wait_for_state(TRAN, EC_TRAN_READ_ENTRY); | ||
844 | if (ret < 0) | ||
845 | goto ata_read_error; | ||
846 | |||
847 | BLOCK_COUNT_REG = incount; | ||
848 | |||
849 | #ifdef HAVE_HOTSWAP | ||
850 | if(currcard->ocr & (1<<30) ) | ||
851 | { | ||
852 | /* SDHC */ | ||
853 | ret = sd_command(READ_MULTIPLE_BLOCK, start, NULL, 0x1c25); | ||
854 | } | ||
855 | else | ||
856 | #endif | ||
857 | { | ||
858 | ret = sd_command(READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, NULL, 0x1c25); | ||
859 | } | ||
860 | if (ret < 0) | ||
861 | goto ata_read_error; | ||
862 | |||
863 | /* TODO: Don't assume BLOCK_SIZE == SECTOR_SIZE */ | ||
864 | |||
865 | buf_end = (unsigned char *)inbuf + incount * currcard->block_size; | ||
866 | for (buf = inbuf; buf < buf_end;) | ||
867 | { | ||
868 | /* Wait for the FIFO to be full */ | ||
869 | if (sd_poll_status(FIFO_FULL, 0x80000)) | ||
870 | { | ||
871 | copy_read_sectors_fast(&buf); /* Copy one chunk of 16 words */ | ||
872 | /* TODO: Switch bank if necessary */ | ||
873 | continue; | ||
874 | } | ||
875 | |||
876 | ret = -EC_FIFO_READ_FULL; | ||
877 | goto ata_read_error; | ||
878 | } | ||
879 | |||
880 | last_disk_activity = current_tick; | ||
881 | |||
882 | ret = sd_command(STOP_TRANSMISSION, 0, NULL, 1); | ||
883 | if (ret < 0) | ||
884 | goto ata_read_error; | ||
885 | |||
886 | ret = sd_wait_for_state(TRAN, EC_TRAN_READ_EXIT); | ||
887 | if (ret < 0) | ||
888 | goto ata_read_error; | ||
889 | |||
890 | while (1) | ||
891 | { | ||
892 | ata_led(false); | ||
893 | mutex_unlock(&sd_mtx); | ||
894 | |||
895 | return ret; | ||
896 | |||
897 | ata_read_error: | ||
898 | if (sd_status[drive].retry < sd_status[drive].retry_max | ||
899 | && ret != -EC_NOCARD) | ||
900 | { | ||
901 | sd_status[drive].retry++; | ||
902 | currcard->initialized = 0; | ||
903 | goto ata_read_retry; | ||
904 | } | ||
905 | } | ||
906 | } | ||
907 | |||
908 | int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, | ||
909 | const void* outbuf) | ||
910 | { | ||
911 | /* Write support is not finished yet */ | ||
912 | /* TODO: The standard suggests using ACMD23 prior to writing multiple blocks | ||
913 | to improve performance */ | ||
914 | #ifndef HAVE_HOTSWAP | ||
915 | const int drive = 0; | ||
916 | #endif | ||
917 | int ret; | ||
918 | const unsigned char *buf, *buf_end; | ||
919 | int bank; | ||
920 | |||
921 | mutex_lock(&sd_mtx); | ||
922 | |||
923 | ata_led(true); | ||
924 | |||
925 | ata_write_retry: | ||
926 | if (drive != 0 && !card_detect_target()) | ||
927 | { | ||
928 | /* no external sd-card inserted */ | ||
929 | ret = -EC_NOCARD; | ||
930 | goto ata_write_error; | ||
931 | } | ||
932 | |||
933 | sd_select_device(drive); | ||
934 | |||
935 | if (currcard->initialized < 0) | ||
936 | { | ||
937 | ret = currcard->initialized; | ||
938 | goto ata_write_error; | ||
939 | } | ||
940 | |||
941 | /* Only switch banks with non-SDHC cards */ | ||
942 | if((currcard->ocr & (1<<30))==0) | ||
943 | { | ||
944 | bank = start / BLOCKS_PER_BANK; | ||
945 | |||
946 | if (currcard->current_bank != bank) | ||
947 | { | ||
948 | ret = sd_select_bank(bank); | ||
949 | if (ret < 0) | ||
950 | goto ata_write_error; | ||
951 | } | ||
952 | |||
953 | start -= bank * BLOCKS_PER_BANK; | ||
954 | } | ||
955 | |||
956 | check_time[EC_WRITE_TIMEOUT] = USEC_TIMER; | ||
957 | |||
958 | ret = sd_wait_for_state(TRAN, EC_TRAN_WRITE_ENTRY); | ||
959 | if (ret < 0) | ||
960 | goto ata_write_error; | ||
961 | |||
962 | BLOCK_COUNT_REG = count; | ||
963 | |||
964 | #ifdef HAVE_HOTSWAP | ||
965 | if(currcard->ocr & (1<<30) ) | ||
966 | { | ||
967 | /* SDHC */ | ||
968 | ret = sd_command(WRITE_MULTIPLE_BLOCK, start, NULL, 0x1c2d); | ||
969 | } | ||
970 | else | ||
971 | #endif | ||
972 | { | ||
973 | ret = sd_command(WRITE_MULTIPLE_BLOCK, start*BLOCK_SIZE, NULL, 0x1c2d); | ||
974 | } | ||
975 | if (ret < 0) | ||
976 | goto ata_write_error; | ||
977 | |||
978 | buf_end = outbuf + count * currcard->block_size - 2*FIFO_LEN; | ||
979 | |||
980 | for (buf = outbuf; buf <= buf_end;) | ||
981 | { | ||
982 | if (buf == buf_end) | ||
983 | { | ||
984 | /* Set SD_STATE_REG to PRG for the last buffer fill */ | ||
985 | SD_STATE_REG = PRG; | ||
986 | } | ||
987 | |||
988 | udelay(2); /* needed here (loop is too fast :-) */ | ||
989 | |||
990 | /* Wait for the FIFO to empty */ | ||
991 | if (sd_poll_status(FIFO_EMPTY, 0x80000)) | ||
992 | { | ||
993 | copy_write_sectors(&buf); /* Copy one chunk of 16 words */ | ||
994 | /* TODO: Switch bank if necessary */ | ||
995 | continue; | ||
996 | } | ||
997 | |||
998 | ret = -EC_FIFO_WR_EMPTY; | ||
999 | goto ata_write_error; | ||
1000 | } | ||
1001 | |||
1002 | last_disk_activity = current_tick; | ||
1003 | |||
1004 | if (!sd_poll_status(DATA_DONE, 0x80000)) | ||
1005 | { | ||
1006 | ret = -EC_FIFO_WR_DONE; | ||
1007 | goto ata_write_error; | ||
1008 | } | ||
1009 | |||
1010 | ret = sd_command(STOP_TRANSMISSION, 0, NULL, 1); | ||
1011 | if (ret < 0) | ||
1012 | goto ata_write_error; | ||
1013 | |||
1014 | ret = sd_wait_for_state(TRAN, EC_TRAN_WRITE_EXIT); | ||
1015 | if (ret < 0) | ||
1016 | goto ata_write_error; | ||
1017 | |||
1018 | while (1) | ||
1019 | { | ||
1020 | ata_led(false); | ||
1021 | mutex_unlock(&sd_mtx); | ||
1022 | |||
1023 | return ret; | ||
1024 | |||
1025 | ata_write_error: | ||
1026 | if (sd_status[drive].retry < sd_status[drive].retry_max | ||
1027 | && ret != -EC_NOCARD) | ||
1028 | { | ||
1029 | sd_status[drive].retry++; | ||
1030 | currcard->initialized = 0; | ||
1031 | goto ata_write_retry; | ||
1032 | } | ||
1033 | } | ||
1034 | } | ||
1035 | |||
1036 | static void sd_thread(void) __attribute__((noreturn)); | ||
1037 | static void sd_thread(void) | ||
1038 | { | ||
1039 | struct queue_event ev; | ||
1040 | bool idle_notified = false; | ||
1041 | |||
1042 | while (1) | ||
1043 | { | ||
1044 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | ||
1045 | |||
1046 | switch ( ev.id ) | ||
1047 | { | ||
1048 | #ifdef HAVE_HOTSWAP | ||
1049 | case SYS_HOTSWAP_INSERTED: | ||
1050 | case SYS_HOTSWAP_EXTRACTED: | ||
1051 | fat_lock(); /* lock-out FAT activity first - | ||
1052 | prevent deadlocking via disk_mount that | ||
1053 | would cause a reverse-order attempt with | ||
1054 | another thread */ | ||
1055 | mutex_lock(&sd_mtx); /* lock-out card activity - direct calls | ||
1056 | into driver that bypass the fat cache */ | ||
1057 | |||
1058 | /* We now have exclusive control of fat cache and ata */ | ||
1059 | |||
1060 | disk_unmount(1); /* release "by force", ensure file | ||
1061 | descriptors aren't leaked and any busy | ||
1062 | ones are invalid if mounting */ | ||
1063 | |||
1064 | /* Force card init for new card, re-init for re-inserted one or | ||
1065 | * clear if the last attempt to init failed with an error. */ | ||
1066 | card_info[1].initialized = 0; | ||
1067 | sd_status[1].retry = 0; | ||
1068 | |||
1069 | if (ev.id == SYS_HOTSWAP_INSERTED) | ||
1070 | disk_mount(1); | ||
1071 | |||
1072 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
1073 | |||
1074 | /* Access is now safe */ | ||
1075 | mutex_unlock(&sd_mtx); | ||
1076 | fat_unlock(); | ||
1077 | break; | ||
1078 | #endif | ||
1079 | case SYS_TIMEOUT: | ||
1080 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | ||
1081 | { | ||
1082 | idle_notified = false; | ||
1083 | } | ||
1084 | else | ||
1085 | { | ||
1086 | /* never let a timer wrap confuse us */ | ||
1087 | next_yield = USEC_TIMER; | ||
1088 | |||
1089 | if (!idle_notified) | ||
1090 | { | ||
1091 | call_ata_idle_notifys(false); | ||
1092 | idle_notified = true; | ||
1093 | } | ||
1094 | } | ||
1095 | break; | ||
1096 | case SYS_USB_CONNECTED: | ||
1097 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
1098 | /* Wait until the USB cable is extracted again */ | ||
1099 | usb_wait_for_disconnect(&sd_queue); | ||
1100 | |||
1101 | break; | ||
1102 | case SYS_USB_DISCONNECTED: | ||
1103 | usb_acknowledge(SYS_USB_DISCONNECTED_ACK); | ||
1104 | break; | ||
1105 | } | ||
1106 | } | ||
1107 | } | ||
1108 | |||
1109 | |||
1110 | void ata_spindown(int seconds) | ||
1111 | { | ||
1112 | (void)seconds; | ||
1113 | } | ||
1114 | |||
1115 | bool ata_disk_is_active(void) | ||
1116 | { | ||
1117 | return 0; | ||
1118 | } | ||
1119 | |||
1120 | void ata_sleep(void) | ||
1121 | { | ||
1122 | } | ||
1123 | |||
1124 | void ata_spin(void) | ||
1125 | { | ||
1126 | } | ||
1127 | |||
1128 | /* Hardware reset protocol as specified in chapter 9.1, ATA spec draft v5 */ | ||
1129 | int ata_hard_reset(void) | ||
1130 | { | ||
1131 | return 0; | ||
1132 | } | ||
1133 | |||
1134 | int ata_soft_reset(void) | ||
1135 | { | ||
1136 | return 0; | ||
1137 | } | ||
1138 | |||
1139 | void ata_enable(bool on) | ||
1140 | { | ||
1141 | if(on) | ||
1142 | { | ||
1143 | DEV_EN |= DEV_ATA; /* Enable controller */ | ||
1144 | } | ||
1145 | else | ||
1146 | { | ||
1147 | DEV_EN &= ~DEV_ATA; /* Disable controller */ | ||
1148 | } | ||
1149 | } | ||
1150 | |||
1151 | #ifdef HAVE_HOTSWAP | ||
1152 | void card_enable_monitoring_target(bool on) | ||
1153 | { | ||
1154 | if (on) | ||
1155 | { | ||
1156 | #ifdef SANSA_E200 | ||
1157 | GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80); | ||
1158 | #elif defined(SANSA_C200) | ||
1159 | GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08); | ||
1160 | #endif | ||
1161 | } | ||
1162 | else | ||
1163 | { | ||
1164 | #ifdef SANSA_E200 | ||
1165 | GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80); | ||
1166 | #elif defined(SANSA_C200) | ||
1167 | GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08); | ||
1168 | #endif | ||
1169 | } | ||
1170 | } | ||
1171 | #endif | ||
1172 | |||
1173 | int ata_init(void) | ||
1174 | { | ||
1175 | int ret = 0; | ||
1176 | |||
1177 | if (!initialized) | ||
1178 | mutex_init(&sd_mtx); | ||
1179 | |||
1180 | mutex_lock(&sd_mtx); | ||
1181 | |||
1182 | ata_led(false); | ||
1183 | |||
1184 | if (!initialized) | ||
1185 | { | ||
1186 | initialized = true; | ||
1187 | |||
1188 | /* init controller */ | ||
1189 | outl(inl(0x70000088) & ~(0x4), 0x70000088); | ||
1190 | outl(inl(0x7000008c) & ~(0x4), 0x7000008c); | ||
1191 | GPO32_ENABLE |= 0x4; | ||
1192 | |||
1193 | GPIO_SET_BITWISE(GPIOG_ENABLE, (0x3 << 5)); | ||
1194 | GPIO_SET_BITWISE(GPIOG_OUTPUT_EN, (0x3 << 5)); | ||
1195 | GPIO_SET_BITWISE(GPIOG_OUTPUT_VAL, (0x3 << 5)); | ||
1196 | |||
1197 | #ifdef HAVE_HOTSWAP | ||
1198 | /* enable card detection port - mask interrupt first */ | ||
1199 | #ifdef SANSA_E200 | ||
1200 | GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80); | ||
1201 | |||
1202 | GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x80); | ||
1203 | GPIO_SET_BITWISE(GPIOA_ENABLE, 0x80); | ||
1204 | #elif defined SANSA_C200 | ||
1205 | GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08); | ||
1206 | |||
1207 | GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_EN, 0x08); | ||
1208 | GPIO_SET_BITWISE(GPIOL_ENABLE, 0x08); | ||
1209 | #endif | ||
1210 | #endif | ||
1211 | sd_select_device(0); | ||
1212 | |||
1213 | if (currcard->initialized < 0) | ||
1214 | ret = currcard->initialized; | ||
1215 | |||
1216 | queue_init(&sd_queue, true); | ||
1217 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0, | ||
1218 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) | ||
1219 | IF_COP(, CPU)); | ||
1220 | |||
1221 | /* enable interupt for the mSD card */ | ||
1222 | sleep(HZ/10); | ||
1223 | #ifdef HAVE_HOTSWAP | ||
1224 | #ifdef SANSA_E200 | ||
1225 | CPU_INT_EN = HI_MASK; | ||
1226 | CPU_HI_INT_EN = GPIO0_MASK; | ||
1227 | |||
1228 | GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80); | ||
1229 | |||
1230 | GPIOA_INT_CLR = 0x80; | ||
1231 | #elif defined SANSA_C200 | ||
1232 | CPU_INT_EN = HI_MASK; | ||
1233 | CPU_HI_INT_EN = GPIO2_MASK; | ||
1234 | |||
1235 | GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08); | ||
1236 | |||
1237 | GPIOL_INT_CLR = 0x08; | ||
1238 | #endif | ||
1239 | #endif | ||
1240 | } | ||
1241 | |||
1242 | mutex_unlock(&sd_mtx); | ||
1243 | |||
1244 | return ret; | ||
1245 | } | ||
1246 | |||
1247 | /* move the sd-card info to mmc struct */ | ||
1248 | tCardInfo *card_get_info_target(int card_no) | ||
1249 | { | ||
1250 | int i, temp; | ||
1251 | static tCardInfo card; | ||
1252 | static const char mantissa[] = { /* *10 */ | ||
1253 | 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 }; | ||
1254 | static const int exponent[] = { /* use varies */ | ||
1255 | 1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000 }; | ||
1256 | |||
1257 | card.initialized = card_info[card_no].initialized; | ||
1258 | card.ocr = card_info[card_no].ocr; | ||
1259 | for(i=0; i<4; i++) card.csd[i] = card_info[card_no].csd[3-i]; | ||
1260 | for(i=0; i<4; i++) card.cid[i] = card_info[card_no].cid[3-i]; | ||
1261 | card.numblocks = card_info[card_no].numblocks; | ||
1262 | card.blocksize = card_info[card_no].block_size; | ||
1263 | card.size = card_info[card_no].capacity < 0xffffffff ? | ||
1264 | card_info[card_no].capacity : 0xffffffff; | ||
1265 | card.block_exp = card_info[card_no].block_exp; | ||
1266 | temp = card_extract_bits(card.csd, 29, 3); | ||
1267 | card.speed = mantissa[card_extract_bits(card.csd, 25, 4)] | ||
1268 | * exponent[temp > 2 ? 7 : temp + 4]; | ||
1269 | card.nsac = 100 * card_extract_bits(card.csd, 16, 8); | ||
1270 | temp = card_extract_bits(card.csd, 13, 3); | ||
1271 | card.tsac = mantissa[card_extract_bits(card.csd, 9, 4)] | ||
1272 | * exponent[temp] / 10; | ||
1273 | card.cid[0] = htobe32(card.cid[0]); /* ascii chars here */ | ||
1274 | card.cid[1] = htobe32(card.cid[1]); /* ascii chars here */ | ||
1275 | temp = *((char*)card.cid+13); /* adjust year<=>month, 1997 <=> 2000 */ | ||
1276 | *((char*)card.cid+13) = (unsigned char)((temp >> 4) | (temp << 4)) + 3; | ||
1277 | |||
1278 | return &card; | ||
1279 | } | ||
1280 | |||
1281 | #ifdef HAVE_HOTSWAP | ||
1282 | bool card_detect_target(void) | ||
1283 | { | ||
1284 | #ifdef SANSA_E200 | ||
1285 | return (GPIOA_INPUT_VAL & 0x80) == 0; /* low active */ | ||
1286 | #elif defined SANSA_C200 | ||
1287 | return (GPIOL_INPUT_VAL & 0x08) != 0; /* high active */ | ||
1288 | #endif | ||
1289 | } | ||
1290 | |||
1291 | static bool sd1_oneshot_callback(struct timeout *tmo) | ||
1292 | { | ||
1293 | (void)tmo; | ||
1294 | |||
1295 | /* This is called only if the state was stable for 300ms - check state | ||
1296 | * and post appropriate event. */ | ||
1297 | if (card_detect_target()) | ||
1298 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | ||
1299 | else | ||
1300 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
1301 | |||
1302 | return false; | ||
1303 | } | ||
1304 | |||
1305 | /* called on insertion/removal interrupt */ | ||
1306 | void microsd_int(void) | ||
1307 | { | ||
1308 | static struct timeout sd1_oneshot; | ||
1309 | |||
1310 | #ifdef SANSA_E200 | ||
1311 | GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80); | ||
1312 | GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80); | ||
1313 | GPIOA_INT_CLR = 0x80; | ||
1314 | GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80); | ||
1315 | |||
1316 | #elif defined SANSA_C200 | ||
1317 | GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08); | ||
1318 | GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08); | ||
1319 | GPIOL_INT_CLR = 0x08; | ||
1320 | GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08); | ||
1321 | #endif | ||
1322 | timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0); | ||
1323 | |||
1324 | } | ||
1325 | #endif /* HAVE_HOTSWAP */ | ||