/drivers/staging/tidspbridge/core/wdt.c

https://bitbucket.org/slukk/jb-tsm-kernel-4.2 · C · 150 lines · 102 code · 29 blank · 19 comment · 13 complexity · 79b4326a83238efdecbcfb83b88300b6 MD5 · raw file

  1. /*
  2. * wdt.c
  3. *
  4. * DSP-BIOS Bridge driver support functions for TI OMAP processors.
  5. *
  6. * IO dispatcher for a shared memory channel driver.
  7. *
  8. * Copyright (C) 2010 Texas Instruments, Inc.
  9. *
  10. * This package 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. * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  16. * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  17. */
  18. #include <linux/types.h>
  19. #include <dspbridge/dbdefs.h>
  20. #include <dspbridge/dspdeh.h>
  21. #include <dspbridge/dev.h>
  22. #include <dspbridge/_chnl_sm.h>
  23. #include <dspbridge/wdt.h>
  24. #include <dspbridge/host_os.h>
  25. #ifdef CONFIG_TIDSPBRIDGE_WDT3
  26. #define OMAP34XX_WDT3_BASE (L4_PER_34XX_BASE + 0x30000)
  27. static struct dsp_wdt_setting dsp_wdt;
  28. void dsp_wdt_dpc(unsigned long data)
  29. {
  30. struct deh_mgr *deh_mgr;
  31. dev_get_deh_mgr(dev_get_first(), &deh_mgr);
  32. if (deh_mgr)
  33. bridge_deh_notify(deh_mgr, DSP_WDTOVERFLOW, 0);
  34. }
  35. irqreturn_t dsp_wdt_isr(int irq, void *data)
  36. {
  37. u32 value;
  38. /* ack wdt3 interrupt */
  39. value = __raw_readl(dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
  40. __raw_writel(value, dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
  41. tasklet_schedule(&dsp_wdt.wdt3_tasklet);
  42. return IRQ_HANDLED;
  43. }
  44. int dsp_wdt_init(void)
  45. {
  46. int ret = 0;
  47. dsp_wdt.sm_wdt = NULL;
  48. dsp_wdt.reg_base = OMAP2_L4_IO_ADDRESS(OMAP34XX_WDT3_BASE);
  49. tasklet_init(&dsp_wdt.wdt3_tasklet, dsp_wdt_dpc, 0);
  50. dsp_wdt.fclk = clk_get(NULL, "wdt3_fck");
  51. if (dsp_wdt.fclk) {
  52. dsp_wdt.iclk = clk_get(NULL, "wdt3_ick");
  53. if (!dsp_wdt.iclk) {
  54. clk_put(dsp_wdt.fclk);
  55. dsp_wdt.fclk = NULL;
  56. ret = -EFAULT;
  57. }
  58. } else
  59. ret = -EFAULT;
  60. if (!ret)
  61. ret = request_irq(INT_34XX_WDT3_IRQ, dsp_wdt_isr, 0,
  62. "dsp_wdt", &dsp_wdt);
  63. /* Disable at this moment, it will be enabled when DSP starts */
  64. if (!ret)
  65. disable_irq(INT_34XX_WDT3_IRQ);
  66. return ret;
  67. }
  68. void dsp_wdt_sm_set(void *data)
  69. {
  70. dsp_wdt.sm_wdt = data;
  71. dsp_wdt.sm_wdt->wdt_overflow = CONFIG_TIDSPBRIDGE_WDT_TIMEOUT;
  72. }
  73. void dsp_wdt_exit(void)
  74. {
  75. free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt);
  76. tasklet_kill(&dsp_wdt.wdt3_tasklet);
  77. if (dsp_wdt.fclk)
  78. clk_put(dsp_wdt.fclk);
  79. if (dsp_wdt.iclk)
  80. clk_put(dsp_wdt.iclk);
  81. dsp_wdt.fclk = NULL;
  82. dsp_wdt.iclk = NULL;
  83. dsp_wdt.sm_wdt = NULL;
  84. dsp_wdt.reg_base = NULL;
  85. }
  86. void dsp_wdt_enable(bool enable)
  87. {
  88. u32 tmp;
  89. static bool wdt_enable;
  90. if (wdt_enable == enable || !dsp_wdt.fclk || !dsp_wdt.iclk)
  91. return;
  92. wdt_enable = enable;
  93. if (enable) {
  94. clk_enable(dsp_wdt.fclk);
  95. clk_enable(dsp_wdt.iclk);
  96. dsp_wdt.sm_wdt->wdt_setclocks = 1;
  97. tmp = __raw_readl(dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
  98. __raw_writel(tmp, dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
  99. enable_irq(INT_34XX_WDT3_IRQ);
  100. } else {
  101. disable_irq(INT_34XX_WDT3_IRQ);
  102. dsp_wdt.sm_wdt->wdt_setclocks = 0;
  103. clk_disable(dsp_wdt.iclk);
  104. clk_disable(dsp_wdt.fclk);
  105. }
  106. }
  107. #else
  108. void dsp_wdt_enable(bool enable)
  109. {
  110. }
  111. void dsp_wdt_sm_set(void *data)
  112. {
  113. }
  114. int dsp_wdt_init(void)
  115. {
  116. return 0;
  117. }
  118. void dsp_wdt_exit(void)
  119. {
  120. }
  121. #endif