1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#define L4_34XX_BASE 0x48000000
20
21#include <linux/types.h>
22
23
24#include <dspbridge/host_os.h>
25#include <plat/dmtimer.h>
26#include <linux/platform_data/asoc-ti-mcbsp.h>
27
28
29#include <dspbridge/dbdefs.h>
30#include <dspbridge/drv.h>
31#include <dspbridge/dev.h>
32#include "_tiomap.h"
33
34
35#include <dspbridge/clk.h>
36
37
38
39#define OMAP_SSI_OFFSET 0x58000
40#define OMAP_SSI_SIZE 0x1000
41#define OMAP_SSI_SYSCONFIG_OFFSET 0x10
42
43#define SSI_AUTOIDLE (1 << 0)
44#define SSI_SIDLE_SMARTIDLE (2 << 3)
45#define SSI_MIDLE_NOIDLE (1 << 12)
46
47
48#define IVA2_CLK 0
49#define GPT_CLK 1
50#define WDT_CLK 2
51#define MCBSP_CLK 3
52#define SSI_CLK 4
53
54
55#define DMT_ID(id) ((id) + 4)
56#define DM_TIMER_CLOCKS 4
57
58
59#define MCBSP_ID(id) ((id) - 6)
60
61static struct omap_dm_timer *timer[4];
62
63struct clk *iva2_clk;
64
65struct dsp_ssi {
66 struct clk *sst_fck;
67 struct clk *ssr_fck;
68 struct clk *ick;
69};
70
71static struct dsp_ssi ssi;
72
73static u32 dsp_clocks;
74
75static inline u32 is_dsp_clk_active(u32 clk, u8 id)
76{
77 return clk & (1 << id);
78}
79
80static inline void set_dsp_clk_active(u32 *clk, u8 id)
81{
82 *clk |= (1 << id);
83}
84
85static inline void set_dsp_clk_inactive(u32 *clk, u8 id)
86{
87 *clk &= ~(1 << id);
88}
89
90static s8 get_clk_type(u8 id)
91{
92 s8 type;
93
94 if (id == DSP_CLK_IVA2)
95 type = IVA2_CLK;
96 else if (id <= DSP_CLK_GPT8)
97 type = GPT_CLK;
98 else if (id == DSP_CLK_WDT3)
99 type = WDT_CLK;
100 else if (id <= DSP_CLK_MCBSP5)
101 type = MCBSP_CLK;
102 else if (id == DSP_CLK_SSI)
103 type = SSI_CLK;
104 else
105 type = -1;
106
107 return type;
108}
109
110
111
112
113
114
115void dsp_clk_exit(void)
116{
117 int i;
118
119 dsp_clock_disable_all(dsp_clocks);
120
121 for (i = 0; i < DM_TIMER_CLOCKS; i++)
122 omap_dm_timer_free(timer[i]);
123
124 clk_unprepare(iva2_clk);
125 clk_put(iva2_clk);
126 clk_unprepare(ssi.sst_fck);
127 clk_put(ssi.sst_fck);
128 clk_unprepare(ssi.ssr_fck);
129 clk_put(ssi.ssr_fck);
130 clk_unprepare(ssi.ick);
131 clk_put(ssi.ick);
132}
133
134
135
136
137
138
139void dsp_clk_init(void)
140{
141 static struct platform_device dspbridge_device;
142 int i, id;
143
144 dspbridge_device.dev.bus = &platform_bus_type;
145
146 for (i = 0, id = 5; i < DM_TIMER_CLOCKS; i++, id++)
147 timer[i] = omap_dm_timer_request_specific(id);
148
149 iva2_clk = clk_get(&dspbridge_device.dev, "iva2_ck");
150 if (IS_ERR(iva2_clk))
151 dev_err(bridge, "failed to get iva2 clock %p\n", iva2_clk);
152 else
153 clk_prepare(iva2_clk);
154
155 ssi.sst_fck = clk_get(&dspbridge_device.dev, "ssi_sst_fck");
156 ssi.ssr_fck = clk_get(&dspbridge_device.dev, "ssi_ssr_fck");
157 ssi.ick = clk_get(&dspbridge_device.dev, "ssi_ick");
158
159 if (IS_ERR(ssi.sst_fck) || IS_ERR(ssi.ssr_fck) || IS_ERR(ssi.ick)) {
160 dev_err(bridge, "failed to get ssi: sst %p, ssr %p, ick %p\n",
161 ssi.sst_fck, ssi.ssr_fck, ssi.ick);
162 } else {
163 clk_prepare(ssi.sst_fck);
164 clk_prepare(ssi.ssr_fck);
165 clk_prepare(ssi.ick);
166 }
167}
168
169
170
171
172
173
174
175
176
177void dsp_gpt_wait_overflow(short int clk_id, unsigned int load)
178{
179 struct omap_dm_timer *gpt = timer[clk_id - 1];
180 unsigned long timeout;
181
182 if (!gpt)
183 return;
184
185
186 omap_dm_timer_set_int_enable(gpt, OMAP_TIMER_INT_OVERFLOW);
187
188
189
190
191
192 omap_dm_timer_set_load_start(gpt, 0, load);
193
194
195 udelay(80);
196
197 timeout = msecs_to_jiffies(5);
198
199 while (!(omap_dm_timer_read_status(gpt) & OMAP_TIMER_INT_OVERFLOW)) {
200 if (time_is_after_jiffies(timeout)) {
201 pr_err("%s: GPTimer interrupt failed\n", __func__);
202 break;
203 }
204 }
205}
206
207
208
209
210
211
212
213int dsp_clk_enable(enum dsp_clk_id clk_id)
214{
215 int status = 0;
216
217 if (is_dsp_clk_active(dsp_clocks, clk_id)) {
218 dev_err(bridge, "WARN: clock id %d already enabled\n", clk_id);
219 goto out;
220 }
221
222 switch (get_clk_type(clk_id)) {
223 case IVA2_CLK:
224 clk_enable(iva2_clk);
225 break;
226 case GPT_CLK:
227 status = omap_dm_timer_start(timer[clk_id - 1]);
228 break;
229#ifdef CONFIG_OMAP_MCBSP
230 case MCBSP_CLK:
231 omap_mcbsp_request(MCBSP_ID(clk_id));
232 omap2_mcbsp_set_clks_src(MCBSP_ID(clk_id), MCBSP_CLKS_PAD_SRC);
233 break;
234#endif
235 case WDT_CLK:
236 dev_err(bridge, "ERROR: DSP requested to enable WDT3 clk\n");
237 break;
238 case SSI_CLK:
239 clk_enable(ssi.sst_fck);
240 clk_enable(ssi.ssr_fck);
241 clk_enable(ssi.ick);
242
243
244
245
246
247
248
249
250 ssi_clk_prepare(true);
251 break;
252 default:
253 dev_err(bridge, "Invalid clock id for enable\n");
254 status = -EPERM;
255 }
256
257 if (!status)
258 set_dsp_clk_active(&dsp_clocks, clk_id);
259
260out:
261 return status;
262}
263
264
265
266
267
268
269
270u32 dsp_clock_enable_all(u32 dsp_per_clocks)
271{
272 u32 clk_id;
273 u32 status = -EPERM;
274
275 for (clk_id = 0; clk_id < DSP_CLK_NOT_DEFINED; clk_id++) {
276 if (is_dsp_clk_active(dsp_per_clocks, clk_id))
277 status = dsp_clk_enable(clk_id);
278 }
279
280 return status;
281}
282
283
284
285
286
287
288
289int dsp_clk_disable(enum dsp_clk_id clk_id)
290{
291 int status = 0;
292
293 if (!is_dsp_clk_active(dsp_clocks, clk_id)) {
294 dev_err(bridge, "ERR: clock id %d already disabled\n", clk_id);
295 goto out;
296 }
297
298 switch (get_clk_type(clk_id)) {
299 case IVA2_CLK:
300 clk_disable(iva2_clk);
301 break;
302 case GPT_CLK:
303 status = omap_dm_timer_stop(timer[clk_id - 1]);
304 break;
305#ifdef CONFIG_OMAP_MCBSP
306 case MCBSP_CLK:
307 omap2_mcbsp_set_clks_src(MCBSP_ID(clk_id), MCBSP_CLKS_PRCM_SRC);
308 omap_mcbsp_free(MCBSP_ID(clk_id));
309 break;
310#endif
311 case WDT_CLK:
312 dev_err(bridge, "ERROR: DSP requested to disable WDT3 clk\n");
313 break;
314 case SSI_CLK:
315 ssi_clk_prepare(false);
316 ssi_clk_prepare(false);
317 clk_disable(ssi.sst_fck);
318 clk_disable(ssi.ssr_fck);
319 clk_disable(ssi.ick);
320 break;
321 default:
322 dev_err(bridge, "Invalid clock id for disable\n");
323 status = -EPERM;
324 }
325
326 if (!status)
327 set_dsp_clk_inactive(&dsp_clocks, clk_id);
328
329out:
330 return status;
331}
332
333
334
335
336
337
338
339
340
341u32 dsp_clock_disable_all(u32 dsp_per_clocks)
342{
343 u32 clk_id;
344 u32 status = -EPERM;
345
346 for (clk_id = 0; clk_id < DSP_CLK_NOT_DEFINED; clk_id++) {
347 if (is_dsp_clk_active(dsp_per_clocks, clk_id))
348 status = dsp_clk_disable(clk_id);
349 }
350
351 return status;
352}
353
354u32 dsp_clk_get_iva2_rate(void)
355{
356 u32 clk_speed_khz;
357
358 clk_speed_khz = clk_get_rate(iva2_clk);
359 clk_speed_khz /= 1000;
360 dev_dbg(bridge, "%s: clk speed Khz = %d\n", __func__, clk_speed_khz);
361
362 return clk_speed_khz;
363}
364
365void ssi_clk_prepare(bool FLAG)
366{
367 void __iomem *ssi_base;
368 unsigned int value;
369
370 ssi_base = ioremap(L4_34XX_BASE + OMAP_SSI_OFFSET, OMAP_SSI_SIZE);
371 if (!ssi_base) {
372 pr_err("%s: error, SSI not configured\n", __func__);
373 return;
374 }
375
376 if (FLAG) {
377
378
379
380 value = SSI_AUTOIDLE | SSI_SIDLE_SMARTIDLE | SSI_MIDLE_NOIDLE;
381 } else {
382
383
384
385 value = SSI_AUTOIDLE;
386 }
387
388 __raw_writel(value, ssi_base + OMAP_SSI_SYSCONFIG_OFFSET);
389 iounmap(ssi_base);
390}
391
392