aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap_hwmod.c
diff options
context:
space:
mode:
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 2c12e8cd7183..95c9a5f774e1 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
@@ -57,7 +57,7 @@
57#define MAX_MODULE_RESET_WAIT 10000 57#define MAX_MODULE_RESET_WAIT 10000
58 58
59/* Name of the OMAP hwmod for the MPU */ 59/* Name of the OMAP hwmod for the MPU */
60#define MPU_INITIATOR_NAME "mpu_hwmod" 60#define MPU_INITIATOR_NAME "mpu"
61 61
62/* omap_hwmod_list contains all registered struct omap_hwmods */ 62/* omap_hwmod_list contains all registered struct omap_hwmods */
63static LIST_HEAD(omap_hwmod_list); 63static LIST_HEAD(omap_hwmod_list);
@@ -403,21 +403,20 @@ static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
403 */ 403 */
404static int _init_main_clk(struct omap_hwmod *oh) 404static int _init_main_clk(struct omap_hwmod *oh)
405{ 405{
406 struct clk *c;
407 int ret = 0; 406 int ret = 0;
408 407
409 if (!oh->main_clk) 408 if (!oh->main_clk)
410 return 0; 409 return 0;
411 410
412 c = omap_clk_get_by_name(oh->main_clk); 411 oh->_clk = omap_clk_get_by_name(oh->main_clk);
413 WARN(IS_ERR(c), "omap_hwmod: %s: cannot clk_get main_clk %s\n", 412 if (!oh->_clk)
414 oh->name, oh->main_clk); 413 pr_warning("omap_hwmod: %s: cannot clk_get main_clk %s\n",
415 if (IS_ERR(c)) 414 oh->name, oh->main_clk);
416 ret = -EINVAL; 415 return -EINVAL;
417 oh->_clk = c;
418 416
419 WARN(!c->clkdm, "omap_hwmod: %s: missing clockdomain for %s.\n", 417 if (!oh->_clk->clkdm)
420 oh->main_clk, c->name); 418 pr_warning("omap_hwmod: %s: missing clockdomain for %s.\n",
419 oh->main_clk, oh->_clk->name);
421 420
422 return ret; 421 return ret;
423} 422}
@@ -431,7 +430,6 @@ static int _init_main_clk(struct omap_hwmod *oh)
431 */ 430 */
432static int _init_interface_clks(struct omap_hwmod *oh) 431static int _init_interface_clks(struct omap_hwmod *oh)
433{ 432{
434 struct omap_hwmod_ocp_if *os;
435 struct clk *c; 433 struct clk *c;
436 int i; 434 int i;
437 int ret = 0; 435 int ret = 0;
@@ -439,14 +437,16 @@ static int _init_interface_clks(struct omap_hwmod *oh)
439 if (oh->slaves_cnt == 0) 437 if (oh->slaves_cnt == 0)
440 return 0; 438 return 0;
441 439
442 for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) { 440 for (i = 0; i < oh->slaves_cnt; i++) {
441 struct omap_hwmod_ocp_if *os = oh->slaves[i];
442
443 if (!os->clk) 443 if (!os->clk)
444 continue; 444 continue;
445 445
446 c = omap_clk_get_by_name(os->clk); 446 c = omap_clk_get_by_name(os->clk);
447 WARN(IS_ERR(c), "omap_hwmod: %s: cannot clk_get " 447 if (!c)
448 "interface_clk %s\n", oh->name, os->clk); 448 pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n",
449 if (IS_ERR(c)) 449 oh->name, os->clk);
450 ret = -EINVAL; 450 ret = -EINVAL;
451 os->_clk = c; 451 os->_clk = c;
452 } 452 }
@@ -470,9 +470,9 @@ static int _init_opt_clks(struct omap_hwmod *oh)
470 470
471 for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) { 471 for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) {
472 c = omap_clk_get_by_name(oc->clk); 472 c = omap_clk_get_by_name(oc->clk);
473 WARN(IS_ERR(c), "omap_hwmod: %s: cannot clk_get opt_clk " 473 if (!c)
474 "%s\n", oh->name, oc->clk); 474 pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n",
475 if (IS_ERR(c)) 475 oh->name, oc->clk);
476 ret = -EINVAL; 476 ret = -EINVAL;
477 oc->_clk = c; 477 oc->_clk = c;
478 } 478 }
@@ -489,19 +489,19 @@ static int _init_opt_clks(struct omap_hwmod *oh)
489 */ 489 */
490static int _enable_clocks(struct omap_hwmod *oh) 490static int _enable_clocks(struct omap_hwmod *oh)
491{ 491{
492 struct omap_hwmod_ocp_if *os;
493 int i; 492 int i;
494 493
495 pr_debug("omap_hwmod: %s: enabling clocks\n", oh->name); 494 pr_debug("omap_hwmod: %s: enabling clocks\n", oh->name);
496 495
497 if (oh->_clk && !IS_ERR(oh->_clk)) 496 if (oh->_clk)
498 clk_enable(oh->_clk); 497 clk_enable(oh->_clk);
499 498
500 if (oh->slaves_cnt > 0) { 499 if (oh->slaves_cnt > 0) {
501 for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) { 500 for (i = 0; i < oh->slaves_cnt; i++) {
501 struct omap_hwmod_ocp_if *os = oh->slaves[i];
502 struct clk *c = os->_clk; 502 struct clk *c = os->_clk;
503 503
504 if (c && !IS_ERR(c) && (os->flags & OCPIF_SWSUP_IDLE)) 504 if (c && (os->flags & OCPIF_SWSUP_IDLE))
505 clk_enable(c); 505 clk_enable(c);
506 } 506 }
507 } 507 }
@@ -519,19 +519,19 @@ static int _enable_clocks(struct omap_hwmod *oh)
519 */ 519 */
520static int _disable_clocks(struct omap_hwmod *oh) 520static int _disable_clocks(struct omap_hwmod *oh)
521{ 521{
522 struct omap_hwmod_ocp_if *os;
523 int i; 522 int i;
524 523
525 pr_debug("omap_hwmod: %s: disabling clocks\n", oh->name); 524 pr_debug("omap_hwmod: %s: disabling clocks\n", oh->name);
526 525
527 if (oh->_clk && !IS_ERR(oh->_clk)) 526 if (oh->_clk)
528 clk_disable(oh->_clk); 527 clk_disable(oh->_clk);
529 528
530 if (oh->slaves_cnt > 0) { 529 if (oh->slaves_cnt > 0) {
531 for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) { 530 for (i = 0; i < oh->slaves_cnt; i++) {
531 struct omap_hwmod_ocp_if *os = oh->slaves[i];
532 struct clk *c = os->_clk; 532 struct clk *c = os->_clk;
533 533
534 if (c && !IS_ERR(c) && (os->flags & OCPIF_SWSUP_IDLE)) 534 if (c && (os->flags & OCPIF_SWSUP_IDLE))
535 clk_disable(c); 535 clk_disable(c);
536 } 536 }
537 } 537 }
@@ -550,14 +550,15 @@ static int _disable_clocks(struct omap_hwmod *oh)
550 */ 550 */
551static int _find_mpu_port_index(struct omap_hwmod *oh) 551static int _find_mpu_port_index(struct omap_hwmod *oh)
552{ 552{
553 struct omap_hwmod_ocp_if *os;
554 int i; 553 int i;
555 int found = 0; 554 int found = 0;
556 555
557 if (!oh || oh->slaves_cnt == 0) 556 if (!oh || oh->slaves_cnt == 0)
558 return -EINVAL; 557 return -EINVAL;
559 558
560 for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) { 559 for (i = 0; i < oh->slaves_cnt; i++) {
560 struct omap_hwmod_ocp_if *os = oh->slaves[i];
561
561 if (os->user & OCP_USER_MPU) { 562 if (os->user & OCP_USER_MPU) {
562 found = 1; 563 found = 1;
563 break; 564 break;
@@ -592,7 +593,7 @@ static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
592 if (!oh || oh->slaves_cnt == 0) 593 if (!oh || oh->slaves_cnt == 0)
593 return NULL; 594 return NULL;
594 595
595 os = *oh->slaves + index; 596 os = oh->slaves[index];
596 597
597 for (i = 0, mem = os->addr; i < os->addr_cnt; i++, mem++) { 598 for (i = 0, mem = os->addr; i < os->addr_cnt; i++, mem++) {
598 if (mem->flags & ADDR_TYPE_RT) { 599 if (mem->flags & ADDR_TYPE_RT) {
@@ -780,9 +781,10 @@ static int _init_clocks(struct omap_hwmod *oh)
780 ret |= _init_interface_clks(oh); 781 ret |= _init_interface_clks(oh);
781 ret |= _init_opt_clks(oh); 782 ret |= _init_opt_clks(oh);
782 783
783 oh->_state = _HWMOD_STATE_CLKS_INITED; 784 if (!ret)
785 oh->_state = _HWMOD_STATE_CLKS_INITED;
784 786
785 return ret; 787 return 0;
786} 788}
787 789
788/** 790/**
@@ -805,9 +807,9 @@ static int _wait_target_ready(struct omap_hwmod *oh)
805 if (oh->_int_flags & _HWMOD_NO_MPU_PORT) 807 if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
806 return 0; 808 return 0;
807 809
808 os = *oh->slaves + oh->_mpu_port_index; 810 os = oh->slaves[oh->_mpu_port_index];
809 811
810 if (!(os->flags & OCPIF_HAS_IDLEST)) 812 if (oh->flags & HWMOD_NO_IDLEST)
811 return 0; 813 return 0;
812 814
813 /* XXX check module SIDLEMODE */ 815 /* XXX check module SIDLEMODE */
@@ -818,11 +820,8 @@ static int _wait_target_ready(struct omap_hwmod *oh)
818 ret = omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs, 820 ret = omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs,
819 oh->prcm.omap2.idlest_reg_id, 821 oh->prcm.omap2.idlest_reg_id,
820 oh->prcm.omap2.idlest_idle_bit); 822 oh->prcm.omap2.idlest_idle_bit);
821#if 0
822 } else if (cpu_is_omap44xx()) { 823 } else if (cpu_is_omap44xx()) {
823 ret = omap4_cm_wait_module_ready(oh->prcm.omap4.module_offs, 824 ret = omap4_cm_wait_module_ready(oh->prcm.omap4.clkctrl_reg);
824 oh->prcm.omap4.device_offs);
825#endif
826 } else { 825 } else {
827 BUG(); 826 BUG();
828 }; 827 };
@@ -911,16 +910,21 @@ static int _enable(struct omap_hwmod *oh)
911 _add_initiator_dep(oh, mpu_oh); 910 _add_initiator_dep(oh, mpu_oh);
912 _enable_clocks(oh); 911 _enable_clocks(oh);
913 912
914 if (oh->class->sysc) {
915 if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED))
916 _update_sysc_cache(oh);
917 _sysc_enable(oh);
918 }
919
920 r = _wait_target_ready(oh); 913 r = _wait_target_ready(oh);
921 if (!r) 914 if (!r) {
922 oh->_state = _HWMOD_STATE_ENABLED; 915 oh->_state = _HWMOD_STATE_ENABLED;
923 916
917 /* Access the sysconfig only if the target is ready */
918 if (oh->class->sysc) {
919 if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED))
920 _update_sysc_cache(oh);
921 _sysc_enable(oh);
922 }
923 } else {
924 pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
925 oh->name, r);
926 }
927
924 return r; 928 return r;
925} 929}
926 930
@@ -997,18 +1001,18 @@ static int _shutdown(struct omap_hwmod *oh)
997 */ 1001 */
998static int _setup(struct omap_hwmod *oh) 1002static int _setup(struct omap_hwmod *oh)
999{ 1003{
1000 struct omap_hwmod_ocp_if *os; 1004 int i, r;
1001 int i;
1002 1005
1003 if (!oh) 1006 if (!oh)
1004 return -EINVAL; 1007 return -EINVAL;
1005 1008
1006 /* Set iclk autoidle mode */ 1009 /* Set iclk autoidle mode */
1007 if (oh->slaves_cnt > 0) { 1010 if (oh->slaves_cnt > 0) {
1008 for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) { 1011 for (i = 0; i < oh->slaves_cnt; i++) {
1012 struct omap_hwmod_ocp_if *os = oh->slaves[i];
1009 struct clk *c = os->_clk; 1013 struct clk *c = os->_clk;
1010 1014
1011 if (!c || IS_ERR(c)) 1015 if (!c)
1012 continue; 1016 continue;
1013 1017
1014 if (os->flags & OCPIF_SWSUP_IDLE) { 1018 if (os->flags & OCPIF_SWSUP_IDLE) {
@@ -1022,7 +1026,12 @@ static int _setup(struct omap_hwmod *oh)
1022 1026
1023 oh->_state = _HWMOD_STATE_INITIALIZED; 1027 oh->_state = _HWMOD_STATE_INITIALIZED;
1024 1028
1025 _enable(oh); 1029 r = _enable(oh);
1030 if (r) {
1031 pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
1032 oh->name, oh->_state);
1033 return 0;
1034 }
1026 1035
1027 if (!(oh->flags & HWMOD_INIT_NO_RESET)) { 1036 if (!(oh->flags & HWMOD_INIT_NO_RESET)) {
1028 /* 1037 /*
@@ -1430,7 +1439,7 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
1430 ret = oh->mpu_irqs_cnt + oh->sdma_chs_cnt; 1439 ret = oh->mpu_irqs_cnt + oh->sdma_chs_cnt;
1431 1440
1432 for (i = 0; i < oh->slaves_cnt; i++) 1441 for (i = 0; i < oh->slaves_cnt; i++)
1433 ret += (*oh->slaves + i)->addr_cnt; 1442 ret += oh->slaves[i]->addr_cnt;
1434 1443
1435 return ret; 1444 return ret;
1436} 1445}
@@ -1471,7 +1480,7 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
1471 for (i = 0; i < oh->slaves_cnt; i++) { 1480 for (i = 0; i < oh->slaves_cnt; i++) {
1472 struct omap_hwmod_ocp_if *os; 1481 struct omap_hwmod_ocp_if *os;
1473 1482
1474 os = *oh->slaves + i; 1483 os = oh->slaves[i];
1475 1484
1476 for (j = 0; j < os->addr_cnt; j++) { 1485 for (j = 0; j < os->addr_cnt; j++) {
1477 (res + r)->start = (os->addr + j)->pa_start; 1486 (res + r)->start = (os->addr + j)->pa_start;