drivers: wdt: Migrate esp32 wdt driver api to new wdt interface

patch migrates the esp32 wdt driver to new wdt interfaces

Signed-off-by: Savinay Dharmappa <savinay.dharmappa@intel.com>
This commit is contained in:
Savinay Dharmappa 2018-09-10 16:37:57 +05:30 committed by Anas Nashif
commit 7b6776a36a
2 changed files with 60 additions and 59 deletions

View file

@ -14,7 +14,10 @@
#include <device.h> #include <device.h>
struct wdt_esp32_data { struct wdt_esp32_data {
struct wdt_config config; u32_t timeout;
enum wdt_mode mode;
wdt_callback_t callback;
struct device *dev;
}; };
static struct wdt_esp32_data shared_data; static struct wdt_esp32_data shared_data;
@ -37,12 +40,10 @@ static inline void wdt_esp32_unseal(void)
*reg = TIMG_WDT_WKEY_VALUE; *reg = TIMG_WDT_WKEY_VALUE;
} }
static void wdt_esp32_enable(struct device *dev) static void wdt_esp32_enable(void)
{ {
volatile u32_t *reg = (u32_t *)TIMG_WDTCONFIG0_REG(1); volatile u32_t *reg = (u32_t *)TIMG_WDTCONFIG0_REG(1);
ARG_UNUSED(dev);
wdt_esp32_unseal(); wdt_esp32_unseal();
*reg |= BIT(TIMG_WDT_EN_S); *reg |= BIT(TIMG_WDT_EN_S);
wdt_esp32_seal(); wdt_esp32_seal();
@ -64,44 +65,14 @@ static int wdt_esp32_disable(struct device *dev)
static void adjust_timeout(u32_t timeout) static void adjust_timeout(u32_t timeout)
{ {
volatile u32_t *reg; volatile u32_t *reg;
enum wdt_clock_timeout_cycles cycles = u32_t ticks = timeout;
(enum wdt_clock_timeout_cycles)timeout;
u32_t ticks;
/* The watchdog API in Zephyr was modeled after the QMSI drivers,
* and those were modeled after the Quark MCUs. The possible
* values of enum wdt_clock_timeout_cycles maps 1:1 to what the
* Quark D2000 expects. At 32MHz, the timeout value in ms is given
* by the following formula, according to the D2000 datasheet:
*
* 2^(cycles + 11)
* timeout_ms = ---------------
* 1000
*
* (e.g. 2.048ms for 2^16 cycles, or the WDT_2_16_CYCLES value.)
*
* While this is sort of backwards (this should be given units of
* time and converted to what the hardware expects), try to map this
* value to what the ESP32 expects. Use the same timeout value for
* stages 0 and 1, regardless of the configuration mode, in order to
* simplify things.
*/
/* MWDT ticks every 12.5ns. Set the prescaler to 40000, so the
* counter for each watchdog stage is decremented every 0.5ms.
*/
reg = (u32_t *)TIMG_WDTCONFIG1_REG(1); reg = (u32_t *)TIMG_WDTCONFIG1_REG(1);
/* MWDT ticks every 12.5ns. Set the prescaler to 40000, so the
* counter for each watchdog stage is decremented every 0.5ms.
*/
*reg = 40000; *reg = 40000;
ticks = 1<<(cycles + 2);
/* Correct the value: this is an integer-only approximation of
* 0.114074 * exp(0.67822 * cycles)
* Which calculates the difference in ticks from the D2000 values to
* the value calculated by the previous expression.
*/
ticks += (1<<cycles) / 10;
reg = (u32_t *)TIMG_WDTCONFIG2_REG(1); reg = (u32_t *)TIMG_WDTCONFIG2_REG(1);
*reg = ticks; *reg = ticks;
@ -111,7 +82,7 @@ static void adjust_timeout(u32_t timeout)
static void wdt_esp32_isr(void *param); static void wdt_esp32_isr(void *param);
static void wdt_esp32_reload(struct device *dev) static int wdt_esp32_reload(struct device *dev, int channel_id)
{ {
volatile u32_t *reg = (u32_t *)TIMG_WDTFEED_REG(1); volatile u32_t *reg = (u32_t *)TIMG_WDTFEED_REG(1);
@ -120,6 +91,8 @@ static void wdt_esp32_reload(struct device *dev)
wdt_esp32_unseal(); wdt_esp32_unseal();
*reg = 0xABAD1DEA; /* Writing any value to WDTFEED will reload it. */ *reg = 0xABAD1DEA; /* Writing any value to WDTFEED will reload it. */
wdt_esp32_seal(); wdt_esp32_seal();
return 0;
} }
static void set_interrupt_enabled(bool setting) static void set_interrupt_enabled(bool setting)
@ -142,13 +115,13 @@ static void set_interrupt_enabled(bool setting)
} }
} }
static int wdt_esp32_set_config(struct device *dev, struct wdt_config *config) static int wdt_esp32_set_config(struct device *dev, u8_t options)
{ {
struct wdt_esp32_data *data = dev->driver_data; struct wdt_esp32_data *data = dev->driver_data;
volatile u32_t *reg = (u32_t *)TIMG_WDTCONFIG0_REG(1); volatile u32_t *reg = (u32_t *)TIMG_WDTCONFIG0_REG(1);
u32_t v; u32_t v;
if (!config) { if (!data) {
return -EINVAL; return -EINVAL;
} }
@ -162,14 +135,14 @@ static int wdt_esp32_set_config(struct device *dev, struct wdt_config *config)
v |= 7<<TIMG_WDT_SYS_RESET_LENGTH_S; v |= 7<<TIMG_WDT_SYS_RESET_LENGTH_S;
v |= 7<<TIMG_WDT_CPU_RESET_LENGTH_S; v |= 7<<TIMG_WDT_CPU_RESET_LENGTH_S;
if (config->mode == WDT_MODE_RESET) { if (data->mode == WDT_MODE_RESET) {
/* Warm reset on timeout */ /* Warm reset on timeout */
v |= TIMG_WDT_STG_SEL_RESET_SYSTEM<<TIMG_WDT_STG0_S; v |= TIMG_WDT_STG_SEL_RESET_SYSTEM<<TIMG_WDT_STG0_S;
v |= TIMG_WDT_STG_SEL_OFF<<TIMG_WDT_STG1_S; v |= TIMG_WDT_STG_SEL_OFF<<TIMG_WDT_STG1_S;
/* Disable interrupts for this mode. */ /* Disable interrupts for this mode. */
v &= ~(TIMG_WDT_LEVEL_INT_EN | TIMG_WDT_EDGE_INT_EN); v &= ~(TIMG_WDT_LEVEL_INT_EN | TIMG_WDT_EDGE_INT_EN);
} else if (config->mode == WDT_MODE_INTERRUPT_RESET) { } else if (data->mode == WDT_MODE_INTERRUPT_RESET) {
/* Interrupt first, and warm reset if not reloaded */ /* Interrupt first, and warm reset if not reloaded */
v |= TIMG_WDT_STG_SEL_INT<<TIMG_WDT_STG0_S; v |= TIMG_WDT_STG_SEL_INT<<TIMG_WDT_STG0_S;
v |= TIMG_WDT_STG_SEL_RESET_SYSTEM<<TIMG_WDT_STG1_S; v |= TIMG_WDT_STG_SEL_RESET_SYSTEM<<TIMG_WDT_STG1_S;
@ -183,29 +156,44 @@ static int wdt_esp32_set_config(struct device *dev, struct wdt_config *config)
wdt_esp32_unseal(); wdt_esp32_unseal();
*reg = v; *reg = v;
adjust_timeout(config->timeout & WDT_TIMEOUT_MASK); adjust_timeout(data->timeout);
set_interrupt_enabled(config->mode == WDT_MODE_INTERRUPT_RESET); set_interrupt_enabled(data->mode == WDT_MODE_INTERRUPT_RESET);
wdt_esp32_seal(); wdt_esp32_seal();
wdt_esp32_reload(dev); wdt_esp32_reload(dev, 0);
memcpy(&data->config, config, sizeof(*config));
return 0; return 0;
} }
static void wdt_esp32_get_config(struct device *dev, struct wdt_config *config) static int wdt_esp32_install_timeout(struct device *dev,
const struct wdt_timeout_cfg *cfg)
{ {
struct wdt_esp32_data *data = dev->driver_data; struct wdt_esp32_data *data = dev->driver_data;
memcpy(config, &data->config, sizeof(*config)); ARG_UNUSED(dev);
if (cfg->flags != WDT_FLAG_RESET_SOC) {
return -ENOTSUP;
}
if (cfg->window.min != 0 || cfg->window.max == 0) {
return -EINVAL;
}
data->dev = dev;
data->timeout = cfg->window.max;
data->mode = (cfg->callback == NULL) ?
WDT_MODE_RESET : WDT_MODE_INTERRUPT_RESET;
data->callback = cfg->callback;
return 0;
} }
static int wdt_esp32_init(struct device *dev) static int wdt_esp32_init(struct device *dev)
{ {
struct wdt_esp32_data *data = dev->driver_data;
(void)memset(&data->config, 0, sizeof(data->config));
#ifdef CONFIG_WDT_DISABLE_AT_BOOT #ifdef CONFIG_WDT_DISABLE_AT_BOOT
wdt_esp32_disable(dev); wdt_esp32_disable(dev);
#endif #endif
@ -217,15 +205,16 @@ static int wdt_esp32_init(struct device *dev)
esp32_rom_intr_matrix_set(0, ETS_TG1_WDT_LEVEL_INTR_SOURCE, esp32_rom_intr_matrix_set(0, ETS_TG1_WDT_LEVEL_INTR_SOURCE,
CONFIG_WDT_ESP32_IRQ); CONFIG_WDT_ESP32_IRQ);
wdt_esp32_enable();
return 0; return 0;
} }
static const struct wdt_driver_api wdt_api = { static const struct wdt_driver_api wdt_api = {
.enable = wdt_esp32_enable, .setup = wdt_esp32_set_config,
.disable = wdt_esp32_disable, .disable = wdt_esp32_disable,
.get_config = wdt_esp32_get_config, .install_timeout = wdt_esp32_install_timeout,
.set_config = wdt_esp32_set_config, .feed = wdt_esp32_reload
.reload = wdt_esp32_reload
}; };
DEVICE_AND_API_INIT(wdt_esp32, CONFIG_WDT_0_NAME, wdt_esp32_init, DEVICE_AND_API_INIT(wdt_esp32, CONFIG_WDT_0_NAME, wdt_esp32_init,
@ -238,8 +227,9 @@ static void wdt_esp32_isr(void *param)
struct wdt_esp32_data *data = param; struct wdt_esp32_data *data = param;
volatile u32_t *reg = (u32_t *)TIMG_INT_CLR_TIMERS_REG(1); volatile u32_t *reg = (u32_t *)TIMG_INT_CLR_TIMERS_REG(1);
if (data->config.interrupt_fn) {
data->config.interrupt_fn(DEVICE_GET(wdt_esp32)); if (shared_data.callback) {
shared_data.callback(data->dev, 0);
} }
*reg |= TIMG_WDT_INT_CLR; *reg |= TIMG_WDT_INT_CLR;

View file

@ -229,6 +229,17 @@ SECTIONS
_bss_end = ABSOLUTE(.); _bss_end = ABSOLUTE(.);
} GROUP_LINK_IN(RAMABLE_REGION) } GROUP_LINK_IN(RAMABLE_REGION)
SECTION_DATA_PROLOGUE(_APP_NOINIT_SECTION_NAME, (NOLOAD),)
{
. = ALIGN (8);
*(.app_noinit)
*("app_noinit.*")
. = ALIGN (8);
_app_end = ABSOLUTE(.);
} GROUP_LINK_IN(RAMABLE_REGION)
SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),) SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),)
{ {
. = ALIGN (8); . = ALIGN (8);