Configure XOSC and PLL as ref and sys clocks (12MHz and 150MHz).

Signed-off-by: jmug <u.g.a.mariano@gmail.com>
This commit is contained in:
Mariano Uvalle 2025-05-18 23:06:30 -07:00
parent 1e0a36f7b3
commit f30f36420a

View file

@ -10,6 +10,15 @@
.equ pads_set, 0x4003a000
.equ pads_clr, 0x4003b000
.equ resets_wrd, 0b100001001000000 // Bits 14 (PLL_SYS), 9 (PADS_BANK0) and 6 (IO_BANK0)
// Clocks.
.equ xosc_base, 0x40048000
.equ xosc_set, 0x4004a000
.equ xosc_en_mask, 0xfab000
.equ clk_base, 0x40010000
.equ clk_set, 0x40012000
.equ clk_clr, 0x40013000
.equ pll_base, 0x40050000
.equ pll_clr, 0x40053000
.thumb_func // This makes sure that the address of start has its LSB set to signal thumb mode.
.global hello_start
@ -25,9 +34,103 @@ check_rst:
cmp r1, r2
bne check_rst
clocks_setup:
// TODO: Configure the crystal oscilator and set it as the reference clock.
// TODO: Configure the PLL and wait for it to lock.
// TODO: Change the sys clock source to the PLL.
// Configure and enable the crystal oscilator
// Set the freq range.
ldr r0, =xosc_base
mov r1, #0xaa // 1-15MHz range
lsl r1, r1, #4
str r1, [r0]
// Set the startup delay.
mov r1, #0xc4 // This is the defualt value and it's around 4ms at 12MHz
str r1, [r0, #0x0c]
// Enable the clock.
ldr r0, =xosc_set
ldr r1, =xosc_en_mask
str r1, [r0]
// Wait for it to be ready.
ldr r0, =xosc_base
xosc_rdy:
ldr r1, [r0, #0x04]
lsr r1, #31 // The stable flag is bit 31
beq xosc_rdy // If the flag is zero then keep checking.
// Set the crystal osc as the reference clock.
ldr r0, =clk_base
mov r1, #0x02
str r1, [r0, #0x30] // Set XOSC_CLKSRC on the CLK_REF_CTRL reg.
// Wait for it to be selected.
mov r2, #0b100
xosc_ref_selected:
ldr r1, [r0, #0x38]
and r1, r1, r2
cmp r1, r2
bne xosc_ref_selected
// Configure the PLL and wait for it to lock.
// Requested: 150.0 MHz
// FREF: 12MHz (This comes from the XOSC on the board)
// REFDIV: 1
// FBDIV: 125 (VCO = 1500.0 MHz)
// PD1: 5
// PD2: 2
// (FREF / REFDIV) × FBDIV / (POSTDIV1 × POSTDIV2)
// Typically you'd reset the PLL subsystem here, but already did so maybe it'll work.
ldr r0, =pll_base
// Set the refdiv
mov r1, #1 // This is the reset value, just setting it for completeness
str r1, [r0, #0]
// Set the fbdiv
mov r1, #125
str r1, [r0, #0x08]
// Turn on PLL
ldr r0, =pll_clr
mov r1, #0b100001 // Clearing bits 5 (VCOPD) and 0 (PD)
str r1, [r0, #0x04]
// Wait for it to lock (stabilize)
pll_locked:
ldr r0, =pll_base
ldr r1, [r0, #0]
lsr r1, #31 // Bit 31 of the CS reg is LOCK
beq pll_locked // Wait until it's not 0
// Set Post dividers.
mov r1, #5
lsl r1, r1, #4 // PD1 goes on bits 18:16
mov r2, #2
orr r1, r1, r2
lsl r1, r1, #12 // PD2 goes on bits 14:12
str r1, [r0, #0x0c]
// Turn on Post dividers.
ldr r0, =pll_clr
mov r1, #0b1000
str r1, [r0, #0x04]
// Change the sys clock source to the PLL
// Glitchlessly change the sys source to clk ref
ldr r0, =clk_clr
mov r1, #1
str r1, [r0, #0x3c]
// Wait for it to be selected
ldr r0, =clk_base
mov r2, #1
sys_clk_ref_selected:
ldr r1, [r0, #0x44]
and r1, r1, r2
cmp r1, r2
bne sys_clk_ref_selected
// Change the aux clock to pll, will glitch but it's fine because we're on the ref clock as source now.
ldr r0, =clk_clr
mov r1, #0b111
lsl r1, r1, #5 // Clear all bits on AUXSRC, which will make it CLKSRC_PLL_SYS
str r1, [r0, #0x3c]
// Glitchlessly change the sys source to AUX
ldr r0, =clk_set
mov r1, #1
str r1, [r0, #0x3c]
// Wait for it to be selected
ldr r0, =clk_base
mov r2, #0b10
sys_clk_aux_selected:
ldr r1, [r0, #0x44]
and r1, r1, r2
cmp r1, r2
bne sys_clk_aux_selected
configure_peripheral:
// See: https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/src/rp2_common/hardware_gpio/gpio.c#L38
// Set pad input and output enabled.