Remove card_enable_monitoring() and use a mutex instead. The card_enable_monitoring...
[kugel-rb.git] / firmware / target / arm / tcc780x / sd-tcc780x.c
blob88ccf187f01b1061629d38480b01e999cec4e187
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 "sdmmc.h"
26 #include "storage.h"
27 #include "led.h"
28 #include "thread.h"
29 #include "disk.h"
30 #include "fat.h"
31 #include "ata_idle_notify.h"
32 #include "usb.h"
34 #if defined(HAVE_INTERNAL_SD) && defined(HAVE_HOTSWAP)
35 #define CARD_NUM_INTERNAL 0
36 #define CARD_NUM_SLOT 1
37 #elif !defined(HAVE_INTERNAL_SD) && defined(HAVE_HOTSWAP)
38 #define CARD_NUM_SLOT 0
39 #endif
41 #define EC_OK 0
42 #define EC_FAILED 1
43 #define EC_NOCARD 2
44 #define EC_WAIT_STATE_FAILED 3
45 #define EC_POWER_UP 4
46 #define EC_FIFO_WR_EMPTY 5
47 #define EC_FIFO_WR_DONE 6
48 #define EC_TRAN_READ_ENTRY 7
49 #define EC_TRAN_READ_EXIT 8
50 #define EC_TRAN_WRITE_ENTRY 9
51 #define EC_TRAN_WRITE_EXIT 10
52 #define EC_COMMAND 11
53 #define EC_WRITE_PROTECT 12
55 /* for compatibility */
56 static long last_disk_activity = -1;
58 /** static, private data **/
59 static bool initialized = false;
61 static long next_yield = 0;
62 #define MIN_YIELD_PERIOD 1000
64 static tCardInfo card_info[NUM_DRIVES];
65 static tCardInfo *currcard = NULL; /* current active card */
67 struct sd_card_status
69 int retry;
70 int retry_max;
73 static struct sd_card_status sd_status[NUM_DRIVES] =
75 #ifdef HAVE_INTERNAL_SD
76 { 0, 1 },
77 #endif
78 #ifdef HAVE_HOTSWAP
79 { 0, 10 }
80 #endif
83 /* Shoot for around 75% usage */
84 static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
85 static const char sd_thread_name[] = "sd";
86 static struct mutex sd_mtx SHAREDBSS_ATTR;
87 static struct event_queue sd_queue;
89 static int sd_first_drive = 0;
92 static bool sd_poll_status(unsigned int trigger, long timeout)
94 long t = USEC_TIMER;
96 while ((SDISTATUS & trigger) != trigger)
98 long time = USEC_TIMER;
100 if (TIME_AFTER(time, next_yield))
102 long ty = USEC_TIMER;
103 yield();
104 timeout += USEC_TIMER - ty;
105 next_yield = ty + MIN_YIELD_PERIOD;
108 if (TIME_AFTER(time, t + timeout))
109 return false;
112 return true;
115 static int sd_command(unsigned int cmd, unsigned int arg,
116 unsigned long* response, unsigned int resp_type)
118 int sdi_cmd = cmd;
120 sdi_cmd |= (127<<12) | (1<<11); /* max wait time | enable */
122 if (resp_type)
124 /* response type & response required flag */
125 sdi_cmd |= (resp_type<<7) | (1<<6);
128 if (cmd == SD_READ_SINGLE_BLOCK ||
129 cmd == SD_READ_MULTIPLE_BLOCK ||
130 cmd == SD_WRITE_BLOCK ||
131 cmd == SD_WRITE_MULTIPLE_BLOCK)
133 sdi_cmd |= (1<<10); /* request data transfer */
136 if (!sd_poll_status(SDISTATUS_CMD_PATH_RDY, 100000))
137 return -EC_COMMAND;
139 SDIARGU = arg;
140 SDICMD = sdi_cmd;
142 udelay(10);
144 if (response == NULL)
145 return 0;
147 if (!sd_poll_status(SDISTATUS_RESP_RCVD, 100000))
148 return -EC_COMMAND;
150 if (resp_type == SDICMD_RES_TYPE2)
152 response[0] = SDIRSPARGU0;
153 response[1] = SDIRSPARGU1;
154 response[2] = SDIRSPARGU2;
155 response[3] = SDIRSPARGU3;
157 else
159 response[0] = SDIRSPARGU0;
162 return 0;
165 static int sd_wait_for_state(unsigned int state, int id)
167 unsigned long response = 0;
168 unsigned int timeout = 0x80000;
170 long start_time = USEC_TIMER;
172 while (1)
174 int ret = sd_command
175 (SD_SEND_STATUS, currcard->rca, &response, SDICMD_RES_TYPE1);
177 long us;
179 if (ret < 0)
180 return ret*100 - id;
182 if (((response >> 9) & 0xf) == state)
184 return 0;
187 if (TIME_AFTER(USEC_TIMER, start_time + timeout))
188 return -EC_WAIT_STATE_FAILED*100 - id;
190 us = USEC_TIMER;
191 if (TIME_AFTER(us, next_yield))
193 yield();
194 timeout += USEC_TIMER - us;
195 next_yield = us + MIN_YIELD_PERIOD;
200 static void sd_card_mux(int card_no)
202 /* We only support the default card */
203 (void)card_no;
206 #ifdef HAVE_HOTSWAP
208 static inline bool card_detect_target(void)
210 #ifdef HAVE_HOTSWAP
211 return (GPIOB & (1<<26)) == 0; /* low active */
212 #else
213 return false;
214 #endif
217 static int sd1_oneshot_callback(struct timeout *tmo)
219 (void)tmo;
221 /* This is called only if the state was stable for 300ms - check state
222 * and post appropriate event. */
223 if (card_detect_target())
224 queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
225 else
226 queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
228 return 0;
231 void EXT0(void)
233 static struct timeout sd1_oneshot;
235 timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0);
238 bool sd_removable(IF_MD_NONVOID(int card_no))
240 #ifndef HAVE_MULTIDRIVE
241 const int card_no = 0;
242 #endif
243 return (card_no == CARD_NUM_SLOT);
246 bool sd_present(IF_MD_NONVOID(int card_no))
248 #ifdef HAVE_MULTIDRIVE
249 (void)card_no;
250 #endif
251 return card_detect_target();
254 #else
256 bool sd_removable(IF_MD_NONVOID(int card_no))
258 #ifndef HAVE_MULTIDRIVE
259 const int card_no = 0;
260 #endif
261 (void)card_no;
263 return false;
266 #endif /* HAVE_HOTSWAP */
269 static void sd_init_device(int card_no)
271 int ret;
272 unsigned long response;
274 /* Initialise card data as blank */
275 memset(currcard, 0, sizeof(*currcard));
277 /* Switch card mux to card to initialize */
278 sd_card_mux(card_no);
280 #ifdef HAVE_HOTSWAP
281 /* Check card is inserted */
282 if (card_no == CARD_NUM_SLOT)
284 if (GPIOB & (1<<26))
286 ret = -EC_NOCARD;
287 goto card_init_error;
290 /* Card will not power up unless this is done */
291 GPIOC_CLEAR = (1<<24);
293 #endif
295 ret = sd_command(SD_GO_IDLE_STATE, 0, NULL, SDICMD_RES_TYPE1);
297 if (ret < 0)
298 goto card_init_error;
300 /* Use slow clock during identification (24MHz / 60 = 400kHz) */
301 SDICLK = (1<<12) | 59;
303 sd_command(SD_SEND_IF_COND, 0x1aa, &response, SDICMD_RES_TYPE3);
305 if (!sd_poll_status(SDISTATUS_CMD_PATH_RDY, 100000))
306 goto card_init_error;
308 currcard->ocr = 0;
310 long start_tick = current_tick;
312 while ((currcard->ocr & (1<<31)) == 0
313 && TIME_BEFORE(current_tick, start_tick + HZ))
315 udelay(100);
316 sd_command(SD_APP_CMD, 0, NULL, SDICMD_RES_TYPE1);
318 int arg = 0x100000 | ((response == 0x1aa) ? (1<<30):0);
319 sd_command(SD_APP_OP_COND, arg, &currcard->ocr, SDICMD_RES_TYPE3);
322 if ((currcard->ocr & (1<<31)) == 0)
324 ret = -EC_POWER_UP;
325 goto card_init_error;
328 ret = sd_command
329 (SD_ALL_SEND_CID, 0, currcard->cid, SDICMD_RES_TYPE2);
331 if (ret < 0)
332 goto card_init_error;
334 ret = sd_command
335 (SD_SEND_RELATIVE_ADDR, 0, &currcard->rca, SDICMD_RES_TYPE1);
337 if (ret < 0)
338 goto card_init_error;
340 ret = sd_command
341 (SD_SEND_CSD, currcard->rca, currcard->csd, SDICMD_RES_TYPE2);
343 if (ret < 0)
344 goto card_init_error;
346 sd_parse_csd(currcard);
348 ret = sd_command
349 (SD_SELECT_CARD, currcard->rca, NULL, SDICMD_RES_TYPE1);
351 if (ret < 0)
352 goto card_init_error;
354 ret = sd_command
355 (SD_APP_CMD, currcard->rca, NULL, SDICMD_RES_TYPE1);
357 if (ret < 0)
358 goto card_init_error;
360 ret = sd_command /* 4 bit */
361 (SD_SET_BUS_WIDTH, currcard->rca | 2, NULL, SDICMD_RES_TYPE1);
363 if (ret < 0)
364 goto card_init_error;
366 ret = sd_command
367 (SD_SET_BLOCKLEN, currcard->blocksize, NULL, SDICMD_RES_TYPE1);
369 if (ret < 0)
370 goto card_init_error;
372 currcard->initialized = 1;
373 return;
375 /* Card failed to initialize so disable it */
376 card_init_error:
377 currcard->initialized = ret;
378 return;
381 /* lock must already be acquired */
382 static void sd_select_device(int card_no)
384 currcard = &card_info[card_no];
386 if (currcard->initialized > 0)
388 /* This card is already initialized - switch to it */
389 sd_card_mux(card_no);
390 return;
393 if (currcard->initialized == 0)
395 /* Card needs (re)init */
396 sd_init_device(card_no);
400 int sd_read_sectors(IF_MD2(int card_no,) unsigned long start, int incount,
401 void* inbuf)
403 #ifndef HAVE_MULTIDRIVE
404 const int card_no = 0;
405 #endif
407 int ret = 0;
408 bool aligned;
409 unsigned char* buf_end;
411 mutex_lock(&sd_mtx);
412 sd_enable(true);
413 led(true);
415 sd_read_retry:
416 if ((card_no == CARD_NUM_SLOT) && !card_detect_target())
418 /* no external sd-card inserted */
419 ret = -EC_NOCARD;
420 goto sd_read_error;
423 sd_select_device(card_no);
425 if (currcard->initialized < 0)
427 ret = currcard->initialized;
428 goto sd_read_error;
431 last_disk_activity = current_tick;
433 ret = sd_wait_for_state(SD_TRAN, EC_TRAN_READ_ENTRY);
435 if (ret < 0)
436 goto sd_read_error;
438 /* Use full SD clock for data transfer (PCK_SDMMC) */
439 SDICLK = (1<<13) | (1<<12); /* bypass divider | enable */
441 /* Block count | FIFO count | Block size (2^9) | 4-bit bus */
442 SDIDCTRL = (incount << 13) | (4<<8) | (9<<4) | (1<<2);
443 SDIDCTRL |= (1<<12); /* nReset */
445 SDIDCTRL2 = (1<<2); /* multi block, read */
447 if (currcard->ocr & (1<<30))
448 ret = sd_command(SD_READ_MULTIPLE_BLOCK, start, NULL, SDICMD_RES_TYPE1);
449 else
450 ret = sd_command(SD_READ_MULTIPLE_BLOCK, start * 512, NULL, SDICMD_RES_TYPE1);
452 if (ret < 0)
453 goto sd_read_error;
455 aligned = (((int)inbuf & 3) == 0);
457 buf_end = (unsigned char *)inbuf + incount * currcard->blocksize;
459 while (inbuf < (void*)buf_end)
461 if (!sd_poll_status(SDISTATUS_FIFO_FETCH_REQ, 100000))
462 goto sd_read_error;
464 if (aligned)
466 unsigned int* ptr = (unsigned int*)inbuf;
467 *ptr++ = SDIRDATA;
468 *ptr++ = SDIRDATA;
469 *ptr++ = SDIRDATA;
470 *ptr = SDIRDATA;
473 else
475 int tmp_buf[4];
477 tmp_buf[0] = SDIRDATA;
478 tmp_buf[1] = SDIRDATA;
479 tmp_buf[2] = SDIRDATA;
480 tmp_buf[3] = SDIRDATA;
482 memcpy(inbuf, tmp_buf, 16);
484 inbuf += 16;
487 ret = sd_command(SD_STOP_TRANSMISSION, 0, NULL, SDICMD_RES_TYPE1);
488 if (ret < 0)
489 goto sd_read_error;
491 ret = sd_wait_for_state(SD_TRAN, EC_TRAN_READ_EXIT);
492 if (ret < 0)
493 goto sd_read_error;
495 while (1)
497 led(false);
498 sd_enable(false);
499 mutex_unlock(&sd_mtx);
501 return ret;
503 sd_read_error:
504 if (sd_status[card_no].retry < sd_status[card_no].retry_max
505 && ret != -EC_NOCARD)
507 sd_status[card_no].retry++;
508 currcard->initialized = 0;
509 goto sd_read_retry;
514 int sd_write_sectors(IF_MD2(int card_no,) unsigned long start, int count,
515 const void* outbuf)
517 /* Write support is not finished yet */
518 /* TODO: The standard suggests using ACMD23 prior to writing multiple blocks
519 to improve performance */
520 #ifndef HAVE_MULTIDRIVE
521 const int card_no = 0;
522 #endif
523 int ret;
524 const unsigned char *buf_end;
525 bool aligned;
527 if ((card_no == CARD_NUM_SLOT) && (GPIOA & 0x10))
529 /* write protect tab set */
530 return -EC_WRITE_PROTECT;
533 mutex_lock(&sd_mtx);
534 sd_enable(true);
535 led(true);
537 sd_write_retry:
538 if ((card_no == CARD_NUM_SLOT) && !card_detect_target())
540 /* no external sd-card inserted */
541 ret = -EC_NOCARD;
542 goto sd_write_error;
545 sd_select_device(card_no);
547 if (currcard->initialized < 0)
549 ret = currcard->initialized;
550 goto sd_write_error;
553 ret = sd_wait_for_state(SD_TRAN, EC_TRAN_WRITE_ENTRY);
555 if (ret < 0)
556 goto sd_write_error;
558 /* Use full SD clock for data transfer (PCK_SDMMC) */
559 SDICLK = (1<<13) | (1<<12); /* bypass divider | enable */
561 /* Block count | FIFO count | Block size (2^9) | 4-bit bus */
562 SDIDCTRL = (count<<13) | (4<<8) | (9<<4) | (1<<2);
563 SDIDCTRL |= (1<<12); /* nReset */
565 SDIDCTRL2 = (1<<2) | (1<<1); /* multi block, write */
567 if (currcard->ocr & (1<<30))
568 ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start, NULL, SDICMD_RES_TYPE1);
569 else
570 ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start * 512, NULL, SDICMD_RES_TYPE1);
572 if (ret < 0)
573 goto sd_write_error;
575 aligned = (((int)outbuf & 3) == 0);
577 buf_end = (unsigned char *)outbuf + count * currcard->blocksize;
579 while (outbuf < (void*)buf_end)
581 if (aligned)
583 unsigned int* ptr = (unsigned int*)outbuf;
584 SDIWDATA = *ptr++;
585 SDIWDATA = *ptr++;
586 SDIWDATA = *ptr++;
587 SDIWDATA = *ptr;
589 else
591 int tmp_buf[4];
593 memcpy(tmp_buf, outbuf, 16);
595 SDIWDATA = tmp_buf[0];
596 SDIWDATA = tmp_buf[1];
597 SDIWDATA = tmp_buf[2];
598 SDIWDATA = tmp_buf[3];
600 outbuf += 16;
602 /* Wait for the FIFO to empty */
603 if (!sd_poll_status(SDISTATUS_FIFO_LOAD_REQ, 0x80000))
605 ret = -EC_FIFO_WR_EMPTY;
606 goto sd_write_error;
610 last_disk_activity = current_tick;
612 if (!sd_poll_status(SDISTATUS_MULTIBLOCK_END, 0x80000))
614 ret = -EC_FIFO_WR_DONE;
615 goto sd_write_error;
618 ret = sd_command(SD_STOP_TRANSMISSION, 0, NULL, SDICMD_RES_TYPE1);
619 if (ret < 0)
620 goto sd_write_error;
622 ret = sd_wait_for_state(SD_TRAN, EC_TRAN_WRITE_EXIT);
623 if (ret < 0)
624 goto sd_write_error;
626 while (1)
628 led(false);
629 sd_enable(false);
630 mutex_unlock(&sd_mtx);
632 return ret;
634 sd_write_error:
635 if (sd_status[card_no].retry < sd_status[card_no].retry_max
636 && ret != -EC_NOCARD)
638 sd_status[card_no].retry++;
639 currcard->initialized = 0;
640 goto sd_write_retry;
645 static void sd_thread(void) __attribute__((noreturn));
646 static void sd_thread(void)
648 struct queue_event ev;
649 bool idle_notified = false;
651 while (1)
653 queue_wait_w_tmo(&sd_queue, &ev, HZ);
655 switch ( ev.id )
657 #ifdef HAVE_HOTSWAP
658 case SYS_HOTSWAP_INSERTED:
659 case SYS_HOTSWAP_EXTRACTED:
660 fat_lock(); /* lock-out FAT activity first -
661 prevent deadlocking via disk_mount that
662 would cause a reverse-order attempt with
663 another thread */
664 mutex_lock(&sd_mtx); /* lock-out card activity - direct calls
665 into driver that bypass the fat cache */
667 /* We now have exclusive control of fat cache and ata */
669 /* Release "by force", ensure file descriptors aren't leaked and
670 any busy ones are invalid if mounting */
671 disk_unmount(sd_first_drive + CARD_NUM_SLOT);
673 /* Force card init for new card, re-init for re-inserted one or
674 * clear if the last attempt to init failed with an error. */
675 card_info[CARD_NUM_SLOT].initialized = 0;
676 sd_status[CARD_NUM_SLOT].retry = 0;
678 if (ev.id == SYS_HOTSWAP_INSERTED)
679 disk_mount(sd_first_drive + CARD_NUM_SLOT);
681 queue_broadcast(SYS_FS_CHANGED, 0);
683 /* Access is now safe */
684 mutex_unlock(&sd_mtx);
685 fat_unlock();
686 break;
687 #endif
688 case SYS_TIMEOUT:
689 if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
691 idle_notified = false;
693 else
695 /* never let a timer wrap confuse us */
696 next_yield = USEC_TIMER;
698 if (!idle_notified)
700 call_storage_idle_notifys(false);
701 idle_notified = true;
704 break;
706 case SYS_USB_CONNECTED:
707 usb_acknowledge(SYS_USB_CONNECTED_ACK);
708 /* Wait until the USB cable is extracted again */
709 usb_wait_for_disconnect(&sd_queue);
710 break;
712 case SYS_USB_DISCONNECTED:
713 usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
714 break;
719 void sd_enable(bool on)
721 if(on)
723 /* Enable controller & clock */
724 BCLKCTR |= DEV_SDMMC;
725 PCLK_SDMMC = PCK_EN | (CKSEL_PLL0<<24) | 7; /* 192/8 = 24MHz */
727 else
729 /* Disable controller & clock */
730 BCLKCTR &= ~DEV_SDMMC;
731 PCLK_SDMMC &= ~PCK_EN;
735 int sd_init(void)
737 int ret = 0;
739 if (!initialized)
740 mutex_init(&sd_mtx);
742 mutex_lock(&sd_mtx);
744 led(false);
746 if (!initialized)
748 initialized = true;
750 SWRESET |= DEV_SDMMC;
751 SWRESET &= ~DEV_SDMMC;
753 /* Configure dual-purpose pins for SD usage */
754 PORTCFG0 &= ~(3<<16);
755 PORTCFG0 |= (1<<16); /* SD_D0 & SD_D1 */
757 PORTCFG2 &= ~((3<<2) | (3<<0));
758 PORTCFG2 |= ((1<<2) | (1<<0)); /* SD_D2/D3/CK/CMD */
760 /* Configure card detection GPIO as input */
761 GPIOB_DIR &= ~(1<<26);
763 /* Configure card power(?) GPIO as output */
764 GPIOC_DIR |= (1<<24);
766 queue_init(&sd_queue, true);
767 create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
768 sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
769 IF_COP(, CPU));
771 sleep(HZ/10);
773 #ifdef HAVE_HOTSWAP
774 /* Configure interrupts for the card slot */
775 TMODE &= ~EXT0_IRQ_MASK; /* edge-triggered */
776 TMODEA |= EXT0_IRQ_MASK; /* trigger on both edges */
777 IEN |= EXT0_IRQ_MASK; /* enable the interrupt */
778 #endif
781 mutex_unlock(&sd_mtx);
783 return ret;
786 long sd_last_disk_activity(void)
788 return last_disk_activity;
791 tCardInfo *card_get_info_target(int card_no)
793 return &card_info[card_no];
796 #ifdef CONFIG_STORAGE_MULTI
798 int sd_num_drives(int first_drive)
800 /* Store which logical drive number(s) we have been assigned */
801 sd_first_drive = first_drive;
803 #if defined(HAVE_INTERNAL_SD) && defined(HAVE_HOTSWAP)
804 return 2;
805 #else
806 return 1;
807 #endif
810 void sd_sleepnow(void)
814 bool sd_disk_is_active(void)
816 return false;
819 int sd_soft_reset(void)
821 return 0;
824 int sd_spinup_time(void)
826 return 0;
829 #endif /* CONFIG_STORAGE_MULTI */