diff options
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c')
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c | 1168 |
1 files changed, 1168 insertions, 0 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c new file mode 100644 index 0000000000..ccd71630a6 --- /dev/null +++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c | |||
@@ -0,0 +1,1168 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2008 by Maurus Cuelenaere | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "config.h" | ||
23 | #include "jz4740.h" | ||
24 | #include "ata.h" | ||
25 | #include "ata-sd-target.h" | ||
26 | #include "system.h" | ||
27 | #include "kernel.h" | ||
28 | #include "panic.h" | ||
29 | #include "debug.h" | ||
30 | |||
31 | static struct wakeup sd_wakeup; | ||
32 | |||
33 | //#define MMC_DMA_ENABLE | ||
34 | #define MMC_DMA_INTERRUPT 0 | ||
35 | |||
36 | //#define DEBUG(x...) DEBUGF(x); | ||
37 | #define DEBUG(x...) printf(x); | ||
38 | |||
39 | #define MMC_CD_PIN (29 + 1 * 32) /* Pin to check card insertion */ | ||
40 | #define MMC_POWER_PIN (30 + 1 * 32) /* Pin to enable/disable card power */ | ||
41 | //#define MMC_PW_PIN (14 + 3 * 32) /* Pin to check protect card */ | ||
42 | |||
43 | #define MMC_POWER_OFF() \ | ||
44 | do { \ | ||
45 | __gpio_set_pin(MMC_POWER_PIN); \ | ||
46 | } while (0) | ||
47 | |||
48 | #define MMC_POWER_ON() \ | ||
49 | do { \ | ||
50 | __gpio_clear_pin(MMC_POWER_PIN); \ | ||
51 | } while (0) | ||
52 | |||
53 | #define MMC_INSERT_STATUS() __gpio_get_pin(MMC_CD_PIN) | ||
54 | |||
55 | #define MMC_RESET() __msc_reset() | ||
56 | |||
57 | #define MMC_IRQ_MASK() \ | ||
58 | do { \ | ||
59 | REG_MSC_IMASK = 0xffff; \ | ||
60 | REG_MSC_IREG = 0xffff; \ | ||
61 | } while (0) | ||
62 | |||
63 | static inline void mmc_init_gpio(void) | ||
64 | { | ||
65 | __gpio_as_msc(); | ||
66 | #ifdef MMC_POWER_PIN | ||
67 | __gpio_as_output(MMC_POWER_PIN); | ||
68 | __gpio_disable_pull(MMC_POWER_PIN); | ||
69 | __gpio_set_pin(MMC_POWER_PIN); | ||
70 | #endif | ||
71 | #ifdef MMC_CD_PIN | ||
72 | __gpio_as_input(MMC_CD_PIN); | ||
73 | __gpio_disable_pull(MMC_CD_PIN); | ||
74 | #endif | ||
75 | #ifdef MMC_PW_PIN | ||
76 | __gpio_as_input(MMC_PW_PIN); | ||
77 | __gpio_disable_pull(MMC_PW_PIN); | ||
78 | #endif | ||
79 | } | ||
80 | |||
81 | /* Error codes */ | ||
82 | enum mmc_result_t | ||
83 | { | ||
84 | MMC_NO_RESPONSE = -1, | ||
85 | MMC_NO_ERROR = 0, | ||
86 | MMC_ERROR_OUT_OF_RANGE, | ||
87 | MMC_ERROR_ADDRESS, | ||
88 | MMC_ERROR_BLOCK_LEN, | ||
89 | MMC_ERROR_ERASE_SEQ, | ||
90 | MMC_ERROR_ERASE_PARAM, | ||
91 | MMC_ERROR_WP_VIOLATION, | ||
92 | MMC_ERROR_CARD_IS_LOCKED, | ||
93 | MMC_ERROR_LOCK_UNLOCK_FAILED, | ||
94 | MMC_ERROR_COM_CRC, | ||
95 | MMC_ERROR_ILLEGAL_COMMAND, | ||
96 | MMC_ERROR_CARD_ECC_FAILED, | ||
97 | MMC_ERROR_CC, | ||
98 | MMC_ERROR_GENERAL, | ||
99 | MMC_ERROR_UNDERRUN, | ||
100 | MMC_ERROR_OVERRUN, | ||
101 | MMC_ERROR_CID_CSD_OVERWRITE, | ||
102 | MMC_ERROR_STATE_MISMATCH, | ||
103 | MMC_ERROR_HEADER_MISMATCH, | ||
104 | MMC_ERROR_TIMEOUT, | ||
105 | MMC_ERROR_CRC, | ||
106 | MMC_ERROR_DRIVER_FAILURE, | ||
107 | }; | ||
108 | |||
109 | /* Standard MMC/SD clock speeds */ | ||
110 | #define MMC_CLOCK_SLOW 400000 /* 400 kHz for initial setup */ | ||
111 | #define MMC_CLOCK_FAST 20000000 /* 20 MHz for maximum for normal operation */ | ||
112 | #define SD_CLOCK_FAST 24000000 /* 24 MHz for SD Cards */ | ||
113 | #define SD_CLOCK_HIGH 48000000 /* 48 MHz for SD Cards */ | ||
114 | |||
115 | /* Extra MMC commands for state control */ | ||
116 | /* Use negative numbers to disambiguate */ | ||
117 | #define MMC_CIM_RESET -1 | ||
118 | |||
119 | /* Standard MMC commands (3.1) type argument response */ | ||
120 | /* class 1 */ | ||
121 | #define MMC_GO_IDLE_STATE 0 /* bc */ | ||
122 | #define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */ | ||
123 | #define MMC_ALL_SEND_CID 2 /* bcr R2 */ | ||
124 | #define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */ | ||
125 | #define MMC_SET_DSR 4 /* bc [31:16] RCA */ | ||
126 | #define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */ | ||
127 | #define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */ | ||
128 | #define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */ | ||
129 | #define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */ | ||
130 | #define MMC_STOP_TRANSMISSION 12 /* ac R1b */ | ||
131 | #define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */ | ||
132 | #define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */ | ||
133 | |||
134 | /* class 2 */ | ||
135 | #define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */ | ||
136 | #define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */ | ||
137 | #define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */ | ||
138 | |||
139 | /* class 3 */ | ||
140 | #define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */ | ||
141 | |||
142 | /* class 4 */ | ||
143 | #define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */ | ||
144 | #define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */ | ||
145 | #define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */ | ||
146 | #define MMC_PROGRAM_CID 26 /* adtc R1 */ | ||
147 | #define MMC_PROGRAM_CSD 27 /* adtc R1 */ | ||
148 | |||
149 | /* class 6 */ | ||
150 | #define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */ | ||
151 | #define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */ | ||
152 | #define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */ | ||
153 | |||
154 | /* class 5 */ | ||
155 | #define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */ | ||
156 | #define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */ | ||
157 | #define MMC_ERASE 37 /* ac R1b */ | ||
158 | |||
159 | /* class 9 */ | ||
160 | #define MMC_FAST_IO 39 /* ac <Complex> R4 */ | ||
161 | #define MMC_GO_IRQ_STATE 40 /* bcr R5 */ | ||
162 | |||
163 | /* class 7 */ | ||
164 | #define MMC_LOCK_UNLOCK 42 /* adtc R1b */ | ||
165 | |||
166 | /* class 8 */ | ||
167 | #define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ | ||
168 | #define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1b */ | ||
169 | |||
170 | /* SD class */ | ||
171 | #define SD_SEND_OP_COND 41 /* bcr [31:0] OCR R3 */ | ||
172 | #define SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ | ||
173 | #define SEND_SCR 51 /* adtc [31:0] staff R1 */ | ||
174 | |||
175 | /* Don't change the order of these; they are used in dispatch tables */ | ||
176 | enum mmc_rsp_t | ||
177 | { | ||
178 | RESPONSE_NONE = 0, | ||
179 | RESPONSE_R1 = 1, | ||
180 | RESPONSE_R1B = 2, | ||
181 | RESPONSE_R2_CID = 3, | ||
182 | RESPONSE_R2_CSD = 4, | ||
183 | RESPONSE_R3 = 5, | ||
184 | RESPONSE_R4 = 6, | ||
185 | RESPONSE_R5 = 7, | ||
186 | RESPONSE_R6 = 8, | ||
187 | }; | ||
188 | |||
189 | |||
190 | /* | ||
191 | MMC status in R1 | ||
192 | Type | ||
193 | e : error bit | ||
194 | s : status bit | ||
195 | r : detected and set for the actual command response | ||
196 | x : detected and set during command execution. the host must poll | ||
197 | the card by sending status command in order to read these bits. | ||
198 | Clear condition | ||
199 | a : according to the card state | ||
200 | b : always related to the previous command. Reception of | ||
201 | a valid command will clear it (with a delay of one command) | ||
202 | c : clear by read | ||
203 | */ | ||
204 | |||
205 | #define R1_OUT_OF_RANGE (1 << 31) /* er, c */ | ||
206 | #define R1_ADDRESS_ERROR (1 << 30) /* erx, c */ | ||
207 | #define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */ | ||
208 | #define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */ | ||
209 | #define R1_ERASE_PARAM (1 << 27) /* ex, c */ | ||
210 | #define R1_WP_VIOLATION (1 << 26) /* erx, c */ | ||
211 | #define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */ | ||
212 | #define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */ | ||
213 | #define R1_COM_CRC_ERROR (1 << 23) /* er, b */ | ||
214 | #define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */ | ||
215 | #define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */ | ||
216 | #define R1_CC_ERROR (1 << 20) /* erx, c */ | ||
217 | #define R1_ERROR (1 << 19) /* erx, c */ | ||
218 | #define R1_UNDERRUN (1 << 18) /* ex, c */ | ||
219 | #define R1_OVERRUN (1 << 17) /* ex, c */ | ||
220 | #define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */ | ||
221 | #define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */ | ||
222 | #define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */ | ||
223 | #define R1_ERASE_RESET (1 << 13) /* sr, c */ | ||
224 | #define R1_STATUS(x) (x & 0xFFFFE000) | ||
225 | #define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ | ||
226 | #define R1_READY_FOR_DATA (1 << 8) /* sx, a */ | ||
227 | #define R1_APP_CMD (1 << 7) /* sr, c */ | ||
228 | |||
229 | enum card_state | ||
230 | { | ||
231 | CARD_STATE_EMPTY = -1, | ||
232 | CARD_STATE_IDLE = 0, | ||
233 | CARD_STATE_READY = 1, | ||
234 | CARD_STATE_IDENT = 2, | ||
235 | CARD_STATE_STBY = 3, | ||
236 | CARD_STATE_TRAN = 4, | ||
237 | CARD_STATE_DATA = 5, | ||
238 | CARD_STATE_RCV = 6, | ||
239 | CARD_STATE_PRG = 7, | ||
240 | CARD_STATE_DIS = 8, | ||
241 | }; | ||
242 | |||
243 | /* These are unpacked versions of the actual responses */ | ||
244 | struct mmc_response_r1 | ||
245 | { | ||
246 | unsigned char cmd; | ||
247 | unsigned int status; | ||
248 | }; | ||
249 | |||
250 | struct mmc_cid | ||
251 | { | ||
252 | unsigned char mid; | ||
253 | unsigned short oid; | ||
254 | unsigned char pnm[7]; /* Product name (we null-terminate) */ | ||
255 | unsigned char prv; | ||
256 | unsigned int psn; | ||
257 | unsigned char mdt; | ||
258 | }; | ||
259 | |||
260 | struct mmc_csd | ||
261 | { | ||
262 | unsigned char csd_structure; | ||
263 | unsigned char spec_vers; | ||
264 | unsigned char taac; | ||
265 | unsigned char nsac; | ||
266 | unsigned char tran_speed; | ||
267 | unsigned short ccc; | ||
268 | unsigned char read_bl_len; | ||
269 | unsigned char read_bl_partial; | ||
270 | unsigned char write_blk_misalign; | ||
271 | unsigned char read_blk_misalign; | ||
272 | unsigned char dsr_imp; | ||
273 | unsigned short c_size; | ||
274 | unsigned char vdd_r_curr_min; | ||
275 | unsigned char vdd_r_curr_max; | ||
276 | unsigned char vdd_w_curr_min; | ||
277 | unsigned char vdd_w_curr_max; | ||
278 | unsigned char c_size_mult; | ||
279 | union | ||
280 | { | ||
281 | struct /* MMC system specification version 3.1 */ | ||
282 | { | ||
283 | unsigned char erase_grp_size; | ||
284 | unsigned char erase_grp_mult; | ||
285 | } v31; | ||
286 | struct /* MMC system specification version 2.2 */ | ||
287 | { | ||
288 | unsigned char sector_size; | ||
289 | unsigned char erase_grp_size; | ||
290 | } v22; | ||
291 | } erase; | ||
292 | unsigned char wp_grp_size; | ||
293 | unsigned char wp_grp_enable; | ||
294 | unsigned char default_ecc; | ||
295 | unsigned char r2w_factor; | ||
296 | unsigned char write_bl_len; | ||
297 | unsigned char write_bl_partial; | ||
298 | unsigned char file_format_grp; | ||
299 | unsigned char copy; | ||
300 | unsigned char perm_write_protect; | ||
301 | unsigned char tmp_write_protect; | ||
302 | unsigned char file_format; | ||
303 | unsigned char ecc; | ||
304 | }; | ||
305 | |||
306 | struct mmc_response_r3 | ||
307 | { | ||
308 | unsigned int ocr; | ||
309 | }; | ||
310 | |||
311 | #define MMC_VDD_145_150 0x00000001 /* VDD voltage 1.45 - 1.50 */ | ||
312 | #define MMC_VDD_150_155 0x00000002 /* VDD voltage 1.50 - 1.55 */ | ||
313 | #define MMC_VDD_155_160 0x00000004 /* VDD voltage 1.55 - 1.60 */ | ||
314 | #define MMC_VDD_160_165 0x00000008 /* VDD voltage 1.60 - 1.65 */ | ||
315 | #define MMC_VDD_165_170 0x00000010 /* VDD voltage 1.65 - 1.70 */ | ||
316 | #define MMC_VDD_17_18 0x00000020 /* VDD voltage 1.7 - 1.8 */ | ||
317 | #define MMC_VDD_18_19 0x00000040 /* VDD voltage 1.8 - 1.9 */ | ||
318 | #define MMC_VDD_19_20 0x00000080 /* VDD voltage 1.9 - 2.0 */ | ||
319 | #define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */ | ||
320 | #define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */ | ||
321 | #define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */ | ||
322 | #define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */ | ||
323 | #define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */ | ||
324 | #define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */ | ||
325 | #define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */ | ||
326 | #define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */ | ||
327 | #define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */ | ||
328 | #define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */ | ||
329 | #define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */ | ||
330 | #define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */ | ||
331 | #define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */ | ||
332 | #define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */ | ||
333 | #define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */ | ||
334 | #define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */ | ||
335 | #define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */ | ||
336 | |||
337 | |||
338 | /* CSD field definitions */ | ||
339 | #define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */ | ||
340 | #define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */ | ||
341 | #define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 */ | ||
342 | |||
343 | #define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */ | ||
344 | #define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */ | ||
345 | #define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */ | ||
346 | #define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 */ | ||
347 | |||
348 | /* the information structure of MMC/SD Card */ | ||
349 | typedef struct MMC_INFO | ||
350 | { | ||
351 | int id; /* Card index */ | ||
352 | int sd; /* MMC or SD card */ | ||
353 | int rca; /* RCA */ | ||
354 | unsigned int scr; /* SCR 63:32*/ | ||
355 | int flags; /* Ejected, inserted */ | ||
356 | enum card_state state; /* empty, ident, ready, whatever */ | ||
357 | |||
358 | /* Card specific information */ | ||
359 | struct mmc_cid cid; | ||
360 | struct mmc_csd csd; | ||
361 | unsigned int block_num; | ||
362 | unsigned int block_len; | ||
363 | unsigned int erase_unit; | ||
364 | } mmc_info; | ||
365 | |||
366 | static mmc_info mmcinfo; | ||
367 | |||
368 | struct mmc_request | ||
369 | { | ||
370 | int index; /* Slot index - used for CS lines */ | ||
371 | int cmd; /* Command to send */ | ||
372 | unsigned int arg; /* Argument to send */ | ||
373 | enum mmc_rsp_t rtype; /* Response type expected */ | ||
374 | |||
375 | /* Data transfer (these may be modified at the low level) */ | ||
376 | unsigned short nob; /* Number of blocks to transfer*/ | ||
377 | unsigned short block_len; /* Block length */ | ||
378 | unsigned char *buffer; /* Data buffer */ | ||
379 | unsigned int cnt; /* Data length, for PIO */ | ||
380 | |||
381 | /* Results */ | ||
382 | unsigned char response[18]; /* Buffer to store response - CRC is optional */ | ||
383 | enum mmc_result_t result; | ||
384 | }; | ||
385 | |||
386 | #define MMC_OCR_ARG 0x00ff8000 /* Argument of OCR */ | ||
387 | |||
388 | /*********************************************************************** | ||
389 | * MMC Events | ||
390 | */ | ||
391 | #define MMC_EVENT_NONE 0x00 /* No events */ | ||
392 | #define MMC_EVENT_RX_DATA_DONE 0x01 /* Rx data done */ | ||
393 | #define MMC_EVENT_TX_DATA_DONE 0x02 /* Tx data done */ | ||
394 | #define MMC_EVENT_PROG_DONE 0x04 /* Programming is done */ | ||
395 | |||
396 | static int use_4bit; /* Use 4-bit data bus */ | ||
397 | static int num_6; | ||
398 | static int sd2_0; | ||
399 | |||
400 | /* Stop the MMC clock and wait while it happens */ | ||
401 | static inline int jz_mmc_stop_clock(void) | ||
402 | { | ||
403 | int timeout = 1000; | ||
404 | |||
405 | DEBUG("stop MMC clock"); | ||
406 | REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP; | ||
407 | |||
408 | while (timeout && (REG_MSC_STAT & MSC_STAT_CLK_EN)) | ||
409 | { | ||
410 | timeout--; | ||
411 | if (timeout == 0) | ||
412 | { | ||
413 | DEBUG("Timeout on stop clock waiting"); | ||
414 | return MMC_ERROR_TIMEOUT; | ||
415 | } | ||
416 | udelay(1); | ||
417 | } | ||
418 | DEBUG("clock off time is %d microsec", timeout); | ||
419 | return MMC_NO_ERROR; | ||
420 | } | ||
421 | |||
422 | /* Start the MMC clock and operation */ | ||
423 | static inline int jz_mmc_start_clock(void) | ||
424 | { | ||
425 | REG_MSC_STRPCL = | ||
426 | MSC_STRPCL_CLOCK_CONTROL_START | MSC_STRPCL_START_OP; | ||
427 | return MMC_NO_ERROR; | ||
428 | } | ||
429 | |||
430 | static inline unsigned int jz_mmc_calc_clkrt(int is_sd, unsigned int rate) | ||
431 | { | ||
432 | unsigned int clkrt; | ||
433 | unsigned int clk_src = is_sd ? 24000000 : 20000000; | ||
434 | |||
435 | clkrt = 0; | ||
436 | while (rate < clk_src) | ||
437 | { | ||
438 | clkrt++; | ||
439 | clk_src >>= 1; | ||
440 | } | ||
441 | return clkrt; | ||
442 | } | ||
443 | |||
444 | static int jz_mmc_check_status(struct mmc_request *request) | ||
445 | { | ||
446 | unsigned int status = REG_MSC_STAT; | ||
447 | |||
448 | /* Checking for response or data timeout */ | ||
449 | if (status & (MSC_STAT_TIME_OUT_RES | MSC_STAT_TIME_OUT_READ)) | ||
450 | { | ||
451 | DEBUG("MMC/SD timeout, MMC_STAT 0x%x CMD %d", status, | ||
452 | request->cmd); | ||
453 | return MMC_ERROR_TIMEOUT; | ||
454 | } | ||
455 | |||
456 | /* Checking for CRC error */ | ||
457 | if (status & | ||
458 | (MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR | | ||
459 | MSC_STAT_CRC_RES_ERR)) | ||
460 | { | ||
461 | DEBUG("MMC/CD CRC error, MMC_STAT 0x%x", status); | ||
462 | return MMC_ERROR_CRC; | ||
463 | } | ||
464 | |||
465 | return MMC_NO_ERROR; | ||
466 | } | ||
467 | |||
468 | /* Obtain response to the command and store it to response buffer */ | ||
469 | static void jz_mmc_get_response(struct mmc_request *request) | ||
470 | { | ||
471 | int i; | ||
472 | unsigned char *buf; | ||
473 | unsigned int data; | ||
474 | |||
475 | DEBUG("fetch response for request %d, cmd %d", request->rtype, | ||
476 | request->cmd); | ||
477 | buf = request->response; | ||
478 | request->result = MMC_NO_ERROR; | ||
479 | |||
480 | switch (request->rtype) | ||
481 | { | ||
482 | case RESPONSE_R1: | ||
483 | case RESPONSE_R1B: | ||
484 | case RESPONSE_R6: | ||
485 | case RESPONSE_R3: | ||
486 | case RESPONSE_R4: | ||
487 | case RESPONSE_R5: | ||
488 | { | ||
489 | data = REG_MSC_RES; | ||
490 | buf[0] = (data >> 8) & 0xff; | ||
491 | buf[1] = data & 0xff; | ||
492 | data = REG_MSC_RES; | ||
493 | buf[2] = (data >> 8) & 0xff; | ||
494 | buf[3] = data & 0xff; | ||
495 | data = REG_MSC_RES; | ||
496 | buf[4] = data & 0xff; | ||
497 | |||
498 | DEBUG("request %d, response [%02x %02x %02x %02x %02x]", | ||
499 | request->rtype, buf[0], buf[1], buf[2], | ||
500 | buf[3], buf[4]); | ||
501 | break; | ||
502 | } | ||
503 | case RESPONSE_R2_CID: | ||
504 | case RESPONSE_R2_CSD: | ||
505 | { | ||
506 | for (i = 0; i < 16; i += 2) | ||
507 | { | ||
508 | data = REG_MSC_RES; | ||
509 | buf[i] = (data >> 8) & 0xff; | ||
510 | buf[i + 1] = data & 0xff; | ||
511 | } | ||
512 | DEBUG("request %d, response [", request->rtype); | ||
513 | break; | ||
514 | } | ||
515 | case RESPONSE_NONE: | ||
516 | DEBUG("No response"); | ||
517 | break; | ||
518 | |||
519 | default: | ||
520 | DEBUG("unhandled response type for request %d", | ||
521 | request->rtype); | ||
522 | break; | ||
523 | } | ||
524 | } | ||
525 | |||
526 | #ifdef MMC_DMA_ENABLE | ||
527 | static int jz_mmc_receive_data_dma(struct mmc_request *req) | ||
528 | { | ||
529 | int ch = RX_DMA_CHANNEL; | ||
530 | unsigned int size = req->block_len * req->nob; | ||
531 | unsigned char err = 0; | ||
532 | |||
533 | /* flush dcache */ | ||
534 | dma_cache_wback_inv((unsigned long) req->buffer, size); | ||
535 | /* setup dma channel */ | ||
536 | REG_DMAC_DSAR(ch) = PHYSADDR(MSC_RXFIFO); /* DMA source addr */ | ||
537 | REG_DMAC_DTAR(ch) = PHYSADDR((unsigned long) req->buffer); /* DMA dest addr */ | ||
538 | REG_DMAC_DTCR(ch) = (size + 3) / 4; /* DMA transfer count */ | ||
539 | REG_DMAC_DRSR(ch) = DMAC_DRSR_RS_MSCIN; /* DMA request type */ | ||
540 | |||
541 | #if MMC_DMA_INTERRUPT | ||
542 | REG_DMAC_DCMD(ch) = | ||
543 | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | | ||
544 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_TIE; | ||
545 | REG_DMAC_DCCSR(ch) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; | ||
546 | OSSemPend(mmc_dma_rx_sem, 100, &err); | ||
547 | #else | ||
548 | REG_DMAC_DCMD(ch) = | ||
549 | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | | ||
550 | DMAC_DCMD_DS_32BIT; | ||
551 | REG_DMAC_DCCSR(ch) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; | ||
552 | while (REG_DMAC_DTCR(ch)); | ||
553 | #endif | ||
554 | /* clear status and disable channel */ | ||
555 | REG_DMAC_DCCSR(ch) = 0; | ||
556 | #if MMC_DMA_INTERRUPT | ||
557 | return (err == OS_NO_ERR); | ||
558 | #else | ||
559 | return 0; | ||
560 | #endif | ||
561 | } | ||
562 | |||
563 | static int jz_mmc_transmit_data_dma(struct mmc_request *req) | ||
564 | { | ||
565 | int ch = TX_DMA_CHANNEL; | ||
566 | unsigned int size = req->block_len * req->nob; | ||
567 | unsigned char err = 0; | ||
568 | |||
569 | /* flush dcache */ | ||
570 | dma_cache_wback_inv((unsigned long) req->buffer, size); | ||
571 | /* setup dma channel */ | ||
572 | REG_DMAC_DSAR(ch) = PHYSADDR((unsigned long) req->buffer); /* DMA source addr */ | ||
573 | REG_DMAC_DTAR(ch) = PHYSADDR(MSC_TXFIFO); /* DMA dest addr */ | ||
574 | REG_DMAC_DTCR(ch) = (size + 3) / 4; /* DMA transfer count */ | ||
575 | REG_DMAC_DRSR(ch) = DMAC_DRSR_RS_MSCOUT; /* DMA request type */ | ||
576 | |||
577 | #if MMC_DMA_INTERRUPT | ||
578 | REG_DMAC_DCMD(ch) = | ||
579 | DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | | ||
580 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_TIE; | ||
581 | REG_DMAC_DCCSR(ch) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; | ||
582 | OSSemPend(mmc_dma_tx_sem, 100, &err); | ||
583 | #else | ||
584 | REG_DMAC_DCMD(ch) = | ||
585 | DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | | ||
586 | DMAC_DCMD_DS_32BIT; | ||
587 | REG_DMAC_DCCSR(ch) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; | ||
588 | /* wait for dma completion */ | ||
589 | while (REG_DMAC_DTCR(ch)); | ||
590 | #endif | ||
591 | /* clear status and disable channel */ | ||
592 | REG_DMAC_DCCSR(ch) = 0; | ||
593 | #if MMC_DMA_INTERRUPT | ||
594 | return (err == OS_NO_ERR); | ||
595 | #else | ||
596 | return 0; | ||
597 | #endif | ||
598 | } | ||
599 | |||
600 | #endif /* MMC_DMA_ENABLE */ | ||
601 | |||
602 | static int jz_mmc_receive_data(struct mmc_request *req) | ||
603 | { | ||
604 | unsigned int nob = req->nob; | ||
605 | unsigned int wblocklen = (unsigned int) (req->block_len + 3) >> 2; /* length in word */ | ||
606 | unsigned char *buf = req->buffer; | ||
607 | unsigned int *wbuf = (unsigned int *) buf; | ||
608 | unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */ | ||
609 | unsigned int stat, timeout, data, cnt; | ||
610 | |||
611 | for (; nob >= 1; nob--) | ||
612 | { | ||
613 | timeout = 0x3FFFFFF; | ||
614 | |||
615 | while (timeout) | ||
616 | { | ||
617 | timeout--; | ||
618 | stat = REG_MSC_STAT; | ||
619 | |||
620 | if (stat & MSC_STAT_TIME_OUT_READ) | ||
621 | return MMC_ERROR_TIMEOUT; | ||
622 | else if (stat & MSC_STAT_CRC_READ_ERROR) | ||
623 | return MMC_ERROR_CRC; | ||
624 | else if (!(stat & MSC_STAT_DATA_FIFO_EMPTY) | ||
625 | || (stat & MSC_STAT_DATA_FIFO_AFULL)) { | ||
626 | /* Ready to read data */ | ||
627 | break; | ||
628 | } | ||
629 | |||
630 | udelay(1); | ||
631 | } | ||
632 | |||
633 | if (!timeout) | ||
634 | return MMC_ERROR_TIMEOUT; | ||
635 | |||
636 | /* Read data from RXFIFO. It could be FULL or PARTIAL FULL */ | ||
637 | DEBUG("Receive Data = %d", wblocklen); | ||
638 | cnt = wblocklen; | ||
639 | while (cnt) | ||
640 | { | ||
641 | data = REG_MSC_RXFIFO; | ||
642 | if (waligned) | ||
643 | *wbuf++ = data; | ||
644 | else | ||
645 | { | ||
646 | *buf++ = (unsigned char) (data >> 0); | ||
647 | *buf++ = (unsigned char) (data >> 8); | ||
648 | *buf++ = (unsigned char) (data >> 16); | ||
649 | *buf++ = (unsigned char) (data >> 24); | ||
650 | } | ||
651 | cnt--; | ||
652 | while (cnt | ||
653 | && (REG_MSC_STAT & | ||
654 | MSC_STAT_DATA_FIFO_EMPTY)); | ||
655 | } | ||
656 | } | ||
657 | |||
658 | return MMC_NO_ERROR; | ||
659 | } | ||
660 | |||
661 | static int jz_mmc_transmit_data(struct mmc_request *req) | ||
662 | { | ||
663 | unsigned int nob = req->nob; | ||
664 | unsigned int wblocklen = (unsigned int) (req->block_len + 3) >> 2; /* length in word */ | ||
665 | unsigned char *buf = req->buffer; | ||
666 | unsigned int *wbuf = (unsigned int *) buf; | ||
667 | unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */ | ||
668 | unsigned int stat, timeout, data, cnt; | ||
669 | |||
670 | for (; nob >= 1; nob--) | ||
671 | { | ||
672 | timeout = 0x3FFFFFF; | ||
673 | |||
674 | while (timeout) | ||
675 | { | ||
676 | timeout--; | ||
677 | stat = REG_MSC_STAT; | ||
678 | |||
679 | if (stat & | ||
680 | (MSC_STAT_CRC_WRITE_ERROR | | ||
681 | MSC_STAT_CRC_WRITE_ERROR_NOSTS)) | ||
682 | return MMC_ERROR_CRC; | ||
683 | else if (!(stat & MSC_STAT_DATA_FIFO_FULL)) | ||
684 | { | ||
685 | /* Ready to write data */ | ||
686 | break; | ||
687 | } | ||
688 | |||
689 | udelay(1); | ||
690 | } | ||
691 | |||
692 | if (!timeout) | ||
693 | return MMC_ERROR_TIMEOUT; | ||
694 | |||
695 | /* Write data to TXFIFO */ | ||
696 | cnt = wblocklen; | ||
697 | while (cnt) | ||
698 | { | ||
699 | while (REG_MSC_STAT & MSC_STAT_DATA_FIFO_FULL); | ||
700 | |||
701 | if (waligned) | ||
702 | REG_MSC_TXFIFO = *wbuf++; | ||
703 | else | ||
704 | { | ||
705 | data = *buf++; | ||
706 | data |= *buf++ << 8; | ||
707 | data |= *buf++ << 16; | ||
708 | data |= *buf++ << 24; | ||
709 | REG_MSC_TXFIFO = data; | ||
710 | } | ||
711 | |||
712 | cnt--; | ||
713 | } | ||
714 | } | ||
715 | |||
716 | return MMC_NO_ERROR; | ||
717 | } | ||
718 | |||
719 | /* Set the MMC clock frequency */ | ||
720 | static void jz_mmc_set_clock(int sd, unsigned int rate) | ||
721 | { | ||
722 | int clkrt = 0; | ||
723 | |||
724 | sd = sd ? 1 : 0; | ||
725 | |||
726 | jz_mmc_stop_clock(); | ||
727 | |||
728 | if(sd2_0) | ||
729 | { | ||
730 | __cpm_select_msc_hs_clk(sd); /* select clock source from CPM */ | ||
731 | REG_CPM_CPCCR |= CPM_CPCCR_CE; | ||
732 | REG_MSC_CLKRT = 0; | ||
733 | } | ||
734 | else | ||
735 | { | ||
736 | __cpm_select_msc_clk(sd); /* select clock source from CPM */ | ||
737 | REG_CPM_CPCCR |= CPM_CPCCR_CE; | ||
738 | clkrt = jz_mmc_calc_clkrt(sd, rate); | ||
739 | REG_MSC_CLKRT = clkrt; | ||
740 | } | ||
741 | DEBUG("set clock to %u Hz is_sd=%d clkrt=%d", rate, sd, clkrt); | ||
742 | } | ||
743 | |||
744 | /******************************************************************************************************************** | ||
745 | ** Name: int jz_mmc_exec_cmd() | ||
746 | ** Function: send command to the card, and get a response | ||
747 | ** Input: struct mmc_request *req: MMC/SD request | ||
748 | ** Output: 0: right >0: error code | ||
749 | ********************************************************************************************************************/ | ||
750 | static int jz_mmc_exec_cmd(struct mmc_request *request) | ||
751 | { | ||
752 | unsigned int cmdat = 0, events = 0; | ||
753 | int retval, timeout = 0x3fffff; | ||
754 | |||
755 | /* Indicate we have no result yet */ | ||
756 | request->result = MMC_NO_RESPONSE; | ||
757 | if (request->cmd == MMC_CIM_RESET) | ||
758 | { | ||
759 | /* On reset, 1-bit bus width */ | ||
760 | use_4bit = 0; | ||
761 | |||
762 | /* Reset MMC/SD controller */ | ||
763 | __msc_reset(); | ||
764 | |||
765 | /* On reset, drop MMC clock down */ | ||
766 | jz_mmc_set_clock(0, MMC_CLOCK_SLOW); | ||
767 | |||
768 | /* On reset, stop MMC clock */ | ||
769 | jz_mmc_stop_clock(); | ||
770 | } | ||
771 | if (request->cmd == MMC_SEND_OP_COND) | ||
772 | { | ||
773 | DEBUG("Have a MMC card"); | ||
774 | /* always use 1bit for MMC */ | ||
775 | use_4bit = 0; | ||
776 | } | ||
777 | if (request->cmd == SET_BUS_WIDTH) | ||
778 | { | ||
779 | if (request->arg == 0x2) | ||
780 | { | ||
781 | DEBUG("Use 4-bit bus width"); | ||
782 | use_4bit = 1; | ||
783 | } | ||
784 | else | ||
785 | { | ||
786 | DEBUG("Use 1-bit bus width"); | ||
787 | use_4bit = 0; | ||
788 | } | ||
789 | } | ||
790 | |||
791 | /* stop clock */ | ||
792 | jz_mmc_stop_clock(); | ||
793 | |||
794 | /* mask all interrupts */ | ||
795 | //REG_MSC_IMASK = 0xffff; | ||
796 | /* clear status */ | ||
797 | REG_MSC_IREG = 0xffff; | ||
798 | /*open interrupt */ | ||
799 | REG_MSC_IMASK = (~7); | ||
800 | /* use 4-bit bus width when possible */ | ||
801 | if (use_4bit) | ||
802 | cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT; | ||
803 | |||
804 | /* Set command type and events */ | ||
805 | switch (request->cmd) | ||
806 | { | ||
807 | /* MMC core extra command */ | ||
808 | case MMC_CIM_RESET: | ||
809 | cmdat |= MSC_CMDAT_INIT; /* Initialization sequence sent prior to command */ | ||
810 | break; | ||
811 | |||
812 | /* bc - broadcast - no response */ | ||
813 | case MMC_GO_IDLE_STATE: | ||
814 | case MMC_SET_DSR: | ||
815 | break; | ||
816 | |||
817 | /* bcr - broadcast with response */ | ||
818 | case MMC_SEND_OP_COND: | ||
819 | case MMC_ALL_SEND_CID: | ||
820 | |||
821 | case MMC_GO_IRQ_STATE: | ||
822 | break; | ||
823 | |||
824 | /* adtc - addressed with data transfer */ | ||
825 | case MMC_READ_DAT_UNTIL_STOP: | ||
826 | case MMC_READ_SINGLE_BLOCK: | ||
827 | case MMC_READ_MULTIPLE_BLOCK: | ||
828 | case SEND_SCR: | ||
829 | #if defined(MMC_DMA_ENABLE) | ||
830 | cmdat |= | ||
831 | MSC_CMDAT_DATA_EN | MSC_CMDAT_READ | MSC_CMDAT_DMA_EN; | ||
832 | #else | ||
833 | cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_READ; | ||
834 | #endif | ||
835 | events = MMC_EVENT_RX_DATA_DONE; | ||
836 | break; | ||
837 | |||
838 | case 6: | ||
839 | if (num_6 < 2) | ||
840 | { | ||
841 | |||
842 | #if defined(MMC_DMA_ENABLE) | ||
843 | cmdat |= | ||
844 | MSC_CMDAT_DATA_EN | MSC_CMDAT_READ | | ||
845 | MSC_CMDAT_DMA_EN; | ||
846 | #else | ||
847 | cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_READ; | ||
848 | #endif | ||
849 | events = MMC_EVENT_RX_DATA_DONE; | ||
850 | } | ||
851 | break; | ||
852 | |||
853 | case MMC_WRITE_DAT_UNTIL_STOP: | ||
854 | case MMC_WRITE_BLOCK: | ||
855 | case MMC_WRITE_MULTIPLE_BLOCK: | ||
856 | case MMC_PROGRAM_CID: | ||
857 | case MMC_PROGRAM_CSD: | ||
858 | case MMC_SEND_WRITE_PROT: | ||
859 | case MMC_GEN_CMD: | ||
860 | case MMC_LOCK_UNLOCK: | ||
861 | #if defined(MMC_DMA_ENABLE) | ||
862 | cmdat |= | ||
863 | MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE | MSC_CMDAT_DMA_EN; | ||
864 | #else | ||
865 | cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE; | ||
866 | #endif | ||
867 | events = MMC_EVENT_TX_DATA_DONE | MMC_EVENT_PROG_DONE; | ||
868 | break; | ||
869 | |||
870 | case MMC_STOP_TRANSMISSION: | ||
871 | events = MMC_EVENT_PROG_DONE; | ||
872 | break; | ||
873 | |||
874 | /* ac - no data transfer */ | ||
875 | default: | ||
876 | break; | ||
877 | } | ||
878 | |||
879 | /* Set response type */ | ||
880 | switch (request->rtype) | ||
881 | { | ||
882 | case RESPONSE_NONE: | ||
883 | break; | ||
884 | case RESPONSE_R1B: | ||
885 | cmdat |= MSC_CMDAT_BUSY; | ||
886 | /*FALLTHRU*/ | ||
887 | case RESPONSE_R1: | ||
888 | cmdat |= MSC_CMDAT_RESPONSE_R1; | ||
889 | break; | ||
890 | case RESPONSE_R2_CID: | ||
891 | case RESPONSE_R2_CSD: | ||
892 | cmdat |= MSC_CMDAT_RESPONSE_R2; | ||
893 | break; | ||
894 | case RESPONSE_R3: | ||
895 | cmdat |= MSC_CMDAT_RESPONSE_R3; | ||
896 | break; | ||
897 | case RESPONSE_R4: | ||
898 | cmdat |= MSC_CMDAT_RESPONSE_R4; | ||
899 | break; | ||
900 | case RESPONSE_R5: | ||
901 | cmdat |= MSC_CMDAT_RESPONSE_R5; | ||
902 | break; | ||
903 | case RESPONSE_R6: | ||
904 | cmdat |= MSC_CMDAT_RESPONSE_R6; | ||
905 | break; | ||
906 | default: | ||
907 | break; | ||
908 | } | ||
909 | |||
910 | /* Set command index */ | ||
911 | if (request->cmd == MMC_CIM_RESET) | ||
912 | REG_MSC_CMD = MMC_GO_IDLE_STATE; | ||
913 | else | ||
914 | REG_MSC_CMD = request->cmd; | ||
915 | |||
916 | /* Set argument */ | ||
917 | REG_MSC_ARG = request->arg; | ||
918 | |||
919 | /* Set block length and nob */ | ||
920 | if (request->cmd == SEND_SCR) | ||
921 | { /* get SCR from DataFIFO */ | ||
922 | REG_MSC_BLKLEN = 8; | ||
923 | REG_MSC_NOB = 1; | ||
924 | } | ||
925 | else | ||
926 | { | ||
927 | REG_MSC_BLKLEN = request->block_len; | ||
928 | REG_MSC_NOB = request->nob; | ||
929 | } | ||
930 | |||
931 | /* Set command */ | ||
932 | REG_MSC_CMDAT = cmdat; | ||
933 | |||
934 | DEBUG("Send cmd %d cmdat: %x arg: %x resp %d", request->cmd, | ||
935 | cmdat, request->arg, request->rtype); | ||
936 | |||
937 | /* Start MMC/SD clock and send command to card */ | ||
938 | jz_mmc_start_clock(); | ||
939 | |||
940 | /* Wait for command completion */ | ||
941 | //__intc_unmask_irq(IRQ_MSC); | ||
942 | //wakeup_wait(&sd_wakeup, 100); | ||
943 | while (timeout-- && !(REG_MSC_STAT & MSC_STAT_END_CMD_RES)); | ||
944 | |||
945 | |||
946 | if (timeout == 0) | ||
947 | return MMC_ERROR_TIMEOUT; | ||
948 | |||
949 | REG_MSC_IREG = MSC_IREG_END_CMD_RES; /* clear flag */ | ||
950 | |||
951 | /* Check for status */ | ||
952 | retval = jz_mmc_check_status(request); | ||
953 | if (retval) | ||
954 | return retval; | ||
955 | |||
956 | /* Complete command with no response */ | ||
957 | if (request->rtype == RESPONSE_NONE) | ||
958 | return MMC_NO_ERROR; | ||
959 | |||
960 | /* Get response */ | ||
961 | jz_mmc_get_response(request); | ||
962 | |||
963 | /* Start data operation */ | ||
964 | if (events & (MMC_EVENT_RX_DATA_DONE | MMC_EVENT_TX_DATA_DONE)) | ||
965 | { | ||
966 | if (events & MMC_EVENT_RX_DATA_DONE) | ||
967 | { | ||
968 | if (request->cmd == SEND_SCR) | ||
969 | { | ||
970 | /* SD card returns SCR register as data. | ||
971 | MMC core expect it in the response buffer, | ||
972 | after normal response. */ | ||
973 | request->buffer = | ||
974 | (unsigned char *) ((unsigned int) request->response + 5); | ||
975 | } | ||
976 | #ifdef MMC_DMA_ENABLE | ||
977 | jz_mmc_receive_data_dma(request); | ||
978 | #else | ||
979 | jz_mmc_receive_data(request); | ||
980 | #endif | ||
981 | } | ||
982 | |||
983 | if (events & MMC_EVENT_TX_DATA_DONE) | ||
984 | { | ||
985 | #ifdef MMC_DMA_ENABLE | ||
986 | jz_mmc_transmit_data_dma(request); | ||
987 | #else | ||
988 | jz_mmc_transmit_data(request); | ||
989 | #endif | ||
990 | } | ||
991 | //__intc_unmask_irq(IRQ_MSC); | ||
992 | //wakeup_wait(&sd_wakeup, 100); | ||
993 | /* Wait for Data Done */ | ||
994 | while (!(REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE)); | ||
995 | REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE; /* clear status */ | ||
996 | |||
997 | } | ||
998 | |||
999 | /* Wait for Prog Done event */ | ||
1000 | if (events & MMC_EVENT_PROG_DONE) | ||
1001 | { | ||
1002 | //__intc_unmask_irq(IRQ_MSC); | ||
1003 | //wakeup_wait(&sd_wakeup, 100); | ||
1004 | while (!(REG_MSC_IREG & MSC_IREG_PRG_DONE)); | ||
1005 | REG_MSC_IREG = MSC_IREG_PRG_DONE; /* clear status */ | ||
1006 | } | ||
1007 | |||
1008 | /* Command completed */ | ||
1009 | |||
1010 | return MMC_NO_ERROR; /* return successfully */ | ||
1011 | } | ||
1012 | |||
1013 | /******************************************************************************************************************* | ||
1014 | ** Name: int mmc_chkcard() | ||
1015 | ** Function: check whether card is insert entirely | ||
1016 | ** Input: NULL | ||
1017 | ** Output: 1: insert entirely 0: not insert entirely | ||
1018 | ********************************************************************************************************************/ | ||
1019 | static int jz_mmc_chkcard(void) | ||
1020 | { | ||
1021 | if (MMC_INSERT_STATUS() == 0) | ||
1022 | return 1; /* insert entirely */ | ||
1023 | else | ||
1024 | return 0; /* not insert entirely */ | ||
1025 | } | ||
1026 | |||
1027 | #if MMC_DMA_INTERRUPT | ||
1028 | static void jz_mmc_tx_handler(unsigned int arg) | ||
1029 | { | ||
1030 | if (__dmac_channel_address_error_detected(arg)) | ||
1031 | { | ||
1032 | DEBUG("%s: DMAC address error.", __FUNCTION__); | ||
1033 | __dmac_channel_clear_address_error(arg); | ||
1034 | } | ||
1035 | if (__dmac_channel_transmit_end_detected(arg)) | ||
1036 | { | ||
1037 | |||
1038 | __dmac_channel_clear_transmit_end(arg); | ||
1039 | OSSemPost(mmc_dma_tx_sem); | ||
1040 | } | ||
1041 | } | ||
1042 | |||
1043 | static void jz_mmc_rx_handler(unsigned int arg) | ||
1044 | { | ||
1045 | if (__dmac_channel_address_error_detected(arg)) | ||
1046 | { | ||
1047 | DEBUG("%s: DMAC address error.", __FUNCTION__); | ||
1048 | __dmac_channel_clear_address_error(arg); | ||
1049 | } | ||
1050 | if (__dmac_channel_transmit_end_detected(arg)) | ||
1051 | { | ||
1052 | __dmac_channel_clear_transmit_end(arg); | ||
1053 | OSSemPost(mmc_dma_rx_sem); | ||
1054 | } | ||
1055 | } | ||
1056 | #endif | ||
1057 | |||
1058 | /* MSC interrupt handler */ | ||
1059 | void MSC(void) | ||
1060 | { | ||
1061 | //wakeup_signal(&sd_wakeup); | ||
1062 | } | ||
1063 | |||
1064 | /******************************************************************************************************************* | ||
1065 | ** Name: void mmc_hardware_init() | ||
1066 | ** Function: initialize the hardware condiction that access sd card | ||
1067 | ** Input: NULL | ||
1068 | ** Output: NULL | ||
1069 | ********************************************************************************************************************/ | ||
1070 | static void jz_mmc_hardware_init(void) | ||
1071 | { | ||
1072 | mmc_init_gpio(); /* init GPIO */ | ||
1073 | MMC_POWER_ON(); /* turn on power of card */ | ||
1074 | MMC_RESET(); /* reset mmc/sd controller */ | ||
1075 | MMC_IRQ_MASK(); /* mask all IRQs */ | ||
1076 | jz_mmc_stop_clock(); /* stop MMC/SD clock */ | ||
1077 | #ifdef MMC_DMA_ENABLE | ||
1078 | __cpm_start_dmac(); | ||
1079 | __dmac_enable_module(); | ||
1080 | // REG_DMAC_DMACR = DMAC_DMACR_DME; | ||
1081 | #if MMC_DMA_INTERRUPT | ||
1082 | mmc_dma_rx_sem = OSSemCreate(0); | ||
1083 | mmc_dma_tx_sem = OSSemCreate(0); | ||
1084 | request_irq(IRQ_DMA_0 + RX_DMA_CHANNEL, jz_mmc_rx_handler, | ||
1085 | RX_DMA_CHANNEL); | ||
1086 | request_irq(IRQ_DMA_0 + TX_DMA_CHANNEL, jz_mmc_tx_handler, | ||
1087 | TX_DMA_CHANNEL); | ||
1088 | #endif | ||
1089 | #endif | ||
1090 | } | ||
1091 | |||
1092 | static void mmc_send_cmd(struct mmc_request *request, int cmd, unsigned int arg, | ||
1093 | unsigned short nob, unsigned short block_len, | ||
1094 | enum mmc_rsp_t rtype, unsigned char* buffer) | ||
1095 | { | ||
1096 | request->cmd = cmd; | ||
1097 | request->arg = arg; | ||
1098 | request->rtype = rtype; | ||
1099 | request->nob = nob; | ||
1100 | request->block_len = block_len; | ||
1101 | request->buffer = buffer; | ||
1102 | request->cnt = nob * block_len; | ||
1103 | printf("mmc_send_cmd: command = %d",cmd); | ||
1104 | jz_mmc_exec_cmd(request); | ||
1105 | } | ||
1106 | |||
1107 | static bool inited = false; | ||
1108 | int sd_init(void) | ||
1109 | { | ||
1110 | if(!inited) | ||
1111 | { | ||
1112 | jz_mmc_hardware_init(); | ||
1113 | wakeup_init(&sd_wakeup); | ||
1114 | inited = true; | ||
1115 | } | ||
1116 | |||
1117 | struct mmc_request test; | ||
1118 | //mmc_send_cmd(&test, MMC_CIM_RESET, 0, 0, 0, RESPONSE_NONE, NULL); | ||
1119 | mmc_send_cmd(&test, MMC_GO_IDLE_STATE, 0, 0, 0, RESPONSE_NONE, NULL); | ||
1120 | mmc_send_cmd(&test, SD_SEND_OP_COND, MMC_OCR_ARG, 0, 0, RESPONSE_R3, NULL); | ||
1121 | |||
1122 | return 0; | ||
1123 | } | ||
1124 | |||
1125 | bool card_detect_target(void) | ||
1126 | { | ||
1127 | return jz_mmc_chkcard() == 1; | ||
1128 | } | ||
1129 | |||
1130 | #ifdef HAVE_HOTSWAP | ||
1131 | void card_enable_monitoring_target(bool on) | ||
1132 | { | ||
1133 | if(on) | ||
1134 | { | ||
1135 | |||
1136 | } | ||
1137 | else | ||
1138 | { | ||
1139 | |||
1140 | } | ||
1141 | } | ||
1142 | #endif | ||
1143 | |||
1144 | /* TODO */ | ||
1145 | tCardInfo* card_get_info_target(int card_no) | ||
1146 | { | ||
1147 | static tCardInfo card; | ||
1148 | |||
1149 | return &card; | ||
1150 | } | ||
1151 | |||
1152 | /* TODO */ | ||
1153 | int sd_read_sectors(unsigned long start, int count, void* buf) | ||
1154 | { | ||
1155 | (void)start; | ||
1156 | (void)count; | ||
1157 | (void)buf; | ||
1158 | return -1; | ||
1159 | } | ||
1160 | |||
1161 | /* TODO */ | ||
1162 | int sd_write_sectors(unsigned long start, int count, const void* buf) | ||
1163 | { | ||
1164 | (void)start; | ||
1165 | (void)count; | ||
1166 | (void)buf; | ||
1167 | return -1; | ||
1168 | } | ||