Пример #1
0
static void am33xx_pre_suspend(unsigned int state)
{
	if (state == PM_SUSPEND_STANDBY) {
		clkdm_wakeup(l3s_clkdm);
		clkdm_wakeup(l4fw_clkdm);
		clkdm_wakeup(clk_24mhz_clkdm);
	}
}
Пример #2
0
static int am33xx_pm_suspend(void)
{
	int state, ret = 0;

	struct omap_hwmod *cpgmac_oh, *gpmc_oh, *usb_oh;

	cpgmac_oh	= omap_hwmod_lookup("cpgmac0");
	usb_oh		= omap_hwmod_lookup("usb_otg_hs");
	gpmc_oh		= omap_hwmod_lookup("gpmc");

	omap_hwmod_enable(cpgmac_oh);
	omap_hwmod_enable(usb_oh);
	omap_hwmod_enable(gpmc_oh);

	omap_hwmod_idle(cpgmac_oh);
	omap_hwmod_idle(usb_oh);
	omap_hwmod_idle(gpmc_oh);

	if (gfx_l3_clkdm && gfx_l4ls_clkdm) {
		clkdm_sleep(gfx_l3_clkdm);
		clkdm_sleep(gfx_l4ls_clkdm);
	}

	/* Try to put GFX to sleep */
	if (gfx_pwrdm)
		pwrdm_set_next_pwrst(gfx_pwrdm, PWRDM_POWER_OFF);
	else
		pr_err("Could not program GFX to low power state\n");

	writel(0x0, AM33XX_CM_MPU_MPU_CLKCTRL);

	ret = cpu_suspend(0, am33xx_do_sram_idle);

	writel(0x2, AM33XX_CM_MPU_MPU_CLKCTRL);

	if (gfx_pwrdm) {
		state = pwrdm_read_pwrst(gfx_pwrdm);
		if (state != PWRDM_POWER_OFF)
			pr_err("GFX domain did not transition to low power state\n");
		else
			pr_info("GFX domain entered low power state\n");
	}

	/* XXX: Why do we need to wakeup the clockdomains? */
	if(gfx_l3_clkdm && gfx_l4ls_clkdm) {
		clkdm_wakeup(gfx_l3_clkdm);
		clkdm_wakeup(gfx_l4ls_clkdm);
	}

	core_suspend_stat = ret;

	return ret;
}
Пример #3
0
static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
{
	/* For every clock enable, force wakeup the clkdm */
	clkdm_wakeup(clkdm);

	return 0;
}
Пример #4
0
void tf_clock_timer_start(void)
{
	unsigned long flags;
	dprintk(KERN_INFO "%s\n", __func__);

	spin_lock_irqsave(&clk_timer_lock, flags);

	tf_crypto_clock_enabled++;

	wake_lock(&g_tf_wake_lock);
	clkdm_wakeup(smc_l4_sec_clkdm);

	/* Stop the timer if already running */
	if (timer_pending(&tf_crypto_clock_timer))
		del_timer(&tf_crypto_clock_timer);

	/* Configure the timer */
	tf_crypto_clock_timer.expires =
		 jiffies + msecs_to_jiffies(INACTIVITY_TIMER_TIMEOUT);
	tf_crypto_clock_timer.function = tf_clock_timer_cb;

	add_timer(&tf_crypto_clock_timer);

	spin_unlock_irqrestore(&clk_timer_lock, flags);
}
Пример #5
0
/**
 * omap_sec_dispatcher: Routine to dispatch low power secure
 * service routines
 * @idx: The HAL API index
 * @flag: The flag indicating criticality of operation
 * @nargs: Number of valid arguments out of four.
 * @arg1, arg2, arg3 args4: Parameters passed to secure API
 *
 * Return the non-zero error value on failure.
 */
u32 omap_secure_dispatcher(u32 idx, u32 flag, u32 nargs, u32 arg1, u32 arg2,
							 u32 arg3, u32 arg4)
{
	u32 ret;
	u32 param[5];

	param[0] = nargs;
	param[1] = arg1;
	param[2] = arg2;
	param[3] = arg3;
	param[4] = arg4;

	if (!l4_secure_clkdm)
		l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm");

	clkdm_wakeup(l4_secure_clkdm);

	/*
	 * Secure API needs physical address
	 * pointer for the parameters
	 */
	flush_cache_all();
	outer_clean_range(__pa(param), __pa(param + 5));
	ret = omap_smc2(idx, flag, __pa(param));

	clkdm_allow_idle(l4_secure_clkdm);

	return ret;
}
Пример #6
0
int omap_rproc_activate(struct omap_device *od)
{
	int i, ret = 0;
	struct rproc *rproc = platform_get_drvdata(&od->pdev);
	struct device *dev = rproc->dev;
	struct omap_rproc_pdata *pdata = dev->platform_data;
	struct omap_rproc_timers_info *timers = pdata->timers;
	struct omap_rproc_priv *rpp = rproc->priv;
#ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND
	struct iommu *iommu;

	if (!rpp->iommu) {
		iommu = iommu_get(pdata->iommu_name);
		if (IS_ERR(iommu)) {
			dev_err(dev, "iommu_get error: %ld\n",
				PTR_ERR(iommu));
			return PTR_ERR(iommu);
		}
		rpp->iommu = iommu;
	}

	if (!rpp->mbox)
		rpp->mbox = omap_mbox_get(pdata->sus_mbox_name, NULL);
#endif
	/**
	 * explicitly configure a boot address from which remoteproc
	 * starts executing code when taken out of reset.
	 */
	_load_boot_addr(rproc, rpp->bootaddr);

	/**
	 * Domain is in HW SUP thus in hw_auto but
	 * since remoteproc will be enabled clkdm
	 * needs to be in sw_sup (Do not let it idle).
	 */
	if (pdata->clkdm)
		clkdm_wakeup(pdata->clkdm);

	for (i = 0; i < pdata->timers_cnt; i++)
		omap_dm_timer_start(timers[i].odt);

	for (i = 0; i < od->hwmods_cnt; i++) {
		ret = omap_hwmod_enable(od->hwmods[i]);
		if (ret) {
			for (i = 0; i < pdata->timers_cnt; i++)
				omap_dm_timer_stop(timers[i].odt);
			break;
		}
	}

	/**
	 * Domain is in force_wkup but since remoteproc
	 * was enabled it is safe now to switch clkdm
	 * to hw_auto (let it idle).
	 */
	if (pdata->clkdm)
		clkdm_allow_idle(pdata->clkdm);

	return ret;
}
Пример #7
0
static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
	static struct clockdomain *cpu1_clkdm;
	static bool booted;
	void __iomem *base = omap_get_wakeupgen_base();

	/*
	 * Set synchronisation state between this boot processor
	 * and the secondary one
	 */
	spin_lock(&boot_lock);

	/*
	 * Update the AuxCoreBoot0 with boot state for secondary core.
	 * omap_secondary_startup() routine will hold the secondary core till
	 * the AuxCoreBoot1 register is updated with cpu state
	 * A barrier is added to ensure that write buffer is drained
	 */
	if (omap_secure_apis_support())
		omap_modify_auxcoreboot0(0x200, 0xfffffdff);
	else
		__raw_writel(0x20, base + OMAP_AUX_CORE_BOOT_0);

	flush_cache_all();
	smp_wmb();

	if (!cpu1_clkdm)
		cpu1_clkdm = clkdm_lookup("mpu1_clkdm");

	/*
	 * The SGI(Software Generated Interrupts) are not wakeup capable
	 * from low power states. This is known limitation on OMAP4 and
	 * needs to be worked around by using software forced clockdomain
	 * wake-up. To wakeup CPU1, CPU0 forces the CPU1 clockdomain to
	 * software force wakeup. The clockdomain is then put back to
	 * hardware supervised mode.
	 * More details can be found in OMAP4430 TRM - Version J
	 * Section :
	 *	4.3.4.2 Power States of CPU0 and CPU1
	 */
	if (booted) {
		clkdm_wakeup(cpu1_clkdm);
		clkdm_allow_idle(cpu1_clkdm);
	} else {
		dsb_sev();
		booted = true;
	}

	gic_raise_softirq(cpumask_of(cpu), 0);

	/*
	 * Now the secondary core is starting up let it run its
	 * calibrations, then wait for it to finish
	 */
	spin_unlock(&boot_lock);

	return 0;
}
Пример #8
0
/**
 * omap4_prcm_freq_update - set freq_update bit
 *
 * Programs the CM shadow registers to update EMIF
 * parametrs. Few usecase only few registers needs to
 * be updated using prcm freq update sequence.
 * EMIF read-idle control and zq-config needs to be
 * updated for temprature alerts and voltage change
 * Returns -1 on error and 0 on success.
 */
