github.com/f-secure-foundry/tamago@v0.0.0-20220307101044-d73fcdd7f11b/soc/imx6/usdhc/sd.go (about) 1 // NXP Ultra Secured Digital Host Controller (uSDHC) driver 2 // https://github.com/f-secure-foundry/tamago 3 // 4 // IP: https://www.mobiveil.com/esdhc/ 5 // 6 // Copyright (c) F-Secure Corporation 7 // https://foundry.f-secure.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/f-secure-foundry/tamago/bits" 21 "github.com/f-secure-foundry/tamago/internal/reg" 22 ) 23 24 // SD registers 25 const ( 26 // p101, 4.3.13 Send Interface Condition Command (CMD8), SD-PL-7.10 27 CMD8_ARG_VHS = 8 28 CMD8_ARG_CHECK_PATTERN = 0 29 30 VHS_HIGH = 0b0001 31 VHS_LOW = 0b0010 32 CHECK_PATTERN = 0b10101010 33 34 // p59, 4.2.3.1 Initialization Command (ACMD41), SD-PL-7.10 35 // p198, 5.1 OCR register, SD-PL-7.10 36 SD_OCR_BUSY = 31 37 SD_OCR_HCS = 30 38 SD_OCR_UHSII = 29 39 SD_OCR_XPC = 28 40 SD_OCR_S18R = 24 41 SD_OCR_VDD_HV_MAX = 23 42 SD_OCR_VDD_HV_MIN = 15 43 SD_OCR_VDD_LV = 7 44 45 // p120, Table 4-32 : Switch Function Commands (class 10), SD-PL-7.10 46 SD_SWITCH_MODE = 31 47 // p92, Table 4-11 : Available Functions of CMD6, SD-PL-7.10 48 SD_SWITCH_POWER_LIMIT_GROUP = 4 49 SD_SWITCH_ACCESS_MODE_GROUP = 1 50 // p95, 4.3.10.4 Switch Function Status, SD-PL-7.10 51 SD_SWITCH_STATUS_LENGTH = 64 52 53 // p89, 4.3.10 Switch Function Command, SD-PL-7.10 54 MODE_CHECK = 0 55 MODE_SWITCH = 1 56 ACCESS_MODE_HS = 0x1 57 ACCESS_MODE_SDR50 = 0x2 58 ACCESS_MODE_SDR104 = 0x3 59 POWER_LIMIT_288W = 0x3 60 61 // p201 5.3.1 CSD_STRUCTURE, SD-PL-7.10 62 SD_CSD_STRUCTURE = 126 + CSD_RSP_OFF 63 64 // p202 5.3.2 CSD Register (CSD Version 1.0), SD-PL-7.10 65 SD_CSD_C_SIZE_MULT_1 = 47 + CSD_RSP_OFF 66 SD_CSD_C_SIZE_1 = 62 + CSD_RSP_OFF 67 SD_CSD_READ_BL_LEN_1 = 80 + CSD_RSP_OFF 68 69 // p209 5.3.3 CSD Register (CSD Version 2.0), SD-PL-7.10 70 SD_CSD_C_SIZE_2 = 48 + CSD_RSP_OFF 71 SD_CSD_READ_BL_LEN_2 = 80 + CSD_RSP_OFF 72 73 // p212 5.3.4 CSD Register (CSD Version 3.0), SD-PL-7.10 74 SD_CSD_C_SIZE_3 = 48 + CSD_RSP_OFF 75 SD_CSD_READ_BL_LEN_3 = 80 + CSD_RSP_OFF 76 77 // p23, 2. System Features, SD-PL-7.10 78 HS_MBPS = 25 79 SDR50_MBPS = 50 80 SDR104_MBPS = 75 // instead of 104 due to NXP ERR010450 81 82 // PLL2 PFD2 clock divided by 2 83 ROOTCLK_UHS_SDR50 = 1 84 // Root clock frequency: 396 MHz / (1 + 1) = 198 MHz 85 86 // PLL2 PFD2 clock divided by 3 87 ROOTCLK_UHS_SDR104 = 2 // instead of 1 due to NXP ERR010450 88 // Root clock frequency: 396 MHz / (1 + 2) = 132 MHz 89 90 // Root clock divided by 2 (Single Data Rate mode) 91 SDCLKFS_UHS_SDR50 = 0x01 92 // SDR50 frequency: 198 / (1 * 2) == 99 MHz 93 94 // Root clock divided by 1 (Single Data Rate mode) 95 SDCLKFS_UHS_SDR104 = 0 96 // SDR104 frequency: 132 / (1 * 1) == 132 MHz 97 ) 98 99 // SD constants 100 const ( 101 SD_DETECT_TIMEOUT = 1 * time.Second 102 SD_DEFAULT_BLOCK_SIZE = 512 103 104 // Tuning should complete in max 40 cycles 105 // p42, 4.2.4.5 Tuning Command, SD-PL-7.10 106 TUNING_MAX_LOOP_COUNT = 40 107 108 // The following values are set to make the standard tuning logic 109 // complete in less then 40 cycles. 110 TUNING_STEP = 2 111 TUNING_START_TAP = 20 112 ) 113 114 func (hw *USDHC) switchSD(mode uint32, group int, val uint32) (status []byte, err error) { 115 var arg uint32 116 117 // set `no influence` (0xf) for all function groups 118 arg = 0x00ffffff 119 // set mode check 120 bits.SetN(&arg, SD_SWITCH_MODE, 1, mode) 121 // set function group 122 bits.SetN(&arg, (group-1)*4, 0xf, val) 123 124 status = make([]byte, SD_SWITCH_STATUS_LENGTH) 125 126 // CMD6 - SWITCH - switch mode of operation 127 if err = hw.transfer(6, READ, uint64(arg), 1, SD_SWITCH_STATUS_LENGTH, status); err != nil { 128 return 129 } 130 131 err = hw.waitState(CURRENT_STATE_TRAN, 500*time.Millisecond) 132 133 if err != nil { 134 return 135 } 136 137 if (hw.rsp(0)>>STATUS_SWITCH_ERROR)&1 != 0 { 138 err = errors.New("switch error") 139 } 140 141 return 142 } 143 144 func (hw *USDHC) executeTuningSD() error { 145 return hw.executeTuning(19, 64) 146 } 147 148 // p350, 35.4.4 SD voltage validation flow chart, IMX6FG 149 func (hw *USDHC) voltageValidationSD() bool { 150 var arg uint32 151 var hv bool 152 153 // ensure 3.3V signaling 154 if hw.LowVoltage != nil { 155 hw.LowVoltage(false) 156 } 157 158 // CMD8 - SEND_IF_COND - read device data 159 // p101, 4.3.13 Send Interface Condition Command (CMD8), SD-PL-7.10 160 161 bits.SetN(&arg, CMD8_ARG_VHS, 0b1111, VHS_HIGH) 162 bits.SetN(&arg, CMD8_ARG_CHECK_PATTERN, 0xff, CHECK_PATTERN) 163 164 if hw.cmd(8, arg, 0, 0) == nil && hw.rsp(0) == arg { 165 // HC/LC HV SD 2.x 166 hw.card.HC = true 167 hv = true 168 } else { 169 arg = VHS_LOW<<CMD8_ARG_VHS | CHECK_PATTERN 170 171 if hw.cmd(8, arg, 0, 0) == nil && hw.rsp(0) == arg { 172 // LC SD 1.x 173 hw.card.HC = true 174 } else { 175 // LC SD 2.x 176 hv = true 177 } 178 } 179 180 // ACMD41 - SD_SEND_OP_COND - read capacity information 181 // p59, 4.2.3.1 Initialization Command (ACMD41), SD-PL-7.10 182 // 183 // The ACMD41 full argument is the OCR, despite the standard 184 // confusingly naming OCR only bits 23-08 of it (which instead 185 // represents part of OCR register voltage window). 186 arg = 0 187 188 if hw.card.HC { 189 // SDHC or SDXC supported 190 bits.Set(&arg, SD_OCR_HCS) 191 // Maximum Performance 192 bits.Set(&arg, SD_OCR_XPC) 193 // Switch to 1.8V (only check acceptance for speed detection) 194 bits.Set(&arg, SD_OCR_S18R) 195 } 196 197 if hv { 198 // set HV range 199 bits.SetN(&arg, SD_OCR_VDD_HV_MIN, 0x1ff, 0x1ff) 200 } else { 201 bits.Set(&arg, SD_OCR_VDD_LV) 202 } 203 204 start := time.Now() 205 206 for time.Since(start) <= SD_DETECT_TIMEOUT { 207 // CMD55 - APP_CMD - next command is application specific 208 if hw.cmd(55, 0, 0, 0) != nil { 209 break 210 } 211 212 // ACMD41 - SD_SEND_OP_COND - send operating conditions 213 if err := hw.cmd(41, arg, 0, 0); err != nil { 214 break 215 } 216 217 rsp := hw.rsp(0) 218 219 if bits.Get(&rsp, SD_OCR_BUSY, 1) == 0 { 220 continue 221 } 222 223 if bits.Get(&rsp, SD_OCR_HCS, 1) == 1 { 224 hw.card.HC = true 225 } 226 227 // Select the fastest mandatory speed mode, supported by this 228 // driver, according to the card type. 229 230 if bits.Get(&rsp, SD_OCR_S18R, 1) == 1 { 231 // UHS-I 232 hw.card.Rate = SDR50_MBPS 233 } else if bits.Get(&rsp, SD_OCR_UHSII, 1) == 1 { 234 // UHS-II 235 hw.card.Rate = SDR50_MBPS 236 } else { 237 // Non UHS-I 238 hw.card.Rate = HS_MBPS 239 } 240 241 hw.card.SD = true 242 243 break 244 } 245 246 return hw.card.SD 247 } 248 249 func (hw *USDHC) detectCapabilitiesSD() (err error) { 250 // CMD9 - SEND_CSD - read device data 251 if err = hw.cmd(9, hw.rca, 0, 0); err != nil { 252 return 253 } 254 255 ver := hw.rspVal(SD_CSD_STRUCTURE, 0b11) 256 257 switch ver { 258 case 0: 259 // CSD Version 1.0 260 c_size_mult := hw.rspVal(SD_CSD_C_SIZE_MULT_1, 0b111) 261 c_size := hw.rspVal(SD_CSD_C_SIZE_1, 0xfff) 262 read_bl_len := hw.rspVal(SD_CSD_READ_BL_LEN_1, 0xf) 263 264 // p205, C_SIZE, SD-PL-7.10 265 hw.card.BlockSize = 2 << (read_bl_len - 1) 266 hw.card.Blocks = int((c_size + 1) * (2 << (c_size_mult + 2))) 267 case 1: 268 // CSD Version 2.0 269 c_size := hw.rspVal(SD_CSD_C_SIZE_2, 0x3fffff) 270 read_bl_len := hw.rspVal(SD_CSD_READ_BL_LEN_2, 0xf) 271 272 // p210, C_SIZE, SD-PL-7.10 273 hw.card.BlockSize = 2 << (read_bl_len - 1) 274 hw.card.Blocks = int(c_size+1) * 1024 275 case 2: 276 // CSD Version 3.0 277 c_size := hw.rspVal(SD_CSD_C_SIZE_2, 0xfffffff) 278 read_bl_len := hw.rspVal(SD_CSD_READ_BL_LEN_2, 0xf) 279 280 // p213, C_SIZE, SD-PL-7.10 281 hw.card.BlockSize = 2 << (read_bl_len - 1) 282 hw.card.Blocks = int(c_size+1) * 1024 283 default: 284 return fmt.Errorf("unsupported CSD version %d", ver) 285 } 286 287 return 288 } 289 290 // p60, 4.2.4 Bus Signal Voltage Switch Sequence, SD-PL-7.10 291 func (hw *USDHC) voltageSwitchSD() (err error) { 292 // CMD11 - VOLTAGE_SWITCH - switch to 1.8V signaling 293 if err = hw.cmd(11, 0, 0, 0); err != nil { 294 return 295 } 296 297 if !reg.WaitFor(1*time.Millisecond, hw.pres_state, PRES_STATE_DLSL, 1, 0) { 298 return fmt.Errorf("voltage switch failed, invalid data line") 299 } 300 301 hw.setClock(-1, -1) 302 303 // SoC uSDHC IO power voltage selection signal (might be unused) 304 reg.Set(hw.vend_spec, VEND_SPEC_VSELECT) 305 306 // board specific low voltage selection/indication function 307 if hw.LowVoltage != nil && !hw.LowVoltage(true) { 308 return errors.New("voltage switch failed, not at LV") 309 } 310 311 time.Sleep(10 * time.Millisecond) 312 313 hw.setClock(DVS_OP, SDCLKFS_OP) 314 315 if !reg.WaitFor(1*time.Millisecond, hw.pres_state, PRES_STATE_DLSL, 1, 1) { 316 return fmt.Errorf("voltage switch failed, invalid data line") 317 } 318 319 return 320 } 321 322 // p351, 35.4.5 SD card initialization flow chart, IMX6FG 323 // p57, 4.2.3 Card Initialization and Identification Process, SD-PL-7.10 324 func (hw *USDHC) initSD() (err error) { 325 var arg uint32 326 var bus_width uint32 327 var mode uint32 328 var root_clk uint32 329 var clk int 330 var tune bool 331 332 if hw.LowVoltage == nil { 333 hw.card.Rate = HS_MBPS 334 } else if hw.card.Rate >= SDR50_MBPS { 335 if err = hw.voltageSwitchSD(); err != nil { 336 hw.card.Rate = HS_MBPS 337 } 338 } 339 340 // CMD2 - ALL_SEND_CID - get unique card identification 341 if err = hw.cmd(2, arg, 0, 0); err != nil { 342 return 343 } 344 345 for i := 0; i < len(hw.card.CID); i += 4 { 346 binary.LittleEndian.PutUint32(hw.card.CID[i:], hw.rsp(i/4)) 347 } 348 349 // CMD3 - SEND_RELATIVE_ADDR - get relative card address (RCA) 350 if err = hw.cmd(3, arg, 0, 0); err != nil { 351 return 352 } 353 354 if state := (hw.rsp(0) >> STATUS_CURRENT_STATE) & 0b1111; state != CURRENT_STATE_IDENT { 355 return fmt.Errorf("card not in ident state (%d)", state) 356 } 357 358 if hw.card.Rate == HS_MBPS { 359 hw.setClock(-1, -1) 360 hw.setClock(DVS_OP, SDCLKFS_OP) 361 } 362 363 // set relative card address 364 hw.rca = hw.rsp(0) & (0xffff << RCA_ADDR) 365 366 if err = hw.detectCapabilitiesSD(); err != nil { 367 return 368 } 369 370 // CMD7 - SELECT/DESELECT CARD - enter transfer state 371 if err = hw.cmd(7, hw.rca, 0, 0); err != nil { 372 return 373 } 374 375 if err = hw.waitState(CURRENT_STATE_TRAN, 1*time.Millisecond); err != nil { 376 return 377 } 378 379 // CMD55 - APP_CMD - next command is application specific 380 if err = hw.cmd(55, hw.rca, 0, 0); err != nil { 381 return 382 } 383 384 if ((hw.rsp(0) >> STATUS_APP_CMD) & 1) != 1 { 385 return fmt.Errorf("card not expecting application command") 386 } 387 388 // p118, Table 4-31, SD-PL-7.10 389 switch hw.width { 390 case 1: 391 bus_width = 0b00 392 case 4: 393 bus_width = 0b10 394 default: 395 return errors.New("unsupported SD bus width") 396 } 397 398 // ACMD6 - SET_BUS_WIDTH - define the card data bus width 399 if err = hw.cmd(6, uint32(bus_width), 0, 0); err != nil { 400 return 401 } 402 403 if hw.card.Rate >= SDR50_MBPS { 404 // Check support bits 415:400 for SDR104 mode, 405 // p96, 4.3.10.4 Switch Function Status, SD-PL-7.10. 406 if status, _ := hw.switchSD(MODE_CHECK, SD_SWITCH_ACCESS_MODE_GROUP, 0xf); status[13]&ACCESS_MODE_SDR104 != 0 { 407 hw.card.Rate = SDR104_MBPS 408 } 409 } 410 411 switch hw.card.Rate { 412 case HS_MBPS: 413 mode = ACCESS_MODE_HS 414 root_clk = ROOTCLK_HS_SDR 415 clk = SDCLKFS_HS_SDR 416 case SDR50_MBPS: 417 mode = ACCESS_MODE_SDR50 418 root_clk = ROOTCLK_UHS_SDR50 419 clk = SDCLKFS_UHS_SDR50 420 tune = true 421 case SDR104_MBPS: 422 mode = ACCESS_MODE_SDR104 423 root_clk = ROOTCLK_UHS_SDR104 424 clk = SDCLKFS_UHS_SDR104 425 tune = true 426 default: 427 return 428 } 429 430 if _, err = hw.switchSD(MODE_SWITCH, SD_SWITCH_POWER_LIMIT_GROUP, POWER_LIMIT_288W); err != nil { 431 return 432 } 433 434 if _, err = hw.switchSD(MODE_SWITCH, SD_SWITCH_ACCESS_MODE_GROUP, mode); err != nil { 435 return 436 } 437 438 hw.setClock(-1, -1) 439 hw.setRootClock(root_clk, 0) 440 hw.setClock(DVS_HS, clk) 441 442 if tune { 443 err = hw.executeTuningSD() 444 } 445 446 hw.card.HS = true 447 448 return 449 }