summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@google.com>2015-02-04 11:28:53 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-02-10 10:47:07 +0000
commit049463f8ad985f9cb996caa7dbc5438383bd3084 (patch)
tree93ff78695657a998919c6d6e28101cd158489368
parenta9ae00b10129feca28713a7b88978ff6cfe7c2a6 (diff)
downloadchrome-ec-049463f8ad985f9cb996caa7dbc5438383bd3084.tar.gz
stm32: Add delay after enabling peripheral clock
We need a dummy read after enabling AHB peripheral clock before we can access the peripheral. For APB, we also need a dummy read for STM32F3. BRANCH=All affected BUG=chrome-os-partner:33007 TEST=make buildall Change-Id: I47f4a024dca294f555428c3f2053c1d32835ebe0 Signed-off-by: Vic Yang <victoryang@google.com> Reviewed-on: https://chromium-review.googlesource.com/246181 Reviewed-by: Alec Berg <alecaberg@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> Tested-by: Vic Yang <victoryang@chromium.org> Commit-Queue: Vic Yang <victoryang@chromium.org>
-rw-r--r--board/ryu/usb_pd_config.h3
-rw-r--r--board/ryu_sh/board.c3
-rw-r--r--chip/stm32/adc-stm32f.c6
-rw-r--r--chip/stm32/clock-stm32f.c13
-rw-r--r--chip/stm32/clock-stm32f0.c13
-rw-r--r--chip/stm32/clock-stm32l.c13
-rw-r--r--chip/stm32/crc_hw.h3
-rw-r--r--chip/stm32/dma.c3
-rw-r--r--chip/stm32/gpio-stm32f.c4
-rw-r--r--chip/stm32/gpio-stm32f0.c4
-rw-r--r--chip/stm32/gpio-stm32f3.c4
-rw-r--r--chip/stm32/gpio-stm32l.c4
-rw-r--r--chip/stm32/gpio.c4
-rw-r--r--chip/stm32/hwtimer.c6
-rw-r--r--chip/stm32/hwtimer32.c4
-rw-r--r--chip/stm32/i2c-stm32f.c3
-rw-r--r--chip/stm32/spi.c4
-rw-r--r--chip/stm32/system.c3
-rw-r--r--chip/stm32/uart.c6
-rw-r--r--chip/stm32/usart.c6
-rw-r--r--chip/stm32/usb_pd_phy.c4
-rw-r--r--include/clock.h17
22 files changed, 129 insertions, 1 deletions
diff --git a/board/ryu/usb_pd_config.h b/board/ryu/usb_pd_config.h
index 4985454675..d5992e3335 100644
--- a/board/ryu/usb_pd_config.h
+++ b/board/ryu/usb_pd_config.h
@@ -9,6 +9,7 @@
#define __USB_PD_CONFIG_H
#include "charge_state.h"
+#include "clock.h"
#include "registers.h"
/* Port and task configuration */
@@ -46,6 +47,8 @@
static inline void spi_enable_clock(int port)
{
STM32_RCC_APB2ENR |= STM32_RCC_PB2_SPI1;
+ /* Delay 1 APB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_APB, 1);
}
#define DMAC_SPI_TX(p) STM32_DMAC_CH3
diff --git a/board/ryu_sh/board.c b/board/ryu_sh/board.c
index 34ed7df7e2..2266e7d95a 100644
--- a/board/ryu_sh/board.c
+++ b/board/ryu_sh/board.c
@@ -4,6 +4,7 @@
*/
/* ryu sensor hub configuration */
+#include "clock.h"
#include "common.h"
#include "console.h"
#include "driver/accelgyro_lsm6ds0.h"
@@ -64,6 +65,8 @@ void board_config_pre_init(void)
* and the register write as no effect.
*/
STM32_RCC_APB2ENR |= 1 << 0;
+ /* Delay 1 APB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_APB, 1);
/*
* Remap USART DMA to match the USART driver
* the DMA mapping is :
diff --git a/chip/stm32/adc-stm32f.c b/chip/stm32/adc-stm32f.c
index 7a92130ece..d6ff369ef9 100644
--- a/chip/stm32/adc-stm32f.c
+++ b/chip/stm32/adc-stm32f.c
@@ -266,6 +266,12 @@ static void adc_init(void)
*/
STM32_RCC_APB2ENR |= (1 << 9);
+ /*
+ * ADC clock is divided with respect to AHB, so no delay needed
+ * here. If ADC clock is the same as AHB, a dummy read on ADC
+ * register is needed here.
+ */
+
if (!adc_powered()) {
/* Power on ADC module */
STM32_ADC_CR2 |= (1 << 0); /* ADON */
diff --git a/chip/stm32/clock-stm32f.c b/chip/stm32/clock-stm32f.c
index 76278c9c01..029c34bd09 100644
--- a/chip/stm32/clock-stm32f.c
+++ b/chip/stm32/clock-stm32f.c
@@ -265,6 +265,19 @@ int clock_get_freq(void)
return CPU_CLOCK;
}
+void clock_wait_bus_cycles(enum bus_type bus, uint32_t cycles)
+{
+ volatile uint32_t dummy __attribute__((unused));
+
+ if (bus == BUS_AHB) {
+ while (cycles--)
+ dummy = STM32_DMA1_REGS->isr;
+ } else { /* APB */
+ while (cycles--)
+ dummy = STM32_USART_BRR(STM32_USART1_BASE);
+ }
+}
+
void clock_init(void)
{
/*
diff --git a/chip/stm32/clock-stm32f0.c b/chip/stm32/clock-stm32f0.c
index 74534eee3a..6dfe0a1447 100644
--- a/chip/stm32/clock-stm32f0.c
+++ b/chip/stm32/clock-stm32f0.c
@@ -418,6 +418,19 @@ int clock_get_freq(void)
return CPU_CLOCK;
}
+void clock_wait_bus_cycles(enum bus_type bus, uint32_t cycles)
+{
+ volatile uint32_t dummy __attribute__((unused));
+
+ if (bus == BUS_AHB) {
+ while (cycles--)
+ dummy = STM32_DMA1_REGS->isr;
+ } else { /* APB */
+ while (cycles--)
+ dummy = STM32_USART_BRR(STM32_USART1_BASE);
+ }
+}
+
void clock_enable_module(enum module_id module, int enable)
{
}
diff --git a/chip/stm32/clock-stm32l.c b/chip/stm32/clock-stm32l.c
index e0c7ebc747..c8b8bc0683 100644
--- a/chip/stm32/clock-stm32l.c
+++ b/chip/stm32/clock-stm32l.c
@@ -50,6 +50,19 @@ int clock_get_freq(void)
return freq;
}
+void clock_wait_bus_cycles(enum bus_type bus, uint32_t cycles)
+{
+ volatile uint32_t dummy __attribute__((unused));
+
+ if (bus == BUS_AHB) {
+ while (cycles--)
+ dummy = STM32_DMA1_REGS->isr;
+ } else { /* APB */
+ while (cycles--)
+ dummy = STM32_USART_BRR(STM32_USART1_BASE);
+ }
+}
+
/**
* Set which oscillator is used for the clock
*
diff --git a/chip/stm32/crc_hw.h b/chip/stm32/crc_hw.h
index c1a97da842..edaf3b5d32 100644
--- a/chip/stm32/crc_hw.h
+++ b/chip/stm32/crc_hw.h
@@ -7,12 +7,15 @@
#define _CRC_HW_H
/* CRC-32 hardware implementation with USB constants */
+#include "clock.h"
#include "registers.h"
static inline void crc32_init(void)
{
/* switch on CRC controller */
STM32_RCC_AHBENR |= 1 << 6; /* switch on CRC controller */
+ /* Delay 1 AHB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_AHB, 1);
/* reset CRC state */
STM32_CRC_CR = STM32_CRC_CR_RESET | STM32_CRC_CR_REV_OUT
| STM32_CRC_CR_REV_IN_WORD;
diff --git a/chip/stm32/dma.c b/chip/stm32/dma.c
index 096ec45186..2a4f4aeb4a 100644
--- a/chip/stm32/dma.c
+++ b/chip/stm32/dma.c
@@ -3,6 +3,7 @@
* found in the LICENSE file.
*/
+#include "clock.h"
#include "common.h"
#include "console.h"
#include "dma.h"
@@ -211,6 +212,8 @@ void dma_init(void)
{
/* Enable DMA1; current chips don't have DMA2 */
STM32_RCC_AHBENR |= STM32_RCC_HB_DMA1;
+ /* Delay 1 AHB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_AHB, 1);
}
int dma_wait(enum dma_channel channel)
diff --git a/chip/stm32/gpio-stm32f.c b/chip/stm32/gpio-stm32f.c
index 147f461528..9a381edfee 100644
--- a/chip/stm32/gpio-stm32f.c
+++ b/chip/stm32/gpio-stm32f.c
@@ -5,6 +5,7 @@
/* GPIO module for Chrome EC */
+#include "clock.h"
#include "common.h"
#include "gpio.h"
#include "hooks.h"
@@ -116,6 +117,9 @@ void gpio_enable_clocks(void)
#else
STM32_RCC_APB2ENR |= 0x1fd;
#endif
+
+ /* Delay 1 APB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_APB, 1);
}
void gpio_set_alternate_function(uint32_t port, uint32_t mask, int func)
diff --git a/chip/stm32/gpio-stm32f0.c b/chip/stm32/gpio-stm32f0.c
index 58a28a25f1..5418399595 100644
--- a/chip/stm32/gpio-stm32f0.c
+++ b/chip/stm32/gpio-stm32f0.c
@@ -5,6 +5,7 @@
/* GPIO module for Chrome EC */
+#include "clock.h"
#include "common.h"
#include "gpio.h"
#include "hooks.h"
@@ -26,6 +27,9 @@ void gpio_enable_clocks(void)
* and support disabling some of them in low-power idle.
*/
STM32_RCC_AHBENR |= 0x7e0000;
+
+ /* Delay 1 AHB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_AHB, 1);
}
static void gpio_init(void)
diff --git a/chip/stm32/gpio-stm32f3.c b/chip/stm32/gpio-stm32f3.c
index 462a5be859..9efddab7fc 100644
--- a/chip/stm32/gpio-stm32f3.c
+++ b/chip/stm32/gpio-stm32f3.c
@@ -5,6 +5,7 @@
/* GPIO module for Chrome EC */
+#include "clock.h"
#include "common.h"
#include "gpio.h"
#include "hooks.h"
@@ -26,6 +27,9 @@ void gpio_enable_clocks(void)
* and support disabling some of them in low-power idle.
*/
STM32_RCC_AHBENR |= 0x7e0000;
+
+ /* Delay 1 AHB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_AHB, 1);
}
static void gpio_init(void)
diff --git a/chip/stm32/gpio-stm32l.c b/chip/stm32/gpio-stm32l.c
index 44282fc5c0..c015112503 100644
--- a/chip/stm32/gpio-stm32l.c
+++ b/chip/stm32/gpio-stm32l.c
@@ -5,6 +5,7 @@
/* GPIO module for Chrome EC */
+#include "clock.h"
#include "common.h"
#include "gpio.h"
#include "hooks.h"
@@ -26,6 +27,9 @@ void gpio_enable_clocks(void)
* and support disabling some of them in low-power idle.
*/
STM32_RCC_AHBENR |= 0x3f;
+
+ /* Delay 1 AHB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_AHB, 1);
}
static void gpio_init(void)
diff --git a/chip/stm32/gpio.c b/chip/stm32/gpio.c
index 0c73081b42..6715e540b0 100644
--- a/chip/stm32/gpio.c
+++ b/chip/stm32/gpio.c
@@ -5,6 +5,7 @@
/* GPIO module for Chrome EC */
+#include "clock.h"
#include "common.h"
#include "console.h"
#include "gpio.h"
@@ -28,6 +29,9 @@ void gpio_pre_init(void)
/* Required to configure external IRQ lines (SYSCFG_EXTICRn) */
STM32_RCC_APB2ENR |= 1 << 0;
+ /* Delay 1 APB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_APB, 1);
+
if (!is_warm)
gpio_enable_clocks();
diff --git a/chip/stm32/hwtimer.c b/chip/stm32/hwtimer.c
index 14a9bc7f2b..9e8f959553 100644
--- a/chip/stm32/hwtimer.c
+++ b/chip/stm32/hwtimer.c
@@ -320,6 +320,9 @@ int __hw_clock_source_init(uint32_t start_t)
__hw_timer_enable_clock(TIM_CLOCK_MSB, 1);
__hw_timer_enable_clock(TIM_CLOCK_LSB, 1);
+ /* Delay 1 APB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_APB, 1);
+
/*
* Timer configuration : Upcounter, counter disabled, update event only
* on overflow.
@@ -405,6 +408,9 @@ void hwtimer_setup_watchdog(void)
/* Enable clock */
__hw_timer_enable_clock(TIM_WATCHDOG, 1);
+ /* Delay 1 APB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_APB, 1);
+
/*
* Timer configuration : Down counter, counter disabled, update
* event only on overflow.
diff --git a/chip/stm32/hwtimer32.c b/chip/stm32/hwtimer32.c
index 4dc4c8cdb7..691e2f90f7 100644
--- a/chip/stm32/hwtimer32.c
+++ b/chip/stm32/hwtimer32.c
@@ -148,6 +148,8 @@ int __hw_clock_source_init(uint32_t start_t)
{
/* Enable TIM peripheral block clocks */
__hw_timer_enable_clock(TIM_CLOCK32, 1);
+ /* Delay 1 APB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_APB, 1);
/*
* Timer configuration : Upcounter, counter disabled, update event only
@@ -218,6 +220,8 @@ void hwtimer_setup_watchdog(void)
{
/* Enable clock */
__hw_timer_enable_clock(TIM_WATCHDOG, 1);
+ /* Delay 1 APB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_APB, 1);
/*
* Timer configuration : Up counter, counter disabled, update
diff --git a/chip/stm32/i2c-stm32f.c b/chip/stm32/i2c-stm32f.c
index 88728f1eb1..75d1587c76 100644
--- a/chip/stm32/i2c-stm32f.c
+++ b/chip/stm32/i2c-stm32f.c
@@ -343,6 +343,9 @@ static void i2c_init_port(unsigned int port)
/* enable I2C2 clock */
STM32_RCC_APB1ENR |= 1 << i2c_clock_bit[port];
+
+ /* Delay 1 APB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_APB, 1);
}
/* force reset of the i2c peripheral */
diff --git a/chip/stm32/spi.c b/chip/stm32/spi.c
index d8c88ba34f..21984618be 100644
--- a/chip/stm32/spi.c
+++ b/chip/stm32/spi.c
@@ -9,6 +9,7 @@
*/
#include "chipset.h"
+#include "clock.h"
#include "console.h"
#include "dma.h"
#include "gpio.h"
@@ -630,6 +631,9 @@ static void spi_init(void)
/* Enable clocks to SPI1 module */
STM32_RCC_APB2ENR |= STM32_RCC_PB2_SPI1;
+ /* Delay 1 APB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_APB, 1);
+
/*
* Enable rx/tx DMA and get ready to receive our first transaction and
* "disable" FIFO by setting event to happen after only 1 byte
diff --git a/chip/stm32/system.c b/chip/stm32/system.c
index 52b200ea11..890c704924 100644
--- a/chip/stm32/system.c
+++ b/chip/stm32/system.c
@@ -5,6 +5,7 @@
/* System module for Chrome EC : hardware specific implementation */
+#include "clock.h"
#include "console.h"
#include "cpu.h"
#include "flash.h"
@@ -165,6 +166,8 @@ void system_pre_init(void)
STM32_RCC_APB1ENR |= 1 << 28;
/* enable backup registers */
STM32_RCC_APB1ENR |= 1 << 27;
+ /* Delay 1 APB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_APB, 1);
/* Enable access to RCC CSR register and RTC backup registers */
STM32_PWR_CR |= 1 << 8;
diff --git a/chip/stm32/uart.c b/chip/stm32/uart.c
index 3544b95efe..33ef1064f0 100644
--- a/chip/stm32/uart.c
+++ b/chip/stm32/uart.c
@@ -279,6 +279,12 @@ void uart_init(void)
STM32_RCC_APB1ENR |= CONCAT2(STM32_RCC_PB1_USART, UARTN);
#endif
+ /*
+ * For STM32F3, A delay of 1 APB clock cycles is needed before we
+ * can access any USART register. Fortunately, we have
+ * gpio_config_module() below and thus don't need to add the delay.
+ */
+
/* Configure GPIOs */
gpio_config_module(MODULE_UART, 1);
diff --git a/chip/stm32/usart.c b/chip/stm32/usart.c
index 264fa35a75..29cb0b705f 100644
--- a/chip/stm32/usart.c
+++ b/chip/stm32/usart.c
@@ -76,6 +76,12 @@ void usart_init(struct usart_config const *config)
*(config->hw->clock_register) |= config->hw->clock_enable;
/*
+ * For STM32F3, A delay of 1 APB clock cycles is needed before we
+ * can access any USART register. Fortunately, we have
+ * gpio_config_module() below and thus don't need to add the delay.
+ */
+
+ /*
* Switch all GPIOs assigned to the USART module over to their USART
* alternate functions.
*/
diff --git a/chip/stm32/usb_pd_phy.c b/chip/stm32/usb_pd_phy.c
index 1a09b8e07a..e0f3204b1b 100644
--- a/chip/stm32/usb_pd_phy.c
+++ b/chip/stm32/usb_pd_phy.c
@@ -582,6 +582,8 @@ void pd_hw_init(int port)
#ifdef CONFIG_PD_USE_DAC_AS_REF
/* Enable DAC interface clock. */
STM32_RCC_APB1ENR |= (1 << 29);
+ /* Delay 1 APB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_APB, 1);
/* set voltage Vout=0.850V (Vref = 3.0V) */
STM32_DAC_DHR12RD = 850 * 4096 / 3000;
/* Start DAC channel 1 */
@@ -593,6 +595,8 @@ void pd_hw_init(int port)
#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
/* turn on COMP/SYSCFG */
STM32_RCC_APB2ENR |= 1 << 0;
+ /* Delay 1 APB clock cycle after the clock is enabled */
+ clock_wait_bus_cycles(BUS_APB, 1);
/* currently in hi-speed mode : TODO revisit later, INM = PA0(INM6) */
STM32_COMP_CSR = STM32_COMP_CMP1MODE_LSPEED |
STM32_COMP_CMP1INSEL_INM6 |
diff --git a/include/clock.h b/include/clock.h
index 62c38bcd6a..7702ca85eb 100644
--- a/include/clock.h
+++ b/include/clock.h
@@ -47,7 +47,7 @@ void clock_enable_module(enum module_id module, int enable);
void clock_enable_pll(int enable, int notify);
/**
- * Wait for a number of clock cycles.
+ * Wait for a number of CPU clock cycles.
*
* Simple busy waiting for use before clocks/timers are initialized.
*
@@ -55,6 +55,21 @@ void clock_enable_pll(int enable, int notify);
*/
void clock_wait_cycles(uint32_t cycles);
+enum bus_type {
+ BUS_AHB,
+ BUS_APB,
+};
+
+/**
+ * Wait for a number of peripheral bus clock cycles.
+ *
+ * Dummy read on peripherals for delay.
+ *
+ * @param bus Which bus clock cycle to use.
+ * @param cycles Number of cycles to wait.
+ */
+void clock_wait_bus_cycles(enum bus_type bus, uint32_t cycles);
+
/* Clock gate control modes for clock_enable_peripheral() */
#define CGC_MODE_RUN (1 << 0)
#define CGC_MODE_SLEEP (1 << 1)