usdhc

package
v0.0.0-...-d73fcdd Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 7, 2022 License: BSD-3-Clause Imports: 10 Imported by: 0

Documentation

Overview

Package usdhc implements a driver for Freescale Enhanced Secure Digital Host Controller (eSDHC) interface, also known as NXP Ultra Secured Digital Host Controller (uSDHC).

It currently supports interfacing with SD/MMC cards up to High Speed mode and Dual Data Rate.

Higher speed modes for eMMC cards are HS200 (controller supported and driver supported) and HS400 mode (unsupported at controller level) [p35, Table 4, JESD84-B51].

Higher speed modes for SD cards are SDR50/SDR104 (controller and driver supported), DDR50 (controller supported, unimplemented in this driver) and UHS-II modes (unsupported at controller level) [p37-38, Figure 3-14 and 3-15, SD-PL-7.10].

The highest speed supported by the driver, card and controller is automatically selected by Detect().

For eMMC cards, speed mode HS200 requires the target board to have eMMC I/O signaling to 1.8V, this must be advertised by the board package by defining LowVoltage() on the relevant USDHC instance.

For SD cards, speed modes SDR50/SDR104 require the target board to switch SD I/O signaling to 1.8V, the switching procedure must be implemented by the board package by defining LowVoltage() on the relevant USDHC instance.

Note that due to NXP errata ERR010450 the following maximum theoretical limits apply:

  • eMMC HS200: 150MB/s - 150MHz (instead of 200MB/s - 200MHz), supported
  • eMMC DDR52: 90MB/s - 45MHz (instead of 104MB/s - 52MHz), supported
  • SD SDR104: 75MB/s - 150MHz (instead of 104MB/s - 208MHz), supported
  • SD DDR50: 45MB/s - 45MHz (instead of 50MB/s - 50MHz), unsupported

This package is only meant to be used with `GOOS=tamago GOARCH=arm` as supported by the TamaGo framework for bare metal Go on ARM SoCs, see https://github.com/f-secure-foundry/tamago.

Index

Constants

View Source
const (
	ATTR_VALID = 0
	ATTR_END   = 1
	ATTR_INT   = 2
	ATTR_ACT   = 4

	ACT_TRANSFER = 0b10
	ACT_LINK     = 0b11

	DMASEL_NONE  = 0b00
	DMASEL_ADMA1 = 0b01
	DMASEL_ADMA2 = 0b10

	ADMA_BD_MAX_LENGTH = 65532
)

ADMA constants

View Source
const (
	GO_IDLE_STATE = 0

	// p127, 4.9.5 (Published RCA response), SD-PL-7.10
	RCA_ADDR   = 16
	RCA_STATUS = 0

	// p131, Table 4-42 : Card Status, SD-PL-7.10
	// p160, Table 68 - Device Status, JESD84-B51
	STATUS_CURRENT_STATE = 9
	STATUS_SWITCH_ERROR  = 7
	STATUS_APP_CMD       = 5
	CURRENT_STATE_IDENT  = 2
	CURRENT_STATE_TRAN   = 4

	// data transfer direction
	WRITE = 0
	READ  = 1

	// response types
	RSP_NONE          = 0b00
	RSP_136           = 0b01
	RSP_48            = 0b10
	RSP_48_CHECK_BUSY = 0b11

	// SEND_CSD response contains CSD[127:8],
	CSD_RSP_OFF = -8

	DEFAULT_CMD_TIMEOUT = 10 * time.Millisecond
)

CMD constants

View Source
const (
	// p181, 7.1 OCR register, JESD84-B51
	MMC_OCR_BUSY        = 31
	MMC_OCR_ACCESS_MODE = 29
	MMC_OCR_VDD_HV_MAX  = 23
	MMC_OCR_VDD_HV_MIN  = 15
	MMC_OCR_VDD_LV      = 7

	ACCESS_MODE_BYTE   = 0b00
	ACCESS_MODE_SECTOR = 0b10

	// p62, 6.6.1 Command sets and extended settings, JESD84-B51
	MMC_SWITCH_ACCESS  = 24
	MMC_SWITCH_INDEX   = 16
	MMC_SWITCH_VALUE   = 8
	MMC_SWITCH_CMD_SET = 0

	ACCESS_WRITE_BYTE = 0b11

	// p184 7.3 CSD register, JESD84-B51
	MMC_CSD_SPEC_VERS   = 122 + CSD_RSP_OFF
	MMC_CSD_TRAN_SPEED  = 96 + CSD_RSP_OFF
	MMC_CSD_READ_BL_LEN = 80 + CSD_RSP_OFF
	MMC_CSD_C_SIZE      = 62 + CSD_RSP_OFF
	MMC_CSD_C_SIZE_MULT = 47 + CSD_RSP_OFF

	// p186 TRAN_SPEED [103:96], JESD84-B51
	TRAN_SPEED_26MHZ = 0x32

	// p193, 7.4 Extended CSD register, JESD84-B51
	EXT_CSD_SEC_COUNT        = 212
	EXT_CSD_DEVICE_TYPE      = 196
	EXT_CSD_HS_TIMING        = 185
	EXT_CSD_BUS_WIDTH        = 183
	EXT_CSD_PARTITION_CONFIG = 179

	// p224, PARTITION_CONFIG, JESD84-B51
	PARTITION_ACCESS_NONE = 0x0
	PARTITION_ACCESS_RPMB = 0x3

	// p222, 7.4.65 HS_TIMING [185], JESD84-B51
	HS_TIMING_HS    = 0x1
	HS_TIMING_HS200 = 0x2

	// p35, 5.3.2 Bus Speed Modes, JESD84-B51
	HSSDR_MBPS = 52
	HSDDR_MBPS = 104
	HS200_MBPS = 150 // instead of 200 due to NXP ERR010450

	// PLL2 PFD2 clock divided by 2
	ROOTCLK_HS_DDR = 1

	// PLL2 PFD2 clock divided by 3
	ROOTCLK_HS200 = 2 // instead of 1 due to NXP ERR010450

	// Root clock divided by 1 (Single Data Rate mode)
	SDCLKFS_HS200 = 0
)

MMC registers

View Source
const (
	MMC_DETECT_TIMEOUT     = 1 * time.Second
	MMC_DEFAULT_BLOCK_SIZE = 512
)

MMC constants

View Source
const (
	// p101, 4.3.13 Send Interface Condition Command (CMD8), SD-PL-7.10
	CMD8_ARG_VHS           = 8
	CMD8_ARG_CHECK_PATTERN = 0

	VHS_HIGH      = 0b0001
	VHS_LOW       = 0b0010
	CHECK_PATTERN = 0b10101010

	// p59, 4.2.3.1 Initialization Command (ACMD41), SD-PL-7.10
	// p198, 5.1 OCR register, SD-PL-7.10
	SD_OCR_BUSY       = 31
	SD_OCR_HCS        = 30
	SD_OCR_UHSII      = 29
	SD_OCR_XPC        = 28
	SD_OCR_S18R       = 24
	SD_OCR_VDD_HV_MAX = 23
	SD_OCR_VDD_HV_MIN = 15
	SD_OCR_VDD_LV     = 7

	// p120, Table 4-32 : Switch Function Commands (class 10), SD-PL-7.10
	SD_SWITCH_MODE = 31
	// p92, Table 4-11 : Available Functions of CMD6, SD-PL-7.10
	SD_SWITCH_POWER_LIMIT_GROUP = 4
	SD_SWITCH_ACCESS_MODE_GROUP = 1
	// p95, 4.3.10.4 Switch Function Status, SD-PL-7.10
	SD_SWITCH_STATUS_LENGTH = 64

	// p89, 4.3.10 Switch Function Command, SD-PL-7.10
	MODE_CHECK         = 0
	MODE_SWITCH        = 1
	ACCESS_MODE_HS     = 0x1
	ACCESS_MODE_SDR50  = 0x2
	ACCESS_MODE_SDR104 = 0x3
	POWER_LIMIT_288W   = 0x3

	// p201 5.3.1 CSD_STRUCTURE, SD-PL-7.10
	SD_CSD_STRUCTURE = 126 + CSD_RSP_OFF

	// p202 5.3.2 CSD Register (CSD Version 1.0), SD-PL-7.10
	SD_CSD_C_SIZE_MULT_1 = 47 + CSD_RSP_OFF
	SD_CSD_C_SIZE_1      = 62 + CSD_RSP_OFF
	SD_CSD_READ_BL_LEN_1 = 80 + CSD_RSP_OFF

	// p209 5.3.3 CSD Register (CSD Version 2.0), SD-PL-7.10
	SD_CSD_C_SIZE_2      = 48 + CSD_RSP_OFF
	SD_CSD_READ_BL_LEN_2 = 80 + CSD_RSP_OFF

	// p212 5.3.4 CSD Register (CSD Version 3.0), SD-PL-7.10
	SD_CSD_C_SIZE_3      = 48 + CSD_RSP_OFF
	SD_CSD_READ_BL_LEN_3 = 80 + CSD_RSP_OFF

	// p23, 2. System Features, SD-PL-7.10
	HS_MBPS     = 25
	SDR50_MBPS  = 50
	SDR104_MBPS = 75 // instead of 104 due to NXP ERR010450

	// PLL2 PFD2 clock divided by 2
	ROOTCLK_UHS_SDR50 = 1

	// PLL2 PFD2 clock divided by 3
	ROOTCLK_UHS_SDR104 = 2 // instead of 1 due to NXP ERR010450

	// Root clock divided by 2 (Single Data Rate mode)
	SDCLKFS_UHS_SDR50 = 0x01

	// Root clock divided by 1 (Single Data Rate mode)
	SDCLKFS_UHS_SDR104 = 0
)

SD registers

View Source
const (
	SD_DETECT_TIMEOUT     = 1 * time.Second
	SD_DEFAULT_BLOCK_SIZE = 512

	// Tuning should complete in max 40 cycles
	// p42, 4.2.4.5 Tuning Command, SD-PL-7.10
	TUNING_MAX_LOOP_COUNT = 40

	// The following values are set to make the standard tuning logic
	// complete in less then 40 cycles.
	TUNING_STEP      = 2
	TUNING_START_TAP = 20
)

SD constants

View Source
const (
	USDHC1_BASE = 0x02190000
	USDHC2_BASE = 0x02194000

	USDHCx_BLK_ATT  = 0x04
	BLK_ATT_BLKCNT  = 16
	BLK_ATT_BLKSIZE = 0

	USDHCx_CMD_ARG = 0x08

	USDHCx_CMD_XFR_TYP = 0x0c
	CMD_XFR_TYP_CMDINX = 24
	CMD_XFR_TYP_CMDTYP = 22
	CMD_XFR_TYP_DPSEL  = 21
	CMD_XFR_TYP_CICEN  = 20
	CMD_XFR_TYP_CCCEN  = 19
	CMD_XFR_TYP_RSPTYP = 16

	USDHCx_CMD_RSP0 = 0x10
	USDHCx_CMD_RSP1 = 0x14
	USDHCx_CMD_RSP2 = 0x18
	USDHCx_CMD_RSP3 = 0x1c

	USDHCx_PRES_STATE = 0x24
	PRES_STATE_DLSL   = 24
	PRES_STATE_WPSPL  = 19
	PRES_STATE_BREN   = 11
	PRES_STATE_SDSTB  = 3
	PRES_STATE_CDIHB  = 1
	PRES_STATE_CIHB   = 0

	USDHCx_PROT_CTRL = 0x28
	PROT_CTRL_DMASEL = 8
	PROT_CTRL_EMODE  = 4
	PROT_CTRL_DTW    = 1

	USDHCx_SYS_CTRL  = 0x2c
	SYS_CTRL_INITA   = 27
	SYS_CTRL_RSTD    = 26
	SYS_CTRL_RSTC    = 25
	SYS_CTRL_RSTA    = 24
	SYS_CTRL_DTOCV   = 16
	SYS_CTRL_SDCLKFS = 8
	SYS_CTRL_DVS     = 4

	USDHCx_INT_STATUS = 0x30
	INT_STATUS_DMAE   = 28
	INT_STATUS_TNE    = 26
	INT_STATUS_AC12E  = 24
	INT_STATUS_CIE    = 19
	INT_STATUS_CEBE   = 18
	INT_STATUS_CCE    = 17
	INT_STATUS_CTOE   = 16
	INT_STATUS_CRM    = 7
	INT_STATUS_BRR    = 5
	INT_STATUS_TC     = 1
	INT_STATUS_CC     = 0

	USDHCx_INT_STATUS_EN  = 0x34
	INT_STATUS_EN_DTOESEN = 20
	INT_STATUS_EN_BWRSEN  = 4

	USDHCx_INT_SIGNAL_EN = 0x38
	INT_SIGNAL_EN_BWRIEN = 4

	USDHCx_AUTOCMD12_ERR_STATUS      = 0x3c
	AUTOCMD12_ERR_STATUS_SMP_CLK_SEL = 23
	AUTOCMD12_ERR_STATUS_EXE_TUNE    = 22

	USDHCx_WTMK_LVL = 0x44
	WTMK_LVL_WR_WML = 16
	WTMK_LVL_RD_WML = 0

	USDHCx_MIX_CTRL       = 0x48
	MIX_CTRL_FBCLK_SEL    = 25
	MIX_CTRL_AUTO_TUNE_EN = 24
	MIX_CTRL_SMP_CLK_SEL  = 23
	MIX_CTRL_EXE_TUNE     = 22
	MIX_CTRL_MSBSEL       = 5
	MIX_CTRL_DTDSEL       = 4
	MIX_CTRL_DDR_EN       = 3
	MIX_CTRL_AC12EN       = 2
	MIX_CTRL_BCEN         = 1
	MIX_CTRL_DMAEN        = 0

	USDHCx_ADMA_ERR_STATUS = 0x54
	USDHCx_ADMA_SYS_ADDR   = 0x58

	USDHCx_VEND_SPEC       = 0xc0
	VEND_SPEC_FRC_SDCLK_ON = 8
	VEND_SPEC_VSELECT      = 1

	USDHCx_VEND_SPEC2         = 0xc8
	VEND_SPEC2_TUNING_1bit_EN = 5
	VEND_SPEC2_TUNING_8bit_EN = 4

	USDHCx_TUNING_CTRL           = 0xcc
	TUNING_CTRL_STD_TUNING_EN    = 24
	TUNING_CTRL_TUNING_STEP      = 16
	TUNING_CTRL_TUNING_START_TAP = 0
)

