@@ -48,7 +48,6 @@ struct omap_sr {
int srid;
int is_sr_reset;
int is_autocomp_active;
- struct clk *vdd_opp_clk;
u32 clk_length;
unsigned int irq;
struct platform_device *pdev;
@@ -119,64 +118,65 @@ static void sr_clk_disable(struct omap_sr *sr)
sr->is_sr_reset = 1;
}
-static u8 get_vdd1_opp(void)
+static unsigned long get_curr_vdd1_voltage(void)
{
struct omap_opp *opp;
unsigned long freq;
- struct omap_sr *sr_info = _sr_lookup(SR1);
+ struct clk *dpll1_clk;
- if (!sr_info) {
- pr_warning("omap_sr struct corresponding to SR1 not found\n");
- return 0;
- }
-
- if (sr_info->vdd_opp_clk == NULL || IS_ERR(sr_info->vdd_opp_clk))
+ dpll1_clk = clk_get(NULL, "dpll1_ck");
+ if (IS_ERR(dpll1_clk))
return 0;
- freq = sr_info->vdd_opp_clk->rate;
- opp = opp_find_freq_ceil(OPP_MPU, &freq);
+ freq = dpll1_clk->rate;;
+ opp = opp_find_freq_exact(OPP_MPU, freq, 1);
if (IS_ERR(opp))
return 0;
- /*
- * Use higher freq voltage even if an exact match is not available
- * we are probably masking a clock framework bug, so warn
- */
- if (unlikely(freq != sr_info->vdd_opp_clk->rate))
- pr_warning("%s: Available freq %ld != dpll freq %ld.\n",
- __func__, freq, sr_info->vdd_opp_clk->rate);
- return opp_get_opp_id(opp);
+ return opp_get_voltage(opp);
}
-static u8 get_vdd2_opp(void)
+static unsigned long get_curr_vdd2_voltage(void)
{
struct omap_opp *opp;
unsigned long freq;
- struct omap_sr *sr_info = _sr_lookup(SR2);
+ struct clk *l3_clk;
- if (!sr_info) {
- pr_warning("omap_sr struct corresponding to SR2 not found\n");
- return 0;
- }
-
- if (sr_info->vdd_opp_clk == NULL || IS_ERR(sr_info->vdd_opp_clk))
+ l3_clk = clk_get(NULL, "l3_ick");
+ if (IS_ERR(l3_clk))
return 0;
- freq = sr_info->vdd_opp_clk->rate;
- opp = opp_find_freq_ceil(OPP_L3, &freq);
+ freq = l3_clk->rate;
+ opp = opp_find_freq_exact(OPP_L3, freq, 1);
if (IS_ERR(opp))
return 0;
- /*
- * Use higher freq voltage even if an exact match is not available
- * we are probably masking a clock framework bug, so warn
- */
- if (unlikely(freq != sr_info->vdd_opp_clk->rate))
- pr_warning("%s: Available freq %ld != dpll freq %ld.\n",
- __func__, freq, sr_info->vdd_opp_clk->rate);
- return opp_get_opp_id(opp);
+ return opp_get_voltage(opp);
}
+static int sr_match_volt(struct omap_sr *sr, unsigned long volt,
+ struct omap_volt_data *volt_data)
+{
+ struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
+ struct omap_device *odev = to_omap_device(sr->pdev);
+ struct omap_smartreflex_dev_data *sr_dev_data =
+ odev->hwmods[0]->dev_attr;
+ int i;
+
+ if (!pdata->sr_volt_data) {
+ pr_notice("voltage table does not exist for SR %d\n", sr->srid);
+ return false;
+ }
+ for (i = 0; i < sr_dev_data->volts_supported; i++) {
+ if (pdata->sr_volt_data[i].voltage == volt) {
+ *volt_data = pdata->sr_volt_data[i];
+ return true;
+ }
+ }
+ pr_notice("Unable to match the current voltage with \
+ the voltage table for SR %d\n", sr->srid);
+ return false;
+}
static void sr_set_clk_length(struct omap_sr *sr)
{
@@ -211,21 +211,14 @@ static void sr_set_clk_length(struct omap_sr *sr)
static void sr_configure_vp(int srid)
{
- u32 vpconfig;
- u32 vsel;
- int uvdc;
- u32 target_opp_no;
- struct omap_opp *opp;
+ u32 vpconfig, vsel;
+ unsigned long uvdc;
if (srid == SR1) {
- target_opp_no = get_vdd1_opp();
- if (!target_opp_no)
- target_opp_no = VDD1_OPP3;
-
- opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
- BUG_ON(!opp); /* XXX ugh */
-
- uvdc = opp_get_voltage(opp);
+ uvdc = get_curr_vdd1_voltage();
+ if (!uvdc)
+ pr_err("Something wrong.Current voltage not obtained \
+ from OPP framework for SR %d!\n", srid);
vsel = omap_twl_uv_to_vsel(uvdc);
vpconfig = PRM_VP1_CONFIG_ERROROFFSET |
@@ -267,14 +260,10 @@ static void sr_configure_vp(int srid)
OMAP3_PRM_VP1_CONFIG_OFFSET);
} else if (srid == SR2) {
- target_opp_no = get_vdd2_opp();
- if (!target_opp_no)
- target_opp_no = VDD2_OPP3;
-
- opp = opp_find_by_opp_id(OPP_L3, target_opp_no);
- BUG_ON(!opp); /* XXX ugh */
-
- uvdc = opp_get_voltage(opp);
+ uvdc = get_curr_vdd2_voltage();
+ if (!uvdc)
+ pr_err("Something wrong.Current voltage not obtained \
+ from OPP framework for SR %d!\n", srid);
vsel = omap_twl_uv_to_vsel(uvdc);
vpconfig = PRM_VP2_CONFIG_ERROROFFSET |
@@ -368,9 +357,8 @@ static void sr_configure(struct omap_sr *sr)
static int sr_reset_voltage(int srid)
{
- struct omap_opp *opp;
unsigned long uvdc;
- u32 target_opp_no, vsel = 0;
+ u32 vsel = 0;
u32 reg_addr = 0;
u32 loop_cnt = 0, retries_cnt = 0;
u32 vc_bypass_value;
@@ -379,17 +367,12 @@ static int sr_reset_voltage(int srid)
u32 prm_vp1_voltage, prm_vp2_voltage;
if (srid == SR1) {
- target_opp_no = get_vdd1_opp();
- if (!target_opp_no) {
- pr_info("Current OPP unknown: Cannot reset voltage\n");
+ uvdc = get_curr_vdd1_voltage();
+ if (!uvdc) {
+ pr_err("Something wrong.Current voltage not obtained \
+ from OPP framework for SR %d!\n", srid);
return 1;
}
-
- opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
- if (!opp)
- return 1;
-
- uvdc = opp_get_voltage(opp);
vsel = omap_twl_uv_to_vsel(uvdc);
reg_addr = R_VDD1_SR_CONTROL;
@@ -397,17 +380,12 @@ static int sr_reset_voltage(int srid)
OMAP3_PRM_VP1_VOLTAGE_OFFSET);
t2_smps_steps = abs(vsel - prm_vp1_voltage);
} else if (srid == SR2) {
- target_opp_no = get_vdd2_opp();
- if (!target_opp_no) {
- pr_info("Current OPP unknown: Cannot reset voltage\n");
+ uvdc = get_curr_vdd2_voltage();
+ if (!uvdc) {
+ pr_err("Something wrong.Current voltage not obtained \
+ from OPP framework for SR %d!\n", srid);
return 1;
}
-
- opp = opp_find_by_opp_id(OPP_L3, target_opp_no);
- if (!opp)
- return 1;
-
- uvdc = opp_get_voltage(opp);
vsel = omap_twl_uv_to_vsel(uvdc);
reg_addr = R_VDD2_SR_CONTROL;
@@ -452,35 +430,20 @@ static int sr_reset_voltage(int srid)
return 0;
}
-static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
+static int sr_enable(struct omap_sr *sr, unsigned long volt)
{
u32 nvalue_reciprocal, v;
- struct omap_opp *opp;
- struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
- int uvdc;
+ struct omap_volt_data volt_data;
char vsel;
- if (sr->srid == SR1) {
- opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
- if (!opp)
- return false;
- } else {
- opp = opp_find_by_opp_id(OPP_L3, target_opp_no);
- if (!opp)
- return false;
- }
-
- if (!pdata->sr_nvalue) {
- pr_notice("N target values does not exist for SR%d\n",
- sr->srid);
+ if (!sr_match_volt(sr, volt, &volt_data))
return false;
- }
- nvalue_reciprocal = pdata->sr_nvalue[target_opp_no - 1];
+ nvalue_reciprocal = volt_data.sr_nvalue;
if (nvalue_reciprocal == 0) {
- pr_notice("OPP%d doesn't support SmartReflex\n",
- target_opp_no);
+ pr_notice("NVALUE = 0 at voltage %ld for Smartreflex %d\n",
+ volt, sr->srid);
return false;
}
@@ -491,8 +454,7 @@ static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
(ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST),
(ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST));
- uvdc = opp_get_voltage(opp);
- vsel = omap_twl_uv_to_vsel(uvdc);
+ vsel = omap_twl_uv_to_vsel(volt);
if (sr->srid == SR1) {
/* set/latch init voltage */
@@ -578,7 +540,7 @@ static void sr_disable(struct omap_sr *sr)
}
-void sr_start_vddautocomap(int srid, u32 target_opp_no)
+void sr_start_vddautocomap(int srid, unsigned long volt)
{
struct omap_sr *sr = _sr_lookup(srid);
@@ -594,7 +556,7 @@ void sr_start_vddautocomap(int srid, u32 target_opp_no)
}
sr->is_autocomp_active = 1;
- if (!sr_enable(sr, target_opp_no)) {
+ if (!sr_enable(sr, volt)) {
sr->is_autocomp_active = 0;
if (sr->is_sr_reset == 1)
sr_clk_disable(sr);
@@ -627,7 +589,7 @@ EXPORT_SYMBOL(sr_stop_vddautocomap);
void enable_smartreflex(int srid)
{
- u32 target_opp_no = 0;
+ unsigned long curr_volt = 0;
struct omap_sr *sr = _sr_lookup(srid);
if (!sr) {
@@ -642,18 +604,18 @@ void enable_smartreflex(int srid)
sr_clk_enable(sr);
if (srid == SR1)
- target_opp_no = get_vdd1_opp();
+ curr_volt = get_curr_vdd1_voltage();
else if (srid == SR2)
- target_opp_no = get_vdd2_opp();
+ curr_volt = get_curr_vdd2_voltage();
- if (!target_opp_no) {
- pr_info("Current OPP unknown \
+ if (!curr_volt) {
+ pr_info("Current voltage unknown \
Cannot configure SR\n");
}
sr_configure(sr);
- if (!sr_enable(sr, target_opp_no))
+ if (!sr_enable(sr, curr_volt))
sr_clk_disable(sr);
}
}
@@ -788,10 +750,13 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
udelay(t2_smps_delay);
if (sr_status) {
+ unsigned long volt;
+
+ volt = (target_vsel * 12500) + 600000;
if (vdd == VDD1_OPP)
- sr_start_vddautocomap(SR1, target_opp_no);
+ sr_start_vddautocomap(SR1, volt);
else if (vdd == VDD2_OPP)
- sr_start_vddautocomap(SR2, target_opp_no);
+ sr_start_vddautocomap(SR2, volt);
}
return 0;
@@ -824,13 +789,13 @@ static int omap_sr_autocomp_store(void *data, u64 val)
if (val == 0) {
sr_stop_vddautocomap(sr_info->srid);
} else {
- u32 current_opp;
+ unsigned long curr_volt;
if (sr_info->srid == SR1)
- current_opp = get_vdd1_opp();
+ curr_volt = get_curr_vdd1_voltage();
else
- current_opp = get_vdd2_opp();
- sr_start_vddautocomap(sr_info->srid, current_opp);
+ curr_volt = get_curr_vdd2_voltage();
+ sr_start_vddautocomap(sr_info->srid, curr_volt);
}
return 0;
}
@@ -856,12 +821,6 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
sr_info->irq = odev->hwmods[0]->mpu_irqs[0].irq;
sr_set_clk_length(sr_info);
- if (sr_info->srid == SR1) {
- sr_info->vdd_opp_clk = clk_get(NULL, "dpll1_ck");
- } else {
- sr_info->vdd_opp_clk = clk_get(NULL, "l3_ick");
- }
-
/* Create the debug fs enteries */
sprintf(name, "sr%d_autocomp", sr_info->srid);
(void) debugfs_create_file(name, S_IRUGO | S_IWUGO, pm_dbg_main_dir,
@@ -242,6 +242,17 @@ extern u32 current_vdd2_opp;
#endif
/**
+ * omap_volt_data - Omap voltage specific data.
+ *
+ * @voltage : The possible voltage value
+ * @sr_nvalue : Smartreflex N target value at voltage <voltage>
+ */
+struct omap_volt_data {
+ unsigned long voltage;
+ u32 sr_nvalue;
+};
+
+/**
* omap_smartreflex_dev_data - Smartreflex device specific data
*
* @volts_supported : Number of distinct voltages possible for the VDD
@@ -295,10 +306,10 @@ struct omap_smartreflex_dev_data {
* @device_idle : fn pointer to be pouplated with omap_device idle API
*/
struct omap_smartreflex_data {
- u32 senp_mod;
- u32 senn_mod;
- u32 *sr_nvalue;
- bool enable_on_init;
+ u32 senp_mod;
+ u32 senn_mod;
+ struct omap_volt_data *sr_volt_data;
+ bool enable_on_init;
int (*device_enable)(struct platform_device *pdev);
int (*device_shutdown)(struct platform_device *pdev);
int (*device_idle)(struct platform_device *pdev);
@@ -307,7 +318,7 @@ struct omap_smartreflex_data {
void enable_smartreflex(int srid);
void disable_smartreflex(int srid);
int sr_voltagescale_vcbypass(u32 t_opp, u32 c_opp, u8 t_vsel, u8 c_vsel);
-void sr_start_vddautocomap(int srid, u32 target_opp_no);
+void sr_start_vddautocomap(int srid, unsigned long volt);
int sr_stop_vddautocomap(int srid);
#else
static inline void enable_smartreflex(int srid) {}
@@ -51,8 +51,9 @@ static void __init sr_read_efuse(
!dev_data->efuse_nvalues_offs))
return;
- sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
- dev_data->volts_supported , GFP_KERNEL);
+ if (WARN_ON(!sr_data->sr_volt_data))
+ return;
+
sr_data->senn_mod = (omap_ctrl_readl(dev_data->efuse_sr_control) &
(0x3 << dev_data->sennenable_shift) >>
dev_data->sennenable_shift);
@@ -60,7 +61,7 @@ static void __init sr_read_efuse(
(0x3 << dev_data->senpenable_shift) >>
dev_data->senpenable_shift);
for (i = 0; i < dev_data->volts_supported; i++)
- sr_data->sr_nvalue[i] = omap_ctrl_readl(
+ sr_data->sr_volt_data[i].sr_nvalue = omap_ctrl_readl(
dev_data->efuse_nvalues_offs[i]);
}
@@ -78,12 +79,13 @@ static void __init sr_set_testing_nvalues(
!dev_data->test_nvalues))
return;
- sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
- dev_data->volts_supported , GFP_KERNEL);
+ if (WARN_ON(!sr_data->sr_volt_data))
+ return;
+
sr_data->senn_mod = dev_data->test_sennenable;
sr_data->senp_mod = dev_data->test_senpenable;
for (i = 0; i < dev_data->volts_supported; i++)
- sr_data->sr_nvalue[i] = dev_data->test_nvalues[i];
+ sr_data->sr_volt_data[i].sr_nvalue = dev_data->test_nvalues[i];
}
static void __init sr_set_nvalues(struct omap_smartreflex_dev_data *dev_data,
@@ -97,6 +99,28 @@ static void __init sr_set_nvalues(struct omap_smartreflex_dev_data *dev_data,
}
}
+static void __init omap34xx_sr_volt_details(struct omap_smartreflex_data
+ *sr_data, int srid,
+ int volt_count)
+{
+ sr_data->sr_volt_data = kzalloc(sizeof(sr_data->sr_volt_data) *
+ volt_count , GFP_KERNEL);
+ if (WARN_ON(!sr_data->sr_volt_data))
+ return;
+
+ if (srid == SR1) {
+ sr_data->sr_volt_data[0].voltage = 975000;
+ sr_data->sr_volt_data[1].voltage = 1075000;
+ sr_data->sr_volt_data[2].voltage = 1200000;
+ sr_data->sr_volt_data[3].voltage = 1270000;
+ sr_data->sr_volt_data[4].voltage = 1350000;
+ } else if (srid == SR2) {
+ sr_data->sr_volt_data[0].voltage = 975000;
+ sr_data->sr_volt_data[1].voltage = 1050000;
+ sr_data->sr_volt_data[2].voltage = 1150000;
+ }
+}
+
static int __init omap_devinit_smartreflex(void)
{
int i = 0;
@@ -124,6 +148,9 @@ static int __init omap_devinit_smartreflex(void)
sr_data->device_enable = omap_device_enable;
sr_data->device_shutdown = omap_device_shutdown;
sr_data->device_idle = omap_device_idle;
+ if (cpu_is_omap34xx())
+ omap34xx_sr_volt_details(sr_data, i + 1,
+ sr_dev_data->volts_supported);
sr_set_nvalues(sr_dev_data, sr_data);
od = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),