static int sr_class3_enable(struct voltagedomain *voltdm,
		struct omap_volt_data *volt_data)
{

	omap_vp_enable(voltdm);
	return sr_enable(voltdm, volt_data);
}
/**
 * sr_class1p5_enable() - class 1.5 mode of enable for a voltage domain
 * @voltdm:		voltage domain to enable SR for
 * @voltdm_cdata:	voltage domain specific private class data
 * @volt_data:		voltdata for the current OPP being transitioned to
 *
 * when this gets called, we use the h/w loop to setup our voltages
 * to an calibrated voltage, detect any oscillations, recover from the same
 * and finally store the optimized voltage as the calibrated voltage in the
 * system.
 *
 * NOTE: Appropriate locks must be held by calling path to ensure mutual
 * exclusivity
 */
static int sr_class1p5_enable(struct voltagedomain *voltdm,
			      void *voltdm_cdata,
			      struct omap_volt_data *volt_data)
{
	int r;
	struct sr_class1p5_work_data *work_data;

	/* check bypass flag, if enabled, do nothing */
	if (volt_data->sr_bypass)
		return 0;

	if (IS_ERR_OR_NULL(voltdm) || IS_ERR_OR_NULL(volt_data)) {
		pr_err("%s: bad parameters!\n", __func__);
		return -EINVAL;
	}

	/* If already calibrated, nothing to do here.. */
	if (volt_data->volt_calibrated)
		return 0;

	/* Based on Imoseyon's idea to properly calibrate high frequencies e.g. >= 1.4Ghz MPU */
	if (volt_data->volt_nominal >= 1375000) {
		volt_data->volt_calibrated = volt_data->volt_nominal;
		volt_data->volt_dynamic_nominal = volt_data->volt_nominal;
		pr_info("[franciscofranco] %p - nominal %d", __func__, volt_data->volt_nominal);
		pr_info("[franciscofranco] %p - in the selected OPP its default nominal voltage is equal or above 1375mV so we don't calibrate it to prevent a crash.", __func__);
		return 0;
	}

	work_data = (struct sr_class1p5_work_data *)voltdm_cdata;
	if (IS_ERR_OR_NULL(work_data)) {
		pr_err("%s: bad work data??\n", __func__);
		return -EINVAL;
	}

	if (work_data->work_active)
		return 0;

	omap_vp_enable(voltdm);
	r = sr_enable(voltdm, volt_data);
	if (r) {
		pr_err("%s: sr[%s] failed\n", __func__, voltdm->name);
		sr_disable_errgen(voltdm);
		omap_vp_disable(voltdm);
		return r;
	}
	work_data->vdata = volt_data;
	work_data->work_active = true;
	work_data->num_calib_triggers = 0;
	/* Dont interrupt me untill calibration is complete */
	pm_qos_update_request(&work_data->qos, 0);
	/* program the workqueue and leave it to calibrate offline.. */
	schedule_delayed_work(&work_data->work,
			      msecs_to_jiffies(SR1P5_SAMPLING_DELAY_MS *
					       SR1P5_STABLE_SAMPLES));

	return 0;
}
/**
 * sr_classp5_start_hw_loop()
 * @sr:		SmartReflex for which we start calibration
 *
 * Starts hardware calibration
 */
static int sr_classp5_start_hw_loop(struct omap_sr *sr)
{
	int res;

	omap_vp_enable(sr->voltdm);
	res = sr_enable(sr);
	if (res) {
		pr_err("%s: %s failed to start HW loop\n", __func__, sr->name);
		omap_vp_disable(sr->voltdm);
	}
	return res;
}
Esempio n. 4
0
static int sr_class3_enable(struct voltagedomain *voltdm)
{
	unsigned long volt = omap_voltage_get_nom_volt(voltdm);

	if (!volt) {
		pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
				__func__, voltdm->name);
		return -ENODATA;
	}

	omap_vp_enable(voltdm);
	return sr_enable(voltdm, volt);
}
static int sr_class3_enable(struct omap_sr *sr)
{
	unsigned long volt = voltdm_get_voltage(sr->voltdm);

	if (!volt) {
		pr_warning("%s: Curr voltage unknown. Cannot enable %s\n",
				__func__, sr->name);
		return -ENODATA;
	}

	omap_vp_enable(sr->voltdm);
	return sr_enable(sr->voltdm, volt);
}
/**
 * sr_class1p5_enable() - class 1.5 mode of enable
 * @voltdm:		voltage domain to enable SR for
 * @volt_data:	voltdata to the voltage transition taking place
 *
 * when this gets called, we use the h/w loop to setup our voltages
 * to an calibrated voltage, detect any oscillations, recover from the same
 * and finally store the optimized voltage as the calibrated voltage in the
 * system
 */
