Merge branch 'omap4-i2c-init' into omap-for-linus
[pandora-kernel.git] / arch / arm / mach-omap2 / omap_hwmod.c
index 2c12e8c..95c9a5f 100644 (file)
@@ -2,12 +2,12 @@
  * omap_hwmod implementation for OMAP2/3/4
  *
  * Copyright (C) 2009 Nokia Corporation
  * omap_hwmod implementation for OMAP2/3/4
  *
  * Copyright (C) 2009 Nokia Corporation
- * Paul Walmsley
- * With fixes and testing from Kevin Hilman
  *
  *
- * Created in collaboration with (alphabetical order): Benoit Cousson,
- * Kevin Hilman, Tony Lindgren, Rajendra Nayak, Vikram Pandita, Sakari
- * Poussa, Anand Sawant, Santosh Shilimkar, Richard Woodruff
+ * Paul Walmsley, BenoĆ®t Cousson, Kevin Hilman
+ *
+ * Created in collaboration with (alphabetical order): Thara Gopinath,
+ * Tony Lindgren, Rajendra Nayak, Vikram Pandita, Sakari Poussa, Anand
+ * Sawant, Santosh Shilimkar, Richard Woodruff
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -57,7 +57,7 @@
 #define MAX_MODULE_RESET_WAIT          10000
 
 /* Name of the OMAP hwmod for the MPU */
 #define MAX_MODULE_RESET_WAIT          10000
 
 /* Name of the OMAP hwmod for the MPU */
-#define MPU_INITIATOR_NAME             "mpu_hwmod"
+#define MPU_INITIATOR_NAME             "mpu"
 
 /* omap_hwmod_list contains all registered struct omap_hwmods */
 static LIST_HEAD(omap_hwmod_list);
 
 /* omap_hwmod_list contains all registered struct omap_hwmods */
 static LIST_HEAD(omap_hwmod_list);
@@ -403,21 +403,20 @@ static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
  */
 static int _init_main_clk(struct omap_hwmod *oh)
 {
  */
 static int _init_main_clk(struct omap_hwmod *oh)
 {
-       struct clk *c;
        int ret = 0;
 
        if (!oh->main_clk)
                return 0;
 
        int ret = 0;
 
        if (!oh->main_clk)
                return 0;
 
-       c = omap_clk_get_by_name(oh->main_clk);
-       WARN(IS_ERR(c), "omap_hwmod: %s: cannot clk_get main_clk %s\n",
-            oh->name, oh->main_clk);
-       if (IS_ERR(c))
-               ret = -EINVAL;
-       oh->_clk = c;
+       oh->_clk = omap_clk_get_by_name(oh->main_clk);
+       if (!oh->_clk)
+               pr_warning("omap_hwmod: %s: cannot clk_get main_clk %s\n",
+                          oh->name, oh->main_clk);
+               return -EINVAL;
 
 
-       WARN(!c->clkdm, "omap_hwmod: %s: missing clockdomain for %s.\n",
-            oh->main_clk, c->name);
+       if (!oh->_clk->clkdm)
+               pr_warning("omap_hwmod: %s: missing clockdomain for %s.\n",
+                          oh->main_clk, oh->_clk->name);
 
        return ret;
 }
 
        return ret;
 }
@@ -431,7 +430,6 @@ static int _init_main_clk(struct omap_hwmod *oh)
  */
 static int _init_interface_clks(struct omap_hwmod *oh)
 {
  */
 static int _init_interface_clks(struct omap_hwmod *oh)
 {
-       struct omap_hwmod_ocp_if *os;
        struct clk *c;
        int i;
        int ret = 0;
        struct clk *c;
        int i;
        int ret = 0;
@@ -439,14 +437,16 @@ static int _init_interface_clks(struct omap_hwmod *oh)
        if (oh->slaves_cnt == 0)
                return 0;
 
        if (oh->slaves_cnt == 0)
                return 0;
 
-       for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) {
+       for (i = 0; i < oh->slaves_cnt; i++) {
+               struct omap_hwmod_ocp_if *os = oh->slaves[i];
+
                if (!os->clk)
                        continue;
 
                c = omap_clk_get_by_name(os->clk);
                if (!os->clk)
                        continue;
 
                c = omap_clk_get_by_name(os->clk);
-               WARN(IS_ERR(c), "omap_hwmod: %s: cannot clk_get "
-                    "interface_clk %s\n", oh->name, os->clk);
-               if (IS_ERR(c))
+               if (!c)
+                       pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n",
+                                  oh->name, os->clk);
                        ret = -EINVAL;
                os->_clk = c;
        }
                        ret = -EINVAL;
                os->_clk = c;
        }
@@ -470,9 +470,9 @@ static int _init_opt_clks(struct omap_hwmod *oh)
 
        for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) {
                c = omap_clk_get_by_name(oc->clk);
 
        for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) {
                c = omap_clk_get_by_name(oc->clk);
-               WARN(IS_ERR(c), "omap_hwmod: %s: cannot clk_get opt_clk "
-                    "%s\n", oh->name, oc->clk);
-               if (IS_ERR(c))
+               if (!c)
+                       pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n",
+                                  oh->name, oc->clk);
                        ret = -EINVAL;
                oc->_clk = c;
        }
                        ret = -EINVAL;
                oc->_clk = c;
        }