int omap4_prcm_freq_update(void)
{
	u32 shadow_freq_cfg1;
	int i = 0;
	unsigned long flags;

	if (!l3_emif_clkdm) {
		pr_err("%s: clockdomain lookup failed\n", __func__);
		return -EINVAL;
	}

	spin_lock_irqsave(&l3_emif_lock, flags);
	/* Configures MEMIF domain in SW_WKUP */
	clkdm_wakeup(l3_emif_clkdm);

	/* Disable DDR self refresh (Errata ID: i728) */
	omap_emif_frequency_pre_notify();

	/*
	 * FREQ_UPDATE sequence:
	 * - DLL_OVERRIDE=0 (DLL lock & code must not be overridden
	 *	after CORE DPLL lock)
	 * - FREQ_UPDATE=1 (to start HW sequence)
	 */
	shadow_freq_cfg1 = __raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1);
	shadow_freq_cfg1 |= (1 << OMAP4430_DLL_RESET_SHIFT) |
			   (1 << OMAP4430_FREQ_UPDATE_SHIFT);
	shadow_freq_cfg1 &= ~OMAP4430_DLL_OVERRIDE_MASK;
	__raw_writel(shadow_freq_cfg1, OMAP4430_CM_SHADOW_FREQ_CONFIG1);

	/* wait for the configuration to be applied */
	omap_test_timeout(((__raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1)
				& OMAP4430_FREQ_UPDATE_MASK) == 0),
				MAX_FREQ_UPDATE_TIMEOUT, i);

	/* Re-enable DDR self refresh */
	omap_emif_frequency_post_notify();

	/* Configures MEMIF domain back to HW_WKUP */
	clkdm_allow_idle(l3_emif_clkdm);

	spin_unlock_irqrestore(&l3_emif_lock, flags);

	if (i == MAX_FREQ_UPDATE_TIMEOUT) {
		pr_err("%s: Frequency update failed (call from %pF)\n",
			__func__, (void *)_RET_IP_);
		pr_err("CLKCTRL: EMIF_1=0x%x EMIF_2=0x%x DMM=0x%x\n",
		       __raw_readl(OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL),
		       __raw_readl(OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL),
		       __raw_readl(OMAP4430_CM_MEMIF_DMM_CLKCTRL));
		emif_dump(0);
		emif_dump(1);
		return -1;
	}

	return 0;
}
Пример #9
0
/*
 * This sets pwrdm state (other than mpu & core. Currently only ON &
 * RET are supported.
 */
int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
{
	u32 cur_state;
	int sleep_switch = 0;
	int ret = 0;

	if (pwrdm == NULL || IS_ERR(pwrdm))
		return -EINVAL;

	while (!(pwrdm->pwrsts & (1 << state))) {
		if (state == PWRDM_POWER_OFF)
			return ret;
		state--;
	}

	cur_state = pwrdm_read_next_pwrst(pwrdm);
	if (cur_state == state)
		return ret;

	if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
		if ((pwrdm_read_pwrst(pwrdm) > state) &&
			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
			sleep_switch = LOWPOWERSTATE_SWITCH;
		} else {
			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
			pwrdm_wait_transition(pwrdm);
			sleep_switch = FORCEWAKEUP_SWITCH;
		}
	}

	ret = pwrdm_set_next_pwrst(pwrdm, state);
	if (ret) {
		printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
		       pwrdm->name);
		goto err;
	}

	switch (sleep_switch) {
	case FORCEWAKEUP_SWITCH:
		if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO)
			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
		else
			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
		break;
	case LOWPOWERSTATE_SWITCH:
		pwrdm_set_lowpwrstchange(pwrdm);
		break;
	default:
		return ret;
	}

	pwrdm_wait_transition(pwrdm);
	pwrdm_state_switch(pwrdm);
err:
	return ret;
}
Пример #10
0
/*
 * This sets pwrdm state (other than mpu & core. Currently only ON &
 * RET are supported.
 */
