Version:  2.0.40 2.2.26 2.4.37 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18

Linux/drivers/watchdog/davinci_wdt.c

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us