Address | Desc. |
---|---|
0xF0000000 | Hardware ID |
0xF0000004 | Soft reset |
0xF0000008 | Hardware setup |
0xF000000C | PLL - input clock divider |
0xF0000010 | PLL - clock multiplier |
0xF0000014 | PLL - primary clock divider |
0xF0000018 | PLL - secondary clock 1 divider |
0xF000001C | PLL - secondary clock 2 divider |
0xF0000020 | PLL - secondary clock 3 divider |
0xF0000024 | PLL - feedback frequency related |
0xF0000028 | PLL - feedback frequency related |
0xF000002C | PLL - feedback frequency related |
0xF0000030 | ?? |
0xF0000034 | Clocks - Pixel clock setting |
0xF0000038 | Clocks - Camera clock setting |
0xF000003C | Clocks - Audio amplifier clock setting |
0xF0000040 | Clocks - UART0 clock setting |
0xF0000044 | Clocks - UART1 clock setting |
0xF0000048 | Clocks - UART2 clock setting |
0xF000004C | Clocks - I2C clock setting |
0xF0000050 | Clocks - Clock setting for ?? |
0xF0000054 | Clocks - SDIO clock setting |
0xF0000058 | Hardware reset |
0xF000005C | ?? |
0xF0000060 | ?? |
0xF0000064 | ?? |
0xF0000000
This register serves to identify different hardware variations. Not sure if such variations occur in retail gamepads or if they are solely prototype stuff.
Regardless, the stock firmware checks different parts of this register before accessing certain hardware. A prominent example is I2C, for which there are two possible controllers from different vendors.
As far as I've seen, this register reads as 0x00041040 on production motherboards, both revisions 01 and 20.
Bits | Desc. |
---|---|
0-7 | Chip version (Type of GPIO, I2C and other stuff)0x10 (TS) 0x20 (ES1) 0x30 (ES2) 0x40 (ES3) 0x41 (MS01) |
8-15 | ?? |
16 | SoC type; 0=DRC, 1=DRH |
17-18 | Source for second stage bootloader; 0=UART1, 1=UART1, 2=SPI, 3=I2C |
19 | Type of PLL? |
The stock firmware checks bits 0-7 for value 0x41, and in that case:
Bits 8-15 are writable when the boot ROM is running. They seem to become read-only after the boot ROM is disabled. They might just serve as software-defined boot flags.
Bit 12 is set by the boot ROM before resetting the CPU.
Bits 16 and 19 are checked during hardware initialization, to choose the correct PLL settings.
The boot ROM and bootloader seem to be the same for both DRC (gamepad SoC) and DRH (WiiU side SoC).
Notably, when bit 16 is set:
The boot ROM checks bits 17-18 to determine where to load the second stage bootloader from. Those bits can be controlled by the serial header: shorting pad 2 to ground sets those bits to 0, enabling UART boot.
Bit 19 is tied to pad N2 of the SoC. On the gamepad, it is tied to ground through R133 (zero-ohm resistor).
0xF0000008
Unknown.
Bits | Desc. |
---|---|
0 | ??? |
1 | ??? |
2 | ??? |
3 | ??? |
4 | ??? |
0xF0000030
Probably related to clock generation?
Bits | Desc. |
---|---|
0 | ??? |
1 | ??? important |
8 | ??? |
9 | ??? |
10 | ??? setting this bit crashes gamepad |
0xF0000064
Unknown. Probably related to clock stuff. Set to 6 on gamepad, 9 on DRH. Coincidentally, 9/6 = 24/16 = 1.5.
0xF0000004
Soft reset register. Setting bit 0 to 0 then 1 resets the CPU after a short delay.
This likely also disables the boot ROM overlay and makes bit 8-15 in register 0xF0000000 read-only.
Weirdly, the boot ROM sets it to 1 without setting it to 0 first. This register might just react to 0-to-1 transitions.
0xF0000058
Hardware reset register.
Bits | Desc. |
---|---|
0 | Reset IRQ controller |
1 | Reset timers |
2 | Reset RAM? |
3 | Reset DMA |
4 | Reset SPI |
5 | ?? |
6 | Reset SDIO |
7 | Reset UART0 |
8 | Reset UART1 |
9 | Reset UART2 |
10 | Reset I2C0 & I2C general registers |
11 | Reset I2C1 |
12 | Reset I2C2 |
13 | Reset I2C3 |
14 | Reset I2C4 |
15 | Reset audio controller |
16 | Reset H264 codec (0xF0008400) |
17 | ??? |
18 | Reset ??? (0xF0008800, 0xF0008900) |
19 | Reset ??? (0xF0008C00) |
20 | Reset camera controller (0xF0009000) |
21 | Reset LCD controller (0xF0009400, 0xF0009500, 0xF0009600, 0xF0009700) |
Setting a bit to 1 then 0 resets the corresponding hardware component. This register is 22 bits wide.
Bit 2 is used by the boot ROM. Using it from code running in RAM will crash the gamepad. This bit might be for resetting RAM, but at the same time, the RAM does somewhat retain old data across consecutive boots, so it's not entirely clear how this works.
The gamepad starts at a clock of 16 MHz. PLL settings applied by the second stage bootloader change the system clock to 108 MHz.
Different settings are applied based on the base clock.
Setting | 16 MHz value | 24 MHz value |
---|---|---|
0xF000000C | 13 | 20 |
0xF0000010 | 0x5E8000 | |
0xF0000014 | 5 | |
0xF0000018 | 510 | |
0xF000001C | 108 | |
0xF0000020 | 510 | |
0xF0000024 | 0xBC | |
0xF0000028 | 0x24 | |
0xF000002C | 0x3A1 |
TODO: not known yet how the control registers work, ie. how to actually apply PLL settings
The base clock is divided by the input clock divider, then multiplied by the clock multiplier, producing a VCO frequency of 1728 MHz.
This frequency is then fed into 4 separate dividers to produce the primary clock and 3 secondary clocks. The primary clock is then divided by 8 to produce the DRC system clock.
The feedback frequency generation is not completely understood yet.
0xF000000C
Input clock divider. This register is 6 bits wide.
This seems to be a count-up divider, ie. setting it to 13 divides the input clock by 14.
0xF0000010
Clock multiplier. This register is 26 bits wide.
Bits 0-11 seem to be the fractional part of the multiplier.
0xF0000014
Primary clock divider. This register is 9 bits wide.
Possible values:
Value | Divider |
---|---|
0b0'0000'0000 | 4 |
0b0'0000'0010 | 4 |
0bx'xxxx'xxx0 | Register value |
0b0'xxxx'xxx1 | 2 |
0b1'xxxx'xxx1 | 2.5 |
This is a weird kind of divider: if bit 0 is set, the input is divided by 2 or 2.5 (depending on bit 8), but if bit 0 is cleared, the input is divided by the register value. Values 0 and 2 behave the same as 4.
It also appears that 2.5 isn't supported for the primary clock, and acts the same as 2?
0xF0000018
Secondary clock 1 divider. Function same as 0xF0000014.
0xF000001C
Secondary clock 2 divider. Function same as 0xF0000014.
0xF0000020
Secondary clock 3 divider. Function same as 0xF0000014.
0xF0000024
This register is related to the feedback frequency generation. This register is 12 bits wide.
0xF0000028
This register is related to the feedback frequency generation. This register is 12 bits wide.
Needs to be set to a nonzero value.
0xF000002C
This register is related to the feedback frequency generation. This register is 26 bits wide.
This register is related to 0xF0000028 in that one unit of 0xF0000028 equals 512 units of 0xF000002C.
From 0xF0000034 to 0xF0000054
Bits | Desc. |
---|---|
0-7 | Clock divider |
8-10 | Clock source |
Clock source is one of 8 possible source clocks. Clock divider is a simple count-up divider, ie. setting it to 31 divides the selected clock by 32.
The following clock sources are available:
Source | Default frequency | Description |
---|---|---|
0 | 32 MHz | Always 32 MHz, likely just crystal X1 output |
1 | 12 MHz | Camera clock (from 0xF0000038) |
2 | ??? | ??? |
3 | 3.08 MHz | Audio bit clock (from audio amplifier) |
4 | 864 MHz | Primary clock |
5 | 3.38 MHz | Secondary clock 1 |
6 | 16 MHz | Secondary clock 2 |
7 | 3.38 MHz | Secondary clock 3 |
Peripherals may then divide their incoming clocks further. For example, in the case of I2C, the clock is divided by 24 before being output to the SCL line.
The fact that the camera clock can be selected as a clock source means it is possible to source the camera clock from itself. In practice, this doesn't collapse space-time or anything fun. It's more like plugging a power strip into itself.
Source 3 only works if the audio amplifier has been properly initialized.
Source 2 probably comes from another peripheral that needs to be initialized, not yet known which.