summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJes B. Klinke <jbk@chromium.org>2021-08-30 14:52:26 -0700
committerCommit Bot <commit-bot@chromium.org>2021-09-08 18:57:36 +0000
commitf2af0a3a74192876fc1b72706813d756393da167 (patch)
treea53007357e2be115dab1aace09365a4845e109af
parentf351c02b70c6a7d2137d3770e11e7c3a3850a1c8 (diff)
downloadchrome-ec-f2af0a3a74192876fc1b72706813d756393da167.tar.gz
chip/stm32: Factor family specific clock logic out of usb.c
The register for enabling USB register clock appears to have been identical across F0, F3, and G4 families, but for L5 it is different. Rather than having #ifdef in usb.c (as I recently committed), this CL will move the clock logic into clock_enable_module() where it arguably belonged all the time. Additionally: Some of the chip families make use of a clock_mask in their implementation of clock_enable_module(), but since the module_id enum has more than 32 value, until now, some values (among those MODULE_USB) would result in overflow, causing new_mask to be identical to clock_mask, and the USB case could have never been reached. BUG=b:192262089 TEST=Compile servo_v4 without linker errors BRANCH=none Signed-off-by: Jes Bodi Klinke <jbk@chromium.org> Change-Id: I7c29339f45eb513e3e78f662797a70543912c8c7 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3130733 Reviewed-by: Scott Collyer <scollyer@chromium.org>
-rw-r--r--chip/stm32/clock-stm32f0.c14
-rw-r--r--chip/stm32/clock-stm32g4.c19
-rw-r--r--chip/stm32/clock-stm32l.c21
-rw-r--r--chip/stm32/clock-stm32l4.c25
-rw-r--r--chip/stm32/usb.c24
-rw-r--r--include/clock.h7
6 files changed, 78 insertions, 32 deletions
diff --git a/chip/stm32/clock-stm32f0.c b/chip/stm32/clock-stm32f0.c
index 8cfbaef111..0f63bdd394 100644
--- a/chip/stm32/clock-stm32f0.c
+++ b/chip/stm32/clock-stm32f0.c
@@ -407,9 +407,23 @@ void clock_enable_module(enum module_id module, int enable)
else
STM32_RCC_APB2ENR &= ~STM32_RCC_APB2ENR_ADCEN;
return;
+ } else if (module == MODULE_USB) {
+ if (enable)
+ STM32_RCC_APB1ENR |= STM32_RCC_PB1_USB;
+ else
+ STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_USB;
}
}
+int clock_is_module_enabled(enum module_id module)
+{
+ if (module == MODULE_ADC)
+ return !!(STM32_RCC_APB2ENR & STM32_RCC_APB2ENR_ADCEN);
+ else if (module == MODULE_USB)
+ return !!(STM32_RCC_APB1ENR & STM32_RCC_PB1_USB);
+ return 0;
+}
+
void rtc_init(void)
{
rtc_unlock_regs();
diff --git a/chip/stm32/clock-stm32g4.c b/chip/stm32/clock-stm32g4.c
index 94936b932f..42a00a0f6a 100644
--- a/chip/stm32/clock-stm32g4.c
+++ b/chip/stm32/clock-stm32g4.c
@@ -245,10 +245,13 @@ void clock_wait_bus_cycles(enum bus_type bus, uint32_t cycles)
void clock_enable_module(enum module_id module, int enable)
{
if (module == MODULE_USB) {
- if (enable)
+ if (enable) {
+ STM32_RCC_APB1ENR |= STM32_RCC_PB1_USB;
STM32_RCC_CRRCR |= RCC_CRRCR_HSI48O;
- else
+ } else {
STM32_RCC_CRRCR &= ~RCC_CRRCR_HSI48O;
+ STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_USB;
+ }
} else if (module == MODULE_I2C) {
if (enable) {
/* Enable clocks to I2C modules if necessary */
@@ -277,3 +280,15 @@ void clock_enable_module(enum module_id module, int enable)
module);
}
}
+
+int clock_is_module_enabled(enum module_id module)
+{
+ if (module == MODULE_USB)
+ return !!(STM32_RCC_APB1ENR & STM32_RCC_PB1_USB);
+ else if (module == MODULE_I2C)
+ return !!(STM32_RCC_APB1ENR1 & STM32_RCC_APB1ENR1_I2C1EN);
+ else if (module == MODULE_ADC)
+ return !!(STM32_RCC_AHB2ENR & STM32_RCC_AHB2ENR_ADC12EN);
+ return 0;
+}
+
diff --git a/chip/stm32/clock-stm32l.c b/chip/stm32/clock-stm32l.c
index a4e9dd7cdf..bb0da42d14 100644
--- a/chip/stm32/clock-stm32l.c
+++ b/chip/stm32/clock-stm32l.c
@@ -195,15 +195,16 @@ static void clock_set_osc(enum clock_osc osc)
}
}
+static uint64_t clock_mask;
+
void clock_enable_module(enum module_id module, int enable)
{
- static uint32_t clock_mask;
- int new_mask;
+ uint64_t new_mask;
if (enable)
- new_mask = clock_mask | BIT(module);
+ new_mask = clock_mask | BIT_ULL(module);
else
- new_mask = clock_mask & ~BIT(module);
+ new_mask = clock_mask & ~BIT_ULL(module);
/* Only change clock if needed */
if ((!!new_mask) != (!!clock_mask)) {
@@ -214,9 +215,21 @@ void clock_enable_module(enum module_id module, int enable)
clock_set_osc(new_mask ? OSC_HSI : OSC_MSI);
}
+ if (module == MODULE_USB) {
+ if (enable)
+ STM32_RCC_APB1ENR |= STM32_RCC_PB1_USB;
+ else
+ STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_USB;
+ }
+
clock_mask = new_mask;
}
+int clock_is_module_enabled(enum module_id module)
+{
+ return !!(clock_mask & BIT_ULL(module));
+}
+
#ifdef CONFIG_STM32L_FAKE_HIBERNATE
/*
* This is for NOT having enough hibernate (more precisely, the stand-by mode)
diff --git a/chip/stm32/clock-stm32l4.c b/chip/stm32/clock-stm32l4.c
index 540695deb1..a7097c0382 100644
--- a/chip/stm32/clock-stm32l4.c
+++ b/chip/stm32/clock-stm32l4.c
@@ -3,7 +3,7 @@
* found in the LICENSE file.
*/
-/* Clocks and power management settings */
+/* Clocks and power management settings for STM32L4xx as well as STM32L5xx. */
#include "chipset.h"
#include "clock.h"
@@ -451,15 +451,16 @@ static void clock_set_osc(enum clock_osc osc, enum clock_osc pll_osc)
}
}
+static uint64_t clock_mask;
+
void clock_enable_module(enum module_id module, int enable)
{
- static uint32_t clock_mask;
- int new_mask;
+ uint64_t new_mask;
if (enable)
- new_mask = clock_mask | BIT(module);
+ new_mask = clock_mask | BIT_ULL(module);
else
- new_mask = clock_mask & ~BIT(module);
+ new_mask = clock_mask & ~BIT_ULL(module);
/* Only change clock if needed */
if (new_mask != clock_mask) {
@@ -488,12 +489,26 @@ void clock_enable_module(enum module_id module, int enable)
else if ((new_mask & (BIT(MODULE_SPI) |
BIT(MODULE_SPI_CONTROLLER))) == 0)
STM32_RCC_APB2ENR &= ~STM32_RCC_APB2ENR_SPI1EN;
+ } else if (module == MODULE_USB) {
+#if defined(STM32_RCC_APB1ENR2_USBFSEN)
+ if (enable)
+ STM32_RCC_APB1ENR2 |=
+ STM32_RCC_APB1ENR2_USBFSEN;
+ else
+ STM32_RCC_APB1ENR2 &=
+ ~STM32_RCC_APB1ENR2_USBFSEN;
+#endif
}
}
clock_mask = new_mask;
}
+int clock_is_module_enabled(enum module_id module)
+{
+ return !!(clock_mask & BIT_ULL(module));
+}
+
void rtc_init(void)
{
/* Enable RTC Alarm in EXTI */
diff --git a/chip/stm32/usb.c b/chip/stm32/usb.c
index 70acdf6486..0077815a27 100644
--- a/chip/stm32/usb.c
+++ b/chip/stm32/usb.c
@@ -677,14 +677,7 @@ DECLARE_IRQ(STM32_IRQ_USB_LP, usb_interrupt, 1);
void usb_init(void)
{
- /* Enable USB device clock. */
-#if defined(STM32_RCC_APB1ENR2_USBFSEN)
- STM32_RCC_APB1ENR2 |= STM32_RCC_APB1ENR2_USBFSEN;
-#else
- STM32_RCC_APB1ENR |= STM32_RCC_PB1_USB;
-#endif
-
- /* we need a proper 48MHz clock */
+ /* Enable USB device clock, possibly increasing system clock to 48MHz */
clock_enable_module(MODULE_USB, 1);
/* configure the pinmux */
@@ -747,26 +740,15 @@ void usb_release(void)
/* unset pinmux */
gpio_config_module(MODULE_USB, 0);
- /* disable 48MHz clock */
+ /* disable USB device clock, possibly slowing down system clock */
clock_enable_module(MODULE_USB, 0);
-
- /* disable USB device clock */
-#if defined(STM32_RCC_APB1ENR2_USBFSEN)
- STM32_RCC_APB1ENR2 &= ~STM32_RCC_APB1ENR2_USBFSEN;
-#else
- STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_USB;
-#endif
}
/* ensure the host disconnects and reconnects over a sysjump */
DECLARE_HOOK(HOOK_SYSJUMP, usb_release, HOOK_PRIO_DEFAULT);
int usb_is_enabled(void)
{
-#if defined(STM32_RCC_APB1ENR2_USBFSEN)
- return (STM32_RCC_APB1ENR2 & STM32_RCC_APB1ENR2_USBFSEN) ? 1 : 0;
-#else
- return (STM32_RCC_APB1ENR & STM32_RCC_PB1_USB) ? 1 : 0;
-#endif
+ return clock_is_module_enabled(MODULE_USB);
}
void *memcpy_to_usbram(void *dest, const void *src, size_t n)
diff --git a/include/clock.h b/include/clock.h
index acbd3fbcf5..c64cfe4db5 100644
--- a/include/clock.h
+++ b/include/clock.h
@@ -37,6 +37,13 @@ int clock_get_freq(void);
void clock_enable_module(enum module_id module, int enable);
/**
+ * Query whether clock is enabled for given module.
+ *
+ * @return Non-zero if enabled, zero if disabled.
+ */
+int clock_is_module_enabled(enum module_id module);
+
+/**
* Enable or disable the PLL.
*
* @param enable Enable PLL if non-zero; disable if zero.