Commit 029268e4 authored by Tony Lindgren's avatar Tony Lindgren

omap2+: Add separate list for dynamic pads to mux

This avoids going through the list unnecessarily when
idling devices for runtime PM.

Based on an earlier patch by sricharan <r.sricharan@ti.com>.
Signed-off-by: default avatarsricharan <r.sricharan@ti.com>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent 0d959695
...@@ -258,7 +258,7 @@ struct omap_hwmod_mux_info * __init ...@@ -258,7 +258,7 @@ struct omap_hwmod_mux_info * __init
omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads) omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
{ {
struct omap_hwmod_mux_info *hmux; struct omap_hwmod_mux_info *hmux;
int i; int i, nr_pads_dynamic = 0;
if (!bpads || nr_pads < 1) if (!bpads || nr_pads < 1)
return NULL; return NULL;
...@@ -302,9 +302,40 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads) ...@@ -302,9 +302,40 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
pad->enable = bpad->enable; pad->enable = bpad->enable;
pad->idle = bpad->idle; pad->idle = bpad->idle;
pad->off = bpad->off; pad->off = bpad->off;
if (pad->flags & OMAP_DEVICE_PAD_REMUX)
nr_pads_dynamic++;
pr_debug("%s: Initialized %s\n", __func__, pad->name); pr_debug("%s: Initialized %s\n", __func__, pad->name);
} }
if (!nr_pads_dynamic)
return hmux;
/*
* Add pads that need dynamic muxing into a separate list
*/
hmux->nr_pads_dynamic = nr_pads_dynamic;
hmux->pads_dynamic = kzalloc(sizeof(struct omap_device_pad *) *
nr_pads_dynamic, GFP_KERNEL);
if (!hmux->pads_dynamic) {
pr_err("%s: Could not allocate dynamic pads\n", __func__);
return hmux;
}
nr_pads_dynamic = 0;
for (i = 0; i < hmux->nr_pads; i++) {
struct omap_device_pad *pad = &hmux->pads[i];
if (pad->flags & OMAP_DEVICE_PAD_REMUX) {
pr_debug("%s: pad %s tagged dynamic\n",
__func__, pad->name);
hmux->pads_dynamic[nr_pads_dynamic] = pad;
nr_pads_dynamic++;
}
}
return hmux; return hmux;
err3: err3:
...@@ -322,6 +353,44 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state) ...@@ -322,6 +353,44 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
{ {
int i; int i;
/* Runtime idling of dynamic pads */
if (state == _HWMOD_STATE_IDLE && hmux->enabled) {
for (i = 0; i < hmux->nr_pads_dynamic; i++) {
struct omap_device_pad *pad = hmux->pads_dynamic[i];
int val = -EINVAL;
pad->flags |= OMAP_DEVICE_PAD_IDLE;
val = pad->idle;
omap_mux_write(pad->partition, val,
pad->mux->reg_offset);
}
return;
}
/* Runtime enabling of dynamic pads */
if ((state == _HWMOD_STATE_ENABLED) && hmux->pads_dynamic) {
int idled = 0;
for (i = 0; i < hmux->nr_pads_dynamic; i++) {
struct omap_device_pad *pad = hmux->pads_dynamic[i];
int val = -EINVAL;
if (!(pad->flags & OMAP_DEVICE_PAD_IDLE))
continue;
pad->flags &= ~OMAP_DEVICE_PAD_IDLE;
val = pad->enable;
omap_mux_write(pad->partition, val,
pad->mux->reg_offset);
idled++;
}
if (idled)
return;
}
/* Enabling or disabling of all pads */
for (i = 0; i < hmux->nr_pads; i++) { for (i = 0; i < hmux->nr_pads; i++) {
struct omap_device_pad *pad = &hmux->pads[i]; struct omap_device_pad *pad = &hmux->pads[i];
int flags, val = -EINVAL; int flags, val = -EINVAL;
...@@ -330,21 +399,10 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state) ...@@ -330,21 +399,10 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
switch (state) { switch (state) {
case _HWMOD_STATE_ENABLED: case _HWMOD_STATE_ENABLED:
if (flags & OMAP_DEVICE_PAD_ENABLED)
break;
flags |= OMAP_DEVICE_PAD_ENABLED;
val = pad->enable; val = pad->enable;
pr_debug("%s: Enabling %s %x\n", __func__, pr_debug("%s: Enabling %s %x\n", __func__,
pad->name, val); pad->name, val);
break; break;
case _HWMOD_STATE_IDLE:
if (!(flags & OMAP_DEVICE_PAD_REMUX))
break;
flags &= ~OMAP_DEVICE_PAD_ENABLED;
val = pad->idle;
pr_debug("%s: Idling %s %x\n", __func__,
pad->name, val);
break;
case _HWMOD_STATE_DISABLED: case _HWMOD_STATE_DISABLED:
default: default:
/* Use safe mode unless OMAP_DEVICE_PAD_REMUX */ /* Use safe mode unless OMAP_DEVICE_PAD_REMUX */
...@@ -352,7 +410,6 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state) ...@@ -352,7 +410,6 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
val = pad->off; val = pad->off;
else else
val = OMAP_MUX_MODE7; val = OMAP_MUX_MODE7;
flags &= ~OMAP_DEVICE_PAD_ENABLED;
pr_debug("%s: Disabling %s %x\n", __func__, pr_debug("%s: Disabling %s %x\n", __func__,
pad->name, val); pad->name, val);
}; };
...@@ -363,6 +420,11 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state) ...@@ -363,6 +420,11 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
pad->flags = flags; pad->flags = flags;
} }
} }
if (state == _HWMOD_STATE_ENABLED)
hmux->enabled = true;
else
hmux->enabled = false;
} }
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
......
...@@ -159,7 +159,7 @@ struct omap_board_mux { ...@@ -159,7 +159,7 @@ struct omap_board_mux {
u16 value; u16 value;
}; };
#define OMAP_DEVICE_PAD_ENABLED BIT(7) /* Not needed for board-*.c */ #define OMAP_DEVICE_PAD_IDLE BIT(7) /* Not needed for board-*.c */
#define OMAP_DEVICE_PAD_REMUX BIT(1) /* Dynamically remux a pad, #define OMAP_DEVICE_PAD_REMUX BIT(1) /* Dynamically remux a pad,
needs enable, idle and off needs enable, idle and off
values */ values */
......
...@@ -1244,7 +1244,9 @@ static int _enable(struct omap_hwmod *oh) ...@@ -1244,7 +1244,9 @@ static int _enable(struct omap_hwmod *oh)
_deassert_hardreset(oh, oh->rst_lines[0].name); _deassert_hardreset(oh, oh->rst_lines[0].name);
/* Mux pins for device runtime if populated */ /* Mux pins for device runtime if populated */
if (oh->mux) if (oh->mux && (!oh->mux->enabled ||
((oh->_state == _HWMOD_STATE_IDLE) &&
oh->mux->pads_dynamic)))
omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED); omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
_add_initiator_dep(oh, mpu_oh); _add_initiator_dep(oh, mpu_oh);
...@@ -1293,7 +1295,7 @@ static int _idle(struct omap_hwmod *oh) ...@@ -1293,7 +1295,7 @@ static int _idle(struct omap_hwmod *oh)
_disable_clocks(oh); _disable_clocks(oh);
/* Mux pins for device idle if populated */ /* Mux pins for device idle if populated */
if (oh->mux) if (oh->mux && oh->mux->pads_dynamic)
omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE); omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
oh->_state = _HWMOD_STATE_IDLE; oh->_state = _HWMOD_STATE_IDLE;
......
...@@ -90,6 +90,9 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2; ...@@ -90,6 +90,9 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
struct omap_hwmod_mux_info { struct omap_hwmod_mux_info {
int nr_pads; int nr_pads;
struct omap_device_pad *pads; struct omap_device_pad *pads;
int nr_pads_dynamic;
struct omap_device_pad **pads_dynamic;
bool enabled;
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment