Initial commit

This commit is contained in:
shchmue 2019-03-04 18:05:42 -05:00
commit 641476a75e
95 changed files with 28756 additions and 0 deletions

432
source/storage/mmc.h Normal file
View file

@ -0,0 +1,432 @@
/*
* Header for MultiMediaCard (MMC)
*
* Copyright 2002 Hewlett-Packard Company
*
* Use consistent with the GNU GPL is permitted,
* provided that this copyright notice is
* preserved in its entirety in all copies and derived works.
*
* HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
* FITNESS FOR ANY PARTICULAR PURPOSE.
*
* Many thanks to Alessandro Rubini and Jonathan Corbet!
*
* Based strongly on code by:
*
* Author: Yong-iL Joh <tolkien@mizi.com>
*
* Author: Andrew Christian
* 15 May 2002
*/
#ifndef LINUX_MMC_MMC_H
#define LINUX_MMC_MMC_H
/* Standard MMC commands (4.1) type argument response */
/* class 1 */
#define MMC_GO_IDLE_STATE 0 /* bc */
#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */
#define MMC_ALL_SEND_CID 2 /* bcr R2 */
#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */
#define MMC_SET_DSR 4 /* bc [31:16] RCA */
#define MMC_SLEEP_AWAKE 5 /* ac [31:16] RCA 15:flg R1b */
#define MMC_SWITCH 6 /* ac [31:0] See below R1b */
#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */
#define MMC_SEND_EXT_CSD 8 /* adtc R1 */
#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */
#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */
#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */
#define MMC_STOP_TRANSMISSION 12 /* ac R1b */
#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */
#define MMC_BUS_TEST_R 14 /* adtc R1 */
#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */
#define MMC_BUS_TEST_W 19 /* adtc R1 */
#define MMC_SPI_READ_OCR 58 /* spi spi_R3 */
#define MMC_SPI_CRC_ON_OFF 59 /* spi [0:0] flag spi_R1 */
/* class 2 */
#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */
#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */
#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */
#define MMC_SEND_TUNING_BLOCK 19 /* adtc R1 */
#define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1 */
/* class 3 */
#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */
/* class 4 */
#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */
#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */
#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */
#define MMC_PROGRAM_CID 26 /* adtc R1 */
#define MMC_PROGRAM_CSD 27 /* adtc R1 */
/* class 6 */
#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */
#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */
#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */
/* class 5 */
#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */
#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */
#define MMC_ERASE 38 /* ac R1b */
/* class 9 */
#define MMC_FAST_IO 39 /* ac <Complex> R4 */
#define MMC_GO_IRQ_STATE 40 /* bcr R5 */
/* class 7 */
#define MMC_LOCK_UNLOCK 42 /* adtc R1b */
/* class 8 */
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
/* 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 */
#define MMC_EXECUTE_READ_TASK 46 /* adtc [20:16] task id R1 */
#define MMC_EXECUTE_WRITE_TASK 47 /* adtc [20:16] task id R1 */
#define MMC_CMDQ_TASK_MGMT 48 /* ac [20:16] task id R1b */
/*
* MMC_SWITCH argument format:
*
* [31:26] Always 0
* [25:24] Access Mode
* [23:16] Location of target Byte in EXT_CSD
* [15:08] Value Byte
* [07:03] Always 0
* [02:00] Command Set
*/
/*
MMC status in R1, for native mode (SPI bits are different)
Type
e : error bit
s : status bit
r : detected and set for the actual command response
x : detected and set during command execution. the host must poll
the card by sending status command in order to read these bits.
Clear condition
a : according to the card state
b : always related to the previous command. Reception of
a valid command will clear it (with a delay of one command)
c : clear by read
*/
#define R1_OUT_OF_RANGE (1 << 31) /* er, c */
#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */
#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */
#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */
#define R1_ERASE_PARAM (1 << 27) /* ex, c */
#define R1_WP_VIOLATION (1 << 26) /* erx, c */
#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */
#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */
#define R1_COM_CRC_ERROR (1 << 23) /* er, b */
#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */
#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */
#define R1_CC_ERROR (1 << 20) /* erx, c */
#define R1_ERROR (1 << 19) /* erx, c */
#define R1_UNDERRUN (1 << 18) /* ex, c */
#define R1_OVERRUN (1 << 17) /* ex, c */
#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */
#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */
#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */
#define R1_ERASE_RESET (1 << 13) /* sr, c */
#define R1_STATUS(x) (x & 0xFFFFE000)
#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
#define R1_READY_FOR_DATA (1 << 8) /* sx, a */
#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_STATE_IDLE 0
#define R1_STATE_READY 1
#define R1_STATE_IDENT 2
#define R1_STATE_STBY 3
#define R1_STATE_TRAN 4
#define R1_STATE_DATA 5
#define R1_STATE_RCV 6
#define R1_STATE_PRG 7
#define R1_STATE_DIS 8
/*
* MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS
* R1 is the low order byte; R2 is the next highest byte, when present.
*/
#define R1_SPI_IDLE (1 << 0)
#define R1_SPI_ERASE_RESET (1 << 1)
#define R1_SPI_ILLEGAL_COMMAND (1 << 2)
#define R1_SPI_COM_CRC (1 << 3)
#define R1_SPI_ERASE_SEQ (1 << 4)
#define R1_SPI_ADDRESS (1 << 5)
#define R1_SPI_PARAMETER (1 << 6)
/* R1 bit 7 is always zero */
#define R2_SPI_CARD_LOCKED (1 << 8)
#define R2_SPI_WP_ERASE_SKIP (1 << 9) /* or lock/unlock fail */
#define R2_SPI_LOCK_UNLOCK_FAIL R2_SPI_WP_ERASE_SKIP
#define R2_SPI_ERROR (1 << 10)
#define R2_SPI_CC_ERROR (1 << 11)
#define R2_SPI_CARD_ECC_ERROR (1 << 12)
#define R2_SPI_WP_VIOLATION (1 << 13)
#define R2_SPI_ERASE_PARAM (1 << 14)
#define R2_SPI_OUT_OF_RANGE (1 << 15) /* or CSD overwrite */
#define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE
/*
* OCR bits are mostly in host.h
*/
#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
/*
* Card Command Classes (CCC)
*/
#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */
/* (CMD0,1,2,3,4,7,9,10,12,13,15) */
/* (and for SPI, CMD58,59) */
#define CCC_STREAM_READ (1<<1) /* (1) Stream read commands */
/* (CMD11) */
#define CCC_BLOCK_READ (1<<2) /* (2) Block read commands */
/* (CMD16,17,18) */
#define CCC_STREAM_WRITE (1<<3) /* (3) Stream write commands */
/* (CMD20) */
#define CCC_BLOCK_WRITE (1<<4) /* (4) Block write commands */
/* (CMD16,24,25,26,27) */
#define CCC_ERASE (1<<5) /* (5) Ability to erase blocks */
/* (CMD32,33,34,35,36,37,38,39) */
#define CCC_WRITE_PROT (1<<6) /* (6) Able to write protect blocks */
/* (CMD28,29,30) */
#define CCC_LOCK_CARD (1<<7) /* (7) Able to lock down card */
/* (CMD16,CMD42) */
#define CCC_APP_SPEC (1<<8) /* (8) Application specific */
/* (CMD55,56,57,ACMD*) */
#define CCC_IO_MODE (1<<9) /* (9) I/O mode */
/* (CMD5,39,40,52,53) */
#define CCC_SWITCH (1<<10) /* (10) High speed switch */
/* (CMD6,34,35,36,37,50) */
/* (11) Reserved */
/* (CMD?) */
/*
* CSD field definitions
*/
#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */
#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */
#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
#define CSD_STRUCT_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */
#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */
#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */
#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */
#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */
#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */
/*
* EXT_CSD fields
*/
#define EXT_CSD_CMDQ_MODE_EN 15 /* R/W */
#define EXT_CSD_FLUSH_CACHE 32 /* W */
#define EXT_CSD_CACHE_CTRL 33 /* R/W */
#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */
#define EXT_CSD_PACKED_FAILURE_INDEX 35 /* RO */
#define EXT_CSD_PACKED_CMD_STATUS 36 /* RO */
#define EXT_CSD_EXP_EVENTS_STATUS 54 /* RO, 2 bytes */
#define EXT_CSD_EXP_EVENTS_CTRL 56 /* R/W, 2 bytes */
#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */
#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_PARTITION_SUPPORT 160 /* RO */
#define EXT_CSD_HPI_MGMT 161 /* R/W */
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
#define EXT_CSD_BKOPS_EN 163 /* R/W */
#define EXT_CSD_BKOPS_START 164 /* W */
#define EXT_CSD_SANITIZE_START 165 /* W */
#define EXT_CSD_WR_REL_PARAM 166 /* RO */
#define EXT_CSD_RPMB_MULT 168 /* RO */
#define EXT_CSD_FW_CONFIG 169 /* R/W */
#define EXT_CSD_BOOT_WP 173 /* R/W */
#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */
#define EXT_CSD_PART_CONFIG 179 /* R/W */
#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */
#define EXT_CSD_BUS_WIDTH 183 /* R/W */
#define EXT_CSD_STROBE_SUPPORT 184 /* RO */
#define EXT_CSD_HS_TIMING 185 /* R/W */
#define EXT_CSD_POWER_CLASS 187 /* R/W */
#define EXT_CSD_REV 192 /* RO */
#define EXT_CSD_STRUCTURE 194 /* RO */
#define EXT_CSD_CARD_TYPE 196 /* RO */
#define EXT_CSD_DRIVER_STRENGTH 197 /* RO */
#define EXT_CSD_OUT_OF_INTERRUPT_TIME 198 /* RO */
#define EXT_CSD_PART_SWITCH_TIME 199 /* RO */
#define EXT_CSD_PWR_CL_52_195 200 /* RO */
#define EXT_CSD_PWR_CL_26_195 201 /* RO */
#define EXT_CSD_PWR_CL_52_360 202 /* RO */
#define EXT_CSD_PWR_CL_26_360 203 /* RO */
#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
#define EXT_CSD_S_A_TIMEOUT 217 /* RO */
#define EXT_CSD_REL_WR_SEC_C 222 /* RO */
#define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */
#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */
#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */
#define EXT_CSD_BOOT_MULT 226 /* RO */
#define EXT_CSD_SEC_TRIM_MULT 229 /* RO */
#define EXT_CSD_SEC_ERASE_MULT 230 /* RO */
#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */
#define EXT_CSD_TRIM_MULT 232 /* RO */
#define EXT_CSD_PWR_CL_200_195 236 /* RO */
#define EXT_CSD_PWR_CL_200_360 237 /* RO */
#define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */
#define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */
#define EXT_CSD_BKOPS_STATUS 246 /* RO */
#define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */
#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */
#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */
#define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */
#define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */
#define EXT_CSD_DEVICE_VERSION 262 /* RO, 2 bytes */
#define EXT_CSD_PRE_EOL_INFO 267 /* RO */
#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A 268 /* RO */
#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B 269 /* RO */
#define EXT_CSD_CMDQ_DEPTH 307 /* RO */
#define EXT_CSD_CMDQ_SUPPORT 308 /* RO */
#define EXT_CSD_SUPPORTED_MODE 493 /* RO */
#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */
#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */
#define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */
#define EXT_CSD_MAX_PACKED_READS 501 /* RO */
#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */
#define EXT_CSD_HPI_FEATURES 503 /* RO */
/*
* EXT_CSD field definitions
*/
#define EXT_CSD_WR_REL_PARAM_EN (1<<2)
#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS (0x40)
#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS (0x10)
#define EXT_CSD_BOOT_WP_B_PERM_WP_EN (0x04)
#define EXT_CSD_BOOT_WP_B_PWR_WP_EN (0x01)
#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7)
#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1)
#define EXT_CSD_PART_CONFIG_ACC_RPMB (0x3)
#define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4)
#define EXT_CSD_PART_SETTING_COMPLETED (0x1)
#define EXT_CSD_PART_SUPPORT_PART_EN (0x1)
#define EXT_CSD_CMD_SET_NORMAL (1<<0)
#define EXT_CSD_CMD_SET_SECURE (1<<1)
#define EXT_CSD_CMD_SET_CPSECURE (1<<2)
#define EXT_CSD_CARD_TYPE_HS_26 (1<<0) /* Card can run at 26MHz */
#define EXT_CSD_CARD_TYPE_HS_52 (1<<1) /* Card can run at 52MHz */
#define EXT_CSD_CARD_TYPE_HS (EXT_CSD_CARD_TYPE_HS_26 | \
EXT_CSD_CARD_TYPE_HS_52)
#define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */
/* DDR mode @1.8V or 3V I/O */
#define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */
/* DDR mode @1.2V I/O */
#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \
| EXT_CSD_CARD_TYPE_DDR_1_2V)
#define EXT_CSD_CARD_TYPE_HS200_1_8V (1<<4) /* Card can run at 200MHz */
#define EXT_CSD_CARD_TYPE_HS200_1_2V (1<<5) /* Card can run at 200MHz */
/* SDR mode @1.2V I/O */
#define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_HS200_1_8V | \
EXT_CSD_CARD_TYPE_HS200_1_2V)
#define EXT_CSD_CARD_TYPE_HS400_1_8V (1<<6) /* Card can run at 200MHz DDR, 1.8V */
#define EXT_CSD_CARD_TYPE_HS400_1_2V (1<<7) /* Card can run at 200MHz DDR, 1.2V */
#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | \
EXT_CSD_CARD_TYPE_HS400_1_2V)
#define EXT_CSD_CARD_TYPE_HS400ES (1<<8) /* Card can run at HS400ES */
#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */
#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */
#define EXT_CSD_BUS_WIDTH_STROBE (1<<7) /* Enhanced strobe mode */
#define EXT_CSD_TIMING_BC 0 /* Backwards compatility */
#define EXT_CSD_TIMING_HS 1 /* High speed */
#define EXT_CSD_TIMING_HS200 2 /* HS200 */
#define EXT_CSD_TIMING_HS400 3 /* HS400 */
#define EXT_CSD_DRV_STR_SHIFT 4 /* Driver Strength shift */
#define EXT_CSD_SEC_ER_EN (1<<0)
#define EXT_CSD_SEC_BD_BLK_EN (1<<2)
#define EXT_CSD_SEC_GB_CL_EN (1<<4)
#define EXT_CSD_SEC_SANITIZE (1<<6) /* v4.5 only */
#define EXT_CSD_RST_N_EN_MASK 0x3
#define EXT_CSD_RST_N_ENABLED 1 /* RST_n is enabled on card */
#define EXT_CSD_NO_POWER_NOTIFICATION 0
#define EXT_CSD_POWER_ON 1
#define EXT_CSD_POWER_OFF_SHORT 2
#define EXT_CSD_POWER_OFF_LONG 3
#define EXT_CSD_PWR_CL_8BIT_MASK 0xF0 /* 8 bit PWR CLS */
#define EXT_CSD_PWR_CL_4BIT_MASK 0x0F /* 8 bit PWR CLS */
#define EXT_CSD_PWR_CL_8BIT_SHIFT 4
#define EXT_CSD_PWR_CL_4BIT_SHIFT 0
#define EXT_CSD_PACKED_EVENT_EN (1<<3)
/*
* EXCEPTION_EVENT_STATUS field
*/
#define EXT_CSD_URGENT_BKOPS (1<<0)
#define EXT_CSD_DYNCAP_NEEDED (1<<1)
#define EXT_CSD_SYSPOOL_EXHAUSTED (1<<2)
#define EXT_CSD_PACKED_FAILURE (1<<3)
#define EXT_CSD_PACKED_GENERIC_ERROR (1<<0)
#define EXT_CSD_PACKED_INDEXED_ERROR (1<<1)
/*
* BKOPS status level
*/
#define EXT_CSD_BKOPS_LEVEL_2 0x2
/*
* BKOPS modes
*/
#define EXT_CSD_MANUAL_BKOPS_MASK 0x01
#define EXT_CSD_AUTO_BKOPS_MASK 0x02
/*
* Command Queue
*/
#define EXT_CSD_CMDQ_MODE_ENABLED (1<<0)
#define EXT_CSD_CMDQ_DEPTH_MASK 0x1F
#define EXT_CSD_CMDQ_SUPPORTED (1<<0)
/*
* MMC_SWITCH access modes
*/
#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */
#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
/*
* Erase/trim/discard
*/
#define MMC_ERASE_ARG 0x00000000
#define MMC_SECURE_ERASE_ARG 0x80000000
#define MMC_TRIM_ARG 0x00000001
#define MMC_DISCARD_ARG 0x00000003
#define MMC_SECURE_TRIM1_ARG 0x80000001
#define MMC_SECURE_TRIM2_ARG 0x80008000
#define MMC_SECURE_ARGS 0x80000000
#define MMC_TRIM_ARGS 0x00008001
#endif /* LINUX_MMC_MMC_H */

