f_ changed the topic of ##raspberrypi-internals to: The inner workings of the Raspberry Pi (Low level VPU/HW) -- for general queries please visit #raspberrypi -- open firmware: https://librerpi.github.io/ -- VC4 VPU Programmers Manual: https://github.com/hermanhermitage/videocoreiv/wiki -- chat logs: https://libera.irclog.whitequark.org/~h~raspberrypi-internals -- bridged to matrix and discord
jcea has quit [Ping timeout: 268 seconds]
jcea has joined ##raspberrypi-internals
jcea has quit [Ping timeout: 268 seconds]
<f_ridge> <x​2x6_/D> Whats the difference between previous?
<f_ridge> <c​lever___/D> mostly just changing various clocks in the system, ive improve the output more and automated it futher
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> 55.555556 MHz, 228968 uSec to read 1MB 36.636597 mbits/sec
<f_ridge> <c​lever___/D> 50.000000 MHz, 228968 uSec to read 1MB 36.636597 mbits/sec
<f_ridge> <c​lever___/D> 45.454545 MHz, 228971 uSec to read 1MB 36.636116 mbits/sec
<f_ridge> <c​lever___/D> 41.666667 MHz, 229000 uSec to read 1MB 36.631477 mbits/sec
<f_ridge> <c​lever___/D> 38.461538 MHz, 229031 uSec to read 1MB 36.626518 mbits/sec
<f_ridge> <c​lever___/D> 35.714286 MHz, 238523 uSec to read 1MB 35.168968 mbits/sec
<f_ridge> <c​lever___/D> 33.333333 MHz, 253992 uSec to read 1MB 33.027058 mbits/sec
<f_ridge> <c​lever___/D> 31.250000 MHz, 270878 uSec to read 1MB 30.968214 mbits/sec
<f_ridge> <c​lever___/D> 29.411765 MHz, 287763 uSec to read 1MB 29.151100 mbits/sec
<f_ridge> <c​lever___/D> 27.777778 MHz, 304654 uSec to read 1MB 27.534868 mbits/sec
<f_ridge> <c​lever___/D> 26.315789 MHz, 321539 uSec to read 1MB 26.088928 mbits/sec
<f_ridge> <c​lever___/D> 25.000000 MHz, 338429 uSec to read 1MB 24.786907 mbits/sec
<f_ridge> <c​lever___/D> 23.809524 MHz, 355315 uSec to read 1MB 23.608932 mbits/sec
<f_ridge> <c​lever___/D> 22.727273 MHz, 372203 uSec to read 1MB 22.537724 mbits/sec
<f_ridge> <c​lever___/D> 21.739130 MHz, 389093 uSec to read 1MB 21.559391 mbits/sec
<f_ridge> <c​lever___/D> 20.833333 MHz, 405981 uSec to read 1MB 20.662563 mbits/sec
<f_ridge> <c​lever___/D> 20.000000 MHz, 422868 uSec to read 1MB 19.837416 mbits/sec
<f_ridge> <c​lever___/D> 19.230769 MHz, 439756 uSec to read 1MB 19.075596 mbits/sec
<f_ridge> <c​lever___/D> 18.518519 MHz, 456646 uSec to read 1MB 18.370047 mbits/sec
<f_ridge> <c​lever___/D> 17.857143 MHz, 473533 uSec to read 1MB 17.714939 mbits/sec
<f_ridge> <c​lever___/D> 17.241379 MHz, 490422 uSec to read 1MB 17.104877 mbits/sec
<f_ridge> <c​lever___/D> 16.666667 MHz, 507309 uSec to read 1MB 16.535500 mbits/sec
<f_ridge> <c​lever___/D> 16.129032 MHz, 524198 uSec to read 1MB 16.002747 mbits/sec
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> this would be when the VPU clock is set to 500mhz, on a pi3
<f_ridge> <c​lever___/D> sdhost is referenced off the VPU clock, so that 55mhz at the top, is just 500mhz/9
<f_ridge> <c​lever___/D> but when i graph things (oh, fun, font problems during svg->png, lol), it shows a clear linear relationship between mhz and mbit, until it hits a wall
<f_ridge> <c​lever___/D> so the best i can get out of sdhost read, is 36mbit, when the VPU is running at 500mhz
<f_ridge> <c​lever___/D> but this is also entirely without DMA
<f_ridge> <c​lever___/D> the nearly 1:1 ratio between mhz and mbit, also says that i'm still in 1bit mode
<f_ridge> <x​2x6_/D> I am stuck in trying to figure out the magic values in initialization sequence
<f_ridge> <x​2x6_/D> Its not really easy to navigate the simplified SDHOST specification pdf beause it describes SPI mode as whell
<f_ridge> <c​lever___/D> i think you mean sdhci
<f_ridge> <c​lever___/D> there are no official docs for sdhost
<f_ridge> <x​2x6_/D> well, not stuck, but there's too much to check
<f_ridge> <c​lever___/D> and yeah, i'm also confused by what the proper init sequence is
<f_ridge> <c​lever___/D> but i have figured out a hint, on why one of my old cards fails to boot
<f_ridge> <x​2x6_/D> Its not really easy to navigate the simplified SDHCI specification pdf beause it describes SPI mode as whell(edited)
<f_ridge> <c​lever___/D> my init sequence, sends CMD8 to check to see what voltages the card supports
<f_ridge> <c​lever___/D> but, it is valid for a card to just not support CMD8
<f_ridge> <c​lever___/D> so, how do you detect this? how do you init such a card?
<f_ridge> <x​2x6_/D> I am not sure also , I am looking in this section and trying to guess if this is applied to my card
<f_ridge> <c​lever___/D> the lexar cards i bought, clearly say `UHS-I` on the package
<f_ridge> <c​lever___/D> yeah, so that will just return thru 186, if its on such an old card
<f_ridge> <c​lever___/D> likely with a timeout error
<f_ridge> <x​2x6_/D> Why do you think timeout error will be there?
<f_ridge> <c​lever___/D> because when the card doesnt support CMD8, it will just not respond
<f_ridge> <x​2x6_/D> I think it will return a PATTERN but not the same supported voltage bit
<f_ridge> <c​lever___/D> and then a timeout will fire
<f_ridge> <x​2x6_/D> ahh
<f_ridge> <c​lever___/D> the pdf also says, if the voltage you sent isnt supported, it just wont respond
<f_ridge> <x​2x6_/D> Ok, yes, then if emmc controller returns with timeout, then it does not support
<f_ridge> <x​2x6_/D> Ok, yes, then if emmc controller returns with timeout, then it does not support the suggested voltage(edited)
<f_ridge> <c​lever___/D> yep
<f_ridge> <c​lever___/D> the other bit i'm stuck on, is getting ACMD6 to work, SD_APP_SET_BUS_WIDTH
<f_ridge> <c​lever___/D> youve got that handled over in `bcm2835_emmc_reset_handle_scr`
<f_ridge> <c​lever___/D> ah, it looks like you send ACMD51, then parse that to see what the card handles
<f_ridge> <x​2x6_/D> yes. I am going to revise this after I revise acmd41
<f_ridge> <x​2x6_/D> Just to see it actually is done right
<f_ridge> <x​2x6_/D> and all DATAn lines are in play
<f_ridge> <c​lever___/D> in my case, i just blindly send ACMD6, and dont even change the sd controller to 4bit mode
<f_ridge> <c​lever___/D> and things still work, when they shouldnt!
<f_ridge> <x​2x6_/D> What about acmd41?
<f_ridge> <c​lever___/D> i am sending that one, right before ACMD6
<f_ridge> <x​2x6_/D> It is not shown here but shown somewhere else that acmd41 first sent as a query and then as configuration. I've copy pasted it from somewhere I don't remember.
<f_ridge> <c​lever___/D> ah, i can see how it might still be in ident mode here...
<f_ridge> <c​lever___/D> let me check my code closer, and compare to that
<f_ridge> <c​lever___/D> after i do ACMD41 and ACMD6, i go on to `identify_card()`
<f_ridge> <c​lever___/D> `identify_card()` will do CMD2, CMD3, bingo, now its in data mode!
<f_ridge> <c​lever___/D> then CMD10 and CMD9,
<f_ridge> <c​lever___/D> then CMD10 and CMD9(edited)
<f_ridge> <c​lever___/D> so i think you can only do ACMD6 after CMD3 ?
<f_ridge> <c​lever___/D> let me try implementing ACMD51, so i can get the data you have
<f_ridge> <c​lever___/D> it looks like ACMD51 returns 8 bytes over the DAT pins?
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> 4.698505 [EMMC:identify_card]: sending ACMD51
<f_ridge> <c​lever___/D> 4.902578 [EMMC:wait_for_fifo_data]: ERROR: no FIFO data, timed out after 100000us!
<f_ridge> <c​lever___/D> 5.108664 [EMMC:wait_for_fifo_data]: ERROR: no FIFO data, timed out after 100000us!
<f_ridge> <c​lever___/D> 5.114646 [EMMC:identify_card]: done 0x0 0x0
<f_ridge> <c​lever___/D> ```
<f_ridge> <x​2x6_/D> Trying to figure out ACMD41 - looks like first you need to send all zeroes arguemnt to ACMD41 in inquiry mode, then set sometinh. In iquiry mode it should send OCR and some other stuff
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> 8.048801 [EMMC:identify_card]: sending ACMD51
<f_ridge> <c​lever___/D> bool BCM2708SDHost::send_raw(uint32_t, uint32_t):131: CMD 55, arg=0
<f_ridge> <c​lever___/D> bool BCM2708SDHost::send_raw(uint32_t, uint32_t):131: CMD 51, arg=0
<f_ridge> <c​lever___/D> bool BCM2708SDHost::wait_and_get_response():222: Cmd: 51 Resp: ffffffff 0000ff7f 7fffffff 00a40002
<f_ridge> <c​lever___/D> 8.073831 [EMMC:wait_and_get_response]: ERROR: sdhost status: 0x40
<f_ridge> <c​lever___/D> 8.279918 [EMMC:wait_for_fifo_data]: ERROR: no FIFO data, timed out after 100000us!
<f_ridge> <c​lever___/D> 8.505090 [EMMC:wait_for_fifo_data]: ERROR: no FIFO data, timed out after 100000us!
<f_ridge> <c​lever___/D> 8.530199 [EMMC:identify_card]: done 0x0 0x0
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> ah but your showing 41, and i'm stuck on 51
<f_ridge> <c​lever___/D> 41 is something i send during `query_voltage_and_type()`
<f_ridge> <c​lever___/D> ACMD41 is something i send during `query_voltage_and_type()`(edited)
<f_ridge> <c​lever___/D> oh, ive got an idea...
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> [root@system76:/sys/devices/pci0000:00/0000:00:1c.4/0000:02:00.0/rtsx_pci_sdmmc.0/mmc_host/mmc0/mmc0:59b4]# for x in cid csd dsr name ocr rca scr ssr; do echo $x $(cat $x);done
<f_ridge> <c​lever___/D> cid ad4c534c583132381035846b42017501
<f_ridge> <c​lever___/D> csd 400e0032db790003ae077f800a400001
<f_ridge> <c​lever___/D> dsr 0x404
<f_ridge> <c​lever___/D> name LX128
<f_ridge> <c​lever___/D> ocr 0x00300000
<f_ridge> <c​lever___/D> rca 0x59b4
<f_ridge> <c​lever___/D> scr 0245848700000000
<f_ridge> <c​lever___/D> ssr 00000000080000000400a00100fd3a1e000800000001fc0000000000000000000000000000000000000000000000000000000000000000000000000000000000
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> with that, i can read the SCR from linux
<f_ridge> <c​lever___/D> and ACMD51 is to send the SCR
<f_ridge> <c​lever___/D> so, i now know that it should contain `0245848700000000`
<f_ridge> <c​lever___/D> `MMC_DEV_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);` is how linux renders it
<f_ridge> <c​lever___/D> and checking the linux source, yeah, it does look like it returns the reply over DAT
<f_ridge> <x​2x6_/D> But ACMD41 is working in your case?
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> bool BCM2708SDHost::send_raw(uint32_t, uint32_t):131: CMD 55, arg=0
<f_ridge> <c​lever___/D> bool BCM2708SDHost::send_raw(uint32_t, uint32_t):131: CMD 41, arg=1075838976
<f_ridge> <c​lever___/D> bool BCM2708SDHost::wait_and_get_response():222: Cmd: 41 Resp: c0ff8000 00003f7f ffffffff 00004820
<f_ridge> <c​lever___/D> 7.973160 [EMMC:query_voltage_and_type]: SD card has arrived!
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> yeah, this is the debug from then
<f_ridge> <x​2x6_/D> Because it sends OCR register and mine is kind of meaningless and deviates from spec
<f_ridge> <x​2x6_/D> 00ff8000|00000000|00000000|00000000
<f_ridge> <x​2x6_/D> This is what I get first time I run it
<f_ridge> <x​2x6_/D> What do you use as an argument?
<f_ridge> <G​itHub Lines/D> ```cpp
<f_ridge> <G​itHub Lines/D> /* set voltage */
<f_ridge> <G​itHub Lines/D> t = MMC_OCR_3_3V_3_4V;
<f_ridge> <G​itHub Lines/D> if (r[0] == 0x1AA) {
<f_ridge> <G​itHub Lines/D> t |= MMC_OCR_HCS;
<f_ridge> <G​itHub Lines/D> is_sdhc = true;
<f_ridge> <G​itHub Lines/D> }
<f_ridge> <G​itHub Lines/D> /* query voltage and type */
<f_ridge> <G​itHub Lines/D> for (;;) {
<f_ridge> <G​itHub Lines/D> send(MMC_APP_CMD); /* 55 */
<f_ridge> <G​itHub Lines/D> send_no_resp(SD_APP_OP_COND, t);
<f_ridge> <G​itHub Lines/D> ```
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> #define MMC_OCR_HCS (1<<30) /* SD only */
<f_ridge> <c​lever___/D> :#define MMC_OCR_3_3V_3_4V (1<<21)
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> #define MMC_OCR_HCS (1<<30) /* SD only */
<f_ridge> <c​lever___/D> #define MMC_OCR_3_3V_3_4V (1<<21)
<f_ridge> <c​lever___/D> ```(edited)
<f_ridge> <x​2x6_/D> So you don't query?
<f_ridge> <G​itHub Lines/D> ```cpp
<f_ridge> <G​itHub Lines/D> if (!wait_and_get_response())
<f_ridge> <G​itHub Lines/D> return false;
<f_ridge> <G​itHub Lines/D> if (r[0] & MMC_OCR_MEM_READY)
<f_ridge> <G​itHub Lines/D> break;
<f_ridge> <G​itHub Lines/D> //logf("waiting for SD (0x%x) ...\n", r[0]);
<f_ridge> <G​itHub Lines/D> udelay(100);
<f_ridge> <G​itHub Lines/D> ```
<f_ridge> <c​lever___/D> after sending the command, it will wait for a certain value in `r[0]`
<f_ridge> <x​2x6_/D> I mean in the spec it says first to send with all zeroes in arg
<f_ridge> <c​lever___/D> and if it doesnt get that, it waits 100uSec, and sends it again
<f_ridge> <c​lever___/D> ah, yeah, i dont see the code doing that
<f_ridge> <x​2x6_/D> Why if (1aa) then its sdhc and HCS?
<f_ridge> <G​itHub Lines/D> ```cpp
<f_ridge> <G​itHub Lines/D> /* identify */
<f_ridge> <G​itHub Lines/D> send(SD_SEND_IF_COND, 0x1AA);
<f_ridge> <G​itHub Lines/D> wait_and_get_response();
<f_ridge> <G​itHub Lines/D> /* set voltage */
<f_ridge> <G​itHub Lines/D> t = MMC_OCR_3_3V_3_4V;
<f_ridge> <G​itHub Lines/D> if (r[0] == 0x1AA) {
<f_ridge> <G​itHub Lines/D> t |= MMC_OCR_HCS;
<f_ridge> <G​itHub Lines/D> is_sdhc = true;
<f_ridge> <G​itHub Lines/D> }
<f_ridge> <G​itHub Lines/D> ```
<f_ridge> <c​lever___/D> the aa is the check pattern
<f_ridge> <c​lever___/D> your code refers to the check pattern as `CMD8_ARG_PATTERN`
<f_ridge> <x​2x6_/D> Yes, but its CMD8
<f_ridge> <x​2x6_/D> It does not assume the check for sdhc.
<f_ridge> <c​lever___/D> `#define SD_SEND_IF_COND 8 /* R7 */`
<f_ridge> <x​2x6_/D> SDCH - is high capacity type. It should be ruled out from queriying the card's OCR
<f_ridge> <c​lever___/D> this code is a bit of a mess, i dont fully understand all of the choices the previous author did
<f_ridge> <G​itHub Lines/D> ```cpp
<f_ridge> <G​itHub Lines/D> /* fuck me with a rake ... gently */
<f_ridge> <G​itHub Lines/D> ```
<f_ridge> <x​2x6_/D> Yes, I know do the same revisiting and wonder all of those magic ifs)
<f_ridge> <c​lever___/D> i also suspect the previous author was having a lot of trouble making it work
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> 7.047046 [EMMC:identify_card]: sending ACMD51
<f_ridge> <c​lever___/D> bool BCM2708SDHost::send_raw(uint32_t, uint32_t):131: CMD 55, arg=0
<f_ridge> <c​lever___/D> bool BCM2708SDHost::wait_and_get_response():222: Cmd: 55 Resp: ffffffff 0000ff7f dfe00290 4000eb81
<f_ridge> <c​lever___/D> 7.066022 [EMMC:wait_and_get_response]: ERROR: sdhost status: 0x40
<f_ridge> <c​lever___/D> bool BCM2708SDHost::send_raw(uint32_t, uint32_t):131: CMD 51, arg=0
<f_ridge> <c​lever___/D> bool BCM2708SDHost::wait_and_get_response():222: Cmd: 51 Resp: ffffffff 0000ff7f 7fffffff 00a40002
<f_ridge> <c​lever___/D> 7.106048 [EMMC:wait_and_get_response]: ERROR: sdhost status: 0x40
<f_ridge> <c​lever___/D> 7.130053 [EMMC:identify_card]: ACMD51 fail
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> is CMD55 meant to fail with a timeout??
<f_ridge> <c​lever___/D> reading section 4.3.9, it sounds like `CMD55` should have a normal response, which should have the `APP_CMD` bit set
<f_ridge> <x​2x6_/D> All right, seems ACMD41 is solved.
<f_ridge> <x​2x6_/D> So where do you use CMD55? I don't even have it in code
<f_ridge> <c​lever___/D> CMD55 is used for all ACMD's
<f_ridge> <x​2x6_/D> ok,
<f_ridge> <c​lever___/D> ```c
<f_ridge> <c​lever___/D> static int bcm2835_emmc_run_acmd(struct bcm2835_emmc_cmd *c,
<f_ridge> <c​lever___/D> uint64_t timeout_usec, bool mode_polling)
<f_ridge> <c​lever___/D> {
<f_ridge> <c​lever___/D> int acmd_idx;
<f_ridge> <c​lever___/D> int status;
<f_ridge> <c​lever___/D> struct bcm2835_emmc_cmd acmd;
<f_ridge> <c​lever___/D> bcm2835_emmc_cmd_init(&acmd, BCM2835_EMMC_CMD55, c->rca << 16);
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> ah, found the 55 in your codebase
<f_ridge> <x​2x6_/D> So it should have RCA
<f_ridge> <c​lever___/D> oh, good catch
<f_ridge> <x​2x6_/D> and you had 0
<f_ridge> <c​lever___/D> but the pdf also says all 32 bits are stuff bits
<f_ridge> <c​lever___/D> what happens if i supply an rca anyways?
<f_ridge> <c​lever___/D> `bool BCM2708SDHost::wait_and_get_response():222: Cmd: 55 Resp: 00000720 0000377b ffffffff 02900009`
<f_ridge> <c​lever___/D> with `rca << 16`
<f_ridge> <c​lever___/D> `bool BCM2708SDHost::wait_and_get_response():222: Cmd: 55 Resp: ffffffff 0000ff7f dfe00290 4000eb81`
<f_ridge> <c​lever___/D> with `0`
<f_ridge> <x​2x6_/D> one strange thing is that ACMD41 is actually also an ACMD and at this point RCA is not communicated yet, so it can be 0
<f_ridge> <c​lever___/D> ahh
<f_ridge> <x​2x6_/D> RCA is relative address, that is assigned by us to the card
<f_ridge> <x​2x6_/D> something line
<f_ridge> <x​2x6_/D> something like(edited)
<f_ridge> <c​lever___/D> `[6357011.507402] mmc0: new ultra high speed SDR104 SDXC card at address 59b4`
<f_ridge> <c​lever___/D> yep, linux prints it when detecting a card
<f_ridge> <x​2x6_/D> I was wrong - RCA is an output from CMD3
<f_ridge> <x​2x6_/D> )
<f_ridge> <x​2x6_/D> what a mess
<f_ridge> <c​lever___/D> it seems to be in place to support sharing a single CMD pin across many sd cards
<f_ridge> <c​lever___/D> and yet, you can only query it when the CMD pin is private
<f_ridge> <c​lever___/D> checking my code, i can find a `select_card()` function
<f_ridge> <c​lever___/D> that will just CMD7 with the rca
<f_ridge> <x​2x6_/D> So CMD3 is SEND_RCA
<f_ridge> <x​2x6_/D> CMD7 is SELECT_CARD,
<f_ridge> <x​2x6_/D> and only after that you can acutally use CMD55
<f_ridge> <x​2x6_/D> looks like
<f_ridge> <c​lever___/D> i think i just need to set `rca = 0` in my init code, and always send it
<f_ridge> <c​lever___/D> then there wont be any confusion on when the default of 0 is ok
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> bool BCM2708SDHost::send_raw(uint32_t, uint32_t):131: CMD 55, arg=1504968704
<f_ridge> <c​lever___/D> bool BCM2708SDHost::wait_and_get_response():227: Cmd: 55 Resp: 00000720 0000377b ffffffff 02900009
<f_ridge> <c​lever___/D> bool BCM2708SDHost::send_raw(uint32_t, uint32_t):131: CMD 51, arg=0
<f_ridge> <c​lever___/D> bool BCM2708SDHost::wait_and_get_response():227: Cmd: 51 Resp: ffffffff 0000ff7f cdc00001 ffffffff
<f_ridge> <c​lever___/D> 4.924246 [EMMC:wait_and_get_response]: ERROR: sdhost status: 0x40
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> the 55 is now succeeding here, but the ACMD51 still fails
<f_ridge> <c​lever___/D> however, i notice, `select_card()` i think is needed any time your going to use the DAT pins
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> bool BCM2708SDHost::send_raw(uint32_t, uint32_t):131: CMD 51, arg=0
<f_ridge> <c​lever___/D> bool BCM2708SDHost::wait_and_get_response():227: Cmd: 51 Resp: 00000920 00003348 ffffffff 0002480c
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> yep, bingo
<f_ridge> <c​lever___/D> ` 4.915689 [EMMC:identify_card]: done 0x87844502 0x0`
<f_ridge> <c​lever___/D> vs
<f_ridge> <c​lever___/D> `scr 0245848700000000`
<f_ridge> <x​2x6_/D> I don't think selec card should always be used
<f_ridge> <c​lever___/D> this code just calls it later in the init sequence, and then never again
<f_ridge> <c​lever___/D> since there is no other card on the bus, the card just remains selected forever
<f_ridge> <c​lever___/D> but i was reading SCR before that point
<f_ridge> <c​lever___/D> i think i also figured out the 4bit flag
<f_ridge> <c​lever___/D> something in the init code was resetting it back to 1bit mode
<f_ridge> <x​2x6_/D> my cards SCR is like this SCR: 87840502|32640001
<f_ridge> <c​lever___/D> by moving the ACMD6 further down, it seems to stick now, and cause major transfer errors (host still in 1bit mode)
<f_ridge> <c​lever___/D> ` 5.351208 [EMMC:real_read_block]: ERROR: transfer error on FIFO word 114: 0x21`
<f_ridge> <c​lever___/D> `#define SDHSTS_CRC16_ERROR 0x20`
<f_ridge> <x​2x6_/D> so ACMD6 is to use 4 data lines right?
<f_ridge> <c​lever___/D> yep
<f_ridge> <G​itHub Lines/D> ```c
<f_ridge> <G​itHub Lines/D> #define SDHCFG_WIDE_EXT_BUS (1<<2)
<f_ridge> <G​itHub Lines/D> #define SDHCFG_WIDE_INT_BUS (1<<1)
<f_ridge> <G​itHub Lines/D> ```
<f_ridge> <x​2x6_/D> then you have to set emmc control reg
<f_ridge> <c​lever___/D> i now need to set one of these, to tell the host about the change
<f_ridge> <x​2x6_/D> yep
<f_ridge> <c​lever___/D> wide-int is always set
<f_ridge> <c​lever___/D> wide-ext is only set if in 4bit mode
<f_ridge> <c​lever___/D> my restart code specifically clears wide-ext, then sets the register with only wide-int and slow-card
<f_ridge> <x​2x6_/D> so we need to make sure both of this is set
<f_ridge> <x​2x6_/D> and working
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> 55.555556 MHz, 226398 uSec to read 1MB 37.052483 mbits/sec
<f_ridge> <c​lever___/D> 50.000000 MHz, 226426 uSec to read 1MB 37.047901 mbits/sec
<f_ridge> <c​lever___/D> 45.454545 MHz, 228975 uSec to read 1MB 36.635475 mbits/sec
<f_ridge> <c​lever___/D> 41.666667 MHz, 228973 uSec to read 1MB 36.635796 mbits/sec
<f_ridge> <c​lever___/D> 38.461538 MHz, 226411 uSec to read 1MB 37.050354 mbits/sec
<f_ridge> <c​lever___/D> 33.333333 MHz, 228978 uSec to read 1MB 36.634995 mbits/sec
<f_ridge> <c​lever___/D> 31.250000 MHz, 228990 uSec to read 1MB 36.633076 mbits/sec
<f_ridge> <c​lever___/D> 29.411765 MHz, 226433 uSec to read 1MB 37.046757 mbits/sec
<f_ridge> <c​lever___/D> 27.777778 MHz, 228981 uSec to read 1MB 36.634514 mbits/sec
<f_ridge> <c​lever___/D> 26.315789 MHz, 226431 uSec to read 1MB 37.047081 mbits/sec
<f_ridge> <c​lever___/D> 25.000000 MHz, 226407 uSec to read 1MB 37.051010 mbits/sec
<f_ridge> <c​lever___/D> 22.727273 MHz, 229076 uSec to read 1MB 36.619324 mbits/sec
<f_ridge> <c​lever___/D> 21.739130 MHz, 229064 uSec to read 1MB 36.621243 mbits/sec
<f_ridge> <c​lever___/D> 20.833333 MHz, 229030 uSec to read 1MB 36.626678 mbits/sec
<f_ridge> <c​lever___/D> 20.000000 MHz, 226490 uSec to read 1MB 37.037434 mbits/sec
<f_ridge> <c​lever___/D> 19.230769 MHz, 229036 uSec to read 1MB 36.625717 mbits/sec
<f_ridge> <c​lever___/D> 18.518519 MHz, 228997 uSec to read 1MB 36.631954 mbits/sec
<f_ridge> <c​lever___/D> 17.857143 MHz, 226457 uSec to read 1MB 37.042828 mbits/sec
<f_ridge> <c​lever___/D> 17.241379 MHz, 226481 uSec to read 1MB 37.038902 mbits/sec
<f_ridge> <c​lever___/D> 16.666667 MHz, 226500 uSec to read 1MB 37.035797 mbits/sec
<f_ridge> <c​lever___/D> 16.129032 MHz, 226502 uSec to read 1MB 37.035469 mbits/sec
<f_ridge> <c​lever___/D> 15.625000 MHz, 229077 uSec to read 1MB 36.619164 mbits/sec
<f_ridge> <c​lever___/D> 15.151515 MHz, 229072 uSec to read 1MB 36.619961 mbits/sec
<f_ridge> <c​lever___/D> 14.705882 MHz, 229040 uSec to read 1MB 36.625080 mbits/sec
<f_ridge> <c​lever___/D> 14.285714 MHz, 226494 uSec to read 1MB 37.036777 mbits/sec
<f_ridge> <c​lever___/D> 13.157895 MHz, 226443 uSec to read 1MB 37.045120 mbits/sec
<f_ridge> <c​lever___/D> 12.820513 MHz, 226411 uSec to read 1MB 37.050354 mbits/sec
<f_ridge> <c​lever___/D> 12.500000 MHz, 226402 uSec to read 1MB 37.051826 mbits/sec
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> and boom, thats lookin good!
<f_ridge> <c​lever___/D> its able to sustain 37mbit, across the entire clock range
<f_ridge> <c​lever___/D> 12mhz should give it 48mbit, so the bottleneck is now the lack of dma
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> 55.444444 MHz, 226426 uSec to read 1MB 37.047901 mbits/sec
<f_ridge> <c​lever___/D> 49.900000 MHz, 226426 uSec to read 1MB 37.047901 mbits/sec
<f_ridge> <c​lever___/D> 45.363636 MHz, 226397 uSec to read 1MB 37.052647 mbits/sec
<f_ridge> <c​lever___/D> 41.583333 MHz, 226362 uSec to read 1MB 37.058376 mbits/sec
<f_ridge> <c​lever___/D> 38.384615 MHz, 226394 uSec to read 1MB 37.053139 mbits/sec
<f_ridge> <c​lever___/D> 35.642857 MHz, 238183 uSec to read 1MB 35.219173 mbits/sec
<f_ridge> <c​lever___/D> 33.266667 MHz, 253992 uSec to read 1MB 33.027058 mbits/sec
<f_ridge> <c​lever___/D> 31.187500 MHz, 270877 uSec to read 1MB 30.968328 mbits/sec
<f_ridge> <c​lever___/D> 29.352941 MHz, 287763 uSec to read 1MB 29.151100 mbits/sec
<f_ridge> <c​lever___/D> 27.722222 MHz, 304653 uSec to read 1MB 27.534960 mbits/sec
<f_ridge> <c​lever___/D> 26.263158 MHz, 321541 uSec to read 1MB 26.088766 mbits/sec
<f_ridge> <c​lever___/D> 24.950000 MHz, 338428 uSec to read 1MB 24.786980 mbits/sec
<f_ridge> <c​lever___/D> 23.761905 MHz, 355314 uSec to read 1MB 23.608999 mbits/sec
<f_ridge> <c​lever___/D> 22.681818 MHz, 372203 uSec to read 1MB 22.537724 mbits/sec
<f_ridge> <c​lever___/D> 21.695652 MHz, 389092 uSec to read 1MB 21.559446 mbits/sec
<f_ridge> <c​lever___/D> 20.791667 MHz, 405980 uSec to read 1MB 20.662615 mbits/sec
<f_ridge> <c​lever___/D> 19.960000 MHz, 422869 uSec to read 1MB 19.837368 mbits/sec
<f_ridge> <c​lever___/D> 19.192308 MHz, 439757 uSec to read 1MB 19.075554 mbits/sec
<f_ridge> <c​lever___/D> 18.481481 MHz, 456645 uSec to read 1MB 18.370087 mbits/sec
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> and if i comment that out, i instead get this, 37mbit at the higher clocks, and then it drops off with clock rate
<f_ridge> <c​lever___/D> the only worrying thing, is that i randomly get crc16 errors, even as low as 7mhz
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> 8.064516 MHz, 267580 uSec to read 1MB 31.349907 mbits/sec
<f_ridge> <c​lever___/D> 7.936508 MHz, 271887 uSec to read 1MB 30.853289 mbits/sec
<f_ridge> <c​lever___/D> 7.812500 MHz, 276191 uSec to read 1MB 30.372488 mbits/sec
<f_ridge> <c​lever___/D> 7.692308 MHz, 280495 uSec to read 1MB 29.906445 mbits/sec
<f_ridge> <c​lever___/D> 23.480640 [EMMC:real_read_block]: ERROR: transfer error on FIFO word 125: 0x21
<f_ridge> <c​lever___/D> 23.505766 [EMMC:real_read_block]: ERROR: Transfer error, status: 0x0
<f_ridge> <c​lever___/D> 7.575758 MHz, 50133 uSec to read 1MB 167.327072 mbits/sec
<f_ridge> <c​lever___/D> 7.462687 MHz, 289104 uSec to read 1MB 29.015884 mbits/sec
<f_ridge> <c​lever___/D> 7.352941 MHz, 293410 uSec to read 1MB 28.590055 mbits/sec
<f_ridge> <c​lever___/D> 7.246377 MHz, 297714 uSec to read 1MB 28.176733 mbits/sec
<f_ridge> <c​lever___/D> 24.500437 [EMMC:real_read_block]: ERROR: transfer error on FIFO word 126: 0x21
<f_ridge> <c​lever___/D> 24.525567 [EMMC:real_read_block]: ERROR: Transfer error, status: 0x0
<f_ridge> <c​lever___/D> 7.142857 MHz, 50147 uSec to read 1MB 167.280350 mbits/sec
<f_ridge> <c​lever___/D> ```
<f_ridge> <x​2x6_/D> Nice!
<f_ridge> <x​2x6_/D> I mean nice that you have fast reads
<f_ridge> <x​2x6_/D> but CRC errors are daunting of course. strange
<f_ridge> <c​lever___/D> at least this time, i can detect them and retry
<f_ridge> <c​lever___/D> just pure 36mbit, all the way down to ~9mhz!
<f_ridge> <c​lever___/D> i should get some sleep now, its 4:22 am!
ungeskriptet has quit [Quit: Contact links: https://david-w.eu]
Stromeko has quit [Quit: Going… gone.]
Stromeko has joined ##raspberrypi-internals
<f_ridge> <x​2x6_/D> In the meantime I have brushed my SCR handling code a little bit, to understand that I did not set CONTROL0 HIGH_SPEED enable bit. It was never tunred on
<f_ridge> <x​2x6_/D> And now when I turn in on, my next CMDs fail. Probably I need to enable high speed on the SD card some how
<f_ridge> <x​2x6_/D> In your code I dont see it either
ungeskriptet has joined ##raspberrypi-internals
jcea has joined ##raspberrypi-internals
jcea has quit [Ping timeout: 240 seconds]
Ad0 has quit [Ping timeout: 252 seconds]
Ad0 has joined ##raspberrypi-internals
<f_ridge> <c​lever___/D> oh, i can see how getting that wrong would really screw over the comms
<f_ridge> <c​lever___/D> but i also cant see any sign of that existing in sdhost, so how does that work?
<f_ridge> <x​2x6_/D> I thought you told you have this bit set in your code.
<f_ridge> <x​2x6_/D> From which document is this screenshot?
<f_ridge> <c​lever___/D> page 61
<f_ridge> <c​lever___/D> the issue, is that i'm not using the emmc/sdhci controller, but sdhost, and i dont see a matching value in the linux driver
<f_ridge> <x​2x6_/D> What capabilities register are they talking about?
<f_ridge> <x​2x6_/D> Ok
<f_ridge> <c​lever___/D> page 103
<f_ridge> <c​lever___/D> and make sure you go by the number on the page itself, not what the pdf reader claims
<f_ridge> <x​2x6_/D> In the doc you have found this register is on offset 0x40
<f_ridge> <x​2x6_/D> In bcm2835 doc there is a gap
<f_ridge> <x​2x6_/D> I'll check what's there
<f_ridge> <c​lever___/D> i think the main point of the capabilities register, is for a universal sdhci driver to discover what the hw can do on its own
<f_ridge> <c​lever___/D> but the bcm2835 pdf, is explaining the hardware to you, so you can just write the driver to match the pdf
<f_ridge> <c​lever___/D> and then your driver will malfunction if you ever try it on another device, lol
<f_ridge> <x​2x6_/D> Actually all capability register values are 0
<f_ridge> <c​lever___/D> thats strange
<f_ridge> <x​2x6_/D> I though in that post these values are some how renamed values for CONTROL0 register and that BUS WIDTH and HIGH_SPEED bit is what you are talking about. So your CONTROL0 HIGH_SPEED bit was not set?
<f_ridge> <c​lever___/D> those values are from sdhost, which has a radically different interface
<f_ridge> <x​2x6_/D> But today you tuned SDHCI right?
<f_ridge> <c​lever___/D> nope, i got sdhost into 4bit mode
<f_ridge> <x​2x6_/D> So it also knows how to pass those CMDx commands?
<f_ridge> <c​lever___/D> yep
<f_ridge> <x​2x6_/D> I mean sdhost
<f_ridge> <x​2x6_/D> Ok, understood
<f_ridge> <x​2x6_/D> So, without this HS I am on 25MHz
<f_ridge> <x​2x6_/D> So, without this HS bit I am on 25MHz(edited)
<f_ridge> <c​lever___/D> but 25mhz 4bit sdr, is still 100mbit, or 12.5 mbyte/sec
<f_ridge> <c​lever___/D> and how does that compare to what the h264 encoder generates?
<f_ridge> <x​2x6_/D> I am currently revising the driver to understand what is the maximum possible output.
<f_ridge> <x​2x6_/D> I still not sure what is sdr
<f_ridge> <c​lever___/D> sdr is sending one symbol per clock, in this case, 4 bits per clock cycle
<f_ridge> <c​lever___/D> ddr is sending 2 symbols per clock, on the rising and faling edge
<f_ridge> <c​lever___/D> so 4bit ddr can move 8 bits per clock cycle
<f_ridge> <x​2x6_/D> I kind of know that for sdcard there is 3.3 volt regimes that are Default mode (25MHz) and High speed (50Mhz) , others are 1.8v
<f_ridge> <x​2x6_/D> So on raspberry pi we are limited with 3.3v regimets, so these are Default speed mode and High speed mode. Isn't that so?
<f_ridge> <x​2x6_/D> By the way, i really think if setting sw driver art aside, it's possible to solder in 1.8v circuitry to the SDcard Vdd pin)
<f_ridge> <x​2x6_/D> By the way, i really think if setting sw driver part aside, it's possible to solder in 1.8v circuitry to the SDcard Vdd pin)(edited)
<f_ridge> <c​lever___/D> i think it needs 3.3v vdd, and 1.8v IO
<f_ridge> <c​lever___/D> which is more complicated to do
<f_ridge> <x​2x6_/D> Hmm, yes, maybe some level shifter could join the party)
<f_ridge> <x​2x6_/D> Anyways, do you agree that SDR is not an option for raspberry or I am reading the wrong place?)
<f_ridge> <c​lever___/D> the pi0-pi3 is SDR only
<f_ridge> <x​2x6_/D> But also, I would like for normal people to be able to just buy raspberry and use my soft without having to go through soldering)
<f_ridge> <x​2x6_/D> But how?) They don't support 1.8v
<f_ridge> <x​2x6_/D> where is it written?
<f_ridge> <c​lever___/D> are you able to boot the pi normally?
<f_ridge> <c​lever___/D> into linux
<f_ridge> <x​2x6_/D> Not immediately , I have corrupted both of my sdcards with my soft)
<f_ridge> <c​lever___/D> let me boot my pi2w
<f_ridge> <x​2x6_/D> All info I have show more or less the same thing
<f_ridge> <x​2x6_/D> sdr/ddr are 1.8
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> root@raspberrypi:~# cat /sys/kernel/debug/mmc0/ios
<f_ridge> <c​lever___/D> clock: 50000000 Hz
<f_ridge> <c​lever___/D> actual clock: 50000000 Hz
<f_ridge> <c​lever___/D> vdd: 21 (3.3 ~ 3.4 V)
<f_ridge> <c​lever___/D> bus mode: 2 (push-pull)
<f_ridge> <c​lever___/D> chip select: 0 (don't care)
<f_ridge> <c​lever___/D> power mode: 2 (on)
<f_ridge> <c​lever___/D> bus width: 2 (4 bits)
<f_ridge> <c​lever___/D> timing spec: 2 (sd high-speed)
<f_ridge> <c​lever___/D> signal voltage: 0 (3.30 V)
<f_ridge> <c​lever___/D> driver type: 0 (driver type B)
<f_ridge> <c​lever___/D> root@raspberrypi:~# cat /sys/kernel/debug/mmc1/ios
<f_ridge> <c​lever___/D> clock: 50000000 Hz
<f_ridge> <c​lever___/D> actual clock: 50000000 Hz
<f_ridge> <c​lever___/D> vdd: 21 (3.3 ~ 3.4 V)
<f_ridge> <c​lever___/D> bus mode: 2 (push-pull)
<f_ridge> <c​lever___/D> chip select: 0 (don't care)
<f_ridge> <c​lever___/D> power mode: 2 (on)
<f_ridge> <c​lever___/D> bus width: 2 (4 bits)
<f_ridge> <c​lever___/D> timing spec: 2 (sd high-speed)
<f_ridge> <c​lever___/D> signal voltage: 0 (3.30 V)
<f_ridge> <c​lever___/D> driver type: 0 (driver type B)
<f_ridge> <c​lever___/D> root@raspberrypi:~# ```
<f_ridge> <c​lever___/D> one of these is sdhost, the other is sdhci
<f_ridge> <c​lever___/D> one handles the SD card, the other wifi
<f_ridge> <c​lever___/D> they are both supplying 3.3v on vdd, and using 3.3v IO, at 50mhz, 4bit, SDR
<f_ridge> <c​lever___/D> so that seems to imply that 3.3v 50mhz works fine?
<f_ridge> <x​2x6_/D> Yes, but probably not in SDR but in HIGH SPEED. Where do you see SDR?)
<f_ridge> <x​2x6_/D> timing spec: 2 (sd high-speed)
<f_ridge> <x​2x6_/D> So I somehow need to make HS bit working in CONTROL0
<f_ridge> <G​itHub Lines/D> ```c
<f_ridge> <G​itHub Lines/D> if (ios->timing == MMC_TIMING_SD_HS ||
<f_ridge> <G​itHub Lines/D> ios->timing == MMC_TIMING_MMC_HS ||
<f_ridge> <G​itHub Lines/D> ios->timing == MMC_TIMING_MMC_HS400 ||
<f_ridge> <G​itHub Lines/D> ios->timing == MMC_TIMING_MMC_HS200 ||
<f_ridge> <G​itHub Lines/D> ios->timing == MMC_TIMING_MMC_DDR52 ||
<f_ridge> <G​itHub Lines/D> ios->timing == MMC_TIMING_UHS_SDR50 ||
<f_ridge> <G​itHub Lines/D> ios->timing == MMC_TIMING_UHS_SDR104 ||
<f_ridge> <G​itHub Lines/D> ios->timing == MMC_TIMING_UHS_DDR50 ||
<f_ridge> <G​itHub Lines/D> ios->timing == MMC_TIMING_UHS_SDR25)
<f_ridge> <G​itHub Lines/D> ctrl |= SDHCI_CTRL_HISPD;
<f_ridge> <G​itHub Lines/D> else
<f_ridge> <G​itHub Lines/D> ctrl &= ~SDHCI_CTRL_HISPD;
<f_ridge> <G​itHub Lines/D> ```
<f_ridge> <c​lever___/D> if the SD driver core asks for one of those timing modes, the sdhci driver will enable high speed mode
<f_ridge> <x​2x6_/D> All right!
<f_ridge> <G​itHub Lines/D> ```c
<f_ridge> <G​itHub Lines/D> /*
<f_ridge> <G​itHub Lines/D> * Select timing parameters for host.
<f_ridge> <G​itHub Lines/D> */
<f_ridge> <G​itHub Lines/D> void mmc_set_timing(struct mmc_host *host, unsigned int timing)
<f_ridge> <G​itHub Lines/D> {
<f_ridge> <G​itHub Lines/D> host->ios.timing = timing;
<f_ridge> <G​itHub Lines/D> mmc_set_ios(host);
<f_ridge> <G​itHub Lines/D> }
<f_ridge> <G​itHub Lines/D> ```
<f_ridge> <c​lever___/D> this can set that timing flag
<f_ridge> <x​2x6_/D> I am completely lost with this kernel code and what I see in registers when I run pi.
<f_ridge> <x​2x6_/D> So in kernel there is a small branching based on the preset value.
<f_ridge> <x​2x6_/D> Preset value bit is taken from CONTROL2 register. This whole register is read as 0 in my case, along with all capabilities. Then after high speed is set, they disable clock and set some timings. This maps to setting UHSMODE field in control2 register. But it does not have HIGH SPEED, only SDR12,25,50,etc, as discussed SDR's are all 1.8
<f_ridge> <x​2x6_/D> It does not make sense for me)
<f_ridge> <x​2x6_/D> If i disable clock during setting CONTROL0 to HS, then enable back i still get corrupted behavior.
<f_ridge> <x​2x6_/D> probably I don't understand what SDR is. Have to read more
Stromeko has quit [Quit: Going… gone.]
Stromeko has joined ##raspberrypi-internals
<f_ridge> <x​2x6_/D> Ok, thanks, SDR is having two data bits in one pulse - on risign and falling edges but...
<f_ridge> <x​2x6_/D> this is still not relevant. Looking at this screenshot HS bit description does not mention switch to SDR. it tells that instead of falling edge , rising edge will be the point of putting new bit
<f_ridge> <c​lever___/D> other way around, DDR is 2 bits per pulse
<f_ridge> <c​lever___/D> the first d stands for double
<f_ridge> <x​2x6_/D> These are the only settings for UHS mode in CONTROL2 register.
<f_ridge> <x​2x6_/D> aa
<f_ridge> <x​2x6_/D> , ok so sdr is single and probably SDR50 now will be the right value
<f_ridge> <c​lever___/D> yep
<f_ridge> <c​lever___/D> as far as i know, sdr50 is the best the pi0-pi3 range can do, and sdr50 is what ive gotten sdhost to do
<f_ridge> <c​lever___/D> the pi4 can do ddr50, giving you twice the data rate
<f_ridge> <c​lever___/D> let me cross reference the bcm2835 and sd pdf's
<f_ridge> <c​lever___/D> UHSMODE is bits 16-18 of CONTROL2, which also contains TUNED and TUNEON, that may be important
<f_ridge> <c​lever___/D> CONTROL2 is at offset 3c
<f_ridge> <c​lever___/D> the sdhci doc calls that `2.2.24 Auto CMD Error Status Register (Cat.A Offset 03Ch)`
<f_ridge> <c​lever___/D> which doesnt match up at all
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> #define SDHCI_AUTO_CMD_STATUS 0x3C
<f_ridge> <c​lever___/D> #define SDHCI_HOST_CONTROL2 0x3E
<f_ridge> <c​lever___/D> ```
<f_ridge> <c​lever___/D> ah, linux is treating it as 2 x 16bit
<f_ridge> <c​lever___/D> but bcm2835.pdf is treating it as 1 x 32bit
<f_ridge> <c​lever___/D> UHSMODE lands within control2 at 3e
<f_ridge> <c​lever___/D> which sdhci calls `Host Control 2`
<f_ridge> <c​lever___/D> `2.2.25 Host Control 2 Register (Cat.C Offset 03Eh)`
<f_ridge> <c​lever___/D> here is the sdhci version of the UHSMODE you posted
<f_ridge> <c​lever___/D> @x2x6_ this implies that you must trigger the tuning procedure before going up to SDR50 speeds
<f_ridge> <G​itHub Lines/D> ```c
<f_ridge> <G​itHub Lines/D> * The Host Controller needs tuning in case of SDR104 and DDR50
<f_ridge> <G​itHub Lines/D> * mode, and for SDR50 mode when Use Tuning for SDR50 is set in
<f_ridge> <G​itHub Lines/D> * the Capabilities register.
<f_ridge> <G​itHub Lines/D> * If the Host Controller supports the HS200 mode then the
<f_ridge> <G​itHub Lines/D> * tuning function has to be executed.
<f_ridge> <G​itHub Lines/D> ```