From 3d9f032724e72851c6de38d026b2417501a2f240 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 18 Jun 2012 12:12:23 -0600 Subject: ARM: OMAP4: hwmod: rename _enable_module to _omap4_enable_module() _enable_module is specific to SoCs with PRCM interfaces similar to that of the OMAP4, so rename it to be consistent with the corresponding _omap4_disable_module. Signed-off-by: Kevin Hilman [paul@pwsan.com: tweaked commit message] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index bf86f7e8f91..939032a427f 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -771,13 +771,13 @@ static void _disable_optional_clocks(struct omap_hwmod *oh) } /** - * _enable_module - enable CLKCTRL modulemode on OMAP4 + * _omap4_enable_module - enable CLKCTRL modulemode on OMAP4 * @oh: struct omap_hwmod * * * Enables the PRCM module mode related to the hwmod @oh. * No return value. */ -static void _enable_module(struct omap_hwmod *oh) +static void _omap4_enable_module(struct omap_hwmod *oh) { /* The module mode does not exist prior OMAP4 */ if (cpu_is_omap24xx() || cpu_is_omap34xx()) @@ -786,8 +786,8 @@ static void _enable_module(struct omap_hwmod *oh) if (!oh->clkdm || !oh->prcm.omap4.modulemode) return; - pr_debug("omap_hwmod: %s: _enable_module: %d\n", - oh->name, oh->prcm.omap4.modulemode); + pr_debug("omap_hwmod: %s: %s: %d\n", + oh->name, __func__, oh->prcm.omap4.modulemode); omap4_cminst_module_enable(oh->prcm.omap4.modulemode, oh->clkdm->prcm_partition, @@ -1814,7 +1814,7 @@ static int _enable(struct omap_hwmod *oh) } _enable_clocks(oh); - _enable_module(oh); + _omap4_enable_module(oh); r = _wait_target_ready(oh); if (!r) { -- cgit v1.2.3-70-g09d2 From 9ebfd285371835b1c0243d15aaacd72d5def76f8 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 18 Jun 2012 12:12:23 -0600 Subject: ARM: OMAP2+: hwmod: use init-time function ptrs for enable/disable module The enable/disable module functions are specific to SoCs with OMAP4-class PRCM. Rather than use cpu_is* checks at runtime inside the enable/disable module functions, use cpu_is at init time to initialize function pointers only for SoCs that need them. NOTE: the cpu_is* check for _enable_module was different than the one for _disable_module, and this patch uses cpu_is_omap44xx() for both. Signed-off-by: Kevin Hilman [paul@pwsan.com: moved soc_ops function pointers to be per-kernel rather than per-hwmod since they do not vary by hwmod; added kerneldoc] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 62 ++++++++++++++++++++++------ arch/arm/mach-omap2/omap_hwmod_2420_data.c | 1 + arch/arm/mach-omap2/omap_hwmod_2430_data.c | 1 + arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 2 + arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 1 + arch/arm/plat-omap/include/plat/omap_hwmod.h | 2 + 6 files changed, 57 insertions(+), 12 deletions(-) (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 939032a427f..634a79836c6 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -166,6 +166,23 @@ */ #define LINKS_PER_OCP_IF 2 +/** + * struct omap_hwmod_soc_ops - fn ptrs for some SoC-specific operations + * @enable_module: function to enable a module (via MODULEMODE) + * @disable_module: function to disable a module (via MODULEMODE) + * + * XXX Eventually this functionality will be hidden inside the PRM/CM + * device drivers. Until then, this should avoid huge blocks of cpu_is_*() + * conditionals in this code. + */ +struct omap_hwmod_soc_ops { + void (*enable_module)(struct omap_hwmod *oh); + int (*disable_module)(struct omap_hwmod *oh); +}; + +/* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ +static struct omap_hwmod_soc_ops soc_ops; + /* omap_hwmod_list contains all registered struct omap_hwmods */ static LIST_HEAD(omap_hwmod_list); @@ -186,6 +203,9 @@ static struct omap_hwmod_link *linkspace; */ static unsigned short free_ls, max_ls, ls_supp; +/* inited: set to true once the hwmod code is initialized */ +static bool inited; + /* Private functions */ /** @@ -779,10 +799,6 @@ static void _disable_optional_clocks(struct omap_hwmod *oh) */ static void _omap4_enable_module(struct omap_hwmod *oh) { - /* The module mode does not exist prior OMAP4 */ - if (cpu_is_omap24xx() || cpu_is_omap34xx()) - return; - if (!oh->clkdm || !oh->prcm.omap4.modulemode) return; @@ -1571,10 +1587,6 @@ static int _omap4_disable_module(struct omap_hwmod *oh) { int v; - /* The module mode does not exist prior OMAP4 */ - if (!cpu_is_omap44xx()) - return -EINVAL; - if (!oh->clkdm || !oh->prcm.omap4.modulemode) return -EINVAL; @@ -1814,7 +1826,8 @@ static int _enable(struct omap_hwmod *oh) } _enable_clocks(oh); - _omap4_enable_module(oh); + if (soc_ops.enable_module) + soc_ops.enable_module(oh); r = _wait_target_ready(oh); if (!r) { @@ -1870,7 +1883,8 @@ static int _idle(struct omap_hwmod *oh) _idle_sysc(oh); _del_initiator_dep(oh, mpu_oh); - _omap4_disable_module(oh); + if (soc_ops.disable_module) + soc_ops.disable_module(oh); /* * The module must be in idle mode before disabling any parents @@ -1975,7 +1989,8 @@ static int _shutdown(struct omap_hwmod *oh) if (oh->_state == _HWMOD_STATE_ENABLED) { _del_initiator_dep(oh, mpu_oh); /* XXX what about the other system initiators here? dma, dsp */ - _omap4_disable_module(oh); + if (soc_ops.disable_module) + soc_ops.disable_module(oh); _disable_clocks(oh); if (oh->clkdm) clkdm_hwmod_disable(oh->clkdm, oh); @@ -2563,12 +2578,18 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data), * * Intended to be called early in boot before the clock framework is * initialized. If @ois is not null, will register all omap_hwmods - * listed in @ois that are valid for this chip. Returns 0. + * listed in @ois that are valid for this chip. Returns -EINVAL if + * omap_hwmod_init() hasn't been called before calling this function, + * -ENOMEM if the link memory area can't be allocated, or 0 upon + * success. */ int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois) { int r, i; + if (!inited) + return -EINVAL; + if (!ois) return 0; @@ -3401,3 +3422,20 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx) return 0; } + +/** + * omap_hwmod_init - initialize the hwmod code + * + * Sets up some function pointers needed by the hwmod code to operate on the + * currently-booted SoC. Intended to be called once during kernel init + * before any hwmods are registered. No return value. + */ +void __init omap_hwmod_init(void) +{ + if (cpu_is_omap44xx()) { + soc_ops.enable_module = _omap4_enable_module; + soc_ops.disable_module = _omap4_disable_module; + } + + inited = true; +} diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index a7640d1b215..5b1938b52d0 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -585,5 +585,6 @@ static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = { int __init omap2420_hwmod_init(void) { + omap_hwmod_init(); return omap_hwmod_register_links(omap2420_hwmod_ocp_ifs); } diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index 4d726498123..71f199783c6 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -938,5 +938,6 @@ static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = { int __init omap2430_hwmod_init(void) { + omap_hwmod_init(); return omap_hwmod_register_links(omap2430_hwmod_ocp_ifs); } diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index b26d3c9bca1..abb1f6b56ee 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -3283,6 +3283,8 @@ int __init omap3xxx_hwmod_init(void) struct omap_hwmod_ocp_if **h = NULL; unsigned int rev; + omap_hwmod_init(); + /* Register hwmod links common to all OMAP3 */ r = omap_hwmod_register_links(omap3xxx_hwmod_ocp_ifs); if (r < 0) diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 950454a3fa3..d3c48dc26af 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -6144,6 +6144,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { int __init omap44xx_hwmod_init(void) { + omap_hwmod_init(); return omap_hwmod_register_links(omap44xx_hwmod_ocp_ifs); } diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index c835b7194ff..a8ecc53b367 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -629,6 +629,8 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh); int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx); +extern void __init omap_hwmod_init(void); + /* * Chip variant-specific hwmod init routines - XXX should be converted * to use initcalls once the initial boot ordering is straightened out -- cgit v1.2.3-70-g09d2 From baa2607f56f1589eb21c01fe16aa5f5c3f9dad31 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 18 Jun 2012 12:12:24 -0600 Subject: ARM: OMAP4: hwmod: drop extra cpu_is check from _wait_target_disable() _omap4_wait_target_disable() is called only from inside _omap4_disable_module() which is already protected by SoC specific checks. Remove the cpu_is check here. Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/omap_hwmod.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 634a79836c6..2b845836f7d 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -823,9 +823,6 @@ static void _omap4_enable_module(struct omap_hwmod *oh) */ static int _omap4_wait_target_disable(struct omap_hwmod *oh) { - if (!cpu_is_omap44xx()) - return 0; - if (!oh) return -EINVAL; -- cgit v1.2.3-70-g09d2 From 8f6aa8ee114fb52a425e247e27e271ee35d7d3b3 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 18 Jun 2012 12:12:24 -0600 Subject: ARM: OMAP2+: hwmod: use init-time function pointer for wait_target_ready Rather than using cpu_is* checking at runtime, initialize an SoC specific function pointer for wait_target_ready(). While here, downgrade the BUG() to a WARN_ON() so it gives a noisy warning instead of causing a kernel panic. Signed-off-by: Kevin Hilman [paul@pwsan.com: convert to use soc_ops function pointers; add kerneldoc; move soc_ops functions to their own section in the code; integrated the _wait_target_ready() function with the OMAP2/OMAP4 variants; renamed the wait_module_ready field to wait_target_ready] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 115 ++++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 49 deletions(-) (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 2b845836f7d..d1f784cd5f0 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -178,6 +178,7 @@ struct omap_hwmod_soc_ops { void (*enable_module)(struct omap_hwmod *oh); int (*disable_module)(struct omap_hwmod *oh); + int (*wait_target_ready)(struct omap_hwmod *oh); }; /* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ @@ -1361,53 +1362,6 @@ static int _init_clocks(struct omap_hwmod *oh, void *data) return ret; } -/** - * _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 _wait_target_ready(struct omap_hwmod *oh) -{ - struct omap_hwmod_ocp_if *os; - int ret; - - if (!oh) - return -EINVAL; - - if (oh->flags & HWMOD_NO_IDLEST) - return 0; - - os = _find_mpu_rt_port(oh); - if (!os) - return 0; - - /* XXX check module SIDLEMODE */ - - /* XXX check clock enable states */ - - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - ret = omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs, - oh->prcm.omap2.idlest_reg_id, - oh->prcm.omap2.idlest_idle_bit); - } else if (cpu_is_omap44xx()) { - if (!oh->clkdm) - return -EINVAL; - - ret = omap4_cminst_wait_module_ready(oh->clkdm->prcm_partition, - oh->clkdm->cm_inst, - oh->clkdm->clkdm_offs, - oh->prcm.omap4.clkctrl_offs); - } else { - BUG(); - }; - - return ret; -} - /** * _lookup_hardreset - fill register bit info for this hwmod/reset line * @oh: struct omap_hwmod * @@ -1826,7 +1780,8 @@ static int _enable(struct omap_hwmod *oh) if (soc_ops.enable_module) soc_ops.enable_module(oh); - r = _wait_target_ready(oh); + r = (soc_ops.wait_target_ready) ? soc_ops.wait_target_ready(oh) : + -EINVAL; if (!r) { /* * Set the clockdomain to HW_AUTO only if the target is ready, @@ -2443,6 +2398,63 @@ static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois) return 0; } +/* Static functions intended only for use in soc_ops field function pointers */ + +/** + * _omap2_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 _omap2_wait_target_ready(struct omap_hwmod *oh) +{ + if (!oh) + return -EINVAL; + + if (oh->flags & HWMOD_NO_IDLEST) + return 0; + + if (!_find_mpu_rt_port(oh)) + return 0; + + /* XXX check module SIDLEMODE, hardreset status, enabled clocks */ + + return omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs, + oh->prcm.omap2.idlest_reg_id, + oh->prcm.omap2.idlest_idle_bit); +} + +/** + * _omap4_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 _omap4_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 omap4_cminst_wait_module_ready(oh->clkdm->prcm_partition, + oh->clkdm->cm_inst, + oh->clkdm->clkdm_offs, + oh->prcm.omap4.clkctrl_offs); +} + /* Public functions */ u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs) @@ -3429,9 +3441,14 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx) */ void __init omap_hwmod_init(void) { - if (cpu_is_omap44xx()) { + if (cpu_is_omap24xx() || cpu_is_omap34xx()) { + soc_ops.wait_target_ready = _omap2_wait_target_ready; + } else if (cpu_is_omap44xx()) { soc_ops.enable_module = _omap4_enable_module; soc_ops.disable_module = _omap4_disable_module; + soc_ops.wait_target_ready = _omap4_wait_target_ready; + } else { + WARN(1, "omap_hwmod: unknown SoC type\n"); } inited = true; -- cgit v1.2.3-70-g09d2 From b8249cf2d2b16de9582d3cbaa98c16c32c624d8a Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 18 Jun 2012 12:12:24 -0600 Subject: ARM: OMAP2+: hwmod: use init-time function pointer for hardreset Rather than using cpu_is* checking at runtime, initialize SoC specific function pointers for the various hard reset functions at init time. Signed-off-by: Kevin Hilman [paul@pwsan.com: convert to use soc_ops function pointers; add kerneldoc] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 216 ++++++++++++++++++++++++++++++--------- 1 file changed, 169 insertions(+), 47 deletions(-) (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index d1f784cd5f0..93cb96dbb54 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -179,6 +179,12 @@ struct omap_hwmod_soc_ops { void (*enable_module)(struct omap_hwmod *oh); int (*disable_module)(struct omap_hwmod *oh); int (*wait_target_ready)(struct omap_hwmod *oh); + int (*assert_hardreset)(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri); + int (*deassert_hardreset)(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri); + int (*is_hardreset_asserted)(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri); }; /* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ @@ -1398,32 +1404,31 @@ static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name, * @oh: struct omap_hwmod * * @name: name of the reset line to lookup and assert * - * Some IP like dsp, ipu or iva contain processor that require - * an HW reset line to be assert / deassert in order to enable fully - * the IP. + * Some IP like dsp, ipu or iva contain processor that require an HW + * reset line to be assert / deassert in order to enable fully the IP. + * Returns -EINVAL if @oh is null, -ENOSYS if we have no way of + * asserting the hardreset line on the currently-booted SoC, or passes + * along the return value from _lookup_hardreset() or the SoC's + * assert_hardreset code. */ static int _assert_hardreset(struct omap_hwmod *oh, const char *name) { struct omap_hwmod_rst_info ohri; - u8 ret; + u8 ret = -EINVAL; if (!oh) return -EINVAL; + if (!soc_ops.assert_hardreset) + return -ENOSYS; + ret = _lookup_hardreset(oh, name, &ohri); if (IS_ERR_VALUE(ret)) return ret; - if (cpu_is_omap24xx() || cpu_is_omap34xx()) - return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs, - ohri.rst_shift); - else if (cpu_is_omap44xx()) - return omap4_prminst_assert_hardreset(ohri.rst_shift, - oh->clkdm->pwrdm.ptr->prcm_partition, - oh->clkdm->pwrdm.ptr->prcm_offs, - oh->prcm.omap4.rstctrl_offs); - else - return -EINVAL; + ret = soc_ops.assert_hardreset(oh, &ohri); + + return ret; } /** @@ -1432,38 +1437,29 @@ static int _assert_hardreset(struct omap_hwmod *oh, const char *name) * @oh: struct omap_hwmod * * @name: name of the reset line to look up and deassert * - * Some IP like dsp, ipu or iva contain processor that require - * an HW reset line to be assert / deassert in order to enable fully - * the IP. + * Some IP like dsp, ipu or iva contain processor that require an HW + * reset line to be assert / deassert in order to enable fully the IP. + * Returns -EINVAL if @oh is null, -ENOSYS if we have no way of + * deasserting the hardreset line on the currently-booted SoC, or passes + * along the return value from _lookup_hardreset() or the SoC's + * deassert_hardreset code. */ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name) { struct omap_hwmod_rst_info ohri; - int ret; + int ret = -EINVAL; if (!oh) return -EINVAL; + if (!soc_ops.deassert_hardreset) + return -ENOSYS; + ret = _lookup_hardreset(oh, name, &ohri); if (IS_ERR_VALUE(ret)) return ret; - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - ret = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs, - ohri.rst_shift, - ohri.st_shift); - } else if (cpu_is_omap44xx()) { - if (ohri.st_shift) - pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n", - oh->name, name); - ret = omap4_prminst_deassert_hardreset(ohri.rst_shift, - oh->clkdm->pwrdm.ptr->prcm_partition, - oh->clkdm->pwrdm.ptr->prcm_offs, - oh->prcm.omap4.rstctrl_offs); - } else { - return -EINVAL; - } - + ret = soc_ops.deassert_hardreset(oh, &ohri); if (ret == -EBUSY) pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name); @@ -1476,31 +1472,28 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name) * @oh: struct omap_hwmod * * @name: name of the reset line to look up and read * - * Return the state of the reset line. + * Return the state of the reset line. Returns -EINVAL if @oh is + * null, -ENOSYS if we have no way of reading the hardreset line + * status on the currently-booted SoC, or passes along the return + * value from _lookup_hardreset() or the SoC's is_hardreset_asserted + * code. */ static int _read_hardreset(struct omap_hwmod *oh, const char *name) { struct omap_hwmod_rst_info ohri; - u8 ret; + u8 ret = -EINVAL; if (!oh) return -EINVAL; + if (!soc_ops.is_hardreset_asserted) + return -ENOSYS; + ret = _lookup_hardreset(oh, name, &ohri); if (IS_ERR_VALUE(ret)) return ret; - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs, - ohri.st_shift); - } else if (cpu_is_omap44xx()) { - return omap4_prminst_is_hardreset_asserted(ohri.rst_shift, - oh->clkdm->pwrdm.ptr->prcm_partition, - oh->clkdm->pwrdm.ptr->prcm_offs, - oh->prcm.omap4.rstctrl_offs); - } else { - return -EINVAL; - } + return soc_ops.is_hardreset_asserted(oh, &ohri); } /** @@ -2455,6 +2448,129 @@ static int _omap4_wait_target_ready(struct omap_hwmod *oh) 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 + * + * Call omap2_prm_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 omap2_prm_assert_hardreset(). XXX This function is scheduled + * for removal when the PRM code is moved into drivers/. + */ +static int _omap2_assert_hardreset(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri) +{ + return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs, + ohri->rst_shift); +} + +/** + * _omap2_deassert_hardreset - call OMAP2 PRM hardreset fn with hwmod args + * @oh: struct omap_hwmod * to deassert hardreset + * @ohri: hardreset line data + * + * Call omap2_prm_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 omap2_prm_deassert_hardreset(). XXX This function is + * scheduled for removal when the PRM code is moved into drivers/. + */ +static int _omap2_deassert_hardreset(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri) +{ + return omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs, + ohri->rst_shift, + ohri->st_shift); +} + +/** + * _omap2_is_hardreset_asserted - call OMAP2 PRM hardreset fn with hwmod args + * @oh: struct omap_hwmod * to test hardreset + * @ohri: hardreset line data + * + * Call omap2_prm_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 omap2_prm_is_hardreset_asserted(). XXX This + * function is scheduled for removal when the PRM code is moved into + * drivers/. + */ +static int _omap2_is_hardreset_asserted(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri) +{ + return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs, + ohri->st_shift); +} + +/** + * _omap4_assert_hardreset - call OMAP4 PRM hardreset fn with hwmod args + * @oh: struct omap_hwmod * to assert hardreset + * @ohri: hardreset line data + * + * Call omap4_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 omap4_prminst_assert_hardreset(). XXX This + * function is scheduled for removal when the PRM code is moved into + * drivers/. + */ +static int _omap4_assert_hardreset(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri) + +{ + return omap4_prminst_assert_hardreset(ohri->rst_shift, + oh->clkdm->pwrdm.ptr->prcm_partition, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.rstctrl_offs); +} + +/** + * _omap4_deassert_hardreset - call OMAP4 PRM hardreset fn with hwmod args + * @oh: struct omap_hwmod * to deassert hardreset + * @ohri: hardreset line data + * + * Call omap4_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 omap4_prminst_deassert_hardreset(). XXX This + * function is scheduled for removal when the PRM code is moved into + * drivers/. + */ +static int _omap4_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 omap4_prminst_deassert_hardreset(ohri->rst_shift, + oh->clkdm->pwrdm.ptr->prcm_partition, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.rstctrl_offs); +} + +/** + * _omap4_is_hardreset_asserted - call OMAP4 PRM hardreset fn with hwmod args + * @oh: struct omap_hwmod * to test hardreset + * @ohri: hardreset line data + * + * Call omap4_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 omap4_prminst_is_hardreset_asserted(). XXX + * This function is scheduled for removal when the PRM code is moved + * into drivers/. + */ +static int _omap4_is_hardreset_asserted(struct omap_hwmod *oh, + struct omap_hwmod_rst_info *ohri) +{ + return omap4_prminst_is_hardreset_asserted(ohri->rst_shift, + oh->clkdm->pwrdm.ptr->prcm_partition, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.rstctrl_offs); +} + /* Public functions */ u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs) @@ -3443,10 +3559,16 @@ void __init omap_hwmod_init(void) { if (cpu_is_omap24xx() || cpu_is_omap34xx()) { soc_ops.wait_target_ready = _omap2_wait_target_ready; + soc_ops.assert_hardreset = _omap2_assert_hardreset; + soc_ops.deassert_hardreset = _omap2_deassert_hardreset; + soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted; } else if (cpu_is_omap44xx()) { soc_ops.enable_module = _omap4_enable_module; soc_ops.disable_module = _omap4_disable_module; soc_ops.wait_target_ready = _omap4_wait_target_ready; + soc_ops.assert_hardreset = _omap4_assert_hardreset; + soc_ops.deassert_hardreset = _omap4_deassert_hardreset; + soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted; } else { WARN(1, "omap_hwmod: unknown SoC type\n"); } -- cgit v1.2.3-70-g09d2 From 0a179eaa436e58ed9fd00e09cdf01f1b3604d9a1 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 18 Jun 2012 12:12:25 -0600 Subject: ARM: OMAP2+: hwmod: use init-time function pointer for _init_clkdm Rather than use runtime cpu_is* checking inside _init_clkdm, initialize SoC specific function pointer at init time. Signed-off-by: Kevin Hilman [paul@pwsan.com: convert to use soc_ops function pointers; remove second para from commit message since soc_ops function pointers are now set during hwmod layer init] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 93cb96dbb54..acc616c02e1 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -185,6 +185,7 @@ struct omap_hwmod_soc_ops { struct omap_hwmod_rst_info *ohri); int (*is_hardreset_asserted)(struct omap_hwmod *oh, struct omap_hwmod_rst_info *ohri); + int (*init_clkdm)(struct omap_hwmod *oh); }; /* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ @@ -1315,9 +1316,6 @@ static struct omap_hwmod *_lookup(const char *name) */ static int _init_clkdm(struct omap_hwmod *oh) { - if (cpu_is_omap24xx() || cpu_is_omap34xx()) - return 0; - if (!oh->clkdm_name) { pr_warning("omap_hwmod: %s: no clkdm_name\n", oh->name); return -EINVAL; @@ -1358,7 +1356,8 @@ static int _init_clocks(struct omap_hwmod *oh, void *data) ret |= _init_main_clk(oh); ret |= _init_interface_clks(oh); ret |= _init_opt_clks(oh); - ret |= _init_clkdm(oh); + if (soc_ops.init_clkdm) + ret |= soc_ops.init_clkdm(oh); if (!ret) oh->_state = _HWMOD_STATE_CLKS_INITED; @@ -3569,6 +3568,7 @@ void __init omap_hwmod_init(void) soc_ops.assert_hardreset = _omap4_assert_hardreset; soc_ops.deassert_hardreset = _omap4_deassert_hardreset; soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted; + soc_ops.init_clkdm = _init_clkdm; } else { WARN(1, "omap_hwmod: unknown SoC type\n"); } -- cgit v1.2.3-70-g09d2 From 868c157df9721675c19729eed2c96bac6c3f1d01 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 19 Jun 2012 15:01:02 -0600 Subject: ARM: OMAP2+: hwmod: remove prm_clkdm, cm_clkdm; allow hwmods to have no clockdomain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove prm_clkdm and cm_clkdm and allow hwmods to have no clockdomain. Signed-off-by: Paul Walmsley Cc: Benoît Cousson --- arch/arm/mach-omap2/Makefile | 1 - arch/arm/mach-omap2/clockdomain.h | 2 -- arch/arm/mach-omap2/clockdomains2420_data.c | 2 -- arch/arm/mach-omap2/clockdomains2430_data.c | 2 -- arch/arm/mach-omap2/clockdomains3xxx_data.c | 2 -- arch/arm/mach-omap2/clockdomains44xx_data.c | 2 -- arch/arm/mach-omap2/clockdomains_common_data.c | 24 ---------------------- arch/arm/mach-omap2/omap_hwmod.c | 28 +++++++++++++++++--------- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 3 --- 9 files changed, 19 insertions(+), 47 deletions(-) delete mode 100644 arch/arm/mach-omap2/clockdomains_common_data.c (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index fa742f3c262..bc7d2393161 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -116,7 +116,6 @@ obj-$(CONFIG_ARCH_OMAP4) += powerdomains44xx_data.o # PRCM clockdomain control clockdomain-common += clockdomain.o -clockdomain-common += clockdomains_common_data.o obj-$(CONFIG_ARCH_OMAP2) += $(clockdomain-common) obj-$(CONFIG_ARCH_OMAP2) += clockdomain2xxx_3xxx.o obj-$(CONFIG_ARCH_OMAP2) += clockdomains2xxx_3xxx_data.o diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index f7b58609bad..349dcbb6fec 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -206,7 +206,5 @@ extern struct clkdm_ops omap4_clkdm_operations; extern struct clkdm_dep gfx_24xx_wkdeps[]; extern struct clkdm_dep dsp_24xx_wkdeps[]; extern struct clockdomain wkup_common_clkdm; -extern struct clockdomain prm_common_clkdm; -extern struct clockdomain cm_common_clkdm; #endif diff --git a/arch/arm/mach-omap2/clockdomains2420_data.c b/arch/arm/mach-omap2/clockdomains2420_data.c index 0ab8e46d5b2..5c741852fac 100644 --- a/arch/arm/mach-omap2/clockdomains2420_data.c +++ b/arch/arm/mach-omap2/clockdomains2420_data.c @@ -131,8 +131,6 @@ static struct clockdomain dss_2420_clkdm = { static struct clockdomain *clockdomains_omap242x[] __initdata = { &wkup_common_clkdm, - &cm_common_clkdm, - &prm_common_clkdm, &mpu_2420_clkdm, &iva1_2420_clkdm, &dsp_2420_clkdm, diff --git a/arch/arm/mach-omap2/clockdomains2430_data.c b/arch/arm/mach-omap2/clockdomains2430_data.c index 3645ed04489..f09617555e1 100644 --- a/arch/arm/mach-omap2/clockdomains2430_data.c +++ b/arch/arm/mach-omap2/clockdomains2430_data.c @@ -157,8 +157,6 @@ static struct clockdomain dss_2430_clkdm = { static struct clockdomain *clockdomains_omap243x[] __initdata = { &wkup_common_clkdm, - &cm_common_clkdm, - &prm_common_clkdm, &mpu_2430_clkdm, &mdm_clkdm, &dsp_2430_clkdm, diff --git a/arch/arm/mach-omap2/clockdomains3xxx_data.c b/arch/arm/mach-omap2/clockdomains3xxx_data.c index 6038adb9771..2cdc17c9d2f 100644 --- a/arch/arm/mach-omap2/clockdomains3xxx_data.c +++ b/arch/arm/mach-omap2/clockdomains3xxx_data.c @@ -347,8 +347,6 @@ static struct clkdm_autodep clkdm_autodeps[] = { static struct clockdomain *clockdomains_omap3430_common[] __initdata = { &wkup_common_clkdm, - &cm_common_clkdm, - &prm_common_clkdm, &mpu_3xxx_clkdm, &neon_clkdm, &iva2_clkdm, diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c index c5342584749..bd7ed13515c 100644 --- a/arch/arm/mach-omap2/clockdomains44xx_data.c +++ b/arch/arm/mach-omap2/clockdomains44xx_data.c @@ -430,8 +430,6 @@ static struct clockdomain *clockdomains_omap44xx[] __initdata = { &l4_wkup_44xx_clkdm, &emu_sys_44xx_clkdm, &l3_dma_44xx_clkdm, - &prm_common_clkdm, - &cm_common_clkdm, NULL }; diff --git a/arch/arm/mach-omap2/clockdomains_common_data.c b/arch/arm/mach-omap2/clockdomains_common_data.c deleted file mode 100644 index 615b1f04967..00000000000 --- a/arch/arm/mach-omap2/clockdomains_common_data.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * OMAP2+-common clockdomain data - * - * Copyright (C) 2008-2012 Texas Instruments, Inc. - * Copyright (C) 2008-2010 Nokia Corporation - * - * Paul Walmsley, Jouni Högander - */ - -#include -#include - -#include "clockdomain.h" - -/* These are implicit clockdomains - they are never defined as such in TRM */ -struct clockdomain prm_common_clkdm = { - .name = "prm_clkdm", - .pwrdm = { .name = "wkup_pwrdm" }, -}; - -struct clockdomain cm_common_clkdm = { - .name = "cm_clkdm", - .pwrdm = { .name = "core_pwrdm" }, -}; diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index bf86f7e8f91..32a5e08ffb9 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -810,7 +810,7 @@ static int _omap4_wait_target_disable(struct omap_hwmod *oh) if (!cpu_is_omap44xx()) return 0; - if (!oh) + if (!oh || !oh->clkdm) return -EINVAL; if (oh->_int_flags & _HWMOD_NO_MPU_PORT) @@ -1285,23 +1285,22 @@ static struct omap_hwmod *_lookup(const char *name) return oh; } + /** * _init_clkdm - look up a clockdomain name, store pointer in omap_hwmod * @oh: struct omap_hwmod * * * Convert a clockdomain name stored in a struct omap_hwmod into a * clockdomain pointer, and save it into the struct omap_hwmod. - * return -EINVAL if clkdm_name does not exist or if the lookup failed. + * Return -EINVAL if the clkdm_name lookup failed. */ static int _init_clkdm(struct omap_hwmod *oh) { if (cpu_is_omap24xx() || cpu_is_omap34xx()) return 0; - if (!oh->clkdm_name) { - pr_warning("omap_hwmod: %s: no clkdm_name\n", oh->name); - return -EINVAL; - } + if (!oh->clkdm_name) + return 0; oh->clkdm = clkdm_lookup(oh->clkdm_name); if (!oh->clkdm) { @@ -1447,16 +1446,20 @@ static int _assert_hardreset(struct omap_hwmod *oh, const char *name) if (IS_ERR_VALUE(ret)) return ret; - if (cpu_is_omap24xx() || cpu_is_omap34xx()) + if (cpu_is_omap24xx() || cpu_is_omap34xx()) { return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs, ohri.rst_shift); - else if (cpu_is_omap44xx()) + } else if (cpu_is_omap44xx()) { + if (!oh->clkdm) + return -EINVAL; + return omap4_prminst_assert_hardreset(ohri.rst_shift, oh->clkdm->pwrdm.ptr->prcm_partition, oh->clkdm->pwrdm.ptr->prcm_offs, oh->prcm.omap4.rstctrl_offs); - else + } else { return -EINVAL; + } } /** @@ -1489,6 +1492,10 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name) if (ohri.st_shift) pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n", oh->name, name); + + if (!oh->clkdm) + return -EINVAL; + ret = omap4_prminst_deassert_hardreset(ohri.rst_shift, oh->clkdm->pwrdm.ptr->prcm_partition, oh->clkdm->pwrdm.ptr->prcm_offs, @@ -1527,6 +1534,9 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name) return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs, ohri.st_shift); } else if (cpu_is_omap44xx()) { + if (!oh->clkdm) + return -EINVAL; + return omap4_prminst_is_hardreset_asserted(ohri.rst_shift, oh->clkdm->pwrdm.ptr->prcm_partition, oh->clkdm->pwrdm.ptr->prcm_offs, diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 950454a3fa3..e9e9ec0df64 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -2540,14 +2540,12 @@ static struct omap_hwmod omap44xx_prcm_mpu_hwmod = { static struct omap_hwmod omap44xx_cm_core_aon_hwmod = { .name = "cm_core_aon", .class = &omap44xx_prcm_hwmod_class, - .clkdm_name = "cm_clkdm", }; /* cm_core */ static struct omap_hwmod omap44xx_cm_core_hwmod = { .name = "cm_core", .class = &omap44xx_prcm_hwmod_class, - .clkdm_name = "cm_clkdm", }; /* prm */ @@ -2564,7 +2562,6 @@ static struct omap_hwmod_rst_info omap44xx_prm_resets[] = { static struct omap_hwmod omap44xx_prm_hwmod = { .name = "prm", .class = &omap44xx_prcm_hwmod_class, - .clkdm_name = "prm_clkdm", .mpu_irqs = omap44xx_prm_irqs, .rst_lines = omap44xx_prm_resets, .rst_lines_cnt = ARRAY_SIZE(omap44xx_prm_resets), -- cgit v1.2.3-70-g09d2 From 5165882a387325ac0df2f30c62ea710cfa328b54 Mon Sep 17 00:00:00 2001 From: Vishwanath BS Date: Fri, 22 Jun 2012 08:40:04 -0600 Subject: ARM: OMAP3PLUS: hwmod: reconfigure IO Daisychain during hwmod mux IO Daisychain feature has to be triggered whenever there is a change in device's mux configuration (See section 3.9.4 in OMAP4 Public TRM vP). Now devices can idle independent of the powerdomain, there can be a window where device is idled and corresponding powerdomain can be ON/INACTIVE state. In such situations, since both module wake up is enabled at padlevel as well as io daisychain sequence is triggered, there will be 2 PRCM interrupts (Module async wake up via swakeup and IO Pad interrupt). But as PRCM Interrupt handler clears the Module Padlevel WKST bit in the first interrupt, module specific interrupt handler will not triggered for the second time Also look at detailed explanation given by Rajendra at http://www.spinics.net/lists/linux-serial/msg04480.html Signed-off-by: Vishwanath BS Signed-off-by: Tero Kristo Reviewed-by: Rajendra Nayak [paul@pwsan.com: remove dependency on pm.c & pm.h; add kerneldoc] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index bf86f7e8f91..6d6c31a10a1 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -153,6 +153,7 @@ #include "prm44xx.h" #include "prminst44xx.h" #include "mux.h" +#include "pm.h" /* Maximum microseconds to wait for OMAP module to softreset */ #define MAX_MODULE_SOFTRESET_WAIT 10000 @@ -172,6 +173,9 @@ static LIST_HEAD(omap_hwmod_list); /* mpu_oh: used to add/remove MPU initiator from sleepdep list */ static struct omap_hwmod *mpu_oh; +/* io_chain_lock: used to serialize reconfigurations of the I/O chain */ +static DEFINE_SPINLOCK(io_chain_lock); + /* * linkspace: ptr to a buffer that struct omap_hwmod_link records are * allocated from - used to reduce the number of small memory @@ -1737,6 +1741,32 @@ static int _reset(struct omap_hwmod *oh) return r; } +/** + * _reconfigure_io_chain - clear any I/O chain wakeups and reconfigure chain + * + * Call the appropriate PRM function to clear any logged I/O chain + * wakeups and to reconfigure the chain. This apparently needs to be + * done upon every mux change. Since hwmods can be concurrently + * enabled and idled, hold a spinlock around the I/O chain + * reconfiguration sequence. No return value. + * + * XXX When the PRM code is moved to drivers, this function can be removed, + * as the PRM infrastructure should abstract this. + */ +static void _reconfigure_io_chain(void) +{ + unsigned long flags; + + spin_lock_irqsave(&io_chain_lock, flags); + + if (cpu_is_omap34xx() && omap3_has_io_chain_ctrl()) + omap3xxx_prm_reconfigure_io_chain(); + else if (cpu_is_omap44xx()) + omap44xx_prm_reconfigure_io_chain(); + + spin_unlock_irqrestore(&io_chain_lock, flags); +} + /** * _enable - enable an omap_hwmod * @oh: struct omap_hwmod * @@ -1793,8 +1823,10 @@ static int _enable(struct omap_hwmod *oh) /* Mux pins for device runtime if populated */ if (oh->mux && (!oh->mux->enabled || ((oh->_state == _HWMOD_STATE_IDLE) && - oh->mux->pads_dynamic))) + oh->mux->pads_dynamic))) { omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED); + _reconfigure_io_chain(); + } _add_initiator_dep(oh, mpu_oh); @@ -1883,8 +1915,10 @@ static int _idle(struct omap_hwmod *oh) clkdm_hwmod_disable(oh->clkdm, oh); /* Mux pins for device idle if populated */ - if (oh->mux && oh->mux->pads_dynamic) + if (oh->mux && oh->mux->pads_dynamic) { omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE); + _reconfigure_io_chain(); + } oh->_state = _HWMOD_STATE_IDLE; -- cgit v1.2.3-70-g09d2 From bed9d1bb4ed8c9bdaca77d31a2562c3a9dae43a7 Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Wed, 4 Jul 2012 05:00:48 -0600 Subject: ARM: OMAP2+: hwmod: add omap_hwmod_get_main_clk() API Add an API to get main clock name associated with a given @oh. This will avoid the need to construct fclk names during early initialization in order to get fclk handle using clk_get(). Signed-off-by: Tarun Kanti DebBarma Cc: Benoit Cousson Cc: Paul Walmsley Cc: Tony Lindgren Cc: Kevin Hilman Cc: Rajendra Nayak Cc: Santosh Shilimkar Acked-by: Benoit Cousson Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 15 +++++++++++++++ arch/arm/plat-omap/include/plat/omap_hwmod.h | 2 ++ 2 files changed, 17 insertions(+) (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 773193670ea..a89214ee469 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -3401,3 +3401,18 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx) return 0; } + +/** + * omap_hwmod_get_main_clk - get pointer to main clock name + * @oh: struct omap_hwmod * + * + * Returns the main clock name assocated with @oh upon success, + * or NULL if @oh is NULL. + */ +const char *omap_hwmod_get_main_clk(struct omap_hwmod *oh) +{ + if (!oh) + return NULL; + + return oh->main_clk; +} diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index c835b7194ff..da22acd0ce7 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -629,6 +629,8 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh); int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx); +const char *omap_hwmod_get_main_clk(struct omap_hwmod *oh); + /* * Chip variant-specific hwmod init routines - XXX should be converted * to use initcalls once the initial boot ordering is straightened out -- cgit v1.2.3-70-g09d2 From 6668546f3bb4cc0dde75ac1ef1d436b67e4ef638 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Wed, 4 Jul 2012 05:09:21 -0600 Subject: ARM: OMAP2+: hwmod code: add support to set dmadisable in hwmod framework The DMADISABLE bit is a semi-automatic bit present in sysconfig register of some modules. When the DMA must perform read/write accesses, the DMADISABLE bit is cleared by the hardware. But when the DMA must stop for power management, software must set the DMADISABLE bit back to 1. In cases where the ROMCODE/BOOTLOADER uses dma, the hardware clears the DMADISABLE bit (but the romcode/bootloader might not set it back to 1). In order for the kernel to start in a clean state, it is necessary for the kernel to set DMADISABLE bit back to 1 (irrespective of whether it's been set to 1 in romcode or bootloader). During _reset of the (hwmod)device, the DMADISABLE bit is set so that it does not prevent idling of the system. (NOTE: having DMADISABLE to 0, prevents the system to idle) DMADISABLE bit is present in usbotgss module of omap5. Cc: Benoit Cousson Cc: Kevin Hilman Cc: Paul Walmsley Signed-off-by: Kishon Vijay Abraham I [paul@pwsan.com: updated to apply; fixed checkpatch warnings] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 61 +++++++++++++++++++++++++--- arch/arm/mach-omap2/omap_hwmod_common_data.c | 1 + arch/arm/plat-omap/include/plat/omap_hwmod.h | 5 +++ 3 files changed, 62 insertions(+), 5 deletions(-) (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index a89214ee469..98cde62c0ca 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -387,6 +387,49 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v) return 0; } +/** + * _set_dmadisable: set OCP_SYSCONFIG.DMADISABLE bit in @v + * @oh: struct omap_hwmod * + * + * The DMADISABLE bit is a semi-automatic bit present in sysconfig register + * of some modules. When the DMA must perform read/write accesses, the + * DMADISABLE bit is cleared by the hardware. But when the DMA must stop + * for power management, software must set the DMADISABLE bit back to 1. + * + * Set the DMADISABLE bit in @v for hwmod @oh. Returns -EINVAL upon + * error or 0 upon success. + */ +static int _set_dmadisable(struct omap_hwmod *oh) +{ + u32 v; + u32 dmadisable_mask; + + if (!oh->class->sysc || + !(oh->class->sysc->sysc_flags & SYSC_HAS_DMADISABLE)) + return -EINVAL; + + if (!oh->class->sysc->sysc_fields) { + WARN(1, "omap_hwmod: %s: offset struct for sysconfig not provided in class\n", oh->name); + return -EINVAL; + } + + /* clocks must be on for this operation */ + if (oh->_state != _HWMOD_STATE_ENABLED) { + pr_warn("omap_hwmod: %s: dma can be disabled only from enabled state\n", oh->name); + return -EINVAL; + } + + pr_debug("omap_hwmod: %s: setting DMADISABLE\n", oh->name); + + v = oh->_sysc_cache; + dmadisable_mask = + (0x1 << oh->class->sysc->sysc_fields->dmadisable_shift); + v |= dmadisable_mask; + _write_sysconfig(v, oh); + + return 0; +} + /** * _set_module_autoidle: set the OCP_SYSCONFIG AUTOIDLE field in @v * @oh: struct omap_hwmod * @@ -1698,11 +1741,17 @@ dis_opt_clks: * therefore have no OCP header registers to access. Others (like the * IVA) have idiosyncratic reset sequences. So for these relatively * rare cases, custom reset code can be supplied in the struct - * omap_hwmod_class .reset function pointer. Passes along the return - * value from either _ocp_softreset() or the custom reset function - - * these must return -EINVAL if the hwmod cannot be reset this way or - * if the hwmod is in the wrong state, -ETIMEDOUT if the module did - * not reset in time, or 0 upon success. + * omap_hwmod_class .reset function pointer. + * + * _set_dmadisable() is called to set the DMADISABLE bit so that it + * does not prevent idling of the system. This is necessary for cases + * where ROMCODE/BOOTLOADER uses dma and transfers control to the + * kernel without disabling dma. + * + * Passes along the return value from either _ocp_softreset() or the + * custom reset function - these must return -EINVAL if the hwmod + * cannot be reset this way or if the hwmod is in the wrong state, + * -ETIMEDOUT if the module did not reset in time, or 0 upon success. */ static int _reset(struct omap_hwmod *oh) { @@ -1724,6 +1773,8 @@ static int _reset(struct omap_hwmod *oh) } } + _set_dmadisable(oh); + /* * OCP_SYSCONFIG bits need to be reprogrammed after a * softreset. The _enable() function should be split to avoid diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.c b/arch/arm/mach-omap2/omap_hwmod_common_data.c index 51e5418899f..aff61385291 100644 --- a/arch/arm/mach-omap2/omap_hwmod_common_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_common_data.c @@ -47,6 +47,7 @@ struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2 = { .midle_shift = SYSC_TYPE2_MIDLEMODE_SHIFT, .sidle_shift = SYSC_TYPE2_SIDLEMODE_SHIFT, .srst_shift = SYSC_TYPE2_SOFTRESET_SHIFT, + .dmadisable_shift = SYSC_TYPE2_DMADISABLE_SHIFT, }; struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr = { diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index da22acd0ce7..27455ed0a2a 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -69,6 +69,8 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2; #define SYSC_TYPE2_SIDLEMODE_MASK (0x3 << SYSC_TYPE2_SIDLEMODE_SHIFT) #define SYSC_TYPE2_MIDLEMODE_SHIFT 4 #define SYSC_TYPE2_MIDLEMODE_MASK (0x3 << SYSC_TYPE2_MIDLEMODE_SHIFT) +#define SYSC_TYPE2_DMADISABLE_SHIFT 16 +#define SYSC_TYPE2_DMADISABLE_MASK (0x1 << SYSC_TYPE2_DMADISABLE_SHIFT) /* OCP SYSSTATUS bit shifts/masks */ #define SYSS_RESETDONE_SHIFT 0 @@ -283,6 +285,7 @@ struct omap_hwmod_ocp_if { #define SYSS_HAS_RESET_STATUS (1 << 7) #define SYSC_NO_CACHE (1 << 8) /* XXX SW flag, belongs elsewhere */ #define SYSC_HAS_RESET_STATUS (1 << 9) +#define SYSC_HAS_DMADISABLE (1 << 10) /* omap_hwmod_sysconfig.clockact flags */ #define CLOCKACT_TEST_BOTH 0x0 @@ -298,6 +301,7 @@ struct omap_hwmod_ocp_if { * @enwkup_shift: Offset of the enawakeup bit * @srst_shift: Offset of the softreset bit * @autoidle_shift: Offset of the autoidle bit + * @dmadisable_shift: Offset of the dmadisable bit */ struct omap_hwmod_sysc_fields { u8 midle_shift; @@ -306,6 +310,7 @@ struct omap_hwmod_sysc_fields { u8 enwkup_shift; u8 srst_shift; u8 autoidle_shift; + u8 dmadisable_shift; }; /** -- cgit v1.2.3-70-g09d2 From 68c9a95e9253ce1776bd21bf8d37ddf213cced66 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 6 Jul 2012 00:58:43 -0700 Subject: ARM: OMAP2+: Fix mismerge for omap_hwmod_get_main_clk() API Commit ac5b0ea3d (Merge tag 'omap-devel-f-for-3.6'...) had a merge conflict that somehow got incorrecly resolved in a lossy way for commit bed9d1bb (ARM: OMAP2+: hwmod: add omap_hwmod_get_main_clk() API). Fix the issue by applying the missing pieces. Reported-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod.c | 15 +++++++++++++++ arch/arm/plat-omap/include/plat/omap_hwmod.h | 2 ++ 2 files changed, 17 insertions(+) (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index ebdf0016e53..ff76ef1d723 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -3633,3 +3633,18 @@ void __init omap_hwmod_init(void) inited = true; } + +/** + * omap_hwmod_get_main_clk - get pointer to main clock name + * @oh: struct omap_hwmod * + * + * Returns the main clock name assocated with @oh upon success, + * or NULL if @oh is NULL. + */ +const char *omap_hwmod_get_main_clk(struct omap_hwmod *oh) +{ + if (!oh) + return NULL; + + return oh->main_clk; +} diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 30f55eb8b0b..6132972aff3 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -648,6 +648,8 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx); extern void __init omap_hwmod_init(void); +const char *omap_hwmod_get_main_clk(struct omap_hwmod *oh); + /* * Chip variant-specific hwmod init routines - XXX should be converted * to use initcalls once the initial boot ordering is straightened out -- cgit v1.2.3-70-g09d2 From 05e152c76a1efaa3165afecf5acf535c8283f386 Mon Sep 17 00:00:00 2001 From: R Sricharan Date: Tue, 5 Jun 2012 16:21:32 +0530 Subject: ARM: OMAP5: Add minimal support for OMAP5430 SOC OMAP5430 is Texas Instrument's SOC based on ARM Cortex-A15 SMP architecture. It's a dual core SOC with GIC used for interrupt handling and with an integrated L2 cache controller. OMAP5432 is another variant of OMAP5430, with a memory controller supporting DDR3 and SATA. Patch includes: - The machine specific headers and sources updates. - Platform header updates. - Minimum initialisation support for serial. - IO table init Signed-off-by: R Sricharan Signed-off-by: Santosh Shilimkar --- arch/arm/mach-omap2/Makefile | 23 +++++++++++--- arch/arm/mach-omap2/common.c | 24 ++++++++++++++ arch/arm/mach-omap2/common.h | 11 +++++++ arch/arm/mach-omap2/include/mach/debug-macro.S | 8 ++--- arch/arm/mach-omap2/io.c | 44 ++++++++++++++++++++++++++ arch/arm/mach-omap2/iomap.h | 27 ++++++++++++++++ arch/arm/mach-omap2/omap_hwmod.c | 2 +- arch/arm/mach-omap2/prcm-common.h | 2 +- arch/arm/mach-omap2/prcm.c | 2 +- arch/arm/plat-omap/include/plat/hardware.h | 1 + arch/arm/plat-omap/include/plat/multi.h | 9 ++++++ arch/arm/plat-omap/include/plat/omap54xx.h | 32 +++++++++++++++++++ arch/arm/plat-omap/include/plat/serial.h | 10 ++++++ arch/arm/plat-omap/include/plat/uncompress.h | 6 ++++ arch/arm/plat-omap/sram.c | 11 +++++-- 15 files changed, 198 insertions(+), 14 deletions(-) create mode 100644 arch/arm/plat-omap/include/plat/omap54xx.h (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 240f1969f2a..085e17175ef 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common) obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common) obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common) $(secure-common) obj-$(CONFIG_SOC_AM33XX) += irq.o $(hwmod-common) +obj-$(CONFIG_SOC_OMAP5) += prm44xx.o $(hwmod-common) $(secure-common) ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),) obj-y += mcbsp.o @@ -29,8 +30,10 @@ obj-$(CONFIG_SOC_HAS_OMAP2_SDRC) += sdrc.o obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o -obj-$(CONFIG_ARCH_OMAP4) += omap4-common.o omap-wakeupgen.o -obj-$(CONFIG_ARCH_OMAP4) += sleep44xx.o +omap-4-5-common = omap4-common.o omap-wakeupgen.o \ + sleep44xx.o +obj-$(CONFIG_ARCH_OMAP4) += $(omap-4-5-common) +obj-$(CONFIG_SOC_OMAP5) += $(omap-4-5-common) plus_sec := $(call as-instr,.arch_extension sec,+sec) AFLAGS_omap-headsmp.o :=-Wa,-march=armv7-a$(plus_sec) @@ -70,6 +73,7 @@ obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o obj-$(CONFIG_ARCH_OMAP3) += cpuidle34xx.o obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o omap-mpuss-lowpower.o +obj-$(CONFIG_SOC_OMAP5) += omap-mpuss-lowpower.o obj-$(CONFIG_ARCH_OMAP4) += cpuidle44xx.o obj-$(CONFIG_PM_DEBUG) += pm-debug.o obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o @@ -85,14 +89,16 @@ endif endif # PRCM +omap-prcm-4-5-common = prcm.o cminst44xx.o cm44xx.o \ + prcm_mpu44xx.o prminst44xx.o \ + vc44xx_data.o vp44xx_data.o obj-y += prm_common.o obj-$(CONFIG_ARCH_OMAP2) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o obj-$(CONFIG_ARCH_OMAP3) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o obj-$(CONFIG_ARCH_OMAP3) += vc3xxx_data.o vp3xxx_data.o -obj-$(CONFIG_ARCH_OMAP4) += prcm.o cminst44xx.o cm44xx.o -obj-$(CONFIG_ARCH_OMAP4) += prcm_mpu44xx.o prminst44xx.o -obj-$(CONFIG_ARCH_OMAP4) += vc44xx_data.o vp44xx_data.o prm44xx.o obj-$(CONFIG_SOC_AM33XX) += prcm.o prm33xx.o cm33xx.o +obj-$(CONFIG_ARCH_OMAP4) += $(omap-prcm-4-5-common) prm44xx.o +obj-$(CONFIG_SOC_OMAP5) += $(omap-prcm-4-5-common) # OMAP voltage domains voltagedomain-common := voltage.o vc.o vp.o @@ -104,6 +110,7 @@ obj-$(CONFIG_ARCH_OMAP4) += $(voltagedomain-common) obj-$(CONFIG_ARCH_OMAP4) += voltagedomains44xx_data.o obj-$(CONFIG_SOC_AM33XX) += $(voltagedomain-common) obj-$(CONFIG_SOC_AM33XX) += voltagedomains33xx_data.o +obj-$(CONFIG_SOC_OMAP5) += $(voltagedomain-common) # OMAP powerdomain framework powerdomain-common += powerdomain.o powerdomain-common.o @@ -121,6 +128,8 @@ obj-$(CONFIG_ARCH_OMAP4) += powerdomains44xx_data.o obj-$(CONFIG_SOC_AM33XX) += $(powerdomain-common) obj-$(CONFIG_SOC_AM33XX) += powerdomain33xx.o obj-$(CONFIG_SOC_AM33XX) += powerdomains33xx_data.o +obj-$(CONFIG_SOC_OMAP5) += $(powerdomain-common) +obj-$(CONFIG_SOC_OMAP5) += powerdomain44xx.o # PRCM clockdomain control clockdomain-common += clockdomain.o @@ -139,6 +148,8 @@ obj-$(CONFIG_ARCH_OMAP4) += clockdomains44xx_data.o obj-$(CONFIG_SOC_AM33XX) += $(clockdomain-common) obj-$(CONFIG_SOC_AM33XX) += clockdomain33xx.o obj-$(CONFIG_SOC_AM33XX) += clockdomains33xx_data.o +obj-$(CONFIG_SOC_OMAP5) += $(clockdomain-common) +obj-$(CONFIG_SOC_OMAP5) += clockdomain44xx.o # Clock framework obj-$(CONFIG_ARCH_OMAP2) += $(clock-common) clock2xxx.o @@ -157,6 +168,8 @@ obj-$(CONFIG_ARCH_OMAP3) += clkt_iclk.o obj-$(CONFIG_ARCH_OMAP4) += $(clock-common) clock44xx_data.o obj-$(CONFIG_ARCH_OMAP4) += dpll3xxx.o dpll44xx.o obj-$(CONFIG_SOC_AM33XX) += $(clock-common) dpll3xxx.o +obj-$(CONFIG_SOC_OMAP5) += $(clock-common) +obj-$(CONFIG_SOC_OMAP5) += dpll3xxx.o dpll44xx.o # OMAP2 clock rate set data (old "OPP" data) obj-$(CONFIG_SOC_OMAP2420) += opp2420_data.o diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c index 73d2a0b9ca0..069f9725b1c 100644 --- a/arch/arm/mach-omap2/common.c +++ b/arch/arm/mach-omap2/common.c @@ -178,3 +178,27 @@ void __init omap4_map_io(void) } #endif +#if defined(CONFIG_SOC_OMAP5) +static struct omap_globals omap5_globals = { + .class = OMAP54XX_CLASS, + .tap = OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE), + .ctrl = OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE), + .ctrl_pad = OMAP2_L4_IO_ADDRESS(OMAP54XX_CTRL_BASE), + .prm = OMAP2_L4_IO_ADDRESS(OMAP54XX_PRM_BASE), + .cm = OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_AON_BASE), + .cm2 = OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_BASE), + .prcm_mpu = OMAP2_L4_IO_ADDRESS(OMAP54XX_PRCM_MPU_BASE), +}; + +void __init omap2_set_globals_5xxx(void) +{ + omap2_set_globals_tap(&omap5_globals); + omap2_set_globals_control(&omap5_globals); + omap2_set_globals_prcm(&omap5_globals); +} + +void __init omap5_map_io(void) +{ + omap5_map_common_io(); +} +#endif diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index 404f172d95a..399e5bb1383 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h @@ -115,6 +115,14 @@ static inline int omap_mux_late_init(void) } #endif +#ifdef CONFIG_SOC_OMAP5 +extern void omap5_map_common_io(void); +#else +static inline void omap5_map_common_io(void) +{ +} +#endif + extern void omap2_init_common_infrastructure(void); extern struct sys_timer omap2_timer; @@ -134,6 +142,7 @@ void am35xx_init_early(void); void ti81xx_init_early(void); void am33xx_init_early(void); void omap4430_init_early(void); +void omap5_init_early(void); void omap3_init_late(void); /* Do not use this one */ void omap4430_init_late(void); void omap2420_init_late(void); @@ -169,6 +178,7 @@ void omap2_set_globals_242x(void); void omap2_set_globals_243x(void); void omap2_set_globals_3xxx(void); void omap2_set_globals_443x(void); +void omap2_set_globals_5xxx(void); void omap2_set_globals_ti81xx(void); void omap2_set_globals_am33xx(void); @@ -188,6 +198,7 @@ void omap243x_map_io(void); void omap3_map_io(void); void am33xx_map_io(void); void omap4_map_io(void); +void omap5_map_io(void); void ti81xx_map_io(void); void omap_barriers_init(void); diff --git a/arch/arm/mach-omap2/include/mach/debug-macro.S b/arch/arm/mach-omap2/include/mach/debug-macro.S index d7f844a99a7..93d10de7129 100644 --- a/arch/arm/mach-omap2/include/mach/debug-macro.S +++ b/arch/arm/mach-omap2/include/mach/debug-macro.S @@ -60,12 +60,12 @@ omap_uart_lsr: .word 0 beq 23f @ configure OMAP2UART3 cmp \rp, #OMAP3UART3 @ only on 34xx beq 33f @ configure OMAP3UART3 - cmp \rp, #OMAP4UART3 @ only on 44xx - beq 43f @ configure OMAP4UART3 + cmp \rp, #OMAP4UART3 @ only on 44xx/54xx + beq 43f @ configure OMAP4/5UART3 cmp \rp, #OMAP3UART4 @ only on 36xx beq 34f @ configure OMAP3UART4 - cmp \rp, #OMAP4UART4 @ only on 44xx - beq 44f @ configure OMAP4UART4 + cmp \rp, #OMAP4UART4 @ only on 44xx/54xx + beq 44f @ configure OMAP4/5UART4 cmp \rp, #TI81XXUART1 @ ti81Xx UART offsets different beq 81f @ configure UART1 cmp \rp, #TI81XXUART2 @ ti81Xx UART offsets different diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index cb6c11cd8df..8976be90c8e 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -233,6 +233,35 @@ static struct map_desc omap44xx_io_desc[] __initdata = { }; #endif +#ifdef CONFIG_SOC_OMAP5 +static struct map_desc omap54xx_io_desc[] __initdata = { + { + .virtual = L3_54XX_VIRT, + .pfn = __phys_to_pfn(L3_54XX_PHYS), + .length = L3_54XX_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = L4_54XX_VIRT, + .pfn = __phys_to_pfn(L4_54XX_PHYS), + .length = L4_54XX_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = L4_WK_54XX_VIRT, + .pfn = __phys_to_pfn(L4_WK_54XX_PHYS), + .length = L4_WK_54XX_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = L4_PER_54XX_VIRT, + .pfn = __phys_to_pfn(L4_PER_54XX_PHYS), + .length = L4_PER_54XX_SIZE, + .type = MT_DEVICE, + }, +}; +#endif + #ifdef CONFIG_SOC_OMAP2420 void __init omap242x_map_common_io(void) { @@ -278,6 +307,12 @@ void __init omap44xx_map_common_io(void) } #endif +#ifdef CONFIG_SOC_OMAP5 +void __init omap5_map_common_io(void) +{ + iotable_init(omap54xx_io_desc, ARRAY_SIZE(omap54xx_io_desc)); +} +#endif /* * omap2_init_reprogram_sdrc - reprogram SDRC timing parameters * @@ -513,6 +548,15 @@ void __init omap4430_init_late(void) } #endif +#ifdef CONFIG_SOC_OMAP5 +void __init omap5_init_early(void) +{ + omap2_set_globals_5xxx(); + omap5xxx_check_revision(); + omap_common_init_early(); +} +#endif + void __init omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0, struct omap_sdrc_params *sdrc_cs1) { diff --git a/arch/arm/mach-omap2/iomap.h b/arch/arm/mach-omap2/iomap.h index 80b88921fab..cce2b65039f 100644 --- a/arch/arm/mach-omap2/iomap.h +++ b/arch/arm/mach-omap2/iomap.h @@ -1,6 +1,14 @@ /* * IO mappings for OMAP2+ * + * IO definitions for TI OMAP processors and boards + * + * Copied from arch/arm/mach-sa1100/include/mach/io.h + * Copyright (C) 1997-1999 Russell King + * + * Copyright (C) 2009-2012 Texas Instruments + * Added OMAP4/5 support - Santosh Shilimkar + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your @@ -166,4 +174,23 @@ /* 0x49000000 --> 0xfb000000 */ #define L4_ABE_44XX_VIRT (L4_ABE_44XX_PHYS + OMAP2_L4_IO_OFFSET) #define L4_ABE_44XX_SIZE SZ_1M +/* + * ---------------------------------------------------------------------------- + * Omap5 specific IO mapping + * ---------------------------------------------------------------------------- + */ +#define L3_54XX_PHYS L3_54XX_BASE /* 0x44000000 --> 0xf8000000 */ +#define L3_54XX_VIRT (L3_54XX_PHYS + OMAP4_L3_IO_OFFSET) +#define L3_54XX_SIZE SZ_1M + +#define L4_54XX_PHYS L4_54XX_BASE /* 0x4a000000 --> 0xfc000000 */ +#define L4_54XX_VIRT (L4_54XX_PHYS + OMAP2_L4_IO_OFFSET) +#define L4_54XX_SIZE SZ_4M + +#define L4_WK_54XX_PHYS L4_WK_54XX_BASE /* 0x4ae00000 --> 0xfce00000 */ +#define L4_WK_54XX_VIRT (L4_WK_54XX_PHYS + OMAP2_L4_IO_OFFSET) +#define L4_WK_54XX_SIZE SZ_2M +#define L4_PER_54XX_PHYS L4_PER_54XX_BASE /* 0x48000000 --> 0xfa000000 */ +#define L4_PER_54XX_VIRT (L4_PER_54XX_PHYS + OMAP2_L4_IO_OFFSET) +#define L4_PER_54XX_SIZE SZ_4M diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index ff76ef1d723..2ada3642c67 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -3619,7 +3619,7 @@ void __init omap_hwmod_init(void) soc_ops.assert_hardreset = _omap2_assert_hardreset; soc_ops.deassert_hardreset = _omap2_deassert_hardreset; soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted; - } else if (cpu_is_omap44xx()) { + } else if (cpu_is_omap44xx() || soc_is_omap54xx()) { soc_ops.enable_module = _omap4_enable_module; soc_ops.disable_module = _omap4_disable_module; soc_ops.wait_target_ready = _omap4_wait_target_ready; diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h index 6da3ba483ad..44485a8f255 100644 --- a/arch/arm/mach-omap2/prcm-common.h +++ b/arch/arm/mach-omap2/prcm-common.h @@ -416,7 +416,7 @@ extern void __iomem *cm_base; extern void __iomem *cm2_base; extern void __iomem *prcm_mpu_base; -#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_OMAP5) +#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) extern void omap_prm_base_init(void); extern void omap_cm_base_init(void); #else diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c index 28cbfb2b573..053e24ed3c4 100644 --- a/arch/arm/mach-omap2/prcm.c +++ b/arch/arm/mach-omap2/prcm.c @@ -160,7 +160,7 @@ void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals) if (omap2_globals->prcm_mpu) prcm_mpu_base = omap2_globals->prcm_mpu; - if (cpu_is_omap44xx()) { + if (cpu_is_omap44xx() || soc_is_omap54xx()) { omap_prm_base_init(); omap_cm_base_init(); } diff --git a/arch/arm/plat-omap/include/plat/hardware.h b/arch/arm/plat-omap/include/plat/hardware.h index e897978371c..ddbde38e1e3 100644 --- a/arch/arm/plat-omap/include/plat/hardware.h +++ b/arch/arm/plat-omap/include/plat/hardware.h @@ -288,5 +288,6 @@ #include #include #include +#include #endif /* __ASM_ARCH_OMAP_HARDWARE_H */ diff --git a/arch/arm/plat-omap/include/plat/multi.h b/arch/arm/plat-omap/include/plat/multi.h index 999ffba2690..045e320f106 100644 --- a/arch/arm/plat-omap/include/plat/multi.h +++ b/arch/arm/plat-omap/include/plat/multi.h @@ -99,4 +99,13 @@ # endif #endif +#ifdef CONFIG_SOC_OMAP5 +# ifdef OMAP_NAME +# undef MULTI_OMAP2 +# define MULTI_OMAP2 +# else +# define OMAP_NAME omap5 +# endif +#endif + #endif /* __PLAT_OMAP_MULTI_H */ diff --git a/arch/arm/plat-omap/include/plat/omap54xx.h b/arch/arm/plat-omap/include/plat/omap54xx.h new file mode 100644 index 00000000000..a2582bb3cab --- /dev/null +++ b/arch/arm/plat-omap/include/plat/omap54xx.h @@ -0,0 +1,32 @@ +/*: + * Address mappings and base address for OMAP5 interconnects + * and peripherals. + * + * Copyright (C) 2012 Texas Instruments + * Santosh Shilimkar + * Sricharan + * + * 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 + * published by the Free Software Foundation. + */ +#ifndef __ASM_SOC_OMAP54XX_H +#define __ASM_SOC_OMAP54XX_H + +/* + * Please place only base defines here and put the rest in device + * specific headers. + */ +#define L4_54XX_BASE 0x4a000000 +#define L4_WK_54XX_BASE 0x4ae00000 +#define L4_PER_54XX_BASE 0x48000000 +#define L3_54XX_BASE 0x44000000 +#define OMAP54XX_32KSYNCT_BASE 0x4ae04000 +#define OMAP54XX_CM_CORE_AON_BASE 0x4a004000 +#define OMAP54XX_CM_CORE_BASE 0x4a008000 +#define OMAP54XX_PRM_BASE 0x4ae06000 +#define OMAP54XX_PRCM_MPU_BASE 0x48243000 +#define OMAP54XX_SCM_BASE 0x4a002000 +#define OMAP54XX_CTRL_BASE 0x4a002800 + +#endif /* __ASM_SOC_OMAP555554XX_H */ diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h index 28e2d250c2f..65fce44dce3 100644 --- a/arch/arm/plat-omap/include/plat/serial.h +++ b/arch/arm/plat-omap/include/plat/serial.h @@ -63,6 +63,14 @@ /* AM33XX serial port */ #define AM33XX_UART1_BASE 0x44E09000 +/* OMAP5 serial ports */ +#define OMAP5_UART1_BASE OMAP2_UART1_BASE +#define OMAP5_UART2_BASE OMAP2_UART2_BASE +#define OMAP5_UART3_BASE OMAP4_UART3_BASE +#define OMAP5_UART4_BASE OMAP4_UART4_BASE +#define OMAP5_UART5_BASE 0x48066000 +#define OMAP5_UART6_BASE 0x48068000 + /* External port on Zoom2/3 */ #define ZOOM_UART_BASE 0x10000000 #define ZOOM_UART_VIRT 0xfa400000 @@ -97,6 +105,8 @@ #define TI81XXUART2 82 #define TI81XXUART3 83 #define AM33XXUART1 84 +#define OMAP5UART3 OMAP4UART3 +#define OMAP5UART4 OMAP4UART4 #define ZOOM_UART 95 /* Only on zoom2/3 */ /* This is only used by 8250.c for omap1510 */ diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h index ac432339021..b8d19a13678 100644 --- a/arch/arm/plat-omap/include/plat/uncompress.h +++ b/arch/arm/plat-omap/include/plat/uncompress.h @@ -95,6 +95,9 @@ static inline void flush(void) _DEBUG_LL_ENTRY(mach, OMAP4_UART##p##_BASE, OMAP_PORT_SHIFT, \ OMAP4UART##p) +#define DEBUG_LL_OMAP5(p, mach) \ + _DEBUG_LL_ENTRY(mach, OMAP5_UART##p##_BASE, OMAP_PORT_SHIFT, \ + OMAP5UART##p) /* Zoom2/3 shift is different for UART1 and external port */ #define DEBUG_LL_ZOOM(mach) \ _DEBUG_LL_ENTRY(mach, ZOOM_UART_BASE, ZOOM_PORT_SHIFT, ZOOM_UART) @@ -177,6 +180,9 @@ static inline void __arch_decomp_setup(unsigned long arch_id) DEBUG_LL_OMAP4(3, omap_4430sdp); DEBUG_LL_OMAP4(3, omap4_panda); + /* omap5 based boards using UART3 */ + DEBUG_LL_OMAP5(3, omap5_sevm); + /* zoom2/3 external uart */ DEBUG_LL_ZOOM(omap_zoom2); DEBUG_LL_ZOOM(omap_zoom3); diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 70cf825bdd8..766181cb5c9 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -6,8 +6,8 @@ * Copyright (C) 2005 Nokia Corporation * Written by Tony Lindgren * - * Copyright (C) 2009 Texas Instruments - * Added OMAP4 support - Santosh Shilimkar + * Copyright (C) 2009-2012 Texas Instruments + * Added OMAP4/5 support - Santosh Shilimkar * * 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 @@ -44,6 +44,7 @@ #else #define OMAP4_SRAM_PUB_PA (OMAP4_SRAM_PA + 0x4000) #endif +#define OMAP5_SRAM_PA 0x40300000 #if defined(CONFIG_ARCH_OMAP2PLUS) #define SRAM_BOOTLOADER_SZ 0x00 @@ -118,6 +119,9 @@ static void __init omap_detect_sram(void) } else if (cpu_is_omap44xx()) { omap_sram_start = OMAP4_SRAM_PUB_PA; omap_sram_size = 0xa000; /* 40K */ + } else if (soc_is_omap54xx()) { + omap_sram_start = OMAP5_SRAM_PA; + omap_sram_size = SZ_128K; /* 128KB */ } else { omap_sram_start = OMAP2_SRAM_PUB_PA; omap_sram_size = 0x800; /* 2K */ @@ -132,6 +136,9 @@ static void __init omap_detect_sram(void) } else if (cpu_is_omap44xx()) { omap_sram_start = OMAP4_SRAM_PA; omap_sram_size = 0xe000; /* 56K */ + } else if (soc_is_omap54xx()) { + omap_sram_start = OMAP5_SRAM_PA; + omap_sram_size = SZ_128K; /* 128KB */ } else { omap_sram_start = OMAP2_SRAM_PA; if (cpu_is_omap242x()) -- cgit v1.2.3-70-g09d2