wdt: dw: Add support for optional clock gating
Clock gating is platform specific and not mandatory. Thus making it Kconfig based as well as generic. Change-Id: I4ea10eadb077ac3d57c9337b43b1a9fb14763302 Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
parent
61c15ba1e1
commit
04f5cfb889
6 changed files with 78 additions and 14 deletions
|
@ -129,9 +129,6 @@ struct scss_interrupt {
|
|||
/* Watchdog */
|
||||
#define WDT_DW_INT_MASK (SCSS_INT_BASE + 0x7C)
|
||||
#define SCSS_PERIPH_CFG0 0x4
|
||||
#define SCSS_PERIPH_CFG0_WDT_ENABLE (1 << 1)
|
||||
#define CCU_WDT_PCLK_EN_SW (1 << 10)
|
||||
|
||||
|
||||
/* RTC */
|
||||
#define RTC_DW_INT_MASK (SCSS_INT_BASE + 0x78)
|
||||
|
|
|
@ -170,6 +170,12 @@ endif
|
|||
if WATCHDOG
|
||||
config WDT_DW
|
||||
def_bool y
|
||||
config WDT_DW_CLOCK_GATE
|
||||
def_bool n
|
||||
config WDT_DW_CLOCK_GATE_DRV_NAME
|
||||
default CLOCK_CONTROL_QUARK_SE_PERIPHERAL_DRV_NAME
|
||||
config WDT_DW_CLOCK_GATE_SUBSYS
|
||||
default 10
|
||||
config WDT_DW_BASE_ADDR
|
||||
default 0xB0000000
|
||||
config WDT_DW_IRQ
|
||||
|
|
|
@ -207,9 +207,6 @@ struct scss_interrupt {
|
|||
|
||||
#define SCSS_CCU_SYS_CLK_CTL 0x38
|
||||
|
||||
/* Peripheral Configuration */
|
||||
#define SCSS_PERIPH_CFG0 (0x4)
|
||||
|
||||
/* Peripheral Clock Gate Control */
|
||||
#define SCSS_CCU_PERIPH_CLK_GATE_CTL 0x18
|
||||
#define CCU_PERIPH_CLK_EN (1 << 1)
|
||||
|
@ -221,8 +218,7 @@ struct scss_interrupt {
|
|||
|
||||
/* Watchdog */
|
||||
#define WDT_DW_INT_MASK (SCSS_INT_BASE + 0x7C)
|
||||
#define SCSS_PERIPH_CFG0_WDT_ENABLE (1 << 1)
|
||||
#define CCU_WDT_PCLK_EN_SW (1 << 10)
|
||||
#define SCSS_PERIPH_CFG0 (0x4)
|
||||
|
||||
/* RTC */
|
||||
#define RTC_DW_INT_MASK (SCSS_INT_BASE + 0x78)
|
||||
|
|
|
@ -33,6 +33,24 @@ config WDT_DW
|
|||
help
|
||||
Enable watchdog timer.
|
||||
|
||||
config WDT_DW_CLOCK_GATE
|
||||
bool "Enable clock gating"
|
||||
depends on WDT_DW
|
||||
select CLOCK_CONTROL
|
||||
default n
|
||||
help
|
||||
Enable clock gating on WDT DesignWare controller
|
||||
|
||||
config WDT_DW_CLOCK_GATE_DRV_NAME
|
||||
string "Clock gating driver name"
|
||||
depends on WDT_DW_CLOCK_GATE
|
||||
default ""
|
||||
|
||||
config WDT_DW_CLOCK_GATE_SUBSYS
|
||||
int "Clock controller's subsystem"
|
||||
depends on WDT_DW_CLOCK_GATE
|
||||
default 0
|
||||
|
||||
config WDT_DW_DRV_NAME
|
||||
string "Driver instance name"
|
||||
default "WDT_DW"
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <nanokernel.h>
|
||||
#include <init.h>
|
||||
#include <clock_control.h>
|
||||
#include "wdt_dw.h"
|
||||
|
||||
#ifdef WDT_DW_INT_MASK
|
||||
|
@ -28,25 +29,60 @@ static inline void _wdt_dw_int_unmask(void)
|
|||
#define _wdt_dw_int_unmask()
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_WDT_DW_CLOCK_GATE
|
||||
static inline void _wdt_dw_clock_config(struct device *dev)
|
||||
{
|
||||
char *drv = CONFIG_WDT_DW_CLOCK_GATE_DRV_NAME;
|
||||
struct device *clk;
|
||||
|
||||
clk = device_get_binding(drv);
|
||||
if (clk) {
|
||||
struct wdt_dw_runtime *context = dev->driver_data;
|
||||
|
||||
context->clock = clk;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _wdt_dw_clock_on(struct device *dev)
|
||||
{
|
||||
struct wdt_dw_dev_config *config = dev->config->config_info;
|
||||
struct wdt_dw_runtime *context = dev->driver_data;
|
||||
|
||||
clock_control_on(context->clock, config->clock_data);
|
||||
}
|
||||
|
||||
static inline void _wdt_dw_clock_off(struct device *dev)
|
||||
{
|
||||
struct wdt_dw_dev_config *config = dev->config->config_info;
|
||||
struct wdt_dw_runtime *context = dev->driver_data;
|
||||
|
||||
clock_control_off(context->clock, config->clock_data);
|
||||
}
|
||||
#else
|
||||
#define _wdt_dw_clock_config(...)
|
||||
#define _wdt_dw_clock_on(...)
|
||||
#define _wdt_dw_clock_off(...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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;
|
||||
_wdt_dw_clock_on(dev);
|
||||
|
||||
sys_set_bit(wdt_dev->base_address + WDT_CR, 0);
|
||||
|
||||
sys_set_bit(CLOCK_PERIPHERAL_BASE_ADDR, 1);
|
||||
#if defined(CONFIG_PLATFORM_QUARK_SE) || defined(CONFIG_PLATFORM_QUARK_D2000)
|
||||
sys_set_bit(SCSS_PERIPHERAL_BASE + SCSS_PERIPH_CFG0, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void wdt_dw_disable(struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
_wdt_dw_clock_off(dev);
|
||||
|
||||
/* Disable the clock for the peripheral watchdog */
|
||||
#if defined(CONFIG_PLATFORM_QUARK_SE) || defined(CONFIG_PLATFORM_QUARK_D2000)
|
||||
sys_clear_bit(SCSS_PERIPHERAL_BASE + SCSS_PERIPH_CFG0, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void wdt_dw_isr(void *arg)
|
||||
|
@ -126,6 +162,8 @@ int wdt_dw_init(struct device *dev)
|
|||
|
||||
_wdt_dw_int_unmask();
|
||||
|
||||
_wdt_dw_clock_config(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -133,6 +171,9 @@ struct wdt_dw_runtime wdt_runtime;
|
|||
|
||||
struct wdt_dw_dev_config wdt_dev = {
|
||||
.base_address = CONFIG_WDT_DW_BASE_ADDR,
|
||||
#ifdef CONFIG_WDT_DW_CLOCK_GATE
|
||||
.clock_data = UINT_TO_POINTER(CONFIG_WDT_DW_CLOCK_GATE_SUBSYS),
|
||||
#endif
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_INIT_CONFIG(wdt, CONFIG_WDT_DW_DRV_NAME,
|
||||
|
|
|
@ -47,10 +47,16 @@
|
|||
|
||||
struct wdt_dw_runtime {
|
||||
void (*cb_fn)(struct device *dev);
|
||||
#ifdef CONFIG_WDT_DW_CLOCK_GATE
|
||||
struct device *clock;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct wdt_dw_dev_config {
|
||||
uint32_t base_address;
|
||||
#ifdef CONFIG_WDT_DW_CLOCK_GATE
|
||||
void *clock_data;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* WDT_DW_H_ */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue