Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

By: a guest on Dec 9th, 2011  |  syntax: None  |  size: 12.68 KB  |  views: 40  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /***************************************************************************
  2.  *             __________               __   ___.
  3.  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
  4.  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
  5.  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
  6.  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
  7.  *                     \/            \/     \/    \/            \/
  8.  * $Id$
  9.  *
  10.  * Copyright (C) 2011 by Amaury Pouly
  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 "config.h"
  22. #include "system.h"
  23. #include "sd.h"
  24. #include "sdmmc.h"
  25. #include "ssp-imx233.h"
  26. #include "pinctrl-imx233.h"
  27. #include "button-target.h"
  28. #include "fat.h"
  29. #include "disk.h"
  30. #include "usb.h"
  31. #include "debug.h"
  32.  
  33. /**
  34.  * This code assumes a single SD card slot
  35.  */
  36.  
  37. #ifdef SANSA_FUZEPLUS
  38. #define SD_SSP      1
  39. #else
  40. #error You need to configure the ssp to use
  41. #endif
  42.  
  43. static tCardInfo card_info;
  44. static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
  45. static struct mutex sd_mutex;
  46. static const char sd_thread_name[] = "sd";
  47. static struct event_queue sd_queue;
  48. static int sd_first_drive;
  49. static int last_disk_activity;
  50.  
  51. static void sd_detect_callback(int ssp)
  52. {
  53.     (void)ssp;
  54.  
  55.     /* This is called only if the state was stable for 300ms - check state
  56.      * and post appropriate event. */
  57.     if(imx233_ssp_sdmmc_detect(SD_SSP))
  58.         queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
  59.     else
  60.         queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
  61.     imx233_ssp_sdmmc_setup_detect(SD_SSP, true, sd_detect_callback);
  62. }
  63.  
  64. void sd_power(bool on)
  65. {
  66.     #ifdef SANSA_FUZEPLUS
  67.     /* The Fuze+ uses pin B0P8 for whatever reason, power ? */
  68.     imx233_set_pin_function(0, 8, PINCTRL_FUNCTION_GPIO);
  69.     imx233_enable_gpio_output(0, 8, true);
  70.     imx233_set_gpio_output(0, 8, !on);
  71.     /* disable pull ups when not needed to save power */
  72.     imx233_ssp_setup_ssp1_sd_mmc_pins(on, 4, PINCTRL_DRIVE_4mA, false);
  73.     /* It also setups pin B1P30, unknown purpose */
  74.     imx233_set_pin_function(1, 30, PINCTRL_FUNCTION_GPIO);
  75.     imx233_enable_gpio_output(1, 30, false);
  76.     #endif
  77. }
  78.  
  79. void sd_enable(bool on)
  80. {
  81.     static bool sd_enable = false;
  82.     if(sd_enable == on)
  83.         return;
  84.  
  85.     sd_enable = on;
  86. }
  87.  
  88. #define MCI_NO_RESP     0
  89. #define MCI_RESP        (1<<0)
  90. #define MCI_LONG_RESP   (1<<1)
  91. #define MCI_ACMD        (1<<2)
  92. #define MCI_NOCRC       (1<<3)
  93.  
  94. static bool send_cmd(uint8_t cmd, uint32_t arg, uint32_t flags, uint32_t *resp)
  95. {
  96.     if((flags & MCI_ACMD) && !send_cmd(SD_APP_CMD, card_info.rca, MCI_RESP, resp))
  97.         return false;
  98.  
  99.     enum imx233_ssp_resp_t resp_type = (flags & MCI_LONG_RESP) ? SSP_LONG_RESP :
  100.         (flags & MCI_RESP) ? SSP_SHORT_RESP : SSP_NO_RESP;
  101.     enum imx233_ssp_error_t ret = imx233_ssp_sd_mmc_transfer(SD_SSP, cmd, arg,
  102.         resp_type, NULL, 0, false, false, resp);
  103.     return ret == SSP_SUCCESS;
  104. }
  105.  
  106. static int sd_wait_for_tran_state(void)
  107. {
  108.     unsigned long response;
  109.     unsigned int timeout = current_tick + 5*HZ;
  110.     int cmd_retry = 10;
  111.    
  112.     while (1)
  113.     {
  114.         while(!send_cmd(SD_SEND_STATUS, card_info.rca, SSP_SHORT_RESP, &response) && cmd_retry > 0)
  115.             cmd_retry--;
  116.  
  117.         if(cmd_retry <= 0)
  118.             return -1;
  119.  
  120.         if(((response >> 9) & 0xf) == SD_TRAN)
  121.             return 0;
  122.  
  123.         if(TIME_AFTER(current_tick, timeout))
  124.             return -10 * ((response >> 9) & 0xf);
  125.  
  126.         last_disk_activity = current_tick;
  127.     }
  128. }
  129.  
  130. static int sd_init_card(void)
  131. {
  132.     imx233_ssp_start(SD_SSP);
  133.     imx233_ssp_softreset(SD_SSP);
  134.     imx233_ssp_set_mode(SD_SSP, HW_SSP_CTRL1__SSP_MODE__SD_MMC);
  135.     /* SSPCLK @ 96MHz
  136.      * gives bitrate of 96000 / 240 / 1 = 400kHz */
  137.     imx233_ssp_set_timings(SD_SSP, 240, 0, 0xffff);
  138.    
  139.     imx233_ssp_sd_mmc_power_up_sequence(SD_SSP);
  140.     imx233_ssp_set_bus_width(SD_SSP, 1);
  141.     imx233_ssp_set_block_size(SD_SSP, 9);
  142.  
  143.     card_info.rca = 0;
  144.     bool sd_v2 = false;
  145.     uint32_t resp;
  146.     long init_timeout;
  147.     /* go to idle state */
  148.     if(!send_cmd(SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL))
  149.         return -1;
  150.     /* CMD8 Check for v2 sd card.  Must be sent before using ACMD41
  151.        Non v2 cards will not respond to this command */
  152.     if(send_cmd(SD_SEND_IF_COND, 0x1AA, MCI_RESP, &resp))
  153.         if((resp & 0xFFF) == 0x1AA)
  154.             sd_v2 = true;
  155.     /* timeout for initialization is 1sec, from SD Specification 2.00 */
  156.     init_timeout = current_tick + HZ;
  157.     do
  158.     {
  159.         /* this timeout is the only valid error for this loop*/
  160.         if(TIME_AFTER(current_tick, init_timeout))
  161.             return -2;
  162.  
  163.         /* ACMD41 For v2 cards set HCS bit[30] & send host voltage range to all */
  164.         if(!send_cmd(SD_APP_OP_COND, (0x00FF8000 | (sd_v2 ? 1<<30 : 0)),
  165.                 MCI_ACMD|MCI_NOCRC|MCI_RESP, &card_info.ocr))
  166.             return -100;
  167.     } while(!(card_info.ocr & (1<<31)));
  168.  
  169.     /* CMD2 send CID */
  170.     if(!send_cmd(SD_ALL_SEND_CID, 0, MCI_RESP|MCI_LONG_RESP, card_info.cid))
  171.         return -3;
  172.  
  173.     /* CMD3 send RCA */
  174.     if(!send_cmd(SD_SEND_RELATIVE_ADDR, 0, MCI_RESP, &card_info.rca))
  175.         return -4;
  176.  
  177.     /* Try to switch V2 cards to HS timings, non HS seem to ignore this */
  178.     if(sd_v2)
  179.     {
  180.         /*  CMD7 w/rca: Select card to put it in TRAN state */
  181.         if(!send_cmd(SD_SELECT_CARD, card_info.rca, MCI_RESP, NULL))
  182.             return -5;
  183.  
  184.         if(sd_wait_for_tran_state())
  185.             return -6;
  186.  
  187.         /* CMD6 */
  188.         if(!send_cmd(SD_SWITCH_FUNC, 0x80fffff1, MCI_NO_RESP, NULL))
  189.             return -7;
  190.         sleep(HZ/10);
  191.  
  192.         /*  go back to STBY state so we can read csd */
  193.         /*  CMD7 w/rca=0:  Deselect card to put it in STBY state */
  194.         if(!send_cmd(SD_DESELECT_CARD, 0, MCI_NO_RESP, NULL))
  195.             return -8;
  196.     }
  197.  
  198.     /* CMD9 send CSD */
  199.     if(!send_cmd(SD_SEND_CSD, card_info.rca, MCI_RESP|MCI_LONG_RESP, card_info.csd))
  200.         return -9;
  201.  
  202.     sd_parse_csd(&card_info);
  203.  
  204.     /* SSPCLK @ 96MHz
  205.      * gives bitrate of 96 / 4 / 1 = 24MHz */
  206.     imx233_ssp_set_timings(SD_SSP, 4, 0, 0xffff);
  207.  
  208.     /* CMD7 w/rca: Select card to put it in TRAN state */
  209.     if(!send_cmd(SD_SELECT_CARD, card_info.rca, MCI_RESP, &resp))
  210.         return -12;
  211.     if(sd_wait_for_tran_state() < 0)
  212.         return -13;
  213.  
  214.     /* ACMD6: set bus width to 4-bit */
  215.     if(!send_cmd(SD_SET_BUS_WIDTH, 2, MCI_RESP|MCI_ACMD, &resp))
  216.         return -15;
  217.     /* ACMD42: disconnect the pull-up resistor on CD/DAT3 */
  218.     if(!send_cmd(SD_SET_CLR_CARD_DETECT, 0, MCI_RESP|MCI_ACMD, &resp))
  219.         return -17;
  220.  
  221.     /* Switch to 4-bit */
  222.     imx233_ssp_set_bus_width(SD_SSP, 4);
  223.  
  224.     card_info.initialized = 1;
  225.    
  226.     return 0;
  227. }
  228.  
  229. static void sd_thread(void) NORETURN_ATTR;
  230. static void sd_thread(void)
  231. {
  232.     struct queue_event ev;
  233.  
  234.     while (1)
  235.     {
  236.         queue_wait_w_tmo(&sd_queue, &ev, HZ);
  237.  
  238.         switch(ev.id)
  239.         {
  240.         case SYS_HOTSWAP_INSERTED:
  241.         case SYS_HOTSWAP_EXTRACTED:
  242.         {
  243.             int microsd_init = 1;
  244.             fat_lock();          /* lock-out FAT activity first -
  245.                                     prevent deadlocking via disk_mount that
  246.                                     would cause a reverse-order attempt with
  247.                                     another thread */
  248.             mutex_lock(&sd_mutex); /* lock-out card activity - direct calls
  249.                                     into driver that bypass the fat cache */
  250.  
  251.             /* We now have exclusive control of fat cache and sd */
  252.  
  253.             disk_unmount(sd_first_drive);     /* release "by force", ensure file
  254.                                     descriptors aren't leaked and any busy
  255.                                     ones are invalid if mounting */
  256.             /* Force card init for new card, re-init for re-inserted one or
  257.              * clear if the last attempt to init failed with an error. */
  258.             card_info.initialized = 0;
  259.  
  260.             if(ev.id == SYS_HOTSWAP_INSERTED)
  261.             {
  262.                 sd_power(true);
  263.                 sd_enable(true);
  264.                 microsd_init = sd_init_card();
  265.                 _logf("sd_init_card: %d", microsd_init);
  266.                 if(microsd_init == 0)
  267.                     microsd_init = disk_mount(sd_first_drive); /* 0 if fail */
  268.                 else
  269.                     DEBUGF("sd_init_card failed: %d", ret);
  270.             }
  271.             else
  272.                 sd_power(false);
  273.             panicf("ok");
  274.             /*
  275.              * Mount succeeded, or this was an EXTRACTED event,
  276.              * in both cases notify the system about the changed filesystems
  277.              */
  278.             if(microsd_init)
  279.                 queue_broadcast(SYS_FS_CHANGED, 0);
  280.  
  281.             sd_enable(false);
  282.             /* Access is now safe */
  283.             mutex_unlock(&sd_mutex);
  284.             fat_unlock();
  285.             break;
  286.         }
  287.         case SYS_TIMEOUT:
  288.             if(!TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
  289.                 sd_enable(false);
  290.             break;
  291.         case SYS_USB_CONNECTED:
  292.             usb_acknowledge(SYS_USB_CONNECTED_ACK);
  293.             /* Wait until the USB cable is extracted again */
  294.             usb_wait_for_disconnect(&sd_queue);
  295.             break;
  296.         }
  297.     }
  298. }
  299.  
  300. int sd_init(void)
  301. {
  302.     mutex_init(&sd_mutex);
  303.     queue_init(&sd_queue, true);
  304.     create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
  305.             sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));
  306.  
  307.     imx233_ssp_sdmmc_setup_detect(SD_SSP, true, sd_detect_callback);
  308.  
  309.     if(imx233_ssp_sdmmc_detect(SD_SSP))
  310.         queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
  311.    
  312.     return 0;
  313. }
  314.  
  315. static int transfer_sectors(IF_MD2(int drive,) unsigned long start, int count, void *buf, bool read)
  316. {
  317.     IF_MD((void) drive);
  318.     int ret = 0;
  319.     uint32_t resp;
  320.  
  321.     last_disk_activity = current_tick;
  322.  
  323.     mutex_lock(&sd_mutex);
  324.     mutex_unlock(&sd_mutex);
  325.     return -1;
  326.  
  327.     mutex_lock(&sd_mutex);
  328.     sd_enable(true);
  329.  
  330.     ret = -1;
  331.     goto Lend;
  332.    
  333.     if(card_info.initialized <= 0)
  334.     {
  335.         ret = sd_init_card();
  336.         if(!(card_info.initialized))
  337.             goto Lend;
  338.     }
  339.    
  340.     if(!send_cmd(SD_SELECT_CARD, card_info.rca, SSP_NO_RESP, NULL))
  341.     {
  342.         _logf("sd: can't select card");
  343.         ret = -20;
  344.         goto Lend;
  345.     }
  346.     ret = sd_wait_for_tran_state();
  347.     if(ret < 0)
  348.     {
  349.         _logf("sd: wait for tran: %d", ret);
  350.         goto Ldeselect;
  351.     }
  352.    
  353.     while(count != 0)
  354.     {
  355.         int this_count = MIN(count, IMX233_MAX_SSP_XFER_SIZE / 512);
  356.         ret = imx233_ssp_sd_mmc_transfer(SD_SSP, read ? SD_READ_MULTIPLE_BLOCK : SD_WRITE_MULTIPLE_BLOCK,
  357.             start, SSP_SHORT_RESP, buf, this_count, false, read, &resp);
  358.         if(ret != SSP_SUCCESS)
  359.         {
  360.             _logf("sd: read: %d", ret);
  361.             break;
  362.         }
  363.         if(!send_cmd(SD_STOP_TRANSMISSION, 0, SSP_SHORT_RESP, &resp))
  364.         {
  365.             _logf("sd: stop: %d", ret);
  366.             break;
  367.         }
  368.         count -= this_count;
  369.         start += this_count;
  370.         buf += this_count * 512;
  371.     }
  372.  
  373.     Ldeselect:
  374.     /* CMD lines are separate, not common, so we need to actively deselect */
  375.     /*  CMD7 w/rca =0 : deselects card & puts it in STBY state */
  376.     if(!send_cmd(SD_DESELECT_CARD, 0, SSP_NO_RESP, NULL))
  377.         ret = -23;
  378.  
  379.     Lend:
  380.     mutex_unlock(&sd_mutex);
  381.     return ret;
  382. }
  383.  
  384. int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count,
  385.                      void* buf)
  386. {
  387.     return transfer_sectors(IF_MD2(drive,) start, count, buf, true);
  388. }
  389.  
  390. int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
  391.                      const void* buf)
  392. {
  393.     //return transfer_sectors(IF_MD2(drive,) start, count, (void *)buf, false);
  394.     return -1;
  395. }
  396.  
  397. tCardInfo *card_get_info_target(int card_no)
  398. {
  399.     (void)card_no;
  400.     return &card_info;
  401. }
  402.  
  403. int sd_num_drives(int first_drive)
  404. {
  405.     sd_first_drive = first_drive;
  406.     return 1;
  407. }
  408.  
  409. bool sd_present(IF_MD(int drive))
  410. {
  411.     IF_MD((void) drive);
  412.     return imx233_ssp_sdmmc_detect(SD_SSP);
  413. }
  414.  
  415. bool sd_removable(IF_MD(int drive))
  416. {
  417.     IF_MD((void) drive);
  418.     return true;
  419. }
  420.  
  421. long sd_last_disk_activity(void)
  422. {
  423.     return last_disk_activity;
  424. }
  425.  
  426.  
  427.  
clone this paste RAW Paste Data