int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
{
	u32 cur_state;
	int sleep_switch = -1;
	int ret = 0;
	int hwsup = 0;

	if (pwrdm == NULL || IS_ERR(pwrdm))
		return -EINVAL;

	while (!(pwrdm->pwrsts & (1 << state))) {
		if (state == PWRDM_POWER_OFF)
			return ret;
		state--;
	}

	cur_state = pwrdm_read_next_pwrst(pwrdm);
	if (cur_state == state)
		return ret;

	if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
		if ((pwrdm_read_pwrst(pwrdm) > state) &&
			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
			sleep_switch = LOWPOWERSTATE_SWITCH;
		} else {
			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
			sleep_switch = FORCEWAKEUP_SWITCH;
		}
	}

	ret = pwrdm_set_next_pwrst(pwrdm, state);
	if (ret) {
		pr_err("%s: unable to set state of powerdomain: %s\n",
		       __func__, pwrdm->name);
		goto err;
	}

	switch (sleep_switch) {
	case FORCEWAKEUP_SWITCH:
		if (hwsup)
			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
		else
			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
		break;
	case LOWPOWERSTATE_SWITCH:
		pwrdm_set_lowpwrstchange(pwrdm);
		break;
	default:
		return ret;
	}

	pwrdm_state_switch(pwrdm);
err:
	return ret;
}
Пример #11
0
static int omap_rproc_iommu_init(struct rproc *rproc,
		 int (*callback)(struct rproc *rproc, u64 fa, u32 flags))
{
	struct device *dev = rproc->dev;
	struct omap_rproc_pdata *pdata = dev->platform_data;
	int ret, i;
	struct iommu *iommu;
	struct omap_rproc_priv *rpp;

	rpp = kzalloc(sizeof(*rpp), GFP_KERNEL);
	if (!rpp)
		return -ENOMEM;

	if (pdata->clkdm)
		clkdm_wakeup(pdata->clkdm);
	iommu_set_isr(pdata->iommu_name, omap_rproc_iommu_isr, rproc);
	iommu_set_secure(pdata->iommu_name, rproc->secure_mode,
						rproc->secure_ttb);
	iommu = iommu_get(pdata->iommu_name);
	if (IS_ERR(iommu)) {
		ret = PTR_ERR(iommu);
		dev_err(dev, "iommu_get error: %d\n", ret);
		goto err_mmu;
	}

	rpp->iommu = iommu;
	rpp->iommu_cb = callback;
	rproc->priv = rpp;

	if (!rproc->secure_mode) {
		for (i = 0; rproc->memory_maps[i].size; i++) {
			const struct rproc_mem_entry *me =
							&rproc->memory_maps[i];

			ret = omap_rproc_map(dev, iommu, me->da, me->pa,
								 me->size);
			if (ret)
				goto err_map;
		}
	}
	if (pdata->clkdm)
		clkdm_allow_idle(pdata->clkdm);

	return 0;

err_map:
	iommu_put(iommu);
err_mmu:
	iommu_set_secure(pdata->iommu_name, false, NULL);
	if (pdata->clkdm)
		clkdm_allow_idle(pdata->clkdm);
	kfree(rpp);
	return ret;
}
Пример #12
0
void tf_l4sec_clkdm_wakeup(bool wakelock)
{
	spin_lock(&tf_get_device()->sm.lock);
#ifdef CONFIG_HAS_WAKELOCK
	if (wakelock) {
		atomic_inc(&tf_wake_lock_count);
		wake_lock(&g_tf_wake_lock);
	}
#endif
	atomic_inc(&smc_l4_sec_clkdm_use_count);
	clkdm_wakeup(smc_l4_sec_clkdm);
	spin_unlock(&tf_get_device()->sm.lock);
}
Пример #13
0
Файл: pm.c Проект: ivdok/linux
/*
 * This sets pwrdm state (other than mpu & core. Currently only ON &
 * RET are supported.
 */
int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
{
	u8 curr_pwrst, next_pwrst;
	int sleep_switch = -1, ret = 0, hwsup = 0;

	if (!pwrdm || IS_ERR(pwrdm))
		return -EINVAL;

	while (!(pwrdm->pwrsts & (1 << pwrst))) {
		if (pwrst == PWRDM_POWER_OFF)
			return ret;
		pwrst--;
	}

	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
	if (next_pwrst == pwrst)
		return ret;

	curr_pwrst = pwrdm_read_pwrst(pwrdm);
	if (curr_pwrst < PWRDM_POWER_ON) {
		if ((curr_pwrst > pwrst) &&
			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
			sleep_switch = LOWPOWERSTATE_SWITCH;
		} else {
			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
			sleep_switch = FORCEWAKEUP_SWITCH;
		}
	}

	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
	if (ret)
		pr_err("%s: unable to set power state of powerdomain: %s\n",
		       __func__, pwrdm->name);

	switch (sleep_switch) {
	case FORCEWAKEUP_SWITCH:
		if (hwsup)
			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
		else
			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
		break;
	case LOWPOWERSTATE_SWITCH:
		pwrdm_set_lowpwrstchange(pwrdm);
		pwrdm_wait_transition(pwrdm);
		pwrdm_state_switch(pwrdm);
		break;
	}

	return ret;
}
Пример #14
0
static int usbhs_wakeup_handler(struct omap_hwmod_mux_info *unused)
{
	int queued;

	queued = queue_delayed_work(pm_wq, &usbhs_wakeup,
			msecs_to_jiffies(20));

	if (queued) {
		clkdm_wakeup(l3init_clkdm);
		pm_runtime_get(&pdev_usbhs->dev);
	}

	return 0;
}
Пример #15
0
/**
 * omap_sec_dispatcher: Routine to dispatch low power secure
 * service routines
 * @idx: The HAL API index
 * @flag: The flag indicating criticality of operation
 * @nargs: Number of valid arguments out of four.
 * @arg1, arg2, arg3 args4: Parameters passed to secure API
 *
 * Return the non-zero error value on failure.
 */