77
source/storage/nx_emmc.c Normal file
View file

@ -0,0 +1,77 @@
/*
* Copyright (c) 2018 naehrwert
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "nx_emmc.h"
#include "../mem/heap.h"
#include "../utils/list.h"
void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage)
{
u8 *buf = (u8 *)malloc(NX_GPT_NUM_BLOCKS * NX_EMMC_BLOCKSIZE);
sdmmc_storage_read(storage, NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, buf);
gpt_header_t *hdr = (gpt_header_t *)buf;
for (u32 i = 0; i < hdr->num_part_ents; i++)
{
gpt_entry_t *ent = (gpt_entry_t *)(buf + (hdr->part_ent_lba - 1) * NX_EMMC_BLOCKSIZE + i * sizeof(gpt_entry_t));
emmc_part_t *part = (emmc_part_t *)malloc(sizeof(emmc_part_t));
part->lba_start = ent->lba_start;
part->lba_end = ent->lba_end;
part->attrs = ent->attrs;
//HACK
for (u32 i = 0; i < 36; i++)
part->name[i] = ent->name[i];
part->name[36] = 0;
list_append(gpt, &part->link);
}
free(buf);
}
void nx_emmc_gpt_free(link_t *gpt)
{
LIST_FOREACH_SAFE(iter, gpt)
free(CONTAINER_OF(iter, emmc_part_t, link));
}
emmc_part_t *nx_emmc_part_find(link_t *gpt, const char *name)
{
LIST_FOREACH_ENTRY(emmc_part_t, part, gpt, link)
if (!strcmp(part->name, name))
return part;
return NULL;
}
int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf)
{
// The last LBA is inclusive.
if (part->lba_start + sector_off > part->lba_end)
return 0;
return sdmmc_storage_read(storage, part->lba_start + sector_off, num_sectors, buf);
}
int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf)
{
// The last LBA is inclusive.
if (part->lba_start + sector_off > part->lba_end)
return 0;
return sdmmc_storage_write(storage, part->lba_start + sector_off, num_sectors, buf);
}

72
source/storage/nx_emmc.h Normal file
View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2018 naehrwert
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _NX_EMMC_H_
#define _NX_EMMC_H_
#include "../utils/types.h"
#include "../utils/list.h"
#include "sdmmc.h"
typedef struct _gpt_entry_t
{
u8 type_guid[0x10];
u8 part_guid[0x10];
u64 lba_start;
u64 lba_end;
u64 attrs;
u16 name[36];
} gpt_entry_t;
typedef struct _gpt_header_t
{
u64 signature;
u32 revision;
u32 size;
u32 crc32;
u32 res1;
u64 my_lba;
u64 alt_lba;
u64 first_use_lba;
u64 last_use_lba;
u8 disk_guid[0x10];
u64 part_ent_lba;
u32 num_part_ents;
u32 part_ent_size;
u32 part_ents_crc32;
u8 res2[420];
} gpt_header_t;
#define NX_GPT_FIRST_LBA 1
#define NX_GPT_NUM_BLOCKS 33
#define NX_EMMC_BLOCKSIZE 512
typedef struct _emmc_part_t
{
u32 lba_start;
u32 lba_end;
u64 attrs;
s8 name[37];
link_t link;
} emmc_part_t;
void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage);
void nx_emmc_gpt_free(link_t *gpt);
emmc_part_t *nx_emmc_part_find(link_t *gpt, const char *name);
int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
#endif

124
source/storage/sd.h Normal file
View file

@ -0,0 +1,124 @@
/*
* include/linux/mmc/sd.h
*
* Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
* Copyright (C) 2018 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
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*/
#ifndef LINUX_MMC_SD_H
#define LINUX_MMC_SD_H
/* 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 */
/* class 10 */
#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 */
/* 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 */
/* OCR bit definitions */
#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_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */
/*
* 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)
*/
/*
* 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 */
#define SD_SCR_BUS_WIDTH_1 (1<<0)
#define SD_SCR_BUS_WIDTH_4 (1<<2)
/*
* SD bus widths
*/
#define SD_BUS_WIDTH_1 0
#define SD_BUS_WIDTH_4 2
/*
* SD bus speeds
*/
#define UHS_SDR12_BUS_SPEED 0
#define HIGH_SPEED_BUS_SPEED 1
#define UHS_SDR25_BUS_SPEED 1
#define UHS_SDR50_BUS_SPEED 2
#define UHS_SDR104_BUS_SPEED 3
#define UHS_DDR50_BUS_SPEED 4
#define HS400_BUS_SPEED 5
#define SD_MODE_HIGH_SPEED (1 << HIGH_SPEED_BUS_SPEED)
#define SD_MODE_UHS_SDR12 (1 << UHS_SDR12_BUS_SPEED)
#define SD_MODE_UHS_SDR25 (1 << UHS_SDR25_BUS_SPEED)
#define SD_MODE_UHS_SDR50 (1 << UHS_SDR50_BUS_SPEED)
#define SD_MODE_UHS_SDR104 (1 << UHS_SDR104_BUS_SPEED)
#define SD_MODE_UHS_DDR50 (1 << UHS_DDR50_BUS_SPEED)
#define SD_DRIVER_TYPE_B 0x01
#define SD_DRIVER_TYPE_A 0x02
#define SD_SET_CURRENT_LIMIT_200 0
#define SD_SET_CURRENT_LIMIT_400 1
#define SD_SET_CURRENT_LIMIT_600 2
#define SD_SET_CURRENT_LIMIT_800 3
/*
* SD_SWITCH mode
*/
#define SD_SWITCH_CHECK 0
#define SD_SWITCH_SET 1
/*
* SD_SWITCH function groups
*/
#define SD_SWITCH_GRP_ACCESS 0
/*
* SD_SWITCH access modes
*/
#define SD_SWITCH_ACCESS_DEF 0
#define SD_SWITCH_ACCESS_HS 1
#endif /* LINUX_MMC_SD_H */

