@@ -258,7 +258,7 @@ struct omap_hwmod_mux_info * __init
omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
{
struct omap_hwmod_mux_info *hmux;
- int i;
+ int i, pads_static = 0, pads_dynamic = 0;
if (!bpads || nr_pads < 1)
return NULL;
@@ -267,18 +267,48 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
if (!hmux)
goto err1;
- hmux->nr_pads = nr_pads;
+ hmux->nr_pads_static = 0;
+ hmux->nr_pads_dynamic = 0;
+ hmux->static_pads_initialised = 0;
+
+ for (i = 0; i < nr_pads; i++) {
+ struct omap_device_pad *bpad = &bpads[i];
+
+ /*
+ * only pads for which a remux is required during the
+ * device state transitions between idle/enable are
+ * added to dynamic list
+ */
+
+ if ((bpad->flags) & (OMAP_DEVICE_PAD_REMUX_IDLE))
+ hmux->nr_pads_dynamic++;
+ else
+ hmux->nr_pads_static++;
- hmux->pads = kzalloc(sizeof(struct omap_device_pad) *
- nr_pads, GFP_KERNEL);
- if (!hmux->pads)
+ }
+
+ hmux->pads_static = kzalloc(sizeof(struct omap_device_pad) *
+ hmux->nr_pads_static, GFP_KERNEL);
+ hmux->pads_dynamic = kzalloc(sizeof(struct omap_device_pad) *
+ hmux->nr_pads_dynamic, GFP_KERNEL);
+
+ if ((!hmux->pads_static) || (!hmux->pads_dynamic))
goto err2;
- for (i = 0; i < hmux->nr_pads; i++) {
+ for (i = 0; i < nr_pads; i++) {
struct omap_mux_partition *partition;
- struct omap_device_pad *bpad = &bpads[i], *pad = &hmux->pads[i];
+ struct omap_device_pad *bpad = &bpads[i], *pad;
struct omap_mux *mux;
int mux_mode;
+ int pad_dynamic = 0;
+
+ if ((bpad->flags) & (OMAP_DEVICE_PAD_REMUX_IDLE)) {
+ pad = &hmux->pads_dynamic[pads_dynamic++];
+ pad_dynamic = 1;
+ } else {
+ pad = &hmux->pads_static[pads_static++];
+ pad_dynamic = 0;
+ }
mux_mode = omap_mux_get_by_name(bpad->name, &partition, &mux);
if (mux_mode < 0)
@@ -290,10 +320,28 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
pad->name = kzalloc(strlen(bpad->name) + 1, GFP_KERNEL);
if (!pad->name) {
- int j;
+ int j, k;
+
+ /*
+ * pads_dynamic or pads_static has the count of the
+ * next pad in the list. So current pad is 1 less
+ * than the index. Since current pad is unallocated
+ * start deleting from 2 less than the index
+ */
+
+ if (pad_dynamic) {
+ j = pads_dynamic - 2;
+ k = pads_static - 1;
+ } else {
+ j = pads_static - 2;
+ k = pads_dynamic - 1;
+ }
+
+ for (; j >= 0; j--)
+ kfree(hmux->pads_dynamic[j].name);
+ for (; k >= 0; k--)
+ kfree(hmux->pads_static[k].name);
- for (j = i - 1; j >= 0; j--)
- kfree(hmux->pads[j].name);
goto err3;
}
strcpy(pad->name, bpad->name);
@@ -308,7 +356,8 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
return hmux;
err3:
- kfree(hmux->pads);
+ kfree(hmux->pads_static);
+ kfree(hmux->pads_dynamic);
err2:
kfree(hmux);
err1:
@@ -318,53 +367,137 @@ err1:
}
/* Assumes the calling function takes care of locking */
-void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
+void omap_hwmod_mux_enable(struct omap_hwmod_mux_info *hmux, u8 state)
{
int i;
- for (i = 0; i < hmux->nr_pads; i++) {
- struct omap_device_pad *pad = &hmux->pads[i];
- int flags, val = -EINVAL;
+ if (!hmux->static_pads_initialised) {
+ hmux->static_pads_initialised = 1;
- flags = pad->flags;
+ for (i = 0; i < hmux->nr_pads_static; i++) {
+ struct omap_device_pad *pad = &hmux->pads_static[i];
+ int val = -EINVAL;
- switch (state) {
- case _HWMOD_STATE_ENABLED:
- if (flags & OMAP_DEVICE_PAD_ENABLED)
- break;
- flags |= OMAP_DEVICE_PAD_ENABLED;
val = pad->enable;
pr_debug("%s: Enabling %s %x\n", __func__,
- pad->name, val);
- 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:
- default:
- /* Use safe mode unless OMAP_DEVICE_PAD_REMUX */
- if (flags & OMAP_DEVICE_PAD_REMUX)
- val = pad->off;
- else
- val = OMAP_MUX_MODE7;
- flags &= ~OMAP_DEVICE_PAD_ENABLED;
- pr_debug("%s: Disabling %s %x\n", __func__,
- pad->name, val);
- };
+ pad->name, val);
+
+ if (val >= 0) {
+ omap_mux_write(pad->partition, val,
+ pad->mux->reg_offset);
+ }
+ }
+ }
+
+ for (i = 0; i < hmux->nr_pads_dynamic; i++) {
+ struct omap_device_pad *pad = &hmux->pads_dynamic[i];
+ int flags, val = -EINVAL;
+
+ flags = pad->flags;
+
+ if (flags & OMAP_DEVICE_PAD_ENABLED)
+ continue;
+
+ flags |= OMAP_DEVICE_PAD_ENABLED;
+ val = pad->enable;
+ pr_debug("%s: Enabling %s %x\n", __func__,
+ pad->name, val);
if (val >= 0) {
omap_mux_write(pad->partition, val,
- pad->mux->reg_offset);
+ pad->mux->reg_offset);
pad->flags = flags;
}
}
}
+/* Assumes the calling function takes care of locking */
+void omap_hwmod_mux_disable(struct omap_hwmod_mux_info *hmux, u8 state)
+{
+ int i;
+
+ /*
+ * All the static pads are uninitialised because of driver
+ * being removed. They have to be initialised again by Enable
+ */
+ hmux->static_pads_initialised = 0;
+
+ for (i = 0; i < hmux->nr_pads_static; i++) {
+ struct omap_device_pad *pad = &hmux->pads_static[i];
+ int flags, val = -EINVAL;
+
+ flags = pad->flags;
+
+ /* Use safe mode unless OMAP_DEVICE_PAD_REMUX */
+ if (flags & OMAP_DEVICE_PAD_REMUX_DISABLE)
+ val = pad->off;
+ else
+ val = OMAP_MUX_MODE7;
+
+ pr_debug("%s: Disabling static %s %x\n", __func__,
+ pad->name, val);
+ if (val >= 0) {
+ omap_mux_write(pad->partition, val,
+ pad->mux->reg_offset);
+ }
+ }
+
+ /*
+ * All the dynamic pads should also be remuxed. So this
+ * functions remuxes all the pads of a hwmod
+ */
+
+ for (i = 0; i < hmux->nr_pads_dynamic; i++) {
+ struct omap_device_pad *pad = &hmux->pads_dynamic[i];
+ int flags, val = -EINVAL;
+
+ flags = pad->flags;
+
+ /* Use safe mode unless OMAP_DEVICE_PAD_REMUX_DISABLE */
+ if (flags & OMAP_DEVICE_PAD_REMUX_DISABLE)
+ val = pad->off;
+ else
+ val = OMAP_MUX_MODE7;
+
+ flags &= ~OMAP_DEVICE_PAD_ENABLED;
+
+ pr_debug("%s: Disabling dynamic %s %x\n", __func__,
+ pad->name, val);
+ if (val >= 0) {
+ omap_mux_write(pad->partition, val,
+ pad->mux->reg_offset);
+ pad->flags = flags;
+ }
+ }
+}
+
+/* Assumes the calling function takes care of locking */
+void omap_hwmod_mux_idle(struct omap_hwmod_mux_info *hmux, u8 state)
+{
+ int i;
+
+ for (i = 0; i < hmux->nr_pads_dynamic; i++) {
+ struct omap_device_pad *pad = &hmux->pads_dynamic[i];
+ int flags, val = -EINVAL;
+
+ flags = pad->flags;
+
+ /* Use the pad idle mode remux value */
+ val = pad->idle;
+
+ flags &= ~OMAP_DEVICE_PAD_ENABLED;
+
+ pr_debug("%s: Disabling %s %x\n", __func__,
+ pad->name, val);
+ if (val >= 0) {
+ omap_mux_write(pad->partition, val,
+ pad->mux->reg_offset);
+ pad->flags = flags;
+ }
+ }
+}
+
+
#ifdef CONFIG_DEBUG_FS
#define OMAP_MUX_MAX_NR_FLAGS 10
@@ -160,9 +160,13 @@ struct omap_board_mux {
};
#define OMAP_DEVICE_PAD_ENABLED BIT(7) /* Not needed for board-*.c */
-#define OMAP_DEVICE_PAD_REMUX BIT(1) /* Dynamically remux a pad,
- needs enable, idle and off
- values */
+#define OMAP_DEVICE_PAD_REMUX_DISABLE BIT(2) /* Dynamic remux needed
+ when pad would be
+ disabled. Say when
+ the driver is removed */
+#define OMAP_DEVICE_PAD_REMUX_IDLE BIT(1) /* Dynamic remux needed
+ for pad, during power
+ state transitions. */
#define OMAP_DEVICE_PAD_WAKEUP BIT(0) /* Pad is wake-up capable */
/**
@@ -212,13 +216,32 @@ extern struct omap_hwmod_mux_info *
omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);
/**
- * omap_hwmod_mux - omap hwmod specific pin muxing
+ * omap_hwmod_mux_enable - omap hwmod specific pin muxing
* @hmux: Pads for a hwmod
* @state: Desired _HWMOD_STATE
*
* Called only from omap_hwmod.c, do not use.
*/
-void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);
+void omap_hwmod_mux_enable(struct omap_hwmod_mux_info *hmux, u8 state);
+
+/**
+ * omap_hwmod_mux_idle - omap hwmod specific pin muxing
+ * @hmux: Pads for a hwmod
+ * @state: Desired _HWMOD_STATE
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+void omap_hwmod_mux_idle(struct omap_hwmod_mux_info *hmux, u8 state);
+
+/**
+ * omap_hwmod_mux_disable - omap hwmod specific pin muxing
+ * @hmux: Pads for a hwmod
+ * @state: Desired _HWMOD_STATE
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+void omap_hwmod_mux_disable(struct omap_hwmod_mux_info *hmux, u8 state);
+
#else
@@ -1231,7 +1231,7 @@ static int _enable(struct omap_hwmod *oh)
/* Mux pins for device runtime if populated */
if (oh->mux)
- omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
+ omap_hwmod_mux_enable(oh->mux, _HWMOD_STATE_ENABLED);
_add_initiator_dep(oh, mpu_oh);
_enable_clocks(oh);
@@ -1280,7 +1280,7 @@ static int _idle(struct omap_hwmod *oh)
/* Mux pins for device idle if populated */
if (oh->mux)
- omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
+ omap_hwmod_mux_idle(oh->mux, _HWMOD_STATE_IDLE);
oh->_state = _HWMOD_STATE_IDLE;
@@ -1342,7 +1342,7 @@ static int _shutdown(struct omap_hwmod *oh)
/* Mux pins to safe mode or use populated off mode values */
if (oh->mux)
- omap_hwmod_mux(oh->mux, _HWMOD_STATE_DISABLED);
+ omap_hwmod_mux_disable(oh->mux, _HWMOD_STATE_DISABLED);
oh->_state = _HWMOD_STATE_DISABLED;
@@ -88,8 +88,11 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
* Note that this is currently built during init as needed.
*/
struct omap_hwmod_mux_info {
- int nr_pads;
- struct omap_device_pad *pads;
+ int nr_pads_static;
+ struct omap_device_pad *pads_static;
+ int nr_pads_dynamic;
+ struct omap_device_pad *pads_dynamic;
+ int static_pads_initialised;
};
/**