u32 omap_secure_dispatcher(u32 idx, u32 flag, u32 nargs, u32 arg1, u32 arg2,
							 u32 arg3, u32 arg4)
{
	u32 ret = 0;
	u32 param[5];
	unsigned long flags;

	/* If we have an alternate dispatcher api, use it, else use default */
	spin_lock_irqsave(&_secure_dispatcher_lock, flags);
	if (_alternate_secure_dispatcher) {
		ret = _alternate_secure_dispatcher(idx, flag, nargs, arg1,
						   arg2, arg3, arg4);
		spin_unlock_irqrestore(&_secure_dispatcher_lock, flags);
		return ret;
	}
	spin_unlock_irqrestore(&_secure_dispatcher_lock, flags);

	param[0] = nargs;
	param[1] = arg1;
	param[2] = arg2;
	param[3] = arg3;
	param[4] = arg4;

	if (!l4_secure_clkdm) {
		if (cpu_is_omap54xx())
			l4_secure_clkdm = clkdm_lookup("l4sec_clkdm");
		else
			l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm");
	}

	if (!l4_secure_clkdm) {
		pr_err("%s: failed to get l4_secure_clkdm\n", __func__);
		return -EINVAL;
	}

	clkdm_wakeup(l4_secure_clkdm);

	/*
	 * Secure API needs physical address
	 * pointer for the parameters
	 */
	flush_cache_all();
	outer_clean_range(__pa(param), __pa(param + 5));
	ret = omap_smc2(idx, flag, __pa(param));

	clkdm_allow_idle(l4_secure_clkdm);

	return ret;
}
Пример #16
0
/*
 * Function responsible for formatting parameters to pass from NS world to
 * S world
 */
u32 omap4_secure_dispatcher(u32 app_id, u32 flags, u32 nargs,
	u32 arg1, u32 arg2, u32 arg3, u32 arg4)
{
	u32 ret;
	unsigned long iflags;
	u32 pub2sec_args[5] = {0, 0, 0, 0, 0};

	/*dpr_info("%s: app_id=0x%08x, flags=0x%08x, nargs=%u\n",
		__func__, app_id, flags, nargs);*/

	/*if (nargs != 0)
		dpr_info("%s: args=%08x, %08x, %08x, %08x\n",
			__func__, arg1, arg2, arg3, arg4);*/

	pub2sec_args[0] = nargs;
	pub2sec_args[1] = arg1;
	pub2sec_args[2] = arg2;
	pub2sec_args[3] = arg3;
	pub2sec_args[4] = arg4;

	/* Make sure parameters are visible to the secure world */
	dmac_flush_range((void *)pub2sec_args,
		(void *)(((u32)(pub2sec_args)) + 5*sizeof(u32)));
	outer_clean_range(__pa(pub2sec_args),
		__pa(pub2sec_args) + 5*sizeof(u32));
	wmb();

	/*
	 * Put L4 Secure clock domain to SW_WKUP so that modules are accessible
	 */
	clkdm_wakeup(smc_l4_sec_clkdm);

	local_irq_save(iflags);

	/* proc_id is always 0 */
	ret = schedule_secure_world(app_id, 0, flags, __pa(pub2sec_args));
	local_irq_restore(iflags);

	/* Restore the HW_SUP on L4 Sec clock domain so hardware can idle */
	if ((app_id != API_HAL_HWATURNOFF_INDEX) &&
	    (!timer_pending(&tf_crypto_clock_timer))) {
		(void) tf_crypto_turn_off_clocks();
		clkdm_allow_idle(smc_l4_sec_clkdm);
	}

	/*dpr_info("%s()\n", __func__);*/

	return ret;
}
Пример #17
0
static int omap_rproc_iommu_exit(struct rproc *rproc)
{
	struct omap_rproc_priv *rpp = rproc->priv;
	struct omap_rproc_pdata *pdata = rproc->dev->platform_data;

	if (pdata->clkdm)
		clkdm_wakeup(pdata->clkdm);

	if (rpp->iommu)
		iommu_put(rpp->iommu);
	kfree(rpp);
	if (pdata->clkdm)
		clkdm_allow_idle(pdata->clkdm);

	return 0;
}
Пример #18
0
 /*
  * omap4_sar_save -
  * Save the context to SAR_RAM1 and SAR_RAM2 as per
  * omap4xxx_sar_ram1_layout and omap4xxx_sar_ram2_layout for the device OFF
  * mode
  */
int omap4_sar_save(void)
{
	/*
	 * Not supported on ES1.0 silicon
	 */
	if (omap_rev() == OMAP4430_REV_ES1_0) {
		WARN_ONCE(1, "omap4: SAR backup not supported on ES1.0 ..\n");
		return -ENODEV;
	}

	if (omap4_sar_not_accessible()) {
		pr_debug("%s: USB SAR CNTX registers are not accessible!\n",
			 __func__);
		return -EBUSY;
	}

	/*
	 * SAR bits and clocks needs to be enabled
	 */
	clkdm_wakeup(l3init_clkdm);
	pwrdm_enable_hdwr_sar(l3init_pwrdm);
	clk_enable(usb_host_ck);
	clk_enable(usb_tll_ck);

	/* Save SAR BANK1 */
	if (cpu_is_omap446x())
		sar_save(ARRAY_SIZE(omap446x_sar_ram1_layout), SAR_BANK1_OFFSET,
			 omap446x_sar_ram1_layout);
	else
		sar_save(ARRAY_SIZE(omap443x_sar_ram1_layout), SAR_BANK1_OFFSET,
			 omap443x_sar_ram1_layout);

	clk_disable(usb_host_ck);
	clk_disable(usb_tll_ck);
	pwrdm_disable_hdwr_sar(l3init_pwrdm);
	clkdm_allow_idle(l3init_clkdm);

	/* Save SAR BANK2 */
	if (cpu_is_omap446x())
		sar_save(ARRAY_SIZE(omap446x_sar_ram2_layout), SAR_BANK2_OFFSET,
			 omap446x_sar_ram2_layout);
	else
		sar_save(ARRAY_SIZE(omap443x_sar_ram2_layout), SAR_BANK2_OFFSET,
			 omap443x_sar_ram2_layout);

	return 0;
}
Пример #19
0
static void am33xx_post_suspend(unsigned int state)
{
	int status = 0;

	status = pwrdm_read_pwrst(gfx_pwrdm);
	if (status != PWRDM_POWER_OFF)
		pr_err("GFX domain did not transition\n");

	/*
	 * BUG: GFX_L4LS clock domain needs to be woken up to
	 * ensure thet L4LS clock domain does not get stuck in
	 * transition. If that happens L3 module does not get
	 * disabled, thereby leading to PER power domain
	 * transition failing
	 */
	clkdm_wakeup(gfx_l4ls_clkdm);
	clkdm_sleep(gfx_l4ls_clkdm);
}
Пример #20
0
void omap4_usb_sar_restore(void)
{
	u32 i;

	pr_err("USB SAR- SW Restore\n");
	clkdm_wakeup(l3init_clkdm);
	pwrdm_enable_hdwr_sar(l3init_pwrdm);
	clk_enable(usb_host_ck);
	clk_enable(usb_tll_ck);

	for (i = 0; i < (USB_SAR_AREA_END-USB_SAR_AREA_START)/4; i++)
		__raw_writel(usb_sar_data[i].val, usb_sar_data[i].reg_addr);

	clk_disable(usb_host_ck);
	clk_disable(usb_tll_ck);
	pwrdm_disable_hdwr_sar(l3init_pwrdm);
	clkdm_allow_idle(l3init_clkdm);
}
static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
{
	bool hwsup = false;

	if (!clkdm->clktrctrl_mask)
		return 0;

	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
				clkdm->clktrctrl_mask);

	if (hwsup) {
		/* Disable HW transitions when we are changing deps */
		_disable_hwsup(clkdm);
		_clkdm_add_autodeps(clkdm);
		_enable_hwsup(clkdm);
	} else {
		clkdm_wakeup(clkdm);
	}

	return 0;
}
Пример #22
0
int omap_rproc_deactivate(struct omap_device *od)
{
	int i, ret = 0;
	struct rproc *rproc = platform_get_drvdata(&od->pdev);
	struct device *dev = rproc->dev;
	struct omap_rproc_pdata *pdata = dev->platform_data;
	struct omap_rproc_timers_info *timers = pdata->timers;
#ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND
	struct omap_rproc_priv *rpp = rproc->priv;
#endif
	if (pdata->clkdm)
		clkdm_wakeup(pdata->clkdm);

	for (i = 0; i < od->hwmods_cnt; i++) {
		ret = omap_hwmod_shutdown(od->hwmods[i]);
		if (ret)
			goto err;
	}

	for (i = 0; i < pdata->timers_cnt; i++)
		omap_dm_timer_stop(timers[i].odt);

#ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND
	if (rpp->iommu) {
		iommu_put(rpp->iommu);
		rpp->iommu = NULL;
	}

	if (rpp->mbox) {
		omap_mbox_put(rpp->mbox, NULL);
		rpp->mbox = NULL;
	}
#endif
err:
	if (pdata->clkdm)
		clkdm_allow_idle(pdata->clkdm);

	return ret;
}
Пример #23
0
/*
 * omap4_sec_dispatcher: Routine to dispatch low power secure
 * service routines
 *
 * @idx: The HAL API index
 * @flag: The flag indicating criticality of operation
 * @nargs: Number of valid arguments out of four.
 * @arg1, arg2, arg3 args4: Parameters passed to secure API
 *
 * Return the error value on success/failure
 */