@@ -489,19 +489,19 @@ static int _init_opt_clks(struct omap_hwmod *oh)
  */
 static int _enable_clocks(struct omap_hwmod *oh)
 {
  */
 static int _enable_clocks(struct omap_hwmod *oh)
 {
-       struct omap_hwmod_ocp_if *os;
        int i;
 
        pr_debug("omap_hwmod: %s: enabling clocks\n", oh->name);
 
        int i;
 
        pr_debug("omap_hwmod: %s: enabling clocks\n", oh->name);
 
-       if (oh->_clk && !IS_ERR(oh->_clk))
+       if (oh->_clk)
                clk_enable(oh->_clk);
 
        if (oh->slaves_cnt > 0) {
                clk_enable(oh->_clk);
 
        if (oh->slaves_cnt > 0) {
-               for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) {
+               for (i = 0; i < oh->slaves_cnt; i++) {
+                       struct omap_hwmod_ocp_if *os = oh->slaves[i];
                        struct clk *c = os->_clk;
 
                        struct clk *c = os->_clk;
 
-                       if (c && !IS_ERR(c) && (os->flags & OCPIF_SWSUP_IDLE))
+                       if (c && (os->flags & OCPIF_SWSUP_IDLE))
                                clk_enable(c);
                }
        }
                                clk_enable(c);
                }
        }
@@ -519,19 +519,19 @@ static int _enable_clocks(struct omap_hwmod *oh)
  */
 static int _disable_clocks(struct omap_hwmod *oh)
 {
  */
 static int _disable_clocks(struct omap_hwmod *oh)
 {
-       struct omap_hwmod_ocp_if *os;
        int i;
 
        pr_debug("omap_hwmod: %s: disabling clocks\n", oh->name);
 
        int i;
 
        pr_debug("omap_hwmod: %s: disabling clocks\n", oh->name);
 
-       if (oh->_clk && !IS_ERR(oh->_clk))
+       if (oh->_clk)
                clk_disable(oh->_clk);
 
        if (oh->slaves_cnt > 0) {
                clk_disable(oh->_clk);
 
        if (oh->slaves_cnt > 0) {
-               for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) {
+               for (i = 0; i < oh->slaves_cnt; i++) {
+                       struct omap_hwmod_ocp_if *os = oh->slaves[i];
                        struct clk *c = os->_clk;
 
                        struct clk *c = os->_clk;
 
-                       if (c && !IS_ERR(c) && (os->flags & OCPIF_SWSUP_IDLE))
+                       if (c && (os->flags & OCPIF_SWSUP_IDLE))
                                clk_disable(c);
                }
        }
                                clk_disable(c);
                }
        }
@@ -550,14 +550,15 @@ static int _disable_clocks(struct omap_hwmod *oh)
  */
 static int _find_mpu_port_index(struct omap_hwmod *oh)
 {
  */
 static int _find_mpu_port_index(struct omap_hwmod *oh)
 {
-       struct omap_hwmod_ocp_if *os;
        int i;
        int found = 0;
 
        if (!oh || oh->slaves_cnt == 0)
                return -EINVAL;
 
        int i;
        int found = 0;
 
        if (!oh || oh->slaves_cnt == 0)
                return -EINVAL;
 
-       for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) {
+       for (i = 0; i < oh->slaves_cnt; i++) {
+               struct omap_hwmod_ocp_if *os = oh->slaves[i];
+
                if (os->user & OCP_USER_MPU) {
                        found = 1;
                        break;
                if (os->user & OCP_USER_MPU) {
                        found = 1;
                        break;
@@ -592,7 +593,7 @@ static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
        if (!oh || oh->slaves_cnt == 0)
                return NULL;
 
        if (!oh || oh->slaves_cnt == 0)
                return NULL;
 
-       os = *oh->slaves + index;
+       os = oh->slaves[index];
 
        for (i = 0, mem = os->addr; i < os->addr_cnt; i++, mem++) {
                if (mem->flags & ADDR_TYPE_RT) {
 
        for (i = 0, mem = os->addr; i < os->addr_cnt; i++, mem++) {
                if (mem->flags & ADDR_TYPE_RT) {
@@ -780,9 +781,10 @@ static int _init_clocks(struct omap_hwmod *oh)
        ret |= _init_interface_clks(oh);
        ret |= _init_opt_clks(oh);
 
        ret |= _init_interface_clks(oh);
        ret |= _init_opt_clks(oh);
 
-       oh->_state = _HWMOD_STATE_CLKS_INITED;
+       if (!ret)
+               oh->_state = _HWMOD_STATE_CLKS_INITED;
 
 
-       return ret;
+       return 0;
 }
 
 /**
 }
 
 /**
@@ -805,9 +807,9 @@ static int _wait_target_ready(struct omap_hwmod *oh)
        if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
                return 0;
 
        if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
                return 0;
 
-       os = *oh->slaves + oh->_mpu_port_index;
+       os = oh->slaves[oh->_mpu_port_index];
 
 
-       if (!(os->flags & OCPIF_HAS_IDLEST))
+       if (oh->flags & HWMOD_NO_IDLEST)
                return 0;
 
        /* XXX check module SIDLEMODE */
                return 0;
 
        /* XXX check module SIDLEMODE */
@@ -818,11 +820,8 @@ static int _wait_target_ready(struct omap_hwmod *oh)
                ret = omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs,
                                                 oh->prcm.omap2.idlest_reg_id,
                                                 oh->prcm.omap2.idlest_idle_bit);
                ret = omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs,
                                                 oh->prcm.omap2.idlest_reg_id,
                                                 oh->prcm.omap2.idlest_idle_bit);
-#if 0
        } else if (cpu_is_omap44xx()) {
        } else if (cpu_is_omap44xx()) {
-               ret = omap4_cm_wait_module_ready(oh->prcm.omap4.module_offs,
-                                                oh->prcm.omap4.device_offs);
-#endif
+               ret = omap4_cm_wait_module_ready(oh->prcm.omap4.clkctrl_reg);
        } else {
                BUG();
        };
        } else {
                BUG();
        };
@@ -911,16 +910,21 @@ static int _enable(struct omap_hwmod *oh)
        _add_initiator_dep(oh, mpu_oh);
        _enable_clocks(oh);
 
        _add_initiator_dep(oh, mpu_oh);
        _enable_clocks(oh);
 
-       if (oh->class->sysc) {
-               if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED))
-                       _update_sysc_cache(oh);
-               _sysc_enable(oh);
-       }
-
        r = _wait_target_ready(oh);
        r = _wait_target_ready(oh);
-       if (!r)
+       if (!r) {
                oh->_state = _HWMOD_STATE_ENABLED;
 
                oh->_state = _HWMOD_STATE_ENABLED;
 
+               /* Access the sysconfig only if the target is ready */
+               if (oh->class->sysc) {
+                       if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED))
+                               _update_sysc_cache(oh);
+                       _sysc_enable(oh);
+               }
+       } else {
+               pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
+                        oh->name, r);
+       }
+
        return r;
 }
 
        return r;
 }
 
