mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 01:21:49 +00:00
STM32F: Remove support for this family
There are no boards left that use this family of STM32 parts. If we add one later we can resurect support. Signed-off-by: Anton Staaf <robotboy@chromium.org> BRANCH=None BUG=None TEST=make buildall -j Change-Id: If985a9e9f93c935e98c93f33c075ce00cb9a91ac Reviewed-on: https://chromium-review.googlesource.com/282532 Tested-by: Anton Staaf <robotboy@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> Commit-Queue: Anton Staaf <robotboy@chromium.org> Trybot-Ready: Anton Staaf <robotboy@chromium.org>
This commit is contained in:
committed by
ChromeOS Commit Bot
parent
e881d99fde
commit
ebdad6b0f2
@@ -1,307 +0,0 @@
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "adc.h"
|
||||
#include "adc_chip.h"
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "dma.h"
|
||||
#include "hooks.h"
|
||||
#include "registers.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
|
||||
#define ADC_SINGLE_READ_TIMEOUT 3000 /* 3 ms */
|
||||
|
||||
#define SMPR1_EXPAND(v) ((v) | ((v) << 3) | ((v) << 6) | ((v) << 9) | \
|
||||
((v) << 12) | ((v) << 15) | ((v) << 18) | \
|
||||
((v) << 21))
|
||||
#define SMPR2_EXPAND(v) (SMPR1_EXPAND(v) | ((v) << 24) | ((v) << 27))
|
||||
|
||||
/* Default ADC sample time = 13.5 cycles */
|
||||
#ifndef CONFIG_ADC_SAMPLE_TIME
|
||||
#define CONFIG_ADC_SAMPLE_TIME 2
|
||||
#endif
|
||||
|
||||
struct mutex adc_lock;
|
||||
|
||||
static int watchdog_ain_id;
|
||||
|
||||
static const struct dma_option dma_adc_option = {
|
||||
STM32_DMAC_ADC, (void *)&STM32_ADC_DR,
|
||||
STM32_DMA_CCR_MSIZE_16_BIT | STM32_DMA_CCR_PSIZE_16_BIT,
|
||||
};
|
||||
|
||||
static inline void adc_set_channel(int sample_id, int channel)
|
||||
{
|
||||
uint32_t mask, val;
|
||||
volatile uint32_t *sqr_reg;
|
||||
|
||||
if (sample_id < 6) {
|
||||
mask = 0x1f << (sample_id * 5);
|
||||
val = channel << (sample_id * 5);
|
||||
sqr_reg = &STM32_ADC_SQR3;
|
||||
} else if (sample_id < 12) {
|
||||
mask = 0x1f << ((sample_id - 6) * 5);
|
||||
val = channel << ((sample_id - 6) * 5);
|
||||
sqr_reg = &STM32_ADC_SQR2;
|
||||
} else {
|
||||
mask = 0x1f << ((sample_id - 12) * 5);
|
||||
val = channel << ((sample_id - 12) * 5);
|
||||
sqr_reg = &STM32_ADC_SQR1;
|
||||
}
|
||||
|
||||
*sqr_reg = (*sqr_reg & ~mask) | val;
|
||||
}
|
||||
|
||||
static void adc_configure(int ain_id)
|
||||
{
|
||||
/* Set ADC channel */
|
||||
adc_set_channel(0, ain_id);
|
||||
|
||||
/* Disable DMA */
|
||||
STM32_ADC_CR2 &= ~(1 << 8);
|
||||
|
||||
/* Disable scan mode */
|
||||
STM32_ADC_CR1 &= ~(1 << 8);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) adc_configure_all(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Set ADC channels */
|
||||
STM32_ADC_SQR1 = (ADC_CH_COUNT - 1) << 20;
|
||||
for (i = 0; i < ADC_CH_COUNT; ++i)
|
||||
adc_set_channel(i, adc_channels[i].channel);
|
||||
|
||||
/* Enable DMA */
|
||||
STM32_ADC_CR2 |= (1 << 8);
|
||||
|
||||
/* Enable scan mode */
|
||||
STM32_ADC_CR1 |= (1 << 8);
|
||||
}
|
||||
|
||||
static inline int adc_powered(void)
|
||||
{
|
||||
return STM32_ADC_CR2 & (1 << 0);
|
||||
}
|
||||
|
||||
static inline int adc_conversion_ended(void)
|
||||
{
|
||||
return STM32_ADC_SR & (1 << 1);
|
||||
}
|
||||
|
||||
static int adc_watchdog_enabled(void)
|
||||
{
|
||||
return STM32_ADC_CR1 & (1 << 23);
|
||||
}
|
||||
|
||||
static int adc_enable_watchdog_no_lock(void)
|
||||
{
|
||||
/* Fail if watchdog already enabled */
|
||||
if (adc_watchdog_enabled())
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
/* Set channel */
|
||||
STM32_ADC_SQR3 = watchdog_ain_id;
|
||||
STM32_ADC_SQR1 = 0;
|
||||
STM32_ADC_CR1 = (STM32_ADC_CR1 & ~0x1f) | watchdog_ain_id;
|
||||
|
||||
/* Clear interrupt bit */
|
||||
STM32_ADC_SR &= ~0x1;
|
||||
|
||||
/* AWDSGL=1, SCAN=1, AWDIE=1, AWDEN=1 */
|
||||
STM32_ADC_CR1 |= (1 << 9) | (1 << 8) | (1 << 6) | (1 << 23);
|
||||
|
||||
/* Disable DMA */
|
||||
STM32_ADC_CR2 &= ~(1 << 8);
|
||||
|
||||
/* CONT=1 */
|
||||
STM32_ADC_CR2 |= (1 << 1);
|
||||
|
||||
/* Start conversion */
|
||||
STM32_ADC_CR2 |= (1 << 0);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
int adc_enable_watchdog(int ain_id, int high, int low)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!adc_powered())
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
mutex_lock(&adc_lock);
|
||||
|
||||
watchdog_ain_id = ain_id;
|
||||
|
||||
/* Set thresholds */
|
||||
STM32_ADC_HTR = high & 0xfff;
|
||||
STM32_ADC_LTR = low & 0xfff;
|
||||
|
||||
ret = adc_enable_watchdog_no_lock();
|
||||
mutex_unlock(&adc_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adc_disable_watchdog_no_lock(void)
|
||||
{
|
||||
/* Fail if watchdog not running */
|
||||
if (!adc_watchdog_enabled())
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
/* AWDEN=0, AWDIE=0 */
|
||||
STM32_ADC_CR1 &= ~(1 << 23) & ~(1 << 6);
|
||||
|
||||
/* CONT=0 */
|
||||
STM32_ADC_CR2 &= ~(1 << 1);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
int adc_disable_watchdog(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!adc_powered())
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
mutex_lock(&adc_lock);
|
||||
ret = adc_disable_watchdog_no_lock();
|
||||
mutex_unlock(&adc_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int adc_read_channel(enum adc_channel ch)
|
||||
{
|
||||
const struct adc_t *adc = adc_channels + ch;
|
||||
int value;
|
||||
int restore_watchdog = 0;
|
||||
timestamp_t deadline;
|
||||
|
||||
if (!adc_powered())
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
mutex_lock(&adc_lock);
|
||||
|
||||
if (adc_watchdog_enabled()) {
|
||||
restore_watchdog = 1;
|
||||
adc_disable_watchdog_no_lock();
|
||||
}
|
||||
|
||||
adc_configure(adc->channel);
|
||||
|
||||
/* Clear EOC bit */
|
||||
STM32_ADC_SR &= ~(1 << 1);
|
||||
|
||||
/* Start conversion */
|
||||
STM32_ADC_CR2 |= (1 << 0); /* ADON */
|
||||
|
||||
/* Wait for EOC bit set */
|
||||
deadline.val = get_time().val + ADC_SINGLE_READ_TIMEOUT;
|
||||
value = ADC_READ_ERROR;
|
||||
do {
|
||||
if (adc_conversion_ended()) {
|
||||
value = STM32_ADC_DR & ADC_READ_MAX;
|
||||
break;
|
||||
}
|
||||
} while (!timestamp_expired(deadline, NULL));
|
||||
|
||||
if (restore_watchdog)
|
||||
adc_enable_watchdog_no_lock();
|
||||
|
||||
mutex_unlock(&adc_lock);
|
||||
return (value == ADC_READ_ERROR) ? ADC_READ_ERROR :
|
||||
value * adc->factor_mul / adc->factor_div + adc->shift;
|
||||
}
|
||||
|
||||
int adc_read_all_channels(int *data)
|
||||
{
|
||||
int i;
|
||||
int16_t raw_data[ADC_CH_COUNT];
|
||||
const struct adc_t *adc;
|
||||
int restore_watchdog = 0;
|
||||
int ret = EC_SUCCESS;
|
||||
|
||||
if (!adc_powered())
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
mutex_lock(&adc_lock);
|
||||
|
||||
if (adc_watchdog_enabled()) {
|
||||
restore_watchdog = 1;
|
||||
adc_disable_watchdog_no_lock();
|
||||
}
|
||||
|
||||
adc_configure_all();
|
||||
|
||||
dma_clear_isr(STM32_DMAC_ADC);
|
||||
dma_start_rx(&dma_adc_option, ADC_CH_COUNT, raw_data);
|
||||
|
||||
/* Start conversion */
|
||||
STM32_ADC_CR2 |= (1 << 0); /* ADON */
|
||||
|
||||
if (dma_wait(STM32_DMAC_ADC)) {
|
||||
ret = EC_ERROR_UNKNOWN;
|
||||
goto exit_all_channels;
|
||||
}
|
||||
|
||||
for (i = 0; i < ADC_CH_COUNT; ++i) {
|
||||
adc = adc_channels + i;
|
||||
data[i] = raw_data[i] * adc->factor_mul / adc->factor_div +
|
||||
adc->shift;
|
||||
}
|
||||
|
||||
exit_all_channels:
|
||||
dma_disable(STM32_DMAC_ADC);
|
||||
|
||||
if (restore_watchdog)
|
||||
adc_enable_watchdog_no_lock();
|
||||
|
||||
mutex_unlock(&adc_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void adc_init(void)
|
||||
{
|
||||
/*
|
||||
* Enable ADC clock.
|
||||
* APB2 clock is 16MHz. ADC clock prescaler is /2.
|
||||
* So the ADC clock is 8MHz.
|
||||
*/
|
||||
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 */
|
||||
|
||||
/* Reset calibration */
|
||||
STM32_ADC_CR2 |= (1 << 3); /* RSTCAL */
|
||||
while (STM32_ADC_CR2 & (1 << 3))
|
||||
;
|
||||
|
||||
/* A/D Calibrate */
|
||||
STM32_ADC_CR2 |= (1 << 2); /* CAL */
|
||||
while (STM32_ADC_CR2 & (1 << 2))
|
||||
;
|
||||
}
|
||||
|
||||
/* Set right alignment */
|
||||
STM32_ADC_CR2 &= ~(1 << 11);
|
||||
|
||||
/* Set sample time of all channels */
|
||||
STM32_ADC_SMPR1 = SMPR1_EXPAND(CONFIG_ADC_SAMPLE_TIME);
|
||||
STM32_ADC_SMPR2 = SMPR2_EXPAND(CONFIG_ADC_SAMPLE_TIME);
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, adc_init, HOOK_PRIO_DEFAULT);
|
||||
@@ -1 +0,0 @@
|
||||
adc-stm32f.c
|
||||
307
chip/stm32/adc-stm32f3.c
Normal file
307
chip/stm32/adc-stm32f3.c
Normal file
@@ -0,0 +1,307 @@
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "adc.h"
|
||||
#include "adc_chip.h"
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "dma.h"
|
||||
#include "hooks.h"
|
||||
#include "registers.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
|
||||
#define ADC_SINGLE_READ_TIMEOUT 3000 /* 3 ms */
|
||||
|
||||
#define SMPR1_EXPAND(v) ((v) | ((v) << 3) | ((v) << 6) | ((v) << 9) | \
|
||||
((v) << 12) | ((v) << 15) | ((v) << 18) | \
|
||||
((v) << 21))
|
||||
#define SMPR2_EXPAND(v) (SMPR1_EXPAND(v) | ((v) << 24) | ((v) << 27))
|
||||
|
||||
/* Default ADC sample time = 13.5 cycles */
|
||||
#ifndef CONFIG_ADC_SAMPLE_TIME
|
||||
#define CONFIG_ADC_SAMPLE_TIME 2
|
||||
#endif
|
||||
|
||||
struct mutex adc_lock;
|
||||
|
||||
static int watchdog_ain_id;
|
||||
|
||||
static const struct dma_option dma_adc_option = {
|
||||
STM32_DMAC_ADC, (void *)&STM32_ADC_DR,
|
||||
STM32_DMA_CCR_MSIZE_16_BIT | STM32_DMA_CCR_PSIZE_16_BIT,
|
||||
};
|
||||
|
||||
static inline void adc_set_channel(int sample_id, int channel)
|
||||
{
|
||||
uint32_t mask, val;
|
||||
volatile uint32_t *sqr_reg;
|
||||
|
||||
if (sample_id < 6) {
|
||||
mask = 0x1f << (sample_id * 5);
|
||||
val = channel << (sample_id * 5);
|
||||
sqr_reg = &STM32_ADC_SQR3;
|
||||
} else if (sample_id < 12) {
|
||||
mask = 0x1f << ((sample_id - 6) * 5);
|
||||
val = channel << ((sample_id - 6) * 5);
|
||||
sqr_reg = &STM32_ADC_SQR2;
|
||||
} else {
|
||||
mask = 0x1f << ((sample_id - 12) * 5);
|
||||
val = channel << ((sample_id - 12) * 5);
|
||||
sqr_reg = &STM32_ADC_SQR1;
|
||||
}
|
||||
|
||||
*sqr_reg = (*sqr_reg & ~mask) | val;
|
||||
}
|
||||
|
||||
static void adc_configure(int ain_id)
|
||||
{
|
||||
/* Set ADC channel */
|
||||
adc_set_channel(0, ain_id);
|
||||
|
||||
/* Disable DMA */
|
||||
STM32_ADC_CR2 &= ~(1 << 8);
|
||||
|
||||
/* Disable scan mode */
|
||||
STM32_ADC_CR1 &= ~(1 << 8);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) adc_configure_all(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Set ADC channels */
|
||||
STM32_ADC_SQR1 = (ADC_CH_COUNT - 1) << 20;
|
||||
for (i = 0; i < ADC_CH_COUNT; ++i)
|
||||
adc_set_channel(i, adc_channels[i].channel);
|
||||
|
||||
/* Enable DMA */
|
||||
STM32_ADC_CR2 |= (1 << 8);
|
||||
|
||||
/* Enable scan mode */
|
||||
STM32_ADC_CR1 |= (1 << 8);
|
||||
}
|
||||
|
||||
static inline int adc_powered(void)
|
||||
{
|
||||
return STM32_ADC_CR2 & (1 << 0);
|
||||
}
|
||||
|
||||
static inline int adc_conversion_ended(void)
|
||||
{
|
||||
return STM32_ADC_SR & (1 << 1);
|
||||
}
|
||||
|
||||
static int adc_watchdog_enabled(void)
|
||||
{
|
||||
return STM32_ADC_CR1 & (1 << 23);
|
||||
}
|
||||
|
||||
static int adc_enable_watchdog_no_lock(void)
|
||||
{
|
||||
/* Fail if watchdog already enabled */
|
||||
if (adc_watchdog_enabled())
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
/* Set channel */
|
||||
STM32_ADC_SQR3 = watchdog_ain_id;
|
||||
STM32_ADC_SQR1 = 0;
|
||||
STM32_ADC_CR1 = (STM32_ADC_CR1 & ~0x1f) | watchdog_ain_id;
|
||||
|
||||
/* Clear interrupt bit */
|
||||
STM32_ADC_SR &= ~0x1;
|
||||
|
||||
/* AWDSGL=1, SCAN=1, AWDIE=1, AWDEN=1 */
|
||||
STM32_ADC_CR1 |= (1 << 9) | (1 << 8) | (1 << 6) | (1 << 23);
|
||||
|
||||
/* Disable DMA */
|
||||
STM32_ADC_CR2 &= ~(1 << 8);
|
||||
|
||||
/* CONT=1 */
|
||||
STM32_ADC_CR2 |= (1 << 1);
|
||||
|
||||
/* Start conversion */
|
||||
STM32_ADC_CR2 |= (1 << 0);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
int adc_enable_watchdog(int ain_id, int high, int low)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!adc_powered())
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
mutex_lock(&adc_lock);
|
||||
|
||||
watchdog_ain_id = ain_id;
|
||||
|
||||
/* Set thresholds */
|
||||
STM32_ADC_HTR = high & 0xfff;
|
||||
STM32_ADC_LTR = low & 0xfff;
|
||||
|
||||
ret = adc_enable_watchdog_no_lock();
|
||||
mutex_unlock(&adc_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adc_disable_watchdog_no_lock(void)
|
||||
{
|
||||
/* Fail if watchdog not running */
|
||||
if (!adc_watchdog_enabled())
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
/* AWDEN=0, AWDIE=0 */
|
||||
STM32_ADC_CR1 &= ~(1 << 23) & ~(1 << 6);
|
||||
|
||||
/* CONT=0 */
|
||||
STM32_ADC_CR2 &= ~(1 << 1);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
int adc_disable_watchdog(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!adc_powered())
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
mutex_lock(&adc_lock);
|
||||
ret = adc_disable_watchdog_no_lock();
|
||||
mutex_unlock(&adc_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int adc_read_channel(enum adc_channel ch)
|
||||
{
|
||||
const struct adc_t *adc = adc_channels + ch;
|
||||
int value;
|
||||
int restore_watchdog = 0;
|
||||
timestamp_t deadline;
|
||||
|
||||
if (!adc_powered())
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
mutex_lock(&adc_lock);
|
||||
|
||||
if (adc_watchdog_enabled()) {
|
||||
restore_watchdog = 1;
|
||||
adc_disable_watchdog_no_lock();
|
||||
}
|
||||
|
||||
adc_configure(adc->channel);
|
||||
|
||||
/* Clear EOC bit */
|
||||
STM32_ADC_SR &= ~(1 << 1);
|
||||
|
||||
/* Start conversion */
|
||||
STM32_ADC_CR2 |= (1 << 0); /* ADON */
|
||||
|
||||
/* Wait for EOC bit set */
|
||||
deadline.val = get_time().val + ADC_SINGLE_READ_TIMEOUT;
|
||||
value = ADC_READ_ERROR;
|
||||
do {
|
||||
if (adc_conversion_ended()) {
|
||||
value = STM32_ADC_DR & ADC_READ_MAX;
|
||||
break;
|
||||
}
|
||||
} while (!timestamp_expired(deadline, NULL));
|
||||
|
||||
if (restore_watchdog)
|
||||
adc_enable_watchdog_no_lock();
|
||||
|
||||
mutex_unlock(&adc_lock);
|
||||
return (value == ADC_READ_ERROR) ? ADC_READ_ERROR :
|
||||
value * adc->factor_mul / adc->factor_div + adc->shift;
|
||||
}
|
||||
|
||||
int adc_read_all_channels(int *data)
|
||||
{
|
||||
int i;
|
||||
int16_t raw_data[ADC_CH_COUNT];
|
||||
const struct adc_t *adc;
|
||||
int restore_watchdog = 0;
|
||||
int ret = EC_SUCCESS;
|
||||
|
||||
if (!adc_powered())
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
mutex_lock(&adc_lock);
|
||||
|
||||
if (adc_watchdog_enabled()) {
|
||||
restore_watchdog = 1;
|
||||
adc_disable_watchdog_no_lock();
|
||||
}
|
||||
|
||||
adc_configure_all();
|
||||
|
||||
dma_clear_isr(STM32_DMAC_ADC);
|
||||
dma_start_rx(&dma_adc_option, ADC_CH_COUNT, raw_data);
|
||||
|
||||
/* Start conversion */
|
||||
STM32_ADC_CR2 |= (1 << 0); /* ADON */
|
||||
|
||||
if (dma_wait(STM32_DMAC_ADC)) {
|
||||
ret = EC_ERROR_UNKNOWN;
|
||||
goto exit_all_channels;
|
||||
}
|
||||
|
||||
for (i = 0; i < ADC_CH_COUNT; ++i) {
|
||||
adc = adc_channels + i;
|
||||
data[i] = raw_data[i] * adc->factor_mul / adc->factor_div +
|
||||
adc->shift;
|
||||
}
|
||||
|
||||
exit_all_channels:
|
||||
dma_disable(STM32_DMAC_ADC);
|
||||
|
||||
if (restore_watchdog)
|
||||
adc_enable_watchdog_no_lock();
|
||||
|
||||
mutex_unlock(&adc_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void adc_init(void)
|
||||
{
|
||||
/*
|
||||
* Enable ADC clock.
|
||||
* APB2 clock is 16MHz. ADC clock prescaler is /2.
|
||||
* So the ADC clock is 8MHz.
|
||||
*/
|
||||
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 */
|
||||
|
||||
/* Reset calibration */
|
||||
STM32_ADC_CR2 |= (1 << 3); /* RSTCAL */
|
||||
while (STM32_ADC_CR2 & (1 << 3))
|
||||
;
|
||||
|
||||
/* A/D Calibrate */
|
||||
STM32_ADC_CR2 |= (1 << 2); /* CAL */
|
||||
while (STM32_ADC_CR2 & (1 << 2))
|
||||
;
|
||||
}
|
||||
|
||||
/* Set right alignment */
|
||||
STM32_ADC_CR2 &= ~(1 << 11);
|
||||
|
||||
/* Set sample time of all channels */
|
||||
STM32_ADC_SMPR1 = SMPR1_EXPAND(CONFIG_ADC_SAMPLE_TIME);
|
||||
STM32_ADC_SMPR2 = SMPR2_EXPAND(CONFIG_ADC_SAMPLE_TIME);
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, adc_init, HOOK_PRIO_DEFAULT);
|
||||
@@ -42,7 +42,6 @@ chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o
|
||||
chip-$(HAS_TASK_POWERLED)+=power_led.o
|
||||
chip-$(CONFIG_FLASH)+=flash-$(CHIP_FAMILY).o
|
||||
ifdef CONFIG_FLASH
|
||||
chip-$(CHIP_FAMILY_STM32F)+=flash-f.o
|
||||
chip-$(CHIP_FAMILY_STM32F0)+=flash-f.o
|
||||
chip-$(CHIP_FAMILY_STM32F3)+=flash-f.o
|
||||
endif
|
||||
|
||||
@@ -1,304 +0,0 @@
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/* Clocks and power management settings */
|
||||
|
||||
#include "atomic.h"
|
||||
#include "clock.h"
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "cpu.h"
|
||||
#include "hwtimer.h"
|
||||
#include "registers.h"
|
||||
#include "system.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
|
||||
/* Allow serial console to wake up the EC from STOP mode */
|
||||
/* #define CONFIG_FORCE_CONSOLE_RESUME */
|
||||
|
||||
/*
|
||||
* minimum delay to enter stop mode
|
||||
* STOP mode wakeup time with regulator in low power mode is 5 us.
|
||||
* PLL locking time is 200us.
|
||||
*/
|
||||
#define STOP_MODE_LATENCY 300 /* us */
|
||||
|
||||
/*
|
||||
* RTC clock frequency (connected to LSI clock)
|
||||
*
|
||||
* TODO(crosbug.com/p/12281): Calibrate LSI frequency on a per-chip basis. The
|
||||
* LSI on any given chip can be between 30 kHz to 60 kHz. Without calibration,
|
||||
* LSI frequency may be off by as much as 50%. Fortunately, we don't do any
|
||||
* high-precision delays based solely on LSI.
|
||||
*/
|
||||
#define RTC_FREQ 40000 /* Hz */
|
||||
#define US_PER_RTC_TICK (1000000 / RTC_FREQ)
|
||||
|
||||
static void wait_rtc_ready(void)
|
||||
{
|
||||
/* wait for Registers Synchronized Flag */
|
||||
while (!(STM32_RTC_CRL & (1 << 3)))
|
||||
;
|
||||
}
|
||||
|
||||
static void prepare_rtc_write(void)
|
||||
{
|
||||
/* wait for RTOFF */
|
||||
while (!(STM32_RTC_CRL & (1 << 5)))
|
||||
;
|
||||
/* set CNF bit */
|
||||
STM32_RTC_CRL |= (1 << 4);
|
||||
}
|
||||
|
||||
static void finalize_rtc_write(void)
|
||||
{
|
||||
/* reset CNF bit */
|
||||
STM32_RTC_CRL &= ~(1 << 4);
|
||||
/* wait for RTOFF */
|
||||
while (!(STM32_RTC_CRL & (1 << 5)))
|
||||
;
|
||||
}
|
||||
|
||||
uint32_t set_rtc_alarm(unsigned delay_s, unsigned delay_us)
|
||||
{
|
||||
unsigned rtc_t0, rtc_t1;
|
||||
|
||||
rtc_t0 = ((uint32_t)STM32_RTC_CNTH << 16) | STM32_RTC_CNTL;
|
||||
rtc_t1 = rtc_t0 + delay_us / US_PER_RTC_TICK + delay_s * RTC_FREQ;
|
||||
|
||||
prepare_rtc_write();
|
||||
/* set RTC alarm timestamp (using the 40kHz counter ) */
|
||||
STM32_RTC_ALRH = rtc_t1 >> 16;
|
||||
STM32_RTC_ALRL = rtc_t1 & 0xffff;
|
||||
/* clear RTC alarm */
|
||||
STM32_RTC_CRL &= ~2;
|
||||
/* enable RTC alarm interrupt */
|
||||
STM32_RTC_CRL |= 2;
|
||||
finalize_rtc_write();
|
||||
/* remove synchro flag */
|
||||
STM32_RTC_CRL &= ~(1 << 3);
|
||||
|
||||
return rtc_t0;
|
||||
}
|
||||
|
||||
uint32_t reset_rtc_alarm(void)
|
||||
{
|
||||
uint32_t rtc_stamp;
|
||||
|
||||
wait_rtc_ready();
|
||||
|
||||
prepare_rtc_write();
|
||||
/* clear RTC alarm */
|
||||
STM32_RTC_CRL &= ~2;
|
||||
finalize_rtc_write();
|
||||
STM32_EXTI_PR = (1 << 17);
|
||||
|
||||
rtc_stamp = ((uint32_t)STM32_RTC_CNTH << 16) | STM32_RTC_CNTL;
|
||||
return rtc_stamp;
|
||||
}
|
||||
|
||||
void __rtc_wakeup_irq(void)
|
||||
{
|
||||
reset_rtc_alarm();
|
||||
}
|
||||
DECLARE_IRQ(STM32_IRQ_RTC_WAKEUP, __rtc_wakeup_irq, 1);
|
||||
|
||||
void __rtc_alarm_irq(void)
|
||||
{
|
||||
reset_rtc_alarm();
|
||||
}
|
||||
DECLARE_IRQ(STM32_IRQ_RTC_ALARM, __rtc_alarm_irq, 1);
|
||||
|
||||
/*
|
||||
* These were the clock settings we used for the STM32F103 reference, but
|
||||
* they'll need updating for use on some other board.
|
||||
*
|
||||
* HSI = 8MHz, no prescaler, no MCO
|
||||
* PLLSRC = HSI/2, PLLMUL = x12 => PLLCLK = 48MHz
|
||||
* USB clock = PLLCLK
|
||||
*/
|
||||
#define DESIRED_CPU_CLOCK 48000000
|
||||
#define RCC_CFGR 0x00680000
|
||||
#error "Need board-specific clock settings"
|
||||
|
||||
BUILD_ASSERT(CPU_CLOCK == DESIRED_CPU_CLOCK);
|
||||
|
||||
static void config_hispeed_clock(void)
|
||||
{
|
||||
/* Ensure that HSI is ON */
|
||||
if (!(STM32_RCC_CR & (1 << 1))) {
|
||||
/* Enable HSI */
|
||||
STM32_RCC_CR |= 1 << 0;
|
||||
/* Wait for HSI to be ready */
|
||||
while (!(STM32_RCC_CR & (1 << 1)))
|
||||
;
|
||||
}
|
||||
|
||||
STM32_RCC_CFGR = RCC_CFGR;
|
||||
/* Enable the PLL */
|
||||
STM32_RCC_CR |= 1 << 24;
|
||||
/* Wait for the PLL to lock */
|
||||
while (!(STM32_RCC_CR & (1 << 25)))
|
||||
;
|
||||
/* switch to SYSCLK to the PLL */
|
||||
STM32_RCC_CFGR = RCC_CFGR | 0x02;
|
||||
|
||||
/* wait until the PLL is the clock source */
|
||||
while ((STM32_RCC_CFGR & 0xc) != 0x8)
|
||||
;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HIBERNATE
|
||||
void __enter_hibernate(uint32_t seconds, uint32_t microseconds)
|
||||
{
|
||||
if (seconds || microseconds)
|
||||
set_rtc_alarm(seconds, microseconds);
|
||||
|
||||
/* interrupts off now */
|
||||
asm volatile("cpsid i");
|
||||
|
||||
/* enable the wake up pin */
|
||||
STM32_PWR_CSR |= STM32_PWR_CSR_EWUP;
|
||||
STM32_PWR_CR |= 0xe;
|
||||
CPU_SCB_SYSCTRL |= 0x4;
|
||||
/* go to Standby mode */
|
||||
asm("wfi");
|
||||
|
||||
/* we should never reach that point */
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LOW_POWER_IDLE
|
||||
|
||||
void clock_refresh_console_in_use(void)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FORCE_CONSOLE_RESUME
|
||||
static void enable_serial_wakeup(int enable)
|
||||
{
|
||||
static uint32_t save_exticr;
|
||||
|
||||
if (enable) {
|
||||
/**
|
||||
* allow to wake up from serial port (RX on pin PA10)
|
||||
* by setting it as a GPIO with an external interrupt.
|
||||
*/
|
||||
save_exticr = STM32_AFIO_EXTICR(10 / 4);
|
||||
STM32_AFIO_EXTICR(10 / 4) = (save_exticr & ~(0xf << 8));
|
||||
} else {
|
||||
/* serial port wake up : don't go back to sleep */
|
||||
if (STM32_EXTI_PR & (1 << 10))
|
||||
disable_sleep(SLEEP_MASK_FORCE_NO_DSLEEP);
|
||||
/* restore keyboard external IT on PC10 */
|
||||
STM32_AFIO_EXTICR(10 / 4) = save_exticr;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void enable_serial_wakeup(int enable)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Idle task. Executed when no tasks are ready to be scheduled. */
|
||||
void __idle(void)
|
||||
{
|
||||
timestamp_t t0, t1;
|
||||
int next_delay;
|
||||
uint32_t rtc_t0, rtc_t1;
|
||||
|
||||
while (1) {
|
||||
asm volatile("cpsid i");
|
||||
|
||||
t0 = get_time();
|
||||
next_delay = __hw_clock_event_get() - t0.le.lo;
|
||||
|
||||
if (DEEP_SLEEP_ALLOWED && (next_delay > STOP_MODE_LATENCY)) {
|
||||
/* deep-sleep in STOP mode */
|
||||
|
||||
enable_serial_wakeup(1);
|
||||
|
||||
/* set deep sleep bit */
|
||||
CPU_SCB_SYSCTRL |= 0x4;
|
||||
|
||||
rtc_t0 = set_rtc_alarm(0,
|
||||
next_delay - STOP_MODE_LATENCY);
|
||||
asm("wfi");
|
||||
|
||||
CPU_SCB_SYSCTRL &= ~0x4;
|
||||
|
||||
enable_serial_wakeup(0);
|
||||
|
||||
/* re-lock the PLL */
|
||||
config_hispeed_clock();
|
||||
|
||||
/* fast forward timer according to RTC counter */
|
||||
rtc_t1 = reset_rtc_alarm();
|
||||
t1.val = t0.val + (rtc_t1 - rtc_t0) * US_PER_RTC_TICK;
|
||||
force_time(t1);
|
||||
} else {
|
||||
/* normal idle : only CPU clock stopped */
|
||||
asm("wfi");
|
||||
}
|
||||
asm volatile("cpsie i");
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_LOW_POWER_IDLE */
|
||||
|
||||
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)
|
||||
{
|
||||
/*
|
||||
* The initial state :
|
||||
* SYSCLK from HSI (=8MHz), no divider on AHB, APB1, APB2
|
||||
* PLL unlocked, RTC enabled on LSE
|
||||
*/
|
||||
|
||||
config_hispeed_clock();
|
||||
|
||||
/* configure RTC clock */
|
||||
wait_rtc_ready();
|
||||
prepare_rtc_write();
|
||||
/* set RTC divider to /1 */
|
||||
STM32_RTC_PRLH = 0;
|
||||
STM32_RTC_PRLL = 0;
|
||||
finalize_rtc_write();
|
||||
/* setup RTC EXTINT17 to wake up us from STOP mode */
|
||||
STM32_EXTI_IMR |= (1 << 17);
|
||||
STM32_EXTI_RTSR |= (1 << 17);
|
||||
|
||||
/*
|
||||
* Our deep sleep mode is STOP mode.
|
||||
* clear PDDS (stop mode) , set LDDS (regulator in low power mode)
|
||||
*/
|
||||
STM32_PWR_CR = (STM32_PWR_CR & ~2) | 1;
|
||||
|
||||
/* Enable RTC interrupts */
|
||||
task_enable_irq(STM32_IRQ_RTC_WAKEUP);
|
||||
task_enable_irq(STM32_IRQ_RTC_ALARM);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/* Memory mapping */
|
||||
#define CONFIG_FLASH_BASE 0x08000000
|
||||
#define CONFIG_FLASH_PHYSICAL_SIZE 0x00020000
|
||||
#define CONFIG_FLASH_BANK_SIZE 0x1000
|
||||
#define CONFIG_FLASH_ERASE_SIZE 0x0400 /* erase bank size */
|
||||
#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */
|
||||
|
||||
/* No page mode on STM32F, so no benefit to larger write sizes */
|
||||
#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0002
|
||||
|
||||
#define CONFIG_RAM_BASE 0x20000000
|
||||
#define CONFIG_RAM_SIZE 0x00002000
|
||||
|
||||
/* Number of IRQ vectors on the NVIC */
|
||||
#define CONFIG_IRQ_COUNT 61
|
||||
|
||||
/* Reduced history because of limited RAM */
|
||||
#undef CONFIG_CONSOLE_HISTORY
|
||||
#define CONFIG_CONSOLE_HISTORY 3
|
||||
@@ -1,20 +0,0 @@
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/* Memory mapping */
|
||||
#define CONFIG_FLASH_BASE 0x08000000
|
||||
#define CONFIG_FLASH_PHYSICAL_SIZE 0x00020000
|
||||
#define CONFIG_FLASH_BANK_SIZE 0x1000
|
||||
#define CONFIG_FLASH_ERASE_SIZE 0x0400 /* erase bank size */
|
||||
#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */
|
||||
|
||||
/* No page mode on STM32F, so no benefit to larger write sizes */
|
||||
#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0002
|
||||
|
||||
#define CONFIG_RAM_BASE 0x20000000
|
||||
#define CONFIG_RAM_SIZE (10 * 1024)
|
||||
|
||||
/* Number of IRQ vectors on the NVIC */
|
||||
#define CONFIG_IRQ_COUNT 68
|
||||
@@ -24,12 +24,6 @@
|
||||
#include "config-stm32l100.h"
|
||||
#elif defined(CHIP_VARIANT_STM32F373)
|
||||
#include "config-stm32f373.h"
|
||||
#elif defined(CHIP_VARIANT_STM32F100)
|
||||
/* STM32F100xx is currently the only outlier in the STM32F series */
|
||||
#include "config-stm32f100.h"
|
||||
#elif defined(CHIP_VARIANT_STM32F10X)
|
||||
/* STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx, and STM32F107xx */
|
||||
#include "config-stm32f10x.h"
|
||||
#elif defined(CHIP_VARIANT_STM32F09X)
|
||||
/* STM32F09xx */
|
||||
#include "config-stm32f09x.h"
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
/* Copyright 2014 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/* Flash memory module for Chrome EC */
|
||||
|
||||
#include "common.h"
|
||||
#include "flash.h"
|
||||
#include "hooks.h"
|
||||
#include "registers.h"
|
||||
#include "system.h"
|
||||
#include "panic.h"
|
||||
|
||||
/* Flag indicating whether we have locked down entire flash */
|
||||
static int entire_flash_locked;
|
||||
|
||||
#define FLASH_SYSJUMP_TAG 0x5750 /* "WP" - Write Protect */
|
||||
#define FLASH_HOOK_VERSION 1
|
||||
/* The previous write protect state before sys jump */
|
||||
/*
|
||||
* TODO(crosbug.com/p/23798): check if STM32L code works here too - that is,
|
||||
* check if entire flash is locked by attempting to lock it rather than keeping
|
||||
* a global variable.
|
||||
*/
|
||||
struct flash_wp_state {
|
||||
int entire_flash_locked;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Physical layer APIs */
|
||||
|
||||
int flash_physical_get_protect(int block)
|
||||
{
|
||||
return entire_flash_locked || !(STM32_FLASH_WRPR & (1 << block));
|
||||
}
|
||||
|
||||
uint32_t flash_physical_get_protect_flags(void)
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
|
||||
/* Read all-protected state from our shadow copy */
|
||||
if (entire_flash_locked)
|
||||
flags |= EC_FLASH_PROTECT_ALL_NOW;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
int flash_physical_protect_now(int all)
|
||||
{
|
||||
if (all) {
|
||||
/*
|
||||
* Lock by writing a wrong key to FLASH_KEYR. This triggers a
|
||||
* bus fault, so we need to disable bus fault handler while
|
||||
* doing this.
|
||||
*/
|
||||
ignore_bus_fault(1);
|
||||
STM32_FLASH_KEYR = 0xffffffff;
|
||||
ignore_bus_fault(0);
|
||||
|
||||
entire_flash_locked = 1;
|
||||
|
||||
return EC_SUCCESS;
|
||||
} else {
|
||||
/* No way to protect just the RO flash until next boot */
|
||||
return EC_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t flash_physical_get_valid_flags(void)
|
||||
{
|
||||
return EC_FLASH_PROTECT_RO_AT_BOOT |
|
||||
EC_FLASH_PROTECT_RO_NOW |
|
||||
EC_FLASH_PROTECT_ALL_NOW;
|
||||
}
|
||||
|
||||
uint32_t flash_physical_get_writable_flags(uint32_t cur_flags)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
/* If RO protection isn't enabled, its at-boot state can be changed. */
|
||||
if (!(cur_flags & EC_FLASH_PROTECT_RO_NOW))
|
||||
ret |= EC_FLASH_PROTECT_RO_AT_BOOT;
|
||||
|
||||
/*
|
||||
* If entire flash isn't protected at this boot, it can be enabled if
|
||||
* the WP GPIO is asserted.
|
||||
*/
|
||||
if (!(cur_flags & EC_FLASH_PROTECT_ALL_NOW) &&
|
||||
(cur_flags & EC_FLASH_PROTECT_GPIO_ASSERTED))
|
||||
ret |= EC_FLASH_PROTECT_ALL_NOW;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int flash_physical_restore_state(void)
|
||||
{
|
||||
uint32_t reset_flags = system_get_reset_flags();
|
||||
int version, size;
|
||||
const struct flash_wp_state *prev;
|
||||
|
||||
/*
|
||||
* If we have already jumped between images, an earlier image could
|
||||
* have applied write protection. Nothing additional needs to be done.
|
||||
*/
|
||||
if (reset_flags & RESET_FLAG_SYSJUMP) {
|
||||
prev = (const struct flash_wp_state *)system_get_jump_tag(
|
||||
FLASH_SYSJUMP_TAG, &version, &size);
|
||||
if (prev && version == FLASH_HOOK_VERSION &&
|
||||
size == sizeof(*prev))
|
||||
entire_flash_locked = prev->entire_flash_locked;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Hooks */
|
||||
|
||||
static void flash_preserve_state(void)
|
||||
{
|
||||
struct flash_wp_state state;
|
||||
|
||||
state.entire_flash_locked = entire_flash_locked;
|
||||
|
||||
system_add_jump_tag(FLASH_SYSJUMP_TAG, FLASH_HOOK_VERSION,
|
||||
sizeof(state), &state);
|
||||
}
|
||||
DECLARE_HOOK(HOOK_SYSJUMP, flash_preserve_state, HOOK_PRIO_DEFAULT);
|
||||
@@ -1 +0,0 @@
|
||||
flash-stm32f.c
|
||||
130
chip/stm32/flash-stm32f3.c
Normal file
130
chip/stm32/flash-stm32f3.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/* Copyright 2014 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/* Flash memory module for Chrome EC */
|
||||
|
||||
#include "common.h"
|
||||
#include "flash.h"
|
||||
#include "hooks.h"
|
||||
#include "registers.h"
|
||||
#include "system.h"
|
||||
#include "panic.h"
|
||||
|
||||
/* Flag indicating whether we have locked down entire flash */
|
||||
static int entire_flash_locked;
|
||||
|
||||
#define FLASH_SYSJUMP_TAG 0x5750 /* "WP" - Write Protect */
|
||||
#define FLASH_HOOK_VERSION 1
|
||||
/* The previous write protect state before sys jump */
|
||||
/*
|
||||
* TODO(crosbug.com/p/23798): check if STM32L code works here too - that is,
|
||||
* check if entire flash is locked by attempting to lock it rather than keeping
|
||||
* a global variable.
|
||||
*/
|
||||
struct flash_wp_state {
|
||||
int entire_flash_locked;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Physical layer APIs */
|
||||
|
||||
int flash_physical_get_protect(int block)
|
||||
{
|
||||
return entire_flash_locked || !(STM32_FLASH_WRPR & (1 << block));
|
||||
}
|
||||
|
||||
uint32_t flash_physical_get_protect_flags(void)
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
|
||||
/* Read all-protected state from our shadow copy */
|
||||
if (entire_flash_locked)
|
||||
flags |= EC_FLASH_PROTECT_ALL_NOW;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
int flash_physical_protect_now(int all)
|
||||
{
|
||||
if (all) {
|
||||
/*
|
||||
* Lock by writing a wrong key to FLASH_KEYR. This triggers a
|
||||
* bus fault, so we need to disable bus fault handler while
|
||||
* doing this.
|
||||
*/
|
||||
ignore_bus_fault(1);
|
||||
STM32_FLASH_KEYR = 0xffffffff;
|
||||
ignore_bus_fault(0);
|
||||
|
||||
entire_flash_locked = 1;
|
||||
|
||||
return EC_SUCCESS;
|
||||
} else {
|
||||
/* No way to protect just the RO flash until next boot */
|
||||
return EC_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t flash_physical_get_valid_flags(void)
|
||||
{
|
||||
return EC_FLASH_PROTECT_RO_AT_BOOT |
|
||||
EC_FLASH_PROTECT_RO_NOW |
|
||||
EC_FLASH_PROTECT_ALL_NOW;
|
||||
}
|
||||
|
||||
uint32_t flash_physical_get_writable_flags(uint32_t cur_flags)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
/* If RO protection isn't enabled, its at-boot state can be changed. */
|
||||
if (!(cur_flags & EC_FLASH_PROTECT_RO_NOW))
|
||||
ret |= EC_FLASH_PROTECT_RO_AT_BOOT;
|
||||
|
||||
/*
|
||||
* If entire flash isn't protected at this boot, it can be enabled if
|
||||
* the WP GPIO is asserted.
|
||||
*/
|
||||
if (!(cur_flags & EC_FLASH_PROTECT_ALL_NOW) &&
|
||||
(cur_flags & EC_FLASH_PROTECT_GPIO_ASSERTED))
|
||||
ret |= EC_FLASH_PROTECT_ALL_NOW;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int flash_physical_restore_state(void)
|
||||
{
|
||||
uint32_t reset_flags = system_get_reset_flags();
|
||||
int version, size;
|
||||
const struct flash_wp_state *prev;
|
||||
|
||||
/*
|
||||
* If we have already jumped between images, an earlier image could
|
||||
* have applied write protection. Nothing additional needs to be done.
|
||||
*/
|
||||
if (reset_flags & RESET_FLAG_SYSJUMP) {
|
||||
prev = (const struct flash_wp_state *)system_get_jump_tag(
|
||||
FLASH_SYSJUMP_TAG, &version, &size);
|
||||
if (prev && version == FLASH_HOOK_VERSION &&
|
||||
size == sizeof(*prev))
|
||||
entire_flash_locked = prev->entire_flash_locked;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Hooks */
|
||||
|
||||
static void flash_preserve_state(void)
|
||||
{
|
||||
struct flash_wp_state state;
|
||||
|
||||
state.entire_flash_locked = entire_flash_locked;
|
||||
|
||||
system_add_jump_tag(FLASH_SYSJUMP_TAG, FLASH_HOOK_VERSION,
|
||||
sizeof(state), &state);
|
||||
}
|
||||
DECLARE_HOOK(HOOK_SYSJUMP, flash_preserve_state, HOOK_PRIO_DEFAULT);
|
||||
@@ -1,149 +0,0 @@
|
||||
/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/* GPIO module for Chrome EC */
|
||||
|
||||
#include "clock.h"
|
||||
#include "common.h"
|
||||
#include "gpio.h"
|
||||
#include "hooks.h"
|
||||
#include "registers.h"
|
||||
#include "task.h"
|
||||
#include "util.h"
|
||||
|
||||
/**
|
||||
* Helper function for generating bitmasks for STM32 GPIO config registers
|
||||
*/
|
||||
static void gpio_config_info(uint32_t port, uint32_t mask, uint32_t *addr,
|
||||
uint32_t *mode, uint32_t *cnf) {
|
||||
/*
|
||||
* 2-bit config followed by 2-bit mode for each pin, each
|
||||
* successive pin raises the exponent for the lowest bit
|
||||
* set by an order of 4, e.g. 2^0, 2^4, 2^8, etc.
|
||||
*/
|
||||
if (mask & 0xff) {
|
||||
*addr = port; /* GPIOx_CRL */
|
||||
*mode = mask;
|
||||
} else {
|
||||
*addr = port + 0x04; /* GPIOx_CRH */
|
||||
*mode = mask >> 8;
|
||||
}
|
||||
*mode = *mode * *mode * *mode * *mode;
|
||||
*mode |= *mode << 1;
|
||||
*cnf = *mode << 2;
|
||||
}
|
||||
|
||||
void gpio_set_flags_by_mask(uint32_t port, uint32_t pmask, uint32_t flags)
|
||||
{
|
||||
uint32_t addr, cnf, mode, mask;
|
||||
|
||||
gpio_config_info(port, pmask, &addr, &mode, &cnf);
|
||||
mask = REG32(addr) & ~(cnf | mode);
|
||||
|
||||
/*
|
||||
* For STM32, the port configuration field changes meaning
|
||||
* depending on whether the port is an input, analog input,
|
||||
* output, or alternate function.
|
||||
*/
|
||||
if (flags & GPIO_OUTPUT) {
|
||||
/*
|
||||
* This sets output max speed to 10MHz. That should be
|
||||
* sufficient for most GPIO needs; the only thing that needs to
|
||||
* go faster is SPI, which overrides the port speed on its own.
|
||||
*/
|
||||
mask |= 0x11111111 & mode;
|
||||
if (flags & GPIO_OPEN_DRAIN)
|
||||
mask |= 0x44444444 & cnf;
|
||||
|
||||
} else {
|
||||
/*
|
||||
* GPIOx_ODR determines which resistor to activate in
|
||||
* input mode, see Table 16 (datasheet rm0041)
|
||||
*/
|
||||
if (flags & GPIO_ANALOG) {
|
||||
/* Analog input, MODE=00 CNF=00 */
|
||||
/* the 4 bits in mask are already reset above */
|
||||
} else if (flags & GPIO_PULL_UP) {
|
||||
mask |= 0x88888888 & cnf;
|
||||
STM32_GPIO_BSRR(port) = pmask;
|
||||
} else if (flags & GPIO_PULL_DOWN) {
|
||||
mask |= 0x88888888 & cnf;
|
||||
STM32_GPIO_BSRR(port) = pmask << 16;
|
||||
} else {
|
||||
mask |= 0x44444444 & cnf;
|
||||
}
|
||||
}
|
||||
|
||||
REG32(addr) = mask;
|
||||
|
||||
if (flags & GPIO_OUTPUT) {
|
||||
/*
|
||||
* Set pin level after port has been set up as to avoid
|
||||
* potential damage, e.g. driving an open-drain output high
|
||||
* before it has been configured as such.
|
||||
*/
|
||||
if (flags & GPIO_HIGH)
|
||||
STM32_GPIO_BSRR(port) = pmask;
|
||||
else if (flags & GPIO_LOW)
|
||||
STM32_GPIO_BSRR(port) = pmask << 16;
|
||||
}
|
||||
|
||||
/* Set up interrupts if necessary */
|
||||
ASSERT(!(flags & (GPIO_INT_F_LOW | GPIO_INT_F_HIGH)));
|
||||
if (flags & GPIO_INT_F_RISING)
|
||||
STM32_EXTI_RTSR |= pmask;
|
||||
if (flags & GPIO_INT_F_FALLING)
|
||||
STM32_EXTI_FTSR |= pmask;
|
||||
/* Interrupt is enabled by gpio_enable_interrupt() */
|
||||
}
|
||||
|
||||
int gpio_is_reboot_warm(void)
|
||||
{
|
||||
return (STM32_RCC_APB1ENR & 1);
|
||||
}
|
||||
|
||||
void gpio_enable_clocks(void)
|
||||
{
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifdef CHIP_VARIANT_STM32TS60
|
||||
STM32_RCC_APB2ENR |= 0x7fd;
|
||||
#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)
|
||||
{
|
||||
/* TODO(crosbug.com/p/21618): implement me! */
|
||||
}
|
||||
|
||||
static void gpio_init(void)
|
||||
{
|
||||
/* Enable IRQs now that pins are set up */
|
||||
task_enable_irq(STM32_IRQ_EXTI0);
|
||||
task_enable_irq(STM32_IRQ_EXTI1);
|
||||
task_enable_irq(STM32_IRQ_EXTI2);
|
||||
task_enable_irq(STM32_IRQ_EXTI3);
|
||||
task_enable_irq(STM32_IRQ_EXTI4);
|
||||
task_enable_irq(STM32_IRQ_EXTI9_5);
|
||||
task_enable_irq(STM32_IRQ_EXTI15_10);
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT);
|
||||
|
||||
DECLARE_IRQ(STM32_IRQ_EXTI0, gpio_interrupt, 1);
|
||||
DECLARE_IRQ(STM32_IRQ_EXTI1, gpio_interrupt, 1);
|
||||
DECLARE_IRQ(STM32_IRQ_EXTI2, gpio_interrupt, 1);
|
||||
DECLARE_IRQ(STM32_IRQ_EXTI3, gpio_interrupt, 1);
|
||||
DECLARE_IRQ(STM32_IRQ_EXTI4, gpio_interrupt, 1);
|
||||
DECLARE_IRQ(STM32_IRQ_EXTI9_5, gpio_interrupt, 1);
|
||||
DECLARE_IRQ(STM32_IRQ_EXTI15_10, gpio_interrupt, 1);
|
||||
@@ -96,17 +96,8 @@ int gpio_enable_interrupt(enum gpio_signal signal)
|
||||
shift = (bit % 4) * 4;
|
||||
bank = (g->port - STM32_GPIOA_BASE) / 0x400;
|
||||
|
||||
#if defined(CHIP_FAMILY_STM32F)
|
||||
STM32_AFIO_EXTICR(group) = (STM32_AFIO_EXTICR(group) &
|
||||
~(0xF << shift)) | (bank << shift);
|
||||
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32L) || \
|
||||
defined(CHIP_FAMILY_STM32F3)
|
||||
STM32_SYSCFG_EXTICR(group) = (STM32_SYSCFG_EXTICR(group) &
|
||||
~(0xF << shift)) | (bank << shift);
|
||||
#else
|
||||
#error "Unsupported chip family"
|
||||
#endif
|
||||
|
||||
~(0xF << shift)) | (bank << shift);
|
||||
STM32_EXTI_IMR |= g->mask;
|
||||
|
||||
return EC_SUCCESS;
|
||||
|
||||
@@ -238,7 +238,7 @@ void __hw_timer_enable_clock(int n, int enable)
|
||||
* Mapping of timers to reg/mask is split into a few different ranges,
|
||||
* some specific to individual chips.
|
||||
*/
|
||||
#if defined(CHIP_FAMILY_STM32F) || defined(CHIP_FAMILY_STM32F0)
|
||||
#if defined(CHIP_FAMILY_STM32F0)
|
||||
if (n == 1) {
|
||||
reg = &STM32_RCC_APB2ENR;
|
||||
mask = STM32_RCC_PB2_TIM1;
|
||||
|
||||
@@ -72,7 +72,7 @@ void __hw_timer_enable_clock(int n, int enable)
|
||||
* Mapping of timers to reg/mask is split into a few different ranges,
|
||||
* some specific to individual chips.
|
||||
*/
|
||||
#if defined(CHIP_FAMILY_STM32F) || defined(CHIP_FAMILY_STM32F0)
|
||||
#if defined(CHIP_FAMILY_STM32F0)
|
||||
if (n == 1) {
|
||||
reg = &STM32_RCC_APB2ENR;
|
||||
mask = STM32_RCC_PB2_TIM1;
|
||||
|
||||
@@ -1,769 +0,0 @@
|
||||
/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "chipset.h"
|
||||
#include "clock.h"
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "dma.h"
|
||||
#include "gpio.h"
|
||||
#include "hooks.h"
|
||||
#include "host_command.h"
|
||||
#include "i2c.h"
|
||||
#include "i2c_arbitration.h"
|
||||
#include "registers.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
|
||||
/* Console output macros */
|
||||
#define CPUTS(outstr) cputs(CC_I2C, outstr)
|
||||
#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args)
|
||||
#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args)
|
||||
|
||||
/* 8-bit I2C slave address */
|
||||
#define I2C_ADDRESS 0x3c
|
||||
|
||||
/* I2C bus frequency */
|
||||
#define I2C_FREQ 100000 /* Hz */
|
||||
|
||||
/* I2C bit period in microseconds */
|
||||
#define I2C_PERIOD_US (SECOND / I2C_FREQ)
|
||||
|
||||
/* Clock divider for I2C controller */
|
||||
#define I2C_CCR (CPU_CLOCK / (2 * I2C_FREQ))
|
||||
|
||||
/*
|
||||
* Transmit timeout in microseconds
|
||||
*
|
||||
* In theory we shouldn't have a timeout here (at least when we're in slave
|
||||
* mode). The slave is supposed to wait forever for the master to read bytes.
|
||||
* ...but we're going to keep the timeout to make sure we're robust. It may in
|
||||
* fact be needed if the host resets itself mid-read.
|
||||
*
|
||||
* NOTE: One case where this timeout is useful is when the battery
|
||||
* flips out. The battery may flip out and hold lines low for up to
|
||||
* 25ms. If we just wait it will eventually let them go.
|
||||
*/
|
||||
#define I2C_TX_TIMEOUT_SLAVE (100 * MSEC)
|
||||
#define I2C_TX_TIMEOUT_MASTER (30 * MSEC)
|
||||
|
||||
/*
|
||||
* We delay 5us in bitbang mode. That gives us 5us low and 5us high or
|
||||
* a frequency of 100kHz.
|
||||
*
|
||||
* Note that the code takes a little time to run so we don't actually get
|
||||
* 100kHz, but that's OK.
|
||||
*/
|
||||
#define I2C_BITBANG_DELAY_US 5
|
||||
|
||||
#define I2C1 STM32_I2C1_PORT
|
||||
#define I2C2 STM32_I2C2_PORT
|
||||
|
||||
/* Select the DMA channels matching the board configuration */
|
||||
#define DMAC_SLAVE_TX \
|
||||
((I2C_PORT_SLAVE) ? STM32_DMAC_I2C2_TX : STM32_DMAC_I2C1_TX)
|
||||
#define DMAC_SLAVE_RX \
|
||||
((I2C_PORT_SLAVE) ? STM32_DMAC_I2C2_RX : STM32_DMAC_I2C1_RX)
|
||||
#define DMAC_MASTER_TX \
|
||||
((I2C_PORT_MASTER) ? STM32_DMAC_I2C2_TX : STM32_DMAC_I2C1_TX)
|
||||
#define DMAC_MASTER_RX \
|
||||
((I2C_PORT_MASTER) ? STM32_DMAC_I2C2_RX : STM32_DMAC_I2C1_RX)
|
||||
|
||||
enum {
|
||||
/*
|
||||
* A stop condition should take 2 clocks, but the process may need more
|
||||
* time to notice if it is preempted, so we poll repeatedly for 8
|
||||
* clocks, before backing off and only check once every
|
||||
* STOP_SENT_RETRY_US for up to TIMEOUT_STOP_SENT clocks before giving
|
||||
* up.
|
||||
*/
|
||||
SLOW_STOP_SENT_US = I2C_PERIOD_US * 8,
|
||||
TIMEOUT_STOP_SENT_US = I2C_PERIOD_US * 200,
|
||||
STOP_SENT_RETRY_US = 150,
|
||||
};
|
||||
|
||||
static const struct dma_option dma_tx_option[I2C_PORT_COUNT] = {
|
||||
{STM32_DMAC_I2C1_TX, (void *)&STM32_I2C_DR(I2C1),
|
||||
STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_16_BIT},
|
||||
{STM32_DMAC_I2C2_TX, (void *)&STM32_I2C_DR(I2C2),
|
||||
STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_16_BIT},
|
||||
};
|
||||
|
||||
static const struct dma_option dma_rx_option[I2C_PORT_COUNT] = {
|
||||
{STM32_DMAC_I2C1_RX, (void *)&STM32_I2C_DR(I2C1),
|
||||
STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_16_BIT},
|
||||
{STM32_DMAC_I2C2_RX, (void *)&STM32_I2C_DR(I2C2),
|
||||
STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_16_BIT},
|
||||
};
|
||||
|
||||
static uint16_t i2c_sr1[I2C_PORT_COUNT];
|
||||
|
||||
/* Buffer for host commands (including version, error code and checksum) */
|
||||
static uint8_t host_buffer[EC_PROTO2_MAX_REQUEST_SIZE];
|
||||
static struct host_cmd_handler_args host_cmd_args;
|
||||
static uint8_t i2c_old_response; /* Send an old-style response */
|
||||
|
||||
/* Flag indicating if a command is currently in the buffer */
|
||||
static uint8_t rx_pending;
|
||||
|
||||
static inline void disable_i2c_interrupt(int port)
|
||||
{
|
||||
STM32_I2C_CR2(port) &= ~(3 << 8);
|
||||
}
|
||||
|
||||
static inline void enable_i2c_interrupt(int port)
|
||||
{
|
||||
STM32_I2C_CR2(port) |= 3 << 8;
|
||||
}
|
||||
|
||||
static inline void enable_ack(int port)
|
||||
{
|
||||
STM32_I2C_CR1(port) |= (1 << 10);
|
||||
}
|
||||
|
||||
static inline void disable_ack(int port)
|
||||
{
|
||||
STM32_I2C_CR1(port) &= ~(1 << 10);
|
||||
}
|
||||
|
||||
static void i2c_init_port(unsigned int port);
|
||||
|
||||
static int i2c_write_raw_slave(int port, void *buf, int len)
|
||||
{
|
||||
stm32_dma_chan_t *chan;
|
||||
int rv;
|
||||
|
||||
/* we don't want to race with TxE interrupt event */
|
||||
disable_i2c_interrupt(port);
|
||||
|
||||
/* Configuring DMA1 channel DMAC_SLAVE_TX */
|
||||
enable_ack(port);
|
||||
chan = dma_get_channel(DMAC_SLAVE_TX);
|
||||
dma_prepare_tx(dma_tx_option + port, len, buf);
|
||||
|
||||
/* Start the DMA */
|
||||
dma_go(chan);
|
||||
|
||||
/* Configuring i2c to use DMA */
|
||||
STM32_I2C_CR2(port) |= (1 << 11);
|
||||
|
||||
if (in_interrupt_context()) {
|
||||
/* Poll for the transmission complete flag */
|
||||
dma_wait(DMAC_SLAVE_TX);
|
||||
dma_clear_isr(DMAC_SLAVE_TX);
|
||||
} else {
|
||||
/* Wait for the transmission complete Interrupt */
|
||||
dma_enable_tc_interrupt(DMAC_SLAVE_TX);
|
||||
rv = task_wait_event(DMA_TRANSFER_TIMEOUT_US);
|
||||
dma_disable_tc_interrupt(DMAC_SLAVE_TX);
|
||||
|
||||
if (!(rv & TASK_EVENT_WAKE)) {
|
||||
CPRINTS("Slave timeout, resetting i2c");
|
||||
i2c_init_port(port);
|
||||
}
|
||||
}
|
||||
|
||||
dma_disable(DMAC_SLAVE_TX);
|
||||
STM32_I2C_CR2(port) &= ~(1 << 11);
|
||||
|
||||
enable_i2c_interrupt(port);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void i2c_send_response(struct host_cmd_handler_args *args)
|
||||
{
|
||||
const uint8_t *data = args->response;
|
||||
int size = args->response_size;
|
||||
uint8_t *out = host_buffer;
|
||||
int sum = 0, i;
|
||||
|
||||
*out++ = args->result;
|
||||
if (!i2c_old_response) {
|
||||
*out++ = size;
|
||||
sum = args->result + size;
|
||||
}
|
||||
for (i = 0; i < size; i++, data++, out++) {
|
||||
if (data != out)
|
||||
*out = *data;
|
||||
sum += *data;
|
||||
}
|
||||
*out++ = sum & 0xff;
|
||||
|
||||
/* send the answer to the AP */
|
||||
i2c_write_raw_slave(I2C2, host_buffer, out - host_buffer);
|
||||
}
|
||||
|
||||
/* Process the command in the i2c host buffer */
|
||||
static void i2c_process_command(void)
|
||||
{
|
||||
struct host_cmd_handler_args *args = &host_cmd_args;
|
||||
char *buff = host_buffer;
|
||||
|
||||
args->command = *buff;
|
||||
args->result = EC_RES_SUCCESS;
|
||||
if (args->command >= EC_CMD_VERSION0) {
|
||||
int csum, i;
|
||||
|
||||
/* Read version and data size */
|
||||
args->version = args->command - EC_CMD_VERSION0;
|
||||
args->command = buff[1];
|
||||
args->params_size = buff[2];
|
||||
|
||||
/* Verify checksum */
|
||||
for (csum = i = 0; i < args->params_size + 3; i++)
|
||||
csum += buff[i];
|
||||
if ((uint8_t)csum != buff[i])
|
||||
args->result = EC_RES_INVALID_CHECKSUM;
|
||||
|
||||
buff += 3;
|
||||
i2c_old_response = 0;
|
||||
} else {
|
||||
/*
|
||||
* Old style (version 1) command.
|
||||
*
|
||||
* TODO(crosbug.com/p/23765): Nothing sends these anymore,
|
||||
* since this was superseded by version 2 before snow launched.
|
||||
* This code should be safe to remove.
|
||||
*/
|
||||
args->version = 0;
|
||||
args->params_size = EC_PROTO2_MAX_PARAM_SIZE; /* unknown */
|
||||
buff++;
|
||||
i2c_old_response = 1;
|
||||
}
|
||||
|
||||
/* we have an available command : execute it */
|
||||
args->send_response = i2c_send_response;
|
||||
args->params = buff;
|
||||
/* skip room for error code, arglen */
|
||||
args->response = host_buffer + 2;
|
||||
args->response_max = EC_PROTO2_MAX_PARAM_SIZE;
|
||||
args->response_size = 0;
|
||||
|
||||
host_command_received(args);
|
||||
}
|
||||
|
||||
static void i2c_event_handler(int port)
|
||||
{
|
||||
/* save and clear status */
|
||||
i2c_sr1[port] = STM32_I2C_SR1(port);
|
||||
STM32_I2C_SR1(port) = 0;
|
||||
|
||||
/* Confirm that you are not in master mode */
|
||||
if (STM32_I2C_SR2(port) & (1 << 0)) {
|
||||
CPRINTS("slave ISR triggered in master mode, ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
/* transfer matched our slave address */
|
||||
if (i2c_sr1[port] & (1 << 1)) {
|
||||
/* If it's a receiver slave */
|
||||
if (!(STM32_I2C_SR2(port) & (1 << 2))) {
|
||||
dma_start_rx(dma_rx_option + port, sizeof(host_buffer),
|
||||
host_buffer);
|
||||
|
||||
STM32_I2C_CR2(port) |= (1 << 11);
|
||||
rx_pending = 1;
|
||||
}
|
||||
|
||||
/* cleared by reading SR1 followed by reading SR2 */
|
||||
STM32_I2C_SR1(port);
|
||||
STM32_I2C_SR2(port);
|
||||
} else if (i2c_sr1[port] & (1 << 4)) {
|
||||
/* If it's a receiver slave */
|
||||
if (!(STM32_I2C_SR2(port) & (1 << 2))) {
|
||||
/* Disable, and clear the DMA transfer complete flag */
|
||||
dma_disable(DMAC_SLAVE_RX);
|
||||
dma_clear_isr(DMAC_SLAVE_RX);
|
||||
|
||||
/* Turn off i2c's DMA flag */
|
||||
STM32_I2C_CR2(port) &= ~(1 << 11);
|
||||
}
|
||||
/* clear STOPF bit by reading SR1 and then writing CR1 */
|
||||
STM32_I2C_SR1(port);
|
||||
STM32_I2C_CR1(port) = STM32_I2C_CR1(port);
|
||||
}
|
||||
|
||||
/* TxE event */
|
||||
if (i2c_sr1[port] & (1 << 7)) {
|
||||
if (port == I2C2) { /* AP is waiting for EC response */
|
||||
if (rx_pending) {
|
||||
i2c_process_command();
|
||||
/* reset host buffer after end of transfer */
|
||||
rx_pending = 0;
|
||||
} else {
|
||||
/* spurious read : return dummy value */
|
||||
STM32_I2C_DR(port) = 0xec;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void i2c2_event_interrupt(void) { i2c_event_handler(I2C2); }
|
||||
DECLARE_IRQ(STM32_IRQ_I2C2_EV, i2c2_event_interrupt, 3);
|
||||
|
||||
static void i2c_error_handler(int port)
|
||||
{
|
||||
i2c_sr1[port] = STM32_I2C_SR1(port);
|
||||
|
||||
if (i2c_sr1[port] & 1 << 10) {
|
||||
/* ACK failed (NACK); expected when AP reads final byte.
|
||||
* Software must clear AF bit. */
|
||||
} else {
|
||||
CPRINTS("%s: I2C_SR1(%d): 0x%04x",
|
||||
__func__, port, i2c_sr1[port]);
|
||||
CPRINTS("%s: I2C_SR2(%d): 0x%04x",
|
||||
__func__, port, STM32_I2C_SR2(port));
|
||||
}
|
||||
|
||||
STM32_I2C_SR1(port) &= ~0xdf00;
|
||||
}
|
||||
void i2c2_error_interrupt(void) { i2c_error_handler(I2C2); }
|
||||
DECLARE_IRQ(STM32_IRQ_I2C2_ER, i2c2_error_interrupt, 2);
|
||||
|
||||
/* board-specific setup for post-I2C module init */
|
||||
void __board_i2c_post_init(int port)
|
||||
{
|
||||
}
|
||||
|
||||
void board_i2c_post_init(int port)
|
||||
__attribute__((weak, alias("__board_i2c_post_init")));
|
||||
|
||||
static void i2c_init_port(unsigned int port)
|
||||
{
|
||||
const int i2c_clock_bit[] = {21, 22};
|
||||
|
||||
if (!(STM32_RCC_APB1ENR & (1 << i2c_clock_bit[port]))) {
|
||||
/* Only unwedge the bus if the clock is off */
|
||||
if (i2c_claim(port) == EC_SUCCESS) {
|
||||
i2c_release(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 */
|
||||
STM32_I2C_CR1(port) = 0x8000;
|
||||
STM32_I2C_CR1(port) = 0x0000;
|
||||
|
||||
/* set clock configuration : standard mode (100kHz) */
|
||||
STM32_I2C_CCR(port) = I2C_CCR;
|
||||
|
||||
/* set slave address */
|
||||
if (port == I2C2)
|
||||
STM32_I2C_OAR1(port) = I2C_ADDRESS;
|
||||
|
||||
/* configuration : I2C mode / Periphal enabled, ACK enabled */
|
||||
STM32_I2C_CR1(port) = (1 << 10) | (1 << 0);
|
||||
/* error and event interrupts enabled / input clock is 16Mhz */
|
||||
STM32_I2C_CR2(port) = (1 << 9) | (1 << 8) | 0x10;
|
||||
|
||||
/* clear status */
|
||||
STM32_I2C_SR1(port) = 0;
|
||||
|
||||
board_i2c_post_init(port);
|
||||
}
|
||||
|
||||
static void i2c_init(void)
|
||||
{
|
||||
/*
|
||||
* TODO(crosbug.com/p/23763): Add config options to determine which
|
||||
* channels to init.
|
||||
*/
|
||||
i2c_init_port(I2C1);
|
||||
i2c_init_port(I2C2);
|
||||
|
||||
/* Enable event and error interrupts */
|
||||
task_enable_irq(STM32_IRQ_I2C2_EV);
|
||||
task_enable_irq(STM32_IRQ_I2C2_ER);
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, i2c_init, HOOK_PRIO_INIT_I2C);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* STM32 Host I2C */
|
||||
|
||||
#define SR1_SB (1 << 0) /* Start bit sent */
|
||||
#define SR1_ADDR (1 << 1) /* Address sent */
|
||||
#define SR1_BTF (1 << 2) /* Byte transfered */
|
||||
#define SR1_ADD10 (1 << 3) /* 10bit address sent */
|
||||
#define SR1_STOPF (1 << 4) /* Stop detected */
|
||||
#define SR1_RxNE (1 << 6) /* Data reg not empty */
|
||||
#define SR1_TxE (1 << 7) /* Data reg empty */
|
||||
#define SR1_BERR (1 << 8) /* Buss error */
|
||||
#define SR1_ARLO (1 << 9) /* Arbitration lost */
|
||||
#define SR1_AF (1 << 10) /* Ack failure */
|
||||
#define SR1_OVR (1 << 11) /* Overrun/underrun */
|
||||
#define SR1_PECERR (1 << 12) /* PEC err in reception */
|
||||
#define SR1_TIMEOUT (1 << 14) /* Timeout : 25ms */
|
||||
#define CR2_DMAEN (1 << 11) /* DMA enable */
|
||||
#define CR2_LAST (1 << 12) /* Next EOT is last EOT */
|
||||
|
||||
static inline void dump_i2c_reg(int port)
|
||||
{
|
||||
#ifdef CONFIG_I2C_DEBUG
|
||||
CPRINTF("CR1 : %016b\n", STM32_I2C_CR1(port));
|
||||
CPRINTF("CR2 : %016b\n", STM32_I2C_CR2(port));
|
||||
CPRINTF("SR2 : %016b\n", STM32_I2C_SR2(port));
|
||||
CPRINTF("SR1 : %016b\n", STM32_I2C_SR1(port));
|
||||
CPRINTF("OAR1 : %016b\n", STM32_I2C_OAR1(port));
|
||||
CPRINTF("OAR2 : %016b\n", STM32_I2C_OAR2(port));
|
||||
CPRINTF("DR : %016b\n", STM32_I2C_DR(port));
|
||||
CPRINTF("CCR : %016b\n", STM32_I2C_CCR(port));
|
||||
CPRINTF("TRISE: %016b\n", STM32_I2C_TRISE(port));
|
||||
#endif /* CONFIG_I2C_DEBUG */
|
||||
}
|
||||
|
||||
enum wait_t {
|
||||
WAIT_NONE,
|
||||
WAIT_MASTER_START,
|
||||
WAIT_ADDR_READY,
|
||||
WAIT_XMIT_TXE,
|
||||
WAIT_XMIT_FINAL_TXE,
|
||||
WAIT_XMIT_BTF,
|
||||
WAIT_XMIT_STOP,
|
||||
WAIT_RX_NE,
|
||||
WAIT_RX_NE_FINAL,
|
||||
WAIT_RX_NE_STOP,
|
||||
WAIT_RX_NE_STOP_SIZE2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Wait for a specific i2c event
|
||||
*
|
||||
* This function waits until the bit(s) corresponding to mask in
|
||||
* the specified port's I2C SR1 register is/are set. It may
|
||||
* return a timeout or success.
|
||||
*
|
||||
* @param port Port to wait on
|
||||
* @param mask A mask specifying which bits in SR1 to wait to be set
|
||||
* @param wait A wait code to be returned with the timeout error code if that
|
||||
* occurs, to help with debugging.
|
||||
* @return EC_SUCCESS, or EC_ERROR_TIMEOUT with the wait code OR'd onto the
|
||||
* bits 8-16 to indicate what it timed out waiting for.
|
||||
*/
|
||||
static int wait_status(int port, uint32_t mask, enum wait_t wait)
|
||||
{
|
||||
uint32_t r;
|
||||
timestamp_t t1, t2;
|
||||
|
||||
t1 = t2 = get_time();
|
||||
r = STM32_I2C_SR1(port);
|
||||
while (mask ? ((r & mask) != mask) : r) {
|
||||
t2 = get_time();
|
||||
|
||||
if (t2.val - t1.val > I2C_TX_TIMEOUT_MASTER)
|
||||
return EC_ERROR_TIMEOUT | (wait << 8);
|
||||
else if (t2.val - t1.val > 150)
|
||||
usleep(100);
|
||||
|
||||
r = STM32_I2C_SR1(port);
|
||||
}
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static inline uint32_t read_clear_status(int port)
|
||||
{
|
||||
uint32_t sr1, sr2;
|
||||
|
||||
sr1 = STM32_I2C_SR1(port);
|
||||
sr2 = STM32_I2C_SR2(port);
|
||||
return (sr2 << 16) | (sr1 & 0xffff);
|
||||
}
|
||||
|
||||
static int master_start(int port, int slave_addr)
|
||||
{
|
||||
int rv;
|
||||
|
||||
/* Change to master send mode, reset stop bit, send start bit */
|
||||
STM32_I2C_CR1(port) = (STM32_I2C_CR1(port) & ~(1 << 9)) | (1 << 8);
|
||||
/* Wait for start bit sent event */
|
||||
rv = wait_status(port, SR1_SB, WAIT_MASTER_START);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
/* Send address */
|
||||
STM32_I2C_DR(port) = slave_addr;
|
||||
/* Wait for addr ready */
|
||||
rv = wait_status(port, SR1_ADDR, WAIT_ADDR_READY);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
read_clear_status(port);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static void master_stop(int port)
|
||||
{
|
||||
STM32_I2C_CR1(port) |= (1 << 9);
|
||||
}
|
||||
|
||||
static int wait_until_stop_sent(int port)
|
||||
{
|
||||
timestamp_t deadline;
|
||||
timestamp_t slow_cutoff;
|
||||
uint8_t is_slow;
|
||||
|
||||
deadline = slow_cutoff = get_time();
|
||||
deadline.val += TIMEOUT_STOP_SENT_US;
|
||||
slow_cutoff.val += SLOW_STOP_SENT_US;
|
||||
|
||||
while (STM32_I2C_CR1(port) & (1 << 9)) {
|
||||
if (timestamp_expired(deadline, NULL)) {
|
||||
ccprintf("Stop event deadline passed:\ttask=%d"
|
||||
"\tCR1=%016b\n",
|
||||
(int)task_get_current(), STM32_I2C_CR1(port));
|
||||
return EC_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
if (is_slow) {
|
||||
/* If we haven't gotten a fast response, sleep */
|
||||
usleep(STOP_SENT_RETRY_US);
|
||||
} else {
|
||||
/* Check to see if this request is taking a while */
|
||||
if (timestamp_expired(slow_cutoff, NULL)) {
|
||||
ccprintf("Stop event taking a while: task=%d",
|
||||
(int)task_get_current());
|
||||
is_slow = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static void handle_i2c_error(int port, int rv)
|
||||
{
|
||||
timestamp_t t1, t2;
|
||||
uint32_t r;
|
||||
|
||||
/* We have not used the bus, just exit */
|
||||
if (rv == EC_ERROR_BUSY)
|
||||
return;
|
||||
|
||||
/* EC_ERROR_TIMEOUT may have a code specifying where the timeout was */
|
||||
if ((rv & 0xff) == EC_ERROR_TIMEOUT) {
|
||||
#ifdef CONFIG_I2C_DEBUG
|
||||
CPRINTS("Wait_status() timeout type: %d", (rv >> 8));
|
||||
#endif
|
||||
rv = EC_ERROR_TIMEOUT;
|
||||
}
|
||||
if (rv)
|
||||
dump_i2c_reg(port);
|
||||
|
||||
/* Clear rc_w0 bits */
|
||||
STM32_I2C_SR1(port) = 0;
|
||||
/* Clear seq read status bits */
|
||||
r = STM32_I2C_SR1(port);
|
||||
r = STM32_I2C_SR2(port);
|
||||
/* Clear busy state */
|
||||
t1 = get_time();
|
||||
|
||||
if (rv == EC_ERROR_TIMEOUT && (STM32_I2C_CR1(port) & (1 << 8))) {
|
||||
/*
|
||||
* If it failed while just trying to send the start bit then
|
||||
* something is wrong with the internal state of the i2c,
|
||||
* (Probably a stray pulse on the line got it out of sync with
|
||||
* the actual bytes) so reset it.
|
||||
*/
|
||||
CPRINTS("Unable to send START, resetting i2c");
|
||||
i2c_init_port(port);
|
||||
goto cr_cleanup;
|
||||
} else if (rv == EC_ERROR_TIMEOUT && !(r & 2)) {
|
||||
/*
|
||||
* If the BUSY bit is faulty, send a stop bit just to be sure.
|
||||
* It seems that this can be happen very briefly while sending
|
||||
* a 1. We've not actually seen this, but just to be safe.
|
||||
*/
|
||||
CPRINTS("Bad BUSY bit detected");
|
||||
master_stop(port);
|
||||
}
|
||||
|
||||
/* Try to send stop bits until the bus becomes idle */
|
||||
while (r & 2) {
|
||||
t2 = get_time();
|
||||
if (t2.val - t1.val > I2C_TX_TIMEOUT_MASTER) {
|
||||
dump_i2c_reg(port);
|
||||
/* Reset the i2c periph to get it back to slave mode */
|
||||
i2c_init_port(port);
|
||||
goto cr_cleanup;
|
||||
}
|
||||
/* Send stop */
|
||||
master_stop(port);
|
||||
usleep(1000);
|
||||
r = STM32_I2C_SR2(port);
|
||||
}
|
||||
|
||||
cr_cleanup:
|
||||
/*
|
||||
* Reset control register to the default state :
|
||||
* I2C mode / Periphal enabled, ACK enabled
|
||||
*/
|
||||
STM32_I2C_CR1(port) = (1 << 10) | (1 << 0);
|
||||
}
|
||||
|
||||
static int i2c_master_transmit(int port, int slave_addr, const uint8_t *data,
|
||||
int size, int stop)
|
||||
{
|
||||
int rv, rv_start;
|
||||
|
||||
disable_ack(port);
|
||||
|
||||
/* Configure DMA channel for TX to host */
|
||||
dma_prepare_tx(dma_tx_option + port, size, data);
|
||||
dma_enable_tc_interrupt(DMAC_MASTER_TX);
|
||||
|
||||
/* Start the DMA */
|
||||
dma_go(dma_get_channel(DMAC_MASTER_TX));
|
||||
|
||||
/* Configuring i2c2 to use DMA */
|
||||
STM32_I2C_CR2(port) |= CR2_DMAEN;
|
||||
|
||||
/* Initialise i2c communication by sending START and ADDR */
|
||||
rv_start = master_start(port, slave_addr);
|
||||
|
||||
/* If it started, wait for the transmission complete Interrupt */
|
||||
if (!rv_start)
|
||||
rv = task_wait_event(DMA_TRANSFER_TIMEOUT_US);
|
||||
|
||||
dma_disable(DMAC_MASTER_TX);
|
||||
dma_disable_tc_interrupt(DMAC_MASTER_TX);
|
||||
STM32_I2C_CR2(port) &= ~CR2_DMAEN;
|
||||
|
||||
if (rv_start)
|
||||
return rv_start;
|
||||
if (!(rv & TASK_EVENT_WAKE))
|
||||
return EC_ERROR_TIMEOUT;
|
||||
|
||||
rv = wait_status(port, SR1_BTF, WAIT_XMIT_BTF);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
if (stop) {
|
||||
master_stop(port);
|
||||
return wait_status(port, 0, WAIT_XMIT_STOP);
|
||||
}
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int i2c_master_receive(int port, int slave_addr, uint8_t *data,
|
||||
int size)
|
||||
{
|
||||
int rv, rv_start;
|
||||
|
||||
if (data == NULL || size < 1)
|
||||
return EC_ERROR_INVAL;
|
||||
|
||||
/* Master receive only supports DMA for payloads > 1 byte */
|
||||
if (size > 1) {
|
||||
enable_ack(port);
|
||||
dma_start_rx(dma_rx_option + port, size, data);
|
||||
|
||||
dma_enable_tc_interrupt(DMAC_MASTER_RX);
|
||||
|
||||
STM32_I2C_CR2(port) |= CR2_DMAEN;
|
||||
STM32_I2C_CR2(port) |= CR2_LAST;
|
||||
|
||||
rv_start = master_start(port, slave_addr | 1);
|
||||
if (!rv_start)
|
||||
rv = task_wait_event(DMA_TRANSFER_TIMEOUT_US);
|
||||
|
||||
dma_disable(DMAC_MASTER_RX);
|
||||
dma_disable_tc_interrupt(DMAC_MASTER_RX);
|
||||
STM32_I2C_CR2(port) &= ~CR2_DMAEN;
|
||||
disable_ack(port);
|
||||
|
||||
if (rv_start)
|
||||
return rv_start;
|
||||
if (!(rv & TASK_EVENT_WAKE))
|
||||
return EC_ERROR_TIMEOUT;
|
||||
|
||||
master_stop(port);
|
||||
} else {
|
||||
disable_ack(port);
|
||||
|
||||
rv = master_start(port, slave_addr | 1);
|
||||
if (rv)
|
||||
return rv;
|
||||
master_stop(port);
|
||||
rv = wait_status(port, SR1_RxNE, WAIT_RX_NE_STOP_SIZE2);
|
||||
if (rv)
|
||||
return rv;
|
||||
data[0] = STM32_I2C_DR(port);
|
||||
}
|
||||
|
||||
return wait_until_stop_sent(port);
|
||||
}
|
||||
|
||||
int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_bytes,
|
||||
uint8_t *in, int in_bytes, int flags)
|
||||
{
|
||||
int rv;
|
||||
|
||||
/* TODO(crosbug.com/p/23569): support start/stop flags */
|
||||
|
||||
ASSERT(out || !out_bytes);
|
||||
ASSERT(in || !in_bytes);
|
||||
|
||||
if (i2c_claim(port))
|
||||
return EC_ERROR_BUSY;
|
||||
|
||||
/* If the port appears to be wedged, then try to unwedge it. */
|
||||
if (!i2c_raw_get_scl(port) || !i2c_raw_get_sda(port)) {
|
||||
i2c_unwedge(port);
|
||||
|
||||
/* Reset the i2c port. */
|
||||
i2c_init_port(port);
|
||||
}
|
||||
|
||||
disable_i2c_interrupt(port);
|
||||
|
||||
rv = i2c_master_transmit(port, slave_addr, out, out_bytes,
|
||||
in_bytes ? 0 : 1);
|
||||
if (!rv && in_bytes)
|
||||
rv = i2c_master_receive(port, slave_addr, in, in_bytes);
|
||||
handle_i2c_error(port, rv);
|
||||
|
||||
enable_i2c_interrupt(port);
|
||||
|
||||
i2c_release(port);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int i2c_raw_get_scl(int port)
|
||||
{
|
||||
enum gpio_signal g;
|
||||
|
||||
if (get_scl_from_i2c_port(port, &g) == EC_SUCCESS)
|
||||
return gpio_get_level(g);
|
||||
|
||||
/* If no SCL pin defined for this port, then return 1 to appear idle. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int i2c_raw_get_sda(int port)
|
||||
{
|
||||
enum gpio_signal g;
|
||||
|
||||
if (get_sda_from_i2c_port(port, &g) == EC_SUCCESS)
|
||||
return gpio_get_level(g);
|
||||
|
||||
/* If no SDA pin defined for this port, then return 1 to appear idle. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int i2c_get_line_levels(int port)
|
||||
{
|
||||
return (i2c_raw_get_sda(port) ? I2C_LINE_SDA_HIGH : 0) |
|
||||
(i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0);
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
/* Settings to enable JTAG debugging */
|
||||
|
||||
#include "jtag.h"
|
||||
#include "registers.h"
|
||||
|
||||
void jtag_pre_init(void)
|
||||
{
|
||||
/* stop TIM1-4 and watchdogs when the JTAG stops the CPU */
|
||||
STM32_DBGMCU_CR |= 0x00003f00;
|
||||
}
|
||||
@@ -38,32 +38,11 @@ static void pwm_configure(enum pwm_channel ch)
|
||||
const struct gpio_info *gpio = gpio_list + pwm->pin;
|
||||
timer_ctlr_t *tim = (timer_ctlr_t *)(pwm->tim.base);
|
||||
volatile unsigned *ccmr = NULL;
|
||||
#ifdef CHIP_FAMILY_STM32F
|
||||
int mask = gpio->mask;
|
||||
volatile uint32_t *gpio_cr = NULL;
|
||||
uint32_t val;
|
||||
#endif
|
||||
|
||||
if (using_pwm[ch])
|
||||
return;
|
||||
|
||||
#if defined(CHIP_FAMILY_STM32F)
|
||||
if (mask < 0x100) {
|
||||
gpio_cr = &STM32_GPIO_CRL(gpio->port);
|
||||
} else {
|
||||
gpio_cr = &STM32_GPIO_CRH(gpio->port);
|
||||
mask >>= 8;
|
||||
}
|
||||
|
||||
/* Expand mask from 8-bit to 32-bit */
|
||||
mask = mask * mask;
|
||||
mask = mask * mask;
|
||||
|
||||
/* Set alternate function */
|
||||
val = *gpio_cr & ~(mask * 0xf);
|
||||
val |= mask * 0x9;
|
||||
*gpio_cr = val;
|
||||
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
|
||||
#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
|
||||
gpio_set_alternate_function(gpio->port, gpio->mask, pwm->gpio_alt_func);
|
||||
#else /* stm32l */
|
||||
gpio_set_alternate_function(gpio->port, gpio->mask,
|
||||
|
||||
@@ -72,8 +72,6 @@
|
||||
|
||||
#ifdef CHIP_VARIANT_STM32TS60
|
||||
#define STM32_IRQ_ADC_1 21
|
||||
#else
|
||||
#define STM32_IRQ_ADC_1 18 /* ADC1 and ADC2 interrupt on STM32F10x */
|
||||
#endif
|
||||
|
||||
#ifdef CHIP_VARIANT_STM32F373
|
||||
@@ -84,10 +82,10 @@
|
||||
#define STM32_IRQ_USB_LP 20
|
||||
#endif
|
||||
|
||||
#define STM32_IRQ_CAN_TX 19 /* STM32F10x/373 only */
|
||||
#define STM32_IRQ_USB_LP_CAN_RX 20 /* STM32F10x/373 only */
|
||||
#define STM32_IRQ_CAN_TX 19 /* STM32F373 only */
|
||||
#define STM32_IRQ_USB_LP_CAN_RX 20 /* STM32F373 only */
|
||||
#define STM32_IRQ_DAC 21
|
||||
#define STM32_IRQ_CAN_RX1 21 /* STM32F10x/373 only */
|
||||
#define STM32_IRQ_CAN_RX1 21 /* STM32F373 only */
|
||||
|
||||
#ifdef CHIP_VARIANT_STM32F373
|
||||
#define STM32_IRQ_COMP 64
|
||||
@@ -95,23 +93,18 @@
|
||||
#define STM32_IRQ_COMP 22
|
||||
#endif
|
||||
|
||||
#define STM32_IRQ_CAN_SCE 22 /* STM32F10x/373 only */
|
||||
#define STM32_IRQ_CAN_SCE 22 /* STM32F373 only */
|
||||
#define STM32_IRQ_ADC_2 22 /* STM32TS60 only */
|
||||
#define STM32_IRQ_EXTI9_5 23
|
||||
#define STM32_IRQ_LCD 24 /* STM32L15X only */
|
||||
#define STM32_IRQ_TIM1_BRK_TIM15 24 /* TIM15 interrupt on STM32F100 only */
|
||||
#define STM32_IRQ_PMAD 24 /* STM32TS60 only */
|
||||
#define STM32_IRQ_TIM15 24 /* STM32F373 only */
|
||||
#define STM32_IRQ_TIM9 25 /* STM32L15X only */
|
||||
#define STM32_IRQ_TIM1_UP_TIM16 25 /* TIM16 interrupt on STM32F100 only */
|
||||
#define STM32_IRQ_PMSE 25 /* STM32TS60 only */
|
||||
#define STM32_IRQ_TIM16 25 /* STM32F373 only */
|
||||
#define STM32_IRQ_TIM10 26 /* STM32L15X only */
|
||||
#define STM32_IRQ_TIM1_TRG_TIM17 26 /* STM32F100 only */
|
||||
#define STM32_IRQ_TIM1_TRG_COM 26 /* STM32F10x only */
|
||||
#define STM32_IRQ_TIM17 26 /* STM32F373 only */
|
||||
#define STM32_IRQ_TIM11 27 /* STM32L15X only */
|
||||
#define STM32_IRQ_TIM1_CC 27 /* STM32F100 and STM32F10x */
|
||||
#define STM32_IRQ_TIM18_DAC2 27 /* STM32F373 only */
|
||||
#define STM32_IRQ_TIM2 28
|
||||
#define STM32_IRQ_TIM3 29
|
||||
@@ -127,34 +120,23 @@
|
||||
#define STM32_IRQ_USART3 39
|
||||
#define STM32_IRQ_EXTI15_10 40
|
||||
#define STM32_IRQ_RTC_ALARM 41
|
||||
#define STM32_IRQ_USB_FS_WAKEUP 42 /* STM32L15X and STM32F10x */
|
||||
#define STM32_IRQ_CEC 42 /* STM32F100/373 only */
|
||||
#define STM32_IRQ_USB_FS_WAKEUP 42 /* STM32L15X */
|
||||
#define STM32_IRQ_CEC 42 /* STM32F373 only */
|
||||
#define STM32_IRQ_TIM6_BASIC 43 /* STM32L15X only */
|
||||
#define STM32_IRQ_TIM12 43 /* STM32F100/373 only */
|
||||
#define STM32_IRQ_TIM8_BRK 43 /* STM32F10x only */
|
||||
#define STM32_IRQ_TIM12 43 /* STM32F373 only */
|
||||
#define STM32_IRQ_TIM7_BASIC 44 /* STM32L15X only */
|
||||
#define STM32_IRQ_TIM13 44 /* STM32F100/373 only */
|
||||
#define STM32_IRQ_TIM8_UP 44 /* STM32F10x only */
|
||||
#define STM32_IRQ_TIM14 45 /* STM32F100/373 only */
|
||||
#define STM32_IRQ_TIM8_TRG_COM 45 /* STM32F10x only */
|
||||
#define STM32_IRQ_TIM8_CC 46 /* STM32F10x only */
|
||||
#define STM32_IRQ_ADC3 47 /* STM32F10x only */
|
||||
#define STM32_IRQ_FSMC 48 /* STM32F100 and STM32F10x */
|
||||
#define STM32_IRQ_SDIO 49 /* STM32F10x only */
|
||||
#define STM32_IRQ_TIM5 50 /* STM32F100, STM32F10x, and STM32F373 */
|
||||
#define STM32_IRQ_SPI3 51 /* STM32F100, STM32F10x, and STM32F373 */
|
||||
#define STM32_IRQ_UART4 52 /* STM32F100 and STM32F10x */
|
||||
#define STM32_IRQ_UART5 53 /* STM32F100 and STM32F10x */
|
||||
#define STM32_IRQ_TIM6_DAC 54 /* STM32F100 and STM32F373 */
|
||||
#define STM32_IRQ_TIM6 54 /* STM32F10x only */
|
||||
#define STM32_IRQ_TIM7 55 /* STM32F100, STM32F10x, and STM32F373 */
|
||||
#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F100, STM32F10x, and STM32F373 */
|
||||
#define STM32_IRQ_DMA2_CHANNEL2 57 /* STM32F100, STM32F10x, and STM32F373 */
|
||||
#define STM32_IRQ_DMA2_CHANNEL3 58 /* STM32F100, STM32F10x, and STM32F373 */
|
||||
#define STM32_IRQ_DMA2_CHANNEL4_5 59 /* STM32F100 and STM32F10x */
|
||||
#define STM32_IRQ_TIM13 44 /* STM32F373 only */
|
||||
#define STM32_IRQ_TIM14 45 /* STM32F373 only */
|
||||
#define STM32_IRQ_TIM5 50 /* STM32F373 */
|
||||
#define STM32_IRQ_SPI3 51 /* STM32F373 */
|
||||
#define STM32_IRQ_TIM6_DAC 54 /* STM32F373 */
|
||||
#define STM32_IRQ_TIM7 55 /* STM32F373 */
|
||||
#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F373 */
|
||||
#define STM32_IRQ_DMA2_CHANNEL2 57 /* STM32F373 */
|
||||
#define STM32_IRQ_DMA2_CHANNEL3 58 /* STM32F373 */
|
||||
#define STM32_IRQ_DMA2_CHANNEL4 59 /* STM32F373 only */
|
||||
/* if MISC_REMAP bits are set */
|
||||
#define STM32_IRQ_DMA2_CHANNEL5 60 /* STM32F100 and STM32F373 */
|
||||
#define STM32_IRQ_DMA2_CHANNEL5 60 /* STM32F373 */
|
||||
#define STM32_IRQ_SDADC1 61 /* STM32F373 only */
|
||||
#define STM32_IRQ_SDADC2 62 /* STM32F373 only */
|
||||
#define STM32_IRQ_SDADC3 63 /* STM32F373 only */
|
||||
@@ -239,29 +221,24 @@
|
||||
#define STM32_IRQ_USART(n) CONCAT2(STM32_IRQ_USART, n)
|
||||
|
||||
/* --- TIMERS --- */
|
||||
#define STM32_TIM1_BASE 0x40012c00 /* STM32F100 and STM32F10x */
|
||||
#define STM32_TIM1_BASE 0x40012c00 /* STM32F373 */
|
||||
#define STM32_TIM2_BASE 0x40000000
|
||||
#define STM32_TIM3_BASE 0x40000400
|
||||
#define STM32_TIM4_BASE 0x40000800
|
||||
#define STM32_TIM5_BASE 0x40000c00 /* STM32F1xx and STM32F373 */
|
||||
#define STM32_TIM5_BASE 0x40000c00 /* STM32F373 */
|
||||
#define STM32_TIM6_BASE 0x40001000
|
||||
#define STM32_TIM7_BASE 0x40001400
|
||||
#define STM32_TIM8_BASE 0x40013400 /* STM32F10x only */
|
||||
#if defined(CHIP_FAMILY_STM32L)
|
||||
#define STM32_TIM9_BASE 0x40010800 /* STM32L15X only */
|
||||
#define STM32_TIM10_BASE 0x40010C00 /* STM32L15X only */
|
||||
#define STM32_TIM11_BASE 0x40011000 /* STM32L15X only */
|
||||
#elif defined(CHIP_VARIANT_STM32F10X)
|
||||
#define STM32_TIM9_BASE 0x40014C00 /* STM32F10x only */
|
||||
#define STM32_TIM10_BASE 0x40015000 /* STM32F10x only */
|
||||
#define STM32_TIM11_BASE 0x40015400 /* STM32F10x only */
|
||||
#endif /* TIM9-11 */
|
||||
#define STM32_TIM12_BASE 0x40001800 /* STM32F1xx and STM32F373 */
|
||||
#define STM32_TIM13_BASE 0x40001c00 /* STM32F1xx and STM32F373 */
|
||||
#define STM32_TIM14_BASE 0x40002000 /* STM32F1xx and STM32F373 */
|
||||
#define STM32_TIM15_BASE 0x40014000 /* STM32F100 only */
|
||||
#define STM32_TIM16_BASE 0x40014400 /* STM32F100 only */
|
||||
#define STM32_TIM17_BASE 0x40014800 /* STM32F100 only */
|
||||
#define STM32_TIM12_BASE 0x40001800 /* STM32F373 */
|
||||
#define STM32_TIM13_BASE 0x40001c00 /* STM32F373 */
|
||||
#define STM32_TIM14_BASE 0x40002000 /* STM32F373 */
|
||||
#define STM32_TIM15_BASE 0x40014000
|
||||
#define STM32_TIM16_BASE 0x40014400
|
||||
#define STM32_TIM17_BASE 0x40014800
|
||||
#define STM32_TIM18_BASE 0x40009c00 /* STM32F373 only */
|
||||
#define STM32_TIM19_BASE 0x40015c00 /* STM32F373 only */
|
||||
|
||||
@@ -403,31 +380,6 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
|
||||
#define GPIO_ALT_F4 0x4
|
||||
#define GPIO_ALT_F5 0x5
|
||||
|
||||
#elif defined(CHIP_FAMILY_STM32F)
|
||||
#define STM32_GPIOA_BASE 0x40010800
|
||||
#define STM32_GPIOB_BASE 0x40010c00
|
||||
#define STM32_GPIOC_BASE 0x40011000
|
||||
#define STM32_GPIOD_BASE 0x40011400
|
||||
#define STM32_GPIOE_BASE 0x40011800
|
||||
#define STM32_GPIOF_BASE 0x4001c000
|
||||
#define STM32_GPIOG_BASE 0x40012000
|
||||
#define STM32_GPIOH_BASE 0x40012400 /* STM32TS only */
|
||||
#define STM32_GPIOI_BASE 0x40012800 /* STM32TS only */
|
||||
|
||||
#define STM32_GPIO_CRL(b) REG32((b) + 0x00)
|
||||
#define STM32_GPIO_CRH(b) REG32((b) + 0x04)
|
||||
#define STM32_GPIO_IDR(b) REG16((b) + 0x08)
|
||||
#define STM32_GPIO_ODR(b) REG16((b) + 0x0c)
|
||||
#define STM32_GPIO_BSRR(b) REG32((b) + 0x10)
|
||||
#define STM32_GPIO_BRR(b) REG32((b) + 0x14)
|
||||
#define STM32_GPIO_LCKR(b) REG32((b) + 0x18)
|
||||
|
||||
#define STM32_AFIO_BASE 0x40010000
|
||||
#define STM32_AFIO_EXTICR(n) REG32(STM32_AFIO_BASE + 8 + 4 * (n))
|
||||
#define STM32_GPIO_AFIO_EVCR REG32(STM32_AFIO_BASE + 0x00)
|
||||
#define STM32_GPIO_AFIO_MAPR REG32(STM32_AFIO_BASE + 0x04)
|
||||
#define STM32_GPIO_AFIO_MAPR2 REG32(STM32_AFIO_BASE + 0x1c)
|
||||
|
||||
#else
|
||||
#error Unsupported chip variant
|
||||
#endif
|
||||
@@ -531,9 +483,7 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
|
||||
#define STM32_PWR_CR REG32(STM32_PWR_BASE + 0x00)
|
||||
#define STM32_PWR_CR_LPSDSR (1 << 0)
|
||||
#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x04)
|
||||
#if defined(CHIP_FAMILY_STM32F)
|
||||
#define STM32_PWR_CSR_EWUP (1 << 8)
|
||||
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
|
||||
#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
|
||||
#define STM32_PWR_CSR_EWUP1 (1 << 8)
|
||||
#define STM32_PWR_CSR_EWUP2 (1 << 9)
|
||||
#define STM32_PWR_CSR_EWUP3 (1 << 10)
|
||||
@@ -594,8 +544,7 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
|
||||
#define STM32_SYSCFG_PMC REG32(STM32_SYSCFG_BASE + 0x04)
|
||||
#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n))
|
||||
|
||||
#elif defined(CHIP_FAMILY_STM32F) || defined(CHIP_FAMILY_STM32F0) || \
|
||||
defined(CHIP_FAMILY_STM32F3)
|
||||
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
|
||||
#define STM32_RCC_BASE 0x40021000
|
||||
|
||||
#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00)
|
||||
@@ -608,7 +557,7 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
|
||||
#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x1c)
|
||||
#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x20)
|
||||
#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x24)
|
||||
/* STM32F100 and STM32F373 */
|
||||
/* STM32F373 */
|
||||
#define STM32_RCC_CFGR2 REG32(STM32_RCC_BASE + 0x2c)
|
||||
/* STM32F0XX and STM32F373 */
|
||||
#define STM32_RCC_CFGR3 REG32(STM32_RCC_BASE + 0x30)
|
||||
@@ -716,36 +665,6 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
|
||||
#define STM32_BKP_ENTRIES 20
|
||||
#endif
|
||||
|
||||
#elif defined(CHIP_FAMILY_STM32F)
|
||||
#define STM32_RTC_CRH REG32(STM32_RTC_BASE + 0x00)
|
||||
#define STM32_RTC_CRL REG32(STM32_RTC_BASE + 0x04)
|
||||
#define STM32_RTC_PRLH REG32(STM32_RTC_BASE + 0x08)
|
||||
#define STM32_RTC_PRLL REG16(STM32_RTC_BASE + 0x0c)
|
||||
#define STM32_RTC_DIVH REG16(STM32_RTC_BASE + 0x10)
|
||||
#define STM32_RTC_DIVL REG16(STM32_RTC_BASE + 0x14)
|
||||
#define STM32_RTC_CNTH REG16(STM32_RTC_BASE + 0x18)
|
||||
#define STM32_RTC_CNTL REG16(STM32_RTC_BASE + 0x1c)
|
||||
#define STM32_RTC_ALRH REG16(STM32_RTC_BASE + 0x20)
|
||||
#define STM32_RTC_ALRL REG16(STM32_RTC_BASE + 0x24)
|
||||
|
||||
/* --- Backup Registers --- */
|
||||
#define STM32_BKP_BASE 0x40006c00
|
||||
|
||||
#if defined(CHIP_VARIANT_STM32F10X)
|
||||
#define STM32_BKP_ENTRIES 42
|
||||
#define STM32_BKP_DATA(n) \
|
||||
REG16(STM32_BKP_BASE + (n < 11 ? 0x4 : 0x40) + 4 * (n))
|
||||
#else
|
||||
#define STM32_BKP_ENTRIES 10
|
||||
#define STM32_BKP_DATA(n) REG16(STM32_BKP_BASE + 0x4 + 4 * (n))
|
||||
#endif
|
||||
|
||||
#define STM32_BKP_RTCCR REG16(STM32_BKP_BASE + 0x2c)
|
||||
#define STM32_BKP_CR REG16(STM32_BKP_BASE + 0x30)
|
||||
#define STM32_BKP_CSR REG16(STM32_BKP_BASE + 0x34)
|
||||
|
||||
#define STM32_RTC_BACKUP(n) STM32_BKP_DATA(n)
|
||||
|
||||
#else
|
||||
#error Unsupported chip variant
|
||||
#endif
|
||||
@@ -753,7 +672,7 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
|
||||
/* --- SPI --- */
|
||||
#define STM32_SPI1_BASE 0x40013000
|
||||
#define STM32_SPI2_BASE 0x40003800
|
||||
#define STM32_SPI3_BASE 0x40003c00 /* STM32F100 and STM32F373 */
|
||||
#define STM32_SPI3_BASE 0x40003c00 /* STM32F373 */
|
||||
|
||||
#define STM32_SPI1_PORT 0
|
||||
#define STM32_SPI2_PORT 1
|
||||
@@ -771,8 +690,8 @@ struct stm32_spi_regs {
|
||||
unsigned crcpr;
|
||||
unsigned rxcrcr;
|
||||
unsigned txcrcr;
|
||||
unsigned i2scfgr; /* STM32F10x and STM32L only */
|
||||
unsigned i2spr; /* STM32F10x and STM32L only */
|
||||
unsigned i2scfgr; /* STM32L only */
|
||||
unsigned i2spr; /* STM32L only */
|
||||
};
|
||||
/* Must be volatile, or compiler optimizes out repeated accesses */
|
||||
typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
|
||||
@@ -861,8 +780,7 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
|
||||
#define STM32_OPTB_WRP3L 0x18
|
||||
#define STM32_OPTB_WRP3H 0x1c
|
||||
|
||||
#elif defined(CHIP_FAMILY_STM32F) || defined(CHIP_FAMILY_STM32F0) || \
|
||||
defined(CHIP_FAMILY_STM32F3)
|
||||
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
|
||||
#define STM32_FLASH_REGS_BASE 0x40022000
|
||||
|
||||
#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00)
|
||||
@@ -915,11 +833,9 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
|
||||
#else /* !CHIP_VARIANT_STM32TS60 */
|
||||
#define STM32_ADC1_BASE 0x40012400
|
||||
#define STM32_ADC_BASE 0x40012700 /* STM32L15X only */
|
||||
#define STM32_ADC2_BASE 0x40012800 /* STM32F10x only */
|
||||
#define STM32_ADC3_BASE 0x40013C00 /* STM32F10x only */
|
||||
#endif
|
||||
|
||||
#if defined(CHIP_VARIANT_STM32F100) || defined(CHIP_VARIANT_STM32F373)
|
||||
#if defined(CHIP_VARIANT_STM32F373)
|
||||
#define STM32_ADC_SR REG32(STM32_ADC1_BASE + 0x00)
|
||||
#define STM32_ADC_CR1 REG32(STM32_ADC1_BASE + 0x04)
|
||||
#define STM32_ADC_CR2 REG32(STM32_ADC1_BASE + 0x08)
|
||||
@@ -1183,8 +1099,7 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
|
||||
|
||||
#if defined(CHIP_FAMILY_STM32L)
|
||||
#define STM32_DMA1_BASE 0x40026000
|
||||
#elif defined(CHIP_FAMILY_STM32F) || defined(CHIP_FAMILY_STM32F0) || \
|
||||
defined(CHIP_FAMILY_STM32F3)
|
||||
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
|
||||
#define STM32_DMA1_BASE 0x40020000
|
||||
#else
|
||||
#error Unsupported chip variant
|
||||
@@ -1236,7 +1151,7 @@ enum dma_channel {
|
||||
STM32_DMAC_SPI2_TX = STM32_DMAC_CH7,
|
||||
#endif
|
||||
|
||||
/* Only DMA1 (with 7 channels) is present on STM32F100 and STM32L151x */
|
||||
/* Only DMA1 (with 7 channels) is present on STM32L151x */
|
||||
STM32_DMAC_COUNT = 7,
|
||||
|
||||
#else /* stm32f03x and stm32f05x have only 5 channels */
|
||||
@@ -1386,14 +1301,8 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t;
|
||||
/* --- MISC --- */
|
||||
|
||||
#define STM32_UNIQUE_ID 0x1ffff7ac
|
||||
#define STM32_CEC_BASE 0x40007800 /* STM32F100 and STM32F373 */
|
||||
#define STM32_CEC_BASE 0x40007800 /* STM32F373 */
|
||||
#define STM32_LCD_BASE 0x40002400
|
||||
#define STM32_FSMC_BASE 0xA0000000 /* STM32F10x only */
|
||||
#define STM32_USB_OTG_FS_BASE 0x50000000 /* STM32F10x only */
|
||||
#define STM32_ETHERNET_BASE 0x40028000 /* STM32F10x only */
|
||||
#define STM32_SDIO_BASE 0x40018000 /* STM32F10x only */
|
||||
#define STM32_BXCAN1_BASE 0x40006400 /* STM32F10x only */
|
||||
#define STM32_BXCAN2_BASE 0x40006800 /* STM32F10x only */
|
||||
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
|
||||
|
||||
@@ -195,8 +195,7 @@ void system_pre_init(void)
|
||||
/* Enable RTC and use LSI as clock source */
|
||||
STM32_RCC_CSR = (STM32_RCC_CSR & ~0x00C30000) | 0x00420000;
|
||||
}
|
||||
#elif defined(CHIP_FAMILY_STM32F) || defined(CHIP_FAMILY_STM32F0) || \
|
||||
defined(CHIP_FAMILY_STM32F3)
|
||||
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
|
||||
if ((STM32_RCC_BDCR & 0x00018300) != 0x00008200) {
|
||||
/* the RTC settings are bad, we need to reset it */
|
||||
STM32_RCC_BDCR |= 0x00010000;
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#include "usart-stm32f.h"
|
||||
|
||||
#include "clock.h"
|
||||
#include "common.h"
|
||||
#include "hooks.h"
|
||||
#include "registers.h"
|
||||
#include "task.h"
|
||||
#include "util.h"
|
||||
|
||||
/*
|
||||
* This configs array stores the currently active usart_config structure for
|
||||
* each USART, an entry will be NULL if no USART driver is initialized for the
|
||||
* corresponding hardware instance.
|
||||
*/
|
||||
static struct usart_config const *configs[STM32_USARTS_MAX];
|
||||
|
||||
static void usart_variant_enable(struct usart_config const *config)
|
||||
{
|
||||
/*
|
||||
* Make sure we register this config before enabling the HW.
|
||||
* If we did it the other way around the FREQ_CHANGE hook could be
|
||||
* called before we update the configs array and we would miss the
|
||||
* clock frequency change event, leaving our baud rate divisor wrong.
|
||||
*/
|
||||
configs[config->hw->index] = config;
|
||||
|
||||
usart_set_baud_f(config, clock_get_freq());
|
||||
|
||||
task_enable_irq(config->hw->irq);
|
||||
}
|
||||
|
||||
static void usart_variant_disable(struct usart_config const *config)
|
||||
{
|
||||
task_disable_irq(config->hw->irq);
|
||||
|
||||
configs[config->hw->index] = NULL;
|
||||
}
|
||||
|
||||
static usart_hw_ops const struct usart_variant_hw_ops = {
|
||||
.enable = usart_variant_enable,
|
||||
.disable = usart_variant_disable,
|
||||
};
|
||||
|
||||
static void freq_change(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(configs); ++i)
|
||||
if (configs[i])
|
||||
usart_set_baud_f(configs[i], clock_get_freq());
|
||||
}
|
||||
|
||||
DECLARE_HOOK(HOOK_FREQ_CHANGE, freq_change, HOOK_PRIO_DEFAULT);
|
||||
|
||||
/*
|
||||
* USART interrupt bindings. These functions can not be defined as static or
|
||||
* they will be removed by the linker because of the way that DECLARE_IRQ works.
|
||||
*/
|
||||
#if defined(CONFIG_STREAM_USART1)
|
||||
struct usart_hw_config const usart1_hw = {
|
||||
.index = 0,
|
||||
.base = STM32_USART1_BASE,
|
||||
.irq = STM32_IRQ_USART1,
|
||||
.clock_register = &STM32_RCC_APB2ENR,
|
||||
.clock_enable = STM32_RCC_PB2_USART1,
|
||||
.ops = &usart_variant_hw_ops,
|
||||
};
|
||||
|
||||
void usart1_interrupt(void)
|
||||
{
|
||||
usart_interrupt(configs[0]);
|
||||
}
|
||||
|
||||
DECLARE_IRQ(STM32_IRQ_USART1, usart1_interrupt, 2);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_STREAM_USART2)
|
||||
struct usart_hw_config const usart2_hw = {
|
||||
.index = 1,
|
||||
.base = STM32_USART2_BASE,
|
||||
.irq = STM32_IRQ_USART2,
|
||||
.clock_register = &STM32_RCC_APB1ENR,
|
||||
.clock_enable = STM32_RCC_PB1_USART2,
|
||||
.ops = &usart_variant_hw_ops,
|
||||
};
|
||||
|
||||
void usart2_interrupt(void)
|
||||
{
|
||||
usart_interrupt(configs[1]);
|
||||
}
|
||||
|
||||
DECLARE_IRQ(STM32_IRQ_USART2, usart2_interrupt, 2);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_STREAM_USART3)
|
||||
struct usart_hw_config const usart3_hw = {
|
||||
.index = 2,
|
||||
.base = STM32_USART3_BASE,
|
||||
.irq = STM32_IRQ_USART3_4,
|
||||
.clock_register = &STM32_RCC_APB1ENR,
|
||||
.clock_enable = STM32_RCC_PB1_USART3,
|
||||
.ops = &usart_variant_hw_ops,
|
||||
};
|
||||
|
||||
void usart3_interrupt(void)
|
||||
{
|
||||
usart_interrupt(configs[2]);
|
||||
}
|
||||
|
||||
DECLARE_IRQ(STM32_IRQ_USART3, usart3_interrupt, 2);
|
||||
#endif
|
||||
@@ -1,20 +0,0 @@
|
||||
/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#ifndef __CROS_EC_USART_STM32F_H
|
||||
#define __CROS_EC_USART_STM32F_H
|
||||
|
||||
#include "usart.h"
|
||||
|
||||
#define STM32_USARTS_MAX 3
|
||||
|
||||
/*
|
||||
* The STM32F series can have as many as three UARTS. These are the HW configs
|
||||
* for those UARTS. They can be used to initialize STM32 generic UART configs.
|
||||
*/
|
||||
extern struct usart_hw_config const usart1_hw;
|
||||
extern struct usart_hw_config const usart2_hw;
|
||||
extern struct usart_hw_config const usart3_hw;
|
||||
|
||||
#endif /* __CROS_EC_USART_STM32F_H */
|
||||
11
common/i2c.c
11
common/i2c.c
@@ -711,19 +711,8 @@ static void scan_bus(int port, const char *desc)
|
||||
watchdog_reload(); /* Otherwise a full scan trips watchdog */
|
||||
ccputs(".");
|
||||
|
||||
#ifdef CHIP_FAMILY_STM32F
|
||||
/*
|
||||
* TODO(crosbug.com/p/23569): The i2c_xfer() implementation on
|
||||
* STM32F can't read a byte without writing one first. So
|
||||
* write a byte and hope nothing bad happens. Remove this
|
||||
* workaround when STM32F is fixed.
|
||||
*/
|
||||
tmp = 0;
|
||||
if (!i2c_xfer(port, a, &tmp, 1, &tmp, 1, I2C_XFER_SINGLE))
|
||||
#else
|
||||
/* Do a single read */
|
||||
if (!i2c_xfer(port, a, NULL, 0, &tmp, 1, I2C_XFER_SINGLE))
|
||||
#endif
|
||||
ccprintf("\n 0x%02x", a);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user