u32 omap4_secure_dispatcher(u32 idx, u32 flag, u32 nargs, u32 arg1, u32 arg2,
							 u32 arg3, u32 arg4)
{
	u32 ret;
	u32 param[5];

	param[0] = nargs;
	param[1] = arg1;
	param[2] = arg2;
	param[3] = arg3;
	param[4] = arg4;

	/* Look-up Only once */
	if (!l4_secure_clkdm)
		l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm");

	/*
	 * Put l4 secure to software wakeup  so that secure
	 * modules are accessible
	 */
	clkdm_wakeup(l4_secure_clkdm);

	/*
	 * Secure API needs physical address
	 * pointer for the parameters
	 */
	flush_cache_all();
	outer_clean_range(__pa(param), __pa(param + 5));

	ret = omap_smc2(idx, flag, __pa(param));

	/*
	 * Restore l4 secure to hardware superwised to allow
	 * secure modules idle
	 */
	clkdm_allow_idle(l4_secure_clkdm);

	return ret;
}
Пример #24
0
static void save_sar_bank3(void)
{
	struct clockdomain *l4_secure_clkdm;

	/*
	 * Not supported on ES1.0 silicon
	 */
	if (omap_rev() == OMAP4430_REV_ES1_0) {
		WARN_ONCE(1, "omap4: SAR backup not supported on ES1.0 ..\n");
		return;
	}

	l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm");
	clkdm_wakeup(l4_secure_clkdm);

	if (cpu_is_omap446x())
		sar_save(ARRAY_SIZE(omap446x_sar_ram3_layout), SAR_BANK3_OFFSET,
			 omap446x_sar_ram3_layout);
	else
		sar_save(ARRAY_SIZE(omap443x_sar_ram3_layout), SAR_BANK3_OFFSET,
			 omap443x_sar_ram3_layout);

	clkdm_allow_idle(l4_secure_clkdm);
}
/**
 * omap4_core_dpll_m2_set_rate - set CORE DPLL M2 divider
 * @clk: struct clk * of DPLL to set
 * @rate: rounded target rate
 *
 * Programs the CM shadow registers to update CORE DPLL M2
 * divider. M2 divider is used to clock external DDR and its
 * reconfiguration on frequency change is managed through a
 * hardware sequencer. This is managed by the PRCM with EMIF
 * uding shadow registers.
 * Returns -EINVAL/-1 on error and 0 on success.
 */
