Blame view
drivers/watchdog/davinci_wdt.c
6.34 KB
7d831bf59 [WATCHDOG] davinc... |
1 2 3 4 5 |
/* * drivers/char/watchdog/davinci_wdt.c * * Watchdog driver for DaVinci DM644x/DM646x processors * |
f48f3ceab watchdog: davinci... |
6 |
* Copyright (C) 2006-2013 Texas Instruments. |
7d831bf59 [WATCHDOG] davinc... |
7 8 9 10 11 12 13 14 15 16 17 |
* * 2007 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/types.h> #include <linux/kernel.h> |
7d831bf59 [WATCHDOG] davinc... |
18 |
#include <linux/watchdog.h> |
7d831bf59 [WATCHDOG] davinc... |
19 |
#include <linux/platform_device.h> |
f78b0a8f2 [WATCHDOG 08/57] ... |
20 |
#include <linux/io.h> |
371d3525e [WATCHDOG] davinc... |
21 |
#include <linux/device.h> |
9fd868f44 [WATCHDOG] davinc... |
22 |
#include <linux/clk.h> |
6330c7070 watchdog: Convert... |
23 |
#include <linux/err.h> |
7d831bf59 [WATCHDOG] davinc... |
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
#define MODULE_NAME "DAVINCI-WDT: " #define DEFAULT_HEARTBEAT 60 #define MAX_HEARTBEAT 600 /* really the max margin is 264/27MHz*/ /* Timer register set definition */ #define PID12 (0x0) #define EMUMGT (0x4) #define TIM12 (0x10) #define TIM34 (0x14) #define PRD12 (0x18) #define PRD34 (0x1C) #define TCR (0x20) #define TGCR (0x24) #define WDTCR (0x28) /* TCR bit definitions */ #define ENAMODE12_DISABLED (0 << 6) #define ENAMODE12_ONESHOT (1 << 6) #define ENAMODE12_PERIODIC (2 << 6) /* TGCR bit definitions */ #define TIM12RS_UNRESET (1 << 0) #define TIM34RS_UNRESET (1 << 1) #define TIMMODE_64BIT_WDOG (2 << 2) /* WDTCR bit definitions */ #define WDEN (1 << 14) #define WDFLAG (1 << 15) #define WDKEY_SEQ0 (0xa5c6 << 16) #define WDKEY_SEQ1 (0xda7e << 16) |
f48f3ceab watchdog: davinci... |
56 |
static int heartbeat; |
6d9a6cf5c watchdog: davinci... |
57 58 59 60 61 62 63 64 65 66 67 68 |
/* * struct to hold data for each WDT device * @base - base io address of WD device * @clk - source clock of WDT * @wdd - hold watchdog device as is in WDT core */ struct davinci_wdt_device { void __iomem *base; struct clk *clk; struct watchdog_device wdd; }; |
7d831bf59 [WATCHDOG] davinc... |
69 |
|
f48f3ceab watchdog: davinci... |
70 |
static int davinci_wdt_start(struct watchdog_device *wdd) |
7d831bf59 [WATCHDOG] davinc... |
71 72 73 |
{ u32 tgcr; u32 timer_margin; |
9fd868f44 [WATCHDOG] davinc... |
74 |
unsigned long wdt_freq; |
6d9a6cf5c watchdog: davinci... |
75 |
struct davinci_wdt_device *davinci_wdt = watchdog_get_drvdata(wdd); |
9fd868f44 [WATCHDOG] davinc... |
76 |
|
6d9a6cf5c watchdog: davinci... |
77 |
wdt_freq = clk_get_rate(davinci_wdt->clk); |
7d831bf59 [WATCHDOG] davinc... |
78 |
|
7d831bf59 [WATCHDOG] davinc... |
79 |
/* disable, internal clock source */ |
6d9a6cf5c watchdog: davinci... |
80 |
iowrite32(0, davinci_wdt->base + TCR); |
7d831bf59 [WATCHDOG] davinc... |
81 |
/* reset timer, set mode to 64-bit watchdog, and unreset */ |
6d9a6cf5c watchdog: davinci... |
82 |
iowrite32(0, davinci_wdt->base + TGCR); |
7d831bf59 [WATCHDOG] davinc... |
83 |
tgcr = TIMMODE_64BIT_WDOG | TIM12RS_UNRESET | TIM34RS_UNRESET; |
6d9a6cf5c watchdog: davinci... |
84 |
iowrite32(tgcr, davinci_wdt->base + TGCR); |
7d831bf59 [WATCHDOG] davinc... |
85 |
/* clear counter regs */ |
6d9a6cf5c watchdog: davinci... |
86 87 |
iowrite32(0, davinci_wdt->base + TIM12); iowrite32(0, davinci_wdt->base + TIM34); |
7d831bf59 [WATCHDOG] davinc... |
88 |
/* set timeout period */ |
f48f3ceab watchdog: davinci... |
89 |
timer_margin = (((u64)wdd->timeout * wdt_freq) & 0xffffffff); |
6d9a6cf5c watchdog: davinci... |
90 |
iowrite32(timer_margin, davinci_wdt->base + PRD12); |
f48f3ceab watchdog: davinci... |
91 |
timer_margin = (((u64)wdd->timeout * wdt_freq) >> 32); |
6d9a6cf5c watchdog: davinci... |
92 |
iowrite32(timer_margin, davinci_wdt->base + PRD34); |
7d831bf59 [WATCHDOG] davinc... |
93 |
/* enable run continuously */ |
6d9a6cf5c watchdog: davinci... |
94 |
iowrite32(ENAMODE12_PERIODIC, davinci_wdt->base + TCR); |
7d831bf59 [WATCHDOG] davinc... |
95 96 97 98 99 |
/* Once the WDT is in pre-active state write to * TIM12, TIM34, PRD12, PRD34, TCR, TGCR, WDTCR are * write protected (except for the WDKEY field) */ /* put watchdog in pre-active state */ |
6d9a6cf5c watchdog: davinci... |
100 |
iowrite32(WDKEY_SEQ0 | WDEN, davinci_wdt->base + WDTCR); |
7d831bf59 [WATCHDOG] davinc... |
101 |
/* put watchdog in active state */ |
6d9a6cf5c watchdog: davinci... |
102 |
iowrite32(WDKEY_SEQ1 | WDEN, davinci_wdt->base + WDTCR); |
f48f3ceab watchdog: davinci... |
103 |
return 0; |
7d831bf59 [WATCHDOG] davinc... |
104 |
} |
f48f3ceab watchdog: davinci... |
105 |
static int davinci_wdt_ping(struct watchdog_device *wdd) |
7d831bf59 [WATCHDOG] davinc... |
106 |
{ |
6d9a6cf5c watchdog: davinci... |
107 |
struct davinci_wdt_device *davinci_wdt = watchdog_get_drvdata(wdd); |
f48f3ceab watchdog: davinci... |
108 |
/* put watchdog in service state */ |
6d9a6cf5c watchdog: davinci... |
109 |
iowrite32(WDKEY_SEQ0, davinci_wdt->base + WDTCR); |
f48f3ceab watchdog: davinci... |
110 |
/* put watchdog in active state */ |
6d9a6cf5c watchdog: davinci... |
111 |
iowrite32(WDKEY_SEQ1, davinci_wdt->base + WDTCR); |
f48f3ceab watchdog: davinci... |
112 |
return 0; |
7d831bf59 [WATCHDOG] davinc... |
113 |
} |
a77199490 watchdog: davinci... |
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
static unsigned int davinci_wdt_get_timeleft(struct watchdog_device *wdd) { u64 timer_counter; unsigned long freq; u32 val; struct davinci_wdt_device *davinci_wdt = watchdog_get_drvdata(wdd); /* if timeout has occured then return 0 */ val = ioread32(davinci_wdt->base + WDTCR); if (val & WDFLAG) return 0; freq = clk_get_rate(davinci_wdt->clk); if (!freq) return 0; timer_counter = ioread32(davinci_wdt->base + TIM12); timer_counter |= ((u64)ioread32(davinci_wdt->base + TIM34) << 32); do_div(timer_counter, freq); return wdd->timeout - timer_counter; } |
f48f3ceab watchdog: davinci... |
138 |
static const struct watchdog_info davinci_wdt_info = { |
f1a08cc9a [WATCHDOG] davinc... |
139 |
.options = WDIOF_KEEPALIVEPING, |
8832b2009 watchdog: davinci... |
140 |
.identity = "DaVinci/Keystone Watchdog", |
7d831bf59 [WATCHDOG] davinc... |
141 |
}; |
f48f3ceab watchdog: davinci... |
142 143 144 145 146 |
static const struct watchdog_ops davinci_wdt_ops = { .owner = THIS_MODULE, .start = davinci_wdt_start, .stop = davinci_wdt_ping, .ping = davinci_wdt_ping, |
a77199490 watchdog: davinci... |
147 |
.get_timeleft = davinci_wdt_get_timeleft, |
7d831bf59 [WATCHDOG] davinc... |
148 |
}; |
2d991a164 watchdog: remove ... |
149 |
static int davinci_wdt_probe(struct platform_device *pdev) |
7d831bf59 [WATCHDOG] davinc... |
150 |
{ |
e20880e60 watchdog: davinci... |
151 |
int ret = 0; |
371d3525e [WATCHDOG] davinc... |
152 |
struct device *dev = &pdev->dev; |
e20880e60 watchdog: davinci... |
153 |
struct resource *wdt_mem; |
f48f3ceab watchdog: davinci... |
154 |
struct watchdog_device *wdd; |
6d9a6cf5c watchdog: davinci... |
155 156 157 158 159 |
struct davinci_wdt_device *davinci_wdt; davinci_wdt = devm_kzalloc(dev, sizeof(*davinci_wdt), GFP_KERNEL); if (!davinci_wdt) return -ENOMEM; |
7d831bf59 [WATCHDOG] davinc... |
160 |
|
6d9a6cf5c watchdog: davinci... |
161 162 163 |
davinci_wdt->clk = devm_clk_get(dev, NULL); if (WARN_ON(IS_ERR(davinci_wdt->clk))) return PTR_ERR(davinci_wdt->clk); |
9fd868f44 [WATCHDOG] davinc... |
164 |
|
6d9a6cf5c watchdog: davinci... |
165 |
clk_prepare_enable(davinci_wdt->clk); |
9fd868f44 [WATCHDOG] davinc... |
166 |
|
6d9a6cf5c watchdog: davinci... |
167 168 169 |
platform_set_drvdata(pdev, davinci_wdt); wdd = &davinci_wdt->wdd; |
f48f3ceab watchdog: davinci... |
170 171 172 173 174 |
wdd->info = &davinci_wdt_info; wdd->ops = &davinci_wdt_ops; wdd->min_timeout = 1; wdd->max_timeout = MAX_HEARTBEAT; wdd->timeout = DEFAULT_HEARTBEAT; |
6551881c8 Watchdog: Fix par... |
175 |
wdd->parent = &pdev->dev; |
f48f3ceab watchdog: davinci... |
176 177 178 179 180 |
watchdog_init_timeout(wdd, heartbeat, dev); dev_info(dev, "heartbeat %d sec ", wdd->timeout); |
7d831bf59 [WATCHDOG] davinc... |
181 |
|
6d9a6cf5c watchdog: davinci... |
182 |
watchdog_set_drvdata(wdd, davinci_wdt); |
f48f3ceab watchdog: davinci... |
183 |
watchdog_set_nowayout(wdd, 1); |
7d831bf59 [WATCHDOG] davinc... |
184 |
|
f712eacf0 watchdog: Convert... |
185 |
wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
6d9a6cf5c watchdog: davinci... |
186 187 188 |
davinci_wdt->base = devm_ioremap_resource(dev, wdt_mem); if (IS_ERR(davinci_wdt->base)) return PTR_ERR(davinci_wdt->base); |
7d831bf59 [WATCHDOG] davinc... |
189 |
|
f48f3ceab watchdog: davinci... |
190 191 192 193 |
ret = watchdog_register_device(wdd); if (ret < 0) dev_err(dev, "cannot register watchdog device "); |
7d831bf59 [WATCHDOG] davinc... |
194 195 196 |
return ret; } |
4b12b896c watchdog: remove ... |
197 |
static int davinci_wdt_remove(struct platform_device *pdev) |
7d831bf59 [WATCHDOG] davinc... |
198 |
{ |
6d9a6cf5c watchdog: davinci... |
199 200 201 202 |
struct davinci_wdt_device *davinci_wdt = platform_get_drvdata(pdev); watchdog_unregister_device(&davinci_wdt->wdd); clk_disable_unprepare(davinci_wdt->clk); |
9fd868f44 [WATCHDOG] davinc... |
203 |
|
7d831bf59 [WATCHDOG] davinc... |
204 205 |
return 0; } |
902e2e7d4 watchdog: davinci... |
206 207 208 209 210 |
static const struct of_device_id davinci_wdt_of_match[] = { { .compatible = "ti,davinci-wdt", }, {}, }; MODULE_DEVICE_TABLE(of, davinci_wdt_of_match); |
7d831bf59 [WATCHDOG] davinc... |
211 212 |
static struct platform_driver platform_wdt_driver = { .driver = { |
843748123 watchdog: davinci... |
213 |
.name = "davinci-wdt", |
902e2e7d4 watchdog: davinci... |
214 |
.of_match_table = davinci_wdt_of_match, |
7d831bf59 [WATCHDOG] davinc... |
215 216 |
}, .probe = davinci_wdt_probe, |
82268714b watchdog: remove ... |
217 |
.remove = davinci_wdt_remove, |
7d831bf59 [WATCHDOG] davinc... |
218 |
}; |
b8ec61189 watchdog: convert... |
219 |
module_platform_driver(platform_wdt_driver); |
7d831bf59 [WATCHDOG] davinc... |
220 221 222 223 224 225 226 227 228 229 230 |
MODULE_AUTHOR("Texas Instruments"); MODULE_DESCRIPTION("DaVinci Watchdog Driver"); module_param(heartbeat, int, 0); MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat period in seconds from 1 to " __MODULE_STRING(MAX_HEARTBEAT) ", default " __MODULE_STRING(DEFAULT_HEARTBEAT)); MODULE_LICENSE("GPL"); |
843748123 watchdog: davinci... |
231 |
MODULE_ALIAS("platform:davinci-wdt"); |