USDHC registers (p4012, 58.8 uSDHC Memory Map/Register Definition, IMX6ULLRM).

View Source
const (

	// Data Timeout Counter Value: SDCLK x 2** 29
	DTOCV = 0xf

	// Divide-by-8
	DVS_ID = 7
	// Root clock divided by 64
	SDCLKFS_ID = 0x20

	// Divide-by-2
	DVS_OP = 1
	// Root clock divided by 4
	SDCLKFS_OP = 0x02

	// PLL2 PFD2 clock divided by 2
	ROOTCLK_HS_SDR = 1

	// Divide-by-1
	DVS_HS = 0
	// Root clock divided by 4 (Single Data Rate mode)
	SDCLKFS_HS_SDR = 0x02
	// Root clock divided by 4 (Dual Data Rate mode)
	SDCLKFS_HS_DDR = 0x01
)

Configuration constants (p348, 35.4.2 Frequency divider configuration, IMX6FG) to support the following frequencies:

  • Identification frequency ≤ 400 KHz
  • Operating frequency ≤ 25 MHz
  • High frequency ≤ 50 MHz

Variables

View Source
var USDHC1 = &USDHC{n: 1}

USDHC1 instance

View Source
var USDHC2 = &USDHC{n: 2}

USDHC2 instance

Functions

This section is empty.

Types

type ADMABufferDescriptor

type ADMABufferDescriptor struct {
	Attribute uint8

	Length  uint16
	Address uint32
	// contains filtered or unexported fields
}

ADMABufferDescriptor implements p3964 58.4.2.4.1 ADMA Concept and Descriptor Format, IMX6ULLRM.

func (*ADMABufferDescriptor) Bytes

func (bd *ADMABufferDescriptor) Bytes() []byte

Bytes converts the descriptor structure to byte array format.

func (*ADMABufferDescriptor) Init

func (bd *ADMABufferDescriptor) Init(addr uint32, size int)

Init initializes an ADMA2 buffer descriptor.

type CardInfo

type CardInfo struct {
	// eMMC card
	MMC bool
	// SD card
	SD bool
	// High Capacity
	HC bool
	// High Speed
	HS bool
	// Dual Data Rate
	DDR bool
	// Maximum throughput (on this controller)
	Rate int

	// Block Size
	BlockSize int
	// Capacity
	Blocks int

	// device identification number
	CID [16]byte
}

CardInfo holds detected card information.

type USDHC

type USDHC struct {
	sync.Mutex

	// LowVoltage is the board specific function responsible for voltage
	// switching (SD) or low voltage indication (eMMC).
	//
	// The return value reflects whether the voltage switch (SD) or
	// low voltage indication (MMC) is successful.
	LowVoltage func(enable bool) bool
	// contains filtered or unexported fields
}

USDHC represents a controller instance.

func (*USDHC) Detect

func (hw *USDHC) Detect() (err error)

Detect initializes an SD/MMC card. The highest speed supported by the driver, card and controller is automatically selected. Speed modes that require voltage switching require definition of function VoltageSelect on the USDHC instance, which is up to board packages.

func (*USDHC) Info

func (hw *USDHC) Info() CardInfo

Info returns detected card information.

func (*USDHC) Init

func (hw *USDHC) Init(width int)

Init initializes the uSDHC controller instance.

func (*USDHC) Read

func (hw *USDHC) Read(offset int64, size int64) (buf []byte, err error)

Read transfers data from the card.

func (*USDHC) ReadBlocks

func (hw *USDHC) ReadBlocks(lba int, buf []byte) (err error)

ReadBlocks transfers full blocks of data from the card.

func (*USDHC) ReadRPMB

func (hw *USDHC) ReadRPMB(buf []byte) (err error)

ReadRPMB transfers a single Replay Protected Memory Block (RPMB) data frame from the card.

func (*USDHC) WriteBlocks

func (hw *USDHC) WriteBlocks(lba int, buf []byte) (err error)

WriteBlocks transfers full blocks of data to the card.

func (*USDHC) WriteRPMB

func (hw *USDHC) WriteRPMB(buf []byte, rel bool) (err error)

WriteRPMB transfers a single Replay Protected Memory Block (RPMB) data frame to the card. The `rel` boolean indicates whether a reliable write should be requested (required for some RPMB transfer).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL