stm32: Add delay after enabling peripheral clock [chromiumos/platform/ec : master]

37 views
Skip to first unread message

ChromeOS Commit Bot (Gerrit)

unread,
Feb 10, 2015, 5:47:11 AM2/10/15
to Vic Yang, Vincent Palatin, Randall Spangler, Alec Berg
ChromeOS Commit Bot has submitted this change and it was merged.

Change subject: stm32: Add delay after enabling peripheral clock
......................................................................


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 <victo...@google.com>
Reviewed-on: https://chromium-review.googlesource.com/246181
Reviewed-by: Alec Berg <alec...@chromium.org>
Reviewed-by: Randall Spangler <rspa...@chromium.org>
Tested-by: Vic Yang <victo...@chromium.org>
Commit-Queue: Vic Yang <victo...@chromium.org>
---
M board/ryu/usb_pd_config.h
M board/ryu_sh/board.c
M chip/stm32/adc-stm32f.c
M chip/stm32/clock-stm32f.c
M chip/stm32/clock-stm32f0.c
M chip/stm32/clock-stm32l.c
M chip/stm32/crc_hw.h
M chip/stm32/dma.c
M chip/stm32/gpio-stm32f.c
M chip/stm32/gpio-stm32f0.c
M chip/stm32/gpio-stm32f3.c
M chip/stm32/gpio-stm32l.c
M chip/stm32/gpio.c
M chip/stm32/hwtimer.c
M chip/stm32/hwtimer32.c
M chip/stm32/i2c-stm32f.c
M chip/stm32/spi.c
M chip/stm32/system.c
M chip/stm32/uart.c
M chip/stm32/usart.c
M chip/stm32/usb_pd_phy.c
M include/clock.h
22 files changed, 129 insertions(+), 1 deletion(-)

Approvals:
Alec Berg: Looks good to me, approved
Randall Spangler: Looks good to me, approved
Vic Yang: Ready; Verified



diff --git a/board/ryu/usb_pd_config.h b/board/ryu/usb_pd_config.h
index 4985454..d5992e3 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 34ed7df..2266e7d 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 @@
* 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 7a92130..d6ff369 100644
--- a/chip/stm32/adc-stm32f.c
+++ b/chip/stm32/adc-stm32f.c
@@ -266,6 +266,12 @@
*/
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 76278c9..029c34b 100644
--- a/chip/stm32/clock-stm32f.c
+++ b/chip/stm32/clock-stm32f.c
@@ -265,6 +265,19 @@
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 74534ee..6dfe0a1 100644
--- a/chip/stm32/clock-stm32f0.c
+++ b/chip/stm32/clock-stm32f0.c
@@ -418,6 +418,19 @@
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 e0c7ebc..c8b8bc0 100644
--- a/chip/stm32/clock-stm32l.c
+++ b/chip/stm32/clock-stm32l.c
@@ -50,6 +50,19 @@
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 c1a97da..edaf3b5 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 096ec45..2a4f4ae 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 @@
{
/* 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 147f461..9a381ed 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 @@
#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 58a28a2..5418399 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 @@
* 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 462a5be..9efddab 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 @@
* 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 44282fc..c015112 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 @@
* 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 0c73081..6715e54 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 @@
/* 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 14a9bc7..9e8f959 100644
--- a/chip/stm32/hwtimer.c
+++ b/chip/stm32/hwtimer.c
@@ -320,6 +320,9 @@
__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 @@
/* 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 4dc4c8c..691e2f9 100644
--- a/chip/stm32/hwtimer32.c
+++ b/chip/stm32/hwtimer32.c
@@ -148,6 +148,8 @@
{
/* 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 @@
{
/* 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 88728f1..75d1587 100644
--- a/chip/stm32/i2c-stm32f.c
+++ b/chip/stm32/i2c-stm32f.c
@@ -343,6 +343,9 @@

/* 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 d8c88ba..2198461 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 @@
/* 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 52b200e..890c704 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 @@
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 3544b95..33ef106 100644
--- a/chip/stm32/uart.c
+++ b/chip/stm32/uart.c
@@ -279,6 +279,12 @@
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 264fa35..29cb0b7 100644
--- a/chip/stm32/usart.c
+++ b/chip/stm32/usart.c
@@ -76,6 +76,12 @@
*(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 1a09b8e..e0f3204 100644
--- a/chip/stm32/usb_pd_phy.c
+++ b/chip/stm32/usb_pd_phy.c
@@ -582,6 +582,8 @@
#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 @@
#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 62c38bc..7702ca8 100644
--- a/include/clock.h
+++ b/include/clock.h
@@ -47,7 +47,7 @@
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_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)

--
To view, visit https://chromium-review.googlesource.com/246181
To unsubscribe, visit https://chromium-review.googlesource.com/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I47f4a024dca294f555428c3f2053c1d32835ebe0
Gerrit-PatchSet: 4
Gerrit-Project: chromiumos/platform/ec
Gerrit-Branch: master
Gerrit-Owner: Vic Yang <victo...@chromium.org>
Gerrit-Reviewer: Alec Berg <alec...@chromium.org>
Gerrit-Reviewer: ChromeOS Commit Bot <chromeos-...@chromium.org>
Gerrit-Reviewer: Randall Spangler <rspa...@chromium.org>
Gerrit-Reviewer: Vic Yang <victo...@chromium.org>
Gerrit-Reviewer: Vincent Palatin <vpal...@chromium.org>
Reply all
Reply to author
Forward
0 new messages