3 * Copyright (C) 2012 Spreadtrum Communications Inc.
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #ifndef _SPRD_WDT_SYS_H_
16 #define _SPRD_WDT_SYS_H_
17 #include <linux/spinlock.h>
18 #include <linux/bitops.h>
19 #include <soc/sprd/adi.h>
20 #include <soc/sprd/sci_glb_regs.h>
21 #include <soc/sprd/sci.h>
22 #include <soc/sprd/hardware.h>
24 unsigned long ap_wdt_addr;
25 unsigned long a7_wdt_addr;
27 #define AP_WDG_LOAD_LOW (ap_wdt_addr + 0x00)
28 #define AP_WDG_LOAD_HIGH (ap_wdt_addr + 0x04)
29 #define AP_WDG_CTRL (ap_wdt_addr + 0x08)
30 #define AP_WDG_INT_CLR (ap_wdt_addr + 0x0C)
31 #define AP_WDG_INT_RAW (ap_wdt_addr + 0x10)
32 #define AP_WDG_INT_MSK (ap_wdt_addr + 0x14)
33 #define AP_WDG_CNT_LOW (ap_wdt_addr + 0x18)
34 #define AP_WDG_CNT_HIGH (ap_wdt_addr + 0x1C)
35 #define AP_WDG_LOCK (ap_wdt_addr + 0x20)
37 #define CA7_WDG_LOAD_LOW (a7_wdt_addr + 0x00)
38 #define CA7_WDG_LOAD_HIGH (a7_wdt_addr + 0x04)
39 #define CA7_WDG_CTRL (a7_wdt_addr + 0x08)
40 #define CA7_WDG_INT_CLR (a7_wdt_addr + 0x0C)
41 #define CA7_WDG_INT_RAW (a7_wdt_addr + 0x10)
42 #define CA7_WDG_INT_MSK (a7_wdt_addr + 0x14)
43 #define CA7_WDG_CNT_LOW (a7_wdt_addr + 0x18)
44 #define CA7_WDG_CNT_HIGH (a7_wdt_addr + 0x1C)
45 #define CA7_WDG_LOCK (a7_wdt_addr + 0x20)
46 #define CA7_WDG_IRQ_LOAD_LOW (a7_wdt_addr + 0x2c)
47 #define CA7_WDG_IRQ_LOAD_HIGH (a7_wdt_addr + 0x30)
49 #define AP_WDG_LOAD_TIMER_VALUE(value) \
52 sci_glb_write( AP_WDG_LOAD_HIGH, (uint16_t)(((value) >> 16 ) & 0xffff), -1UL); \
53 sci_glb_write( AP_WDG_LOAD_LOW , (uint16_t)((value) & 0xffff), -1UL ); \
54 while((sci_glb_read(AP_WDG_INT_RAW, -1UL) & WDG_LD_BUSY_BIT) && ( cnt < ANA_WDG_LOAD_TIMEOUT_NUM )) cnt++; \
57 #define CA7_WDG_LOAD_TIMER_VALUE(margin, irq) \
60 sci_glb_write( CA7_WDG_LOAD_HIGH, (uint16_t)(((margin) >> 16 ) & 0xffff), -1UL); \
61 sci_glb_write( CA7_WDG_LOAD_LOW , (uint16_t)((margin) & 0xffff), -1UL ); \
62 sci_glb_write( CA7_WDG_IRQ_LOAD_HIGH, (uint16_t)(((irq) >> 16 ) & 0xffff), -1UL); \
63 sci_glb_write( CA7_WDG_IRQ_LOAD_LOW , (uint16_t)((irq) & 0xffff), -1UL ); \
64 while((sci_glb_read(CA7_WDG_INT_RAW, -1UL) & WDG_LD_BUSY_BIT) && ( cnt < ANA_WDG_LOAD_TIMEOUT_NUM )) cnt++; \
68 #ifdef CONFIG_SC_INTERNAL_WATCHDOG
69 static inline void FEED_ALL_WDG(int chip_margin, int ap_margin,
70 int ca7_margin, int ca7_irq_margin)
72 AP_WDG_LOAD_TIMER_VALUE(ap_margin * WDG_CLK);
73 WDG_LOAD_TIMER_VALUE(chip_margin * WDG_CLK);
74 CA7_WDG_LOAD_TIMER_VALUE(ca7_margin * WDG_CLK, (ca7_margin - ca7_irq_margin) * WDG_CLK);
77 static inline void FEED_ALL_WDG(int chip_margin, int ap_margin,
78 int ca7_margin, int ca7_irq_margin) { }
81 #define ENABLE_ALL_WDG() \
83 sci_adi_set(WDG_CTRL, WDG_CNT_EN_BIT | WDG_RST_EN_BIT); \
84 sci_glb_set(AP_WDG_CTRL, WDG_CNT_EN_BIT | WDG_RST_EN_BIT); \
85 sci_glb_set(CA7_WDG_CTRL, WDG_CNT_EN_BIT | WDG_RST_EN_BIT | WDG_INT_EN_BIT); \
88 #define DISABLE_ALL_WDG() \
90 sci_adi_clr(WDG_CTRL, WDG_CNT_EN_BIT | WDG_RST_EN_BIT); \
91 sci_glb_clr(AP_WDG_CTRL, WDG_CNT_EN_BIT | WDG_RST_EN_BIT); \
92 sci_glb_clr(CA7_WDG_CTRL, WDG_CNT_EN_BIT | WDG_RST_EN_BIT | WDG_INT_EN_BIT); \
95 #define WATCHDOG_THREAD_USER_BIT 0
96 #define WATCHDOG_THREAD_KERNEL_BIT 1
98 #define WATCHDOG_FEED_BY_USER_ST_BIT (0)
99 #define WATCHDOG_FEED_BY_USER_BIT (1)
100 #define WATCHDOG_FEED_BY_KERNEL_BIT (2)
101 #define WATCHDOG_FEED_ENABLE_BIT (30)
102 #define WATCHDOG_FEED_START_BIT (31)
104 #define WATCHDOG_FEED_BY_KERNEL_THREAD ( \
105 (1 << WATCHDOG_FEED_BY_USER_BIT) | \
106 (1 << WATCHDOG_FEED_BY_KERNEL_BIT) \
109 #define WATCHDOG_FEED_BY_USER_THREAD ( \
110 (1 << WATCHDOG_FEED_BY_USER_ST_BIT) \
113 #define WATCHDOG_FEED_BY_THREAD \
114 (WATCHDOG_FEED_BY_KERNEL_THREAD | WATCHDOG_FEED_BY_USER_THREAD)
116 #ifdef CONFIG_SC_INTERNAL_WATCHDOG
117 static inline void watchdog_start(int chip_margin, int ap_margin,
118 int ca7_margin, int ca7_irq_margin)
120 /* start the chip watchdog */
121 sci_adi_set(ANA_AGEN, AGEN_WDG_EN);
122 sci_adi_set(ANA_RTC_CLK_EN, AGEN_RTC_WDG_EN);
123 sci_adi_raw_write(WDG_LOCK, WDG_UNLOCK_KEY);
124 sci_adi_set(WDG_CTRL, WDG_NEW_VER_EN);
125 WDG_LOAD_TIMER_VALUE(chip_margin * WDG_CLK);
126 sci_adi_set(WDG_CTRL, WDG_CNT_EN_BIT | WDG_RST_EN_BIT);
128 /* start ap watchdog */
129 sci_glb_set(REG_AON_APB_APB_EB0, BIT_AP_WDG_EB);
130 sci_glb_set(REG_AON_APB_APB_RTC_EB, BIT_AP_WDG_RTC_EB);
131 sci_glb_write(AP_WDG_LOCK, WDG_UNLOCK_KEY, -1UL);
132 sci_glb_set(AP_WDG_CTRL, WDG_NEW_VER_EN);
133 AP_WDG_LOAD_TIMER_VALUE(ap_margin * WDG_CLK);
134 sci_glb_set(AP_WDG_CTRL, WDG_CNT_EN_BIT | WDG_RST_EN_BIT);
136 /* start ca7 watchdog */
137 sci_glb_set(REG_AON_APB_APB_EB1, BIT_CA7_WDG_EB);
138 sci_glb_set(REG_AON_APB_APB_RTC_EB, BIT_CA7_WDG_RTC_EB);
139 sci_glb_write(CA7_WDG_LOCK, WDG_UNLOCK_KEY, -1UL);
140 sci_glb_set(CA7_WDG_CTRL, WDG_NEW_VER_EN);
141 CA7_WDG_LOAD_TIMER_VALUE(ca7_margin * WDG_CLK, (ca7_margin - ca7_irq_margin) * WDG_CLK);
142 sci_glb_set(CA7_WDG_CTRL, WDG_CNT_EN_BIT | WDG_RST_EN_BIT | WDG_INT_EN_BIT);
146 static inline void watchdog_start(int chip_margin, int ap_margin,
147 int ca7_margin, int ca7_irq_margin) { }