aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap_hwmod.c
diff options
context:
space:
mode:
authorVishwanath BS <vishwanath.bs@ti.com>2012-06-22 10:40:04 -0400
committerPaul Walmsley <paul@pwsan.com>2012-06-22 10:40:04 -0400
commit5165882a387325ac0df2f30c62ea710cfa328b54 (patch)
treec3a1f28c84416de628b02b40eaaf069b701927be /arch/arm/mach-omap2/omap_hwmod.c
parent8a680ea2eb2e9ad602e290396add29e9eaed0911 (diff)
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 <vishwanath.bs@ti.com> Signed-off-by: Tero Kristo <t-kristo@ti.com> Reviewed-by: Rajendra Nayak <rnayak@ti.com> [paul@pwsan.com: remove dependency on pm.c & pm.h; add kerneldoc] Signed-off-by: Paul Walmsley <paul@pwsan.com>
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index bf86f7e8f91f..6d6c31a10a1b 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -153,6 +153,7 @@
153#include "prm44xx.h" 153#include "prm44xx.h"
154#include "prminst44xx.h" 154#include "prminst44xx.h"
155#include "mux.h" 155#include "mux.h"
156#include "pm.h"
156 157
157/* Maximum microseconds to wait for OMAP module to softreset */ 158/* Maximum microseconds to wait for OMAP module to softreset */
158#define MAX_MODULE_SOFTRESET_WAIT 10000 159#define MAX_MODULE_SOFTRESET_WAIT 10000
@@ -172,6 +173,9 @@ static LIST_HEAD(omap_hwmod_list);
172/* mpu_oh: used to add/remove MPU initiator from sleepdep list */ 173/* mpu_oh: used to add/remove MPU initiator from sleepdep list */
173static struct omap_hwmod *mpu_oh; 174static struct omap_hwmod *mpu_oh;
174 175
176/* io_chain_lock: used to serialize reconfigurations of the I/O chain */
177static DEFINE_SPINLOCK(io_chain_lock);
178
175/* 179/*
176 * linkspace: ptr to a buffer that struct omap_hwmod_link records are 180 * linkspace: ptr to a buffer that struct omap_hwmod_link records are
177 * allocated from - used to reduce the number of small memory 181 * allocated from - used to reduce the number of small memory
@@ -1738,6 +1742,32 @@ static int _reset(struct omap_hwmod *oh)
1738} 1742}
1739 1743
1740/** 1744/**
1745 * _reconfigure_io_chain - clear any I/O chain wakeups and reconfigure chain
1746 *
1747 * Call the appropriate PRM function to clear any logged I/O chain
1748 * wakeups and to reconfigure the chain. This apparently needs to be
1749 * done upon every mux change. Since hwmods can be concurrently
1750 * enabled and idled, hold a spinlock around the I/O chain
1751 * reconfiguration sequence. No return value.
1752 *
1753 * XXX When the PRM code is moved to drivers, this function can be removed,
1754 * as the PRM infrastructure should abstract this.
1755 */
1756static void _reconfigure_io_chain(void)
1757{
1758 unsigned long flags;
1759
1760 spin_lock_irqsave(&io_chain_lock, flags);
1761
1762 if (cpu_is_omap34xx() && omap3_has_io_chain_ctrl())
1763 omap3xxx_prm_reconfigure_io_chain();
1764 else if (cpu_is_omap44xx())
1765 omap44xx_prm_reconfigure_io_chain();
1766
1767 spin_unlock_irqrestore(&io_chain_lock, flags);
1768}
1769
1770/**
1741 * _enable - enable an omap_hwmod 1771 * _enable - enable an omap_hwmod
1742 * @oh: struct omap_hwmod * 1772 * @oh: struct omap_hwmod *
1743 * 1773 *
@@ -1793,8 +1823,10 @@ static int _enable(struct omap_hwmod *oh)
1793 /* Mux pins for device runtime if populated */ 1823 /* Mux pins for device runtime if populated */
1794 if (oh->mux && (!oh->mux->enabled || 1824 if (oh->mux && (!oh->mux->enabled ||
1795 ((oh->_state == _HWMOD_STATE_IDLE) && 1825 ((oh->_state == _HWMOD_STATE_IDLE) &&
1796 oh->mux->pads_dynamic))) 1826 oh->mux->pads_dynamic))) {
1797 omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED); 1827 omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
1828 _reconfigure_io_chain();
1829 }
1798 1830
1799 _add_initiator_dep(oh, mpu_oh); 1831 _add_initiator_dep(oh, mpu_oh);
1800 1832
@@ -1883,8 +1915,10 @@ static int _idle(struct omap_hwmod *oh)
1883 clkdm_hwmod_disable(oh->clkdm, oh); 1915 clkdm_hwmod_disable(oh->clkdm, oh);
1884 1916
1885 /* Mux pins for device idle if populated */ 1917 /* Mux pins for device idle if populated */
1886 if (oh->mux && oh->mux->pads_dynamic) 1918 if (oh->mux && oh->mux->pads_dynamic) {
1887 omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE); 1919 omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
1920 _reconfigure_io_chain();
1921 }
1888 1922
1889 oh->_state = _HWMOD_STATE_IDLE; 1923 oh->_state = _HWMOD_STATE_IDLE;
1890 1924