rp2: perform lazy block init to save power

This changes the machine init process for the rp2040/rp2350
to only unreset aka make available the minimum needed peripherals
in order to try to save power use.

I2C, SPI, and other devices unreset themselves as needed as used.

Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
deadprogram
2026-01-12 01:33:04 +01:00
parent ca36fba7e4
commit cde28db20e
7 changed files with 15 additions and 37 deletions
+1 -6
View File
@@ -49,15 +49,10 @@ func machineInit() {
bits := ^uint32(initDontReset)
resetBlock(bits)
// Remove reset from peripherals which are clocked only by clkSys and
// clkRef. Other peripherals stay in reset until we've configured clocks.
bits = ^uint32(initUnreset)
unresetBlockWait(bits)
clocks.init()
// Peripheral clocks should now all be running
unresetBlockWait(RESETS_RESET_Msk)
unresetBlockWait(initUnreset)
// DBGPAUSE pauses the timer when a debugger is connected. This prevents
// sleep functions from ever returning, so disable it.
+2 -7
View File
@@ -15,13 +15,8 @@ const (
_NUMIRQ = 32
rp2350ExtraReg = 0
RESETS_RESET_Msk = 0x01ffffff
initUnreset = rp.RESETS_RESET_ADC |
rp.RESETS_RESET_RTC |
rp.RESETS_RESET_SPI0 |
rp.RESETS_RESET_SPI1 |
rp.RESETS_RESET_UART0 |
rp.RESETS_RESET_UART1 |
rp.RESETS_RESET_USBCTRL
initUnreset = rp.RESETS_RESET_IO_BANK0 |
rp.RESETS_RESET_TIMER
initDontReset = rp.RESETS_RESET_IO_QSPI |
rp.RESETS_RESET_PADS_QSPI |
rp.RESETS_RESET_PLL_USB |
+2 -6
View File
@@ -16,12 +16,8 @@ const (
_NUMIRQ = 51
notimpl = "rp2350: not implemented"
RESETS_RESET_Msk = 0x1fffffff
initUnreset = rp.RESETS_RESET_ADC |
rp.RESETS_RESET_SPI0 |
rp.RESETS_RESET_SPI1 |
rp.RESETS_RESET_UART0 |
rp.RESETS_RESET_UART1 |
rp.RESETS_RESET_USBCTRL
initUnreset = rp.RESETS_RESET_IO_BANK0 |
rp.RESETS_RESET_TIMER0
initDontReset = rp.RESETS_RESET_USBCTRL |
rp.RESETS_RESET_SYSCFG |
rp.RESETS_RESET_PLL_USB |
+4 -4
View File
@@ -19,10 +19,10 @@ var adcAref uint32
// InitADC resets the ADC peripheral.
func InitADC() {
rp.RESETS.RESET.SetBits(rp.RESETS_RESET_ADC)
rp.RESETS.RESET.ClearBits(rp.RESETS_RESET_ADC)
for !rp.RESETS.RESET_DONE.HasBits(rp.RESETS_RESET_ADC) {
}
// reset ADC controller
resetBlock(rp.RESETS_RESET_ADC)
unresetBlockWait(rp.RESETS_RESET_ADC)
// enable ADC
rp.ADC.CS.Set(rp.ADC_CS_EN)
adcAref = 3300
+2 -5
View File
@@ -259,10 +259,7 @@ func (i2c *I2C) init(config I2CConfig) error {
//go:inline
func (i2c *I2C) reset() {
resetVal := i2c.deinit()
rp.RESETS.RESET.ClearBits(resetVal)
// Wait until reset is done.
for !rp.RESETS.RESET_DONE.HasBits(resetVal) {
}
unresetBlockWait(resetVal)
}
// deinit sets reset bit for I2C. Must call reset to reenable I2C after deinit.
@@ -276,7 +273,7 @@ func (i2c *I2C) deinit() (resetVal uint32) {
resetVal = rp.RESETS_RESET_I2C1
}
// Perform I2C reset.
rp.RESETS.RESET.SetBits(resetVal)
resetBlock(resetVal)
return resetVal
}
+2 -5
View File
@@ -212,10 +212,7 @@ func (spi *SPI) setFormat(mode uint8) {
//go:inline
func (spi *SPI) reset() {
resetVal := spi.deinit()
rp.RESETS.RESET.ClearBits(resetVal)
// Wait until reset is done.
for !rp.RESETS.RESET_DONE.HasBits(resetVal) {
}
unresetBlockWait(resetVal)
}
//go:inline
@@ -227,7 +224,7 @@ func (spi *SPI) deinit() (resetVal uint32) {
resetVal = rp.RESETS_RESET_SPI1
}
// Perform SPI reset.
rp.RESETS.RESET.SetBits(resetVal)
resetBlock(resetVal)
return resetVal
}
+2 -4
View File
@@ -148,10 +148,8 @@ func initUART(uart *UART) {
}
// reset UART
rp.RESETS.RESET.SetBits(resetVal)
rp.RESETS.RESET.ClearBits(resetVal)
for !rp.RESETS.RESET_DONE.HasBits(resetVal) {
}
resetBlock(resetVal)
unresetBlockWait(resetVal)
}
// handleInterrupt should be called from the appropriate interrupt handler for