1 /* 2 * drivers/watchdog/orion_wdt.c 3 * 4 * Watchdog driver for Orion/Kirkwood processors 5 * 6 * Author: Sylver Bruneau <sylver.bruneau@googlemail.com> 7 * 8 * This file is licensed under the terms of the GNU General Public 9 * License version 2. This program is licensed "as is" without any 10 * warranty of any kind, whether express or implied. 11 */ 12 13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 14 15 #include <linux/module.h> 16 #include <linux/moduleparam.h> 17 #include <linux/types.h> 18 #include <linux/kernel.h> 19 #include <linux/platform_device.h> 20 #include <linux/watchdog.h> 21 #include <linux/interrupt.h> 22 #include <linux/io.h> 23 #include <linux/clk.h> 24 #include <linux/err.h> 25 #include <linux/of.h> 26 #include <linux/of_device.h> 27 28 /* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */ 29 #define ORION_RSTOUT_MASK_OFFSET 0x20108 30 31 /* Internal registers can be configured at any 1 MiB aligned address */ 32 #define INTERNAL_REGS_MASK ~(SZ_1M - 1) 33 34 /* 35 * Watchdog timer block registers. 36 */ 37 #define TIMER_CTRL 0x0000 38 #define TIMER_A370_STATUS 0x04 39 40 #define WDT_MAX_CYCLE_COUNT 0xffffffff 41 42 #define WDT_A370_RATIO_MASK(v) ((v) << 16) 43 #define WDT_A370_RATIO_SHIFT 5 44 #define WDT_A370_RATIO (1 << WDT_A370_RATIO_SHIFT) 45 46 #define WDT_AXP_FIXED_ENABLE_BIT BIT(10) 47 #define WDT_A370_EXPIRED BIT(31) 48 49 static bool nowayout = WATCHDOG_NOWAYOUT; 50 static int heartbeat = -1; /* module parameter (seconds) */ 51 52 struct orion_watchdog; 53 54 struct orion_watchdog_data { 55 int wdt_counter_offset; 56 int wdt_enable_bit; 57 int rstout_enable_bit; 58 int (*clock_init)(struct platform_device *, 59 struct orion_watchdog *); 60 int (*start)(struct watchdog_device *); 61 }; 62 63 struct orion_watchdog { 64 struct watchdog_device wdt; 65 void __iomem *reg; 66 void __iomem *rstout; 67 unsigned long clk_rate; 68 struct clk *clk; 69 const struct orion_watchdog_data *data; 70 }; 71 72 static int orion_wdt_clock_init(struct platform_device *pdev, 73 struct orion_watchdog *dev) 74 { 75 int ret; 76 77 dev->clk = clk_get(&pdev->dev, NULL); 78 if (IS_ERR(dev->clk)) 79 return PTR_ERR(dev->clk); 80 ret = clk_prepare_enable(dev->clk); 81 if (ret) { 82 clk_put(dev->clk); 83 return ret; 84 } 85 86 dev->clk_rate = clk_get_rate(dev->clk); 87 return 0; 88 } 89 90 static int armada370_wdt_clock_init(struct platform_device *pdev, 91 struct orion_watchdog *dev) 92 { 93 int ret; 94 95 dev->clk = clk_get(&pdev->dev, NULL); 96 if (IS_ERR(dev->clk)) 97 return PTR_ERR(dev->clk); 98 ret = clk_prepare_enable(dev->clk); 99 if (ret) { 100 clk_put(dev->clk); 101 return ret; 102 } 103 104 /* Setup watchdog input clock */ 105 atomic_io_modify(dev->reg + TIMER_CTRL, 106 WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT), 107 WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT)); 108 109 dev->clk_rate = clk_get_rate(dev->clk) / WDT_A370_RATIO; 110 return 0; 111 } 112 113 static int armadaxp_wdt_clock_init(struct platform_device *pdev, 114 struct orion_watchdog *dev) 115 { 116 int ret; 117 118 dev->clk = of_clk_get_by_name(pdev->dev.of_node, "fixed"); 119 if (IS_ERR(dev->clk)) 120 return PTR_ERR(dev->clk); 121 ret = clk_prepare_enable(dev->clk); 122 if (ret) { 123 clk_put(dev->clk); 124 return ret; 125 } 126 127 /* Enable the fixed watchdog clock input */ 128 atomic_io_modify(dev->reg + TIMER_CTRL, 129 WDT_AXP_FIXED_ENABLE_BIT, 130 WDT_AXP_FIXED_ENABLE_BIT); 131 132 dev->clk_rate = clk_get_rate(dev->clk); 133 return 0; 134 } 135 136 static int orion_wdt_ping(struct watchdog_device *wdt_dev) 137 { 138 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); 139 /* Reload watchdog duration */ 140 writel(dev->clk_rate * wdt_dev->timeout, 141 dev->reg + dev->data->wdt_counter_offset); 142 return 0; 143 } 144 145 static int armada370_start(struct watchdog_device *wdt_dev) 146 { 147 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); 148 149 /* Set watchdog duration */ 150 writel(dev->clk_rate * wdt_dev->timeout, 151 dev->reg + dev->data->wdt_counter_offset); 152 153 /* Clear the watchdog expiration bit */ 154 atomic_io_modify(dev->reg + TIMER_A370_STATUS, WDT_A370_EXPIRED, 0); 155 156 /* Enable watchdog timer */ 157 atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, 158 dev->data->wdt_enable_bit); 159 160 atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit, 161 dev->data->rstout_enable_bit); 162 return 0; 163 } 164 165 static int orion_start(struct watchdog_device *wdt_dev) 166 { 167 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); 168 169 /* Set watchdog duration */ 170 writel(dev->clk_rate * wdt_dev->timeout, 171 dev->reg + dev->data->wdt_counter_offset); 172 173 /* Enable watchdog timer */ 174 atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, 175 dev->data->wdt_enable_bit); 176 177 /* Enable reset on watchdog */ 178 atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit, 179 dev->data->rstout_enable_bit); 180 181 return 0; 182 } 183 184 static int orion_wdt_start(struct watchdog_device *wdt_dev) 185 { 186 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); 187 188 /* There are some per-SoC quirks to handle */ 189 return dev->data->start(wdt_dev); 190 } 191 192 static int orion_wdt_stop(struct watchdog_device *wdt_dev) 193 { 194 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); 195 196 /* Disable reset on watchdog */ 197 atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit, 0); 198 199 /* Disable watchdog timer */ 200 atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, 0); 201 202 return 0; 203 } 204 205 static int orion_wdt_enabled(struct orion_watchdog *dev) 206 { 207 bool enabled, running; 208 209 enabled = readl(dev->rstout) & dev->data->rstout_enable_bit; 210 running = readl(dev->reg + TIMER_CTRL) & dev->data->wdt_enable_bit; 211 212 return enabled && running; 213 } 214 215 static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev) 216 { 217 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); 218 return readl(dev->reg + dev->data->wdt_counter_offset) / dev->clk_rate; 219 } 220 221 static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev, 222 unsigned int timeout) 223 { 224 wdt_dev->timeout = timeout; 225 return 0; 226 } 227 228 static const struct watchdog_info orion_wdt_info = { 229 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, 230 .identity = "Orion Watchdog", 231 }; 232 233 static const struct watchdog_ops orion_wdt_ops = { 234 .owner = THIS_MODULE, 235 .start = orion_wdt_start, 236 .stop = orion_wdt_stop, 237 .ping = orion_wdt_ping, 238 .set_timeout = orion_wdt_set_timeout, 239 .get_timeleft = orion_wdt_get_timeleft, 240 }; 241 242 static irqreturn_t orion_wdt_irq(int irq, void *devid) 243 { 244 panic("Watchdog Timeout"); 245 return IRQ_HANDLED; 246 } 247 248 /* 249 * The original devicetree binding for this driver specified only 250 * one memory resource, so in order to keep DT backwards compatibility 251 * we try to fallback to a hardcoded register address, if the resource 252 * is missing from the devicetree. 253 */ 254 static void __iomem *orion_wdt_ioremap_rstout(struct platform_device *pdev, 255 phys_addr_t internal_regs) 256 { 257 struct resource *res; 258 phys_addr_t rstout; 259 260 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 261 if (res) 262 return devm_ioremap(&pdev->dev, res->start, 263 resource_size(res)); 264 265 /* This workaround works only for "orion-wdt", DT-enabled */ 266 if (!of_device_is_compatible(pdev->dev.of_node, "marvell,orion-wdt")) 267 return NULL; 268 269 rstout = internal_regs + ORION_RSTOUT_MASK_OFFSET; 270 271 WARN(1, FW_BUG "falling back to harcoded RSTOUT reg %pa\n", &rstout); 272 return devm_ioremap(&pdev->dev, rstout, 0x4); 273 } 274 275 static const struct orion_watchdog_data orion_data = { 276 .rstout_enable_bit = BIT(1), 277 .wdt_enable_bit = BIT(4), 278 .wdt_counter_offset = 0x24, 279 .clock_init = orion_wdt_clock_init, 280 .start = orion_start, 281 }; 282 283 static const struct orion_watchdog_data armada370_data = { 284 .rstout_enable_bit = BIT(8), 285 .wdt_enable_bit = BIT(8), 286 .wdt_counter_offset = 0x34, 287 .clock_init = armada370_wdt_clock_init, 288 .start = armada370_start, 289 }; 290 291 static const struct orion_watchdog_data armadaxp_data = { 292 .rstout_enable_bit = BIT(8), 293 .wdt_enable_bit = BIT(8), 294 .wdt_counter_offset = 0x34, 295 .clock_init = armadaxp_wdt_clock_init, 296 .start = armada370_start, 297 }; 298 299 static const struct of_device_id orion_wdt_of_match_table[] = { 300 { 301 .compatible = "marvell,orion-wdt", 302 .data = &orion_data, 303 }, 304 { 305 .compatible = "marvell,armada-370-wdt", 306 .data = &armada370_data, 307 }, 308 { 309 .compatible = "marvell,armada-xp-wdt", 310 .data = &armadaxp_data, 311 }, 312 {}, 313 }; 314 MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table); 315 316 static int orion_wdt_probe(struct platform_device *pdev) 317 { 318 struct orion_watchdog *dev; 319 const struct of_device_id *match; 320 unsigned int wdt_max_duration; /* (seconds) */ 321 struct resource *res; 322 int ret, irq; 323 324 dev = devm_kzalloc(&pdev->dev, sizeof(struct orion_watchdog), 325 GFP_KERNEL); 326 if (!dev) 327 return -ENOMEM; 328 329 match = of_match_device(orion_wdt_of_match_table, &pdev->dev); 330 if (!match) 331 /* Default legacy match */ 332 match = &orion_wdt_of_match_table[0]; 333 334 dev->wdt.info = &orion_wdt_info; 335 dev->wdt.ops = &orion_wdt_ops; 336 dev->wdt.min_timeout = 1; 337 dev->data = match->data; 338 339 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 340 if (!res) 341 return -ENODEV; 342 343 dev->reg = devm_ioremap(&pdev->dev, res->start, 344 resource_size(res)); 345 if (!dev->reg) 346 return -ENOMEM; 347 348 dev->rstout = orion_wdt_ioremap_rstout(pdev, res->start & 349 INTERNAL_REGS_MASK); 350 if (!dev->rstout) 351 return -ENODEV; 352 353 ret = dev->data->clock_init(pdev, dev); 354 if (ret) { 355 dev_err(&pdev->dev, "cannot initialize clock\n"); 356 return ret; 357 } 358 359 wdt_max_duration = WDT_MAX_CYCLE_COUNT / dev->clk_rate; 360 361 dev->wdt.timeout = wdt_max_duration; 362 dev->wdt.max_timeout = wdt_max_duration; 363 watchdog_init_timeout(&dev->wdt, heartbeat, &pdev->dev); 364 365 platform_set_drvdata(pdev, &dev->wdt); 366 watchdog_set_drvdata(&dev->wdt, dev); 367 368 /* 369 * Let's make sure the watchdog is fully stopped, unless it's 370 * explicitly enabled. This may be the case if the module was 371 * removed and re-insterted, or if the bootloader explicitly 372 * set a running watchdog before booting the kernel. 373 */ 374 if (!orion_wdt_enabled(dev)) 375 orion_wdt_stop(&dev->wdt); 376 377 /* Request the IRQ only after the watchdog is disabled */ 378 irq = platform_get_irq(pdev, 0); 379 if (irq > 0) { 380 /* 381 * Not all supported platforms specify an interrupt for the 382 * watchdog, so let's make it optional. 383 */ 384 ret = devm_request_irq(&pdev->dev, irq, orion_wdt_irq, 0, 385 pdev->name, dev); 386 if (ret < 0) { 387 dev_err(&pdev->dev, "failed to request IRQ\n"); 388 goto disable_clk; 389 } 390 } 391 392 watchdog_set_nowayout(&dev->wdt, nowayout); 393 ret = watchdog_register_device(&dev->wdt); 394 if (ret) 395 goto disable_clk; 396 397 pr_info("Initial timeout %d sec%s\n", 398 dev->wdt.timeout, nowayout ? ", nowayout" : ""); 399 return 0; 400 401 disable_clk: 402 clk_disable_unprepare(dev->clk); 403 clk_put(dev->clk); 404 return ret; 405 } 406 407 static int orion_wdt_remove(struct platform_device *pdev) 408 { 409 struct watchdog_device *wdt_dev = platform_get_drvdata(pdev); 410 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); 411 412 watchdog_unregister_device(wdt_dev); 413 clk_disable_unprepare(dev->clk); 414 clk_put(dev->clk); 415 return 0; 416 } 417 418 static void orion_wdt_shutdown(struct platform_device *pdev) 419 { 420 struct watchdog_device *wdt_dev = platform_get_drvdata(pdev); 421 orion_wdt_stop(wdt_dev); 422 } 423 424 static struct platform_driver orion_wdt_driver = { 425 .probe = orion_wdt_probe, 426 .remove = orion_wdt_remove, 427 .shutdown = orion_wdt_shutdown, 428 .driver = { 429 .owner = THIS_MODULE, 430 .name = "orion_wdt", 431 .of_match_table = orion_wdt_of_match_table, 432 }, 433 }; 434 435 module_platform_driver(orion_wdt_driver); 436 437 MODULE_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>"); 438 MODULE_DESCRIPTION("Orion Processor Watchdog"); 439 440 module_param(heartbeat, int, 0); 441 MODULE_PARM_DESC(heartbeat, "Initial watchdog heartbeat in seconds"); 442 443 module_param(nowayout, bool, 0); 444 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 445 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 446 447 MODULE_LICENSE("GPL"); 448 MODULE_ALIAS("platform:orion_wdt"); 449