| /* |
| * 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 |
| |
| |