summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2011-03-01 07:53:46 +0000
committerMarcin Bukat <marcin.bukat@gmail.com>2011-03-01 07:53:46 +0000
commitfec3193f8a32ce4158767ee063105692cce4c1b8 (patch)
tree15eed2f934e9acccbc6f7d594c73c639260baab8 /firmware/target
parentfb3616368f5e9994716e30a040865f3cf398aa21 (diff)
downloadrockbox-fec3193f8a32ce4158767ee063105692cce4c1b8.tar.gz
rockbox-fec3193f8a32ce4158767ee063105692cce4c1b8.zip
Move ata_mmc.c into target tree as it is SH (ondio) specific. Associated header file is left intact as it seems to be used in many places for historical reasons
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29478 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/sh/archos/ondio/ata_mmc.c1027
1 files changed, 1027 insertions, 0 deletions
diff --git a/firmware/target/sh/archos/ondio/ata_mmc.c b/firmware/target/sh/archos/ondio/ata_mmc.c
new file mode 100644
index 0000000000..fc2efcd3e4
--- /dev/null
+++ b/firmware/target/sh/archos/ondio/ata_mmc.c
@@ -0,0 +1,1027 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 by Jens Arnold
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#include <stdbool.h>
22#include "mmc.h"
23#include "ata_mmc.h"
24#include "sdmmc.h"
25#include "ata_idle_notify.h"
26#include "kernel.h"
27#include "thread.h"
28#include "led.h"
29#include "sh7034.h"
30#include "system.h"
31#include "debug.h"
32#include "panic.h"
33#include "usb.h"
34#include "power.h"
35#include "string.h"
36#include "hwcompat.h"
37#include "adc.h"
38#include "bitswap.h"
39#include "disk.h" /* for mount/unmount */
40#include "storage.h"
41
42#define BLOCK_SIZE 512 /* fixed */
43
44/* Command definitions */
45#define CMD_GO_IDLE_STATE 0x40 /* R1 */
46#define CMD_SEND_OP_COND 0x41 /* R1 */
47#define CMD_SEND_CSD 0x49 /* R1 */
48#define CMD_SEND_CID 0x4a /* R1 */
49#define CMD_STOP_TRANSMISSION 0x4c /* R1 */
50#define CMD_SEND_STATUS 0x4d /* R2 */
51#define CMD_SET_BLOCKLEN 0x50 /* R1 */
52#define CMD_READ_SINGLE_BLOCK 0x51 /* R1 */
53#define CMD_READ_MULTIPLE_BLOCK 0x52 /* R1 */
54#define CMD_WRITE_BLOCK 0x58 /* R1b */
55#define CMD_WRITE_MULTIPLE_BLOCK 0x59 /* R1b */
56#define CMD_READ_OCR 0x7a /* R3 */
57
58/* Response formats:
59 R1 = single byte, msb=0, various error flags
60 R1b = R1 + busy token(s)
61 R2 = 2 bytes (1st byte identical to R1), additional flags
62 R3 = 5 bytes (R1 + OCR register)
63*/
64
65#define R1_PARAMETER_ERR 0x40
66#define R1_ADDRESS_ERR 0x20
67#define R1_ERASE_SEQ_ERR 0x10
68#define R1_COM_CRC_ERR 0x08
69#define R1_ILLEGAL_CMD 0x04
70#define R1_ERASE_RESET 0x02
71#define R1_IN_IDLE_STATE 0x01
72
73#define R2_OUT_OF_RANGE 0x80
74#define R2_ERASE_PARAM 0x40
75#define R2_WP_VIOLATION 0x20
76#define R2_CARD_ECC_FAIL 0x10
77#define R2_CC_ERROR 0x08
78#define R2_ERROR 0x04
79#define R2_ERASE_SKIP 0x02
80#define R2_CARD_LOCKED 0x01
81
82/* Data start tokens */
83
84#define DT_START_BLOCK 0xfe
85#define DT_START_WRITE_MULTIPLE 0xfc
86#define DT_STOP_TRAN 0xfd
87
88/* for compatibility */
89static long last_disk_activity = -1;
90
91/* private variables */
92
93static struct mutex mmc_mutex SHAREDBSS_ATTR;
94
95#ifdef HAVE_HOTSWAP
96static long mmc_stack[((DEFAULT_STACK_SIZE*2) + 0x800)/sizeof(long)];
97#else
98static long mmc_stack[(DEFAULT_STACK_SIZE*2)/sizeof(long)];
99#endif
100static const char mmc_thread_name[] = "mmc";
101static struct event_queue mmc_queue SHAREDBSS_ATTR;
102static bool initialized = false;
103static bool new_mmc_circuit;
104
105static enum {
106 MMC_UNKNOWN,
107 MMC_UNTOUCHED,
108 MMC_TOUCHED
109} mmc_status = MMC_UNKNOWN;
110
111static enum {
112 SER_POLL_WRITE,
113 SER_POLL_READ,
114 SER_DISABLED
115} serial_mode;
116
117static const unsigned char dummy[] = {
118 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
119};
120
121/* 2 buffers used alternatively for writing, including start token,
122 * dummy CRC and an extra byte to keep word alignment. */
123static unsigned char write_buffer[2][BLOCK_SIZE+4];
124static int current_buffer = 0;
125static const unsigned char *send_block_addr = NULL;
126
127static tCardInfo card_info[2];
128#ifndef HAVE_MULTIDRIVE
129static int current_card = 0;
130#endif
131static bool last_mmc_status = false;
132static int countdown = -1; /* for mmc switch debouncing. -1 because the
133 countdown should not happen if the card
134 is inserted at boot */
135static bool usb_activity; /* monitoring the USB bridge */
136static long last_usb_activity;
137
138/* private function declarations */
139
140static int select_card(int card_no);
141static void deselect_card(void);
142static void setup_sci1(int bitrate_register);
143static void set_sci1_poll_read(void);
144static void write_transfer(const unsigned char *buf, int len)
145 __attribute__ ((section(".icode")));
146static void read_transfer(unsigned char *buf, int len)
147 __attribute__ ((section(".icode")));
148static unsigned char poll_byte(long timeout);
149static unsigned char poll_busy(long timeout);
150static unsigned char send_cmd(int cmd, unsigned long parameter, void *data);
151static int receive_cxd(unsigned char *buf);
152static int initialize_card(int card_no);
153static int receive_block(unsigned char *inbuf, long timeout);
154static void send_block_prepare(void);
155static int send_block_send(unsigned char start_token, long timeout,
156 bool prepare_next);
157static void mmc_tick(void);
158
159/* implementation */
160
161void mmc_enable_int_flash_clock(bool on)
162{
163 /* Internal flash clock is enabled by setting PA12 high with the new
164 * clock circuit, and by setting it low with the old clock circuit */
165 if (on ^ new_mmc_circuit)
166 and_b(~0x10, &PADRH); /* clear clock gate PA12 */
167 else
168 or_b(0x10, &PADRH); /* set clock gate PA12 */
169}
170
171static int select_card(int card_no)
172{
173 mutex_lock(&mmc_mutex);
174 led(true);
175 last_disk_activity = current_tick;
176
177 mmc_enable_int_flash_clock(card_no == 0);
178
179 if (!card_info[card_no].initialized)
180 {
181 setup_sci1(7); /* Initial rate: 375 kbps (need <= 400 per mmc specs) */
182 write_transfer(dummy, 10); /* allow the card to synchronize */
183 while (!(SSR1 & SCI_TEND));
184 }
185
186 if (card_no == 0) /* internal */
187 and_b(~0x04, &PADRH); /* assert CS */
188 else /* external */
189 and_b(~0x02, &PADRH); /* assert CS */
190
191 if (card_info[card_no].initialized)
192 {
193 setup_sci1(card_info[card_no].bitrate_register);
194 return 0;
195 }
196 else
197 {
198 return initialize_card(card_no);
199 }
200}
201
202static void deselect_card(void)
203{
204 while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */
205 or_b(0x06, &PADRH); /* deassert CS (both cards) */
206
207 led(false);
208 mutex_unlock(&mmc_mutex);
209 last_disk_activity = current_tick;
210}
211
212static void setup_sci1(int bitrate_register)
213{
214 while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */
215
216 SCR1 = 0; /* disable serial port */
217 SMR1 = SYNC_MODE; /* no prescale */
218 BRR1 = bitrate_register;
219 SSR1 = 0;
220
221 SCR1 = SCI_TE; /* enable transmitter */
222 serial_mode = SER_POLL_WRITE;
223}
224
225static void set_sci1_poll_read(void)
226{
227 while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */
228 SCR1 = 0; /* disable transmitter (& receiver) */
229 SCR1 = (SCI_TE|SCI_RE); /* re-enable transmitter & receiver */
230 while (!(SSR1 & SCI_TEND)); /* wait for SCI init completion (!) */
231 serial_mode = SER_POLL_READ;
232 TDR1 = 0xFF; /* send do-nothing while reading */
233}
234
235static void write_transfer(const unsigned char *buf, int len)
236{
237 const unsigned char *buf_end = buf + len;
238 register unsigned char data;
239
240 if (serial_mode != SER_POLL_WRITE)
241 {
242 while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */
243 SCR1 = 0; /* disable transmitter & receiver */
244 SSR1 = 0; /* clear all flags */
245 SCR1 = SCI_TE; /* enable transmitter only */
246 serial_mode = SER_POLL_WRITE;
247 }
248
249 while (buf < buf_end)
250 {
251 data = fliptable[(signed char)(*buf++)]; /* bitswap */
252 while (!(SSR1 & SCI_TDRE)); /* wait for end of transfer */
253 TDR1 = data; /* write byte */
254 SSR1 = 0; /* start transmitting */
255 }
256}
257
258/* don't call this with len == 0 */
259static void read_transfer(unsigned char *buf, int len)
260{
261 unsigned char *buf_end = buf + len - 1;
262 register signed char data;
263
264 if (serial_mode != SER_POLL_READ)
265 set_sci1_poll_read();
266
267 SSR1 = 0; /* start receiving first byte */
268 while (buf < buf_end)
269 {
270 while (!(SSR1 & SCI_RDRF)); /* wait for data */
271 data = RDR1; /* read byte */
272 SSR1 = 0; /* start receiving */
273 *buf++ = fliptable[data]; /* bitswap */
274 }
275 while (!(SSR1 & SCI_RDRF)); /* wait for last byte */
276 *buf = fliptable[(signed char)(RDR1)]; /* read & bitswap */
277}
278
279/* returns 0xFF on timeout, timeout is in bytes */
280static unsigned char poll_byte(long timeout)
281{
282 long i;
283 unsigned char data = 0; /* stop the compiler complaining */
284
285 if (serial_mode != SER_POLL_READ)
286 set_sci1_poll_read();
287
288 i = 0;
289 do {
290 SSR1 = 0; /* start receiving */
291 while (!(SSR1 & SCI_RDRF)); /* wait for data */
292 data = RDR1; /* read byte */
293 } while ((data == 0xFF) && (++i < timeout));
294
295 return fliptable[(signed char)data];
296}
297
298/* returns 0 on timeout, timeout is in bytes */
299static unsigned char poll_busy(long timeout)
300{
301 long i;
302 unsigned char data, dummy;
303
304 if (serial_mode != SER_POLL_READ)
305 set_sci1_poll_read();
306
307 /* get data response */
308 SSR1 = 0; /* start receiving */
309 while (!(SSR1 & SCI_RDRF)); /* wait for data */
310 data = fliptable[(signed char)(RDR1)]; /* read byte */
311
312 /* wait until the card is ready again */
313 i = 0;
314 do {
315 SSR1 = 0; /* start receiving */
316 while (!(SSR1 & SCI_RDRF)); /* wait for data */
317 dummy = RDR1; /* read byte */
318 } while ((dummy != 0xFF) && (++i < timeout));
319
320 return (dummy == 0xFF) ? data : 0;
321}
322
323/* Send MMC command and get response. Returns R1 byte directly.
324 * Returns further R2 or R3 bytes in *data (can be NULL for other commands) */
325static unsigned char send_cmd(int cmd, unsigned long parameter, void *data)
326{
327 static struct {
328 unsigned char cmd;
329 unsigned long parameter;
330 const unsigned char crc7; /* fixed, valid for CMD0 only */
331 const unsigned char trailer;
332 } __attribute__((packed)) command = {0x40, 0, 0x95, 0xFF};
333
334 unsigned char ret;
335
336 command.cmd = cmd;
337 command.parameter = htobe32(parameter);
338
339 write_transfer((unsigned char *)&command, sizeof(command));
340
341 ret = poll_byte(20);
342
343 switch (cmd)
344 {
345 case CMD_SEND_CSD: /* R1 response, leave open */
346 case CMD_SEND_CID:
347 case CMD_READ_SINGLE_BLOCK:
348 case CMD_READ_MULTIPLE_BLOCK:
349 return ret;
350
351 case CMD_SEND_STATUS: /* R2 response, close with dummy */
352 read_transfer(data, 1);
353 break;
354
355 case CMD_READ_OCR: /* R3 response, close with dummy */
356 read_transfer(data, 4);
357 break;
358
359 default: /* R1 response, close with dummy */
360 break; /* also catches block writes */
361 }
362 write_transfer(dummy, 1);
363 return ret;
364}
365
366/* Receive CID/ CSD data (16 bytes) */
367static int receive_cxd(unsigned char *buf)
368{
369 if (poll_byte(20) != DT_START_BLOCK)
370 {
371 write_transfer(dummy, 1);
372 return -1; /* not start of data */
373 }
374
375 read_transfer(buf, 16);
376 write_transfer(dummy, 3); /* 2 bytes dontcare crc + 1 byte trailer */
377 return 0;
378}
379
380
381static int initialize_card(int card_no)
382{
383 int rc, i;
384 int blk_exp, ts_exp, taac_exp;
385 tCardInfo *card = &card_info[card_no];
386
387 static const char mantissa[] = { /* *10 */
388 0, 10, 12, 13, 15, 20, 25, 30,
389 35, 40, 45, 50, 55, 60, 70, 80
390 };
391 static const int exponent[] = { /* use varies */
392 1, 10, 100, 1000, 10000, 100000, 1000000,
393 10000000, 100000000, 1000000000
394 };
395
396 if (card_no == 1)
397 mmc_status = MMC_TOUCHED;
398
399 /* switch to SPI mode */
400 if (send_cmd(CMD_GO_IDLE_STATE, 0, NULL) != 0x01)
401 return -1; /* error or no response */
402
403 /* initialize card */
404 for (i = HZ;;) /* try for 1 second*/
405 {
406 sleep(1);
407 if (send_cmd(CMD_SEND_OP_COND, 0, NULL) == 0)
408 break;
409 if (--i <= 0)
410 return -2; /* timeout */
411 }
412
413 /* get OCR register */
414 if (send_cmd(CMD_READ_OCR, 0, &card->ocr))
415 return -3;
416 card->ocr = betoh32(card->ocr); /* no-op on big endian */
417
418 /* check voltage */
419 if (!(card->ocr & 0x00100000)) /* 3.2 .. 3.3 V */
420 return -4;
421
422 /* get CSD register */
423 if (send_cmd(CMD_SEND_CSD, 0, NULL))
424 return -5;
425 rc = receive_cxd((unsigned char*)card->csd);
426 if (rc)
427 return rc * 10 - 5;
428
429 blk_exp = card_extract_bits(card->csd, 83, 4);
430 if (blk_exp < 9) /* block size < 512 bytes not supported */
431 return -6;
432
433 card->numblocks = (card_extract_bits(card->csd, 73, 12) + 1)
434 << (card_extract_bits(card->csd, 49, 3) + 2 + blk_exp - 9);
435 card->blocksize = BLOCK_SIZE;
436
437 /* max transmission speed, clock divider */
438 ts_exp = card_extract_bits(card->csd, 98, 3);
439 ts_exp = (ts_exp > 3) ? 3 : ts_exp;
440 card->speed = mantissa[card_extract_bits(card->csd, 102, 4)]
441 * exponent[ts_exp + 4];
442 card->bitrate_register = (FREQ/4-1) / card->speed;
443
444 /* NSAC, TAAC, read timeout */
445 card->nsac = 100 * card_extract_bits(card->csd, 111, 8);
446 card->taac = mantissa[card_extract_bits(card->csd, 118, 4)];
447 taac_exp = card_extract_bits(card->csd, 114, 3);
448 card->read_timeout = ((FREQ/4) / (card->bitrate_register + 1)
449 * card->taac / exponent[9 - taac_exp]
450 + (10 * card->nsac));
451 card->read_timeout /= 8; /* clocks -> bytes */
452 card->taac = card->taac * exponent[taac_exp] / 10;
453
454 /* r2w_factor, write timeout */
455 card->r2w_factor = BIT_N(card_extract_bits(card->csd, 28, 3));
456 card->write_timeout = card->read_timeout * card->r2w_factor;
457
458 if (card->r2w_factor > 32) /* Such cards often need extra read delay */
459 card->read_timeout *= 4;
460
461 /* switch to full speed */
462 setup_sci1(card->bitrate_register);
463
464 /* always use 512 byte blocks */
465 if (send_cmd(CMD_SET_BLOCKLEN, BLOCK_SIZE, NULL))
466 return -7;
467
468 /* get CID register */
469 if (send_cmd(CMD_SEND_CID, 0, NULL))
470 return -8;
471 rc = receive_cxd((unsigned char*)card->cid);
472 if (rc)
473 return rc * 10 - 8;
474
475 card->initialized = true;
476 return 0;
477}
478
479tCardInfo *mmc_card_info(int card_no)
480{
481 tCardInfo *card = &card_info[card_no];
482
483 if (!card->initialized && ((card_no == 0) || mmc_detect()))
484 {
485 select_card(card_no);
486 deselect_card();
487 }
488 return card;
489}
490
491/* Receive one block with DMA and bitswap it (chasing bitswap). */
492static int receive_block(unsigned char *inbuf, long timeout)
493{
494 unsigned long buf_end;
495
496 if (poll_byte(timeout) != DT_START_BLOCK)
497 {
498 write_transfer(dummy, 1);
499 return -1; /* not start of data */
500 }
501
502 while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */
503
504 SCR1 = 0; /* disable serial */
505 SSR1 = 0; /* clear all flags */
506
507 /* setup DMA channel 0 */
508 CHCR0 = 0; /* disable */
509 SAR0 = RDR1_ADDR;
510 DAR0 = (unsigned long) inbuf;
511 DTCR0 = BLOCK_SIZE;
512 CHCR0 = 0x4601; /* fixed source address, RXI1, enable */
513 DMAOR = 0x0001;
514 SCR1 = (SCI_RE|SCI_RIE); /* kick off DMA */
515
516 /* DMA receives 2 bytes more than DTCR2, but the last 2 bytes are not
517 * stored. The first extra byte is available from RDR1 after the DMA ends,
518 * the second one is lost because of the SCI overrun. However, this
519 * behaviour conveniently discards the crc. */
520
521 yield(); /* be nice */
522
523 /* Bitswap received data, chasing the DMA pointer */
524 buf_end = (unsigned long)inbuf + BLOCK_SIZE;
525 do
526 {
527 /* Call bitswap whenever (a multiple of) 8 bytes are
528 * available (value optimised by experimentation). */
529 int swap_now = (DAR0 - (unsigned long)inbuf) & ~0x00000007;
530 if (swap_now)
531 {
532 bitswap(inbuf, swap_now);
533 inbuf += swap_now;
534 }
535 }
536 while ((unsigned long)inbuf < buf_end);
537
538 while (!(CHCR0 & 0x0002)); /* wait for end of DMA */
539 while (!(SSR1 & SCI_ORER)); /* wait for the trailing bytes */
540 SCR1 = 0;
541 serial_mode = SER_DISABLED;
542
543 write_transfer(dummy, 1); /* send trailer */
544 last_disk_activity = current_tick;
545 return 0;
546}
547
548/* Prepare a block for sending by copying it to the next write buffer
549 * and bitswapping it. */
550static void send_block_prepare(void)
551{
552 unsigned char *dest;
553
554 current_buffer ^= 1; /* toggle buffer */
555 dest = write_buffer[current_buffer] + 2;
556
557 memcpy(dest, send_block_addr, BLOCK_SIZE);
558 bitswap(dest, BLOCK_SIZE);
559
560 send_block_addr += BLOCK_SIZE;
561}
562
563/* Send one block with DMA from the current write buffer, possibly preparing
564 * the next block within the next write buffer in the background. */
565static int send_block_send(unsigned char start_token, long timeout,
566 bool prepare_next)
567{
568 int rc = 0;
569 unsigned char *curbuf = write_buffer[current_buffer];
570
571 curbuf[1] = fliptable[(signed char)start_token];
572 *(unsigned short *)(curbuf + BLOCK_SIZE + 2) = 0xFFFF;
573
574 while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */
575
576 SCR1 = 0; /* disable serial */
577 SSR1 = 0; /* clear all flags */
578
579 /* setup DMA channel 0 */
580 CHCR0 = 0; /* disable */
581 SAR0 = (unsigned long)(curbuf + 1);
582 DAR0 = TDR1_ADDR;
583 DTCR0 = BLOCK_SIZE + 3; /* start token + block + dummy crc */
584 CHCR0 = 0x1701; /* fixed dest. address, TXI1, enable */
585 DMAOR = 0x0001;
586 SCR1 = (SCI_TE|SCI_TIE); /* kick off DMA */
587
588 if (prepare_next)
589 send_block_prepare();
590 yield(); /* be nice */
591
592 while (!(CHCR0 & 0x0002)); /* wait for end of DMA */
593 while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */
594 SCR1 = 0;
595 serial_mode = SER_DISABLED;
596
597 if ((poll_busy(timeout) & 0x1F) != 0x05) /* something went wrong */
598 rc = -1;
599
600 write_transfer(dummy, 1);
601 last_disk_activity = current_tick;
602
603 return rc;
604}
605
606int mmc_read_sectors(IF_MD2(int drive,)
607 unsigned long start,
608 int incount,
609 void* inbuf)
610{
611 int rc = 0;
612 int lastblock = 0;
613 unsigned long end_block;
614 tCardInfo *card;
615#ifndef HAVE_MULTIDRIVE
616 int drive = current_card;
617#endif
618
619 card = &card_info[drive];
620 rc = select_card(drive);
621 if (rc)
622 {
623 rc = rc * 10 - 1;
624 goto error;
625 }
626
627 end_block = start + incount;
628 if (end_block > card->numblocks)
629 {
630 rc = -2;
631 goto error;
632 }
633
634 /* Some cards don't like reading the very last block with
635 * CMD_READ_MULTIPLE_BLOCK, so make sure this block is always
636 * read with CMD_READ_SINGLE_BLOCK. */
637 if (end_block == card->numblocks)
638 lastblock = 1;
639
640 if (incount > 1)
641 {
642 /* MMC4.2: make multiplication conditional */
643 if (send_cmd(CMD_READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, NULL))
644 {
645 rc = -3;
646 goto error;
647 }
648 while (--incount >= lastblock)
649 {
650 rc = receive_block(inbuf, card->read_timeout);
651 if (rc)
652 {
653 /* If an error occurs during multiple block reading, the
654 * host still needs to send CMD_STOP_TRANSMISSION */
655 send_cmd(CMD_STOP_TRANSMISSION, 0, NULL);
656 rc = rc * 10 - 4;
657 goto error;
658 }
659 inbuf += BLOCK_SIZE;
660 start++;
661 /* ^^ necessary for the abovementioned last block special case */
662 }
663 if (send_cmd(CMD_STOP_TRANSMISSION, 0, NULL))
664 {
665 rc = -5;
666 goto error;
667 }
668 }
669 if (incount > 0)
670 {
671 /* MMC4.2: make multiplication conditional */
672 if (send_cmd(CMD_READ_SINGLE_BLOCK, start * BLOCK_SIZE, NULL))
673 {
674 rc = -6;
675 goto error;
676 }
677 rc = receive_block(inbuf, card->read_timeout);
678 if (rc)
679 {
680 rc = rc * 10 - 7;
681 goto error;
682 }
683 }
684
685 error:
686
687 deselect_card();
688
689 return rc;
690}
691
692int mmc_write_sectors(IF_MD2(int drive,)
693 unsigned long start,
694 int count,
695 const void* buf)
696{
697 int rc = 0;
698 int write_cmd;
699 unsigned char start_token;
700 tCardInfo *card;
701#ifndef HAVE_MULTIDRIVE
702 int drive = current_card;
703#endif
704
705 card = &card_info[drive];
706 rc = select_card(drive);
707 if (rc)
708 {
709 rc = rc * 10 - 1;
710 goto error;
711 }
712
713 if (start + count > card->numblocks)
714 panicf("Writing past end of card");
715
716 send_block_addr = buf;
717 send_block_prepare();
718
719 if (count > 1)
720 {
721 write_cmd = CMD_WRITE_MULTIPLE_BLOCK;
722 start_token = DT_START_WRITE_MULTIPLE;
723 }
724 else
725 {
726 write_cmd = CMD_WRITE_BLOCK;
727 start_token = DT_START_BLOCK;
728 }
729 /* MMC4.2: make multiplication conditional */
730 if (send_cmd(write_cmd, start * BLOCK_SIZE, NULL))
731 {
732 rc = -2;
733 goto error;
734 }
735 while (--count >= 0)
736 {
737 rc = send_block_send(start_token, card->write_timeout, count > 0);
738 if (rc)
739 {
740 rc = rc * 10 - 3;
741 break;
742 /* If an error occurs during multiple block writing,
743 * the STOP_TRAN token still needs to be sent. */
744 }
745 }
746 if (write_cmd == CMD_WRITE_MULTIPLE_BLOCK)
747 {
748 static const unsigned char stop_tran = DT_STOP_TRAN;
749 write_transfer(&stop_tran, 1);
750 poll_busy(card->write_timeout);
751 }
752
753 error:
754
755 deselect_card();
756
757 return rc;
758}
759
760bool mmc_disk_is_active(void)
761{
762 /* this is correct unless early return from write gets implemented */
763 return mutex_test(&mmc_mutex);
764}
765
766static void mmc_thread(void)
767{
768 struct queue_event ev;
769 bool idle_notified = false;
770
771 while (1) {
772 queue_wait_w_tmo(&mmc_queue, &ev, HZ);
773 switch ( ev.id )
774 {
775 case SYS_USB_CONNECTED:
776 usb_acknowledge(SYS_USB_CONNECTED_ACK);
777 /* Wait until the USB cable is extracted again */
778 usb_wait_for_disconnect(&mmc_queue);
779 break;
780
781#ifdef HAVE_HOTSWAP
782 case SYS_HOTSWAP_INSERTED:
783 disk_mount(1); /* mount MMC */
784 queue_broadcast(SYS_FS_CHANGED, 0);
785 break;
786
787 case SYS_HOTSWAP_EXTRACTED:
788 disk_unmount(1); /* release "by force" */
789 queue_broadcast(SYS_FS_CHANGED, 0);
790 break;
791#endif
792
793 default:
794 if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
795 {
796 idle_notified = false;
797 }
798 else
799 {
800 if (!idle_notified)
801 {
802 call_storage_idle_notifys(false);
803 idle_notified = true;
804 }
805 }
806 break;
807 }
808 }
809}
810
811bool mmc_detect(void)
812{
813 return (adc_read(ADC_MMC_SWITCH) < 0x200);
814}
815
816bool mmc_touched(void)
817{
818 if (mmc_status == MMC_UNKNOWN) /* try to detect */
819 {
820 mutex_lock(&mmc_mutex);
821 setup_sci1(7); /* safe value */
822 and_b(~0x02, &PADRH); /* assert CS */
823 if (send_cmd(CMD_SEND_OP_COND, 0, NULL) == 0xFF)
824 mmc_status = MMC_UNTOUCHED;
825 else
826 mmc_status = MMC_TOUCHED;
827
828 deselect_card();
829 }
830 return mmc_status == MMC_TOUCHED;
831}
832
833bool mmc_usb_active(int delayticks)
834{
835 /* reading "inactive" is delayed by user-supplied monoflop value */
836 return (usb_activity ||
837 TIME_BEFORE(current_tick, last_usb_activity + delayticks));
838}
839
840static void mmc_tick(void)
841{
842 bool current_status;
843
844 if (new_mmc_circuit)
845 /* USB bridge activity is 0 on idle, ~527 on active */
846 current_status = adc_read(ADC_USB_ACTIVE) > 0x100;
847 else
848 current_status = adc_read(ADC_USB_ACTIVE) < 0x190;
849
850 if (!current_status && usb_activity)
851 last_usb_activity = current_tick;
852 usb_activity = current_status;
853
854 current_status = mmc_detect();
855 /* Only report when the status has changed */
856 if (current_status != last_mmc_status)
857 {
858 last_mmc_status = current_status;
859 countdown = HZ/3;
860 }
861 else
862 {
863 /* Count down until it gets negative */
864 if (countdown >= 0)
865 countdown--;
866
867 if (countdown == 0)
868 {
869 if (current_status)
870 {
871 queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
872 }
873 else
874 {
875 queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
876 mmc_status = MMC_UNTOUCHED;
877 card_info[1].initialized = false;
878 }
879 }
880 }
881}
882
883void mmc_enable(bool on)
884{
885 PBCR1 &= ~0x0CF0; /* PB13, PB11 and PB10 become GPIO,
886 * if not modified below */
887 if (on)
888 PBCR1 |= 0x08A0; /* as SCK1, TxD1, RxD1 */
889
890 and_b(~0x80, &PADRL); /* assert flash reset */
891 sleep(HZ/100);
892 or_b(0x80, &PADRL); /* de-assert flash reset */
893 sleep(HZ/100);
894 card_info[0].initialized = false;
895 card_info[1].initialized = false;
896}
897
898int mmc_init(void)
899{
900 int rc = 0;
901
902 if (!initialized)
903 {
904 mutex_init(&mmc_mutex);
905 queue_init(&mmc_queue, true);
906 }
907 mutex_lock(&mmc_mutex);
908 led(false);
909
910 last_mmc_status = mmc_detect();
911#ifndef HAVE_MULTIDRIVE
912 /* Use MMC if inserted, internal flash otherwise */
913 current_card = last_mmc_status ? 1 : 0;
914#endif
915
916 if (!initialized)
917 {
918 if (!last_mmc_status)
919 mmc_status = MMC_UNTOUCHED;
920
921 /* Port setup */
922 PACR1 &= ~0x0F3C; /* GPIO function for PA13 (flash busy), PA12
923 * (clk gate), PA10 (flash CS), PA9 (MMC CS) */
924 PACR2 &= ~0x4000; /* GPIO for PA7 (flash reset) */
925 PADR |= 0x0680; /* set all the selects + reset high (=inactive) */
926 PAIOR |= 0x1680; /* make outputs for them and the PA12 clock gate */
927
928 PBCR1 &= ~0x0CF0; /* GPIO function for PB13, PB11 and PB10 */
929 PBDR |= 0x2C00; /* SCK1, TxD1 and RxD1 high in GPIO */
930 PBIOR |= 0x2000; /* SCK1 output */
931 PBIOR &= ~0x0C00; /* TxD1, RxD1 input */
932
933 IPRE &= 0x0FFF; /* disable SCI1 interrupts for the CPU */
934
935 new_mmc_circuit = ((HW_MASK & MMC_CLOCK_POLARITY) != 0);
936
937 create_thread(mmc_thread, mmc_stack,
938 sizeof(mmc_stack), 0, mmc_thread_name
939 IF_PRIO(, PRIORITY_SYSTEM)
940 IF_COP(, CPU));
941 tick_add_task(mmc_tick);
942 initialized = true;
943 }
944 mmc_enable(true);
945
946 mutex_unlock(&mmc_mutex);
947 return rc;
948}
949
950long mmc_last_disk_activity(void)
951{
952 return last_disk_activity;
953}
954
955#ifdef STORAGE_GET_INFO
956void mmc_get_info(IF_MD2(int drive,) struct storage_info *info)
957{
958#ifndef HAVE_MULTIDRIVE
959 const int drive=0;
960#endif
961 info->sector_size=card_info[drive].blocksize;
962 info->num_sectors=card_info[drive].numblocks;
963 info->vendor="Rockbox";
964 if(drive==0)
965 {
966 info->product="Internal Storage";
967 }
968 else
969 {
970 info->product="MMC Card Slot";
971 }
972 info->revision="0.00";
973}
974#endif
975
976#ifdef HAVE_HOTSWAP
977bool mmc_removable(IF_MD_NONVOID(int drive))
978{
979#ifndef HAVE_MULTIDRIVE
980 const int drive=0;
981#endif
982 return (drive==1);
983}
984
985bool mmc_present(IF_MD_NONVOID(int drive))
986{
987#ifndef HAVE_MULTIDRIVE
988 const int drive=0;
989#endif
990 if(drive==0)
991 {
992 return true;
993 }
994 else
995 {
996 return mmc_detect();
997 }
998}
999#endif
1000
1001
1002void mmc_sleep(void)
1003{
1004}
1005
1006void mmc_spin(void)
1007{
1008}
1009
1010void mmc_spindown(int seconds)
1011{
1012 (void)seconds;
1013}
1014
1015#ifdef CONFIG_STORAGE_MULTI
1016int mmc_num_drives(int first_drive)
1017{
1018 /* We don't care which logical drive number(s) we have been assigned */
1019 (void)first_drive;
1020
1021#ifdef HAVE_MULTIDRIVE
1022 return 2;
1023#else
1024 return 1;
1025#endif
1026}
1027#endif