diff options
Diffstat (limited to 'firmware/drivers/ata_mmc.c')
-rw-r--r-- | firmware/drivers/ata_mmc.c | 102 |
1 files changed, 76 insertions, 26 deletions
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c index a7d7f1d40a..b4c2e844e0 100644 --- a/firmware/drivers/ata_mmc.c +++ b/firmware/drivers/ata_mmc.c | |||
@@ -137,6 +137,12 @@ static int initialize_card(int card_no); | |||
137 | 137 | ||
138 | static int select_card(int card_no) | 138 | static int select_card(int card_no) |
139 | { | 139 | { |
140 | if (!card_info[card_no].initialized) | ||
141 | { | ||
142 | write_transfer(dummy, 10); /* allow the card to synchronize */ | ||
143 | while (!(SSR1 & SCI_TEND)); | ||
144 | } | ||
145 | |||
140 | if (card_no == 0) | 146 | if (card_no == 0) |
141 | { /* internal */ | 147 | { /* internal */ |
142 | or_b(0x10, &PADRH); /* set clock gate PA12 CHECKME: mask? */ | 148 | or_b(0x10, &PADRH); /* set clock gate PA12 CHECKME: mask? */ |
@@ -161,7 +167,7 @@ static int select_card(int card_no) | |||
161 | 167 | ||
162 | static void deselect_card(void) | 168 | static void deselect_card(void) |
163 | { | 169 | { |
164 | while (!(SSR1 & SCI_TEND)); /* wait until end of transfer */ | 170 | while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */ |
165 | or_b(0x06, &PADRH); /* deassert CS (both cards) */ | 171 | or_b(0x06, &PADRH); /* deassert CS (both cards) */ |
166 | } | 172 | } |
167 | 173 | ||
@@ -169,7 +175,7 @@ static void setup_sci1(int bitrate_register) | |||
169 | { | 175 | { |
170 | int i; | 176 | int i; |
171 | 177 | ||
172 | while (!(SSR1 & SCI_TEND)); /* wait until previous transfer ended */ | 178 | while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */ |
173 | 179 | ||
174 | SCR1 = 0; /* disable serial port */ | 180 | SCR1 = 0; /* disable serial port */ |
175 | SMR1 = SYNC_MODE; /* no prescale */ | 181 | SMR1 = SYNC_MODE; /* no prescale */ |
@@ -187,12 +193,10 @@ static void write_transfer(const unsigned char *buf, int len) | |||
187 | const unsigned char *buf_end = buf + len; | 193 | const unsigned char *buf_end = buf + len; |
188 | 194 | ||
189 | /* TODO: DMA */ | 195 | /* TODO: DMA */ |
190 | 196 | ||
191 | while (!(SSR1 & SCI_TEND)); /* wait until previous transfer ended */ | ||
192 | |||
193 | while (buf < buf_end) | 197 | while (buf < buf_end) |
194 | { | 198 | { |
195 | while (!(SSR1 & SCI_TDRE)); /* wait for Tx reg. free */ | 199 | while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */ |
196 | TDR1 = fliptable[(signed char)(*buf++)]; /* write byte */ | 200 | TDR1 = fliptable[(signed char)(*buf++)]; /* write byte */ |
197 | SSR1 = 0; /* start transmitting */ | 201 | SSR1 = 0; /* start transmitting */ |
198 | } | 202 | } |
@@ -204,7 +208,7 @@ static void read_transfer(unsigned char *buf, int len) | |||
204 | 208 | ||
205 | /* TODO: DMA */ | 209 | /* TODO: DMA */ |
206 | 210 | ||
207 | while (!(SSR1 & SCI_TEND)); /* wait until previous transfer ended */ | 211 | while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */ |
208 | TDR1 = 0xFF; /* send do-nothing data in parallel */ | 212 | TDR1 = 0xFF; /* send do-nothing data in parallel */ |
209 | 213 | ||
210 | while (buf < buf_end) | 214 | while (buf < buf_end) |
@@ -221,7 +225,7 @@ static unsigned char poll_byte(int timeout) | |||
221 | int i; | 225 | int i; |
222 | unsigned char data = 0; /* stop the compiler complaining */ | 226 | unsigned char data = 0; /* stop the compiler complaining */ |
223 | 227 | ||
224 | while (!(SSR1 & SCI_TEND)); /* wait until previous transfer ended */ | 228 | while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */ |
225 | TDR1 = 0xFF; /* send do-nothing data in parallel */ | 229 | TDR1 = 0xFF; /* send do-nothing data in parallel */ |
226 | 230 | ||
227 | i = 0; | 231 | i = 0; |
@@ -234,6 +238,24 @@ static unsigned char poll_byte(int timeout) | |||
234 | return fliptable[(signed char)data]; | 238 | return fliptable[(signed char)data]; |
235 | } | 239 | } |
236 | 240 | ||
241 | static unsigned char poll_busy(int timeout) | ||
242 | { | ||
243 | int i; | ||
244 | unsigned char data; | ||
245 | |||
246 | while (!(SSR1 &SCI_TEND)); /* wait for end of transfer */ | ||
247 | TDR1 = 0xFF; /* send do-nothing data in parallel */ | ||
248 | |||
249 | i = 0; | ||
250 | do { | ||
251 | SSR1 = 0; /* start receiving */ | ||
252 | while (!(SSR1 & SCI_RDRF)); /* wait for data */ | ||
253 | data = RDR1; /* read byte */ | ||
254 | } while ((data == 0x00) && (++i < timeout)); | ||
255 | |||
256 | return fliptable[(signed char)data]; | ||
257 | } | ||
258 | |||
237 | static int send_cmd(int cmd, unsigned long parameter, unsigned char *response) | 259 | static int send_cmd(int cmd, unsigned long parameter, unsigned char *response) |
238 | { | 260 | { |
239 | unsigned char command[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95 }; | 261 | unsigned char command[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95 }; |
@@ -250,7 +272,7 @@ static int send_cmd(int cmd, unsigned long parameter, unsigned char *response) | |||
250 | 272 | ||
251 | write_transfer(command, 6); | 273 | write_transfer(command, 6); |
252 | 274 | ||
253 | response[0] = poll_byte(50); | 275 | response[0] = poll_byte(20); |
254 | 276 | ||
255 | if (response[0] != 0x00) | 277 | if (response[0] != 0x00) |
256 | { | 278 | { |
@@ -301,6 +323,23 @@ static int receive_data(unsigned char *buf, int len, int timeout) | |||
301 | return 0; | 323 | return 0; |
302 | } | 324 | } |
303 | 325 | ||
326 | static int send_data(const unsigned char *buf, int len, int timeout) | ||
327 | { | ||
328 | static const unsigned char start_data = 0xFE; | ||
329 | int ret = 0; | ||
330 | |||
331 | write_transfer(&start_data, 1); | ||
332 | write_transfer(buf, len); | ||
333 | write_transfer(dummy, 2); /* crc - dontcare */ | ||
334 | |||
335 | if ((poll_busy(timeout) & 0x1F) != 0x05) /* something went wrong */ | ||
336 | ret = -1; | ||
337 | |||
338 | write_transfer(dummy, 1); | ||
339 | |||
340 | return ret; | ||
341 | } | ||
342 | |||
304 | static int initialize_card(int card_no) | 343 | static int initialize_card(int card_no) |
305 | { | 344 | { |
306 | int i, temp; | 345 | int i, temp; |
@@ -322,8 +361,7 @@ static int initialize_card(int card_no) | |||
322 | 361 | ||
323 | card->initialized = false; | 362 | card->initialized = false; |
324 | setup_sci1(7); /* Initial rate: 375 kBit/s (need <= 400 per mmc specs) */ | 363 | setup_sci1(7); /* Initial rate: 375 kBit/s (need <= 400 per mmc specs) */ |
325 | write_transfer(dummy, 10); /* synchronize: 74+ clocks */ | 364 | |
326 | |||
327 | /* switch to SPI mode */ | 365 | /* switch to SPI mode */ |
328 | send_cmd(CMD_GO_IDLE_STATE, 0, &response); | 366 | send_cmd(CMD_GO_IDLE_STATE, 0, &response); |
329 | if (response != 0x01) | 367 | if (response != 0x01) |
@@ -331,7 +369,7 @@ static int initialize_card(int card_no) | |||
331 | 369 | ||
332 | /* initialize card */ | 370 | /* initialize card */ |
333 | i = 0; | 371 | i = 0; |
334 | while (send_cmd(CMD_SEND_OP_COND, 0, &response) && (++i < 100)); | 372 | while (send_cmd(CMD_SEND_OP_COND, 0, &response) && (++i < 200)); |
335 | if (response != 0x00) | 373 | if (response != 0x00) |
336 | return -2; /* not ready */ | 374 | return -2; /* not ready */ |
337 | 375 | ||
@@ -409,7 +447,7 @@ int ata_read_sectors(unsigned long start, | |||
409 | unsigned long addr; | 447 | unsigned long addr; |
410 | unsigned char response; | 448 | unsigned char response; |
411 | tCardInfo *card = &card_info[current_card]; | 449 | tCardInfo *card = &card_info[current_card]; |
412 | 450 | ||
413 | addr = start * SECTOR_SIZE; | 451 | addr = start * SECTOR_SIZE; |
414 | 452 | ||
415 | mutex_lock(&ata_mtx); | 453 | mutex_lock(&ata_mtx); |
@@ -424,7 +462,7 @@ int ata_read_sectors(unsigned long start, | |||
424 | addr += SECTOR_SIZE; | 462 | addr += SECTOR_SIZE; |
425 | inbuf += SECTOR_SIZE; | 463 | inbuf += SECTOR_SIZE; |
426 | } | 464 | } |
427 | 465 | ||
428 | deselect_card(); | 466 | deselect_card(); |
429 | mutex_unlock(&ata_mtx); | 467 | mutex_unlock(&ata_mtx); |
430 | 468 | ||
@@ -437,17 +475,30 @@ int ata_write_sectors(unsigned long start, | |||
437 | const void* buf) | 475 | const void* buf) |
438 | { | 476 | { |
439 | int ret = 0; | 477 | int ret = 0; |
478 | int i; | ||
479 | unsigned long addr; | ||
480 | unsigned char response; | ||
481 | tCardInfo *card = &card_info[current_card]; | ||
440 | 482 | ||
441 | if (start == 0) | 483 | if (start == 0) |
442 | panicf("Writing on sector 0\n"); | 484 | panicf("Writing on sector 0\n"); |
443 | 485 | ||
486 | addr = start * SECTOR_SIZE; | ||
487 | |||
444 | mutex_lock(&ata_mtx); | 488 | mutex_lock(&ata_mtx); |
489 | ret = select_card(current_card); | ||
445 | 490 | ||
446 | /* ToDo: action */ | 491 | for (i = 0; (i < count) && (ret == 0); i++) |
447 | (void)start; | 492 | { |
448 | (void)count; | 493 | if ((ret = send_cmd(CMD_WRITE_BLOCK, addr, &response))) |
449 | (void)buf; | 494 | break; |
495 | ret = send_data(buf, SECTOR_SIZE, card->write_timeout); | ||
450 | 496 | ||
497 | addr += SECTOR_SIZE; | ||
498 | buf += SECTOR_SIZE; | ||
499 | } | ||
500 | |||
501 | deselect_card(); | ||
451 | mutex_unlock(&ata_mtx); | 502 | mutex_unlock(&ata_mtx); |
452 | 503 | ||
453 | return ret; | 504 | return ret; |
@@ -532,16 +583,15 @@ void ata_enable(bool on) | |||
532 | PBCR1 &= ~0x0CF0; /* PB13, PB11 and PB10 become GPIOs, if not modified below */ | 583 | PBCR1 &= ~0x0CF0; /* PB13, PB11 and PB10 become GPIOs, if not modified below */ |
533 | if (on) | 584 | if (on) |
534 | { | 585 | { |
535 | /* serial setup */ | ||
536 | PBCR1 |= 0x08A0; /* as SCK1, TxD1, RxD1 */ | 586 | PBCR1 |= 0x08A0; /* as SCK1, TxD1, RxD1 */ |
587 | IPRE &= 0x0FFF; /* disable SCI1 interrupts for the CPU */ | ||
537 | } | 588 | } |
538 | else | 589 | and_b(~0x80, &PADRL); /* assert reset */ |
539 | { | 590 | sleep(HZ/20); |
540 | and_b(~0x80, &PADRL); /* assert reset */ | 591 | or_b(0x80, &PADRL); /* de-assert reset */ |
541 | sleep(5); | 592 | sleep(HZ/20); |
542 | or_b(0x80, &PADRL); /* de-assert reset */ | 593 | card_info[0].initialized = false; |
543 | sleep(5); | 594 | card_info[1].initialized = false; |
544 | } | ||
545 | } | 595 | } |
546 | 596 | ||
547 | int ata_init(void) | 597 | int ata_init(void) |