e8c4335aa6
A platform might provide multiple watchdogs, either internally or externally. Applying the changes to the DesignWare driver relevantly as well as into the sample application. Taking the opportunity to apply propre style when need (80 chars limit for instance). Change-Id: Iad020c697846db483a70a748cfc8fe7147ec3c04 Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
134 lines
3.5 KiB
C
134 lines
3.5 KiB
C
/*
|
|
* Copyright (c) 2015 Intel Corporation.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <nanokernel.h>
|
|
#include <init.h>
|
|
#include "wdt_dw.h"
|
|
|
|
/**
|
|
* Enables the clock for the peripheral watchdog
|
|
*/
|
|
static void wdt_dw_enable(struct device *dev)
|
|
{
|
|
struct wdt_dw_dev_config *wdt_dev = dev->config->config_info;
|
|
|
|
sys_set_bit(wdt_dev->base_address + WDT_CR, 0);
|
|
|
|
sys_set_bit(CLOCK_PERIPHERAL_BASE_ADDR, 1);
|
|
sys_set_bit(SCSS_PERIPHERAL_BASE + SCSS_PERIPH_CFG0, 1);
|
|
}
|
|
|
|
static void wdt_dw_disable(struct device *dev)
|
|
{
|
|
ARG_UNUSED(dev);
|
|
|
|
/* Disable the clock for the peripheral watchdog */
|
|
sys_clear_bit(SCSS_PERIPHERAL_BASE + SCSS_PERIPH_CFG0, 1);
|
|
}
|
|
|
|
void wdt_dw_isr(void *arg)
|
|
{
|
|
struct device *dev = arg;
|
|
struct wdt_dw_runtime *context = dev->driver_data;
|
|
|
|
if (context->cb_fn) {
|
|
context->cb_fn(dev);
|
|
}
|
|
}
|
|
|
|
static void wdt_dw_get_config(struct device *dev, struct wdt_config *config)
|
|
{
|
|
struct wdt_dw_dev_config *wdt_dev = dev->config->config_info;
|
|
struct wdt_dw_runtime *context = dev->driver_data;
|
|
|
|
config->timeout = sys_read32(wdt_dev->base_address + WDT_TORR) &
|
|
WDT_TIMEOUT_MASK;
|
|
config->mode = (sys_read32(wdt_dev->base_address + WDT_CR) & WDT_MODE)
|
|
>> WDT_MODE_OFFSET;
|
|
config->interrupt_fn = context->cb_fn;
|
|
}
|
|
|
|
static void wdt_dw_reload(struct device *dev)
|
|
{
|
|
struct wdt_dw_dev_config *wdt_dev = dev->config->config_info;
|
|
|
|
sys_write32(WDT_CRR_VAL, wdt_dev->base_address + WDT_CRR);
|
|
}
|
|
|
|
static int wdt_dw_set_config(struct device *dev, struct wdt_config *config)
|
|
{
|
|
struct wdt_dw_dev_config *wdt_dev = dev->config->config_info;
|
|
struct wdt_dw_runtime *context = dev->driver_data;
|
|
|
|
sys_write32(config->timeout, wdt_dev->base_address + WDT_TORR);
|
|
|
|
/* Set response mode */
|
|
if (WDT_MODE_RESET == config->mode) {
|
|
sys_clear_bit(wdt_dev->base_address + WDT_CR, 1);
|
|
} else {
|
|
if (!config->interrupt_fn) {
|
|
return DEV_FAIL;
|
|
}
|
|
|
|
context->cb_fn = config->interrupt_fn;
|
|
sys_set_bit(wdt_dev->base_address + WDT_CR, 1);
|
|
|
|
/* unmask WDT interrupts to lmt */
|
|
SCSS_INTERRUPT->int_watchdog_mask &= INT_UNMASK_IA;
|
|
}
|
|
|
|
/* Enable WDT, cannot be disabled until soc reset */
|
|
sys_set_bit(wdt_dev->base_address + WDT_CR, 0);
|
|
|
|
wdt_dw_reload(dev);
|
|
|
|
return DEV_OK;
|
|
}
|
|
|
|
static struct wdt_driver_api wdt_dw_funcs = {
|
|
.set_config = wdt_dw_set_config,
|
|
.get_config = wdt_dw_get_config,
|
|
.enable = wdt_dw_enable,
|
|
.disable = wdt_dw_disable,
|
|
.reload = wdt_dw_reload,
|
|
};
|
|
|
|
/* IRQ_CONFIG needs the flags variable declared by IRQ_CONNECT_STATIC */
|
|
IRQ_CONNECT_STATIC(wdt_dw, INT_WDT_IRQ, INT_WDT_IRQ_PRI, wdt_dw_isr, 0, 0);
|
|
|
|
int wdt_dw_init(struct device *dev)
|
|
{
|
|
dev->driver_api = &wdt_dw_funcs;
|
|
|
|
IRQ_CONFIG(wdt_dw, INT_WDT_IRQ);
|
|
irq_enable(INT_WDT_IRQ);
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct wdt_dw_runtime wdt_runtime;
|
|
|
|
struct wdt_dw_dev_config wdt_dev = {
|
|
.base_address = WDT_BASE_ADDR,
|
|
};
|
|
|
|
DECLARE_DEVICE_INIT_CONFIG(wdt, WDT_DRV_NAME, &wdt_dw_init, &wdt_dev);
|
|
|
|
SYS_DEFINE_DEVICE(wdt, &wdt_runtime, SECONDARY,
|
|
CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|
|
|
|
struct device *wdt_dw_isr_dev = SYS_GET_DEVICE(wdt);
|