1
0
Fork 0
forked from nuttx/nuttx-update

Support RP2040 Clock Outputs

This commit is contained in:
Adam Comley 2024-02-03 10:10:31 -06:00 committed by Xiang Xiao
parent 3594e3e541
commit 399cd88e7f
5 changed files with 350 additions and 4 deletions

View file

@ -23,6 +23,7 @@ USB
PIO RP2040 Programmable I/O
IRQs
DMA
Clock Output
ws2812 Smart pixels (e.g. Neopixel)
Flash ROM Boot
SRAM Boot If Pico SDK is available a nuttx.uf2 file will be created

View file

@ -663,6 +663,218 @@ endif # ADC
endif # RP2040_ADC
#####################################################################
# CLK_GPOUT Configuration
#####################################################################
menuconfig RP2040_CLK_GPOUT_ENABLE
bool "Enable Clock Outputs"
default n
if RP2040_CLK_GPOUT_ENABLE
config RP2040_CLK_GPOUT0
bool "CLK_GPOUT0 Clock Output (pin 21)"
default n
---help---
Enable CLK_GPOUT0
if RP2040_CLK_GPOUT0
choice
prompt "Source Clock"
config RP2040_CLK_GPOUT0_SRC_REF
bool "REF (6 - 12 MHz)"
---help---
Reference clock that is always running unless in DORMANT mode. Runs from
Ring Oscillator (ROSC) at power-up but can be switched to Crystal
Oscillator (XOSC) for more accuracy.
config RP2040_CLK_GPOUT0_SRC_SYS
bool "SYS (125 MHz)"
---help---
System clock that is always running unless in DORMANT mode. Runs from
clk_ref at power-up but is typically switched to a PLL.
config RP2040_CLK_GPOUT0_SRC_USB
bool "USB (48 MHz)"
---help---
USB reference clock. Must be 48MHz.
config RP2040_CLK_GPOUT0_SRC_ADC
bool "ADC (48 MHz)"
---help---
ADC reference clock. Must be 48MHz.
config RP2040_CLK_GPOUT0_SRC_RTC
bool "RTC (46875 Hz)"
---help---
RTC reference clock. The RTC divides this clock to generate a 1 second reference.
endchoice
config RP2040_CLK_GPOUT0_DIVINT
int "Divisor (Integer)"
default 1
config RP2040_CLK_GPOUT0_DIVFRAC
int "Divisor (Fractional)"
default 0
endif # RP2040_CLK_GPOUT0
config RP2040_CLK_GPOUT1
bool "CLK_GPOUT1 Clock Output (pin 23)"
default n
---help---
Enable CLK_GPOUT1
if RP2040_CLK_GPOUT1
choice
prompt "Source Clock"
config RP2040_CLK_GPOUT1_SRC_REF
bool "REF (6 - 12 MHz)"
---help---
Reference clock that is always running unless in DORMANT mode. Runs from
Ring Oscillator (ROSC) at power-up but can be switched to Crystal
Oscillator (XOSC) for more accuracy.
config RP2040_CLK_GPOUT1_SRC_SYS
bool "SYS (125 MHz)"
---help---
System clock that is always running unless in DORMANT mode. Runs from
clk_ref at power-up but is typically switched to a PLL.
config RP2040_CLK_GPOUT1_SRC_USB
bool "USB (48 MHz)"
---help---
USB reference clock. Must be 48MHz.
config RP2040_CLK_GPOUT1_SRC_ADC
bool "ADC (48 MHz)"
---help---
ADC reference clock. Must be 48MHz.
config RP2040_CLK_GPOUT1_SRC_RTC
bool "RTC (46875 Hz)"
---help---
RTC reference clock. The RTC divides this clock to generate a 1 second reference.
endchoice
config RP2040_CLK_GPOUT1_DIVINT
int "Divisor (Integer)"
default 1
config RP2040_CLK_GPOUT1_DIVFRAC
int "Divisor (Fractional)"
default 0
endif # RP2040_CLK_GPOUT1
config RP2040_CLK_GPOUT2
bool "CLK_GPOUT2 Clock Output (pin 24)"
default n
---help---
Enable CLK_GPOUT2
if RP2040_CLK_GPOUT2
choice
prompt "Source Clock"
config RP2040_CLK_GPOUT2_SRC_REF
bool "REF (6 - 12 MHz)"
---help---
Reference clock that is always running unless in DORMANT mode. Runs from
Ring Oscillator (ROSC) at power-up but can be switched to Crystal
Oscillator (XOSC) for more accuracy.
config RP2040_CLK_GPOUT2_SRC_SYS
bool "SYS (125 MHz)"
---help---
System clock that is always running unless in DORMANT mode. Runs from
clk_ref at power-up but is typically switched to a PLL.
config RP2040_CLK_GPOUT2_SRC_USB
bool "USB (48 MHz)"
---help---
USB reference clock. Must be 48MHz.
config RP2040_CLK_GPOUT2_SRC_ADC
bool "ADC (48 MHz)"
---help---
ADC reference clock. Must be 48MHz.
config RP2040_CLK_GPOUT2_SRC_RTC
bool "RTC (46875 Hz)"
---help---
RTC reference clock. The RTC divides this clock to generate a 1 second reference.
endchoice
config RP2040_CLK_GPOUT2_DIVINT
int "Divisor (Integer)"
default 1
config RP2040_CLK_GPOUT2_DIVFRAC
int "Divisor (Fractional)"
default 0
endif # RP2040_CLK_GPOUT2
config RP2040_CLK_GPOUT3
bool "CLK_GPOUT3 Clock Output (pin 25)"
default n
---help---
Enable CLK_GPOUT3
if RP2040_CLK_GPOUT3
choice
prompt "Source Clock"
config RP2040_CLK_GPOUT3_SRC_REF
bool "REF (6 - 12 MHz)"
---help---
Reference clock that is always running unless in DORMANT mode. Runs from
Ring Oscillator (ROSC) at power-up but can be switched to Crystal
Oscillator (XOSC) for more accuracy.
config RP2040_CLK_GPOUT3_SRC_SYS
bool "SYS (125 MHz)"
---help---
System clock that is always running unless in DORMANT mode. Runs from
clk_ref at power-up but is typically switched to a PLL.
config RP2040_CLK_GPOUT3_SRC_USB
bool "USB (48 MHz)"
---help---
USB reference clock. Must be 48MHz.
config RP2040_CLK_GPOUT3_SRC_ADC
bool "ADC (48 MHz)"
---help---
ADC reference clock. Must be 48MHz.
config RP2040_CLK_GPOUT3_SRC_RTC
bool "RTC (46875 Hz)"
---help---
RTC reference clock. The RTC divides this clock to generate a 1 second reference.
endchoice
config RP2040_CLK_GPOUT3_DIVINT
int "Divisor (Integer)"
default 1
config RP2040_CLK_GPOUT3_DIVFRAC
int "Divisor (Fractional)"
default 0
endif # RP2040_CLK_GPOUT3
endif # RP2040_CLK_GPOUT_ENABLE
#####################################################################
# WS2812 Configuration
#####################################################################

