diff --git a/cpu/cc26x0/include/cc26x0_prcm.h b/cpu/cc26x0/include/cc26x0_prcm.h index 562e5ef56b..1c7a1fe1e0 100644 --- a/cpu/cc26x0/include/cc26x0_prcm.h +++ b/cpu/cc26x0/include/cc26x0_prcm.h @@ -337,6 +337,10 @@ typedef struct { #define PDSTAT1_CPU_ON 0x2 #define PDSTAT1_RFC_ON 0x4 #define PDSTAT1_VIMS_ON 0x8 + +#define GPIOCLKGR_CLK_EN 0x1 +#define I2CCLKGR_CLK_EN 0x1 +#define UARTCLKGR_CLK_EN_UART0 0x1 /** @} */ /** @ingroup cpu_specific_peripheral_memory_map diff --git a/cpu/cc26x0/periph/i2c.c b/cpu/cc26x0/periph/i2c.c index 5b7ffaaa29..db6ffcc7ab 100644 --- a/cpu/cc26x0/periph/i2c.c +++ b/cpu/cc26x0/periph/i2c.c @@ -31,6 +31,8 @@ #include "cpu.h" #include "periph/i2c.h" +#include "cc26xx_cc13xx_power.h" + #define ENABLE_DEBUG 0 #include "debug.h" @@ -96,17 +98,14 @@ void i2c_init(i2c_t devnum) /* Make sure everything is shut off in case of reinit */ I2C->MCR = 0; - PRCM->I2CCLKGR = 0; /* Enable serial power domain */ if (!power_is_domain_enabled(POWER_DOMAIN_SERIAL)) { power_enable_domain(POWER_DOMAIN_SERIAL); } - /* enable i2c clock in run mode */ - PRCM->I2CCLKGR = 1; - PRCM->CLKLOADCTL |= CLKLOADCTL_LOAD; - while (!(PRCM->CLKLOADCTL & CLKLOADCTL_LOADDONE)) {} + /* enable I2C clock in run mode */ + power_clock_enable_i2c(); /* configure pins */ IOC->CFG[I2C_SDA_PIN] = (IOCFG_PORTID_I2C_MSSDA diff --git a/cpu/cc26x2_cc13x2/include/cc26x2_cc13x2_prcm.h b/cpu/cc26x2_cc13x2/include/cc26x2_cc13x2_prcm.h index 246d333ea1..24d2e44628 100644 --- a/cpu/cc26x2_cc13x2/include/cc26x2_cc13x2_prcm.h +++ b/cpu/cc26x2_cc13x2/include/cc26x2_cc13x2_prcm.h @@ -254,6 +254,11 @@ typedef struct { #define PDSTAT1_CPU_ON 0x2 #define PDSTAT1_RFC_ON 0x4 #define PDSTAT1_VIMS_ON 0x8 + +#define GPIOCLKGR_CLK_EN 0x1 +#define I2CCLKGR_CLK_EN 0x1 +#define UARTCLKGR_CLK_EN_UART0 0x1 +#define UARTCLKGR_CLK_EN_UART1 0x1 /** @} */ /** @ingroup cpu_specific_peripheral_memory_map diff --git a/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx_power.h b/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx_power.h index 5f55de24b3..d14723df17 100644 --- a/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx_power.h +++ b/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx_power.h @@ -22,6 +22,8 @@ #include #include +#include "periph/uart.h" + #ifdef __cplusplus extern "C" { #endif @@ -50,10 +52,41 @@ bool power_is_domain_enabled(const power_domain_t domain); /** * @brief Enable the specified power domain. * - * @params[in] domain The domain. + * @param[in] domain The domain. */ void power_enable_domain(const power_domain_t domain); +/** + * @brief Enable GPIO clock + */ +void power_clock_enable_gpio(void); + +/** + * @brief Enable General Purpose Timer clock + * + * @param[in] tim The timer to enable + */ +void power_clock_enable_gpt(uint32_t tim); + +/** + * @brief Enable I2C clock + */ +void power_clock_enable_i2c(void); + +/** + * @brief Enable UART clocks + * + * @param[in] uart The UART number + */ +void power_clock_enable_uart(uart_t uart); + +/** + * @brief Disable UART clocks + * + * @param[in] uart The UART number + */ +void power_clock_disable_uart(uart_t uart); + #ifdef __cplusplus } /* end extern "C" */ #endif diff --git a/cpu/cc26xx_cc13xx/periph/gpio.c b/cpu/cc26xx_cc13xx/periph/gpio.c index 5a0aa91a31..74fd13f1fa 100644 --- a/cpu/cc26xx_cc13xx/periph/gpio.c +++ b/cpu/cc26xx_cc13xx/periph/gpio.c @@ -22,6 +22,8 @@ #include "cpu.h" #include "periph/gpio.h" +#include "cc26xx_cc13xx_power.h" + #define DOE_SHIFT (29U) #ifdef MODULE_PERIPH_GPIO_IRQ @@ -44,9 +46,7 @@ int gpio_init(gpio_t pin, gpio_mode_t mode) } /* enable GPIO clock */ - PRCM->GPIOCLKGR |= 1; - PRCM->CLKLOADCTL |= CLKLOADCTL_LOAD; - while (!(PRCM->CLKLOADCTL & CLKLOADCTL_LOADDONE)) ; + power_clock_enable_gpio(); /* configure the GPIO mode */ IOC->CFG[pin] = mode; diff --git a/cpu/cc26xx_cc13xx/periph/timer.c b/cpu/cc26xx_cc13xx/periph/timer.c index 396fcd1b3b..8cd9db7411 100644 --- a/cpu/cc26xx_cc13xx/periph/timer.c +++ b/cpu/cc26xx_cc13xx/periph/timer.c @@ -29,6 +29,8 @@ #include "periph_conf.h" #include "periph/timer.h" +#include "cc26xx_cc13xx_power.h" + #define ENABLE_DEBUG (0) #include "debug.h" @@ -105,9 +107,7 @@ int timer_init(tim_t tim, unsigned long freq, timer_cb_t cb, void *arg) } /* enable the timer clock */ - PRCM->GPTCLKGR |= (1 << tim); - PRCM->CLKLOADCTL = CLKLOADCTL_LOAD; - while (!(PRCM->CLKLOADCTL & CLKLOADCTL_LOADDONE)) {} + power_clock_enable_gpt(tim); /* disable (and reset) timer */ dev(tim)->CTL = 0; diff --git a/cpu/cc26xx_cc13xx/periph/uart.c b/cpu/cc26xx_cc13xx/periph/uart.c index c93de7bdbb..a4306f4703 100644 --- a/cpu/cc26xx_cc13xx/periph/uart.c +++ b/cpu/cc26xx_cc13xx/periph/uart.c @@ -24,6 +24,8 @@ #include "periph/uart.h" #include "periph_conf.h" +#include "cc26xx_cc13xx_power.h" + /** * @brief Bit mask for the fractional part of the baudrate */ @@ -161,9 +163,8 @@ void uart_poweron(uart_t uart) uart_regs_t *uart_reg = uart_config[uart].regs; - PRCM->UARTCLKGR |= 0x1; - PRCM->CLKLOADCTL = CLKLOADCTL_LOAD; - while (!(PRCM->CLKLOADCTL & CLKLOADCTL_LOADDONE)) {} + /* Enable clock for this UART */ + power_clock_enable_uart(uart); uart_reg->CTL = ENABLE_MASK; } @@ -176,10 +177,8 @@ void uart_poweroff(uart_t uart) uart_reg->CTL = 0; - PRCM->UARTCLKGR = 0; - PRCM->CLKLOADCTL = CLKLOADCTL_LOAD; - while (!(PRCM->CLKLOADCTL & CLKLOADCTL_LOADDONE)) {} - + /* Disable clock for this UART */ + power_clock_disable_uart(uart); } static void isr_uart(uart_t uart) diff --git a/cpu/cc26xx_cc13xx/power_arch.c b/cpu/cc26xx_cc13xx/power_arch.c index f6910aa011..28abea1c07 100644 --- a/cpu/cc26xx_cc13xx/power_arch.c +++ b/cpu/cc26xx_cc13xx/power_arch.c @@ -19,9 +19,21 @@ */ #include "cpu.h" +#include "cc26xx_cc13xx_power.h" #define DOMAIN_ON (1) +/* Save changes of the PRCM */ +static void prcm_commit(void) +{ + /* Write CLKLOADCTL in the non-buffered register bank to avoid buffered + * writes */ + PRCM_NONBUF->CLKLOADCTL = CLKLOADCTL_LOAD; + + /* Wait while load is done */ + while (!(PRCM->CLKLOADCTL & CLKLOADCTL_LOADDONE)) {} +} + bool power_is_domain_enabled(const power_domain_t domain) { switch (domain) { @@ -80,3 +92,50 @@ void power_enable_domain(const power_domain_t domain) while (!power_is_domain_enabled(domain)) {} } + +void power_clock_enable_gpio(void) +{ + PRCM->GPIOCLKGR = GPIOCLKGR_CLK_EN; + + prcm_commit(); +} + +void power_clock_enable_gpt(uint32_t tim) +{ + PRCM->GPTCLKGR |= (1 << tim); + + prcm_commit(); +} +void power_clock_enable_i2c(void) { + PRCM->I2CCLKGR = I2CCLKGR_CLK_EN; + + prcm_commit(); +} + +void power_clock_enable_uart(uart_t uart) +{ + if (uart == 0) { + PRCM->UARTCLKGR |= UARTCLKGR_CLK_EN_UART0; + } +#ifdef UARTCLKGR_CLK_EN_UART1 + else if (uart == 1) { + PRCM->UARTCLKGR |= UARTCLKGR_CLK_EN_UART1; + } +#endif + + prcm_commit(); +} + +void power_clock_disable_uart(uart_t uart) +{ + if (uart == 0) { + PRCM->UARTCLKGR &= ~UARTCLKGR_CLK_EN_UART0; + } +#ifdef UARTCLKGR_CLK_EN_UART1 + else if (uart == 1) { + PRCM->UARTCLKGR &= ~UARTCLKGR_CLK_EN_UART1; + } +#endif + + prcm_commit(); +}