-
Notifications
You must be signed in to change notification settings - Fork 4
Clocks and resets
MMIO | description |
---|---|
0xb0000200 | clock and reset controller |
offset | type | name | description |
---|---|---|---|
0x00 | u32 | CLKEN | clock enable |
0x04 | u32 | CLKSEL | clock select |
0x08 | u32 | CLKDIV | clock divide |
0x0c | u32 | PLLCON0 | PLL0 configuration |
0x10 | u32 | PLLCON1 | PLL1 configuration |
0x14 | u32 | PMCON | power management control |
0x18 | u32 | IRQWAKECON | IRQ wake-up control |
0x1c | u32 | IRQWAKEFLAG | IRQ wake-up flags |
0x20 | u32 | IPSRST | reset lines |
0x24 | u32 | ??? | undocumented PLL |
The clock tree of the WPCM450 consists of:
- An external 48MHz reference clock oscillator
- Two PLLs, which can be individually enabled and configured
- Clock enable gates for every peripheral, allowing selection between the 48MHz refclock, PLL0, PLL1, and GPIO 83
- Clock selection muxes for different parts of the chip
- Clock dividers for different parts of the chip
reference +---------+ +---------------+ +---------+ output
---------->| input |------------>| |---.-->| output |------->
(48 MHz) | divider | | comparator | | | divider |
+---------+ | and | | +---------+
feedback | oscillator | |
.----------->| | |
| +---------------+ |
| |
| +----------+ |
'--------------| feedback |<-----'
| divider |
+----------+
The two PLLs are each controlled by a 32-bit register containing multiple fields:
bits | name | description |
---|---|---|
0:5 | INDV | input divider |
8:10 | OTDV | output divider |
12 | PWDEN | powerdown enable |
13 | PRST | PLL reset mode |
16:24 | FBDV | feedback divider |
The output frequency is calculated as:
Fout = Fref / (INDV+1) * (FBDV+1) / (OTDV+1)
Between the 48 MHz reference oscillator and the PLLs on one side, and peripherals on the other side, there are intermediate clocks, that allow selecting their parent clock (CLKSEL) or setting a divider (CLKDIV).
Most of these clocks correspond to memory buses in the SoC.
clock | parent(s) | CLKSEL | divider | CLKDIV | description |
---|---|---|---|---|---|
CPU | PLL0, PLL1, REF | 0:1 | 2 | -- | CPU clock |
CLKOUT | PLL0, PLL1, REF | 2:3 | 1 | -- | clock output |
USBPHY | PLL0, PLL1, REF | 6:7 | 1 | -- | USB 1.1 PHY clock, should be 60 MHz |
UART | PLL0, PLL1, REF | 8:9 | DIV+1 | 16:19 | UART reference clock |
HUART | REF, REF/2 | 10 | 1 | -- | Host UART reference clock |
AHB | CPU | -- | 1,2 | 24:25 | |
AHB3 | AHB | -- | 1,2,4,8 | 8:9 | |
AHB1,2 | AHB | -- | 1 | -- | |
APB | AHB | -- | 1,2,4,8 | 26:27 | |
ADC | REF | -- | 1,2,4,8 | 28:29 |
Unless otherwise noted, two-bit fields can take the following values:
value | CLKDIV | CLKSEL |
---|---|---|
0 | divide by 1 | PLL0 |
1 | divide by 2 | PLL1 |
2 | divide by 4 | REF (48 MHz) |
3 | divide by 8 | REF or reserved |
When reconfiguring the CPU clock, you must ensure that the bus clocks don't run slower then the connected peripherals. For example, in a fairly standard configuration, we have these values:
- PLL0 = 400 MHz
- CPU = 200 MHz (PLL0/2)
- AHB = 100 MHz (CPU/2)
- APB = 50 MHz (AHB/2)
- UART = 24 MHz (REF/2)
Switching the CPU clock to 100 MHz works, because the APB clock (25 MHz) runs slightly faster than the UART clock (24 MHz). Switching the CPU clock to 66.6 MHz induces malfunction in the UART peripheral, probably at the interface between the APB bus and the UART peripheral.
Unknnoowwn coommmmand wwbb0000000
>
Thus, when switching the CPU to a clock slower than 96 MHz, the AHB and APB clock dividers should be adjusted before using the UART.
When you set the CPU clock rate to 24 MHz (REF/2), a few different malfunctions can happen:
The external DRAM is no longer able to hold data properly: Every byte reads back as 0x00.
> ww 3000 1 2 3 4
> rw 3000 4
00003000: 00000002 00000001 00000004 00000003
There are additional random errors, though:
>>> l.write32(0x2000, [x for x in range(0x100)])
>>> l.read32(0x2000, 0x100) == [x^1 for x in range(0x100)]
False
>>> l.read32(0x2000, 0x100) == [x^1 for x in range(0x100)]
True
>>> l.read32(0x2000, 0x100) == [x^1 for x in range(0x100)]
True
>>> l.read32(0x2000, 0x100) == [x^1 for x in range(0x100)]
False
>>> a = l.read32(0x2000, 0x100); b = [x^1 for x in range(0x100)]; print(a==b); [(i, a[i] ^ b[i]) for i in range(0x100) if a[i]!=b[i]]
False
[(124, 21), (204, 4)]
>>> a = l.read32(0x2000, 0x100); b = [x^1 for x in range(0x100)]; print(a==b); [(i, a[i] ^ b[i]) for i in range(0x100) if a[i]!=b[i]]
False
[(7, 4)]
bit | name | parent clk | description |
---|---|---|---|
0 | FIU | AHB3 | SPI flash controller |
1 | XBUS | AHB3 | XBUS |
2 | KCS | APB? | |
3 | GDMA | DMA engine (?) (reserved) | |
4 | SHM | AHB3? | |
5 | USB1 | AHB1? | USB 1.1 controller |
6 | EMC0 | AHB1 | Ethernet MAC 0 |
7 | EMC1 | AHB1 | Ethernet MAC 1 |
8 | USB0 | AHB1 | USB 2.0 controller |
9 | PECI | APB? | |
10 | AES | APB? | |
11 | UART0 | UART? | UART 0 |
12 | UART1 | UART? | UART 1 |
13 | SMB2 | APB? | I2C/SMBus 2 |
14 | SMB3 | APB? | I2C/SMBus 3 |
15 | SMB4 | APB? | I2C/SMBus 4 |
16 | SMB5 | APB? | I2C/SMBus 5 |
17 | HUART | HUART? | |
18 | PWM | APB? | PWM |
19 | TIMER0 | REF/2 | |
20 | TIMER1 | REF/2 | |
21 | TIMER2 | REF/2 | |
22 | TIMER3 | REF/2 | |
23 | TIMER4 | REF/2 | |
24 | MFT0 | APB? | Multi-function timer 0 |
25 | MFT1 | APB? | Multi-function timer 1 |
26 | WDT | REF/2 | |
27 | ADC | ADC? | |
28 | SDIO | AHB1? | SD card interface — note that the SDIO clock speed is based on 48 MHz |
29 | SSPI | APB? | |
30 | SMB0 | APB? | I2C/SMBus 0 |
31 | SMB1 | APB? | I2C/SMBus 1 |
In addition, the clock controller controls the reset lines of different parts of the chip.
bit | name | description |
---|---|---|
0 | FIU | SPI flash controller |
1 | -- | |
2 | -- | |
3 | GDMA | DMA engine (?) (reserved) |
4 | -- | |
5 | RNG | Random number generator (reserved) |
6 | EMC0 | Ethernet MAC 0 |
7 | EMC1 | Ethernet MAC 1 |
8 | USB0 | USB 2.0 controller |
9 | USB1 | USB 1.1 controller |
10 | AES/PECI | AES engine and PECI controller |
11 | UART | both UARTs |
12 | MC | Memory controller |
13 | SMB2 ? | I2C/SMBus 2 |
14 | SMB3 ? | I2C/SMBus 3 |
15 | SMB4 ? | I2C/SMBus 4 |
16 | SMB5 ? | I2C/SMBus 5 |
17 | -- | |
18 | PWM | PWM |
19 | TIMER ? | Timers |
20 | -- | |
21 | -- | |
22 | -- | |
23 | -- | |
24 | -- | |
25 | -- | |
26 | -- | |
27 | ADC ? | ADC |
28 | SDIO ? | SDIO controller |
29 | SSPI ? | Secondary SPI controller |
30 | SMB0 ? | I2C/SMBus 0 |
31 | SMB1 ? | I2C/SMBus 1 |
- When FIU is clock-gated, its register and flash windows read 0. After ungating, the old state is restored.
- When FIU is reset, its register and flash windows read ff. When it is released from reset, the registers have their initial values.
- Ethernet
- reset: read 0, release: read 0 (initial values)
- gate: read 0, ungate: read values
- Some register spaces, such as the one of the AES engine, do not read all-0 when held in reset
- Registers (ATEN)
- Clock enable bits (AMI, Dell)
Overview:
Basics:
Peripherals:
- Memory controller
- UART, SPI/SSPI, I2C, SD
- GPIOs and pinmux
- Ethernet
- USB, LPC, PECI, XBUS
- PWM and Tachometer, ADC
- Graphics
Board specifics: