예제 #1
0
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;
}
예제 #2
0
파일: pm.c 프로젝트: matianfu/kunlun-kernel
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;
}