aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-26 20:42:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-26 20:42:18 -0400
commitb0189cd087aa82bd23277cb5c8960ab030e13e5c (patch)
tree7b1a4c152cd62ce136fd5b0e4379d58eb2244e66 /arch/arm/plat-omap
parent69f1d1a6acbaa7d83ef3f4ee26209c58cd000204 (diff)
parentbc574e190d3fbed37d724e33a16aee326d6f2ac4 (diff)
Merge branch 'next/devel2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/linux-arm-soc
* 'next/devel2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/linux-arm-soc: (47 commits) OMAP: Add debugfs node to show the summary of all clocks OMAP2+: hwmod: Follow the recommended PRCM module enable sequence OMAP2+: clock: allow per-SoC clock init code to prevent clockdomain calls from clock code OMAP2+: clockdomain: Add per clkdm lock to prevent concurrent state programming OMAP2+: PM: idle clkdms only if already in idle OMAP2+: clockdomain: add clkdm_in_hwsup() OMAP2+: clockdomain: Add 2 APIs to control clockdomain from hwmod framework OMAP: clockdomain: Remove redundant call to pwrdm_wait_transition() OMAP4: hwmod: Introduce the module control in hwmod control OMAP4: cm: Add two new APIs for modulemode control OMAP4: hwmod data: Add modulemode entry in omap_hwmod structure OMAP4: hwmod data: Add PRM context register offset OMAP4: prm: Remove deprecated functions OMAP4: prm: Replace warm reset API with the offset based version OMAP4: hwmod: Replace RSTCTRL absolute address with offset macros OMAP: hwmod: Wait the idle status to be disabled OMAP4: hwmod: Replace CLKCTRL absolute address with offset macros OMAP2+: hwmod: Init clkdm field at boot time OMAP4: hwmod data: Add clock domain attribute OMAP4: clock data: Add missing divider selection for auxclks ...
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r--arch/arm/plat-omap/clock.c39
-rw-r--r--arch/arm/plat-omap/include/plat/irqs.h12
-rw-r--r--arch/arm/plat-omap/include/plat/omap_hwmod.h14
-rw-r--r--arch/arm/plat-omap/omap_device.c85
4 files changed, 111 insertions, 39 deletions
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 964704f40bbe..3ba4d11ca73e 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -475,8 +475,41 @@ int __init clk_init(struct clk_functions * custom_clocks)
475/* 475/*
476 * debugfs support to trace clock tree hierarchy and attributes 476 * debugfs support to trace clock tree hierarchy and attributes
477 */ 477 */
478
479#include <linux/debugfs.h>
480#include <linux/seq_file.h>
481
478static struct dentry *clk_debugfs_root; 482static struct dentry *clk_debugfs_root;
479 483
484static int clk_dbg_show_summary(struct seq_file *s, void *unused)
485{
486 struct clk *c;
487 struct clk *pa;
488
489 seq_printf(s, "%-30s %-30s %-10s %s\n",
490 "clock-name", "parent-name", "rate", "use-count");
491
492 list_for_each_entry(c, &clocks, node) {
493 pa = c->parent;
494 seq_printf(s, "%-30s %-30s %-10lu %d\n",
495 c->name, pa ? pa->name : "none", c->rate, c->usecount);
496 }
497
498 return 0;
499}
500
501static int clk_dbg_open(struct inode *inode, struct file *file)
502{
503 return single_open(file, clk_dbg_show_summary, inode->i_private);
504}
505
506static const struct file_operations debug_clock_fops = {
507 .open = clk_dbg_open,
508 .read = seq_read,
509 .llseek = seq_lseek,
510 .release = single_release,
511};
512
480static int clk_debugfs_register_one(struct clk *c) 513static int clk_debugfs_register_one(struct clk *c)
481{ 514{
482 int err; 515 int err;
@@ -545,6 +578,12 @@ static int __init clk_debugfs_init(void)
545 if (err) 578 if (err)
546 goto err_out; 579 goto err_out;
547 } 580 }
581
582 d = debugfs_create_file("summary", S_IRUGO,
583 d, NULL, &debug_clock_fops);
584 if (!d)
585 return -ENOMEM;
586
548 return 0; 587 return 0;
549err_out: 588err_out:
550 debugfs_remove_recursive(clk_debugfs_root); 589 debugfs_remove_recursive(clk_debugfs_root);
diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h
index c88432005665..926d25c780f3 100644
--- a/arch/arm/plat-omap/include/plat/irqs.h
+++ b/arch/arm/plat-omap/include/plat/irqs.h
@@ -407,11 +407,19 @@
407#endif 407#endif
408#define TWL6030_IRQ_END (TWL6030_IRQ_BASE + TWL6030_BASE_NR_IRQS) 408#define TWL6030_IRQ_END (TWL6030_IRQ_BASE + TWL6030_BASE_NR_IRQS)
409 409
410#define TWL6040_CODEC_IRQ_BASE TWL6030_IRQ_END
411#ifdef CONFIG_TWL6040_CODEC
412#define TWL6040_CODEC_NR_IRQS 6
413#else
414#define TWL6040_CODEC_NR_IRQS 0
415#endif
416#define TWL6040_CODEC_IRQ_END (TWL6040_CODEC_IRQ_BASE + TWL6040_CODEC_NR_IRQS)
417
410/* Total number of interrupts depends on the enabled blocks above */ 418/* Total number of interrupts depends on the enabled blocks above */
411#if (TWL4030_GPIO_IRQ_END > TWL6030_IRQ_END) 419#if (TWL4030_GPIO_IRQ_END > TWL6040_CODEC_IRQ_END)
412#define TWL_IRQ_END TWL4030_GPIO_IRQ_END 420#define TWL_IRQ_END TWL4030_GPIO_IRQ_END
413#else 421#else
414#define TWL_IRQ_END TWL6030_IRQ_END 422#define TWL_IRQ_END TWL6040_CODEC_IRQ_END
415#endif 423#endif
416 424
417/* GPMC related */ 425/* GPMC related */
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index fafdfe3c8d4e..0e329ca88a70 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -2,6 +2,7 @@
2 * omap_hwmod macros, structures 2 * omap_hwmod macros, structures
3 * 3 *
4 * Copyright (C) 2009-2011 Nokia Corporation 4 * Copyright (C) 2009-2011 Nokia Corporation
5 * Copyright (C) 2011 Texas Instruments, Inc.
5 * Paul Walmsley 6 * Paul Walmsley
6 * 7 *
7 * Created in collaboration with (alphabetical order): Benoît Cousson, 8 * Created in collaboration with (alphabetical order): Benoît Cousson,
@@ -79,6 +80,11 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
79#define HWMOD_IDLEMODE_SMART (1 << 2) 80#define HWMOD_IDLEMODE_SMART (1 << 2)
80#define HWMOD_IDLEMODE_SMART_WKUP (1 << 3) 81#define HWMOD_IDLEMODE_SMART_WKUP (1 << 3)
81 82
83/* modulemode control type (SW or HW) */
84#define MODULEMODE_HWCTRL 1
85#define MODULEMODE_SWCTRL 2
86
87
82/** 88/**
83 * struct omap_hwmod_mux_info - hwmod specific mux configuration 89 * struct omap_hwmod_mux_info - hwmod specific mux configuration
84 * @pads: array of omap_device_pad entries 90 * @pads: array of omap_device_pad entries
@@ -360,9 +366,11 @@ struct omap_hwmod_omap2_prcm {
360 * @submodule_wkdep_bit: bit shift of the WKDEP range 366 * @submodule_wkdep_bit: bit shift of the WKDEP range
361 */ 367 */
362struct omap_hwmod_omap4_prcm { 368struct omap_hwmod_omap4_prcm {
363 void __iomem *clkctrl_reg; 369 u16 clkctrl_offs;
364 void __iomem *rstctrl_reg; 370 u16 rstctrl_offs;
371 u16 context_offs;
365 u8 submodule_wkdep_bit; 372 u8 submodule_wkdep_bit;
373 u8 modulemode;
366}; 374};
367 375
368 376
@@ -515,6 +523,8 @@ struct omap_hwmod {
515 const char *main_clk; 523 const char *main_clk;
516 struct clk *_clk; 524 struct clk *_clk;
517 struct omap_hwmod_opt_clk *opt_clks; 525 struct omap_hwmod_opt_clk *opt_clks;
526 char *clkdm_name;
527 struct clockdomain *clkdm;
518 char *vdd_name; 528 char *vdd_name;
519 struct voltagedomain *voltdm; 529 struct voltagedomain *voltdm;
520 struct omap_hwmod_ocp_if **masters; /* connect to *_IA */ 530 struct omap_hwmod_ocp_if **masters; /* connect to *_IA */
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 3471c650743b..b6b409744954 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -236,56 +236,71 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
236 return 0; 236 return 0;
237} 237}
238 238
239static void _add_clkdev(struct omap_device *od, const char *clk_alias,
240 const char *clk_name)
241{
242 struct clk *r;
243 struct clk_lookup *l;
244
245 if (!clk_alias || !clk_name)
246 return;
247
248 pr_debug("omap_device: %s: Creating %s -> %s\n",
249 dev_name(&od->pdev.dev), clk_alias, clk_name);
250
251 r = clk_get_sys(dev_name(&od->pdev.dev), clk_alias);
252 if (!IS_ERR(r)) {
253 pr_warning("omap_device: %s: alias %s already exists\n",
254 dev_name(&od->pdev.dev), clk_alias);
255 clk_put(r);
256 return;
257 }
258
259 r = omap_clk_get_by_name(clk_name);
260 if (IS_ERR(r)) {
261 pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
262 dev_name(&od->pdev.dev), clk_name);
263 return;
264 }
265
266 l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev.dev));
267 if (!l) {
268 pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
269 dev_name(&od->pdev.dev), clk_alias);
270 return;
271 }
272
273 clkdev_add(l);
274}
275
239/** 276/**
240 * _add_optional_clock_clkdev - Add clkdev entry for hwmod optional clocks 277 * _add_hwmod_clocks_clkdev - Add clkdev entry for hwmod optional clocks
278 * and main clock
241 * @od: struct omap_device *od 279 * @od: struct omap_device *od
280 * @oh: struct omap_hwmod *oh
242 * 281 *
243 * For every optional clock present per hwmod per omap_device, this function 282 * For the main clock and every optional clock present per hwmod per
244 * adds an entry in the clkdev table of the form <dev-id=dev_name, con-id=role> 283 * omap_device, this function adds an entry in the clkdev table of the
245 * if it does not exist already. 284 * form <dev-id=dev_name, con-id=role> if it does not exist already.
246 * 285 *
247 * The function is called from inside omap_device_build_ss(), after 286 * The function is called from inside omap_device_build_ss(), after
248 * omap_device_register. 287 * omap_device_register.
249 * 288 *
250 * This allows drivers to get a pointer to its optional clocks based on its role 289 * This allows drivers to get a pointer to its optional clocks based on its role
251 * by calling clk_get(<dev*>, <role>). 290 * by calling clk_get(<dev*>, <role>).
291 * In the case of the main clock, a "fck" alias is used.
252 * 292 *
253 * No return value. 293 * No return value.
254 */ 294 */
255static void _add_optional_clock_clkdev(struct omap_device *od, 295static void _add_hwmod_clocks_clkdev(struct omap_device *od,
256 struct omap_hwmod *oh) 296 struct omap_hwmod *oh)
257{ 297{
258 int i; 298 int i;
259 299
260 for (i = 0; i < oh->opt_clks_cnt; i++) { 300 _add_clkdev(od, "fck", oh->main_clk);
261 struct omap_hwmod_opt_clk *oc;
262 struct clk *r;
263 struct clk_lookup *l;
264
265 oc = &oh->opt_clks[i];
266
267 if (!oc->_clk)
268 continue;
269
270 r = clk_get_sys(dev_name(&od->pdev.dev), oc->role);
271 if (!IS_ERR(r))
272 continue; /* clkdev entry exists */
273 301
274 r = omap_clk_get_by_name((char *)oc->clk); 302 for (i = 0; i < oh->opt_clks_cnt; i++)
275 if (IS_ERR(r)) { 303 _add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk);
276 pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
277 dev_name(&od->pdev.dev), oc->clk);
278 continue;
279 }
280
281 l = clkdev_alloc(r, oc->role, dev_name(&od->pdev.dev));
282 if (!l) {
283 pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
284 dev_name(&od->pdev.dev), oc->role);
285 return;
286 }
287 clkdev_add(l);
288 }
289} 304}
290 305
291 306
@@ -492,7 +507,7 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
492 507
493 for (i = 0; i < oh_cnt; i++) { 508 for (i = 0; i < oh_cnt; i++) {
494 hwmods[i]->od = od; 509 hwmods[i]->od = od;
495 _add_optional_clock_clkdev(od, hwmods[i]); 510 _add_hwmod_clocks_clkdev(od, hwmods[i]);
496 } 511 }
497 512
498 if (ret) 513 if (ret)