DSP_STATUS CHNLSM_InterruptDSP2(struct WMD_DEV_CONTEXT *pDevContext, u16 wMbVal) { #ifndef CONFIG_DISABLE_BRIDGE_PM #ifndef CONFIG_DISABLE_BRIDGE_DVFS u32 opplevel; #endif #endif struct CFG_HOSTRES resources; unsigned long timeout; u32 temp; DSP_STATUS status = DSP_SOK; /* We are waiting indefinitely here. This needs to be fixed in the * second phase */ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources); if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION || pDevContext->dwBrdState == BRD_HIBERNATION) { #ifndef CONFIG_DISABLE_BRIDGE_PM #ifndef CONFIG_DISABLE_BRIDGE_DVFS #ifndef CONFIG_OMAP3_PM opplevel = omap_pm_dsp_get_opp(); /* If OPP is at minimum level, increase it before waking up * the DSP */ if (opplevel == 1) { omap_pm_dsp_set_min_opp(opplevel+1); DBG_Trace(DBG_LEVEL7, "CHNLSM_InterruptDSP:Setting " "the vdd1 constraint level to %d before " "waking DSP \n", (opplevel + 1)); } #else opplevel = constraint_get_level(dsp_constraint_handle); /* If OPP is at minimum level, increase it before waking up * the DSP */ if (opplevel == 1) { if (constraint_set(dsp_constraint_handle, (opplevel+1)) != 0) { DBG_Trace(DBG_LEVEL7, "CHNLSM_InterruptDSP: " "Constraint set failed\n"); return DSP_EFAIL; } DBG_Trace(DBG_LEVEL7, "CHNLSM_InterruptDSP:Setting " "the vdd1 constraint level to %d before " "waking DSP \n", (opplevel + 1)); } #endif #endif #endif /* Restart the IVA clock that was disabled while * the DSP initiated Hibernation. */ if ((pDevContext->dwBrdState == BRD_DSP_HIBERNATION) || (pDevContext->dwBrdState == BRD_HIBERNATION)) { status = CLK_Enable(SERVICESCLK_iva2_ck); if (DSP_FAILED(status)) return status; } /* Read MMU register to invoke short wakeup of DSP */ temp = (u32) *((REG_UWORD32 *) ((u32) (resources.dwDmmuBase) + 0x10)); /* Restore mailbox settings */ HW_MBOX_restoreSettings(resources.dwMboxBase); DBG_Trace(DBG_LEVEL6, "MailBoxSettings: SYSCONFIG = 0x%x\n", mboxsetting.sysconfig); DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE0 = 0x%x\n", mboxsetting.irqEnable0); DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE1 = 0x%x\n", mboxsetting.irqEnable1); /* Restart the peripheral clocks that were disabled only * in DSP initiated Hibernation case.*/ if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION) DSP_PeripheralClocks_Enable(pDevContext, NULL); pDevContext->dwBrdState = BRD_RUNNING; } timeout = jiffies + msecs_to_jiffies(35); while (HW_MBOX_IsFull(resources.dwMboxBase, MBOX_ARM2DSP)) { if (time_after(jiffies, timeout)) { printk(KERN_ERR "dspbridge: " "timed out waiting for mailbox\n"); return WMD_E_TIMEOUT; } } DBG_Trace(DBG_LEVEL3, "writing %x to Mailbox\n", wMbVal); HW_MBOX_MsgWrite(resources.dwMboxBase, MBOX_ARM2DSP, wMbVal); return DSP_SOK; }
static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { unsigned long value; static unsigned long prev_mpu_freq = 0; if (sscanf(buf, "%lu", &value) != 1) return -EINVAL; if (attr == &tick_control_attr) { if (value == 1) tick_nohz_disable(1); else if (value == 0) tick_nohz_disable(0); } /* Check locks */ if (attr == &vdd1_lock_attr) { if (vdd1_locked) { /* vdd1 currently locked */ if (value == 0) { omap_pm_cpu_set_freq(prev_mpu_freq * 1000); vdd1_locked = 0; return n; } else { printk(KERN_ERR "%s: vdd1 already locked to %d\n", __func__, vdd1_locked); return -EINVAL; } } else { /* vdd1 currently unlocked */ if (value != 0) { u8 i = 0; unsigned long freq = 0; struct cpufreq_frequency_table *freq_table = *omap_pm_cpu_get_freq_table(); if (freq_table == NULL) { printk(KERN_ERR "%s: Could not get freq_table\n", __func__); return -ENODEV; } for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { if (freq_table[i].index == value - 1) { freq = freq_table[i].frequency; break; } } if (freq_table[i].frequency == CPUFREQ_TABLE_END) { printk(KERN_ERR "%s: Invalid value [0..%d]\n", __func__, i-1); return -EINVAL; } prev_mpu_freq = omap_pm_cpu_get_freq(); omap_pm_cpu_set_freq(freq * 1000); vdd1_locked = value; } else { printk(KERN_ERR "%s: vdd1 already unlocked\n", __func__); return -EINVAL; } } } else if (attr == &vdd2_lock_attr) { if (vdd2_locked) { /* vdd2 currently locked */ if (value == 0) { int tmp_lock = vdd2_locked; vdd2_locked = 0; if (omap_pm_set_min_bus_tput(&sysfs_cpufreq_dev, OCP_INITIATOR_AGENT, -1)) { printk(KERN_ERR "%s: Failed to remove vdd2_lock\n", __func__); vdd2_locked = tmp_lock; /* restore previous lock */ } else { return n; } } else { printk(KERN_ERR "%s: vdd2 already locked to %d\n", __func__, vdd2_locked); return -EINVAL; } } else { /* vdd2 currently unlocked */ if (value != 0) { unsigned long freq = 0; if (cpu_is_omap3630()) { if(value == 1) { freq = 100*1000*4; } else if (value == 2) { freq = 200*1000*4; } else { printk(KERN_ERR "%s: Invalid value [1,2]\n", __func__); return -EINVAL; } } else if (cpu_is_omap44xx()) { if (omap_rev() <= OMAP4430_REV_ES2_0) { if(value == 1) { freq = 100*1000*4; } else if (value == 2) { freq = 200*1000*4; } else { printk(KERN_ERR "%s: Invalid value [1,2]\n", __func__); return -EINVAL; } } else { if(value == 1) { freq = 98304*4; } else if (value == 2) { freq = 100*1000*4; } else if (value == 3) { freq = 200*1000*4; } else { printk(KERN_ERR "%s: Invalid value [1,2,3]\n", __func__); return -EINVAL; } } } else { printk(KERN_ERR "%s: Unsupported HW [OMAP3630, OMAP44XX]\n", __func__); return -ENODEV; } if (omap_pm_set_min_bus_tput(&sysfs_cpufreq_dev, OCP_INITIATOR_AGENT, freq)) { printk(KERN_ERR "%s: Failed to add vdd2_lock\n", __func__); } else { vdd2_locked = value; } return n; } else { printk(KERN_ERR "%s: vdd2 already unlocked\n", __func__); return -EINVAL; } } } else if (attr == &dsp_freq_attr) { u8 i, opp_id = 0; struct omap_opp *opp_table = omap_pm_dsp_get_opp_table(); if (opp_table == NULL) { printk(KERN_ERR "%s: Could not get dsp opp_table\n", __func__); return -ENODEV; } for (i = 1; opp_table[i].rate; i++) { if (opp_table[i].rate >= value) { opp_id = i; break; } } if (opp_id == 0) { printk(KERN_ERR "%s: Invalid value\n", __func__); return -EINVAL; } omap_pm_dsp_set_min_opp(opp_id); } else if (attr == &vdd1_opp_attr) { printk(KERN_ERR "%s: changing vdd1_opp is not supported\n", __func__); return -EINVAL; } else if (attr == &vdd2_opp_attr) { printk(KERN_ERR "%s: changing vdd2_opp is not supported\n", __func__); return -EINVAL; } else { return -EINVAL; } return n; }