X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=arch%2Farm%2Fmach-omap2%2Fomap_hwmod.c;h=acff6b7b79a2212d512f7c031c8f1f0ebae3c7a4;hb=5dcc3b975e972989574c009457f0e333c342910d;hp=37afbd173c2c27969e81f37917d70a767e8fbc2d;hpb=9bc67590a65a18201444c2d3d7dae3e897e700c2;p=platform%2Fadaptation%2Frenesas_rcar%2Frenesas_kernel.git diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 37afbd1..acff6b7 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -139,18 +139,20 @@ #include #include -#include "common.h" -#include -#include "clockdomain.h" -#include "powerdomain.h" #include #include #include +#include "soc.h" +#include "common.h" +#include "clockdomain.h" +#include "powerdomain.h" #include "cm2xxx_3xxx.h" #include "cminst44xx.h" +#include "cm33xx.h" #include "prm2xxx_3xxx.h" #include "prm44xx.h" +#include "prm33xx.h" #include "prminst44xx.h" #include "mux.h" #include "pm.h" @@ -677,16 +679,25 @@ static int _init_main_clk(struct omap_hwmod *oh) if (!oh->main_clk) return 0; - oh->_clk = omap_clk_get_by_name(oh->main_clk); - if (!oh->_clk) { + oh->_clk = clk_get(NULL, oh->main_clk); + if (IS_ERR(oh->_clk)) { pr_warning("omap_hwmod: %s: cannot clk_get main_clk %s\n", oh->name, oh->main_clk); return -EINVAL; } + /* + * HACK: This needs a re-visit once clk_prepare() is implemented + * to do something meaningful. Today its just a no-op. + * If clk_prepare() is used at some point to do things like + * voltage scaling etc, then this would have to be moved to + * some point where subsystems like i2c and pmic become + * available. + */ + clk_prepare(oh->_clk); if (!oh->_clk->clkdm) pr_warning("omap_hwmod: %s: missing clockdomain for %s.\n", - oh->main_clk, oh->_clk->name); + oh->name, oh->main_clk); return ret; } @@ -713,13 +724,22 @@ static int _init_interface_clks(struct omap_hwmod *oh) if (!os->clk) continue; - c = omap_clk_get_by_name(os->clk); - if (!c) { + c = clk_get(NULL, os->clk); + if (IS_ERR(c)) { pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n", oh->name, os->clk); ret = -EINVAL; } os->_clk = c; + /* + * HACK: This needs a re-visit once clk_prepare() is implemented + * to do something meaningful. Today its just a no-op. + * If clk_prepare() is used at some point to do things like + * voltage scaling etc, then this would have to be moved to + * some point where subsystems like i2c and pmic become + * available. + */ + clk_prepare(os->_clk); } return ret; @@ -740,13 +760,22 @@ static int _init_opt_clks(struct omap_hwmod *oh) int ret = 0; for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) { - c = omap_clk_get_by_name(oc->clk); - if (!c) { + c = clk_get(NULL, oc->clk); + if (IS_ERR(c)) { pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n", oh->name, oc->clk); ret = -EINVAL; } oc->_clk = c; + /* + * HACK: This needs a re-visit once clk_prepare() is implemented + * to do something meaningful. Today its just a no-op. + * If clk_prepare() is used at some point to do things like + * voltage scaling etc, then this would have to be moved to + * some point where subsystems like i2c and pmic become + * available. + */ + clk_prepare(oc->_clk); } return ret; @@ -825,7 +854,7 @@ static void _enable_optional_clocks(struct omap_hwmod *oh) for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) if (oc->_clk) { pr_debug("omap_hwmod: enable %s:%s\n", oc->role, - oc->_clk->name); + __clk_get_name(oc->_clk)); clk_enable(oc->_clk); } } @@ -840,7 +869,7 @@ static void _disable_optional_clocks(struct omap_hwmod *oh) for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) if (oc->_clk) { pr_debug("omap_hwmod: disable %s:%s\n", oc->role, - oc->_clk->name); + __clk_get_name(oc->_clk)); clk_disable(oc->_clk); } } @@ -868,6 +897,26 @@ static void _omap4_enable_module(struct omap_hwmod *oh) } /** + * _am33xx_enable_module - enable CLKCTRL modulemode on AM33XX + * @oh: struct omap_hwmod * + * + * Enables the PRCM module mode related to the hwmod @oh. + * No return value. + */ +static void _am33xx_enable_module(struct omap_hwmod *oh) +{ + if (!oh->clkdm || !oh->prcm.omap4.modulemode) + return; + + pr_debug("omap_hwmod: %s: %s: %d\n", + oh->name, __func__, oh->prcm.omap4.modulemode); + + am33xx_cm_module_enable(oh->prcm.omap4.modulemode, oh->clkdm->cm_inst, + oh->clkdm->clkdm_offs, + oh->prcm.omap4.clkctrl_offs); +} + +/** * _omap4_wait_target_disable - wait for a module to be disabled on OMAP4 * @oh: struct omap_hwmod * * @@ -894,6 +943,31 @@ static int _omap4_wait_target_disable(struct omap_hwmod *oh) } /** + * _am33xx_wait_target_disable - wait for a module to be disabled on AM33XX + * @oh: struct omap_hwmod * + * + * Wait for a module @oh to enter slave idle. Returns 0 if the module + * does not have an IDLEST bit or if the module successfully enters + * slave idle; otherwise, pass along the return value of the + * appropriate *_cm*_wait_module_idle() function. + */ +static int _am33xx_wait_target_disable(struct omap_hwmod *oh) +{ + if (!oh) + return -EINVAL; + + if (oh->_int_flags & _HWMOD_NO_MPU_PORT) + return 0; + + if (oh->flags & HWMOD_NO_IDLEST) + return 0; + + return am33xx_cm_wait_module_idle(oh->clkdm->cm_inst, + oh->clkdm->clkdm_offs, + oh->prcm.omap4.clkctrl_offs); +} + +/** * _count_mpu_irqs - count the number of MPU IRQ lines associated with @oh * @oh: struct omap_hwmod *oh * @@ -1614,6 +1688,36 @@ static int _omap4_disable_module(struct omap_hwmod *oh) } /** + * _am33xx_disable_module - enable CLKCTRL modulemode on AM33XX + * @oh: struct omap_hwmod * + * + * Disable the PRCM module mode related to the hwmod @oh. + * Return EINVAL if the modulemode is not supported and 0 in case of success. + */ +static int _am33xx_disable_module(struct omap_hwmod *oh) +{ + int v; + + if (!oh->clkdm || !oh->prcm.omap4.modulemode) + return -EINVAL; + + pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__); + + am33xx_cm_module_disable(oh->clkdm->cm_inst, oh->clkdm->clkdm_offs, + oh->prcm.omap4.clkctrl_offs); + + if (_are_any_hardreset_lines_asserted(oh)) + return 0; + + v = _am33xx_wait_target_disable(oh); + if (v) + pr_warn("omap_hwmod: %s: _wait_target_disable failed\n", + oh->name); + + return 0; +} + +/** * _ocp_softreset - reset an omap_hwmod via the OCP_SYSCONFIG bit * @oh: struct omap_hwmod * * @@ -2549,6 +2653,33 @@ static int _omap4_wait_target_ready(struct omap_hwmod *oh) } /** + * _am33xx_wait_target_ready - wait for a module to leave slave idle + * @oh: struct omap_hwmod * + * + * Wait for a module @oh to leave slave idle. Returns 0 if the module + * does not have an IDLEST bit or if the module successfully leaves + * slave idle; otherwise, pass along the return value of the + * appropriate *_cm*_wait_module_ready() function. + */ +static int _am33xx_wait_target_ready(struct omap_hwmod *oh) +{ + if (!oh || !oh->clkdm) + return -EINVAL; + + if (oh->flags & HWMOD_NO_IDLEST) + return 0; + + if (!_find_mpu_rt_port(oh)) + return 0; + + /* XXX check module SIDLEMODE, hardreset status */ + + return am33xx_cm_wait_module_ready(oh->clkdm->cm_inst, + oh->clkdm->clkdm_offs, + oh->prcm.omap4.clkctrl_offs); +} + +/** * _omap2_assert_hardreset - call OMAP2 PRM hardreset fn with hwmod args * @oh: struct omap_hwmod * to assert hardreset * @ohri: hardreset line data @@ -2679,6 +2810,72 @@ static int _omap4_is_hardreset_asserted(struct omap_hwmod *oh, oh->prcm.omap4.rstctrl_offs); } +/** + * _am33xx_assert_hardreset - call AM33XX PRM hardreset fn with hwmod args + * @oh: struct omap_hwmod * to assert hardreset + * @ohri: hardreset line data + * + * Call am33xx_prminst_assert_hardreset() with parameters extracted + * from the hwmod @oh and the hardreset line data @ohri. Only + * intended for use as an soc_ops function pointer. Passes along the + * return value from am33xx_prminst_assert_hardreset(). XXX This + * function is scheduled for removal when the PRM code is moved into + * drivers/. + */ +static int _am33xx_assert_hardreset(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri) + +{ + return am33xx_prm_assert_hardreset(ohri->rst_shift, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.rstctrl_offs); +} + +/** + * _am33xx_deassert_hardreset - call AM33XX PRM hardreset fn with hwmod args + * @oh: struct omap_hwmod * to deassert hardreset + * @ohri: hardreset line data + * + * Call am33xx_prminst_deassert_hardreset() with parameters extracted + * from the hwmod @oh and the hardreset line data @ohri. Only + * intended for use as an soc_ops function pointer. Passes along the + * return value from am33xx_prminst_deassert_hardreset(). XXX This + * function is scheduled for removal when the PRM code is moved into + * drivers/. + */ +static int _am33xx_deassert_hardreset(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri) +{ + if (ohri->st_shift) + pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n", + oh->name, ohri->name); + + return am33xx_prm_deassert_hardreset(ohri->rst_shift, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.rstctrl_offs, + oh->prcm.omap4.rstst_offs); +} + +/** + * _am33xx_is_hardreset_asserted - call AM33XX PRM hardreset fn with hwmod args + * @oh: struct omap_hwmod * to test hardreset + * @ohri: hardreset line data + * + * Call am33xx_prminst_is_hardreset_asserted() with parameters + * extracted from the hwmod @oh and the hardreset line data @ohri. + * Only intended for use as an soc_ops function pointer. Passes along + * the return value from am33xx_prminst_is_hardreset_asserted(). XXX + * This function is scheduled for removal when the PRM code is moved + * into drivers/. + */ +static int _am33xx_is_hardreset_asserted(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri) +{ + return am33xx_prm_is_hardreset_asserted(ohri->rst_shift, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.rstctrl_offs); +} + /* Public functions */ u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs) @@ -3678,6 +3875,14 @@ void __init omap_hwmod_init(void) soc_ops.deassert_hardreset = _omap4_deassert_hardreset; soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted; soc_ops.init_clkdm = _init_clkdm; + } else if (soc_is_am33xx()) { + soc_ops.enable_module = _am33xx_enable_module; + soc_ops.disable_module = _am33xx_disable_module; + soc_ops.wait_target_ready = _am33xx_wait_target_ready; + soc_ops.assert_hardreset = _am33xx_assert_hardreset; + soc_ops.deassert_hardreset = _am33xx_deassert_hardreset; + soc_ops.is_hardreset_asserted = _am33xx_is_hardreset_asserted; + soc_ops.init_clkdm = _init_clkdm; } else { WARN(1, "omap_hwmod: unknown SoC type\n"); }