github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/soc/nxp/usdhc/mmc.go (about) 1 // NXP Ultra Secured Digital Host Controller (uSDHC) driver 2 // https://github.com/usbarmory/tamago 3 // 4 // IP: https://www.mobiveil.com/esdhc/ 5 // 6 // Copyright (c) WithSecure Corporation 7 // https://foundry.withsecure.com 8 // 9 // Use of this source code is governed by the license 10 // that can be found in the LICENSE file. 11 12 package usdhc 13 14 import ( 15 "encoding/binary" 16 "errors" 17 "fmt" 18 "time" 19 20 "github.com/usbarmory/tamago/bits" 21 "github.com/usbarmory/tamago/internal/reg" 22 ) 23 24 // MMC registers 25 const ( 26 // p181, 7.1 OCR register, JESD84-B51 27 MMC_OCR_BUSY = 31 28 MMC_OCR_ACCESS_MODE = 29 29 MMC_OCR_VDD_HV_MAX = 23 30 MMC_OCR_VDD_HV_MIN = 15 31 MMC_OCR_VDD_LV = 7 32 33 ACCESS_MODE_BYTE = 0b00 34 ACCESS_MODE_SECTOR = 0b10 35 36 // p62, 6.6.1 Command sets and extended settings, JESD84-B51 37 MMC_SWITCH_ACCESS = 24 38 MMC_SWITCH_INDEX = 16 39 MMC_SWITCH_VALUE = 8 40 MMC_SWITCH_CMD_SET = 0 41 42 ACCESS_WRITE_BYTE = 0b11 43 44 // p184 7.3 CSD register, JESD84-B51 45 MMC_CSD_SPEC_VERS = 122 + CSD_RSP_OFF 46 MMC_CSD_TRAN_SPEED = 96 + CSD_RSP_OFF 47 MMC_CSD_READ_BL_LEN = 80 + CSD_RSP_OFF 48 MMC_CSD_C_SIZE = 62 + CSD_RSP_OFF 49 MMC_CSD_C_SIZE_MULT = 47 + CSD_RSP_OFF 50 51 // p186 TRAN_SPEED [103:96], JESD84-B51 52 TRAN_SPEED_26MHZ = 0x32 53 54 // p193, 7.4 Extended CSD register, JESD84-B51 55 EXT_CSD_SEC_COUNT = 212 56 EXT_CSD_DEVICE_TYPE = 196 57 EXT_CSD_HS_TIMING = 185 58 EXT_CSD_BUS_WIDTH = 183 59 EXT_CSD_PARTITION_CONFIG = 179 60 61 // p224, PARTITION_CONFIG, JESD84-B51 62 PARTITION_ACCESS_NONE = 0x0 63 PARTITION_ACCESS_RPMB = 0x3 64 65 // p222, 7.4.65 HS_TIMING [185], JESD84-B51 66 HS_TIMING_HS = 0x1 67 HS_TIMING_HS200 = 0x2 68 69 // p35, 5.3.2 Bus Speed Modes, JESD84-B51 70 HSSDR_MBPS = 52 71 HSDDR_MBPS = 104 72 HS200_MBPS = 150 // instead of 200 due to NXP ERR010450 73 74 // PLL2 PFD2 clock divided by 2 75 ROOTCLK_HS_DDR = 1 76 // Root clock frequency: 396 MHz / (1 + 1) = 198 MHz 77 78 // PLL2 PFD2 clock divided by 3 79 ROOTCLK_HS200 = 2 // instead of 1 due to NXP ERR010450 80 // Root clock frequency: 396 MHz / (1 + 2) = 132 MHz 81 82 // Root clock divided by 1 (Single Data Rate mode) 83 SDCLKFS_HS200 = 0 84 // HS200 frequency: 132 / (1 * 1) == 132 MHz 85 86 ) 87 88 // MMC constants 89 const ( 90 MMC_DETECT_TIMEOUT = 1 * time.Second 91 MMC_DEFAULT_BLOCK_SIZE = 512 92 ) 93 94 // p352, 35.4.6 MMC voltage validation flow chart, IMX6FG 95 func (hw *USDHC) voltageValidationMMC() bool { 96 var arg uint32 97 98 // CMD1 - SEND_OP_COND 99 // p57, 6.4.2 Access mode validation, JESD84-B51 100 101 // sector mode supported 102 bits.SetN(&arg, MMC_OCR_ACCESS_MODE, 0b11, ACCESS_MODE_SECTOR) 103 // set HV range 104 bits.SetN(&arg, MMC_OCR_VDD_HV_MIN, 0x1ff, 0x1ff) 105 106 // p46, 6.3.1 Device reset to Pre-idle state, JESD84-B51 107 time.Sleep(1 * time.Millisecond) 108 109 start := time.Now() 110 111 for time.Since(start) <= MMC_DETECT_TIMEOUT { 112 // CMD1 - SEND_OP_COND - send operating conditions 113 if err := hw.cmd(1, arg, 0, 0); err != nil { 114 break 115 } 116 117 rsp := hw.rsp(0) 118 119 if bits.Get(&rsp, MMC_OCR_BUSY, 1) == 0 { 120 continue 121 } 122 123 if bits.Get(&rsp, MMC_OCR_ACCESS_MODE, 0b11) == ACCESS_MODE_SECTOR { 124 hw.card.HC = true 125 } 126 127 hw.card.MMC = true 128 129 break 130 } 131 132 return hw.card.MMC 133 } 134 135 func (hw *USDHC) writeCardRegisterMMC(reg uint32, val uint32) (err error) { 136 var arg uint32 137 138 // write MMC_SWITCH_VALUE in register pointed in MMC_SWITCH_INDEX 139 bits.SetN(&arg, MMC_SWITCH_ACCESS, 0b11, ACCESS_WRITE_BYTE) 140 // set MMC_SWITCH_INDEX to desired register 141 bits.SetN(&arg, MMC_SWITCH_INDEX, 0xff, reg) 142 // set register value 143 bits.SetN(&arg, MMC_SWITCH_VALUE, 0xff, val) 144 145 // CMD6 - SWITCH - switch mode of operation 146 err = hw.cmd(6, arg, 0, 0) 147 148 if err != nil { 149 return 150 } 151 152 // We could use EXT_CSD[GENERIC_CMD6_TIME] for a better tran state 153 // timeout, we rather choose to apply a generic timeout for now (as 154 // most drivers do). 155 err = hw.waitState(CURRENT_STATE_TRAN, 500*time.Millisecond) 156 157 if err != nil { 158 return 159 } 160 161 if (hw.rsp(0)>>STATUS_SWITCH_ERROR)&1 != 0 { 162 err = errors.New("switch error") 163 } 164 165 return 166 } 167 168 func (hw *USDHC) detectCapabilitiesMMC(c_size_mult uint32, c_size uint32, read_bl_len uint32) (err error) { 169 extCSD := make([]byte, MMC_DEFAULT_BLOCK_SIZE) 170 171 // CMD8 - SEND_EXT_CSD - read extended device data 172 if err = hw.transfer(8, READ, 0, 1, MMC_DEFAULT_BLOCK_SIZE, extCSD); err != nil { 173 return 174 } 175 176 // p128, Table 39 — e•MMC internal sizes and related Units / Granularities, JESD84-B51 177 178 // density greater than 2GB (emulation mode is always assumed) 179 if c_size > 0xff { 180 hw.card.BlockSize = MMC_DEFAULT_BLOCK_SIZE 181 hw.card.Blocks = int(binary.LittleEndian.Uint32(extCSD[EXT_CSD_SEC_COUNT:])) 182 } else { 183 // p188, 7.3.12 C_SIZE [73:62], JESD84-B51 184 hw.card.BlockSize = 2 << (read_bl_len - 1) 185 hw.card.Blocks = int((c_size + 1) * (2 << (c_size_mult + 2))) 186 } 187 188 // p220, Table 137 — Device types, JESD84-B51 189 deviceType := extCSD[EXT_CSD_DEVICE_TYPE] 190 191 if (deviceType>>4)&0b11 > 0 && hw.LowVoltage != nil && hw.LowVoltage(false) { 192 hw.card.Rate = HS200_MBPS 193 } else if (deviceType>>2)&0b11 > 0 { 194 hw.card.Rate = HSDDR_MBPS 195 } else if deviceType&0b11 > 0 { 196 hw.card.Rate = HSSDR_MBPS 197 } 198 199 return 200 } 201 202 func (hw *USDHC) executeTuningMMC() error { 203 reg.SetN(hw.vend_spec2, VEND_SPEC2_TUNING_8bit_EN, 1, 1) 204 return hw.executeTuning(21, 128) 205 } 206 207 // p352, 35.4.7 MMC card initialization flow chart, IMX6FG 208 // p58, 6.4.4 Device identification process, JESD84-B51 209 func (hw *USDHC) initMMC() (err error) { 210 var arg uint32 211 var bus_width uint32 212 var timing uint32 213 var root_clk uint32 214 var clk int 215 var ddr bool 216 var tune bool 217 218 // CMD2 - ALL_SEND_CID - get unique card identification 219 if err = hw.cmd(2, arg, 0, 0); err != nil { 220 return 221 } 222 223 for i := 0; i < len(hw.card.CID); i += 4 { 224 binary.LittleEndian.PutUint32(hw.card.CID[i:], hw.rsp(i/4)) 225 } 226 227 // Send CMD3 with a chosen RCA, with value greater than 1, 228 // p301, A.6.1 Bus initialization , JESD84-B51. 229 hw.rca = (uint32(hw.Index) + 1) << RCA_ADDR 230 231 // CMD3 - SET_RELATIVE_ADDR - set relative card address (RCA), 232 if err = hw.cmd(3, hw.rca, 0, 0); err != nil { 233 return 234 } 235 236 if state := (hw.rsp(0) >> STATUS_CURRENT_STATE) & 0b1111; state != CURRENT_STATE_IDENT { 237 return fmt.Errorf("card not in ident state (%d)", state) 238 } 239 240 // CMD9 - SEND_CSD - read device data 241 if err = hw.cmd(9, hw.rca, 0, 0); err != nil { 242 return 243 } 244 245 // block count multiplier 246 c_size_mult := hw.rspVal(MMC_CSD_C_SIZE_MULT, 0b111) 247 // block count 248 c_size := hw.rspVal(MMC_CSD_C_SIZE, 0xfff) 249 // block size 250 read_bl_len := hw.rspVal(MMC_CSD_READ_BL_LEN, 0xf) 251 // operating frequency 252 mhz := hw.rspVal(MMC_CSD_TRAN_SPEED, 0xff) 253 // e•MMC specification version 254 ver := hw.rspVal(MMC_CSD_SPEC_VERS, 0xf) 255 256 if mhz == TRAN_SPEED_26MHZ { 257 // clear clock 258 hw.setFreq(-1, -1) 259 // set operating frequency 260 hw.setFreq(DVS_OP, SDCLKFS_OP) 261 } else { 262 return fmt.Errorf("unexpected TRAN_SPEED %#x", mhz) 263 } 264 265 // CMD7 - SELECT/DESELECT CARD - enter transfer state 266 if err = hw.cmd(7, hw.rca, 0, 0); err != nil { 267 return 268 } 269 270 err = hw.waitState(CURRENT_STATE_TRAN, 1*time.Millisecond) 271 272 if err != nil { 273 return 274 } 275 276 // p223, 7.4.67 BUS_WIDTH [183], JESD84-B51 277 switch hw.width { 278 case 4: 279 bus_width = 1 280 case 8: 281 bus_width = 2 282 default: 283 return errors.New("unsupported MMC bus width") 284 } 285 286 err = hw.writeCardRegisterMMC(EXT_CSD_BUS_WIDTH, bus_width) 287 288 if err != nil { 289 return 290 } 291 292 err = hw.detectCapabilitiesMMC(c_size_mult, c_size, read_bl_len) 293 294 if err != nil { 295 return 296 } 297 298 // Enable High Speed DDR mode only on Version 4.1 or above eMMC cards 299 // with supported rate. 300 if ver < 4 || hw.card.Rate <= HSSDR_MBPS { 301 return 302 } 303 304 switch hw.card.Rate { 305 case HSDDR_MBPS: 306 timing = HS_TIMING_HS 307 root_clk = ROOTCLK_HS_DDR 308 clk = SDCLKFS_HS_DDR 309 ddr = true 310 311 // p223, 7.4.67 BUS_WIDTH [183], JESD84-B51 312 switch hw.width { 313 case 4: 314 bus_width = 5 315 case 8: 316 bus_width = 6 317 } 318 case HS200_MBPS: 319 timing = HS_TIMING_HS200 320 root_clk = ROOTCLK_HS200 321 clk = SDCLKFS_HS200 322 tune = true 323 default: 324 return 325 } 326 327 // p112, Dual Data Rate mode operation, JESD84-B51 328 err = hw.writeCardRegisterMMC(EXT_CSD_HS_TIMING, timing) 329 330 if err != nil { 331 return 332 } 333 334 err = hw.writeCardRegisterMMC(EXT_CSD_BUS_WIDTH, bus_width) 335 336 if err != nil { 337 return 338 } 339 340 hw.setFreq(-1, -1) 341 hw.SetClock(hw.Index, root_clk, 0) 342 hw.setFreq(DVS_HS, clk) 343 344 if tune { 345 // FIXME: Use fixed sampling clock as eMMC tuning fails for unknown reasons. 346 // err = hw.executeTuningMMC() 347 } 348 349 hw.card.DDR = ddr 350 hw.card.HS = true 351 352 return 353 } 354 355 // p224, 7.4.69 PARTITION_CONFIG [179], JESD84-B51 356 func (hw *USDHC) partitionAccessMMC(access uint32) (err error) { 357 return hw.writeCardRegisterMMC(EXT_CSD_PARTITION_CONFIG, access) 358 } 359 360 // p106, 6.6.22.4.3 Authenticated Data Write, JESD84-B51 361 // p108, 6.6.22.4.4 Authenticated Data Read, JESD84-B51 362 func (hw *USDHC) transferRPMB(dtd int, buf []byte, rel bool) (err error) { 363 if !hw.card.MMC { 364 return fmt.Errorf("no MMC card detected on uSDHC%d", hw.Index) 365 } 366 367 if len(buf) != 512 { 368 return errors.New("transfer size must be 512") 369 } 370 371 blocks := uint32(1) 372 373 hw.Lock() 374 hw.rpmb = true 375 376 defer func() { 377 hw.rpmb = false 378 hw.Unlock() 379 }() 380 381 if dtd == WRITE { 382 if rel { 383 // reliable write request 384 bits.Set(&blocks, 31) 385 } 386 387 // CMD25 - WRITE_MULTIPLE_BLOCK - write consecutive blocks 388 err = hw.transfer(25, WRITE, 0, blocks, 512, buf) 389 } else { 390 // CMD18 - READ_MULTIPLE_BLOCK - read consecutive blocks 391 err = hw.transfer(18, READ, 0, blocks, 512, buf) 392 } 393 394 return 395 } 396 397 // WriteRPMB transfers a single Replay Protected Memory Block (RPMB) data frame 398 // to the card. The `rel` boolean indicates whether a reliable write should be 399 // requested (required for some RPMB transfer). 400 func (hw *USDHC) WriteRPMB(buf []byte, rel bool) (err error) { 401 return hw.transferRPMB(WRITE, buf, rel) 402 } 403 404 // ReadRPMB transfers a single Replay Protected Memory Block (RPMB) data 405 // frame from the card. 406 func (hw *USDHC) ReadRPMB(buf []byte) (err error) { 407 return hw.transferRPMB(READ, buf, false) 408 }