Add BPMP overclock, add hekate fixes, fix sprintf

This commit is contained in:
shchmue 2019-09-14 22:16:10 -06:00
parent 34890f0025
commit 82bea6be8f
39 changed files with 1130 additions and 544 deletions

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (C) 2018 CTCaer
* Copyright (C) 2018-2019 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -26,8 +26,6 @@
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...)
extern boot_cfg_t b_cfg;
static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
{
const u32 mask = (size < 32 ? 1 << size : 0) - 1;
@ -71,6 +69,7 @@ static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *re
if (_sdmmc_storage_check_result(*resp))
if (expected_state == 0x10 || R1_CURRENT_STATE(*resp) == expected_state)
return 1;
return 0;
}
@ -84,6 +83,7 @@ static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage)
{
sdmmc_cmd_t cmd;
sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
return sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0);
}
@ -93,7 +93,9 @@ static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf)
sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0))
return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2);
return 1;
}
@ -108,7 +110,9 @@ static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf)
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2);
return 1;
}
@ -146,8 +150,10 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
u32 tmp = 0;
sdmmc_stop_transmission(storage->sdmmc, &tmp);
_sdmmc_storage_get_status(storage, &tmp, 0);
return 0;
}
return 1;
}
@ -155,7 +161,9 @@ int sdmmc_storage_end(sdmmc_storage_t *storage)
{
if (!_sdmmc_storage_go_idle_state(storage))
return 0;
sdmmc_end(storage->sdmmc);
return 1;
}
@ -177,14 +185,16 @@ static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 nu
msleep(100);
} while (retries);
return 0;
out:;
DPRINTF("readwrite: %08X\n", blkcnt);
DPRINTF("readwrite: %08X\n", blkcnt);
sector += blkcnt;
num_sectors -= blkcnt;
bbuf += 512 * blkcnt;
}
return 1;
}
@ -235,14 +245,17 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
u32 cond = 0;
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
break;
if (cond & MMC_CARD_BUSY)
{
if (cond & 0x40000000)
storage->has_sector_access = 1;
return 1;
}
if (get_tmr_ms() > timeout)
break;
usleep(1000);
}
@ -372,6 +385,7 @@ static int _mmc_storage_switch_buswidth(sdmmc_storage_t *storage, u32 bus_width)
if (_sdmmc_storage_check_status(storage))
{
sdmmc_set_bus_width(storage->sdmmc, bus_width);
return 1;
}
@ -382,14 +396,19 @@ static int _mmc_storage_enable_HS(sdmmc_storage_t *storage, int check)
{
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS)))
return 0;
if (check && !_sdmmc_storage_check_status(storage))
return 0;
if (!sdmmc_setup_clock(storage->sdmmc, 2))
return 0;
DPRINTF("[MMC] switched to HS\n");
DPRINTF("[MMC] switched to HS\n");
storage->csd.busspeed = 52;
if (check || _sdmmc_storage_check_status(storage))
return 1;
return 0;
}
@ -397,12 +416,16 @@ static int _mmc_storage_enable_HS200(sdmmc_storage_t *storage)
{
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200)))
return 0;
if (!sdmmc_setup_clock(storage->sdmmc, 3))
return 0;
if (!sdmmc_config_tuning(storage->sdmmc, 3, MMC_SEND_TUNING_BLOCK_HS200))
return 0;
DPRINTF("[MMC] switched to HS200\n");
DPRINTF("[MMC] switched to HS200\n");
storage->csd.busspeed = 200;
return _sdmmc_storage_check_status(storage);
}
@ -410,17 +433,24 @@ static int _mmc_storage_enable_HS400(sdmmc_storage_t *storage)
{
if (!_mmc_storage_enable_HS200(storage))
return 0;
sdmmc_get_venclkctl(storage->sdmmc);
if (!_mmc_storage_enable_HS(storage, 0))
return 0;
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_DDR_BUS_WIDTH_8)))
return 0;
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400)))
return 0;
if (!sdmmc_setup_clock(storage->sdmmc, 4))
return 0;
DPRINTF("[MMC] switched to HS400\n");
DPRINTF("[MMC] switched to HS400\n");
storage->csd.busspeed = 400;
return _sdmmc_storage_check_status(storage);
}
@ -432,8 +462,7 @@ static int _mmc_storage_enable_highspeed(sdmmc_storage_t *storage, u32 card_type
goto out;
if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 &&
card_type & EXT_CSD_CARD_TYPE_HS400_1_8V &&
type == 4)
card_type & EXT_CSD_CARD_TYPE_HS400_1_8V && type == 4)
return _mmc_storage_enable_HS400(storage);
if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 ||
@ -445,6 +474,7 @@ static int _mmc_storage_enable_highspeed(sdmmc_storage_t *storage, u32 card_type
out:;
if (card_type & EXT_CSD_CARD_TYPE_HS_52)
return _mmc_storage_enable_HS(storage, 1);
return 1;
}
@ -452,6 +482,7 @@ static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage)
{
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_BKOPS_LEVEL_2)))
return 0;
return _sdmmc_storage_check_status(storage);
}
@ -463,42 +494,42 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
if (!sdmmc_init(sdmmc, id, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, 0, 0))
return 0;
DPRINTF("[MMC] after init\n");
DPRINTF("[MMC] after init\n");
usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor);
if (!_sdmmc_storage_go_idle_state(storage))
return 0;
DPRINTF("[MMC] went to idle state\n");
DPRINTF("[MMC] went to idle state\n");
if (!_mmc_storage_get_op_cond(storage, SDMMC_POWER_1_8))
return 0;
DPRINTF("[MMC] got op cond\n");
DPRINTF("[MMC] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
return 0;
DPRINTF("[MMC] got cid\n");
DPRINTF("[MMC] got cid\n");
if (!_mmc_storage_set_relative_addr(storage))
return 0;
DPRINTF("[MMC] set relative addr\n");
DPRINTF("[MMC] set relative addr\n");
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
return 0;
DPRINTF("[MMC] got csd\n");
DPRINTF("[MMC] got csd\n");
_mmc_storage_parse_csd(storage);
if (!sdmmc_setup_clock(storage->sdmmc, 1))
return 0;
DPRINTF("[MMC] after setup clock\n");
DPRINTF("[MMC] after setup clock\n");
if (!_sdmmc_storage_select_card(storage))
return 0;
DPRINTF("[MMC] card selected\n");
DPRINTF("[MMC] card selected\n");
if (!_sdmmc_storage_set_blocklen(storage, 512))
return 0;
DPRINTF("[MMC] set blocklen to 512\n");
DPRINTF("[MMC] set blocklen to 512\n");
u32 *csd = (u32 *)storage->raw_csd;
//Check system specification version, only version 4.0 and later support below features.
@ -510,7 +541,7 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
if (!_mmc_storage_switch_buswidth(storage, bus_width))
return 0;
DPRINTF("[MMC] switched buswidth\n");
DPRINTF("[MMC] switched buswidth\n");
u8 *ext_csd = (u8 *)malloc(512);
if (!_mmc_storage_get_ext_csd(storage, ext_csd))
@ -519,7 +550,7 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
return 0;
}
free(ext_csd);
DPRINTF("[MMC] got ext_csd\n");
DPRINTF("[MMC] got ext_csd\n");
_mmc_storage_parse_cid(storage); //This needs to be after csd and ext_csd
//gfx_hexdump(0, ext_csd, 512);
@ -529,16 +560,16 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2) && 0)
{
_mmc_storage_enable_bkops(storage);
DPRINTF("[MMC] BKOPS enabled\n");
DPRINTF("[MMC] BKOPS enabled\n");
}
else
{
DPRINTF("[MMC] BKOPS disabled\n");
DPRINTF("[MMC] BKOPS disabled\n");
}
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
return 0;
DPRINTF("[MMC] succesfully switched to highspeed mode\n");
DPRINTF("[MMC] succesfully switched to highspeed mode\n");
sdmmc_sd_clock_ctrl(storage->sdmmc, 1);
@ -549,8 +580,10 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
{
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_PART_CONFIG, partition)))
return 0;
if (!_sdmmc_storage_check_status(storage))
return 0;
storage->partition = partition;
return 1;
}
@ -564,6 +597,7 @@ static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_st
u32 tmp;
if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask))
return 0;
return sdmmc_execute_cmd(storage->sdmmc, cmd, req, blkcnt_out);
}
@ -571,6 +605,7 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp
{
if (!_sdmmc_storage_execute_cmd_type1(storage, MMC_APP_CMD, storage->rca << 16, 0, R1_STATE_TRAN))
return 0;
return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0);
}
@ -602,6 +637,7 @@ static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int
sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
if (!_sd_storage_execute_app_cmd(storage, 0x10, is_version_1 ? 0x400000 : 0, &cmdbuf, 0, 0))
return 0;
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
}
@ -629,7 +665,7 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, i
return 0;
storage->is_low_voltage = 1;
DPRINTF("-> switched to low voltage\n");
DPRINTF("-> switched to low voltage\n");
}
}
@ -783,17 +819,17 @@ void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u8 *buf)
switch (pwr)
{
case SD_SET_CURRENT_LIMIT_800:
DPRINTF("[SD] Power limit raised to 800mA\n");
DPRINTF("[SD] Power limit raised to 800mA\n");
break;
case SD_SET_CURRENT_LIMIT_600:
DPRINTF("[SD] Power limit raised to 600mA\n");
DPRINTF("[SD] Power limit raised to 600mA\n");
break;
case SD_SET_CURRENT_LIMIT_400:
DPRINTF("[SD] Power limit raised to 800mA\n");
DPRINTF("[SD] Power limit raised to 800mA\n");
break;
default:
case SD_SET_CURRENT_LIMIT_200:
DPRINTF("[SD] Power limit defaulted to 200mA\n");
DPRINTF("[SD] Power limit defaulted to 200mA\n");
break;
}
}
@ -802,10 +838,12 @@ int _sd_storage_enable_highspeed(sdmmc_storage_t *storage, u32 hs_type, u8 *buf)
{
if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, 0, hs_type))
return 0;
DPRINTF("[SD] SD supports switch to (U)HS check\n");
u32 type_out = buf[16] & 0xF;
if (type_out != hs_type)
return 0;
DPRINTF("[SD] SD supports selected (U)HS mode\n");
if ((((u16)buf[0] << 8) | buf[1]) < 0x320)
{
@ -834,31 +872,31 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
u32 hs_type = 0;
switch (type)
{
case 11:
case 11: // SDR104.
// Fall through if not supported.
if (buf[13] & SD_MODE_UHS_SDR104)
{
type = 11;
hs_type = UHS_SDR104_BUS_SPEED;
DPRINTF("[SD] Bus speed set to SDR104\n");
DPRINTF("[SD] Bus speed set to SDR104\n");
storage->csd.busspeed = 104;
break;
}
case 10:
case 10: // SDR50.
if (buf[13] & SD_MODE_UHS_SDR50)
{
type = 10;
hs_type = UHS_SDR50_BUS_SPEED;
DPRINTF("[SD] Bus speed set to SDR50\n");
DPRINTF("[SD] Bus speed set to SDR50\n");
storage->csd.busspeed = 50;
break;
}
case 8:
case 8: // SDR12.
if (!(buf[13] & SD_MODE_UHS_SDR12))
return 0;
type = 8;
hs_type = UHS_SDR12_BUS_SPEED;
DPRINTF("[SD] Bus speed set to SDR12\n");
DPRINTF("[SD] Bus speed set to SDR12\n");
storage->csd.busspeed = 12;
break;
default:
@ -868,10 +906,13 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
if (!_sd_storage_enable_highspeed(storage, hs_type, buf))
return 0;
DPRINTF("[SD] SD card accepted UHS\n");
if (!sdmmc_setup_clock(storage->sdmmc, type))
return 0;
DPRINTF("[SD] setup clock\n");
if (!sdmmc_config_tuning(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK))
return 0;
DPRINTF("[SD] config tuning\n");
return _sdmmc_storage_check_status(storage);
}
@ -885,8 +926,10 @@ int _sd_storage_enable_highspeed_high_volt(sdmmc_storage_t *storage, u8 *buf)
if (!_sd_storage_enable_highspeed(storage, 1, buf))
return 0;
if (!_sdmmc_storage_check_status(storage))
return 0;
return sdmmc_setup_clock(storage->sdmmc, 7);
}
@ -949,7 +992,7 @@ static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
if (!(storage->csd.cmdclass & CCC_APP_SPEC))
{
DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
return 0;
}
@ -1011,49 +1054,54 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
}
}
void sdmmc_storage_init_wait_sd()
{
u32 sd_poweroff_time = (u32)get_tmr_ms() - sd_power_cycle_time_start;
if (sd_poweroff_time < 100)
msleep(100 - sd_poweroff_time);
}
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32 bus_width, u32 type)
{
int is_version_1 = 0;
// Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
u32 sd_poweroff_time = (u32)get_tmr_ms() - b_cfg.sd_timeoff;
if (id == SDMMC_1 && (sd_poweroff_time < 100))
msleep(100 - sd_poweroff_time);
sdmmc_storage_init_wait_sd();
memset(storage, 0, sizeof(sdmmc_storage_t));
storage->sdmmc = sdmmc;
if (!sdmmc_init(sdmmc, id, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, 5, 0))
return 0;
DPRINTF("[SD] after init\n");
DPRINTF("[SD] after init\n");
usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor);
if (!_sdmmc_storage_go_idle_state(storage))
return 0;
DPRINTF("[SD] went to idle state\n");
DPRINTF("[SD] went to idle state\n");
is_version_1 = _sd_storage_send_if_cond(storage);
if (is_version_1 == 2)
return 0;
DPRINTF("[SD] after send if cond\n");
DPRINTF("[SD] after send if cond\n");
if (!_sd_storage_get_op_cond(storage, is_version_1, bus_width == SDMMC_BUS_WIDTH_4 && type == 11))
return 0;
DPRINTF("[SD] got op cond\n");
DPRINTF("[SD] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
return 0;
DPRINTF("[SD] got cid\n");
DPRINTF("[SD] got cid\n");
_sd_storage_parse_cid(storage);
if (!_sd_storage_get_rca(storage))
return 0;
DPRINTF("[SD] got rca (= %04X)\n", storage->rca);
DPRINTF("[SD] got rca (= %04X)\n", storage->rca);
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
return 0;
DPRINTF("[SD] got csd\n");
DPRINTF("[SD] got csd\n");
//Parse CSD.
_sd_storage_parse_csd(storage);
@ -1066,7 +1114,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
storage->sec_cnt = storage->csd.c_size << 10;
break;
default:
DPRINTF("[SD] Unknown CSD structure %d\n", storage->csd.structure);
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
break;
}
@ -1074,21 +1122,21 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
{
if (!sdmmc_setup_clock(storage->sdmmc, 6))
return 0;
DPRINTF("[SD] after setup clock\n");
DPRINTF("[SD] after setup clock\n");
}
if (!_sdmmc_storage_select_card(storage))
return 0;
DPRINTF("[SD] card selected\n");
DPRINTF("[SD] card selected\n");
if (!_sdmmc_storage_set_blocklen(storage, 512))
return 0;
DPRINTF("[SD] set blocklen to 512\n");
DPRINTF("[SD] set blocklen to 512\n");
u32 tmp = 0;
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN))
return 0;
DPRINTF("[SD] cleared card detect\n");
DPRINTF("[SD] cleared card detect\n");
u8 *buf = (u8 *)malloc(512);
if (!_sd_storage_get_scr(storage, buf))
@ -1098,7 +1146,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
}
//gfx_hexdump(0, storage->raw_scr, 8);
DPRINTF("[SD] got scr\n");
DPRINTF("[SD] got scr\n");
// Check if card supports a wider bus and if it's not SD Version 1.X
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF))
@ -1109,11 +1157,11 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
return 0;
}
sdmmc_set_bus_width(storage->sdmmc, SDMMC_BUS_WIDTH_4);
DPRINTF("[SD] switched to wide bus width\n");
DPRINTF("[SD] switched to wide bus width\n");
}
else
{
DPRINTF("[SD] SD does not support wide bus width\n");
DPRINTF("[SD] SD does not support wide bus width\n");
}
if (storage->is_low_voltage)
@ -1123,7 +1171,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
free(buf);
return 0;
}
DPRINTF("[SD] enabled highspeed (low voltage)\n");
DPRINTF("[SD] enabled UHS\n");
}
else if (type != 6 && (storage->scr.sda_vsn & 0xF) != 0)
{
@ -1132,7 +1180,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
free(buf);
return 0;
}
DPRINTF("[SD] enabled highspeed (high voltage)\n");
DPRINTF("[SD] enabled HS\n");
storage->csd.busspeed = 25;
}
@ -1141,7 +1189,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
// Parse additional card info from sd status.
if (_sd_storage_get_ssr(storage, buf))
{
DPRINTF("[SD] got sd status\n");
DPRINTF("[SD] got sd status\n");
}
free(buf);
@ -1186,13 +1234,13 @@ int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc)
if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, 14, 0))
return 0;
DPRINTF("[gc] after init\n");
DPRINTF("[gc] after init\n");
usleep(1000 + (10000 + sdmmc->divisor - 1) / sdmmc->divisor);
if (!sdmmc_config_tuning(storage->sdmmc, 14, MMC_SEND_TUNING_BLOCK_HS200))
return 0;
DPRINTF("[gc] after tuning\n");
DPRINTF("[gc] after tuning\n");
sdmmc_sd_clock_ctrl(sdmmc, 1);

