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 */
|
/* Watchdog */
|
||||||
#define WDT_DW_INT_MASK (SCSS_INT_BASE + 0x7C)
|
#define WDT_DW_INT_MASK (SCSS_INT_BASE + 0x7C)
|
||||||
#define SCSS_PERIPH_CFG0 0x4
|
#define SCSS_PERIPH_CFG0 0x4
|
||||||
#define SCSS_PERIPH_CFG0_WDT_ENABLE (1 << 1)
|
|
||||||
#define CCU_WDT_PCLK_EN_SW (1 << 10)
|
|
||||||
|
|
||||||
|
|
||||||
/* RTC */
|
/* RTC */
|
||||||
#define RTC_DW_INT_MASK (SCSS_INT_BASE + 0x78)
|
#define RTC_DW_INT_MASK (SCSS_INT_BASE + 0x78)
|
||||||
|
|
|
@ -170,6 +170,12 @@ endif
|
||||||
if WATCHDOG
|
if WATCHDOG
|
||||||
config WDT_DW
|
config WDT_DW
|
||||||
def_bool y
|
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
|
config WDT_DW_BASE_ADDR
|
||||||
default 0xB0000000
|
default 0xB0000000
|
||||||
config WDT_DW_IRQ
|
config WDT_DW_IRQ
|
||||||
|
|
|
@ -207,9 +207,6 @@ struct scss_interrupt {
|
||||||
|
|
||||||
#define SCSS_CCU_SYS_CLK_CTL 0x38
|
#define SCSS_CCU_SYS_CLK_CTL 0x38
|
||||||
|
|
||||||
/* Peripheral Configuration */
|
|
||||||
#define SCSS_PERIPH_CFG0 (0x4)
|
|
||||||
|
|
||||||
/* Peripheral Clock Gate Control */
|
/* Peripheral Clock Gate Control */
|
||||||
#define SCSS_CCU_PERIPH_CLK_GATE_CTL 0x18
|
#define SCSS_CCU_PERIPH_CLK_GATE_CTL 0x18
|
||||||
#define CCU_PERIPH_CLK_EN (1 << 1)
|
#define CCU_PERIPH_CLK_EN (1 << 1)
|
||||||
|
@ -221,8 +218,7 @@ struct scss_interrupt {
|
||||||
|
|
||||||
/* Watchdog */
|
/* Watchdog */
|
||||||
#define WDT_DW_INT_MASK (SCSS_INT_BASE + 0x7C)
|
#define WDT_DW_INT_MASK (SCSS_INT_BASE + 0x7C)
|
||||||
#define SCSS_PERIPH_CFG0_WDT_ENABLE (1 << 1)
|
#define SCSS_PERIPH_CFG0 (0x4)
|
||||||
#define CCU_WDT_PCLK_EN_SW (1 << 10)
|
|
||||||
|
|
||||||
/* RTC */
|
/* RTC */
|
||||||
#define RTC_DW_INT_MASK (SCSS_INT_BASE + 0x78)
|
#define RTC_DW_INT_MASK (SCSS_INT_BASE + 0x78)
|
||||||
|
|
|
@ -33,6 +33,24 @@ config WDT_DW
|
||||||
help
|
help
|
||||||
Enable watchdog timer.
|
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
|
config WDT_DW_DRV_NAME
|
||||||
string "Driver instance name"
|
string "Driver instance name"
|
||||||
default "WDT_DW"
|
default "WDT_DW"
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include <nanokernel.h>
|
#include <nanokernel.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
|
#include <clock_control.h>
|
||||||
#include "wdt_dw.h"
|
#include "wdt_dw.h"
|
||||||
|
|
||||||
#ifdef WDT_DW_INT_MASK
|
#ifdef WDT_DW_INT_MASK
|
||||||
|
@ -28,25 +29,60 @@ static inline void _wdt_dw_int_unmask(void)
|
||||||
#define _wdt_dw_int_unmask()
|
#define _wdt_dw_int_unmask()
|
||||||
#endif
|
#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
|
* Enables the clock for the peripheral watchdog
|
||||||
*/
|
*/
|
||||||
static void wdt_dw_enable(struct device *dev)
|
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);
|
#if defined(CONFIG_PLATFORM_QUARK_SE) || defined(CONFIG_PLATFORM_QUARK_D2000)
|
||||||
|
|
||||||
sys_set_bit(CLOCK_PERIPHERAL_BASE_ADDR, 1);
|
|
||||||
sys_set_bit(SCSS_PERIPHERAL_BASE + SCSS_PERIPH_CFG0, 1);
|
sys_set_bit(SCSS_PERIPHERAL_BASE + SCSS_PERIPH_CFG0, 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wdt_dw_disable(struct device *dev)
|
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);
|
sys_clear_bit(SCSS_PERIPHERAL_BASE + SCSS_PERIPH_CFG0, 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void wdt_dw_isr(void *arg)
|
void wdt_dw_isr(void *arg)
|
||||||
|
@ -126,6 +162,8 @@ int wdt_dw_init(struct device *dev)
|
||||||
|
|
||||||
_wdt_dw_int_unmask();
|
_wdt_dw_int_unmask();
|
||||||
|
|
||||||
|
_wdt_dw_clock_config(dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +171,9 @@ struct wdt_dw_runtime wdt_runtime;
|
||||||
|
|
||||||
struct wdt_dw_dev_config wdt_dev = {
|
struct wdt_dw_dev_config wdt_dev = {
|
||||||
.base_address = CONFIG_WDT_DW_BASE_ADDR,
|
.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,
|
DECLARE_DEVICE_INIT_CONFIG(wdt, CONFIG_WDT_DW_DRV_NAME,
|
||||||
|
|
|
@ -47,10 +47,16 @@
|
||||||
|
|
||||||
struct wdt_dw_runtime {
|
struct wdt_dw_runtime {
|
||||||
void (*cb_fn)(struct device *dev);
|
void (*cb_fn)(struct device *dev);
|
||||||
|
#ifdef CONFIG_WDT_DW_CLOCK_GATE
|
||||||
|
struct device *clock;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wdt_dw_dev_config {
|
struct wdt_dw_dev_config {
|
||||||
uint32_t base_address;
|
uint32_t base_address;
|
||||||
|
#ifdef CONFIG_WDT_DW_CLOCK_GATE
|
||||||
|
void *clock_data;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* WDT_DW_H_ */
|
#endif /* WDT_DW_H_ */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue