diff options
author | Craig Hesling <hesling@chromium.org> | 2019-10-31 16:56:07 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-11-08 22:58:57 +0000 |
commit | ecde5dcec0745c56b90d27f307e3504fff20c6ef (patch) | |
tree | a23db65ffae4aa0586956f123aa8047cc8b6b172 | |
parent | 69bbeb8af0a300aef51e70e31f1c2c102bc501f6 (diff) | |
download | chrome-ec-ecde5dcec0745c56b90d27f307e3504fff20c6ef.tar.gz |
stm32f4: Enable gpio port clocks that are used
We can reduce the power draw of the MCU by limiting which
GPIO port clocks are enabled.
This CL uses the gpio.inc to determine the minimal set of
GPIO ports that need to be enabled/clocked. Only these
ports have their clocks enabled at boot.
Other stm32 chip variants in EC simply enabled all GPIO
port clocks at boot init.
Thank you to Ravi Chandra Sadineni for identifying this optimization
and validating.
For more context, see crrev.com/c/1888116, which this CL replaces.
BRANCH=nocturne,hatch
BUG=b:130561737
TEST=make buildall -j
TEST=make BOARD=bloonchipper
# Connect dragonclaw dev board over servo micro
sudo servod --board=bloonchipper --config bloonchipper_rev0.1.xml &
./util/flash_ec --board=bloonchipper
minicom -D $(dut-control raw_fpmcu_uart_pty | cut -d: -f2)
> sysinfo
# Check that we are in RW
Signed-off-by: Craig Hesling <hesling@chromium.org>
Change-Id: Iad51b11eb5959b5d502320560b9ebda7e614d97e
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1890924
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
-rw-r--r-- | chip/stm32/gpio-stm32f4.c | 27 | ||||
-rw-r--r-- | chip/stm32/gpio_chip.h | 6 | ||||
-rw-r--r-- | chip/stm32/registers-stm32f4.h | 9 | ||||
-rw-r--r-- | chip/stm32/system.c | 14 |
4 files changed, 49 insertions, 7 deletions
diff --git a/chip/stm32/gpio-stm32f4.c b/chip/stm32/gpio-stm32f4.c index 3d4e5ddde1..4a4e095a71 100644 --- a/chip/stm32/gpio-stm32f4.c +++ b/chip/stm32/gpio-stm32f4.c @@ -13,15 +13,30 @@ #include "task.h" #include "util.h" -void gpio_enable_clocks(void) +int gpio_required_clocks(void) { + const int gpio_ports_used = (0 +# define GPIO(name, pin, flags) pin +# define GPIO_INT(name, pin, flags, signal) pin +# define ALTERNATE(pinmask, function, module, flagz) pinmask +# define PIN(port, index) | STM32_RCC_AHB1ENR_GPIO_PORT ## port +# define PIN_MASK(port, mask) PIN(port, 0) +# include "gpio.wrap" + ); + /* - * Enable all GPIOs clocks - * - * TODO(crosbug.com/p/23770): only enable the banks we need to, - * and support disabling some of them in low-power idle. + * If no ports are in use, then system_is_reboot_warm + * may not be valid. */ - STM32_RCC_AHB1ENR |= STM32_RCC_AHB1ENR_GPIOMASK; + ASSERT(gpio_ports_used); + + return gpio_ports_used; +} + +void gpio_enable_clocks(void) +{ + /* Enable only ports that are referenced in the gpio.inc */ + STM32_RCC_AHB1ENR |= gpio_required_clocks(); /* Delay 1 AHB clock cycle after the clock is enabled */ clock_wait_bus_cycles(BUS_AHB, 1); diff --git a/chip/stm32/gpio_chip.h b/chip/stm32/gpio_chip.h index ec9da96e14..a5b642fb05 100644 --- a/chip/stm32/gpio_chip.h +++ b/chip/stm32/gpio_chip.h @@ -13,4 +13,10 @@ */ void gpio_enable_clocks(void); +/** + * Return gpio port clocks that are necessary to support + * the pins in gpio.inc. + */ +int gpio_required_clocks(void); + #endif /* __CROS_EC_CHIP_STM32_GPIO_CHIP_H */ diff --git a/chip/stm32/registers-stm32f4.h b/chip/stm32/registers-stm32f4.h index aef2f87f6f..452737254a 100644 --- a/chip/stm32/registers-stm32f4.h +++ b/chip/stm32/registers-stm32f4.h @@ -521,10 +521,19 @@ #define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x24) #define STM32_RCC_AHB1ENR REG32(STM32_RCC_BASE + 0x30) +#define STM32_RCC_AHB1ENR_GPIO_PORTA BIT(0) +#define STM32_RCC_AHB1ENR_GPIO_PORTB BIT(1) +#define STM32_RCC_AHB1ENR_GPIO_PORTC BIT(2) +#define STM32_RCC_AHB1ENR_GPIO_PORTD BIT(3) +#define STM32_RCC_AHB1ENR_GPIO_PORTE BIT(4) +#define STM32_RCC_AHB1ENR_GPIO_PORTF BIT(5) +#define STM32_RCC_AHB1ENR_GPIO_PORTG BIT(6) +#define STM32_RCC_AHB1ENR_GPIO_PORTH BIT(7) #define STM32_RCC_AHB1ENR_GPIOMASK (0xff << 0) #define STM32_RCC_AHB1ENR_BKPSRAMEN BIT(18) #define STM32_RCC_AHB1ENR_DMA1EN BIT(21) #define STM32_RCC_AHB1ENR_DMA2EN BIT(22) + /* TODO(nsanders): normalize naming.*/ #define STM32_RCC_HB1_DMA1 BIT(21) #define STM32_RCC_HB1_DMA2 BIT(22) diff --git a/chip/stm32/system.c b/chip/stm32/system.c index ddba03958a..58b77fba92 100644 --- a/chip/stm32/system.c +++ b/chip/stm32/system.c @@ -9,6 +9,7 @@ #include "console.h" #include "cpu.h" #include "flash.h" +#include "gpio_chip.h" #include "host_command.h" #include "registers.h" #include "panic.h" @@ -567,6 +568,17 @@ int system_set_bbram(enum system_bbram_idx idx, uint8_t value) int system_is_reboot_warm(void) { + /* + * Detecting if the system is warm is relevant for a + * few reasons. + * One such reason is that some firmwares transition from + * RO to RW images. When this happens, we may not need to + * restart certain clocks. On the flip side, we may need + * to restart the clocks if the RW requires a different + * set of clocks. Thus, the clock configurations need to + * be checked for a perfect match. + */ + #if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) return ((STM32_RCC_AHBENR & 0x7e0000) == 0x7e0000); #elif defined(CHIP_FAMILY_STM32L) @@ -576,7 +588,7 @@ int system_is_reboot_warm(void) == STM32_RCC_AHB2ENR_GPIOMASK); #elif defined(CHIP_FAMILY_STM32F4) return ((STM32_RCC_AHB1ENR & STM32_RCC_AHB1ENR_GPIOMASK) - == STM32_RCC_AHB1ENR_GPIOMASK); + == gpio_required_clocks()); #elif defined(CHIP_FAMILY_STM32H7) return ((STM32_RCC_AHB4ENR & STM32_RCC_AHB4ENR_GPIOMASK) == STM32_RCC_AHB4ENR_GPIOMASK); |