#include <linux/delay.h>
#include <linux/io.h>
-#include <linux/clk.h>
#include <linux/err.h>
+#include <linux/export.h>
#include <linux/debugfs.h>
#include <linux/slab.h>
+#include <linux/clk.h>
#include <plat/common.h>
static LIST_HEAD(voltdm_list);
-static int __init _config_common_vdd_data(struct voltagedomain *voltdm)
-{
- char *sys_ck_name;
- struct clk *sys_ck;
- u32 sys_clk_speed, timeout_val, waittime;
- struct omap_vdd_info *vdd = voltdm->vdd;
-
- /*
- * XXX Clockfw should handle this, or this should be in a
- * struct record
- */
- if (cpu_is_omap24xx() || cpu_is_omap34xx())
- sys_ck_name = "sys_ck";
- else if (cpu_is_omap44xx())
- sys_ck_name = "sys_clkin_ck";
- else
- return -EINVAL;
-
- /*
- * Sys clk rate is require to calculate vp timeout value and
- * smpswaittimemin and smpswaittimemax.
- */
- sys_ck = clk_get(NULL, sys_ck_name);
- if (IS_ERR(sys_ck)) {
- pr_warning("%s: Could not get the sys clk to calculate"
- "various vdd_%s params\n", __func__, voltdm->name);
- return -EINVAL;
- }
- sys_clk_speed = clk_get_rate(sys_ck);
- clk_put(sys_ck);
- /* Divide to avoid overflow */
- sys_clk_speed /= 1000;
-
- /* Generic voltage parameters */
- vdd->volt_scale = omap_vp_forceupdate_scale;
- voltdm->vp->enabled = false;
-
- vdd->vp_rt_data.vpconfig_erroroffset =
- (voltdm->pmic->vp_erroroffset <<
- voltdm->vp->common->vpconfig_erroroffset_shift);
-
- timeout_val = (sys_clk_speed * voltdm->pmic->vp_timeout_us) / 1000;
- vdd->vp_rt_data.vlimitto_timeout = timeout_val;
- vdd->vp_rt_data.vlimitto_vddmin = voltdm->pmic->vp_vddmin;
- vdd->vp_rt_data.vlimitto_vddmax = voltdm->pmic->vp_vddmax;
-
- waittime = ((voltdm->pmic->step_size / voltdm->pmic->slew_rate) *
- sys_clk_speed) / 1000;
- vdd->vp_rt_data.vstepmin_smpswaittimemin = waittime;
- vdd->vp_rt_data.vstepmax_smpswaittimemax = waittime;
- vdd->vp_rt_data.vstepmin_stepmin = voltdm->pmic->vp_vstepmin;
- vdd->vp_rt_data.vstepmax_stepmax = voltdm->pmic->vp_vstepmax;
-
- return 0;
-}
-
-static int __init omap_vdd_data_configure(struct voltagedomain *voltdm)
-{
- int ret = -EINVAL;
-
- if (!voltdm->pmic) {
- pr_err("%s: PMIC info requried to configure vdd_%s not"
- "populated.Hence cannot initialize vdd_%s\n",
- __func__, voltdm->name, voltdm->name);
- goto ovdc_out;
- }
-
- if (IS_ERR_VALUE(_config_common_vdd_data(voltdm)))
- goto ovdc_out;
-
- ret = 0;
-
-ovdc_out:
- return ret;
-}
-
/* Public functions */
/**
- * omap_voltage_get_nom_volt() - Gets the current non-auto-compensated voltage
- * @voltdm: pointer to the VDD for which current voltage info is needed
+ * voltdm_get_voltage() - Gets the current non-auto-compensated voltage
+ * @voltdm: pointer to the voltdm for which current voltage info is needed
*
- * API to get the current non-auto-compensated voltage for a VDD.
- * Returns 0 in case of error else returns the current voltage for the VDD.
+ * API to get the current non-auto-compensated voltage for a voltage domain.
+ * Returns 0 in case of error else returns the current voltage.
*/
-unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm)
+unsigned long voltdm_get_voltage(struct voltagedomain *voltdm)
{
- struct omap_vdd_info *vdd;
-
if (!voltdm || IS_ERR(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return 0;
}
- vdd = voltdm->vdd;
-
- return vdd->curr_volt;
+ return voltdm->nominal_volt;
}
/**
- * omap_voltage_scale_vdd() - API to scale voltage of a particular
- * voltage domain.
- * @voltdm: pointer to the VDD which is to be scaled.
- * @target_volt: The target voltage of the voltage domain
+ * voltdm_scale() - API to scale voltage of a particular voltage domain.
+ * @voltdm: pointer to the voltage domain which is to be scaled.
+ * @target_volt: The target voltage of the voltage domain
*
* This API should be called by the kernel to do the voltage scaling
- * for a particular voltage domain during dvfs or any other situation.
+ * for a particular voltage domain during DVFS.
*/
-int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
- unsigned long target_volt)
+int voltdm_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt)
{
- struct omap_vdd_info *vdd;
+ int ret;
if (!voltdm || IS_ERR(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return -EINVAL;
}
- vdd = voltdm->vdd;
-
- if (!vdd->volt_scale) {
+ if (!voltdm->scale) {
pr_err("%s: No voltage scale API registered for vdd_%s\n",
__func__, voltdm->name);
return -ENODATA;
}
- return vdd->volt_scale(voltdm, target_volt);
+ ret = voltdm->scale(voltdm, target_volt);
+ if (!ret)
+ voltdm->nominal_volt = target_volt;
+
+ return ret;
}
/**
- * omap_voltage_reset() - Resets the voltage of a particular voltage domain
- * to that of the current OPP.
- * @voltdm: pointer to the VDD whose voltage is to be reset.
+ * voltdm_reset() - Resets the voltage of a particular voltage domain
+ * to that of the current OPP.
+ * @voltdm: pointer to the voltage domain whose voltage is to be reset.
*
* This API finds out the correct voltage the voltage domain is supposed
* to be at and resets the voltage to that level. Should be used especially
* while disabling any voltage compensation modules.
*/
-void omap_voltage_reset(struct voltagedomain *voltdm)
+void voltdm_reset(struct voltagedomain *voltdm)
{
- unsigned long target_uvdc;
+ unsigned long target_volt;
if (!voltdm || IS_ERR(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return;
}
- target_uvdc = omap_voltage_get_nom_volt(voltdm);
- if (!target_uvdc) {
+ target_volt = voltdm_get_voltage(voltdm);
+ if (!target_volt) {
pr_err("%s: unable to find current voltage for vdd_%s\n",
__func__, voltdm->name);
return;
}
- omap_voltage_scale_vdd(voltdm, target_uvdc);
+ voltdm_scale(voltdm, target_volt);
}
/**
*
*/
void omap_voltage_get_volttable(struct voltagedomain *voltdm,
- struct omap_volt_data **volt_data)
+ struct omap_volt_data **volt_data)
{
- struct omap_vdd_info *vdd;
-
if (!voltdm || IS_ERR(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return;
}
- vdd = voltdm->vdd;
-
- *volt_data = vdd->volt_data;
+ *volt_data = voltdm->volt_data;
}
/**
* domain or if there is no matching entry.
*/
struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
- unsigned long volt)
+ unsigned long volt)
{
- struct omap_vdd_info *vdd;
int i;
if (!voltdm || IS_ERR(voltdm)) {
return ERR_PTR(-EINVAL);
}
- vdd = voltdm->vdd;
-
- if (!vdd->volt_data) {
+ if (!voltdm->volt_data) {
pr_warning("%s: voltage table does not exist for vdd_%s\n",
__func__, voltdm->name);
return ERR_PTR(-ENODATA);
}
- for (i = 0; vdd->volt_data[i].volt_nominal != 0; i++) {
- if (vdd->volt_data[i].volt_nominal == volt)
- return &vdd->volt_data[i];
+ for (i = 0; voltdm->volt_data[i].volt_nominal != 0; i++) {
+ if (voltdm->volt_data[i].volt_nominal == volt)
+ return &voltdm->volt_data[i];
}
pr_notice("%s: Unable to match the current voltage with the voltage"
* defined in voltage.h
*/
void omap_change_voltscale_method(struct voltagedomain *voltdm,
- int voltscale_method)
+ int voltscale_method)
{
- struct omap_vdd_info *vdd;
-
if (!voltdm || IS_ERR(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return;
}
- vdd = voltdm->vdd;
-
switch (voltscale_method) {
case VOLTSCALE_VPFORCEUPDATE:
- vdd->volt_scale = omap_vp_forceupdate_scale;
+ voltdm->scale = omap_vp_forceupdate_scale;
return;
case VOLTSCALE_VCBYPASS:
- vdd->volt_scale = omap_vc_bypass_scale;
+ voltdm->scale = omap_vc_bypass_scale;
return;
default:
pr_warning("%s: Trying to change the method of voltage scaling"
}
list_for_each_entry(voltdm, &voltdm_list, node) {
+ struct clk *sys_ck;
+
if (!voltdm->scalable)
continue;
+ sys_ck = clk_get(NULL, voltdm->sys_clk.name);
+ if (IS_ERR(sys_ck)) {
+ pr_warning("%s: Could not get sys clk.\n", __func__);
+ return -EINVAL;
+ }
+ voltdm->sys_clk.rate = clk_get_rate(sys_ck);
+ WARN_ON(!voltdm->sys_clk.rate);
+ clk_put(sys_ck);
+
if (voltdm->vc) {
- voltdm->vdd->volt_scale = omap_vc_bypass_scale;
+ voltdm->scale = omap_vc_bypass_scale;
omap_vc_init_channel(voltdm);
}
- if (voltdm->vdd) {
- if (omap_vdd_data_configure(voltdm))
- continue;
+ if (voltdm->vp) {
+ voltdm->scale = omap_vp_forceupdate_scale;
omap_vp_init(voltdm);
}
}