View file

@ -81,6 +81,30 @@ static inline bool has_glitchless_mux(int clk_index)
clk_index == RP2040_CLOCKS_NDX_REF;
}
#if defined(CONFIG_RP2040_CLK_GPOUT_ENABLE)
static bool rp2040_clock_configure_gpout(int clk_index,
uint32_t src,
uint32_t div_int,
uint32_t div_frac)
{
if (clk_index > RP2040_CLOCKS_NDX_GPOUT3 ||
clk_index < RP2040_CLOCKS_NDX_GPOUT0 ||
(src >> RP2040_CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_SHIFT) > 0xa)
{
return false;
}
putreg32((div_int << RP2040_CLOCKS_CLK_GPOUT0_DIV_INT_SHIFT) |
(div_frac & RP2040_CLOCKS_CLK_GPOUT0_DIV_FRAC_MASK),
(RP2040_CLOCKS_CLK_NDX_DIV(clk_index)));
putreg32((src << RP2040_CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_SHIFT) |
RP2040_CLOCKS_CLK_GPOUT0_CTRL_ENABLE,
(RP2040_CLOCKS_CLK_NDX_CTRL(clk_index)));
return true;
}
#endif
bool rp2040_clock_configure(int clk_index,
uint32_t src, uint32_t auxsrc,
uint32_t src_freq, uint32_t freq)
@ -274,6 +298,91 @@ void clocks_init(void)
RP2040_CLOCKS_CLK_PERI_CTRL_AUXSRC_CLK_SYS,
BOARD_SYS_FREQ,
BOARD_PERI_FREQ);
#if defined(CONFIG_RP2040_CLK_GPOUT_ENABLE)
uint32_t src;
#if defined(CONFIG_RP2040_CLK_GPOUT0)
#if defined(CONFIG_RP2040_CLK_GPOUT0_SRC_REF)
src = RP2040_CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_CLK_REF;
#elif defined(CONFIG_RP2040_CLK_GPOUT0_SRC_SYS)
src = RP2040_CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_CLK_SYS;
#elif defined(CONFIG_RP2040_CLK_GPOUT0_SRC_USB)
src = RP2040_CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_CLK_USB;
#elif defined(CONFIG_RP2040_CLK_GPOUT0_SRC_ADC)
src = RP2040_CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_CLK_ADC;
#elif defined(CONFIG_RP2040_CLK_GPOUT0_SRC_RTC)
src = RP2040_CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_CLK_RTC;
#else
src = 0;
#endif
rp2040_clock_configure_gpout(RP2040_CLOCKS_NDX_GPOUT0,
src,
CONFIG_RP2040_CLK_GPOUT0_DIVINT,
CONFIG_RP2040_CLK_GPOUT0_DIVFRAC);
#endif
#if defined(CONFIG_RP2040_CLK_GPOUT1)
#if defined(CONFIG_RP2040_CLK_GPOUT1_SRC_REF)
src = RP2040_CLOCKS_CLK_GPOUT1_CTRL_AUXSRC_CLK_REF;
#elif defined(CONFIG_RP2040_CLK_GPOUT1_SRC_SYS)
src = RP2040_CLOCKS_CLK_GPOUT1_CTRL_AUXSRC_CLK_SYS;
#elif defined(CONFIG_RP2040_CLK_GPOUT1_SRC_USB)
src = RP2040_CLOCKS_CLK_GPOUT1_CTRL_AUXSRC_CLK_USB;
#elif defined(CONFIG_RP2040_CLK_GPOUT1_SRC_ADC)
src = RP2040_CLOCKS_CLK_GPOUT1_CTRL_AUXSRC_CLK_ADC;
#elif defined(CONFIG_RP2040_CLK_GPOUT1_SRC_RTC)
src = RP2040_CLOCKS_CLK_GPOUT1_CTRL_AUXSRC_CLK_RTC;
#else
src = 0;
#endif
rp2040_clock_configure_gpout(RP2040_CLOCKS_NDX_GPOUT1,
src,
CONFIG_RP2040_CLK_GPOUT1_DIVINT,
CONFIG_RP2040_CLK_GPOUT1_DIVFRAC);
#endif
#if defined(CONFIG_RP2040_CLK_GPOUT2)
#if defined(CONFIG_RP2040_CLK_GPOUT2_SRC_REF)
src = RP2040_CLOCKS_CLK_GPOUT2_CTRL_AUXSRC_CLK_REF;
#elif defined(CONFIG_RP2040_CLK_GPOUT2_SRC_SYS)
src = RP2040_CLOCKS_CLK_GPOUT2_CTRL_AUXSRC_CLK_SYS;
#elif defined(CONFIG_RP2040_CLK_GPOUT2_SRC_USB)
src = RP2040_CLOCKS_CLK_GPOUT2_CTRL_AUXSRC_CLK_USB;
#elif defined(CONFIG_RP2040_CLK_GPOUT2_SRC_ADC)
src = RP2040_CLOCKS_CLK_GPOUT2_CTRL_AUXSRC_CLK_ADC;
#elif defined(CONFIG_RP2040_CLK_GPOUT2_SRC_RTC)
src = RP2040_CLOCKS_CLK_GPOUT2_CTRL_AUXSRC_CLK_RTC;
#else
src = 0;
#endif
rp2040_clock_configure_gpout(RP2040_CLOCKS_NDX_GPOUT2,
src,
CONFIG_RP2040_CLK_GPOUT2_DIVINT,
CONFIG_RP2040_CLK_GPOUT2_DIVFRAC);
#endif
#if defined(CONFIG_RP2040_CLK_GPOUT3)
#if defined(CONFIG_RP2040_CLK_GPOUT3_SRC_REF)
src = RP2040_CLOCKS_CLK_GPOUT3_CTRL_AUXSRC_CLK_REF;
#elif defined(CONFIG_RP2040_CLK_GPOUT3_SRC_SYS)
src = RP2040_CLOCKS_CLK_GPOUT3_CTRL_AUXSRC_CLK_SYS;
#elif defined(CONFIG_RP2040_CLK_GPOUT3_SRC_USB)
src = RP2040_CLOCKS_CLK_GPOUT3_CTRL_AUXSRC_CLK_USB;
#elif defined(CONFIG_RP2040_CLK_GPOUT3_SRC_ADC)
src = RP2040_CLOCKS_CLK_GPOUT3_CTRL_AUXSRC_CLK_ADC;
#elif defined(CONFIG_RP2040_CLK_GPOUT3_SRC_RTC)
src = RP2040_CLOCKS_CLK_GPOUT3_CTRL_AUXSRC_CLK_RTC;
#else
src = 0;
#endif
rp2040_clock_configure_gpout(RP2040_CLOCKS_NDX_GPOUT3,
src,
CONFIG_RP2040_CLK_GPOUT3_DIVINT,
CONFIG_RP2040_CLK_GPOUT3_DIVFRAC);
#endif
#endif
}
/****************************************************************************

View file

@ -55,12 +55,19 @@
#define RP2040_GPIO_FUNC_USB RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_USB
#define RP2040_GPIO_FUNC_NULL RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_NULL
/* GPIO function pins *******************************************************/
#define RP2040_GPIO_PIN_CLK_GPOUT0 (21)
#define RP2040_GPIO_PIN_CLK_GPOUT1 (23)
#define RP2040_GPIO_PIN_CLK_GPOUT2 (24)
#define RP2040_GPIO_PIN_CLK_GPOUT3 (25)
/* GPIO interrupt modes *****************************************************/
#define RP2040_GPIO_INTR_LEVEL_LOW 0
#define RP2040_GPIO_INTR_LEVEL_HIGH 1
#define RP2040_GPIO_INTR_EDGE_LOW 2
#define RP2040_GPIO_INTR_EDGE_HIGH 3
#define RP2040_GPIO_INTR_LEVEL_LOW 0
#define RP2040_GPIO_INTR_LEVEL_HIGH 1
#define RP2040_GPIO_INTR_EDGE_LOW 2
#define RP2040_GPIO_INTR_EDGE_HIGH 3
/****************************************************************************
* Public Types

View file

@ -94,6 +94,23 @@ void rp2040_common_earlyinitialize(void)
RP2040_GPIO_FUNC_UART); /* RTS */
#endif
#endif
#if defined(CONFIG_RP2040_CLK_GPOUT0)
rp2040_gpio_set_function(RP2040_GPIO_PIN_CLK_GPOUT0,
RP2040_GPIO_FUNC_CLOCKS);
#endif
#if defined(CONFIG_RP2040_CLK_GPOUT1)
rp2040_gpio_set_function(RP2040_GPIO_PIN_CLK_GPOUT1,
RP2040_GPIO_FUNC_CLOCKS);
#endif
#if defined(CONFIG_RP2040_CLK_GPOUT2)
rp2040_gpio_set_function(RP2040_GPIO_PIN_CLK_GPOUT2,
RP2040_GPIO_FUNC_CLOCKS);
#endif
#if defined(CONFIG_RP2040_CLK_GPOUT3)
rp2040_gpio_set_function(RP2040_GPIO_PIN_CLK_GPOUT3,
RP2040_GPIO_FUNC_CLOCKS);
#endif
}
/****************************************************************************