Merge current mainline tree into linux-omap tree
[pandora-kernel.git] / arch / arm / mach-omap2 / board-n800-dsp.c
1 /*
2  * linux/arch/arm/mach-omap2/board-n800-dsp.c
3  *
4  * Copyright (C) 2006 Nokia Corporation.
5  *
6  * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  *
22  */
23
24 #include <linux/kernel.h>
25 #include <linux/device.h>
26 #include <linux/list.h>
27 #include <linux/err.h>
28 #include <linux/clk.h>
29
30 #include <asm/io.h>
31 #include <mach/clock.h>
32 #include <mach/board.h>
33 #include <mach/dsp_common.h>
34
35 #if     defined(CONFIG_OMAP_DSP)
36
37 /*
38  * dsp peripheral device: AUDIO
39  */
40 static struct dsp_kfunc_device n800_audio_device = {
41         .name    = "audio",
42         .type    = DSP_KFUNC_DEV_TYPE_AUDIO,
43         .enable  = n800_audio_enable,
44         .disable = n800_audio_disable,
45 };
46
47 /*
48  * dsp peripheral device: TIMER
49  */
50 static int dsp_timer_probe(struct dsp_kfunc_device *kdev, int stage)
51 {
52         char clockname[20];
53
54         strcpy(clockname, kdev->name);
55         strcat(clockname, "_fck");
56
57         kdev->fck = clk_get(NULL, clockname);
58         if (IS_ERR(kdev->fck)) {
59                 printk(KERN_ERR "couldn't acquire %s\n", clockname);
60                 return PTR_ERR(kdev->fck);
61         }
62         pr_debug("%s probed successfully\n", clockname);
63
64         strcpy(clockname, kdev->name);
65         strcat(clockname, "_ick");
66         kdev->ick = clk_get(NULL, clockname);
67         if (IS_ERR(kdev->ick)) {
68                 printk(KERN_ERR "couldn't acquire %s\n", clockname);
69                 goto fail;
70         }
71         pr_debug("%s probed successfully\n", clockname);
72
73         return 0;
74  fail:
75         clk_put(kdev->fck);
76
77         return PTR_ERR(kdev->ick);
78 }
79
80 static int dsp_timer_remove(struct dsp_kfunc_device *kdev, int stage)
81 {
82         clk_put(kdev->ick);
83         clk_put(kdev->fck);
84         pr_debug("%s removed successfully\n", kdev->name);
85         return 0;
86 }
87
88 static int dsp_timer_enable(struct dsp_kfunc_device *kdev, int stage)
89 {
90         pr_debug("%s enabled(%d)\n", kdev->name, stage);
91
92         spin_lock(&kdev->lock);
93
94         if (kdev->enabled)
95                 goto out;
96         kdev->enabled = 1;
97
98         clk_enable(kdev->fck);
99         clk_enable(kdev->ick);
100  out:
101         spin_unlock(&kdev->lock);
102
103         return 0;
104 }
105
106 static int dsp_timer_disable(struct dsp_kfunc_device *kdev, int stage)
107 {
108         pr_debug("%s disabled(%d)\n", kdev->name, stage);
109
110         spin_lock(&kdev->lock);
111
112         if (kdev->enabled == 0)
113                 goto out;
114         kdev->enabled = 0;
115
116         clk_disable(kdev->ick);
117         clk_disable(kdev->fck);
118  out:
119         spin_unlock(&kdev->lock);
120
121         return 0;
122 }
123
124 static struct dsp_kfunc_device n800_timer_device = {
125         .name    = "gpt5",
126         .type    = DSP_KFUNC_DEV_TYPE_COMMON,
127         .probe   = dsp_timer_probe,
128         .remove  = dsp_timer_remove,
129         .enable  = dsp_timer_enable,
130         .disable = dsp_timer_disable,
131 };
132
133 static struct dsp_kfunc_device *n800_kfunc_dev[] = {
134         &n800_audio_device,
135         &n800_timer_device,
136 };
137
138 void __init n800_dsp_init(void)
139 {
140         int i, ret;
141         struct dsp_kfunc_device **p = n800_kfunc_dev;
142
143         for (i = 0; i < ARRAY_SIZE(n800_kfunc_dev); i++) {
144                 ret = dsp_kfunc_device_register(p[i]);
145                 if (ret) {
146                         printk(KERN_ERR
147                                "KFUNC device registration failed: %s\n",
148                                p[i]->name);
149                 }
150         }
151 }
152
153 #else
154 void __init n800_dsp_init(void) { }
155 #endif  /* CONFIG_OMAP_DSP */