Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wdt.c
Go to the documentation of this 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 
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 #define OMAP34XX_WDT3_BASE (0x49000000 + 0x30000)
29 #define INT_34XX_WDT3_IRQ (36 + NR_IRQS)
30 
31 static struct dsp_wdt_setting dsp_wdt;
32 
33 void dsp_wdt_dpc(unsigned long data)
34 {
35  struct deh_mgr *deh_mgr;
36  dev_get_deh_mgr(dev_get_first(), &deh_mgr);
37  if (deh_mgr)
39 }
40 
41 irqreturn_t dsp_wdt_isr(int irq, void *data)
42 {
43  u32 value;
44  /* ack wdt3 interrupt */
45  value = __raw_readl(dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
46  __raw_writel(value, dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
47 
48  tasklet_schedule(&dsp_wdt.wdt3_tasklet);
49  return IRQ_HANDLED;
50 }
51 
52 int dsp_wdt_init(void)
53 {
54  int ret = 0;
55 
56  dsp_wdt.sm_wdt = NULL;
57  dsp_wdt.reg_base = ioremap(OMAP34XX_WDT3_BASE, SZ_4K);
58  if (!dsp_wdt.reg_base)
59  return -ENOMEM;
60 
61  tasklet_init(&dsp_wdt.wdt3_tasklet, dsp_wdt_dpc, 0);
62 
63  dsp_wdt.fclk = clk_get(NULL, "wdt3_fck");
64 
65  if (!IS_ERR(dsp_wdt.fclk)) {
66  dsp_wdt.iclk = clk_get(NULL, "wdt3_ick");
67  if (IS_ERR(dsp_wdt.iclk)) {
68  clk_put(dsp_wdt.fclk);
69  dsp_wdt.fclk = NULL;
70  ret = -EFAULT;
71  }
72  } else
73  ret = -EFAULT;
74 
75  if (!ret)
77  "dsp_wdt", &dsp_wdt);
78 
79  /* Disable at this moment, it will be enabled when DSP starts */
80  if (!ret)
82 
83  return ret;
84 }
85 
86 void dsp_wdt_sm_set(void *data)
87 {
88  dsp_wdt.sm_wdt = data;
89  dsp_wdt.sm_wdt->wdt_overflow = 5; /* in seconds */
90 }
91 
92 
93 void dsp_wdt_exit(void)
94 {
95  free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt);
96  tasklet_kill(&dsp_wdt.wdt3_tasklet);
97 
98  if (dsp_wdt.fclk)
99  clk_put(dsp_wdt.fclk);
100  if (dsp_wdt.iclk)
101  clk_put(dsp_wdt.iclk);
102 
103  dsp_wdt.fclk = NULL;
104  dsp_wdt.iclk = NULL;
105  dsp_wdt.sm_wdt = NULL;
106 
107  if (dsp_wdt.reg_base)
108  iounmap(dsp_wdt.reg_base);
109  dsp_wdt.reg_base = NULL;
110 }
111 
113 {
114  u32 tmp;
115  static bool wdt_enable;
116 
117  if (wdt_enable == enable || !dsp_wdt.fclk || !dsp_wdt.iclk)
118  return;
119 
120  wdt_enable = enable;
121 
122  if (enable) {
123  clk_enable(dsp_wdt.fclk);
124  clk_enable(dsp_wdt.iclk);
125  dsp_wdt.sm_wdt->wdt_setclocks = 1;
126  tmp = __raw_readl(dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
127  __raw_writel(tmp, dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
129  } else {
131  dsp_wdt.sm_wdt->wdt_setclocks = 0;
132  clk_disable(dsp_wdt.iclk);
133  clk_disable(dsp_wdt.fclk);
134  }
135 }