Try to get some control over #ifdef hell in usb.c by refactoring and inline function...
[maemo-rb.git] / firmware / target / arm / tcc780x / sd-tcc780x.c
blob3b67d2195827f843a54486827f225a6cc4a42715
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006 Daniel Ankers
11 * Copyright (C) 2009 Rob Purchase
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
22 #include "sd.h"
23 #include "system.h"
24 #include <string.h>
25 #include "gcc_extensions.h"
26 #include "sdmmc.h"
27 #include "storage.h"
28 #include "led.h"
29 #include "thread.h"
30 #include "disk.h"
31 #include "fat.h"
32 #include "ata_idle_notify.h"
33 #include "usb.h"
35 #if defined(HAVE_INTERNAL_SD) && defined(HAVE_HOTSWAP)
36 #define CARD_NUM_INTERNAL 0
37 #define CARD_NUM_SLOT 1
38 #elif !defined(HAVE_INTERNAL_SD) && defined(HAVE_HOTSWAP)
39 #define CARD_NUM_SLOT 0
40 #endif
42 #define EC_OK 0
43 #define EC_FAILED 1
44 #define EC_NOCARD 2
45 #define EC_WAIT_STATE_FAILED 3
46 #define EC_POWER_UP 4
47 #define EC_FIFO_WR_EMPTY 5
48 #define EC_FIFO_WR_DONE 6
49 #define EC_TRAN_READ_ENTRY 7
50 #define EC_TRAN_READ_EXIT 8
51 #define EC_TRAN_WRITE_ENTRY 9
52 #define EC_TRAN_WRITE_EXIT 10
53 #define EC_COMMAND 11
54 #define EC_WRITE_PROTECT 12
56 /* for compatibility */
57 static long last_disk_activity = -1;
59 /** static, private data **/
60 static bool initialized = false;
62 static long next_yield = 0;
63 #define MIN_YIELD_PERIOD 1000
65 static tCardInfo card_info[NUM_DRIVES];
66 static tCardInfo *currcard = NULL; /* current active card */
68 struct sd_card_status
70 int retry;
71 int retry_max;
74 static struct sd_card_status sd_status[NUM_DRIVES] =
76 #ifdef HAVE_INTERNAL_SD
77 { 0, 1 },
78 #endif
79 #ifdef HAVE_HOTSWAP
80 { 0, 10 }
81 #endif
84 /* Shoot for around 75% usage */
85 static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
86 static const char sd_thread_name[] = "sd";
87 static struct mutex sd_mtx SHAREDBSS_ATTR;
88 static struct event_queue sd_queue;
90 static int sd_first_drive = 0;
93 static bool sd_poll_status(unsigned int trigger, long timeout)
95 long t = USEC_TIMER;
97 while ((SDISTATUS & trigger) != trigger)
99 long time = USEC_TIMER;
101 if (TIME_AFTER(time, next_yield))
103 long ty = USEC_TIMER;
104 yield();
105 timeout += USEC_TIMER - ty;
106 next_yield = ty + MIN_YIELD_PERIOD;
109 if (TIME_AFTER(time, t + timeout))
110 return false;
113 return true;
116 static int sd_command(unsigned int cmd, unsigned int arg,
117 unsigned long* response, unsigned int resp_type)
119 int sdi_cmd = cmd;
121 sdi_cmd |= (127<<12) | (1<<11); /* max wait time | enable */
123 if (resp_type)
125 /* response type & response required flag */
126 sdi_cmd |= (resp_type<<7) | (1<<6);
129 if (cmd == SD_READ_SINGLE_BLOCK ||
130 cmd == SD_READ_MULTIPLE_BLOCK ||
131 cmd == SD_WRITE_BLOCK ||
132 cmd == SD_WRITE_MULTIPLE_BLOCK)
134 sdi_cmd |= (1<<10); /* request data transfer */
137 if (!sd_poll_status(SDISTATUS_CMD_PATH_RDY, 100000))
138 return -EC_COMMAND;
140 SDIARGU = arg;
141 SDICMD = sdi_cmd;
143 udelay(10);
145 if (response == NULL)
146 return 0;
148 if (!sd_poll_status(SDISTATUS_RESP_RCVD, 100000))
149 return -EC_COMMAND;
151 if (resp_type == SDICMD_RES_TYPE2)
153 response[0] = SDIRSPARGU0;
154 response[1] = SDIRSPARGU1;
155 response[2] = SDIRSPARGU2;
156 response[3] = SDIRSPARGU3;
158 else
160 response[0] = SDIRSPARGU0;
163 return 0;
166 static int sd_wait_for_state(unsigned int state, int id)
168 unsigned long response = 0;
169 unsigned int timeout = 0x80000;
171 long start_time = USEC_TIMER;
173 while (1)
175 int ret = sd_command
176 (SD_SEND_STATUS, currcard->rca, &response, SDICMD_RES_TYPE1);
178 long us;
180 if (ret < 0)
181 return ret*100 - id;
183 if (((response >> 9) & 0xf) == state)
185 return 0;
188 if (TIME_AFTER(USEC_TIMER, start_time + timeout))
189 return -EC_WAIT_STATE_FAILED*100 - id;
191 us = USEC_TIMER;
192 if (TIME_AFTER(us, next_yield))
194 yield();
195 timeout += USEC_TIMER - us;
196 next_yield = us + MIN_YIELD_PERIOD;
201 static void sd_card_mux(int card_no)
203 /* We only support the default card */
204 (void)card_no;
207 #ifdef HAVE_HOTSWAP
209 static inline bool card_detect_target(void)
211 #ifdef HAVE_HOTSWAP
212 return (GPIOB & (1<<26)) == 0; /* low active */
213 #else
214 return false;
215 #endif
218 static int sd1_oneshot_callback(struct timeout *tmo)
220 (void)tmo;
222 /* This is called only if the state was stable for 300ms - check state
223 * and post appropriate event. */
224 if (card_detect_target())
225 queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
226 else
227 queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
229 return 0;
232 void EXT0(void)
234 static struct timeout sd1_oneshot;
236 timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0);
239 bool sd_removable(IF_MD_NONVOID(int card_no))
241 #ifndef HAVE_MULTIDRIVE
242 const int card_no = 0;
243 #endif
244 return (card_no == CARD_NUM_SLOT);
247 bool sd_present(IF_MD_NONVOID(int card_no))
249 #ifdef HAVE_MULTIDRIVE
250 (void)card_no;
251 #endif
252 return card_detect_target();
255 #else
257 bool sd_removable(IF_MD_NONVOID(int card_no))
259 #ifndef HAVE_MULTIDRIVE
260 const int card_no = 0;
261 #endif
262 (void)card_no;
264 return false;
267 #endif /* HAVE_HOTSWAP */
270 static void sd_init_device(int card_no)
272 int ret;
273 unsigned long response;
275 /* Initialise card data as blank */
276 memset(currcard, 0, sizeof(*currcard));
278 /* Switch card mux to card to initialize */
279 sd_card_mux(card_no);
281 #ifdef HAVE_HOTSWAP
282 /* Check card is inserted */
283 if (card_no == CARD_NUM_SLOT)
285 if (GPIOB & (1<<26))
287 ret = -EC_NOCARD;
288 goto card_init_error;
291 /* Card will not power up unless this is done */
292 GPIOC_CLEAR = (1<<24);
294 #endif
296 ret = sd_command(SD_GO_IDLE_STATE, 0, NULL, SDICMD_RES_TYPE1);
298 if (ret < 0)
299 goto card_init_error;
301 /* Use slow clock during identification (24MHz / 60 = 400kHz) */
302 SDICLK = (1<<12) | 59;
304 sd_command(SD_SEND_IF_COND, 0x1aa, &response, SDICMD_RES_TYPE3);
306 if (!sd_poll_status(SDISTATUS_CMD_PATH_RDY, 100000))
307 goto card_init_error;
309 currcard->ocr = 0;
311 long start_tick = current_tick;
313 while ((currcard->ocr & (1<<31)) == 0
314 && TIME_BEFORE(current_tick, start_tick + HZ))
316 udelay(100);
317 sd_command(SD_APP_CMD, 0, NULL, SDICMD_RES_TYPE1);
319 int arg = 0x100000 | ((response == 0x1aa) ? (1<<30):0);
320 sd_command(SD_APP_OP_COND, arg, &currcard->ocr, SDICMD_RES_TYPE3);
323 if ((currcard->ocr & (1<<31)) == 0)
325 ret = -EC_POWER_UP;
326 goto card_init_error;
329 ret = sd_command
330 (SD_ALL_SEND_CID, 0, currcard->cid, SDICMD_RES_TYPE2);
332 if (ret < 0)
333 goto card_init_error;
335 ret = sd_command
336 (SD_SEND_RELATIVE_ADDR, 0, &currcard->rca, SDICMD_RES_TYPE1);
338 if (ret < 0)
339 goto card_init_error;
341 ret = sd_command
342 (SD_SEND_CSD, currcard->rca, currcard->csd, SDICMD_RES_TYPE2);
344 if (ret < 0)
345 goto card_init_error;
347 sd_parse_csd(currcard);
349 ret = sd_command
350 (SD_SELECT_CARD, currcard->rca, NULL, SDICMD_RES_TYPE1);
352 if (ret < 0)
353 goto card_init_error;
355 ret = sd_command
356 (SD_APP_CMD, currcard->rca, NULL, SDICMD_RES_TYPE1);
358 if (ret < 0)
359 goto card_init_error;
361 ret = sd_command /* 4 bit */
362 (SD_SET_BUS_WIDTH, currcard->rca | 2, NULL, SDICMD_RES_TYPE1);
364 if (ret < 0)
365 goto card_init_error;
367 ret = sd_command
368 (SD_SET_BLOCKLEN, currcard->blocksize, NULL, SDICMD_RES_TYPE1);
370 if (ret < 0)
371 goto card_init_error;
373 currcard->initialized = 1;
374 return;
376 /* Card failed to initialize so disable it */
377 card_init_error:
378 currcard->initialized = ret;
379 return;
382 /* lock must already be acquired */
383 static void sd_select_device(int card_no)
385 currcard = &card_info[card_no];
387 if (currcard->initialized > 0)
389 /* This card is already initialized - switch to it */
390 sd_card_mux(card_no);
391 return;
394 if (currcard->initialized == 0)
396 /* Card needs (re)init */
397 sd_init_device(card_no);
401 int sd_read_sectors(IF_MD2(int card_no,) unsigned long start, int incount,
402 void* inbuf)
404 #ifndef HAVE_MULTIDRIVE
405 const int card_no = 0;
406 #endif
408 int ret = 0;
409 bool aligned;
410 unsigned char* buf_end;
412 mutex_lock(&sd_mtx);
413 sd_enable(true);
414 led(true);
416 sd_read_retry:
417 if ((card_no == CARD_NUM_SLOT) && !card_detect_target())
419 /* no external sd-card inserted */
420 ret = -EC_NOCARD;
421 goto sd_read_error;
424 sd_select_device(card_no);
426 if (currcard->initialized < 0)
428 ret = currcard->initialized;
429 goto sd_read_error;
432 last_disk_activity = current_tick;
434 ret = sd_wait_for_state(SD_TRAN, EC_TRAN_READ_ENTRY);
436 if (ret < 0)
437 goto sd_read_error;
439 /* Use full SD clock for data transfer (PCK_SDMMC) */
440 SDICLK = (1<<13) | (1<<12); /* bypass divider | enable */
442 /* Block count | FIFO count | Block size (2^9) | 4-bit bus */
443 SDIDCTRL = (incount << 13) | (4<<8) | (9<<4) | (1<<2);
444 SDIDCTRL |= (1<<12); /* nReset */
446 SDIDCTRL2 = (1<<2); /* multi block, read */
448 if (currcard->ocr & (1<<30))
449 ret = sd_command(SD_READ_MULTIPLE_BLOCK, start, NULL, SDICMD_RES_TYPE1);
450 else
451 ret = sd_command(SD_READ_MULTIPLE_BLOCK, start * 512, NULL, SDICMD_RES_TYPE1);
453 if (ret < 0)
454 goto sd_read_error;
456 aligned = (((int)inbuf & 3) == 0);
458 buf_end = (unsigned char *)inbuf + incount * currcard->blocksize;
460 while (inbuf < (void*)buf_end)
462 if (!sd_poll_status(SDISTATUS_FIFO_FETCH_REQ, 100000))
463 goto sd_read_error;
465 if (aligned)
467 unsigned int* ptr = (unsigned int*)inbuf;
468 *ptr++ = SDIRDATA;
469 *ptr++ = SDIRDATA;
470 *ptr++ = SDIRDATA;
471 *ptr = SDIRDATA;
474 else
476 int tmp_buf[4];
478 tmp_buf[0] = SDIRDATA;
479 tmp_buf[1] = SDIRDATA;
480 tmp_buf[2] = SDIRDATA;
481 tmp_buf[3] = SDIRDATA;
483 memcpy(inbuf, tmp_buf, 16);
485 inbuf += 16;
488 ret = sd_command(SD_STOP_TRANSMISSION, 0, NULL, SDICMD_RES_TYPE1);
489 if (ret < 0)
490 goto sd_read_error;
492 ret = sd_wait_for_state(SD_TRAN, EC_TRAN_READ_EXIT);
493 if (ret < 0)
494 goto sd_read_error;
496 while (1)
498 led(false);
499 sd_enable(false);
500 mutex_unlock(&sd_mtx);
502 return ret;
504 sd_read_error:
505 if (sd_status[card_no].retry < sd_status[card_no].retry_max
506 && ret != -EC_NOCARD)
508 sd_status[card_no].retry++;
509 currcard->initialized = 0;
510 goto sd_read_retry;
515 int sd_write_sectors(IF_MD2(int card_no,) unsigned long start, int count,
516 const void* outbuf)
518 /* Write support is not finished yet */
519 /* TODO: The standard suggests using ACMD23 prior to writing multiple blocks
520 to improve performance */
521 #ifndef HAVE_MULTIDRIVE
522 const int card_no = 0;
523 #endif
524 int ret;
525 const unsigned char *buf_end;
526 bool aligned;
528 if ((card_no == CARD_NUM_SLOT) && (GPIOA & 0x10))
530 /* write protect tab set */
531 return -EC_WRITE_PROTECT;
534 mutex_lock(&sd_mtx);
535 sd_enable(true);
536 led(true);
538 sd_write_retry:
539 if ((card_no == CARD_NUM_SLOT) && !card_detect_target())
541 /* no external sd-card inserted */
542 ret = -EC_NOCARD;
543 goto sd_write_error;
546 sd_select_device(card_no);
548 if (currcard->initialized < 0)
550 ret = currcard->initialized;
551 goto sd_write_error;
554 ret = sd_wait_for_state(SD_TRAN, EC_TRAN_WRITE_ENTRY);
556 if (ret < 0)
557 goto sd_write_error;
559 /* Use full SD clock for data transfer (PCK_SDMMC) */
560 SDICLK = (1<<13) | (1<<12); /* bypass divider | enable */
562 /* Block count | FIFO count | Block size (2^9) | 4-bit bus */
563 SDIDCTRL = (count<<13) | (4<<8) | (9<<4) | (1<<2);
564 SDIDCTRL |= (1<<12); /* nReset */
566 SDIDCTRL2 = (1<<2) | (1<<1); /* multi block, write */
568 if (currcard->ocr & (1<<30))
569 ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start, NULL, SDICMD_RES_TYPE1);
570 else
571 ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start * 512, NULL, SDICMD_RES_TYPE1);
573 if (ret < 0)
574 goto sd_write_error;
576 aligned = (((int)outbuf & 3) == 0);
578 buf_end = (unsigned char *)outbuf + count * currcard->blocksize;
580 while (outbuf < (void*)buf_end)
582 if (aligned)
584 unsigned int* ptr = (unsigned int*)outbuf;
585 SDIWDATA = *ptr++;
586 SDIWDATA = *ptr++;
587 SDIWDATA = *ptr++;
588 SDIWDATA = *ptr;
590 else
592 int tmp_buf[4];
594 memcpy(tmp_buf, outbuf, 16);
596 SDIWDATA = tmp_buf[0];
597 SDIWDATA = tmp_buf[1];
598 SDIWDATA = tmp_buf[2];
599 SDIWDATA = tmp_buf[3];
601 outbuf += 16;
603 /* Wait for the FIFO to empty */
604 if (!sd_poll_status(SDISTATUS_FIFO_LOAD_REQ, 0x80000))
606 ret = -EC_FIFO_WR_EMPTY;
607 goto sd_write_error;
611 last_disk_activity = current_tick;
613 if (!sd_poll_status(SDISTATUS_MULTIBLOCK_END, 0x80000))
615 ret = -EC_FIFO_WR_DONE;
616 goto sd_write_error;
619 ret = sd_command(SD_STOP_TRANSMISSION, 0, NULL, SDICMD_RES_TYPE1);
620 if (ret < 0)
621 goto sd_write_error;
623 ret = sd_wait_for_state(SD_TRAN, EC_TRAN_WRITE_EXIT);
624 if (ret < 0)
625 goto sd_write_error;
627 while (1)
629 led(false);
630 sd_enable(false);
631 mutex_unlock(&sd_mtx);
633 return ret;
635 sd_write_error:
636 if (sd_status[card_no].retry < sd_status[card_no].retry_max
637 && ret != -EC_NOCARD)
639 sd_status[card_no].retry++;
640 currcard->initialized = 0;
641 goto sd_write_retry;
646 static void sd_thread(void) NORETURN_ATTR;
647 static void sd_thread(void)
649 struct queue_event ev;
650 bool idle_notified = false;
652 while (1)
654 queue_wait_w_tmo(&sd_queue, &ev, HZ);
656 switch ( ev.id )
658 #ifdef HAVE_HOTSWAP
659 case SYS_HOTSWAP_INSERTED:
660 case SYS_HOTSWAP_EXTRACTED:
661 fat_lock(); /* lock-out FAT activity first -
662 prevent deadlocking via disk_mount that
663 would cause a reverse-order attempt with
664 another thread */
665 mutex_lock(&sd_mtx); /* lock-out card activity - direct calls
666 into driver that bypass the fat cache */
668 /* We now have exclusive control of fat cache and ata */
670 /* Release "by force", ensure file descriptors aren't leaked and
671 any busy ones are invalid if mounting */
672 disk_unmount(sd_first_drive + CARD_NUM_SLOT);
674 /* Force card init for new card, re-init for re-inserted one or
675 * clear if the last attempt to init failed with an error. */
676 card_info[CARD_NUM_SLOT].initialized = 0;
677 sd_status[CARD_NUM_SLOT].retry = 0;
679 if (ev.id == SYS_HOTSWAP_INSERTED)
680 disk_mount(sd_first_drive + CARD_NUM_SLOT);
682 queue_broadcast(SYS_FS_CHANGED, 0);
684 /* Access is now safe */
685 mutex_unlock(&sd_mtx);
686 fat_unlock();
687 break;
688 #endif
689 case SYS_TIMEOUT:
690 if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
692 idle_notified = false;
694 else
696 /* never let a timer wrap confuse us */
697 next_yield = USEC_TIMER;
699 if (!idle_notified)
701 call_storage_idle_notifys(false);
702 idle_notified = true;
705 break;
707 case SYS_USB_CONNECTED:
708 usb_acknowledge(SYS_USB_CONNECTED_ACK);
709 /* Wait until the USB cable is extracted again */
710 usb_wait_for_disconnect(&sd_queue);
711 break;
716 void sd_enable(bool on)
718 if(on)
720 /* Enable controller & clock */
721 BCLKCTR |= DEV_SDMMC;
722 PCLK_SDMMC = PCK_EN | (CKSEL_PLL0<<24) | 7; /* 192/8 = 24MHz */
724 else
726 /* Disable controller & clock */
727 BCLKCTR &= ~DEV_SDMMC;
728 PCLK_SDMMC &= ~PCK_EN;
732 int sd_init(void)
734 int ret = 0;
736 if (!initialized)
737 mutex_init(&sd_mtx);
739 mutex_lock(&sd_mtx);
741 led(false);
743 if (!initialized)
745 initialized = true;
747 SWRESET |= DEV_SDMMC;
748 SWRESET &= ~DEV_SDMMC;
750 /* Configure dual-purpose pins for SD usage */
751 PORTCFG0 &= ~(3<<16);
752 PORTCFG0 |= (1<<16); /* SD_D0 & SD_D1 */
754 PORTCFG2 &= ~((3<<2) | (3<<0));
755 PORTCFG2 |= ((1<<2) | (1<<0)); /* SD_D2/D3/CK/CMD */
757 /* Configure card detection GPIO as input */
758 GPIOB_DIR &= ~(1<<26);
760 /* Configure card power(?) GPIO as output */
761 GPIOC_DIR |= (1<<24);
763 queue_init(&sd_queue, true);
764 create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
765 sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
766 IF_COP(, CPU));
768 sleep(HZ/10);
770 #ifdef HAVE_HOTSWAP
771 /* Configure interrupts for the card slot */
772 TMODE &= ~EXT0_IRQ_MASK; /* edge-triggered */
773 TMODEA |= EXT0_IRQ_MASK; /* trigger on both edges */
774 IEN |= EXT0_IRQ_MASK; /* enable the interrupt */
775 #endif
778 mutex_unlock(&sd_mtx);
780 return ret;
783 long sd_last_disk_activity(void)
785 return last_disk_activity;
788 tCardInfo *card_get_info_target(int card_no)
790 return &card_info[card_no];
793 #ifdef CONFIG_STORAGE_MULTI
795 int sd_num_drives(int first_drive)
797 /* Store which logical drive number(s) we have been assigned */
798 sd_first_drive = first_drive;
800 #if defined(HAVE_INTERNAL_SD) && defined(HAVE_HOTSWAP)
801 return 2;
802 #else
803 return 1;
804 #endif
807 void sd_sleepnow(void)
811 bool sd_disk_is_active(void)
813 return false;
816 int sd_soft_reset(void)
818 return 0;
821 int sd_spinup_time(void)
823 return 0;
826 #endif /* CONFIG_STORAGE_MULTI */