watchdog-reset.c 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /* arch/arm/plat-samsung/watchdog-reset.c
  2. *
  3. * Copyright (c) 2008 Simtec Electronics
  4. * Ben Dooks <ben@simtec.co.uk>
  5. *
  6. * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
  7. *
  8. * Watchdog reset support for Samsung SoCs.
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. */
  14. #include <linux/clk.h>
  15. #include <linux/err.h>
  16. #include <linux/io.h>
  17. #include <linux/delay.h>
  18. #include <linux/of.h>
  19. #include <linux/of_address.h>
  20. #define S3C2410_WTCON 0x00
  21. #define S3C2410_WTDAT 0x04
  22. #define S3C2410_WTCNT 0x08
  23. #define S3C2410_WTCON_ENABLE (1 << 5)
  24. #define S3C2410_WTCON_DIV16 (0 << 3)
  25. #define S3C2410_WTCON_RSTEN (1 << 0)
  26. #define S3C2410_WTCON_PRESCALE(x) ((x) << 8)
  27. static void __iomem *wdt_base;
  28. static struct clk *wdt_clock;
  29. void samsung_wdt_reset(void)
  30. {
  31. if (!wdt_base) {
  32. pr_err("%s: wdt reset not initialized\n", __func__);
  33. /* delay to allow the serial port to show the message */
  34. mdelay(50);
  35. return;
  36. }
  37. if (!IS_ERR(wdt_clock))
  38. clk_prepare_enable(wdt_clock);
  39. /* disable watchdog, to be safe */
  40. __raw_writel(0, wdt_base + S3C2410_WTCON);
  41. /* put initial values into count and data */
  42. __raw_writel(0x80, wdt_base + S3C2410_WTCNT);
  43. __raw_writel(0x80, wdt_base + S3C2410_WTDAT);
  44. /* set the watchdog to go and reset... */
  45. __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV16 |
  46. S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x20),
  47. wdt_base + S3C2410_WTCON);
  48. /* wait for reset to assert... */
  49. mdelay(500);
  50. pr_err("Watchdog reset failed to assert reset\n");
  51. /* delay to allow the serial port to show the message */
  52. mdelay(50);
  53. }
  54. #ifdef CONFIG_OF
  55. static const struct of_device_id s3c2410_wdt_match[] = {
  56. { .compatible = "samsung,s3c2410-wdt" },
  57. {},
  58. };
  59. void __init samsung_wdt_reset_of_init(void)
  60. {
  61. struct device_node *np;
  62. np = of_find_matching_node(NULL, s3c2410_wdt_match);
  63. if (!np) {
  64. pr_err("%s: failed to find watchdog node\n", __func__);
  65. return;
  66. }
  67. wdt_base = of_iomap(np, 0);
  68. if (!wdt_base) {
  69. pr_err("%s: failed to map watchdog registers\n", __func__);
  70. return;
  71. }
  72. wdt_clock = of_clk_get(np, 0);
  73. }
  74. #endif
  75. void __init samsung_wdt_reset_init(void __iomem *base)
  76. {
  77. wdt_base = base;
  78. wdt_clock = clk_get(NULL, "watchdog");
  79. }