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