示例#1
0
int msm_spm_drv_set_vdd(struct msm_spm_driver_data *dev, unsigned int vlevel)
{
	uint32_t timeout_us;

	if (!dev)
		return -EINVAL;

	if (msm_spm_debug_mask & MSM_SPM_DEBUG_VCTL)
		pr_info("%s: requesting vlevel 0x%x\n",
			__func__, vlevel);

	msm_spm_drv_set_vctl(dev, vlevel);
	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_VCTL);
	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_PMIC_DATA_0);
	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_PMIC_DATA_1);
	mb();

	/* Wait for PMIC state to return to idle or until timeout */
	timeout_us = dev->vctl_timeout_us;
	msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_STS0);
	while (msm_spm_drv_get_sts_pmic_state(dev) != MSM_SPM_PMIC_STATE_IDLE) {
		if (!timeout_us)
			goto set_vdd_bail;

		if (timeout_us > 10) {
			udelay(10);
			timeout_us -= 10;
		} else {
			udelay(timeout_us);
			timeout_us = 0;
		}
		msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_STS0);
	}

	msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_STS1);

	if (msm_spm_drv_get_sts_curr_pmic_data(dev) != vlevel)
		goto set_vdd_bail;

	if (msm_spm_debug_mask & MSM_SPM_DEBUG_VCTL)
		pr_info("%s: done, remaining timeout %uus\n",
			__func__, timeout_us);

	return 0;

set_vdd_bail:
	pr_err("%s: failed, remaining timeout %uus, vlevel 0x%x\n",
	       __func__, timeout_us, msm_spm_drv_get_sts_curr_pmic_data(dev));
	return -EIO;
}
示例#2
0
static inline bool msm_spm_pmic_arb_present(struct msm_spm_driver_data *dev)
{
	msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_ID);

	if (dev->major == SAW2_MAJOR_2)
		return (dev->reg_shadow[MSM_SPM_REG_SAW2_ID] >> 2) & 0x1;
	else
		return (dev->reg_shadow[MSM_SPM_REG_SAW2_ID] >> 18) & 0x1;
示例#3
0
int msm_spm_drv_set_low_power_mode(struct msm_spm_driver_data *dev,
		uint32_t addr)
{
	void *base = NULL;

	/* SPM is configured to reset start address to zero after end of Program
	 */
	if (!dev)
		return -EINVAL;

	base = dev->reg_base_addr;
	msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_SPM_CTL);
	msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_STS0);
	uncached_logk_pc(LOGK_PM,
		(void *)(base + msm_spm_reg_offsets[MSM_SPM_REG_SAW2_SPM_CTL]),
		(void *)dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL]);
	uncached_logk_pc(LOGK_PM,
		(void *)(base + msm_spm_reg_offsets[MSM_SPM_REG_SAW2_STS0]),
		(void *)dev->reg_shadow[MSM_SPM_REG_SAW2_STS0]);

	msm_spm_drv_set_start_addr(dev, addr);

	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_SPM_CTL);
	wmb();

	uncached_logk_pc(LOGK_PM,
		(void *)(base + msm_spm_reg_offsets[MSM_SPM_REG_SAW2_SPM_CTL]),
		(void *)dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL]);

	if (msm_spm_debug_mask & MSM_SPM_DEBUG_SHADOW) {
		int i;
		for (i = 0; i < MSM_SPM_REG_NR; i++)
			pr_info("%s: reg %02x = 0x%08x\n", __func__,
				msm_spm_reg_offsets[i], dev->reg_shadow[i]);
	}

	return 0;
}
示例#4
0
int __init msm_spm_drv_init(struct msm_spm_driver_data *dev,
		struct msm_spm_platform_data *data)
{

	int i;
	int num_spm_entry;

	BUG_ON(!dev || !data);

	dev->reg_base_addr = data->reg_base_addr;
	memcpy(dev->reg_shadow, data->reg_init_values,
			sizeof(data->reg_init_values));

	dev->vctl_timeout_us = data->vctl_timeout_us;

	for (i = 0; i < MSM_SPM_REG_NR_INITIALIZE; i++)
		msm_spm_drv_flush_shadow(dev, i);
	/* barrier to ensure write completes before we update shadow
	 * registers
	 */
	mb();

	for (i = 0; i < MSM_SPM_REG_NR_INITIALIZE; i++)
		msm_spm_drv_load_shadow(dev, i);

	/* barrier to ensure read completes before we proceed further*/
	mb();

	num_spm_entry = msm_spm_drv_get_num_spm_entry(dev);

	dev->reg_seq_entry_shadow =
		kmalloc(sizeof(*dev->reg_seq_entry_shadow) * num_spm_entry,
				GFP_KERNEL);

	if (!dev->reg_seq_entry_shadow)
		return -ENOMEM;


	memset(dev->reg_seq_entry_shadow, 0x0f,
			num_spm_entry * sizeof(*dev->reg_seq_entry_shadow));

	return 0;
}