blob: da31104a15d6816f717158317f8848dabe43cebb [file] [log] [blame]
/*
* drivers\watchdog\zx29_wdt.h
*
* Copyright (C) 2015 ZTE-TSP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __ZX29_WDT_H
#define __ZX29_WDT_H
#include <mach/board.h>
#include <mach/iomap.h>
#define WDT_SOURCE_CLOCK_RATE (32768)
#define WDT_TIME_1S (WDT_SOURCE_CLOCK_RATE/32)
#define WDT_TIME_1M (WDT_TIME_1S*60)
#define WDT_TIME_1MS (WDT_TIME_1S/1000)
typedef struct
{
/* 0x00 */ volatile unsigned wdt_version;
/* 0x04 */ volatile unsigned wdt_config;
/* 0x08 */ volatile unsigned wdt_load;
/* 0x0c */ volatile unsigned wdt_counter;
/* 0x10 */ volatile unsigned wdt_status;
/* 0x14 */ volatile unsigned wdt_int_value;
/* 0x18 */ volatile unsigned wdt_set_en;
/* 0x1c */ volatile unsigned wdt_start;
} zx29_wdt_registers;
typedef struct
{
unsigned wdt_config;
unsigned wdt_load;
unsigned wdt_int_value;
unsigned wdt_start;
} zx29_wdt_context;
/* we can enable/disable wdt reset function */
#define WDT_RESET_ENABLE_REG (ZX_TOP_CRM_BASE + 0x2c)
#define CPU_AP_WDT_RSTALL_EN (1U << 7)
#define CPU_AP_WDT_RSTEN (1U << 6)
#define __wdt_enable_reset() \
zx_set_reg(WDT_RESET_ENABLE_REG, CPU_AP_WDT_RSTALL_EN|CPU_AP_WDT_RSTEN)
#define __wdt_disable_reset() \
zx_clr_reg(WDT_RESET_ENABLE_REG, CPU_AP_WDT_RSTALL_EN|CPU_AP_WDT_RSTEN)
/******************************************************************************/
#define WDT_WRITE_KEY (0x1234 << 16)
#define WDT_PRESCALE(ptv) (ptv << 8)
static inline void __wdt_start(void __iomem *base)
{
zx29_wdt_registers *wdt_reg = (zx29_wdt_registers *)base;
wdt_reg->wdt_start = WDT_WRITE_KEY|1;
}
static inline void __wdt_stop(void __iomem *base)
{
zx29_wdt_registers *wdt_reg = (zx29_wdt_registers *)base;
wdt_reg->wdt_start = WDT_WRITE_KEY|0;
}
static inline void __wdt_refresh_config_reg(void __iomem *base)
{
zx29_wdt_registers *wdt_reg = (zx29_wdt_registers *)base;
unsigned int tmp=0;
tmp = wdt_reg->wdt_set_en;
tmp ^= 0x30;
wdt_reg->wdt_set_en = WDT_WRITE_KEY|tmp;
}
static inline void __wdt_refresh_load_reg(void __iomem *base)
{
zx29_wdt_registers *wdt_reg = (zx29_wdt_registers *)base;
unsigned int tmp=0;
tmp = wdt_reg->wdt_set_en;
tmp ^= 0xC;
wdt_reg->wdt_set_en = WDT_WRITE_KEY|tmp;
}
static inline void __wdt_refresh_int_value_reg(void __iomem *base)
{
zx29_wdt_registers *wdt_reg = (zx29_wdt_registers *)base;
unsigned int tmp=0;
tmp = wdt_reg->wdt_set_en;
tmp ^= 0x3;
wdt_reg->wdt_set_en = WDT_WRITE_KEY|tmp;
}
static inline void __wdt_refresh_config_load_int_reg(void __iomem *base)
{
zx29_wdt_registers *wdt_reg = (zx29_wdt_registers *)base;
unsigned int tmp=0;
tmp = wdt_reg->wdt_set_en;
tmp ^= 0x3f;
wdt_reg->wdt_set_en = WDT_WRITE_KEY|tmp;
}
static inline void __wdt_wait_value_loaded(void __iomem *base)
{
zx29_wdt_registers *wdt_reg = (zx29_wdt_registers *)base;
while( (wdt_reg->wdt_status & 0x2)==0x0 );
}
/*
* set prescale, default is 0
* 1--div 2 2--div 3 ...
*/
static inline void __wdt_set_prescale(void __iomem *base, u32 prescale)
{
zx29_wdt_registers *wdt_reg = (zx29_wdt_registers *)base;
unsigned int tmp = wdt_reg->wdt_config;
tmp &= WDT_PRESCALE(0xFF);
tmp |= WDT_PRESCALE(prescale);
wdt_reg->wdt_config = WDT_WRITE_KEY|tmp;
__wdt_refresh_config_reg(base);
}
static inline void __wdt_set_load(void __iomem *base, u32 load)
{
zx29_wdt_registers *wdt_reg = (zx29_wdt_registers *)base;
wdt_reg->wdt_load = WDT_WRITE_KEY|load;
__wdt_refresh_load_reg(base);
}
static inline void __wdt_set_int_value(void __iomem *base, u32 int_value)
{
zx29_wdt_registers *wdt_reg = (zx29_wdt_registers *)base;
wdt_reg->wdt_int_value = WDT_WRITE_KEY|int_value;
__wdt_refresh_int_value_reg(base);
}
static inline void __wdt_save_context(void __iomem *base, u32 *pointer)
{
zx29_wdt_registers *wdt_reg = (zx29_wdt_registers *)base;
zx29_wdt_context *wdt_context = (zx29_wdt_context *)pointer;
wdt_context->wdt_config = wdt_reg->wdt_config;
wdt_context->wdt_load = wdt_reg->wdt_load;
wdt_context->wdt_int_value = wdt_reg->wdt_int_value;
wdt_context->wdt_start = wdt_reg->wdt_start;
if(wdt_context->wdt_start)
__wdt_stop(base);
}
static inline void __wdt_restore_context(void __iomem *base, u32 *pointer)
{
zx29_wdt_registers *wdt_reg = (zx29_wdt_registers *)base;
zx29_wdt_context *wdt_context = (zx29_wdt_context *)pointer;
wdt_reg->wdt_config = wdt_context->wdt_config;
wdt_reg->wdt_load = wdt_context->wdt_load;
wdt_reg->wdt_int_value = wdt_context->wdt_int_value;
__wdt_refresh_config_load_int_reg(base);
if(wdt_context->wdt_start)
__wdt_start(base);
}
#endif