Skip to content

Commit

Permalink
ARM: OMAP3PLUS: hwmod: reconfigure IO Daisychain during hwmod mux
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Vishwanath BS authored and Paul Walmsley committed Jun 22, 2012
1 parent 8a680ea commit 5165882
Showing 1 changed file with 36 additions and 2 deletions.
38 changes: 36 additions & 2 deletions arch/arm/mach-omap2/omap_hwmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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 *
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit 5165882

Please sign in to comment.