Update to hekate bdk 5.5.6

This commit is contained in:
shchmue 2021-05-12 15:38:34 -06:00
parent 93909f149e
commit a7712b173c
95 changed files with 2720 additions and 1684 deletions

View file

@ -84,6 +84,11 @@
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
#define MMC_VENDOR_60_CMD 60 /* Vendor Defined */
#define MMC_VENDOR_61_CMD 61 /* Vendor Defined */
#define MMC_VENDOR_62_CMD 62 /* Vendor Defined */
#define MMC_VENDOR_63_CMD 63 /* Vendor Defined */
/* class 11 */
#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */
#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */
@ -142,7 +147,10 @@ c : clear by read
#define R1_SWITCH_ERROR (1 << 7) /* sx, c */
#define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */
#define R1_APP_CMD (1 << 5) /* sr, c */
#define R1_SKIP_STATE_CHECK (1 << 4) /* Custom state to skip expected state check */
#define R1_AKE_SEQ_ERROR (1 << 3)
/* R1_CURRENT_STATE 12:9 */
#define R1_STATE_IDLE 0
#define R1_STATE_READY 1
#define R1_STATE_IDENT 2
@ -179,7 +187,10 @@ c : clear by read
/*
* OCR bits are mostly in host.h
*/
#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
#define MMC_CARD_VDD_18 (1 << 7) /* Card VDD voltage 1.8 */
#define MMC_CARD_VDD_27_34 (0x7F << 15) /* Card VDD voltage 2.7 ~ 3.4 */
#define MMC_CARD_CCS (1 << 30) /* Card Capacity status bit */
#define MMC_CARD_BUSY (1 << 31) /* Card Power up status bit */
/*
* Card Command Classes (CCC)
@ -241,6 +252,7 @@ c : clear by read
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
#define EXT_CSD_MAX_ENH_SIZE_MULT 157 /* RO, 3 bytes */
#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */
#define EXT_CSD_HPI_MGMT 161 /* R/W */
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2018-2021 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,
@ -45,12 +45,15 @@ extern FATFS sd_fs;
void sd_error_count_increment(u8 type);
u16 *sd_get_error_count();
bool sd_get_card_removed();
bool sd_get_card_initialized();
bool sd_get_card_mounted();
u32 sd_get_mode();
int sd_init_retry(bool power_cycle);
bool sd_initialize(bool power_cycle);
bool sd_mount();
void sd_unmount();
void sd_end();
bool sd_is_gpt();
void *sd_file_read(const char *path, u32 *fsize);
int sd_save_to_file(void *buf, u32 size, const char *filename);

View file