1189
source/storage/sdmmc.c Normal file

File diff suppressed because it is too large Load diff

113
source/storage/sdmmc.h Normal file
View file

@ -0,0 +1,113 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (C) 2018 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,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SDMMC_H_
#define _SDMMC_H_
#include "../utils/types.h"
#include "sdmmc_driver.h"
typedef struct _mmc_cid
{
u32 manfid;
u8 prod_name[8];
u8 card_bga;
u8 prv;
u32 serial;
u16 oemid;
u16 year;
u8 hwrev;
u8 fwrev;
u8 month;
} mmc_cid_t;
typedef struct _mmc_csd
{
u8 structure;
u8 mmca_vsn;
u16 cmdclass;
u32 c_size;
u32 r2w_factor;
u32 max_dtr;
u32 erase_size; /* In sectors */
u32 read_blkbits;
u32 write_blkbits;
u32 capacity;
u8 write_protect;
u16 busspeed;
} mmc_csd_t;
typedef struct _mmc_ext_csd
{
u8 rev;
u32 sectors;
int bkops; /* background support bit */
int bkops_en; /* manual bkops enable bit */
u8 ext_struct; /* 194 */
u8 card_type; /* 196 */
u8 bkops_status; /* 246 */
u16 dev_version;
u8 boot_mult;
u8 rpmb_mult;
} mmc_ext_csd_t;
typedef struct _sd_scr
{
u8 sda_vsn;
u8 sda_spec3;
u8 bus_widths;
u8 cmds;
} sd_scr_t;
typedef struct _sd_ssr
{
u8 bus_width;
u8 speed_class;
u8 uhs_grade;
u8 video_class;
u8 app_class;
} sd_ssr_t;
/*! SDMMC storage context. */
typedef struct _sdmmc_storage_t
{
sdmmc_t *sdmmc;
u32 rca;
int has_sector_access;
u32 sec_cnt;
int is_low_voltage;
u32 partition;
u8 raw_cid[0x10];
u8 raw_csd[0x10];
u8 raw_scr[8];
u8 raw_ssr[0x40];
mmc_cid_t cid;
mmc_csd_t csd;
mmc_ext_csd_t ext_csd;
sd_scr_t scr;
sd_ssr_t ssr;
} 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 id, u32 bus_width, u32 type);
int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition);
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);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,126 @@
/*
* Copyright (c) 2018 naehrwert
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SDMMC_DRIVER_H_
#define _SDMMC_DRIVER_H_
#include "../utils/types.h"
#include "sdmmc_t210.h"
/*! SDMMC controller IDs. */
#define SDMMC_1 0
#define SDMMC_2 1
#define SDMMC_3 2
#define SDMMC_4 3
/*! SDMMC power types. */
#define SDMMC_POWER_OFF 0
#define SDMMC_POWER_1_8 1
#define SDMMC_POWER_3_3 2
/*! SDMMC bus widths. */
#define SDMMC_BUS_WIDTH_1 0
#define SDMMC_BUS_WIDTH_4 1
#define SDMMC_BUS_WIDTH_8 2
/*! SDMMC response types. */
#define SDMMC_RSP_TYPE_0 0
#define SDMMC_RSP_TYPE_1 1
#define SDMMC_RSP_TYPE_2 2
#define SDMMC_RSP_TYPE_3 3
#define SDMMC_RSP_TYPE_4 4
#define SDMMC_RSP_TYPE_5 5
/*! SDMMC mask interrupt status. */
#define SDMMC_MASKINT_MASKED 0
#define SDMMC_MASKINT_NOERROR -1
#define SDMMC_MASKINT_ERROR -2
/*! SDMMC host control 2 */
#define SDHCI_CTRL_UHS_MASK 0xFFF8
#define SDHCI_CTRL_VDD_330 0xFFF7
#define SDHCI_CTRL_VDD_180 8
#define SDHCI_CTRL_EXEC_TUNING 0x40
#define SDHCI_CTRL_TUNED_CLK 0x80
#define SDHCI_HOST_VERSION_4_EN 0x1000
#define SDHCI_ADDRESSING_64BIT_EN 0x2000
#define SDHCI_CTRL_PRESET_VAL_EN 0x8000
/*! SD bus speeds. */
#define UHS_SDR12_BUS_SPEED 0
#define HIGH_SPEED_BUS_SPEED 1
#define UHS_SDR25_BUS_SPEED 1
#define UHS_SDR50_BUS_SPEED 2
#define UHS_SDR104_BUS_SPEED 3
#define UHS_DDR50_BUS_SPEED 4
#define HS400_BUS_SPEED 5
/*! Helper for SWITCH command argument. */
#define SDMMC_SWITCH(mode, index, value) (((mode) << 24) | ((index) << 16) | ((value) << 8))
/*! SDMMC controller context. */
typedef struct _sdmmc_t
{
t210_sdmmc_t *regs;
u32 id;
u32 divisor;
u32 clock_stopped;
int no_sd;
int sd_clock_enabled;
int venclkctl_set;
u32 venclkctl_tap;
u32 expected_rsp_type;
u32 dma_addr_next;
u32 rsp[4];
u32 rsp3;
} sdmmc_t;
/*! SDMMC command. */
typedef struct _sdmmc_cmd_t
{
u16 cmd;
u32 arg;
u32 rsp_type;
u32 check_busy;
} sdmmc_cmd_t;
/*! SDMMC request. */
typedef struct _sdmmc_req_t
{
void *buf;
u32 blksize;
u32 num_sectors;
int is_write;
int is_multi_block;
int is_auto_cmd12;
} sdmmc_req_t;
int sdmmc_get_voltage(sdmmc_t *sdmmc);
u32 sdmmc_get_bus_width(sdmmc_t *sdmmc);
void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width);
void sdmmc_get_venclkctl(sdmmc_t *sdmmc);
int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type);
void sdmmc_sd_clock_ctrl(sdmmc_t *sdmmc, int no_sd);
int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type);
int sdmmc_config_tuning(sdmmc_t *sdmmc, u32 type, u32 cmd);
int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp);
int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int no_sd);
void sdmmc_end(sdmmc_t *sdmmc);
void sdmmc_init_cmd(sdmmc_cmd_t *cmdbuf, u16 cmd, u32 arg, u32 rsp_type, u32 check_busy);
int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out);
int sdmmc_enable_low_voltage(sdmmc_t *sdmmc);
#endif

