xilinx_tb_wdt.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Xilinx AXI platforms watchdog timer driver.
  4. *
  5. * Author(s): Michal Simek <michal.simek@xilinx.com>
  6. * Shreenidhi Shedi <yesshedi@gmail.com>
  7. *
  8. * Copyright (c) 2011-2018 Xilinx Inc.
  9. */
  10. #include <common.h>
  11. #include <dm.h>
  12. #include <log.h>
  13. #include <wdt.h>
  14. #include <linux/err.h>
  15. #include <linux/io.h>
  16. #define XWT_CSR0_WRS_MASK 0x00000008 /* Reset status Mask */
  17. #define XWT_CSR0_WDS_MASK 0x00000004 /* Timer state Mask */
  18. #define XWT_CSR0_EWDT1_MASK 0x00000002 /* Enable bit 1 Mask*/
  19. #define XWT_CSRX_EWDT2_MASK 0x00000001 /* Enable bit 2 Mask */
  20. struct watchdog_regs {
  21. u32 twcsr0; /* 0x0 */
  22. u32 twcsr1; /* 0x4 */
  23. u32 tbr; /* 0x8 */
  24. };
  25. struct xlnx_wdt_plat {
  26. bool enable_once;
  27. struct watchdog_regs *regs;
  28. };
  29. static int xlnx_wdt_reset(struct udevice *dev)
  30. {
  31. u32 reg;
  32. struct xlnx_wdt_plat *plat = dev_get_plat(dev);
  33. debug("%s ", __func__);
  34. /* Read the current contents of TCSR0 */
  35. reg = readl(&plat->regs->twcsr0);
  36. /* Clear the watchdog WDS bit */
  37. if (reg & (XWT_CSR0_EWDT1_MASK | XWT_CSRX_EWDT2_MASK))
  38. writel(reg | XWT_CSR0_WDS_MASK, &plat->regs->twcsr0);
  39. return 0;
  40. }
  41. static int xlnx_wdt_stop(struct udevice *dev)
  42. {
  43. u32 reg;
  44. struct xlnx_wdt_plat *plat = dev_get_plat(dev);
  45. if (plat->enable_once) {
  46. debug("Can't stop Xilinx watchdog.\n");
  47. return -EBUSY;
  48. }
  49. /* Read the current contents of TCSR0 */
  50. reg = readl(&plat->regs->twcsr0);
  51. writel(reg & ~XWT_CSR0_EWDT1_MASK, &plat->regs->twcsr0);
  52. writel(~XWT_CSRX_EWDT2_MASK, &plat->regs->twcsr1);
  53. debug("Watchdog disabled!\n");
  54. return 0;
  55. }
  56. static int xlnx_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
  57. {
  58. struct xlnx_wdt_plat *plat = dev_get_plat(dev);
  59. debug("%s:\n", __func__);
  60. writel((XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK | XWT_CSR0_EWDT1_MASK),
  61. &plat->regs->twcsr0);
  62. writel(XWT_CSRX_EWDT2_MASK, &plat->regs->twcsr1);
  63. return 0;
  64. }
  65. static int xlnx_wdt_probe(struct udevice *dev)
  66. {
  67. debug("%s: Probing wdt%u\n", __func__, dev_seq(dev));
  68. return 0;
  69. }
  70. static int xlnx_wdt_of_to_plat(struct udevice *dev)
  71. {
  72. struct xlnx_wdt_plat *plat = dev_get_plat(dev);
  73. plat->regs = (struct watchdog_regs *)dev_read_addr(dev);
  74. if (IS_ERR(plat->regs))
  75. return PTR_ERR(plat->regs);
  76. plat->enable_once = dev_read_u32_default(dev, "xlnx,wdt-enable-once",
  77. 0);
  78. debug("%s: wdt-enable-once %d\n", __func__, plat->enable_once);
  79. return 0;
  80. }
  81. static const struct wdt_ops xlnx_wdt_ops = {
  82. .start = xlnx_wdt_start,
  83. .reset = xlnx_wdt_reset,
  84. .stop = xlnx_wdt_stop,
  85. };
  86. static const struct udevice_id xlnx_wdt_ids[] = {
  87. { .compatible = "xlnx,xps-timebase-wdt-1.00.a", },
  88. { .compatible = "xlnx,xps-timebase-wdt-1.01.a", },
  89. {},
  90. };
  91. U_BOOT_DRIVER(xlnx_wdt) = {
  92. .name = "xlnx_wdt",
  93. .id = UCLASS_WDT,
  94. .of_match = xlnx_wdt_ids,
  95. .probe = xlnx_wdt_probe,
  96. .plat_auto = sizeof(struct xlnx_wdt_plat),
  97. .of_to_plat = xlnx_wdt_of_to_plat,
  98. .ops = &xlnx_wdt_ops,
  99. };