RT-AC56 3.0.0.4.374.37 core
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / tidspbridge / core / wdt.c
blobf3794ee5c547e15860036324df0c3b807078d1a7
1 /*
2 * wdt.c
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
6 * IO dispatcher for a shared memory channel driver.
8 * Copyright (C) 2010 Texas Instruments, Inc.
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.
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.
18 #include <linux/types.h>
20 #include <dspbridge/dbdefs.h>
21 #include <dspbridge/dspdeh.h>
22 #include <dspbridge/dev.h>
23 #include <dspbridge/_chnl_sm.h>
24 #include <dspbridge/wdt.h>
25 #include <dspbridge/host_os.h>
28 #ifdef CONFIG_TIDSPBRIDGE_WDT3
30 #define OMAP34XX_WDT3_BASE (L4_PER_34XX_BASE + 0x30000)
32 static struct dsp_wdt_setting dsp_wdt;
34 void dsp_wdt_dpc(unsigned long data)
36 struct deh_mgr *deh_mgr;
37 dev_get_deh_mgr(dev_get_first(), &deh_mgr);
38 if (deh_mgr)
39 bridge_deh_notify(deh_mgr, DSP_WDTOVERFLOW, 0);
42 irqreturn_t dsp_wdt_isr(int irq, void *data)
44 u32 value;
45 /* ack wdt3 interrupt */
46 value = __raw_readl(dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
47 __raw_writel(value, dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
49 tasklet_schedule(&dsp_wdt.wdt3_tasklet);
50 return IRQ_HANDLED;
53 int dsp_wdt_init(void)
55 int ret = 0;
57 dsp_wdt.sm_wdt = NULL;
58 dsp_wdt.reg_base = OMAP2_L4_IO_ADDRESS(OMAP34XX_WDT3_BASE);
59 tasklet_init(&dsp_wdt.wdt3_tasklet, dsp_wdt_dpc, 0);
61 dsp_wdt.fclk = clk_get(NULL, "wdt3_fck");
63 if (dsp_wdt.fclk) {
64 dsp_wdt.iclk = clk_get(NULL, "wdt3_ick");
65 if (!dsp_wdt.iclk) {
66 clk_put(dsp_wdt.fclk);
67 dsp_wdt.fclk = NULL;
68 ret = -EFAULT;
70 } else
71 ret = -EFAULT;
73 if (!ret)
74 ret = request_irq(INT_34XX_WDT3_IRQ, dsp_wdt_isr, 0,
75 "dsp_wdt", &dsp_wdt);
77 /* Disable at this moment, it will be enabled when DSP starts */
78 if (!ret)
79 disable_irq(INT_34XX_WDT3_IRQ);
81 return ret;
84 void dsp_wdt_sm_set(void *data)
86 dsp_wdt.sm_wdt = data;
87 dsp_wdt.sm_wdt->wdt_overflow = CONFIG_TIDSPBRIDGE_WDT_TIMEOUT;
91 void dsp_wdt_exit(void)
93 free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt);
94 tasklet_kill(&dsp_wdt.wdt3_tasklet);
96 if (dsp_wdt.fclk)
97 clk_put(dsp_wdt.fclk);
98 if (dsp_wdt.iclk)
99 clk_put(dsp_wdt.iclk);
101 dsp_wdt.fclk = NULL;
102 dsp_wdt.iclk = NULL;
103 dsp_wdt.sm_wdt = NULL;
104 dsp_wdt.reg_base = NULL;
107 void dsp_wdt_enable(bool enable)
109 u32 tmp;
110 static bool wdt_enable;
112 if (wdt_enable == enable || !dsp_wdt.fclk || !dsp_wdt.iclk)
113 return;
115 wdt_enable = enable;
117 if (enable) {
118 clk_enable(dsp_wdt.fclk);
119 clk_enable(dsp_wdt.iclk);
120 dsp_wdt.sm_wdt->wdt_setclocks = 1;
121 tmp = __raw_readl(dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
122 __raw_writel(tmp, dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
123 enable_irq(INT_34XX_WDT3_IRQ);
124 } else {
125 disable_irq(INT_34XX_WDT3_IRQ);
126 dsp_wdt.sm_wdt->wdt_setclocks = 0;
127 clk_disable(dsp_wdt.iclk);
128 clk_disable(dsp_wdt.fclk);
132 #else
133 void dsp_wdt_enable(bool enable)
137 void dsp_wdt_sm_set(void *data)
141 int dsp_wdt_init(void)
143 return 0;
146 void dsp_wdt_exit(void)
149 #endif