• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/tidspbridge/core/
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
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>
26
27
28#ifdef CONFIG_TIDSPBRIDGE_WDT3
29
30#define OMAP34XX_WDT3_BASE 		(L4_PER_34XX_BASE + 0x30000)
31
32static struct dsp_wdt_setting dsp_wdt;
33
34void dsp_wdt_dpc(unsigned long data)
35{
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);
40}
41
42irqreturn_t dsp_wdt_isr(int irq, void *data)
43{
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);
48
49	tasklet_schedule(&dsp_wdt.wdt3_tasklet);
50	return IRQ_HANDLED;
51}
52
53int dsp_wdt_init(void)
54{
55	int ret = 0;
56
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);
60
61	dsp_wdt.fclk = clk_get(NULL, "wdt3_fck");
62
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;
69		}
70	} else
71		ret = -EFAULT;
72
73	if (!ret)
74		ret = request_irq(INT_34XX_WDT3_IRQ, dsp_wdt_isr, 0,
75							"dsp_wdt", &dsp_wdt);
76
77	/* Disable at this moment, it will be enabled when DSP starts */
78	if (!ret)
79		disable_irq(INT_34XX_WDT3_IRQ);
80
81	return ret;
82}
83
84void dsp_wdt_sm_set(void *data)
85{
86	dsp_wdt.sm_wdt = data;
87	dsp_wdt.sm_wdt->wdt_overflow = CONFIG_TIDSPBRIDGE_WDT_TIMEOUT;
88}
89
90
91void dsp_wdt_exit(void)
92{
93	free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt);
94	tasklet_kill(&dsp_wdt.wdt3_tasklet);
95
96	if (dsp_wdt.fclk)
97		clk_put(dsp_wdt.fclk);
98	if (dsp_wdt.iclk)
99		clk_put(dsp_wdt.iclk);
100
101	dsp_wdt.fclk = NULL;
102	dsp_wdt.iclk = NULL;
103	dsp_wdt.sm_wdt = NULL;
104	dsp_wdt.reg_base = NULL;
105}
106
107void dsp_wdt_enable(bool enable)
108{
109	u32 tmp;
110	static bool wdt_enable;
111
112	if (wdt_enable == enable || !dsp_wdt.fclk || !dsp_wdt.iclk)
113		return;
114
115	wdt_enable = enable;
116
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);
129	}
130}
131
132#else
133void dsp_wdt_enable(bool enable)
134{
135}
136
137void dsp_wdt_sm_set(void *data)
138{
139}
140
141int dsp_wdt_init(void)
142{
143	return 0;
144}
145
146void dsp_wdt_exit(void)
147{
148}
149#endif
150