int omap4_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
{
    int i = 0;
    u32 validrate = 0, shadow_freq_cfg1 = 0, new_div = 0;
    unsigned long flags;

    if (!clk || !rate)
        return -EINVAL;

    validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
    if (validrate != rate)
        return -EINVAL;

    /* Just to avoid look-up on every call to speed up */
    if (!l3_emif_clkdm) {
        l3_emif_clkdm = clkdm_lookup("l3_emif_clkdm");
        if (!l3_emif_clkdm) {
            pr_err("%s: clockdomain lookup failed\n", __func__);
            return -EINVAL;
        }
    }

    spin_lock_irqsave(&l3_emif_lock, flags);

    /*
     * Errata ID: i728
     *
     * DESCRIPTION:
     *
     * If during a small window the following three events occur:
     *
     * 1) The EMIF_PWR_MGMT_CTRL[7:4] REG_SR_TIM SR_TIMING counter expires
     * 2) Frequency change update is requested CM_SHADOW_FREQ_CONFIG1
     *    FREQ_UPDATE set to 1
     * 3) OCP access is requested
     *
     * There will be instable clock on the DDR interface.
     *
     * WORKAROUND:
     *
     * Prevent event 1) while event 2) is happening.
     *
     * Disable the self-refresh when requesting a frequency change.
     * Before requesting a frequency change, program
     * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x0
     * (omap_emif_frequency_pre_notify)
     *
     * When the frequency change is completed, reprogram
     * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x2.
     * (omap_emif_frequency_post_notify)
     */
    omap_emif_frequency_pre_notify();

    /* Configures MEMIF domain in SW_WKUP */
    clkdm_wakeup(l3_emif_clkdm);

    /*
     * Program EMIF timing parameters in EMIF shadow registers
     * for targetted DRR clock.
     * DDR Clock = core_dpll_m2 / 2
     */
    omap_emif_setup_registers(validrate >> 1, LPDDR2_VOLTAGE_STABLE);

    /*
     * FREQ_UPDATE sequence:
     * - DLL_OVERRIDE=0 (DLL lock & code must not be overridden
     *	after CORE DPLL lock)
     * - DLL_RESET=1 (DLL must be reset upon frequency change)
     * - DPLL_CORE_M2_DIV with same value as the one already
     *	in direct register
     * - DPLL_CORE_DPLL_EN=0x7 (to make CORE DPLL lock)
     * - FREQ_UPDATE=1 (to start HW sequence)
     */
    shadow_freq_cfg1 = (1 << OMAP4430_DLL_RESET_SHIFT) |
                       (new_div << OMAP4430_DPLL_CORE_M2_DIV_SHIFT) |
                       (DPLL_LOCKED << OMAP4430_DPLL_CORE_DPLL_EN_SHIFT) |
                       (1 << OMAP4430_FREQ_UPDATE_SHIFT);
    shadow_freq_cfg1 &= ~OMAP4430_DLL_OVERRIDE_MASK;
    __raw_writel(shadow_freq_cfg1, OMAP4430_CM_SHADOW_FREQ_CONFIG1);

    /* wait for the configuration to be applied */
    omap_test_timeout(((__raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1)
                        & OMAP4430_FREQ_UPDATE_MASK) == 0),
                      MAX_FREQ_UPDATE_TIMEOUT, i);

    /* Configures MEMIF domain back to HW_WKUP */
    clkdm_allow_idle(l3_emif_clkdm);

    /* Re-enable DDR self refresh */
    omap_emif_frequency_post_notify();

    spin_unlock_irqrestore(&l3_emif_lock, flags);

    if (i == MAX_FREQ_UPDATE_TIMEOUT) {
        pr_err("%s: Frequency update for CORE DPLL M2 change failed\n",
               __func__);
        return -1;
    }

    /* Update the clock change */
    clk->rate = validrate;

    return 0;
}
/**
 * omap4_prcm_freq_update - set freq_update bit
 *
 * Programs the CM shadow registers to update EMIF
 * parametrs. Few usecase only few registers needs to
 * be updated using prcm freq update sequence.
 * EMIF read-idle control and zq-config needs to be
 * updated for temprature alerts and voltage change
 * Returns -1 on error and 0 on success.
 */
