Exemplo n.º 1
0
static int sd_init_card(void)
{
    imx233_ssp_start(SD_SSP);
    imx233_ssp_softreset(SD_SSP);
    imx233_ssp_set_mode(SD_SSP, HW_SSP_CTRL1__SSP_MODE__SD_MMC);
    /* SSPCLK @ 96MHz
     * gives bitrate of 96000 / 240 / 1 = 400kHz */
    imx233_ssp_set_timings(SD_SSP, 240, 0, 0xffff);
    imx233_ssp_set_bus_width(SD_SSP, 1);
    imx233_ssp_set_block_size(SD_SSP, 9);

    card_info.rca = 0;
    bool is_v2 = false;
    uint32_t resp;
    /* go to idle state */
    int ret = imx233_ssp_sd_mmc_transfer(SD_SSP, SD_GO_IDLE_STATE, 0, SSP_NO_RESP, NULL, 0, false, false, NULL);
    if(ret != 0)
        return -1;
    /* CMD8 Check for v2 sd card.  Must be sent before using ACMD41
       Non v2 cards will not respond to this command*/
    ret = imx233_ssp_sd_mmc_transfer(SD_SSP, SD_SEND_IF_COND, 0x1AA, SSP_SHORT_RESP, NULL, 0, false, false, &resp);
    if(ret == 0 && (resp & 0xFFF) == 0x1AA)
        is_v2 = true;
    
    return -10;
}
Exemplo n.º 2
0
int mmc_init(void)
{
    mutex_init(&mmc_mutex);
    
    imx233_ssp_start(MMC_SSP);
    imx233_ssp_softreset(MMC_SSP);
    imx233_ssp_set_mode(MMC_SSP, HW_SSP_CTRL1__SSP_MODE__SD_MMC);
    #ifdef SANSA_FUZEPLUS
    /** Sansa Fuze+ has an internal eMMC 8-bit wide flash, power gate is pin PWM3
     * and power up time is 20ms */
    imx233_set_pin_function(1, 29, PINCTRL_FUNCTION_GPIO);
    imx233_enable_gpio_output(1, 29, true);
    imx233_set_gpio_output(1, 29, false);
    sleep(HZ / 5);

    imx233_ssp_setup_ssp2_sd_mmc_pins(true, 8, PINCTRL_DRIVE_8mA);
    #endif
    /* SSPCLK @ 96MHz
     * gives bitrate of 96000 / 240 / 1 = 400kHz */
    imx233_ssp_set_timings(MMC_SSP, 240, 0, 0xffff);
    imx233_ssp_sd_mmc_power_up_sequence(MMC_SSP);
    imx233_ssp_set_bus_width(MMC_SSP, 1);
    imx233_ssp_set_block_size(MMC_SSP, 9);
    /* go to idle state */
    int ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 0, 0, SSP_NO_RESP, NULL, 0, false, false, NULL);
    if(ret != 0)
        return -1;
    /* send op cond until the card respond with busy bit set; it must complete within 1sec */
    unsigned timeout = current_tick + HZ;
    do
    {
        uint32_t ocr;
        ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 1, 0x40ff8000, SSP_SHORT_RESP, NULL, 0, false, false, &ocr);
        if(ret == 0 && ocr & (1 << 31))
            break;
    }while(!TIME_AFTER(current_tick, timeout));

    if(ret != 0)
        return -2;
    /* get CID */
    uint32_t cid[4];
    ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 2, 0, SSP_LONG_RESP, NULL, 0, false, false, cid);
    if(ret != 0)
        return -3;
    /* Set RCA */
    uint32_t status;
    ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 3, MMC_RCA << 16, SSP_SHORT_RESP, NULL, 0, false, false, &status);
    if(ret != 0)
        return -4;
    /* Select card */
    ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 7, MMC_RCA << 16, SSP_SHORT_RESP, NULL, 0, false, false, &status);
    if(ret != 0)
        return -5;
    /* Check TRAN state */
    ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 13, MMC_RCA << 16, SSP_SHORT_RESP, NULL, 0, false, false, &status);
    if(ret != 0)
        return -6;
    if(((status >> 9) & 0xf) != 4)
        return -7;
    /* Switch to 8-bit bus */
    ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 6, 0x3b70200, SSP_SHORT_RESP, NULL, 0, true, false, &status);
    if(ret != 0)
        return -8;
    /* switch error ? */
    if(status & 0x80)
        return -9;
    imx233_ssp_set_bus_width(MMC_SSP, 8);
    /* Switch to high speed mode */
    ret = imx233_ssp_sd_mmc_transfer(MMC_SSP, 6, 0x3b90100, SSP_SHORT_RESP, NULL, 0, true, false, &status);
    if(ret != 0)
        return -10;
    /* switch error ?*/
    if(status & 0x80)
        return -11;
    /* SSPCLK @ 96MHz
     * gives bitrate of 96 / 2 / 1 = 48MHz */
    imx233_ssp_set_timings(MMC_SSP, 2, 0, 0xffff);

    #ifdef SANSA_FUZEPLUS
    /**
     * The Fuze+ uses a strange layout: is has a first MBR at sector 0 with four entries:
     * 1) Actual user partition
     * 2) Sigmatel boot partition
     * 3)4) Other (certificate related ?) partitions
     * The partition 1) has type 1 but it's actually a type 5 (logical partition) with
     * a second partition table with usually one entry which is the FAT32 one.
     * The first table uses 512-byte sector size and the second one usually uses
     * 2048-byte logical sector size.
     *
     * We restrict mmc window to the user partition */
    uint8_t mbr[512];
    mmc_window_start = 0;
    mmc_window_end = INT_MAX;
    ret = mmc_read_sectors(IF_MD2(0,) 0, 1, mbr);
    if(ret != 0)
        return -100;
    if(mbr[510] != 0x55 || mbr[511] != 0xAA)
        return -101; /* invalid MBR */
    /* sanity check that the first partition is greater than 2Gib */
    uint8_t *ent = &mbr[446];
    mmc_window_start = ent[8] | ent[9] << 8 | ent[10] << 16 | ent[11] << 24;
    mmc_window_end = (ent[12] | ent[13] << 8 | ent[14] << 16 | ent[15] << 24) +
        mmc_window_start;
    if(ent[4] == 0x53)
        return -102; /* sigmatel partition */
    if((mmc_window_end - mmc_window_start) < 4 * 1024 * 1024)
        return -103; /* partition too small */
    #endif

    return 0;
}