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 int davinci_wdt_probe(struct platform_device *pdev) 195 { 196 int ret = 0; 197 struct device *dev = &pdev->dev; 198 struct resource *wdt_mem; 199 struct watchdog_device *wdd; 200 struct davinci_wdt_device *davinci_wdt; 201 202 davinci_wdt = devm_kzalloc(dev, sizeof(*davinci_wdt), GFP_KERNEL); 203 if (!davinci_wdt) 204 return -ENOMEM; 205 206 davinci_wdt->clk = devm_clk_get(dev, NULL); 207 208 if (IS_ERR(davinci_wdt->clk)) { 209 if (PTR_ERR(davinci_wdt->clk) != -EPROBE_DEFER) 210 dev_err(&pdev->dev, "failed to get clock node\n"); 211 return PTR_ERR(davinci_wdt->clk); 212 } 213 214 ret = clk_prepare_enable(davinci_wdt->clk); 215 if (ret) { 216 dev_err(&pdev->dev, "failed to prepare clock\n"); 217 return ret; 218 } 219 220 platform_set_drvdata(pdev, davinci_wdt); 221 222 wdd = &davinci_wdt->wdd; 223 wdd->info = &davinci_wdt_info; 224 wdd->ops = &davinci_wdt_ops; 225 wdd->min_timeout = 1; 226 wdd->max_timeout = MAX_HEARTBEAT; 227 wdd->timeout = DEFAULT_HEARTBEAT; 228 wdd->parent = &pdev->dev; 229 230 watchdog_init_timeout(wdd, heartbeat, dev); 231 232 dev_info(dev, "heartbeat %d sec\n", wdd->timeout); 233 234 watchdog_set_drvdata(wdd, davinci_wdt); 235 watchdog_set_nowayout(wdd, 1); 236 watchdog_set_restart_priority(wdd, 128); 237 238 wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 239 davinci_wdt->base = devm_ioremap_resource(dev, wdt_mem); 240 if (IS_ERR(davinci_wdt->base)) { 241 ret = PTR_ERR(davinci_wdt->base); 242 goto err_clk_disable; 243 } 244 245 ret = watchdog_register_device(wdd); 246 if (ret) { 247 dev_err(dev, "cannot register watchdog device\n"); 248 goto err_clk_disable; 249 } 250 251 return 0; 252 253 err_clk_disable: 254 clk_disable_unprepare(davinci_wdt->clk); 255 256 return ret; 257 } 258 259 static int davinci_wdt_remove(struct platform_device *pdev) 260 { 261 struct davinci_wdt_device *davinci_wdt = platform_get_drvdata(pdev); 262 263 watchdog_unregister_device(&davinci_wdt->wdd); 264 clk_disable_unprepare(davinci_wdt->clk); 265 266 return 0; 267 } 268 269 static const struct of_device_id davinci_wdt_of_match[] = { 270 { .compatible = "ti,davinci-wdt", }, 271 {}, 272 }; 273 MODULE_DEVICE_TABLE(of, davinci_wdt_of_match); 274 275 static struct platform_driver platform_wdt_driver = { 276 .driver = { 277 .name = "davinci-wdt", 278 .of_match_table = davinci_wdt_of_match, 279 }, 280 .probe = davinci_wdt_probe, 281 .remove = davinci_wdt_remove, 282 }; 283 284 module_platform_driver(platform_wdt_driver); 285 286 MODULE_AUTHOR("Texas Instruments"); 287 MODULE_DESCRIPTION("DaVinci Watchdog Driver"); 288 289 module_param(heartbeat, int, 0); 290 MODULE_PARM_DESC(heartbeat, 291 "Watchdog heartbeat period in seconds from 1 to " 292 __MODULE_STRING(MAX_HEARTBEAT) ", default " 293 __MODULE_STRING(DEFAULT_HEARTBEAT)); 294 295 MODULE_LICENSE("GPL"); 296 MODULE_ALIAS("platform:davinci-wdt"); 297