int omap4_prcm_freq_update(void)
{
    u32 shadow_freq_cfg1;
    int i = 0;
    unsigned long flags;

    if (!l3_emif_clkdm) {
        pr_err("%s: clockdomain lookup failed\n", __func__);
        return -EINVAL;
    }

    spin_lock_irqsave(&l3_emif_lock, flags);

    /*
     * Errata ID: i728
     *
     * DESCRIPTION:
     *
     * If during a small window the following three events occur:
     *
     * 1) The EMIF_PWR_MGMT_CTRL[7:4] REG_SR_TIM SR_TIMING counter expires
     * 2) Frequency change update is requested CM_SHADOW_FREQ_CONFIG1
     *    FREQ_UPDATE set to 1
     * 3) OCP access is requested
     *
     * There will be instable clock on the DDR interface.
     *
     * WORKAROUND:
     *
     * Prevent event 1) while event 2) is happening.
     *
     * Disable the self-refresh when requesting a frequency change.
     * Before requesting a frequency change, program
     * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x0
     * (omap_emif_frequency_pre_notify)
     *
     * When the frequency change is completed, reprogram
     * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x2.
     * (omap_emif_frequency_post_notify)
     */
    omap_emif_frequency_pre_notify();

    /* Configures MEMIF domain in SW_WKUP */
    clkdm_wakeup(l3_emif_clkdm);

    /*
     * FREQ_UPDATE sequence:
     * - DLL_OVERRIDE=0 (DLL lock & code must not be overridden
     *	after CORE DPLL lock)
     * - FREQ_UPDATE=1 (to start HW sequence)
     */
    shadow_freq_cfg1 = __raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1);
    shadow_freq_cfg1 |= (1 << OMAP4430_DLL_RESET_SHIFT) |
                        (1 << OMAP4430_FREQ_UPDATE_SHIFT);
    shadow_freq_cfg1 &= ~OMAP4430_DLL_OVERRIDE_MASK;
    __raw_writel(shadow_freq_cfg1, OMAP4430_CM_SHADOW_FREQ_CONFIG1);

    /* wait for the configuration to be applied */
    omap_test_timeout(((__raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1)
                        & OMAP4430_FREQ_UPDATE_MASK) == 0),
                      MAX_FREQ_UPDATE_TIMEOUT, i);

    /* Configures MEMIF domain back to HW_WKUP */
    clkdm_allow_idle(l3_emif_clkdm);

    /* Re-enable DDR self refresh */
    omap_emif_frequency_post_notify();

    spin_unlock_irqrestore(&l3_emif_lock, flags);

    if (i == MAX_FREQ_UPDATE_TIMEOUT) {
        pr_err("%s: Frequency update failed (call from %pF)\n",
               __func__, (void *)_RET_IP_);
        pr_err("CLKCTRL: EMIF_1=0x%x EMIF_2=0x%x DMM=0x%x\n",
               __raw_readl(OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL),
               __raw_readl(OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL),
               __raw_readl(OMAP4430_CM_MEMIF_DMM_CLKCTRL));
        emif_dump(0);
        emif_dump(1);
        return -1;
    }

    return 0;
}
Пример #27
0
static int am33xx_pm_suspend(void)
{
	int state, ret = 0;

	struct omap_hwmod *gpmc_oh, *usb_oh, *gpio1_oh;

	usb_oh		= omap_hwmod_lookup("usb_otg_hs");
	gpmc_oh		= omap_hwmod_lookup("gpmc");
	gpio1_oh	= omap_hwmod_lookup("gpio1");	/* WKUP domain GPIO */

	omap_hwmod_enable(usb_oh);
	omap_hwmod_enable(gpmc_oh);

	/*
	 * Keep USB module enabled during standby
	 * to enable USB remote wakeup
	 * Note: This will result in hard-coding USB state
	 * during standby
	 */
	if (suspend_state != PM_SUSPEND_STANDBY)
		omap_hwmod_idle(usb_oh);

	omap_hwmod_idle(gpmc_oh);

	/*
	 * Disable the GPIO module. This ensure that
	 * only sWAKEUP interrupts to Cortex-M3 get generated
	 *
	 * XXX: EVM_SK uses a GPIO0 pin for VTP control
	 * in suspend and hence we can't do this for EVM_SK
	 * alone. The side-effect of this is that GPIO wakeup
	 * might have issues. Refer to commit 672639b for the
	 * details
	 */
	/*
	 * Keep GPIO0 module enabled during standby to
	 * support wakeup via GPIO0 keys.
	 */
	if ((suspend_cfg_param_list[EVM_ID] != EVM_SK) &&
			(suspend_state != PM_SUSPEND_STANDBY))
		omap_hwmod_idle(gpio1_oh);
	/*
	 * Update Suspend_State value to be used in sleep33xx.S to keep
	 * GPIO0 module enabled during standby for EVM-SK
	 */
	if (suspend_state == PM_SUSPEND_STANDBY)
		suspend_cfg_param_list[SUSPEND_STATE] = PM_STANDBY;
	else
		suspend_cfg_param_list[SUSPEND_STATE] = PM_DS0;

	/*
	 * Keep Touchscreen module enabled during standby
	 * to enable wakeup from standby.
	 */
	if (suspend_state == PM_SUSPEND_STANDBY)
		writel(0x2, AM33XX_CM_WKUP_ADC_TSC_CLKCTRL);

	if (gfx_l3_clkdm && gfx_l4ls_clkdm) {
		clkdm_sleep(gfx_l3_clkdm);
		clkdm_sleep(gfx_l4ls_clkdm);
	}

	/* Try to put GFX to sleep */
	if (gfx_pwrdm)
		pwrdm_set_next_pwrst(gfx_pwrdm, PWRDM_POWER_OFF);
	else
		pr_err("Could not program GFX to low power state\n");

	omap3_intc_suspend();

	writel(0x0, AM33XX_CM_MPU_MPU_CLKCTRL);

	ret = cpu_suspend(0, am33xx_do_sram_idle);

	writel(0x2, AM33XX_CM_MPU_MPU_CLKCTRL);

	if (gfx_pwrdm) {
		state = pwrdm_read_pwrst(gfx_pwrdm);
		if (state != PWRDM_POWER_OFF)
			pr_err("GFX domain did not transition to low power state\n");
		else
			pr_info("GFX domain entered low power state\n");
	}

	/* XXX: Why do we need to wakeup the clockdomains? */
	if(gfx_l3_clkdm && gfx_l4ls_clkdm) {
		clkdm_wakeup(gfx_l3_clkdm);
		clkdm_wakeup(gfx_l4ls_clkdm);
	}

	/*
	 * Touchscreen module was enabled during standby
	 * Disable it here.
	 */
	if (suspend_state == PM_SUSPEND_STANDBY)
		writel(0x0, AM33XX_CM_WKUP_ADC_TSC_CLKCTRL);

	/*
	 * Put USB module to idle on resume from standby
	 */
	if (suspend_state == PM_SUSPEND_STANDBY)
		omap_hwmod_idle(usb_oh);

	ret = am33xx_verify_lp_state(ret);

	/*
	 * Enable the GPIO module. Once the driver is
	 * fully adapted to runtime PM this will go away
	 */
	/*
	 * During standby, GPIO was not disabled. Hence no
	 * need to enable it here.
	 */
	if ((suspend_cfg_param_list[EVM_ID] != EVM_SK) &&
			(suspend_state != PM_SUSPEND_STANDBY))
		omap_hwmod_enable(gpio1_oh);

	return ret;
}
Пример #28
0
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
	static struct clockdomain *cpu1_clkdm;
	static bool booted;

	/*
	 * Set synchronisation state between this boot processor
	 * and the secondary one
	 */
	spin_lock(&boot_lock);

	/*
	 * Update the AuxCoreBoot0 with boot state for secondary core.
	 * omap_secondary_startup() routine will hold the secondary core till
	 * the AuxCoreBoot1 register is updated with cpu state
	 * A barrier is added to ensure that write buffer is drained
	 */
	omap_modify_auxcoreboot0(0x200, 0xfffffdff);
	flush_cache_all();
	smp_wmb();

	if (!cpu1_clkdm)
		cpu1_clkdm = clkdm_lookup("mpu1_clkdm");

	/*
	 * The SGI(Software Generated Interrupts) are not wakeup capable
	 * from low power states. This is known limitation on OMAP4 and
	 * needs to be worked around by using software forced clockdomain
	 * wake-up. To wakeup CPU1, CPU0 forces the CPU1 clockdomain to
	 * software force wakeup. After the wakeup, CPU1 restores its
	 * clockdomain hardware supervised mode.
	 * More details can be found in OMAP4430 TRM - Version J
	 * Section :
	 *	4.3.4.2 Power States of CPU0 and CPU1
	 */
	if (booted) {
		/*
		 * GIC distributor control register has changed between
		 * CortexA9 r1pX and r2pX. The Control Register secure
		 * banked version is now composed of 2 bits:
		 * bit 0 == Secure Enable
		 * bit 1 == Non-Secure Enable
		 * The Non-Secure banked register has not changed
		 * Because the ROM Code is based on the r1pX GIC, the CPU1
		 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
		 * The workaround must be:
		 * 1) Before doing the CPU1 wakeup, CPU0 must disable
		 * the GIC distributor
		 * 2) CPU1 must re-enable the GIC distributor on
		 * it's wakeup path.
		 */
		if (!cpu_is_omap443x()) {
			local_irq_disable();
			gic_dist_disable();
		}

		clkdm_wakeup(cpu1_clkdm);

		if (!cpu_is_omap443x()) {
			while (gic_dist_disabled()) {
				udelay(1);
				cpu_relax();
			}
			gic_timer_retrigger();
			local_irq_enable();
		}

	} else {
		clkdm_init_mpu1(cpu1_clkdm);

		dsb_sev();
		booted = true;
	}

	/*
	 * Now the secondary core is starting up let it run its
	 * calibrations, then wait for it to finish
	 */
	spin_unlock(&boot_lock);

	return 0;
}
Пример #29
0
/**
 * omap4_core_dpll_m2_set_rate - set CORE DPLL M2 divider
 * @clk: struct clk * of DPLL to set
 * @rate: rounded target rate
 *
 * Programs the CM shadow registers to update CORE DPLL M2
 * divider. M2 divider is used to clock external DDR and its
 * reconfiguration on frequency change is managed through a
 * hardware sequencer. This is managed by the PRCM with EMIF
 * uding shadow registers.
 * Returns -EINVAL/-1 on error and 0 on success.
 */