@@ -997,18 +1001,18 @@ static int _shutdown(struct omap_hwmod *oh)
  */
 static int _setup(struct omap_hwmod *oh)
 {
  */
 static int _setup(struct omap_hwmod *oh)
 {
-       struct omap_hwmod_ocp_if *os;
-       int i;
+       int i, r;
 
        if (!oh)
                return -EINVAL;
 
        /* Set iclk autoidle mode */
        if (oh->slaves_cnt > 0) {
 
        if (!oh)
                return -EINVAL;
 
        /* Set iclk autoidle mode */
        if (oh->slaves_cnt > 0) {
-               for (i = 0, os = *oh->slaves; i < oh->slaves_cnt; i++, os++) {
+               for (i = 0; i < oh->slaves_cnt; i++) {
+                       struct omap_hwmod_ocp_if *os = oh->slaves[i];
                        struct clk *c = os->_clk;
 
                        struct clk *c = os->_clk;
 
-                       if (!c || IS_ERR(c))
+                       if (!c)
                                continue;
 
                        if (os->flags & OCPIF_SWSUP_IDLE) {
                                continue;
 
                        if (os->flags & OCPIF_SWSUP_IDLE) {
@@ -1022,7 +1026,12 @@ static int _setup(struct omap_hwmod *oh)
 
        oh->_state = _HWMOD_STATE_INITIALIZED;
 
 
        oh->_state = _HWMOD_STATE_INITIALIZED;
 
-       _enable(oh);
+       r = _enable(oh);
+       if (r) {
+               pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
+                          oh->name, oh->_state);
+               return 0;
+       }
 
        if (!(oh->flags & HWMOD_INIT_NO_RESET)) {
                /*
 
        if (!(oh->flags & HWMOD_INIT_NO_RESET)) {
                /*
@@ -1430,7 +1439,7 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
        ret = oh->mpu_irqs_cnt + oh->sdma_chs_cnt;
 
        for (i = 0; i < oh->slaves_cnt; i++)
        ret = oh->mpu_irqs_cnt + oh->sdma_chs_cnt;
 
        for (i = 0; i < oh->slaves_cnt; i++)
-               ret += (*oh->slaves + i)->addr_cnt;
+               ret += oh->slaves[i]->addr_cnt;
 
        return ret;
 }
 
        return ret;
 }
@@ -1471,7 +1480,7 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
        for (i = 0; i < oh->slaves_cnt; i++) {
                struct omap_hwmod_ocp_if *os;
 
        for (i = 0; i < oh->slaves_cnt; i++) {
                struct omap_hwmod_ocp_if *os;
 
-               os = *oh->slaves + i;
+               os = oh->slaves[i];
 
                for (j = 0; j < os->addr_cnt; j++) {
                        (res + r)->start = (os->addr + j)->pa_start;
 
                for (j = 0; j < os->addr_cnt; j++) {
                        (res + r)->start = (os->addr + j)->pa_start;