@ -1,7 +1,7 @@
/*
* Ramdisk driver for Tegra X1
*
* Copyright (c) 2019 CTCaer
* Copyright (c) 2019-2021 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,
@ -19,23 +19,40 @@
#include <string.h>
#include "ramdisk.h"
#include <libs/fatfs/diskio.h>
#include <mem/heap.h>
#include <utils/types.h>
#include <memory_map.h>
int ram_disk_init(FATFS *ram_fs)
static u32 disk_size = 0;
int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size)
{
int res;
u8 *buf = malloc(0x400000);
int res = 0;
disk_size = ramdisk_size;
f_mount(NULL, "ram:", 1); // Unmount ramdisk.
// If ramdisk is not raw, format it.
if (ram_fs)
{
u8 *buf = malloc(0x400000);
res = f_mkfs("ram:", FM_EXFAT, RAMDISK_CLUSTER_SZ, buf, 0x400000); // Format as exFAT w/ 32KB cluster.
if (!res)
res = f_mount(ram_fs, "ram:", 1); // Mount ramdisk.
// Set ramdisk size.
ramdisk_size >>= 9;
disk_set_info(DRIVE_RAM, SET_SECTOR_COUNT, &ramdisk_size);
free(buf);
// Unmount ramdisk.
f_mount(NULL, "ram:", 1);
// Format as exFAT w/ 32KB cluster with no MBR.
res = f_mkfs("ram:", FM_EXFAT | FM_SFD, RAMDISK_CLUSTER_SZ, buf, 0x400000);
// Mount ramdisk.
if (!res)
res = f_mount(ram_fs, "ram:", 1);
free(buf);
}
return res;
}
@ -45,7 +62,7 @@ int ram_disk_read(u32 sector, u32 sector_count, void *buf)
u32 sector_off = RAM_DISK_ADDR + (sector << 9);
u32 bytes_count = sector_count << 9;
if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ)
if ((sector_off - RAM_DISK_ADDR) > disk_size)
return 1;
memcpy(buf, (void *)sector_off, bytes_count);
@ -58,7 +75,7 @@ int ram_disk_write(u32 sector, u32 sector_count, const void *buf)
u32 sector_off = RAM_DISK_ADDR + (sector << 9);
u32 bytes_count = sector_count << 9;
if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ)
if ((sector_off - RAM_DISK_ADDR) > disk_size)
return 1;
memcpy((void *)sector_off, buf, bytes_count);

View file

@ -1,7 +1,7 @@
/*
* Ramdisk driver for Tegra X1
*
* Copyright (c) 2019 CTCaer
* Copyright (c) 2019-2021 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,
@ -23,7 +23,7 @@
#define RAMDISK_CLUSTER_SZ 32768
int ram_disk_init(FATFS *ram_fs);
int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size);
int ram_disk_read(u32 sector, u32 sector_count, void *buf);
int ram_disk_write(u32 sector, u32 sector_count, const void *buf);

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved.
* Copyright (c) 2018 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,58 +14,79 @@
/* SD commands type argument response */
/* class 0 */
/* This is basically the same command as for MMC with some quirks. */
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
/* class 10 */
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
/* class 5 */
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
/* Application commands */
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
#define SD_APP_SD_STATUS 13 /* adtc R1 */
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
#define SD_APP_SET_CLR_CARD_DETECT 42
#define SD_APP_SEND_SCR 51 /* adtc R1 */
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
#define SD_APP_SD_STATUS 13 /* adtc R1 */
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
#define SD_APP_SET_CLR_CARD_DETECT 42 /* adtc R1 */
#define SD_APP_SEND_SCR 51 /* adtc R1 */
/* Application secure commands */
#define SD_APP_SECURE_READ_MULTI_BLOCK 18 /* adtc R1 */
#define SD_APP_SECURE_WRITE_MULTI_BLOCK 25 /* adtc R1 */
#define SD_APP_SECURE_WRITE_MKB 26 /* adtc R1 */
#define SD_APP_SECURE_ERASE 38 /* adtc R1b */
#define SD_APP_GET_MKB 43 /* adtc [31:0] See below R1 */
#define SD_APP_GET_MID 44 /* adtc R1 */
#define SD_APP_SET_CER_RN1 45 /* adtc R1 */
#define SD_APP_GET_CER_RN2 46 /* adtc R1 */
#define SD_APP_SET_CER_RES2 47 /* adtc R1 */
#define SD_APP_GET_CER_RES1 48 /* adtc R1 */
#define SD_APP_CHANGE_SECURE_AREA 49 /* adtc R1b */
/* OCR bit definitions */
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */
#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */
#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
#define SD_OCR_XPC (1 << 28) /* SDXC power control */
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */
#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
#define SD_OCR_BUSY (1 << 31) /* Card Power up Status */
/*
* SD_SWITCH argument format:
*
* [31] Check (0) or switch (1)
* [30:24] Reserved (0)
* [23:20] Function group 6
* [19:16] Function group 5
* [15:12] Function group 4
* [11:8] Function group 3
* [7:4] Function group 2
* [3:0] Function group 1
*/
* SD_SWITCH argument format:
*
* [31] Check (0) or switch (1)
* [30:24] Reserved (0)
* [23:20] Function group 6
* [19:16] Function group 5
* [15:12] Function group 4
* [11:8] Function group 3
* [7:4] Function group 2
* [3:0] Function group 1
*/
/*
* SD_SEND_IF_COND argument format:
*
* [31:12] Reserved (0)
* [11:8] Host Voltage Supply Flags
* [7:0] Check Pattern (0xAA)
*/
* SD_SEND_IF_COND argument format:
*
* [31:12] Reserved (0)
* [11:8] Host Voltage Supply Flags
* [7:0] Check Pattern (0xAA)
*/
/*
* SCR field definitions
*/
* SD_APP_GET_MKB argument format:
*
* [31:24] Number of blocks to read (512 block size)
* [23:16] MKB ID
* [15:0] Block offset
*/
/*
* SCR field definitions
*/
#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */
#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */
#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */
@ -73,14 +94,14 @@
#define SD_SCR_BUS_WIDTH_4 (1<<2)
/*
* SD bus widths
*/
* SD bus widths
*/
#define SD_BUS_WIDTH_1 0
#define SD_BUS_WIDTH_4 2
/*
* SD bus speeds
*/
* SD bus speeds
*/
#define UHS_SDR12_BUS_SPEED 0
#define HIGH_SPEED_BUS_SPEED 1
#define UHS_SDR25_BUS_SPEED 1
@ -110,19 +131,19 @@
#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800)
/*
* SD_SWITCH mode
*/
* SD_SWITCH mode
*/
#define SD_SWITCH_CHECK 0
#define SD_SWITCH_SET 1
/*
* SD_SWITCH function groups
*/
* SD_SWITCH function groups
*/
#define SD_SWITCH_GRP_ACCESS 0
/*
* SD_SWITCH access modes
*/
* SD_SWITCH access modes
*/
#define SD_SWITCH_ACCESS_DEF 0
#define SD_SWITCH_ACCESS_HS 1

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 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,
@ -42,10 +42,10 @@ static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
}
/*
* Common functions for SD and MMC.
*/
* Common functions for SD and MMC.
*/
static int _sdmmc_storage_check_result(u32 res)
static int _sdmmc_storage_check_card_status(u32 res)
{
//Error mask:
//TODO: R1_SWITCH_ERROR can be skipped for certain card types.
@ -66,15 +66,15 @@ static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *re
{
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, cmd, arg, SDMMC_RSP_TYPE_1, check_busy);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
sdmmc_get_rsp(storage->sdmmc, resp, 4, SDMMC_RSP_TYPE_1);
if (mask)
*resp &= ~mask;
if (_sdmmc_storage_check_result(*resp))
if (expected_state == 0x10 || R1_CURRENT_STATE(*resp) == expected_state)
if (_sdmmc_storage_check_card_status(*resp))
if (expected_state == R1_SKIP_STATE_CHECK || R1_CURRENT_STATE(*resp) == expected_state)
return 1;
return 0;
@ -88,37 +88,37 @@ static int _sdmmc_storage_execute_cmd_type1(sdmmc_storage_t *storage, u32 cmd, u
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);
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
return sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0);
return sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL);
}
static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf)
static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage)
{
sdmmc_cmd_t cmd;
sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0))
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2);
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_cid, 16, SDMMC_RSP_TYPE_2);
return 1;
}
static int _sdmmc_storage_select_card(sdmmc_storage_t *storage)
{
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, 0x10);
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, R1_SKIP_STATE_CHECK);
}
static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf)
static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage)
{
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2);
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_csd, 16, SDMMC_RSP_TYPE_2);
return 1;
}
@ -145,6 +145,10 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
sdmmc_cmd_t cmdbuf;
sdmmc_req_t reqbuf;
// If SDSC convert block address to byte address.
if (!storage->has_sector_access)
sector <<= 9;
sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0);
reqbuf.buf = buf;
@ -152,7 +156,7 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
reqbuf.blksize = 512;
reqbuf.is_write = is_write;
reqbuf.is_multi_block = 1;
reqbuf.is_auto_cmd12 = 1;
reqbuf.is_auto_stop_trn = 1;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out))
{
@ -288,25 +292,25 @@ int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v
static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u32 power)
{
sdmmc_cmd_t cmd;
sdmmc_cmd_t cmdbuf;
u32 arg = 0;
switch (power)
{
case SDMMC_POWER_1_8:
arg = SD_OCR_CCS | SD_OCR_VDD_18;
arg = MMC_CARD_CCS | MMC_CARD_VDD_18;
break;
case SDMMC_POWER_3_3:
arg = SD_OCR_CCS | SD_OCR_VDD_27_34;
arg = MMC_CARD_CCS | MMC_CARD_VDD_27_34;
break;
default:
return 0;
}
sdmmc_init_cmd(&cmd, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0))
sdmmc_init_cmd(&cmdbuf, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3);
@ -316,15 +320,17 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
{
u32 timeout = get_tmr_ms() + 1500;
while (1)
while (true)
{
u32 cond = 0;
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
break;
// Check if power up is done.
if (cond & MMC_CARD_BUSY)
{
if (cond & SD_OCR_CCS)
// Check if card is high capacity.
if (cond & MMC_CARD_CCS)
storage->has_sector_access = 1;
return 1;
@ -340,7 +346,7 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
static int _mmc_storage_set_relative_addr(sdmmc_storage_t *storage)
{
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SET_RELATIVE_ADDR, storage->rca << 16, 0, 0x10);
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SET_RELATIVE_ADDR, storage->rca << 16, 0, R1_SKIP_STATE_CHECK);
}
static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
@ -362,7 +368,6 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
case 3: /* MMC v3.1 - v3.3 */
case 4: /* MMC v4 */
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
storage->cid.card_bga = unstuff_bits(raw_cid, 112, 2);
storage->cid.oemid = unstuff_bits(raw_cid, 104, 8);
storage->cid.prv = unstuff_bits(raw_cid, 48, 8);
storage->cid.serial = unstuff_bits(raw_cid, 16, 32);
@ -390,13 +395,14 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
static void _mmc_storage_parse_csd(sdmmc_storage_t *storage)
{
u32 *raw_csd = (u32 *)&(storage->raw_csd);
u32 *raw_csd = (u32 *)storage->raw_csd;
storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4);
storage->csd.structure = unstuff_bits(raw_csd, 126, 2);
storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12);
storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4);
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
storage->sec_cnt = storage->csd.capacity;
}
static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
@ -407,16 +413,26 @@ static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION];
storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT];
storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT];
storage->ext_csd.sectors = *(u32 *)&buf[EXT_CSD_SEC_CNT];
storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT];
storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
//storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT];
//storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
//storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO];
storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A];
storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B];
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT];
storage->ext_csd.cache_size =
buf[EXT_CSD_CACHE_SIZE] |
(buf[EXT_CSD_CACHE_SIZE + 1] << 8) |
(buf[EXT_CSD_CACHE_SIZE + 2] << 16) |
(buf[EXT_CSD_CACHE_SIZE + 3] << 24);
storage->ext_csd.max_enh_mult =
(buf[EXT_CSD_MAX_ENH_SIZE_MULT] |
(buf[EXT_CSD_MAX_ENH_SIZE_MULT + 1] << 8) |
(buf[EXT_CSD_MAX_ENH_SIZE_MULT + 2] << 16)) *
buf[EXT_CSD_HC_WP_GRP_SIZE] * buf[EXT_CSD_HC_ERASE_GRP_SIZE];
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT];
}
static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
@ -430,21 +446,21 @@ static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1;
reqbuf.is_write = 0;
reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0;
reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0))
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0;
u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
_mmc_storage_parse_ext_csd(storage, buf);
return _sdmmc_storage_check_result(tmp);
return _sdmmc_storage_check_card_status(tmp);
}
static int _mmc_storage_switch(sdmmc_storage_t *storage, u32 arg)
{
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, 0x10);
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, R1_SKIP_STATE_CHECK);
}
static int _mmc_storage_switch_buswidth(sdmmc_storage_t *storage, u32 bus_width)
@ -559,19 +575,21 @@ out:
return 1;
}
/*
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)))
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_AUTO_BKOPS_MASK)))
return 0;
return _sdmmc_storage_check_status(storage);
}
*/
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
{
memset(storage, 0, sizeof(sdmmc_storage_t));
storage->sdmmc = sdmmc;
storage->rca = 2; //TODO: this could be a config item.
storage->rca = 2; // Set default device address. This could be a config item.
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE))
return 0;
@ -587,7 +605,7 @@ DPRINTF("[MMC] went to idle state\n");
return 0;
DPRINTF("[MMC] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
if (!_sdmmc_storage_get_cid(storage))
return 0;
DPRINTF("[MMC] got cid\n");
@ -595,7 +613,7 @@ DPRINTF("[MMC] got cid\n");
return 0;
DPRINTF("[MMC] set relative addr\n");
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
if (!_sdmmc_storage_get_csd(storage))
return 0;
DPRINTF("[MMC] got csd\n");
_mmc_storage_parse_csd(storage);
@ -612,13 +630,9 @@ DPRINTF("[MMC] card selected\n");
return 0;
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.
if (unstuff_bits(csd, 122, 4) < CSD_SPEC_VER_4)
{
storage->sec_cnt = (1 + unstuff_bits(csd, 62, 12)) << (unstuff_bits(csd, 47, 3) + 2);
// Check system specification version, only version 4.0 and later support below features.
if (storage->csd.mmca_vsn < CSD_SPEC_VER_4)
return 1;
}
if (!_mmc_storage_switch_buswidth(storage, bus_width))
return 0;
@ -628,21 +642,20 @@ DPRINTF("[MMC] switched buswidth\n");
return 0;
DPRINTF("[MMC] got ext_csd\n");
_mmc_storage_parse_cid(storage); //This needs to be after csd and ext_csd
_mmc_storage_parse_cid(storage); // This needs to be after csd and ext_csd.
//gfx_hexdump(0, ext_csd, 512);
/* When auto BKOPS is enabled the mmc device should be powered all the time until we disable this and check status.
Disable it for now until BKOPS disable added to power down sequence at sdmmc_storage_end().
Additionally this works only when we put the device in idle mode which we don't after enabling it. */
if (0 && storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2))
/*
if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_AUTO_BKOPS_MASK))
{
_mmc_storage_enable_bkops(storage);
DPRINTF("[MMC] BKOPS enabled\n");
}
*/
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
return 0;
DPRINTF("[MMC] succesfully switched to HS mode\n");
DPRINTF("[MMC] successfully switched to HS mode\n");
sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE);
@ -665,16 +678,16 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
}
/*
* SD specific functions.
*/
* SD specific functions.
*/
static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out)
static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmdbuf, sdmmc_req_t *req, u32 *blkcnt_out)
{
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);
return sdmmc_execute_cmd(storage->sdmmc, cmdbuf, req, blkcnt_out);
}
static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state)
@ -685,60 +698,70 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp
return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0);
}
static int _sd_storage_send_if_cond(sdmmc_storage_t *storage)
static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc)
{
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, 0x1AA, SDMMC_RSP_TYPE_5, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
return 1; // The SD Card is version 1.X
u16 vhd_pattern = SD_VHD_27_36 | 0xAA;
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
{
*is_sdsc = 1; // The SD Card is version 1.X
return 1;
}
// For Card version >= 2.0, parse results.
u32 resp = 0;
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5))
return 2;
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5);
return (resp & 0xFF) == 0xAA ? 0 : 2;
// Check if VHD was accepted and pattern was properly returned.
if ((resp & 0xFFF) == vhd_pattern)
return 1;
return 0;
}
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int bus_low_voltage_support)
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, bool is_sdsc, int bus_uhs_support)
{
sdmmc_cmd_t cmdbuf;
// Support for Current > 150mA
u32 arg = (~is_version_1 & 1) ? SD_OCR_XPC : 0;
u32 arg = !is_sdsc ? SD_OCR_XPC : 0;
// Support for handling block-addressed SDHC cards
arg |= (~is_version_1 & 1) ? SD_OCR_CCS : 0;
arg |= !is_sdsc ? SD_OCR_CCS : 0;
// Support for 1.8V
arg |= (bus_low_voltage_support & ~is_version_1 & 1) ? SD_OCR_S18R : 0;
arg |= (bus_uhs_support && !is_sdsc) ? SD_OCR_S18R : 0;
// This is needed for most cards. Do not set bit7 even if 1.8V is supported.
arg |= SD_OCR_VDD_32_33;
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))
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
return 0;
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
}
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int bus_low_voltage_support)
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int bus_uhs_support)
{
u32 timeout = get_tmr_ms() + 1500;
while (1)
while (true)
{
u32 cond = 0;
if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_low_voltage_support))
if (!_sd_storage_get_op_cond_once(storage, &cond, is_sdsc, bus_uhs_support))
break;
if (cond & MMC_CARD_BUSY)
{
DPRINTF("[SD] cond: %08X, lv: %d\n", cond, bus_low_voltage_support);
// Check if power up is done.
if (cond & SD_OCR_BUSY)
{
DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support);
// Check if card is high capacity.
if (cond & SD_OCR_CCS)
storage->has_sector_access = 1;
// Check if card supports 1.8V signaling.
if (cond & SD_ROCR_S18A && bus_low_voltage_support)
if (cond & SD_ROCR_S18A && bus_uhs_support)
{
//The low voltage regulator configuration is valid for SDMMC1 only.
if (storage->sdmmc->id == SDMMC_1 &&
_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
// Switch to 1.8V signaling.
if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
{
if (!sdmmc_enable_low_voltage(storage->sdmmc))
return 0;
@ -769,9 +792,9 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
u32 timeout = get_tmr_ms() + 1500;
while (1)
while (true)
{
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
break;
u32 resp = 0;
@ -802,8 +825,9 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage)
storage->scr.sda_vsn = unstuff_bits(resp, 56, 4);
storage->scr.bus_widths = unstuff_bits(resp, 48, 4);
/* If v2.0 is supported, check if Physical Layer Spec v3.0 is supported */
if (storage->scr.sda_vsn == SCR_SPEC_VER_2)
/* Check if Physical Layer Spec v3.0 is supported */
storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
if (storage->scr.sda_spec3)
storage->scr.cmds = unstuff_bits(resp, 32, 2);
@ -820,9 +844,9 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
reqbuf.num_sectors = 1;
reqbuf.is_write = 0;
reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0;
reqbuf.is_auto_stop_trn = 0;
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, 0))
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL))
return 0;
u32 tmp = 0;
@ -838,7 +862,7 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
_sd_storage_parse_scr(storage);
//gfx_hexdump(0, storage->raw_scr, 8);
return _sdmmc_storage_check_result(tmp);
return _sdmmc_storage_check_card_status(tmp);
}
int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
@ -852,14 +876,14 @@ int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1;
reqbuf.is_write = 0;
reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0;
reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0))
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0;
u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
return _sdmmc_storage_check_result(tmp);
return _sdmmc_storage_check_card_status(tmp);
}
int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group, u32 arg)
@ -876,14 +900,14 @@ int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group,
reqbuf.num_sectors = 1;
reqbuf.is_write = 0;
reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0;
reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0))
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0;
u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
return _sdmmc_storage_check_result(tmp);
return _sdmmc_storage_check_card_status(tmp);
}
void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u16 current_limit, u8 *buf)
@ -1057,41 +1081,64 @@ int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf)
return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25);
}
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage)
{
u32 au_size = storage->ssr.uhs_au_size;
if (!au_size)
au_size = storage->ssr.au_size;
if (au_size <= 10)
{
u32 shift = au_size;
au_size = shift ? 8 : 0;
au_size <<= shift;
}
else
{
switch (au_size)
{
case 11:
au_size = 12288;
break;
case 12:
au_size = 16384;
break;
case 13:
au_size = 24576;
break;
case 14:
au_size = 32768;
break;
case 15:
au_size = 65536;
break;
}
}
return au_size;
}
static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
{
// unstuff_bits supports only 4 u32 so break into 2 x 16byte groups
// unstuff_bits supports only 4 u32 so break into 2 x u32x4 groups.
u32 raw_ssr1[4];
u32 raw_ssr2[4];
raw_ssr1[3] = *(u32 *)&storage->raw_ssr[12];
raw_ssr1[2] = *(u32 *)&storage->raw_ssr[8];
raw_ssr1[1] = *(u32 *)&storage->raw_ssr[4];
raw_ssr1[0] = *(u32 *)&storage->raw_ssr[0];
raw_ssr2[3] = *(u32 *)&storage->raw_ssr[28];
raw_ssr2[2] = *(u32 *)&storage->raw_ssr[24];
raw_ssr2[1] = *(u32 *)&storage->raw_ssr[20];
raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16];
memcpy(raw_ssr1, &storage->raw_ssr[0], 16);
memcpy(raw_ssr2, &storage->raw_ssr[16], 16);
storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1;
storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32);
switch(unstuff_bits(raw_ssr1, 440 - 384, 8))
u32 speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
switch(speed_class)
{
case 0:
storage->ssr.speed_class = 0;
break;
case 1:
storage->ssr.speed_class = 2;
break;
case 2:
storage->ssr.speed_class = 4;
break;
case 3:
storage->ssr.speed_class = 6;
storage->ssr.speed_class = speed_class << 1;
break;
case 4:
@ -1099,16 +1146,18 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
break;
default:
storage->ssr.speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
storage->ssr.speed_class = speed_class;
break;
}
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8);
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4);
}
static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
{
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, SD_APP_SD_STATUS, 0, SDMMC_RSP_TYPE_1, 0);
@ -1119,49 +1168,51 @@ static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
reqbuf.num_sectors = 1;
reqbuf.is_write = 0;
reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0;
reqbuf.is_auto_stop_trn = 0;
if (!(storage->csd.cmdclass & CCC_APP_SPEC))
{
DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
DPRINTF("[SD] ssr: Not supported\n");
return 0;
}
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, 0))
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL))
return 0;
u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
//Prepare buffer for unstuff_bits
for (int i = 0; i < 64; i+=4)
// Convert buffer to LE.
for (int i = 0; i < 64; i += 4)
{
storage->raw_ssr[i + 3] = buf[i];
storage->raw_ssr[i + 2] = buf[i + 1];
storage->raw_ssr[i + 1] = buf[i + 2];
storage->raw_ssr[i] = buf[i + 3];
}
_sd_storage_parse_ssr(storage);
//gfx_hexdump(0, storage->raw_ssr, 64);
return _sdmmc_storage_check_result(tmp);
return _sdmmc_storage_check_card_status(tmp);
}
static void _sd_storage_parse_cid(sdmmc_storage_t *storage)
{
u32 *raw_cid = (u32 *)&(storage->raw_cid);
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8);
storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8);
storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8);
storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8);
storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8);
storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4);
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
storage->cid.month = unstuff_bits(raw_cid, 8, 4);
storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000;
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8);
storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8);
storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8);
storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8);
storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8);
storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4);
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000;
storage->cid.month = unstuff_bits(raw_cid, 8, 4);
}
static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
@ -1176,6 +1227,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
{
case 0:
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
storage->csd.capacity <<= unstuff_bits(raw_csd, 80, 4) - 9; // Convert native block size to LBA 512B.
break;
case 1:
@ -1183,10 +1235,16 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
storage->csd.capacity = storage->csd.c_size << 10;
storage->csd.read_blkbits = 9;
break;
default:
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
break;
}
storage->sec_cnt = storage->csd.capacity;
}
static bool _sdmmc_storage_get_low_voltage_support(u32 bus_width, u32 type)
static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type)
{
switch (type)
{
@ -1213,8 +1271,10 @@ void sdmmc_storage_init_wait_sd()
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
{
int is_version_1 = 0;
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
u32 tmp = 0;
int is_sdsc = 0;
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type);
@ -1234,18 +1294,15 @@ DPRINTF("[SD] after init\n");
return 0;
DPRINTF("[SD] went to idle state\n");
is_version_1 = _sd_storage_send_if_cond(storage);
if (is_version_1 == 2)
if (!_sd_storage_send_if_cond(storage, &is_sdsc))
return 0;
DPRINTF("[SD] after send if cond\n");
bool bus_low_voltage_support = _sdmmc_storage_get_low_voltage_support(bus_width, type);
if (!_sd_storage_get_op_cond(storage, is_version_1, bus_low_voltage_support))
if (!_sd_storage_get_op_cond(storage, is_sdsc, bus_uhs_support))
return 0;
DPRINTF("[SD] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
if (!_sdmmc_storage_get_cid(storage))
return 0;
DPRINTF("[SD] got cid\n");
_sd_storage_parse_cid(storage);
@ -1254,30 +1311,16 @@ DPRINTF("[SD] got cid\n");
return 0;
DPRINTF("[SD] got rca (= %04X)\n", storage->rca);
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
if (!_sdmmc_storage_get_csd(storage))
return 0;
DPRINTF("[SD] got csd\n");
//Parse CSD.
_sd_storage_parse_csd(storage);
switch (storage->csd.structure)
{
case 0:
storage->sec_cnt = storage->csd.capacity;
break;
case 1:
storage->sec_cnt = storage->csd.c_size << 10;
break;
default:
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
break;
}
if (!storage->is_low_voltage)
{
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12))
return 0;
DPRINTF("[SD] after setup clock\n");
DPRINTF("[SD] after setup default clock\n");
}
if (!_sdmmc_storage_select_card(storage))
@ -1288,19 +1331,17 @@ DPRINTF("[SD] card selected\n");
return 0;
DPRINTF("[SD] set blocklen to 512\n");
u32 tmp = 0;
// Disconnect Card Detect resistor from DAT3.
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");
if (!_sd_storage_get_scr(storage, buf))
return 0;
//gfx_hexdump(0, storage->raw_scr, 8);
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))
// If card supports a wider bus and if it's not SD Version 1.0 switch bus width.
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & BIT(SD_BUS_WIDTH_4)) && storage->scr.sda_vsn)
{
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN))
return 0;
@ -1310,6 +1351,7 @@ DPRINTF("[SD] switched to wide bus width\n");
}
else
{
bus_width = SDMMC_BUS_WIDTH_1;
DPRINTF("[SD] SD does not support wide bus width\n");
}
@ -1321,7 +1363,7 @@ DPRINTF("[SD] enabled UHS\n");
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
}
else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF) != 0)
else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0.
{
if (!_sd_storage_enable_hs_high_volt(storage, buf))
return 0;
@ -1340,7 +1382,7 @@ DPRINTF("[SD] enabled HS\n");
}
// Parse additional card info from sd status.
if (_sd_storage_get_ssr(storage, buf))
if (sd_storage_get_ssr(storage, buf))
{
DPRINTF("[SD] got sd status\n");
}
@ -1351,14 +1393,14 @@ DPRINTF("[SD] got sd status\n");
}
/*
* Gamecard specific functions.
*/
* Gamecard specific functions.
*/
int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
{
u32 resp;
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, 60, 0, SDMMC_RSP_TYPE_1, 1);
sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_60_CMD, 0, SDMMC_RSP_TYPE_1, 1);
sdmmc_req_t reqbuf;
reqbuf.buf = buf;
@ -1366,9 +1408,9 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1;
reqbuf.is_write = 1;
reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0;
reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0))
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
{
sdmmc_stop_transmission(storage->sdmmc, &resp);
return 0;
@ -1376,7 +1418,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1))
return 0;
if (!_sdmmc_storage_check_result(resp))
if (!_sdmmc_storage_check_card_status(resp))
return 0;
return _sdmmc_storage_check_status(storage);
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 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,
@ -30,18 +30,18 @@ typedef enum _sdmmc_type
EMMC_GPP = 0,
EMMC_BOOT0 = 1,
EMMC_BOOT1 = 2
EMMC_BOOT1 = 2,
EMMC_RPMB = 3
} sdmmc_type;
typedef struct _mmc_cid
{
u32 manfid;
u8 prod_name[8];
u8 card_bga;
u8 prv;
u32 serial;
u16 oemid;
u16 year;
u8 prv;
u8 hwrev;
u8 fwrev;
u8 month;
@ -65,19 +65,20 @@ typedef struct _mmc_csd
typedef struct _mmc_ext_csd
{
u32 sectors;
int bkops; /* background support bit */
int bkops_en; /* manual bkops enable bit */
//u8 bkops; /* background support bit */
//u8 bkops_en; /* manual bkops enable bit */
//u8 bkops_status; /* 246 */
u8 rev;
u8 ext_struct; /* 194 */
u8 card_type; /* 196 */
u8 bkops_status; /* 246 */
u8 pre_eol_info;
u8 dev_life_est_a;
u8 dev_life_est_b;
u8 boot_mult;
u8 rpmb_mult;
u16 dev_version;
u32 cache_size;
u32 max_enh_mult;
} mmc_ext_csd_t;
typedef struct _sd_scr
@ -90,11 +91,13 @@ typedef struct _sd_scr
typedef struct _sd_ssr
{
u8 bus_width;
u8 speed_class;
u8 uhs_grade;
u8 video_class;
u8 app_class;
u8 bus_width;
u8 speed_class;
u8 uhs_grade;
u8 video_class;
u8 app_class;
u8 au_size;
u8 uhs_au_size;
u32 protected_size;
} sd_ssr_t;
@ -107,6 +110,7 @@ typedef struct _sdmmc_storage_t
u32 sec_cnt;
int is_low_voltage;
u32 partition;
int initialized;
u8 raw_cid[0x10];
u8 raw_csd[0x10];
u8 raw_scr[8];
@ -116,16 +120,18 @@ typedef struct _sdmmc_storage_t
mmc_ext_csd_t ext_csd;
sd_scr_t scr;
sd_ssr_t ssr;
int initialized;
} sdmmc_storage_t;
int sdmmc_storage_end(sdmmc_storage_t *storage);
int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
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 bus_width, u32 type);
int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition);
int sdmmc_storage_end(sdmmc_storage_t *storage);
int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
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 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 bus_width, u32 type);
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type);
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf);
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage);
#endif

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 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,
@ -501,7 +501,7 @@ int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
break;
case SDMMC_RSP_TYPE_2:
if (size < 0x10)
if (size < 16)
return 0;
rsp[0] = sdmmc->rsp[0];
rsp[1] = sdmmc->rsp[1];
@ -934,12 +934,20 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
*blkcnt_out = blkcnt;
u32 trnmode = SDHCI_TRNS_DMA;
// Set mulitblock request.
if (req->is_multi_block)
trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA;
// Set request direction.
if (!req->is_write)
trnmode |= SDHCI_TRNS_READ;
if (req->is_auto_cmd12)
trnmode = (trnmode & ~(SDHCI_TRNS_AUTO_CMD12 | SDHCI_TRNS_AUTO_CMD23)) | SDHCI_TRNS_AUTO_CMD12;
// Automatic send of stop transmission or set block count cmd.
if (req->is_auto_stop_trn)
trnmode |= SDHCI_TRNS_AUTO_CMD12;
//else if (req->is_auto_set_blkcnt)
// trnmode |= SDHCI_TRNS_AUTO_CMD23;
sdmmc->regs->trnmod = trnmode;
@ -1052,7 +1060,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
if (!result)
{
#ifdef ERROR_EXTRA_PRINTING
EPRINTFARGS("SDMMC: DMA Update failed (%08X)!", result);
EPRINTF("SDMMC: DMA Update failed!");
#endif
}
}
@ -1070,7 +1078,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
if (blkcnt_out)
*blkcnt_out = blkcnt;
if (req->is_auto_cmd12)
if (req->is_auto_stop_trn)
sdmmc->rsp3 = sdmmc->regs->rspreg3;
}
@ -1200,8 +1208,8 @@ static int _sdmmc_config_sdmmc1(bool t210b01)
usleep(10000);
// Enable SD card IO power.
max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000);
max77620_regulator_enable(REGULATOR_LDO2, 1);
max7762x_regulator_set_voltage(REGULATOR_LDO2, 3300000);
max7762x_regulator_enable(REGULATOR_LDO2, true);
usleep(1000);
// Set pad slew codes to get good quality clock.
@ -1332,18 +1340,6 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int p
void sdmmc1_disable_power()
{
// Ensure regulator is into default voltage.
if (PMC(APBDEV_PMC_PWR_DET_VAL) & PMC_PWR_DET_SDMMC1_IO_EN)
{
// Switch to 1.8V and wait for regulator to stabilize.
max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000);
usleep(150);
// Inform IO pads that we switched to 1.8V.
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(PMC_PWR_DET_SDMMC1_IO_EN);
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
}
// T210B01 WAR: Clear pull down from CLK pad.
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) &= ~PINMUX_PULL_MASK;
@ -1351,7 +1347,7 @@ void sdmmc1_disable_power()
_sdmmc_config_sdmmc1_pads(true);
// Disable SD card IO power regulator.
max77620_regulator_enable(REGULATOR_LDO2, 0);
max7762x_regulator_enable(REGULATOR_LDO2, false);
usleep(4000);
// Disable SD card IO power pin.
@ -1383,12 +1379,12 @@ void sdmmc_end(sdmmc_t *sdmmc)
_sdmmc_sd_clock_disable(sdmmc);
// Disable SDMMC power.
_sdmmc_set_io_power(sdmmc, SDMMC_POWER_OFF);
_sdmmc_commit_changes(sdmmc);
// Disable SD card power.
if (sdmmc->id == SDMMC_1)
sdmmc1_disable_power();
_sdmmc_commit_changes(sdmmc);
clock_sdmmc_disable(sdmmc->id);
sdmmc->clock_stopped = 1;
}
@ -1440,7 +1436,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
_sdmmc_commit_changes(sdmmc);
// Switch to 1.8V and wait for regulator to stabilize. Assume max possible wait needed.
max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000);
max7762x_regulator_set_voltage(REGULATOR_LDO2, 1800000);
usleep(150);
// Inform IO pads that we switched to 1.8V.

View file

@ -242,7 +242,7 @@ typedef struct _sdmmc_req_t
u32 num_sectors;
int is_write;
int is_multi_block;
int is_auto_cmd12;
int is_auto_stop_trn;
} sdmmc_req_t;
int sdmmc_get_io_power(sdmmc_t *sdmmc);