int omap4_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
{
	int i = 0;
	u32 validrate = 0, shadow_freq_cfg1 = 0, new_div = 0;
	unsigned long flags;

	if (!clk || !rate)
		return -EINVAL;

	validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
	if (validrate != rate)
		return -EINVAL;

	/* Just to avoid look-up on every call to speed up */
	if (!l3_emif_clkdm) {
		l3_emif_clkdm = clkdm_lookup("l3_emif_clkdm");
		if (!l3_emif_clkdm) {
			pr_err("%s: clockdomain lookup failed\n", __func__);
			return -EINVAL;
		}
	}

	spin_lock_irqsave(&l3_emif_lock, flags);

	/* Configures MEMIF domain in SW_WKUP */
	clkdm_wakeup(l3_emif_clkdm);

	/*
	 * Program EMIF timing parameters in EMIF shadow registers
	 * for targetted DRR clock.
	 * DDR Clock = core_dpll_m2 / 2
	 */
	omap_emif_setup_registers(validrate >> 1, LPDDR2_VOLTAGE_STABLE);

	/*
	 * FREQ_UPDATE sequence:
	 * - DLL_OVERRIDE=0 (DLL lock & code must not be overridden
	 *	after CORE DPLL lock)
	 * - DLL_RESET=1 (DLL must be reset upon frequency change)
	 * - DPLL_CORE_M2_DIV with same value as the one already
	 *	in direct register
	 * - DPLL_CORE_DPLL_EN=0x7 (to make CORE DPLL lock)
	 * - FREQ_UPDATE=1 (to start HW sequence)
	 */
	shadow_freq_cfg1 = (1 << OMAP4430_DLL_RESET_SHIFT) |
			(new_div << OMAP4430_DPLL_CORE_M2_DIV_SHIFT) |
			(DPLL_LOCKED << OMAP4430_DPLL_CORE_DPLL_EN_SHIFT) |
			(1 << OMAP4430_FREQ_UPDATE_SHIFT);
	shadow_freq_cfg1 &= ~OMAP4430_DLL_OVERRIDE_MASK;
	__raw_writel(shadow_freq_cfg1, OMAP4430_CM_SHADOW_FREQ_CONFIG1);

	/* wait for the configuration to be applied */
	omap_test_timeout(((__raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1)
				& OMAP4430_FREQ_UPDATE_MASK) == 0),
				MAX_FREQ_UPDATE_TIMEOUT, i);

	/* Configures MEMIF domain back to HW_WKUP */
	clkdm_allow_idle(l3_emif_clkdm);

	spin_unlock_irqrestore(&l3_emif_lock, flags);

	if (i == MAX_FREQ_UPDATE_TIMEOUT) {
		pr_err("%s: Frequency update for CORE DPLL M2 change failed\n",
				__func__);
		return -1;
	}

	/* Update the clock change */
	clk->rate = validrate;

	return 0;
}
Пример #30
0
static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
	static struct clockdomain *cpu1_clkdm;
	static bool booted;
	static struct powerdomain *cpu1_pwrdm;
	void __iomem *base = omap_get_wakeupgen_base();

	/*
	 * Set synchronisation state between this boot processor
	 * and the secondary one
	 */
	spin_lock(&boot_lock);

	/*
	 * Update the AuxCoreBoot0 with boot state for secondary core.
	 * omap4_secondary_startup() routine will hold the secondary core till
	 * the AuxCoreBoot1 register is updated with cpu state
	 * A barrier is added to ensure that write buffer is drained
	 */
	if (omap_secure_apis_support())
		omap_modify_auxcoreboot0(0x200, 0xfffffdff);
	else
		__raw_writel(0x20, base + OMAP_AUX_CORE_BOOT_0);

	if (!cpu1_clkdm && !cpu1_pwrdm) {
		cpu1_clkdm = clkdm_lookup("mpu1_clkdm");
		cpu1_pwrdm = pwrdm_lookup("cpu1_pwrdm");
	}

	/*
	 * The SGI(Software Generated Interrupts) are not wakeup capable
	 * from low power states. This is known limitation on OMAP4 and
	 * needs to be worked around by using software forced clockdomain
	 * wake-up. To wakeup CPU1, CPU0 forces the CPU1 clockdomain to
	 * software force wakeup. The clockdomain is then put back to
	 * hardware supervised mode.
	 * More details can be found in OMAP4430 TRM - Version J
	 * Section :
	 *	4.3.4.2 Power States of CPU0 and CPU1
	 */
	if (booted && cpu1_pwrdm && cpu1_clkdm) {
		/*
		 * GIC distributor control register has changed between
		 * CortexA9 r1pX and r2pX. The Control Register secure
		 * banked version is now composed of 2 bits:
		 * bit 0 == Secure Enable
		 * bit 1 == Non-Secure Enable
		 * The Non-Secure banked register has not changed
		 * Because the ROM Code is based on the r1pX GIC, the CPU1
		 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
		 * The workaround must be:
		 * 1) Before doing the CPU1 wakeup, CPU0 must disable
		 * the GIC distributor
		 * 2) CPU1 must re-enable the GIC distributor on
		 * it's wakeup path.
		 */
		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
			local_irq_disable();
			gic_dist_disable();
		}

		/*
		 * Ensure that CPU power state is set to ON to avoid CPU
		 * powerdomain transition on wfi
		 */
		clkdm_wakeup(cpu1_clkdm);
		omap_set_pwrdm_state(cpu1_pwrdm, PWRDM_POWER_ON);
		clkdm_allow_idle(cpu1_clkdm);

		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
			while (gic_dist_disabled()) {
				udelay(1);
				cpu_relax();
			}
			gic_timer_retrigger();
			local_irq_enable();
		}
	} else {
		dsb_sev();
		booted = true;
	}

	arch_send_wakeup_ipi_mask(cpumask_of(cpu));

	/*
	 * Now the secondary core is starting up let it run its
	 * calibrations, then wait for it to finish
	 */
	spin_unlock(&boot_lock);

	return 0;
}