Technical details:
The basic speed setting is done a function I've called SD_ChgClkSpd (as is my usual practice, camel case names are inferred from Canon strings, but here I've added SD_ since it's otherwise not clear what clock it refers. Functions that didn't have an obvious name are snake_case).
Like most low level SD related functions, the first parameter is a value I call sd_id. This identifies the SD interface, and is almost certainly always zero for the SD card on powershots. However, many of these cameras contain a wifi interface that uses SDIO, and low level SD interface code appears to be somewhat shared on Digic 6 (and likely earlier), so there are code paths where other sd_id may really not be 0. On Digic 7, strings imply the "Lime" CPU has its own SDIO interface for the network card, so presumably it doesn't connect to the main arm cores.
SD_ChgClkSpd and related functions take a second argument I've called speed_id, which I interpret as a mode enum that identifies a set of speed related settings. On Digic 6, the possible values range from 0 to 19, though some values are not supported by the whole firmware. This eventually gets passed down to SetSDClkFrequency, which contains a switch statement that turns enum into values written to MMIOs.
The values are split into two ranges, from 0-9 and 10-19 on digic 6. Digic 7 follows a similar pattern but the numbers are different.
For SD cards on digic 6, the values of interest appear to be in the 0-9 range. Values from 10 and up appear to be non-UHS, both 1 gig SD (not SDHC) and 4g class 4 show 13.
A caller of SD_ChgClkSpd (sx710 101a 0x010e3020) suggests the speed_id values map to the following "Frequency" values
3: 50
5: 80
6: 100
7: 130
8: 196
although I believe the actual setup is more complicated than a single "frequency", and it's not clear to me how this aligns (or not) with the SD specs, or which of the speed related values are changed by SD_ChgClkSpd
Additionally, SDIO / network related strings (sx710 101a 0x010e1a04) suggest the values from 10 and up
11: 18
12: 24
13: 48
For digic 7,
g7x2 function (101a e051ec74) maps the "frequency" values as follows
2: 25
3: 50
4: 80
5: 100
7: 130
9: 196
Note a debug message "Not Support For Musa !!" is associated with 4 (80), although the function returns normally when that value is used. (AFAIK "Musa" refers to Digic 7 or some part of it)
Strings in the 200D firmware (1.0.1 e0247e0a) identify the following, which generally matches the
g7x2 function
0: 1_8V_210K
1: 1_8V_20_0M
2: 1_8V_24_4M
3: 1_8V_48_8M
4: 1_8V_65_0M
5: 1_8V_97_5M
6: 1_8V_111_4M
7: 1_8V_130_0M
8: 1_8V_156_0M
9: 1_8V_195_0M
10: 3_3V_210K
11: 3_3V_20_0M
12: 3_3V_24_4M
13: 3_3V_48_8M
After several intermediate calls, SD_ChgClk ends up calling SetSDClkFrequency, which converts the speed_id value into a set of values that are mostly used to set MMIOs.
It's possible that programming these values directly would allow more extreme overclocks as ML has achieved. I haven't investigated much, but some values appear superficially similar to those set in
ML overclocking code
I chose to use SD_ChgClkSpd rather than one of the intermediate functions because it takes and releases a semaphore associated with low level SD control, and the intervening calls don't do much.
sddomChangeClockSpeed checks the requested speed against limits, which very depending whether it's in the UHS (<10) or non-UHS range and clamps the value the allowed range. The UHS limit on D6 is 8, meaning the value 9 is not available although it's present in the underlying code. The limit can be bypassed by poking the limit variable (the script supports this if limitvar is defined). Doing this and overriding to 9 appears to give similar performance to 8, at least with the cards I have. These limits are in the firmware initialized data, in my testing they do not appear to vary at run time: In other words, it appears to be a soft limit in firmware, not based on the specific card.
The function between sddomChangeClockSpeed and SetSDClkFrequency (unnamed, sx710 101a 010f21ae) saves the new value in a "current speed id" variable.
Thanks to
@names_are_hard for pointing me the 200d code, which contains a function (1.0.1 e02b72e😎 (SddomUHSTuning) which iterates through speed_id 6 - 9 and calls some function to test if it works. This made me realize I could probably just call SD_ChgClkSpd at runtime, where I'd previously assumed I'd have to hook it into the normal initialization process.
The SD_GetSpd functions returns two values via pointers. The first is unknown, but likely related to card card type. I've seen 1 for SD and non-UHS SDHC, and 4 for UHS. The second value is the speed id.
The "tune" options calls SddomUHSTuningSamplingPoint" (aka UTuSmPt) after changing the speed. The SD spec theoretically requires requires tuning at higher clock speeds, but I didn't notice any difference calling it or not. The 200d auto speed tuning mentioned above also appears to use something similar. On Digic 6, the function does not support speed id 9, and returns an error if this is set. The
CMD 19 spam I noticed long ago is related to tuning.