aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap/omap_device.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/arm/plat-omap/omap_device.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'arch/arm/plat-omap/omap_device.c')
-rw-r--r--arch/arm/plat-omap/omap_device.c192
1 files changed, 150 insertions, 42 deletions
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index d2b160942ccc..49fc0df0c21f 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -82,20 +82,18 @@
82#include <linux/slab.h> 82#include <linux/slab.h>
83#include <linux/err.h> 83#include <linux/err.h>
84#include <linux/io.h> 84#include <linux/io.h>
85#include <linux/clk.h>
86#include <linux/clkdev.h>
87#include <linux/pm_runtime.h>
85 88
86#include <plat/omap_device.h> 89#include <plat/omap_device.h>
87#include <plat/omap_hwmod.h> 90#include <plat/omap_hwmod.h>
91#include <plat/clock.h>
88 92
89/* These parameters are passed to _omap_device_{de,}activate() */ 93/* These parameters are passed to _omap_device_{de,}activate() */
90#define USE_WAKEUP_LAT 0 94#define USE_WAKEUP_LAT 0
91#define IGNORE_WAKEUP_LAT 1 95#define IGNORE_WAKEUP_LAT 1
92 96
93/*
94 * OMAP_DEVICE_MAGIC: used to determine whether a struct omap_device
95 * obtained via container_of() is in fact a struct omap_device
96 */
97#define OMAP_DEVICE_MAGIC 0xf00dcafe
98
99/* Private functions */ 97/* Private functions */
100 98
101/** 99/**
@@ -243,10 +241,90 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
243 return container_of(pdev, struct omap_device, pdev); 241 return container_of(pdev, struct omap_device, pdev);
244} 242}
245 243
244/**
245 * _add_optional_clock_clkdev - Add clkdev entry for hwmod optional clocks
246 * @od: struct omap_device *od
247 *
248 * For every optional clock present per hwmod per omap_device, this function
249 * adds an entry in the clkdev table of the form <dev-id=dev_name, con-id=role>
250 * if it does not exist already.
251 *
252 * The function is called from inside omap_device_build_ss(), after
253 * omap_device_register.
254 *
255 * This allows drivers to get a pointer to its optional clocks based on its role
256 * by calling clk_get(<dev*>, <role>).
257 *
258 * No return value.
259 */
260static void _add_optional_clock_clkdev(struct omap_device *od,
261 struct omap_hwmod *oh)
262{
263 int i;
264
265 for (i = 0; i < oh->opt_clks_cnt; i++) {
266 struct omap_hwmod_opt_clk *oc;
267 struct clk *r;
268 struct clk_lookup *l;
269
270 oc = &oh->opt_clks[i];
271
272 if (!oc->_clk)
273 continue;
274
275 r = clk_get_sys(dev_name(&od->pdev.dev), oc->role);
276 if (!IS_ERR(r))
277 continue; /* clkdev entry exists */
278
279 r = omap_clk_get_by_name((char *)oc->clk);
280 if (IS_ERR(r)) {
281 pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
282 dev_name(&od->pdev.dev), oc->clk);
283 continue;
284 }
285
286 l = clkdev_alloc(r, oc->role, dev_name(&od->pdev.dev));
287 if (!l) {
288 pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
289 dev_name(&od->pdev.dev), oc->role);
290 return;
291 }
292 clkdev_add(l);
293 }
294}
295
246 296
247/* Public functions for use by core code */ 297/* Public functions for use by core code */
248 298
249/** 299/**
300 * omap_device_get_context_loss_count - get lost context count
301 * @od: struct omap_device *
302 *
303 * Using the primary hwmod, query the context loss count for this
304 * device.
305 *
306 * Callers should consider context for this device lost any time this
307 * function returns a value different than the value the caller got
308 * the last time it called this function.
309 *
310 * If any hwmods exist for the omap_device assoiated with @pdev,
311 * return the context loss counter for that hwmod, otherwise return
312 * zero.
313 */
314u32 omap_device_get_context_loss_count(struct platform_device *pdev)
315{
316 struct omap_device *od;
317 u32 ret = 0;
318
319 od = _find_by_pdev(pdev);
320
321 if (od->hwmods_cnt)
322 ret = omap_hwmod_get_context_loss_count(od->hwmods[0]);
323
324 return ret;
325}
326
327/**
250 * omap_device_count_resources - count number of struct resource entries needed 328 * omap_device_count_resources - count number of struct resource entries needed
251 * @od: struct omap_device * 329 * @od: struct omap_device *
252 * 330 *
@@ -257,12 +335,11 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
257 */ 335 */
258int omap_device_count_resources(struct omap_device *od) 336int omap_device_count_resources(struct omap_device *od)
259{ 337{
260 struct omap_hwmod *oh;
261 int c = 0; 338 int c = 0;
262 int i; 339 int i;
263 340
264 for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) 341 for (i = 0; i < od->hwmods_cnt; i++)
265 c += omap_hwmod_count_resources(oh); 342 c += omap_hwmod_count_resources(od->hwmods[i]);
266 343
267 pr_debug("omap_device: %s: counted %d total resources across %d " 344 pr_debug("omap_device: %s: counted %d total resources across %d "
268 "hwmods\n", od->pdev.name, c, od->hwmods_cnt); 345 "hwmods\n", od->pdev.name, c, od->hwmods_cnt);
@@ -289,12 +366,11 @@ int omap_device_count_resources(struct omap_device *od)
289 */ 366 */
290int omap_device_fill_resources(struct omap_device *od, struct resource *res) 367int omap_device_fill_resources(struct omap_device *od, struct resource *res)
291{ 368{
292 struct omap_hwmod *oh;
293 int c = 0; 369 int c = 0;
294 int i, r; 370 int i, r;
295 371
296 for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) { 372 for (i = 0; i < od->hwmods_cnt; i++) {
297 r = omap_hwmod_fill_resources(oh, res); 373 r = omap_hwmod_fill_resources(od->hwmods[i], res);
298 res += r; 374 res += r;
299 c += r; 375 c += r;
300 } 376 }
@@ -414,15 +490,15 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
414 od->pm_lats = pm_lats; 490 od->pm_lats = pm_lats;
415 od->pm_lats_cnt = pm_lats_cnt; 491 od->pm_lats_cnt = pm_lats_cnt;
416 492
417 od->magic = OMAP_DEVICE_MAGIC;
418
419 if (is_early_device) 493 if (is_early_device)
420 ret = omap_early_device_register(od); 494 ret = omap_early_device_register(od);
421 else 495 else
422 ret = omap_device_register(od); 496 ret = omap_device_register(od);
423 497
424 for (i = 0; i < oh_cnt; i++) 498 for (i = 0; i < oh_cnt; i++) {
425 hwmods[i]->od = od; 499 hwmods[i]->od = od;
500 _add_optional_clock_clkdev(od, hwmods[i]);
501 }
426 502
427 if (ret) 503 if (ret)
428 goto odbs_exit4; 504 goto odbs_exit4;
@@ -461,6 +537,42 @@ int omap_early_device_register(struct omap_device *od)
461 return 0; 537 return 0;
462} 538}
463 539
540static int _od_runtime_suspend(struct device *dev)
541{
542 struct platform_device *pdev = to_platform_device(dev);
543 int ret;
544
545 ret = pm_generic_runtime_suspend(dev);
546
547 if (!ret)
548 omap_device_idle(pdev);
549
550 return ret;
551}
552
553static int _od_runtime_idle(struct device *dev)
554{
555 return pm_generic_runtime_idle(dev);
556}
557
558static int _od_runtime_resume(struct device *dev)
559{
560 struct platform_device *pdev = to_platform_device(dev);
561
562 omap_device_enable(pdev);
563
564 return pm_generic_runtime_resume(dev);
565}
566
567static struct dev_power_domain omap_device_power_domain = {
568 .ops = {
569 .runtime_suspend = _od_runtime_suspend,
570 .runtime_idle = _od_runtime_idle,
571 .runtime_resume = _od_runtime_resume,
572 USE_PLATFORM_PM_SLEEP_OPS
573 }
574};
575
464/** 576/**
465 * omap_device_register - register an omap_device with one omap_hwmod 577 * omap_device_register - register an omap_device with one omap_hwmod
466 * @od: struct omap_device * to register 578 * @od: struct omap_device * to register
@@ -473,6 +585,8 @@ int omap_device_register(struct omap_device *od)
473{ 585{
474 pr_debug("omap_device: %s: registering\n", od->pdev.name); 586 pr_debug("omap_device: %s: registering\n", od->pdev.name);
475 587
588 od->pdev.dev.parent = &omap_device_parent;
589 od->pdev.dev.pwr_domain = &omap_device_power_domain;
476 return platform_device_register(&od->pdev); 590 return platform_device_register(&od->pdev);
477} 591}
478 592
@@ -566,7 +680,6 @@ int omap_device_shutdown(struct platform_device *pdev)
566{ 680{
567 int ret, i; 681 int ret, i;
568 struct omap_device *od; 682 struct omap_device *od;
569 struct omap_hwmod *oh;
570 683
571 od = _find_by_pdev(pdev); 684 od = _find_by_pdev(pdev);
572 685
@@ -579,8 +692,8 @@ int omap_device_shutdown(struct platform_device *pdev)
579 692
580 ret = _omap_device_deactivate(od, IGNORE_WAKEUP_LAT); 693 ret = _omap_device_deactivate(od, IGNORE_WAKEUP_LAT);
581 694
582 for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) 695 for (i = 0; i < od->hwmods_cnt; i++)
583 omap_hwmod_shutdown(oh); 696 omap_hwmod_shutdown(od->hwmods[i]);
584 697
585 od->_state = OMAP_DEVICE_STATE_SHUTDOWN; 698 od->_state = OMAP_DEVICE_STATE_SHUTDOWN;
586 699
@@ -627,18 +740,6 @@ int omap_device_align_pm_lat(struct platform_device *pdev,
627} 740}
628 741
629/** 742/**
630 * omap_device_is_valid - Check if pointer is a valid omap_device
631 * @od: struct omap_device *
632 *
633 * Return whether struct omap_device pointer @od points to a valid
634 * omap_device.
635 */
636bool omap_device_is_valid(struct omap_device *od)
637{
638 return (od && od->magic == OMAP_DEVICE_MAGIC);
639}
640
641/**
642 * omap_device_get_pwrdm - return the powerdomain * associated with @od 743 * omap_device_get_pwrdm - return the powerdomain * associated with @od
643 * @od: struct omap_device * 744 * @od: struct omap_device *
644 * 745 *
@@ -692,11 +793,10 @@ void __iomem *omap_device_get_rt_va(struct omap_device *od)
692 */ 793 */
693int omap_device_enable_hwmods(struct omap_device *od) 794int omap_device_enable_hwmods(struct omap_device *od)
694{ 795{
695 struct omap_hwmod *oh;
696 int i; 796 int i;
697 797
698 for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) 798 for (i = 0; i < od->hwmods_cnt; i++)
699 omap_hwmod_enable(oh); 799 omap_hwmod_enable(od->hwmods[i]);
700 800
701 /* XXX pass along return value here? */ 801 /* XXX pass along return value here? */
702 return 0; 802 return 0;
@@ -710,11 +810,10 @@ int omap_device_enable_hwmods(struct omap_device *od)
710 */ 810 */
711int omap_device_idle_hwmods(struct omap_device *od) 811int omap_device_idle_hwmods(struct omap_device *od)
712{ 812{
713 struct omap_hwmod *oh;
714 int i; 813 int i;
715 814
716 for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) 815 for (i = 0; i < od->hwmods_cnt; i++)
717 omap_hwmod_idle(oh); 816 omap_hwmod_idle(od->hwmods[i]);
718 817
719 /* XXX pass along return value here? */ 818 /* XXX pass along return value here? */
720 return 0; 819 return 0;
@@ -729,11 +828,10 @@ int omap_device_idle_hwmods(struct omap_device *od)
729 */ 828 */
730int omap_device_disable_clocks(struct omap_device *od) 829int omap_device_disable_clocks(struct omap_device *od)
731{ 830{
732 struct omap_hwmod *oh;
733 int i; 831 int i;
734 832
735 for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) 833 for (i = 0; i < od->hwmods_cnt; i++)
736 omap_hwmod_disable_clocks(oh); 834 omap_hwmod_disable_clocks(od->hwmods[i]);
737 835
738 /* XXX pass along return value here? */ 836 /* XXX pass along return value here? */
739 return 0; 837 return 0;
@@ -748,12 +846,22 @@ int omap_device_disable_clocks(struct omap_device *od)
748 */ 846 */
749int omap_device_enable_clocks(struct omap_device *od) 847int omap_device_enable_clocks(struct omap_device *od)
750{ 848{
751 struct omap_hwmod *oh;
752 int i; 849 int i;
753 850
754 for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) 851 for (i = 0; i < od->hwmods_cnt; i++)
755 omap_hwmod_enable_clocks(oh); 852 omap_hwmod_enable_clocks(od->hwmods[i]);
756 853
757 /* XXX pass along return value here? */ 854 /* XXX pass along return value here? */
758 return 0; 855 return 0;
759} 856}
857
858struct device omap_device_parent = {
859 .init_name = "omap",
860 .parent = &platform_bus,
861};
862
863static int __init omap_device_init(void)
864{
865 return device_register(&omap_device_parent);
866}
867core_initcall(omap_device_init);