132
source/storage/sdmmc_t210.h Normal file
View file

@ -0,0 +1,132 @@
/*
* Copyright (c) 2018 naehrwert
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SDMMC_T210_H_
#define _SDMMC_T210_H_
#include "../utils/types.h"
#define TEGRA_MMC_PWRCTL_SD_BUS_POWER 0x1
#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V1_8 0xA
#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_0 0xC
#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_3 0xE
#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_MASK 0xF1
#define TEGRA_MMC_HOSTCTL_1BIT 0x00
#define TEGRA_MMC_HOSTCTL_4BIT 0x02
#define TEGRA_MMC_HOSTCTL_8BIT 0x20
#define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_ENABLE 0x1
#define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_STABLE 0x2
#define TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE 0x4
#define TEGRA_MMC_CLKCON_CLKGEN_SELECT 0x20
#define TEGRA_MMC_SWRST_SW_RESET_FOR_ALL 0x1
#define TEGRA_MMC_SWRST_SW_RESET_FOR_CMD_LINE 0x2
#define TEGRA_MMC_SWRST_SW_RESET_FOR_DAT_LINE 0x4
#define TEGRA_MMC_TRNMOD_DMA_ENABLE 0x1
#define TEGRA_MMC_TRNMOD_BLOCK_COUNT_ENABLE 0x2
#define TEGRA_MMC_TRNMOD_AUTO_CMD12 0x4
#define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_WRITE 0x0
#define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ 0x10
#define TEGRA_MMC_TRNMOD_MULTI_BLOCK_SELECT 0x20
#define TEGRA_MMC_TRNMOD_CMD_CRC_CHECK 0x8
#define TEGRA_MMC_TRNMOD_CMD_INDEX_CHECK 0x10
#define TEGRA_MMC_TRNMOD_DATA_PRESENT_SELECT_DATA_TRANSFER 0x20
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_MASK 0x3
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_NO_RESPONSE 0x0
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_136 0x1
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48 0x2
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48_BUSY 0x3
#define TEGRA_MMC_NORINTSTS_CMD_COMPLETE 0x1
#define TEGRA_MMC_NORINTSTS_XFER_COMPLETE 0x2
#define TEGRA_MMC_NORINTSTS_DMA_INTERRUPT 0x8
#define TEGRA_MMC_NORINTSTS_ERR_INTERRUPT 0x8000
#define TEGRA_MMC_NORINTSTS_CMD_TIMEOUT 0x10000
#define TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY 0x20
typedef struct _t210_sdmmc_t
{
vu32 sysad;
vu16 blksize;
vu16 blkcnt;
vu32 argument;
vu16 trnmod;
vu16 cmdreg;
vu32 rspreg0;
vu32 rspreg1;
vu32 rspreg2;
vu32 rspreg3;
vu32 bdata;
vu32 prnsts;
vu8 hostctl;
vu8 pwrcon;
vu8 blkgap;
vu8 wakcon;
vu16 clkcon;
vu8 timeoutcon;
vu8 swrst;
vu16 norintsts;
vu16 errintsts;
vu16 norintstsen;
vu16 errintstsen;
vu16 norintsigen;
vu16 errintsigen;
vu16 acmd12errsts;
vu16 hostctl2;
vu32 capareg;
vu32 capareg_1;
vu32 maxcurr;
vu8 res3[4];
vu16 setacmd12err;
vu16 setinterr;
vu8 admaerr;
vu8 res4[3];
vu32 admaaddr;
vu32 admaaddr_hi;
vu8 res5[156];
vu16 slotintstatus;
vu16 hcver;
vu32 venclkctl;
vu32 venspictl;
vu32 venspiintsts;
vu32 venceatactl;
vu32 venbootctl;
vu32 venbootacktout;
vu32 venbootdattout;
vu32 vendebouncecnt;
vu32 venmiscctl;
vu32 res6[34];
vu32 field_1AC;
vu32 field_1B0;
vu8 res7[8];
vu32 field_1BC;
vu32 field_1C0;
vu32 field_1C4;
vu8 field_1C8[24];
vu32 sdmemcmppadctl;
vu32 autocalcfg;
vu32 autocalintval;
vu32 autocalsts;
vu32 field_1F0;
} t210_sdmmc_t;
#endif