diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /arch/arm/mach-davinci/clock.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'arch/arm/mach-davinci/clock.c')
-rw-r--r-- | arch/arm/mach-davinci/clock.c | 298 |
1 files changed, 224 insertions, 74 deletions
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 83d54d50b5ea..bf6218ee94e1 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c | |||
@@ -17,8 +17,8 @@ | |||
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/delay.h> | ||
22 | 22 | ||
23 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
24 | 24 | ||
@@ -42,17 +42,16 @@ static void __clk_enable(struct clk *clk) | |||
42 | if (clk->parent) | 42 | if (clk->parent) |
43 | __clk_enable(clk->parent); | 43 | __clk_enable(clk->parent); |
44 | if (clk->usecount++ == 0 && (clk->flags & CLK_PSC)) | 44 | if (clk->usecount++ == 0 && (clk->flags & CLK_PSC)) |
45 | davinci_psc_config(psc_domain(clk), clk->psc_ctlr, | 45 | davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 1); |
46 | clk->lpsc, 1); | ||
47 | } | 46 | } |
48 | 47 | ||
49 | static void __clk_disable(struct clk *clk) | 48 | static void __clk_disable(struct clk *clk) |
50 | { | 49 | { |
51 | if (WARN_ON(clk->usecount == 0)) | 50 | if (WARN_ON(clk->usecount == 0)) |
52 | return; | 51 | return; |
53 | if (--clk->usecount == 0 && !(clk->flags & CLK_PLL)) | 52 | if (--clk->usecount == 0 && !(clk->flags & CLK_PLL) && |
54 | davinci_psc_config(psc_domain(clk), clk->psc_ctlr, | 53 | (clk->flags & CLK_PSC)) |
55 | clk->lpsc, 0); | 54 | davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 0); |
56 | if (clk->parent) | 55 | if (clk->parent) |
57 | __clk_disable(clk->parent); | 56 | __clk_disable(clk->parent); |
58 | } | 57 | } |
@@ -99,20 +98,75 @@ long clk_round_rate(struct clk *clk, unsigned long rate) | |||
99 | if (clk == NULL || IS_ERR(clk)) | 98 | if (clk == NULL || IS_ERR(clk)) |
100 | return -EINVAL; | 99 | return -EINVAL; |
101 | 100 | ||
101 | if (clk->round_rate) | ||
102 | return clk->round_rate(clk, rate); | ||
103 | |||
102 | return clk->rate; | 104 | return clk->rate; |
103 | } | 105 | } |
104 | EXPORT_SYMBOL(clk_round_rate); | 106 | EXPORT_SYMBOL(clk_round_rate); |
105 | 107 | ||
108 | /* Propagate rate to children */ | ||
109 | static void propagate_rate(struct clk *root) | ||
110 | { | ||
111 | struct clk *clk; | ||
112 | |||
113 | list_for_each_entry(clk, &root->children, childnode) { | ||
114 | if (clk->recalc) | ||
115 | clk->rate = clk->recalc(clk); | ||
116 | propagate_rate(clk); | ||
117 | } | ||
118 | } | ||
119 | |||
106 | int clk_set_rate(struct clk *clk, unsigned long rate) | 120 | int clk_set_rate(struct clk *clk, unsigned long rate) |
107 | { | 121 | { |
122 | unsigned long flags; | ||
123 | int ret = -EINVAL; | ||
124 | |||
108 | if (clk == NULL || IS_ERR(clk)) | 125 | if (clk == NULL || IS_ERR(clk)) |
109 | return -EINVAL; | 126 | return ret; |
127 | |||
128 | if (clk->set_rate) | ||
129 | ret = clk->set_rate(clk, rate); | ||
130 | |||
131 | spin_lock_irqsave(&clockfw_lock, flags); | ||
132 | if (ret == 0) { | ||
133 | if (clk->recalc) | ||
134 | clk->rate = clk->recalc(clk); | ||
135 | propagate_rate(clk); | ||
136 | } | ||
137 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
110 | 138 | ||
111 | /* changing the clk rate is not supported */ | 139 | return ret; |
112 | return -EINVAL; | ||
113 | } | 140 | } |
114 | EXPORT_SYMBOL(clk_set_rate); | 141 | EXPORT_SYMBOL(clk_set_rate); |
115 | 142 | ||
143 | int clk_set_parent(struct clk *clk, struct clk *parent) | ||
144 | { | ||
145 | unsigned long flags; | ||
146 | |||
147 | if (clk == NULL || IS_ERR(clk)) | ||
148 | return -EINVAL; | ||
149 | |||
150 | /* Cannot change parent on enabled clock */ | ||
151 | if (WARN_ON(clk->usecount)) | ||
152 | return -EINVAL; | ||
153 | |||
154 | mutex_lock(&clocks_mutex); | ||
155 | clk->parent = parent; | ||
156 | list_del_init(&clk->childnode); | ||
157 | list_add(&clk->childnode, &clk->parent->children); | ||
158 | mutex_unlock(&clocks_mutex); | ||
159 | |||
160 | spin_lock_irqsave(&clockfw_lock, flags); | ||
161 | if (clk->recalc) | ||
162 | clk->rate = clk->recalc(clk); | ||
163 | propagate_rate(clk); | ||
164 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | EXPORT_SYMBOL(clk_set_parent); | ||
169 | |||
116 | int clk_register(struct clk *clk) | 170 | int clk_register(struct clk *clk) |
117 | { | 171 | { |
118 | if (clk == NULL || IS_ERR(clk)) | 172 | if (clk == NULL || IS_ERR(clk)) |
@@ -123,16 +177,24 @@ int clk_register(struct clk *clk) | |||
123 | clk->name, clk->parent->name)) | 177 | clk->name, clk->parent->name)) |
124 | return -EINVAL; | 178 | return -EINVAL; |
125 | 179 | ||
180 | INIT_LIST_HEAD(&clk->children); | ||
181 | |||
126 | mutex_lock(&clocks_mutex); | 182 | mutex_lock(&clocks_mutex); |
127 | list_add_tail(&clk->node, &clocks); | 183 | list_add_tail(&clk->node, &clocks); |
184 | if (clk->parent) | ||
185 | list_add_tail(&clk->childnode, &clk->parent->children); | ||
128 | mutex_unlock(&clocks_mutex); | 186 | mutex_unlock(&clocks_mutex); |
129 | 187 | ||
130 | /* If rate is already set, use it */ | 188 | /* If rate is already set, use it */ |
131 | if (clk->rate) | 189 | if (clk->rate) |
132 | return 0; | 190 | return 0; |
133 | 191 | ||
192 | /* Else, see if there is a way to calculate it */ | ||
193 | if (clk->recalc) | ||
194 | clk->rate = clk->recalc(clk); | ||
195 | |||
134 | /* Otherwise, default to parent rate */ | 196 | /* Otherwise, default to parent rate */ |
135 | if (clk->parent) | 197 | else if (clk->parent) |
136 | clk->rate = clk->parent->rate; | 198 | clk->rate = clk->parent->rate; |
137 | 199 | ||
138 | return 0; | 200 | return 0; |
@@ -146,6 +208,7 @@ void clk_unregister(struct clk *clk) | |||
146 | 208 | ||
147 | mutex_lock(&clocks_mutex); | 209 | mutex_lock(&clocks_mutex); |
148 | list_del(&clk->node); | 210 | list_del(&clk->node); |
211 | list_del(&clk->childnode); | ||
149 | mutex_unlock(&clocks_mutex); | 212 | mutex_unlock(&clocks_mutex); |
150 | } | 213 | } |
151 | EXPORT_SYMBOL(clk_unregister); | 214 | EXPORT_SYMBOL(clk_unregister); |
@@ -166,11 +229,11 @@ static int __init clk_disable_unused(void) | |||
166 | continue; | 229 | continue; |
167 | 230 | ||
168 | /* ignore if in Disabled or SwRstDisable states */ | 231 | /* ignore if in Disabled or SwRstDisable states */ |
169 | if (!davinci_psc_is_clk_active(ck->psc_ctlr, ck->lpsc)) | 232 | if (!davinci_psc_is_clk_active(ck->gpsc, ck->lpsc)) |
170 | continue; | 233 | continue; |
171 | 234 | ||
172 | pr_info("Clocks: disable unused %s\n", ck->name); | 235 | pr_info("Clocks: disable unused %s\n", ck->name); |
173 | davinci_psc_config(psc_domain(ck), ck->psc_ctlr, ck->lpsc, 0); | 236 | davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc, 0); |
174 | } | 237 | } |
175 | spin_unlock_irq(&clockfw_lock); | 238 | spin_unlock_irq(&clockfw_lock); |
176 | 239 | ||
@@ -179,50 +242,62 @@ static int __init clk_disable_unused(void) | |||
179 | late_initcall(clk_disable_unused); | 242 | late_initcall(clk_disable_unused); |
180 | #endif | 243 | #endif |
181 | 244 | ||
182 | static void clk_sysclk_recalc(struct clk *clk) | 245 | static unsigned long clk_sysclk_recalc(struct clk *clk) |
183 | { | 246 | { |
184 | u32 v, plldiv; | 247 | u32 v, plldiv; |
185 | struct pll_data *pll; | 248 | struct pll_data *pll; |
249 | unsigned long rate = clk->rate; | ||
186 | 250 | ||
187 | /* If this is the PLL base clock, no more calculations needed */ | 251 | /* If this is the PLL base clock, no more calculations needed */ |
188 | if (clk->pll_data) | 252 | if (clk->pll_data) |
189 | return; | 253 | return rate; |
190 | 254 | ||
191 | if (WARN_ON(!clk->parent)) | 255 | if (WARN_ON(!clk->parent)) |
192 | return; | 256 | return rate; |
193 | 257 | ||
194 | clk->rate = clk->parent->rate; | 258 | rate = clk->parent->rate; |
195 | 259 | ||
196 | /* Otherwise, the parent must be a PLL */ | 260 | /* Otherwise, the parent must be a PLL */ |
197 | if (WARN_ON(!clk->parent->pll_data)) | 261 | if (WARN_ON(!clk->parent->pll_data)) |
198 | return; | 262 | return rate; |
199 | 263 | ||
200 | pll = clk->parent->pll_data; | 264 | pll = clk->parent->pll_data; |
201 | 265 | ||
202 | /* If pre-PLL, source clock is before the multiplier and divider(s) */ | 266 | /* If pre-PLL, source clock is before the multiplier and divider(s) */ |
203 | if (clk->flags & PRE_PLL) | 267 | if (clk->flags & PRE_PLL) |
204 | clk->rate = pll->input_rate; | 268 | rate = pll->input_rate; |
205 | 269 | ||
206 | if (!clk->div_reg) | 270 | if (!clk->div_reg) |
207 | return; | 271 | return rate; |
208 | 272 | ||
209 | v = __raw_readl(pll->base + clk->div_reg); | 273 | v = __raw_readl(pll->base + clk->div_reg); |
210 | if (v & PLLDIV_EN) { | 274 | if (v & PLLDIV_EN) { |
211 | plldiv = (v & PLLDIV_RATIO_MASK) + 1; | 275 | plldiv = (v & PLLDIV_RATIO_MASK) + 1; |
212 | if (plldiv) | 276 | if (plldiv) |
213 | clk->rate /= plldiv; | 277 | rate /= plldiv; |
214 | } | 278 | } |
279 | |||
280 | return rate; | ||
281 | } | ||
282 | |||
283 | static unsigned long clk_leafclk_recalc(struct clk *clk) | ||
284 | { | ||
285 | if (WARN_ON(!clk->parent)) | ||
286 | return clk->rate; | ||
287 | |||
288 | return clk->parent->rate; | ||
215 | } | 289 | } |
216 | 290 | ||
217 | static void __init clk_pll_init(struct clk *clk) | 291 | static unsigned long clk_pllclk_recalc(struct clk *clk) |
218 | { | 292 | { |
219 | u32 ctrl, mult = 1, prediv = 1, postdiv = 1; | 293 | u32 ctrl, mult = 1, prediv = 1, postdiv = 1; |
220 | u8 bypass; | 294 | u8 bypass; |
221 | struct pll_data *pll = clk->pll_data; | 295 | struct pll_data *pll = clk->pll_data; |
296 | unsigned long rate = clk->rate; | ||
222 | 297 | ||
223 | pll->base = IO_ADDRESS(pll->phys_base); | 298 | pll->base = IO_ADDRESS(pll->phys_base); |
224 | ctrl = __raw_readl(pll->base + PLLCTL); | 299 | ctrl = __raw_readl(pll->base + PLLCTL); |
225 | clk->rate = pll->input_rate = clk->parent->rate; | 300 | rate = pll->input_rate = clk->parent->rate; |
226 | 301 | ||
227 | if (ctrl & PLLCTL_PLLEN) { | 302 | if (ctrl & PLLCTL_PLLEN) { |
228 | bypass = 0; | 303 | bypass = 0; |
@@ -255,9 +330,9 @@ static void __init clk_pll_init(struct clk *clk) | |||
255 | } | 330 | } |
256 | 331 | ||
257 | if (!bypass) { | 332 | if (!bypass) { |
258 | clk->rate /= prediv; | 333 | rate /= prediv; |
259 | clk->rate *= mult; | 334 | rate *= mult; |
260 | clk->rate /= postdiv; | 335 | rate /= postdiv; |
261 | } | 336 | } |
262 | 337 | ||
263 | pr_debug("PLL%d: input = %lu MHz [ ", | 338 | pr_debug("PLL%d: input = %lu MHz [ ", |
@@ -270,56 +345,135 @@ static void __init clk_pll_init(struct clk *clk) | |||
270 | pr_debug("* %d ", mult); | 345 | pr_debug("* %d ", mult); |
271 | if (postdiv > 1) | 346 | if (postdiv > 1) |
272 | pr_debug("/ %d ", postdiv); | 347 | pr_debug("/ %d ", postdiv); |
273 | pr_debug("] --> %lu MHz output.\n", clk->rate / 1000000); | 348 | pr_debug("] --> %lu MHz output.\n", rate / 1000000); |
349 | |||
350 | return rate; | ||
274 | } | 351 | } |
275 | 352 | ||
276 | int __init davinci_clk_init(struct davinci_clk *clocks) | 353 | /** |
354 | * davinci_set_pllrate - set the output rate of a given PLL. | ||
355 | * | ||
356 | * Note: Currently tested to work with OMAP-L138 only. | ||
357 | * | ||
358 | * @pll: pll whose rate needs to be changed. | ||
359 | * @prediv: The pre divider value. Passing 0 disables the pre-divider. | ||
360 | * @pllm: The multiplier value. Passing 0 leads to multiply-by-one. | ||
361 | * @postdiv: The post divider value. Passing 0 disables the post-divider. | ||
362 | */ | ||
363 | int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, | ||
364 | unsigned int mult, unsigned int postdiv) | ||
365 | { | ||
366 | u32 ctrl; | ||
367 | unsigned int locktime; | ||
368 | unsigned long flags; | ||
369 | |||
370 | if (pll->base == NULL) | ||
371 | return -EINVAL; | ||
372 | |||
373 | /* | ||
374 | * PLL lock time required per OMAP-L138 datasheet is | ||
375 | * (2000 * prediv)/sqrt(pllm) OSCIN cycles. We approximate sqrt(pllm) | ||
376 | * as 4 and OSCIN cycle as 25 MHz. | ||
377 | */ | ||
378 | if (prediv) { | ||
379 | locktime = ((2000 * prediv) / 100); | ||
380 | prediv = (prediv - 1) | PLLDIV_EN; | ||
381 | } else { | ||
382 | locktime = PLL_LOCK_TIME; | ||
383 | } | ||
384 | if (postdiv) | ||
385 | postdiv = (postdiv - 1) | PLLDIV_EN; | ||
386 | if (mult) | ||
387 | mult = mult - 1; | ||
388 | |||
389 | /* Protect against simultaneous calls to PLL setting seqeunce */ | ||
390 | spin_lock_irqsave(&clockfw_lock, flags); | ||
391 | |||
392 | ctrl = __raw_readl(pll->base + PLLCTL); | ||
393 | |||
394 | /* Switch the PLL to bypass mode */ | ||
395 | ctrl &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN); | ||
396 | __raw_writel(ctrl, pll->base + PLLCTL); | ||
397 | |||
398 | udelay(PLL_BYPASS_TIME); | ||
399 | |||
400 | /* Reset and enable PLL */ | ||
401 | ctrl &= ~(PLLCTL_PLLRST | PLLCTL_PLLDIS); | ||
402 | __raw_writel(ctrl, pll->base + PLLCTL); | ||
403 | |||
404 | if (pll->flags & PLL_HAS_PREDIV) | ||
405 | __raw_writel(prediv, pll->base + PREDIV); | ||
406 | |||
407 | __raw_writel(mult, pll->base + PLLM); | ||
408 | |||
409 | if (pll->flags & PLL_HAS_POSTDIV) | ||
410 | __raw_writel(postdiv, pll->base + POSTDIV); | ||
411 | |||
412 | udelay(PLL_RESET_TIME); | ||
413 | |||
414 | /* Bring PLL out of reset */ | ||
415 | ctrl |= PLLCTL_PLLRST; | ||
416 | __raw_writel(ctrl, pll->base + PLLCTL); | ||
417 | |||
418 | udelay(locktime); | ||
419 | |||
420 | /* Remove PLL from bypass mode */ | ||
421 | ctrl |= PLLCTL_PLLEN; | ||
422 | __raw_writel(ctrl, pll->base + PLLCTL); | ||
423 | |||
424 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
425 | |||
426 | return 0; | ||
427 | } | ||
428 | EXPORT_SYMBOL(davinci_set_pllrate); | ||
429 | |||
430 | int __init davinci_clk_init(struct clk_lookup *clocks) | ||
277 | { | 431 | { |
278 | struct davinci_clk *c; | 432 | struct clk_lookup *c; |
279 | struct clk *clk; | 433 | struct clk *clk; |
434 | size_t num_clocks = 0; | ||
435 | |||
436 | for (c = clocks; c->clk; c++) { | ||
437 | clk = c->clk; | ||
280 | 438 | ||
281 | for (c = clocks; c->lk.clk; c++) { | 439 | if (!clk->recalc) { |
282 | clk = c->lk.clk; | ||
283 | 440 | ||
284 | if (clk->pll_data) | 441 | /* Check if clock is a PLL */ |
285 | clk_pll_init(clk); | 442 | if (clk->pll_data) |
443 | clk->recalc = clk_pllclk_recalc; | ||
286 | 444 | ||
287 | /* Calculate rates for PLL-derived clocks */ | 445 | /* Else, if it is a PLL-derived clock */ |
288 | else if (clk->flags & CLK_PLL) | 446 | else if (clk->flags & CLK_PLL) |
289 | clk_sysclk_recalc(clk); | 447 | clk->recalc = clk_sysclk_recalc; |
448 | |||
449 | /* Otherwise, it is a leaf clock (PSC clock) */ | ||
450 | else if (clk->parent) | ||
451 | clk->recalc = clk_leafclk_recalc; | ||
452 | } | ||
453 | |||
454 | if (clk->recalc) | ||
455 | clk->rate = clk->recalc(clk); | ||
290 | 456 | ||
291 | if (clk->lpsc) | 457 | if (clk->lpsc) |
292 | clk->flags |= CLK_PSC; | 458 | clk->flags |= CLK_PSC; |
293 | 459 | ||
294 | clkdev_add(&c->lk); | ||
295 | clk_register(clk); | 460 | clk_register(clk); |
461 | num_clocks++; | ||
296 | 462 | ||
297 | /* Turn on clocks that Linux doesn't otherwise manage */ | 463 | /* Turn on clocks that Linux doesn't otherwise manage */ |
298 | if (clk->flags & ALWAYS_ENABLED) | 464 | if (clk->flags & ALWAYS_ENABLED) |
299 | clk_enable(clk); | 465 | clk_enable(clk); |
300 | } | 466 | } |
301 | 467 | ||
302 | return 0; | 468 | clkdev_add_table(clocks, num_clocks); |
303 | } | ||
304 | |||
305 | #ifdef CONFIG_PROC_FS | ||
306 | #include <linux/proc_fs.h> | ||
307 | #include <linux/seq_file.h> | ||
308 | 469 | ||
309 | static void *davinci_ck_start(struct seq_file *m, loff_t *pos) | 470 | return 0; |
310 | { | ||
311 | return *pos < 1 ? (void *)1 : NULL; | ||
312 | } | 471 | } |
313 | 472 | ||
314 | static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos) | 473 | #ifdef CONFIG_DEBUG_FS |
315 | { | ||
316 | ++*pos; | ||
317 | return NULL; | ||
318 | } | ||
319 | 474 | ||
320 | static void davinci_ck_stop(struct seq_file *m, void *v) | 475 | #include <linux/debugfs.h> |
321 | { | 476 | #include <linux/seq_file.h> |
322 | } | ||
323 | 477 | ||
324 | #define CLKNAME_MAX 10 /* longest clock name */ | 478 | #define CLKNAME_MAX 10 /* longest clock name */ |
325 | #define NEST_DELTA 2 | 479 | #define NEST_DELTA 2 |
@@ -352,49 +506,45 @@ dump_clock(struct seq_file *s, unsigned nest, struct clk *parent) | |||
352 | /* REVISIT show device associations too */ | 506 | /* REVISIT show device associations too */ |
353 | 507 | ||
354 | /* cost is now small, but not linear... */ | 508 | /* cost is now small, but not linear... */ |
355 | list_for_each_entry(clk, &clocks, node) { | 509 | list_for_each_entry(clk, &parent->children, childnode) { |
356 | if (clk->parent == parent) | 510 | dump_clock(s, nest + NEST_DELTA, clk); |
357 | dump_clock(s, nest + NEST_DELTA, clk); | ||
358 | } | 511 | } |
359 | } | 512 | } |
360 | 513 | ||
361 | static int davinci_ck_show(struct seq_file *m, void *v) | 514 | static int davinci_ck_show(struct seq_file *m, void *v) |
362 | { | 515 | { |
363 | /* Show clock tree; we know the main oscillator is first. | 516 | struct clk *clk; |
364 | * We trust nonzero usecounts equate to PSC enables... | 517 | |
518 | /* | ||
519 | * Show clock tree; We trust nonzero usecounts equate to PSC enables... | ||
365 | */ | 520 | */ |
366 | mutex_lock(&clocks_mutex); | 521 | mutex_lock(&clocks_mutex); |
367 | if (!list_empty(&clocks)) | 522 | list_for_each_entry(clk, &clocks, node) |
368 | dump_clock(m, 0, list_first_entry(&clocks, struct clk, node)); | 523 | if (!clk->parent) |
524 | dump_clock(m, 0, clk); | ||
369 | mutex_unlock(&clocks_mutex); | 525 | mutex_unlock(&clocks_mutex); |
370 | 526 | ||
371 | return 0; | 527 | return 0; |
372 | } | 528 | } |
373 | 529 | ||
374 | static const struct seq_operations davinci_ck_op = { | ||
375 | .start = davinci_ck_start, | ||
376 | .next = davinci_ck_next, | ||
377 | .stop = davinci_ck_stop, | ||
378 | .show = davinci_ck_show | ||
379 | }; | ||
380 | |||
381 | static int davinci_ck_open(struct inode *inode, struct file *file) | 530 | static int davinci_ck_open(struct inode *inode, struct file *file) |
382 | { | 531 | { |
383 | return seq_open(file, &davinci_ck_op); | 532 | return single_open(file, davinci_ck_show, NULL); |
384 | } | 533 | } |
385 | 534 | ||
386 | static const struct file_operations proc_davinci_ck_operations = { | 535 | static const struct file_operations davinci_ck_operations = { |
387 | .open = davinci_ck_open, | 536 | .open = davinci_ck_open, |
388 | .read = seq_read, | 537 | .read = seq_read, |
389 | .llseek = seq_lseek, | 538 | .llseek = seq_lseek, |
390 | .release = seq_release, | 539 | .release = single_release, |
391 | }; | 540 | }; |
392 | 541 | ||
393 | static int __init davinci_ck_proc_init(void) | 542 | static int __init davinci_clk_debugfs_init(void) |
394 | { | 543 | { |
395 | proc_create("davinci_clocks", 0, NULL, &proc_davinci_ck_operations); | 544 | debugfs_create_file("davinci_clocks", S_IFREG | S_IRUGO, NULL, NULL, |
545 | &davinci_ck_operations); | ||
396 | return 0; | 546 | return 0; |
397 | 547 | ||
398 | } | 548 | } |
399 | __initcall(davinci_ck_proc_init); | 549 | device_initcall(davinci_clk_debugfs_init); |
400 | #endif /* CONFIG_DEBUG_PROC_FS */ | 550 | #endif /* CONFIG_DEBUG_FS */ |