From 4643ed573342a09238d23c215335dbedbc9a1074 Mon Sep 17 00:00:00 2001 From: Jean Pierre Dudey Date: Fri, 13 Mar 2020 01:23:25 -0500 Subject: [PATCH] cc26xx_cc13xx: add power abstraction Signed-off-by: Jean Pierre Dudey --- cpu/cc26x2_cc13x2/Makefile.dep | 2 + .../include/cc26xx_cc13xx_power.h | 63 ++++++++++++++ cpu/cc26xx_cc13xx/periph/gpio.c | 7 +- cpu/cc26xx_cc13xx/periph/uart.c | 6 +- cpu/cc26xx_cc13xx/power_arch.c | 82 +++++++++++++++++++ 5 files changed, 156 insertions(+), 4 deletions(-) create mode 100644 cpu/cc26xx_cc13xx/include/cc26xx_cc13xx_power.h create mode 100644 cpu/cc26xx_cc13xx/power_arch.c diff --git a/cpu/cc26x2_cc13x2/Makefile.dep b/cpu/cc26x2_cc13x2/Makefile.dep index a0a73e54fe..cb4d821401 100644 --- a/cpu/cc26x2_cc13x2/Makefile.dep +++ b/cpu/cc26x2_cc13x2/Makefile.dep @@ -1 +1,3 @@ +USEMODULE += cc26xx_cc13xx + include ${RIOTCPU}/cc26xx_cc13xx/Makefile.dep diff --git a/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx_power.h b/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx_power.h new file mode 100644 index 0000000000..5f55de24b3 --- /dev/null +++ b/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx_power.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2020 Locha Inc + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_cc26xx_cc13xx + * @{ + * + * @file + * @brief CC26xx/CC13xx Power management + * + * @author Jean Pierre Dudey + */ + +#ifndef CC26XX_CC13XX_POWER_H +#define CC26XX_CC13XX_POWER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Power domains + */ +typedef enum { + POWER_DOMAIN_PERIPHERALS, /**< Peripherals domain */ + POWER_DOMAIN_SERIAL, /**< Serial domain */ + POWER_DOMAIN_RFC, /**< RF Core domain */ + POWER_DOMAIN_CPU, /**< CPU domain */ + POWER_DOMAIN_VIMS, /**< VIMS domain */ +} power_domain_t; + +/** + * @brief Is power domain enabled? + * + * @param[in] domain The domain. + * + * @return true Is enabled. + * @return false Is not enabled. + */ +bool power_is_domain_enabled(const power_domain_t domain); + +/** + * @brief Enable the specified power domain. + * + * @params[in] domain The domain. + */ +void power_enable_domain(const power_domain_t domain); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* CC26XX_CC13XX_POWER_H */ + +/*@}*/ diff --git a/cpu/cc26xx_cc13xx/periph/gpio.c b/cpu/cc26xx_cc13xx/periph/gpio.c index 1c8345d020..5a0aa91a31 100644 --- a/cpu/cc26xx_cc13xx/periph/gpio.c +++ b/cpu/cc26xx_cc13xx/periph/gpio.c @@ -38,9 +38,12 @@ int gpio_init(gpio_t pin, gpio_mode_t mode) if ((unsigned int)pin > 31) return -1; + /* enable peripherals power domain */ + if (!power_is_domain_enabled(POWER_DOMAIN_PERIPHERALS)) { + power_enable_domain(POWER_DOMAIN_PERIPHERALS); + } + /* enable GPIO clock */ - PRCM->PDCTL0 |= PDCTL0_PERIPH_ON; - while(!(PRCM->PDSTAT0 & PDSTAT0_PERIPH_ON)) ; PRCM->GPIOCLKGR |= 1; PRCM->CLKLOADCTL |= CLKLOADCTL_LOAD; while (!(PRCM->CLKLOADCTL & CLKLOADCTL_LOADDONE)) ; diff --git a/cpu/cc26xx_cc13xx/periph/uart.c b/cpu/cc26xx_cc13xx/periph/uart.c index e65f85140a..c93de7bdbb 100644 --- a/cpu/cc26xx_cc13xx/periph/uart.c +++ b/cpu/cc26xx_cc13xx/periph/uart.c @@ -57,9 +57,11 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) int rts_pin = uart_config[uart].rts_pin; int cts_pin = uart_config[uart].cts_pin; #endif + /* enable clocks: serial power domain and UART */ - PRCM->PDCTL0SERIAL = 1; - while (!(PRCM->PDSTAT0 & PDSTAT0_SERIAL_ON)) ; + if (!power_is_domain_enabled(POWER_DOMAIN_SERIAL)) { + power_enable_domain(POWER_DOMAIN_SERIAL); + } uart_poweron(uart); /* disable and reset the UART */ diff --git a/cpu/cc26xx_cc13xx/power_arch.c b/cpu/cc26xx_cc13xx/power_arch.c new file mode 100644 index 0000000000..f6910aa011 --- /dev/null +++ b/cpu/cc26xx_cc13xx/power_arch.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2020 Locha Inc + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_cc26xx_cc13xx + * @{ + * + * @file + * @brief Power management abstractions + * + * @author Jean Pierre Dudey + * + * @} + */ + +#include "cpu.h" + +#define DOMAIN_ON (1) + +bool power_is_domain_enabled(const power_domain_t domain) +{ + switch (domain) { + case POWER_DOMAIN_PERIPHERALS: + return PRCM->PDSTAT0PERIPH == DOMAIN_ON; + + case POWER_DOMAIN_SERIAL: + return PRCM->PDSTAT0SERIAL == DOMAIN_ON; + + case POWER_DOMAIN_RFC: + /* At least one of the registers need to indicate that the power + * domain is on */ + return (PRCM->PDSTAT1RFC == DOMAIN_ON) || + (PRCM->PDSTAT0RFC == DOMAIN_ON); + + case POWER_DOMAIN_VIMS: + return PRCM->PDSTAT1VIMS == DOMAIN_ON; + + case POWER_DOMAIN_CPU: + return PRCM->PDSTAT1CPU == DOMAIN_ON; + + default: + return false; + } + + return false; +} + +void power_enable_domain(const power_domain_t domain) +{ + switch (domain) { + case POWER_DOMAIN_PERIPHERALS: + PRCM->PDCTL0PERIPH = DOMAIN_ON; + break; + + case POWER_DOMAIN_SERIAL: + PRCM->PDCTL0SERIAL = DOMAIN_ON; + break; + + case POWER_DOMAIN_RFC: + /* On CC26x0 MCUs PDCTL1RFC needs to be written too in order to + * enable the RF Core power domain. On `cc13x2_cc26x2` it's not + * necessary and domain is powered normally. */ + PRCM->PDCTL0RFC = DOMAIN_ON; + PRCM->PDCTL1RFC = DOMAIN_ON; + break; + + case POWER_DOMAIN_CPU: + PRCM->PDCTL1CPU = DOMAIN_ON; + break; + + case POWER_DOMAIN_VIMS: + PRCM->PDCTL1VIMS = DOMAIN_ON; + break; + } + + while (!power_is_domain_enabled(domain)) {} +}