aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap_hwmod.c
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2010-05-20 14:35:19 -0400
committerTony Lindgren <tony@atomide.com>2010-05-20 14:35:19 -0400
commit4fa73a1bf89ebea4eba8a9982b5f64d266d8b5e9 (patch)
tree9d4558065a2586c25a0c0c3d87ed8402981d616d /arch/arm/mach-omap2/omap_hwmod.c
parentc8f626fe1c7e6de983b0c3b6375da69ded3313b6 (diff)
parent59dd7224892142fe1d8505cf2c90bd732d730005 (diff)
Merge branch 'for_2.6.35' of git://git.pwsan.com/linux-2.6 into omap-for-linus
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c121
1 files changed, 65 insertions, 56 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index e436dcb19795..0a563a671dde 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2,12 +2,12 @@
2 * omap_hwmod implementation for OMAP2/3/4 2 * omap_hwmod implementation for OMAP2/3/4
3 * 3 *
4 * Copyright (C) 2009 Nokia Corporation 4 * Copyright (C) 2009 Nokia Corporation
5 * Paul Walmsley
6 * With fixes and testing from Kevin Hilman
7 * 5 *
8 * Created in collaboration with (alphabetical order): Benoit Cousson, 6 * Paul Walmsley, BenoƮt Cousson, Kevin Hilman
9 * Kevin Hilman, Tony Lindgren, Rajendra Nayak, Vikram Pandita, Sakari 7 *
10 * Poussa, Anand Sawant, Santosh Shilimkar, Richard Woodruff 8 * Created in collaboration with (alphabetical order): Thara Gopinath,
9 * Tony Lindgren, Rajendra Nayak, Vikram Pandita, Sakari Poussa, Anand
10 * Sawant, Santosh Shilimkar, Richard Woodruff
11 * 11 *
12 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as 13 * it under the terms of the GNU General Public License version 2 as
@@ -58,7 +58,7 @@
58#define MAX_MODULE_RESET_WAIT 10000 58#define MAX_MODULE_RESET_WAIT 10000
59 59
60/* Name of the OMAP hwmod for the MPU */ 60/* Name of the OMAP hwmod for the MPU */
61#define MPU_INITIATOR_NAME "mpu_hwmod" 61#define MPU_INITIATOR_NAME "mpu"
62 62
63/* omap_hwmod_list contains all registered struct omap_hwmods */ 63/* omap_hwmod_list contains all registered struct omap_hwmods */
64static LIST_HEAD(omap_hwmod_list); 64static LIST_HEAD(omap_hwmod_list);
@@ -404,21 +404,20 @@ static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
404 */ 404 */
405static int _init_main_clk(struct omap_hwmod *oh) 405static int _init_main_clk(struct omap_hwmod *oh)
406{ 406{
407 struct clk *c;
408 int ret = 0; 407 int ret = 0;
409 408
410 if (!oh->main_clk) 409 if (!oh->main_clk)
411 return 0; 410 return 0;
412 411
413 c = omap_clk_get_by_name(oh->main_clk); 412 oh->_clk = omap_clk_get_by_name(oh->main_clk);
414 WARN(IS_ERR(c), "omap_hwmod: %s: cannot clk_get main_clk %s\n", 413 if (!oh->_clk)
415 oh->name, oh->main_clk); 414 pr_warning("omap_hwmod: %s: cannot clk_get main_clk %s\n",
416 if (IS_ERR(c)) 415 oh->name, oh->main_clk);
417 ret = -EINVAL; 416 return -EINVAL;
418 oh->_clk = c;
419 417
420 WARN(!c->clkdm, "omap_hwmod: %s: missing clockdomain for %s.\n", 418 if (!oh->_clk->clkdm)
421 oh->main_clk, c->name); 419 pr_warning("omap_hwmod: %s: missing clockdomain for %s.\n",
420 oh->main_clk, oh->_clk->name);
422 421
423 return ret; 422 return ret;
424} 423}
@@ -432,7 +431,6 @@ static int _init_main_clk(struct omap_hwmod *oh)
432 */ 431 */
433static int _init_interface_clks(struct omap_hwmod *oh) 432static int _init_interface_clks(struct omap_hwmod *oh)
434{ 433{
435 struct omap_hwmod_ocp_if *os;
436 struct clk *c; 434 struct clk *c;
437 int i; 435 int i;
438 int ret = 0; 436 int ret = 0;
@@ -440,14 +438,16 @@ static int _init_interface_clks(struct omap_hwmod *oh)
440 if (oh->slaves_cnt == 0) 438 if (oh->slaves_cnt == 0)
441 return 0; 439 return 0;
442 440
443 for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) { 441 for (i = 0; i < oh->slaves_cnt; i++) {
442 struct omap_hwmod_ocp_if *os = oh->slaves[i];
443
444 if (!os->clk) 444 if (!os->clk)
445 continue; 445 continue;
446 446
447 c = omap_clk_get_by_name(os->clk); 447 c = omap_clk_get_by_name(os->clk);
448 WARN(IS_ERR(c), "omap_hwmod: %s: cannot clk_get " 448 if (!c)
449 "interface_clk %s\n", oh->name, os->clk); 449 pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n",
450 if (IS_ERR(c)) 450 oh->name, os->clk);
451 ret = -EINVAL; 451 ret = -EINVAL;
452 os->_clk = c; 452 os->_clk = c;
453 } 453 }
@@ -471,9 +471,9 @@ static int _init_opt_clks(struct omap_hwmod *oh)
471 471
472 for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) { 472 for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) {
473 c = omap_clk_get_by_name(oc->clk); 473 c = omap_clk_get_by_name(oc->clk);
474 WARN(IS_ERR(c), "omap_hwmod: %s: cannot clk_get opt_clk " 474 if (!c)
475 "%s\n", oh->name, oc->clk); 475 pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n",
476 if (IS_ERR(c)) 476 oh->name, oc->clk);
477 ret = -EINVAL; 477 ret = -EINVAL;
478 oc->_clk = c; 478 oc->_clk = c;
479 } 479 }
@@ -490,19 +490,19 @@ static int _init_opt_clks(struct omap_hwmod *oh)
490 */ 490 */
491static int _enable_clocks(struct omap_hwmod *oh) 491static int _enable_clocks(struct omap_hwmod *oh)
492{ 492{
493 struct omap_hwmod_ocp_if *os;
494 int i; 493 int i;
495 494
496 pr_debug("omap_hwmod: %s: enabling clocks\n", oh->name); 495 pr_debug("omap_hwmod: %s: enabling clocks\n", oh->name);
497 496
498 if (oh->_clk && !IS_ERR(oh->_clk)) 497 if (oh->_clk)
499 clk_enable(oh->_clk); 498 clk_enable(oh->_clk);
500 499
501 if (oh->slaves_cnt > 0) { 500 if (oh->slaves_cnt > 0) {
502 for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) { 501 for (i = 0; i < oh->slaves_cnt; i++) {
502 struct omap_hwmod_ocp_if *os = oh->slaves[i];
503 struct clk *c = os->_clk; 503 struct clk *c = os->_clk;
504 504
505 if (c && !IS_ERR(c) && (os->flags & OCPIF_SWSUP_IDLE)) 505 if (c && (os->flags & OCPIF_SWSUP_IDLE))
506 clk_enable(c); 506 clk_enable(c);
507 } 507 }
508 } 508 }
@@ -520,19 +520,19 @@ static int _enable_clocks(struct omap_hwmod *oh)
520 */ 520 */
521static int _disable_clocks(struct omap_hwmod *oh) 521static int _disable_clocks(struct omap_hwmod *oh)
522{ 522{
523 struct omap_hwmod_ocp_if *os;
524 int i; 523 int i;
525 524
526 pr_debug("omap_hwmod: %s: disabling clocks\n", oh->name); 525 pr_debug("omap_hwmod: %s: disabling clocks\n", oh->name);
527 526
528 if (oh->_clk && !IS_ERR(oh->_clk)) 527 if (oh->_clk)
529 clk_disable(oh->_clk); 528 clk_disable(oh->_clk);
530 529
531 if (oh->slaves_cnt > 0) { 530 if (oh->slaves_cnt > 0) {
532 for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) { 531 for (i = 0; i < oh->slaves_cnt; i++) {
532 struct omap_hwmod_ocp_if *os = oh->slaves[i];
533 struct clk *c = os->_clk; 533 struct clk *c = os->_clk;
534 534
535 if (c && !IS_ERR(c) && (os->flags & OCPIF_SWSUP_IDLE)) 535 if (c && (os->flags & OCPIF_SWSUP_IDLE))
536 clk_disable(c); 536 clk_disable(c);
537 } 537 }
538 } 538 }
@@ -551,14 +551,15 @@ static int _disable_clocks(struct omap_hwmod *oh)
551 */ 551 */
552static int _find_mpu_port_index(struct omap_hwmod *oh) 552static int _find_mpu_port_index(struct omap_hwmod *oh)
553{ 553{
554 struct omap_hwmod_ocp_if *os;
555 int i; 554 int i;
556 int found = 0; 555 int found = 0;
557 556
558 if (!oh || oh->slaves_cnt == 0) 557 if (!oh || oh->slaves_cnt == 0)
559 return -EINVAL; 558 return -EINVAL;
560 559
561 for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) { 560 for (i = 0; i < oh->slaves_cnt; i++) {
561 struct omap_hwmod_ocp_if *os = oh->slaves[i];
562
562 if (os->user & OCP_USER_MPU) { 563 if (os->user & OCP_USER_MPU) {
563 found = 1; 564 found = 1;
564 break; 565 break;
@@ -593,7 +594,7 @@ static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
593 if (!oh || oh->slaves_cnt == 0) 594 if (!oh || oh->slaves_cnt == 0)
594 return NULL; 595 return NULL;
595 596
596 os = *oh->slaves + index; 597 os = oh->slaves[index];
597 598
598 for (i = 0, mem = os->addr; i < os->addr_cnt; i++, mem++) { 599 for (i = 0, mem = os->addr; i < os->addr_cnt; i++, mem++) {
599 if (mem->flags & ADDR_TYPE_RT) { 600 if (mem->flags & ADDR_TYPE_RT) {
@@ -781,9 +782,10 @@ static int _init_clocks(struct omap_hwmod *oh)
781 ret |= _init_interface_clks(oh); 782 ret |= _init_interface_clks(oh);
782 ret |= _init_opt_clks(oh); 783 ret |= _init_opt_clks(oh);
783 784
784 oh->_state = _HWMOD_STATE_CLKS_INITED; 785 if (!ret)
786 oh->_state = _HWMOD_STATE_CLKS_INITED;
785 787
786 return ret; 788 return 0;
787} 789}
788 790
789/** 791/**
@@ -806,9 +808,9 @@ static int _wait_target_ready(struct omap_hwmod *oh)
806 if (oh->_int_flags & _HWMOD_NO_MPU_PORT) 808 if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
807 return 0; 809 return 0;
808 810
809 os = *oh->slaves + oh->_mpu_port_index; 811 os = oh->slaves[oh->_mpu_port_index];
810 812
811 if (!(os->flags & OCPIF_HAS_IDLEST)) 813 if (oh->flags & HWMOD_NO_IDLEST)
812 return 0; 814 return 0;
813 815
814 /* XXX check module SIDLEMODE */ 816 /* XXX check module SIDLEMODE */
@@ -819,11 +821,8 @@ static int _wait_target_ready(struct omap_hwmod *oh)
819 ret = omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs, 821 ret = omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs,
820 oh->prcm.omap2.idlest_reg_id, 822 oh->prcm.omap2.idlest_reg_id,
821 oh->prcm.omap2.idlest_idle_bit); 823 oh->prcm.omap2.idlest_idle_bit);
822#if 0
823 } else if (cpu_is_omap44xx()) { 824 } else if (cpu_is_omap44xx()) {
824 ret = omap4_cm_wait_module_ready(oh->prcm.omap4.module_offs, 825 ret = omap4_cm_wait_module_ready(oh->prcm.omap4.clkctrl_reg);
825 oh->prcm.omap4.device_offs);
826#endif
827 } else { 826 } else {
828 BUG(); 827 BUG();
829 }; 828 };
@@ -912,16 +911,21 @@ static int _enable(struct omap_hwmod *oh)
912 _add_initiator_dep(oh, mpu_oh); 911 _add_initiator_dep(oh, mpu_oh);
913 _enable_clocks(oh); 912 _enable_clocks(oh);
914 913
915 if (oh->class->sysc) {
916 if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED))
917 _update_sysc_cache(oh);
918 _sysc_enable(oh);
919 }
920
921 r = _wait_target_ready(oh); 914 r = _wait_target_ready(oh);
922 if (!r) 915 if (!r) {
923 oh->_state = _HWMOD_STATE_ENABLED; 916 oh->_state = _HWMOD_STATE_ENABLED;
924 917
918 /* Access the sysconfig only if the target is ready */
919 if (oh->class->sysc) {
920 if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED))
921 _update_sysc_cache(oh);
922 _sysc_enable(oh);
923 }
924 } else {
925 pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
926 oh->name, r);
927 }
928
925 return r; 929 return r;
926} 930}
927 931
@@ -998,18 +1002,18 @@ static int _shutdown(struct omap_hwmod *oh)
998 */ 1002 */
999static int _setup(struct omap_hwmod *oh) 1003static int _setup(struct omap_hwmod *oh)
1000{ 1004{
1001 struct omap_hwmod_ocp_if *os; 1005 int i, r;
1002 int i;
1003 1006
1004 if (!oh) 1007 if (!oh)
1005 return -EINVAL; 1008 return -EINVAL;
1006 1009
1007 /* Set iclk autoidle mode */ 1010 /* Set iclk autoidle mode */
1008 if (oh->slaves_cnt > 0) { 1011 if (oh->slaves_cnt > 0) {
1009 for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) { 1012 for (i = 0; i < oh->slaves_cnt; i++) {
1013 struct omap_hwmod_ocp_if *os = oh->slaves[i];
1010 struct clk *c = os->_clk; 1014 struct clk *c = os->_clk;
1011 1015
1012 if (!c || IS_ERR(c)) 1016 if (!c)
1013 continue; 1017 continue;
1014 1018
1015 if (os->flags & OCPIF_SWSUP_IDLE) { 1019 if (os->flags & OCPIF_SWSUP_IDLE) {
@@ -1023,7 +1027,12 @@ static int _setup(struct omap_hwmod *oh)
1023 1027
1024 oh->_state = _HWMOD_STATE_INITIALIZED; 1028 oh->_state = _HWMOD_STATE_INITIALIZED;
1025 1029
1026 _enable(oh); 1030 r = _enable(oh);
1031 if (r) {
1032 pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
1033 oh->name, oh->_state);
1034 return 0;
1035 }
1027 1036
1028 if (!(oh->flags & HWMOD_INIT_NO_RESET)) { 1037 if (!(oh->flags & HWMOD_INIT_NO_RESET)) {
1029 /* 1038 /*
@@ -1431,7 +1440,7 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
1431 ret = oh->mpu_irqs_cnt + oh->sdma_chs_cnt; 1440 ret = oh->mpu_irqs_cnt + oh->sdma_chs_cnt;
1432 1441
1433 for (i = 0; i < oh->slaves_cnt; i++) 1442 for (i = 0; i < oh->slaves_cnt; i++)
1434 ret += (*oh->slaves + i)->addr_cnt; 1443 ret += oh->slaves[i]->addr_cnt;
1435 1444
1436 return ret; 1445 return ret;
1437} 1446}
@@ -1472,7 +1481,7 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
1472 for (i = 0; i < oh->slaves_cnt; i++) { 1481 for (i = 0; i < oh->slaves_cnt; i++) {
1473 struct omap_hwmod_ocp_if *os; 1482 struct omap_hwmod_ocp_if *os;
1474 1483
1475 os = *oh->slaves + i; 1484 os = oh->slaves[i];
1476 1485
1477 for (j = 0; j < os->addr_cnt; j++) { 1486 for (j = 0; j < os->addr_cnt; j++) {
1478 (res + r)->start = (os->addr + j)->pa_start; 1487 (res + r)->start = (os->addr + j)->pa_start;