diff options
Diffstat (limited to 'arch/arm/plat-omap/omap_device.c')
-rw-r--r-- | arch/arm/plat-omap/omap_device.c | 110 |
1 files changed, 68 insertions, 42 deletions
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index d2b160942ccc..abe933cd8f09 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c | |||
@@ -82,6 +82,7 @@ | |||
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> | ||
85 | 86 | ||
86 | #include <plat/omap_device.h> | 87 | #include <plat/omap_device.h> |
87 | #include <plat/omap_hwmod.h> | 88 | #include <plat/omap_hwmod.h> |
@@ -90,12 +91,6 @@ | |||
90 | #define USE_WAKEUP_LAT 0 | 91 | #define USE_WAKEUP_LAT 0 |
91 | #define IGNORE_WAKEUP_LAT 1 | 92 | #define IGNORE_WAKEUP_LAT 1 |
92 | 93 | ||
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 */ | 94 | /* Private functions */ |
100 | 95 | ||
101 | /** | 96 | /** |
@@ -243,6 +238,44 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev) | |||
243 | return container_of(pdev, struct omap_device, pdev); | 238 | return container_of(pdev, struct omap_device, pdev); |
244 | } | 239 | } |
245 | 240 | ||
241 | /** | ||
242 | * _add_optional_clock_alias - Add clock alias for hwmod optional clocks | ||
243 | * @od: struct omap_device *od | ||
244 | * | ||
245 | * For every optional clock present per hwmod per omap_device, this function | ||
246 | * adds an entry in the clocks list of the form <dev-id=dev_name, con-id=role> | ||
247 | * if an entry is already present in it with the form <dev-id=NULL, con-id=role> | ||
248 | * | ||
249 | * The function is called from inside omap_device_build_ss(), after | ||
250 | * omap_device_register. | ||
251 | * | ||
252 | * This allows drivers to get a pointer to its optional clocks based on its role | ||
253 | * by calling clk_get(<dev*>, <role>). | ||
254 | * | ||
255 | * No return value. | ||
256 | */ | ||
257 | static void _add_optional_clock_alias(struct omap_device *od, | ||
258 | struct omap_hwmod *oh) | ||
259 | { | ||
260 | int i; | ||
261 | |||
262 | for (i = 0; i < oh->opt_clks_cnt; i++) { | ||
263 | struct omap_hwmod_opt_clk *oc; | ||
264 | int r; | ||
265 | |||
266 | oc = &oh->opt_clks[i]; | ||
267 | |||
268 | if (!oc->_clk) | ||
269 | continue; | ||
270 | |||
271 | r = clk_add_alias(oc->role, dev_name(&od->pdev.dev), | ||
272 | (char *)oc->clk, &od->pdev.dev); | ||
273 | if (r) | ||
274 | pr_err("omap_device: %s: clk_add_alias for %s failed\n", | ||
275 | dev_name(&od->pdev.dev), oc->role); | ||
276 | } | ||
277 | } | ||
278 | |||
246 | 279 | ||
247 | /* Public functions for use by core code */ | 280 | /* Public functions for use by core code */ |
248 | 281 | ||
@@ -257,12 +290,11 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev) | |||
257 | */ | 290 | */ |
258 | int omap_device_count_resources(struct omap_device *od) | 291 | int omap_device_count_resources(struct omap_device *od) |
259 | { | 292 | { |
260 | struct omap_hwmod *oh; | ||
261 | int c = 0; | 293 | int c = 0; |
262 | int i; | 294 | int i; |
263 | 295 | ||
264 | for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) | 296 | for (i = 0; i < od->hwmods_cnt; i++) |
265 | c += omap_hwmod_count_resources(oh); | 297 | c += omap_hwmod_count_resources(od->hwmods[i]); |
266 | 298 | ||
267 | pr_debug("omap_device: %s: counted %d total resources across %d " | 299 | pr_debug("omap_device: %s: counted %d total resources across %d " |
268 | "hwmods\n", od->pdev.name, c, od->hwmods_cnt); | 300 | "hwmods\n", od->pdev.name, c, od->hwmods_cnt); |
@@ -289,12 +321,11 @@ int omap_device_count_resources(struct omap_device *od) | |||
289 | */ | 321 | */ |
290 | int omap_device_fill_resources(struct omap_device *od, struct resource *res) | 322 | int omap_device_fill_resources(struct omap_device *od, struct resource *res) |
291 | { | 323 | { |
292 | struct omap_hwmod *oh; | ||
293 | int c = 0; | 324 | int c = 0; |
294 | int i, r; | 325 | int i, r; |
295 | 326 | ||
296 | for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) { | 327 | for (i = 0; i < od->hwmods_cnt; i++) { |
297 | r = omap_hwmod_fill_resources(oh, res); | 328 | r = omap_hwmod_fill_resources(od->hwmods[i], res); |
298 | res += r; | 329 | res += r; |
299 | c += r; | 330 | c += r; |
300 | } | 331 | } |
@@ -414,15 +445,15 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id, | |||
414 | od->pm_lats = pm_lats; | 445 | od->pm_lats = pm_lats; |
415 | od->pm_lats_cnt = pm_lats_cnt; | 446 | od->pm_lats_cnt = pm_lats_cnt; |
416 | 447 | ||
417 | od->magic = OMAP_DEVICE_MAGIC; | ||
418 | |||
419 | if (is_early_device) | 448 | if (is_early_device) |
420 | ret = omap_early_device_register(od); | 449 | ret = omap_early_device_register(od); |
421 | else | 450 | else |
422 | ret = omap_device_register(od); | 451 | ret = omap_device_register(od); |
423 | 452 | ||
424 | for (i = 0; i < oh_cnt; i++) | 453 | for (i = 0; i < oh_cnt; i++) { |
425 | hwmods[i]->od = od; | 454 | hwmods[i]->od = od; |
455 | _add_optional_clock_alias(od, hwmods[i]); | ||
456 | } | ||
426 | 457 | ||
427 | if (ret) | 458 | if (ret) |
428 | goto odbs_exit4; | 459 | goto odbs_exit4; |
@@ -473,6 +504,7 @@ int omap_device_register(struct omap_device *od) | |||
473 | { | 504 | { |
474 | pr_debug("omap_device: %s: registering\n", od->pdev.name); | 505 | pr_debug("omap_device: %s: registering\n", od->pdev.name); |
475 | 506 | ||
507 | od->pdev.dev.parent = &omap_device_parent; | ||
476 | return platform_device_register(&od->pdev); | 508 | return platform_device_register(&od->pdev); |
477 | } | 509 | } |
478 | 510 | ||
@@ -566,7 +598,6 @@ int omap_device_shutdown(struct platform_device *pdev) | |||
566 | { | 598 | { |
567 | int ret, i; | 599 | int ret, i; |
568 | struct omap_device *od; | 600 | struct omap_device *od; |
569 | struct omap_hwmod *oh; | ||
570 | 601 | ||
571 | od = _find_by_pdev(pdev); | 602 | od = _find_by_pdev(pdev); |
572 | 603 | ||
@@ -579,8 +610,8 @@ int omap_device_shutdown(struct platform_device *pdev) | |||
579 | 610 | ||
580 | ret = _omap_device_deactivate(od, IGNORE_WAKEUP_LAT); | 611 | ret = _omap_device_deactivate(od, IGNORE_WAKEUP_LAT); |
581 | 612 | ||
582 | for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) | 613 | for (i = 0; i < od->hwmods_cnt; i++) |
583 | omap_hwmod_shutdown(oh); | 614 | omap_hwmod_shutdown(od->hwmods[i]); |
584 | 615 | ||
585 | od->_state = OMAP_DEVICE_STATE_SHUTDOWN; | 616 | od->_state = OMAP_DEVICE_STATE_SHUTDOWN; |
586 | 617 | ||
@@ -627,18 +658,6 @@ int omap_device_align_pm_lat(struct platform_device *pdev, | |||
627 | } | 658 | } |
628 | 659 | ||
629 | /** | 660 | /** |
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 | */ | ||
636 | bool 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 | 661 | * omap_device_get_pwrdm - return the powerdomain * associated with @od |
643 | * @od: struct omap_device * | 662 | * @od: struct omap_device * |
644 | * | 663 | * |
@@ -692,11 +711,10 @@ void __iomem *omap_device_get_rt_va(struct omap_device *od) | |||
692 | */ | 711 | */ |
693 | int omap_device_enable_hwmods(struct omap_device *od) | 712 | int omap_device_enable_hwmods(struct omap_device *od) |
694 | { | 713 | { |
695 | struct omap_hwmod *oh; | ||
696 | int i; | 714 | int i; |
697 | 715 | ||
698 | for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) | 716 | for (i = 0; i < od->hwmods_cnt; i++) |
699 | omap_hwmod_enable(oh); | 717 | omap_hwmod_enable(od->hwmods[i]); |
700 | 718 | ||
701 | /* XXX pass along return value here? */ | 719 | /* XXX pass along return value here? */ |
702 | return 0; | 720 | return 0; |
@@ -710,11 +728,10 @@ int omap_device_enable_hwmods(struct omap_device *od) | |||
710 | */ | 728 | */ |
711 | int omap_device_idle_hwmods(struct omap_device *od) | 729 | int omap_device_idle_hwmods(struct omap_device *od) |
712 | { | 730 | { |
713 | struct omap_hwmod *oh; | ||
714 | int i; | 731 | int i; |
715 | 732 | ||
716 | for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) | 733 | for (i = 0; i < od->hwmods_cnt; i++) |
717 | omap_hwmod_idle(oh); | 734 | omap_hwmod_idle(od->hwmods[i]); |
718 | 735 | ||
719 | /* XXX pass along return value here? */ | 736 | /* XXX pass along return value here? */ |
720 | return 0; | 737 | return 0; |
@@ -729,11 +746,10 @@ int omap_device_idle_hwmods(struct omap_device *od) | |||
729 | */ | 746 | */ |
730 | int omap_device_disable_clocks(struct omap_device *od) | 747 | int omap_device_disable_clocks(struct omap_device *od) |
731 | { | 748 | { |
732 | struct omap_hwmod *oh; | ||
733 | int i; | 749 | int i; |
734 | 750 | ||
735 | for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) | 751 | for (i = 0; i < od->hwmods_cnt; i++) |
736 | omap_hwmod_disable_clocks(oh); | 752 | omap_hwmod_disable_clocks(od->hwmods[i]); |
737 | 753 | ||
738 | /* XXX pass along return value here? */ | 754 | /* XXX pass along return value here? */ |
739 | return 0; | 755 | return 0; |
@@ -748,12 +764,22 @@ int omap_device_disable_clocks(struct omap_device *od) | |||
748 | */ | 764 | */ |
749 | int omap_device_enable_clocks(struct omap_device *od) | 765 | int omap_device_enable_clocks(struct omap_device *od) |
750 | { | 766 | { |
751 | struct omap_hwmod *oh; | ||
752 | int i; | 767 | int i; |
753 | 768 | ||
754 | for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) | 769 | for (i = 0; i < od->hwmods_cnt; i++) |
755 | omap_hwmod_enable_clocks(oh); | 770 | omap_hwmod_enable_clocks(od->hwmods[i]); |
756 | 771 | ||
757 | /* XXX pass along return value here? */ | 772 | /* XXX pass along return value here? */ |
758 | return 0; | 773 | return 0; |
759 | } | 774 | } |
775 | |||
776 | struct device omap_device_parent = { | ||
777 | .init_name = "omap", | ||
778 | .parent = &platform_bus, | ||
779 | }; | ||
780 | |||
781 | static int __init omap_device_init(void) | ||
782 | { | ||
783 | return device_register(&omap_device_parent); | ||
784 | } | ||
785 | core_initcall(omap_device_init); | ||