View file

@ -21,6 +21,8 @@
#include "../utils/types.h"
#include "sdmmc_driver.h"
u32 sd_power_cycle_time_start;
typedef struct _mmc_cid
{
u32 manfid;
@ -47,7 +49,7 @@ typedef struct _mmc_csd
u32 read_blkbits;
u32 write_blkbits;
u32 capacity;
u8 write_protect;
u8 write_protect;
u16 busspeed;
} mmc_csd_t;
@ -107,6 +109,7 @@ int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, vo
int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32 bus_width, u32 type);
int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition);
void sdmmc_storage_init_wait_sd();
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32 bus_width, u32 type);
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);

View file

@ -21,6 +21,7 @@
#include "sdmmc.h"
#include "../gfx/gfx.h"
#include "../power/max7762x.h"
#include "../soc/bpmp.h"
#include "../soc/clock.h"
#include "../soc/gpio.h"
#include "../soc/pinmux.h"
@ -31,8 +32,6 @@
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...)
extern boot_cfg_t b_cfg;
/*! SCMMC controller base addresses. */
static const u32 _sdmmc_bases[4] = {
0x700B0000,
@ -123,6 +122,7 @@ static int _sdmmc_config_ven_ceata_clk(sdmmc_t *sdmmc, u32 id)
{
if (!sdmmc->venclkctl_set)
return 0;
tap_val = sdmmc->venclkctl_tap;
}
else
@ -201,7 +201,7 @@ out:;
int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
{
//Disable the SD clock if it was enabled, and reenable it later.
// Disable the SD clock if it was enabled, and reenable it later.
bool should_enable_sd_clock = false;
if (sdmmc->regs->clkcon & TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE)
{
@ -217,7 +217,7 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
case 1:
case 5:
case 6:
sdmmc->regs->hostctl &= 0xFB; //Should this be 0xFFFB (~4) ?
sdmmc->regs->hostctl &= 0xFB; // Should this be 0xFFFB (~4) ?
sdmmc->regs->hostctl2 &= SDHCI_CTRL_VDD_330;
break;
case 2:
@ -233,7 +233,7 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
break;
case 4:
//Non standard
// Non standard.
sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | HS400_BUS_SPEED;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
break;
@ -242,7 +242,7 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
break;
case 10:
//T210 Errata for SDR50, the host must be set to SDR104.
// T210 Errata for SDR50, the host must be set to SDR104.
sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | UHS_SDR104_BUS_SPEED;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
break;
@ -264,7 +264,7 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
divisor = div >> 8;
sdmmc->regs->clkcon = (sdmmc->regs->clkcon & 0x3F) | (div << 8) | (divisor << 6);
//Enable the SD clock again.
// Enable the SD clock again.
if (should_enable_sd_clock)
sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
@ -398,7 +398,7 @@ static int _sdmmc_wait_prnsts_type0(sdmmc_t *sdmmc, u32 wait_dat)
_sdmmc_get_clkcon(sdmmc);
u32 timeout = get_tmr_ms() + 2000;
while(sdmmc->regs->prnsts & 1) //CMD inhibit.
while(sdmmc->regs->prnsts & 1) // CMD inhibit.
if (get_tmr_ms() > timeout)
{
_sdmmc_reset(sdmmc);
@ -408,7 +408,7 @@ static int _sdmmc_wait_prnsts_type0(sdmmc_t *sdmmc, u32 wait_dat)
if (wait_dat)
{
timeout = get_tmr_ms() + 2000;
while (sdmmc->regs->prnsts & 2) //DAT inhibit.
while (sdmmc->regs->prnsts & 2) // DAT inhibit.
if (get_tmr_ms() > timeout)
{
_sdmmc_reset(sdmmc);
@ -424,7 +424,7 @@ static int _sdmmc_wait_prnsts_type1(sdmmc_t *sdmmc)
_sdmmc_get_clkcon(sdmmc);
u32 timeout = get_tmr_ms() + 2000;
while (!(sdmmc->regs->prnsts & 0x100000)) //DAT0 line level.
while (!(sdmmc->regs->prnsts & 0x100000)) // DAT0 line level.
if (get_tmr_ms() > timeout)
{
_sdmmc_reset(sdmmc);
@ -511,13 +511,17 @@ static int _sdmmc_config_tuning_once(sdmmc_t *sdmmc, u32 cmd)
return 0;
_sdmmc_setup_read_small_block(sdmmc);
sdmmc->regs->norintstsen |= TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY;
sdmmc->regs->norintsts = sdmmc->regs->norintsts;
sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
_sdmmc_parse_cmd_48(sdmmc, cmd);
_sdmmc_get_clkcon(sdmmc);
usleep(1);
_sdmmc_reset(sdmmc);
sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
_sdmmc_get_clkcon(sdmmc);
@ -533,10 +537,13 @@ static int _sdmmc_config_tuning_once(sdmmc_t *sdmmc, u32 cmd)
return 1;
}
}
_sdmmc_reset(sdmmc);
sdmmc->regs->norintstsen &= 0xFFDF;
_sdmmc_get_clkcon(sdmmc);
usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor);
return 0;
}
@ -563,8 +570,8 @@ int sdmmc_config_tuning(sdmmc_t *sdmmc, u32 type, u32 cmd)
return 0;
}
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | flag;
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | 0x40;
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | flag; // Tries.
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | 0x40; // Multiplier.
sdmmc->regs->ventunctl0 |= 0x20000;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_EXEC_TUNING;
@ -577,6 +584,7 @@ int sdmmc_config_tuning(sdmmc_t *sdmmc, u32 type, u32 cmd)
if (sdmmc->regs->hostctl2 & SDHCI_CTRL_TUNED_CLK)
return 1;
return 0;
}
@ -666,7 +674,7 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power)
{
if (get_tmr_ms() > timeout)
{
//In case autocalibration fails, we load suggested standard values.
// In case autocalibration fails, we load suggested standard values.
_sdmmc_pad_config_fallback(sdmmc, power);
sdmmc->regs->autocalcfg &= 0xDFFFFFFF;
break;
@ -703,7 +711,7 @@ static int _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask)
if (pout)
*pout = norintsts;
//Check for error interrupt.
// Check for error interrupt.
if (norintsts & TEGRA_MMC_NORINTSTS_ERR_INTERRUPT)
{
sdmmc->regs->errintsts = errintsts;
@ -746,11 +754,14 @@ static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp)
return 0;
_sdmmc_enable_interrupts(sdmmc);
cmd.cmd = MMC_STOP_TRANSMISSION;
cmd.arg = 0;
cmd.rsp_type = SDMMC_RSP_TYPE_1;
cmd.check_busy = 1;
_sdmmc_parse_cmdbuf(sdmmc, &cmd, false);
int res = _sdmmc_wait_request(sdmmc);
_sdmmc_mask_interrupts(sdmmc);
@ -758,6 +769,7 @@ static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp)
return 0;
_sdmmc_cache_rsp(sdmmc, rsp, 4, SDMMC_RSP_TYPE_1);
return _sdmmc_wait_prnsts_type1(sdmmc);
}
@ -777,6 +789,7 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp)
int res = _sdmmc_stop_transmission_inner(sdmmc, rsp);
usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor);
if (should_disable_sd_clock)
sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
@ -793,7 +806,7 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
blkcnt = 0xFFFF;
u32 admaaddr = (u32)req->buf;
//Check alignment.
// Check alignment.
if (admaaddr << 29)
return 0;
@ -817,7 +830,7 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
trnmode |= TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ;
if (req->is_auto_cmd12)
trnmode = (trnmode & 0xFFF3) | TEGRA_MMC_TRNMOD_AUTO_CMD12;
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY);
sdmmc->regs->trnmod = trnmode;
return 1;
@ -836,15 +849,18 @@ static int _sdmmc_update_dma(sdmmc_t *sdmmc)
while (1)
{
u16 intr = 0;
res = _sdmmc_check_mask_interrupt(sdmmc, &intr,
res = _sdmmc_check_mask_interrupt(sdmmc, &intr,
TEGRA_MMC_NORINTSTS_XFER_COMPLETE | TEGRA_MMC_NORINTSTS_DMA_INTERRUPT);
if (res < 0)
break;
if (intr & TEGRA_MMC_NORINTSTS_XFER_COMPLETE)
return 1; //Transfer complete.
{
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY);
return 1; // Transfer complete.
}
if (intr & TEGRA_MMC_NORINTSTS_DMA_INTERRUPT)
{
//Update DMA.
// Update DMA.
sdmmc->regs->admaaddr = sdmmc->dma_addr_next;
sdmmc->regs->admaaddr_hi = 0;
sdmmc->dma_addr_next += 0x80000;
@ -906,6 +922,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
{
if (blkcnt_out)
*blkcnt_out = blkcnt;
if (req->is_auto_cmd12)
sdmmc->rsp3 = sdmmc->regs->rspreg3;
}
@ -919,12 +936,14 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
static int _sdmmc_config_sdmmc1()
{
//Configure SD card detect.
// Configure SD card detect.
PINMUX_AUX(PINMUX_AUX_GPIO_PZ1) = PINMUX_INPUT_ENABLE | PINMUX_PULL_UP | 1; //GPIO control, pull up.
APB_MISC(APB_MISC_GP_VGPIO_GPIO_MUX_SEL) = 0;
gpio_config(GPIO_PORT_Z, GPIO_PIN_1, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_Z, GPIO_PIN_1, GPIO_OUTPUT_DISABLE);
usleep(100);
// Check if SD card is inserted.
if(!!gpio_read(GPIO_PORT_Z, GPIO_PIN_1))
return 0;
@ -937,8 +956,8 @@ static int _sdmmc_config_sdmmc1()
* APB_MISC_GP_SDMMCx_CLK_LPBK_CONTROL = SDMMCx_CLK_PAD_E_LPBK for CLK
*/
//Configure SDMMC1 pinmux.
APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1;
// Configure SDMMC1 pinmux.
APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1; // Enable deep loopback for SDMMC1 CLK pad.
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED;
PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP;
@ -946,12 +965,12 @@ static int _sdmmc_config_sdmmc1()
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP;
//Make sure the SDMMC1 controller is powered.
// Make sure the SDMMC1 controller is powered.
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(1 << 12);
//Assume 3.3V SD card voltage.
// Assume 3.3V SD card voltage.
PMC(APBDEV_PMC_PWR_DET_VAL) |= (1 << 12);
//Set enable SD card power.
// Set enable SD card power.
PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN | 1; //GPIO control, pull down.
gpio_config(GPIO_PORT_E, GPIO_PIN_4, GPIO_MODE_GPIO);
gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_HIGH);
@ -959,13 +978,13 @@ static int _sdmmc_config_sdmmc1()
usleep(1000);
//Enable SD card power.
// Enable SD card power.
max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000);
max77620_regulator_enable(REGULATOR_LDO2, 1);
usleep(1000);
//For good measure.
// For good measure.
APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = 0x10000000;
usleep(1000);
@ -1009,18 +1028,23 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int n
sdmmc->regs->sdmemcmppadctl = (sdmmc->regs->sdmemcmppadctl & 0xF) | 7;
if (!_sdmmc_autocal_config_offset(sdmmc, power))
return 0;
_sdmmc_autocal_execute(sdmmc, power);
if (_sdmmc_enable_internal_clock(sdmmc))
{
sdmmc_set_bus_width(sdmmc, bus_width);
_sdmmc_set_voltage(sdmmc, power);
if (sdmmc_setup_clock(sdmmc, type))
{
sdmmc_sd_clock_ctrl(sdmmc, no_sd);
_sdmmc_sd_clock_enable(sdmmc);
_sdmmc_get_clkcon(sdmmc);
return 1;
}
return 0;
}
return 0;
@ -1039,8 +1063,8 @@ void sdmmc_end(sdmmc_t *sdmmc)
{
gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE);
max77620_regulator_enable(REGULATOR_LDO2, 0);
b_cfg.sd_timeoff = get_tmr_ms(); // Some sandisc U1 cards need 100ms for a power cycle.
msleep(1); // To power cycle, min 1ms without power is needed.
sd_power_cycle_time_start = get_tmr_ms(); // Some sandisc U1 cards need 100ms for a power cycle.
usleep(1000); // To power cycle, min 1ms without power is needed.
}
_sdmmc_get_clkcon(sdmmc);
@ -1062,7 +1086,7 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b
if (!sdmmc->sd_clock_enabled)
return 0;
//Recalibrate periodically for SDMMC1.
// Recalibrate periodically for SDMMC1.
if (sdmmc->id == SDMMC_1 && sdmmc->no_sd)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_voltage(sdmmc));
@ -1077,6 +1101,7 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b
int res = _sdmmc_execute_cmd_inner(sdmmc, cmd, req, blkcnt_out);
usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor);
if (should_disable_sd_clock)
sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
@ -1093,6 +1118,14 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
_sdmmc_get_clkcon(sdmmc);
// Enable schmitt trigger for better duty cycle and low jitter clock.
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT2) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) |= PINMUX_SCHMT;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) |= PINMUX_SCHMT;
max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000);
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(1 << 12);
@ -1106,7 +1139,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
{
sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
_sdmmc_get_clkcon(sdmmc);
msleep(1);
usleep(1000);
if ((sdmmc->regs->prnsts & 0xF00000) == 0xF00000)
return 1;
}