static int sr_class1p5_enable(struct voltagedomain *voltdm,
			      struct omap_volt_data *volt_data)
{
	int r;
	struct sr_class1p5_work_data *work_data;

	if (IS_ERR_OR_NULL(voltdm) || IS_ERR_OR_NULL(volt_data)) {
		pr_err("%s: bad parameters!\n", __func__);
		return -EINVAL;
	}

	/* if already calibrated, nothing to do here.. */
	if (volt_data->volt_calibrated)
		return 0;

	work_data = get_sr1p5_work(voltdm);
	if (unlikely(!work_data)) {
		pr_err("%s: aieeee.. bad work data??\n", __func__);
		return -EINVAL;
	}

	if (work_data->work_active)
		return 0;

	omap_vp_enable(voltdm);
	r = sr_enable(voltdm, volt_data);
	if (r) {
		pr_err("%s: sr[%s] failed\n", __func__, voltdm->name);
		omap_vp_disable(voltdm);
		return r;
	}
	work_data->vdata = volt_data;
	work_data->work_active = true;
	work_data->num_calib_triggers = 0;

	/* Hold a c-state constraint */
	omap_pm_set_max_mpu_wakeup_lat(&work_data->qos_request, 1000);
	pr_debug("%s - %s: hold c-state\n", __func__, voltdm->name);

	/* program the workqueue and leave it to calibrate offline.. */
	schedule_delayed_work(&work_data->work,
			      msecs_to_jiffies(SR1P5_SAMPLING_DELAY_MS *
					       SR1P5_STABLE_SAMPLES));

	return 0;
}
/**
 * sr_class1p5_enable() - class 1.5 mode of enable for a voltage domain
 * @voltdm:		voltage domain to enable SR for
 * @voltdm_cdata:	voltage domain specific private class data
 * @volt_data:		voltdata for the current OPP being transitioned to
 *
 * when this gets called, we use the h/w loop to setup our voltages
 * to an calibrated voltage, detect any oscillations, recover from the same
 * and finally store the optimized voltage as the calibrated voltage in the
 * system.
 *
 * NOTE: Appropriate locks must be held by calling path to ensure mutual
 * exclusivity
 */
static int sr_class1p5_enable(struct voltagedomain *voltdm,
                              void *voltdm_cdata,
                              struct omap_volt_data *volt_data)
{
    int r;
    struct sr_class1p5_work_data *work_data;

    if (IS_ERR_OR_NULL(voltdm) || IS_ERR_OR_NULL(volt_data)) {
        pr_err("%s: bad parameters!\n", __func__);
        return -EINVAL;
    }

    /* If already calibrated, nothing to do here.. */
    if (volt_data->volt_calibrated)
        return 0;

    work_data = (struct sr_class1p5_work_data *)voltdm_cdata;
    if (IS_ERR_OR_NULL(work_data)) {
        pr_err("%s: bad work data??\n", __func__);
        return -EINVAL;
    }

    if (work_data->work_active)
        return 0;

    omap_vp_enable(voltdm);
    r = sr_enable(voltdm, volt_data);
    if (r) {
        pr_err("%s: sr[%s] failed\n", __func__, voltdm->name);
        sr_disable_errgen(voltdm);
        omap_vp_disable(voltdm);
        return r;
    }
    work_data->vdata = volt_data;
    work_data->work_active = true;
    work_data->num_calib_triggers = 0;
    /* program the workqueue and leave it to calibrate offline.. */
    schedule_delayed_work(&work_data->work,
                          msecs_to_jiffies(SR1P5_SAMPLING_DELAY_MS *
                                           SR1P5_STABLE_SAMPLES));

    return 0;
}