@@ -430,9 +430,9 @@ void omap_sram_idle(void)
* Only needed if we are going to enter retention or off.
*/
if (mpu_next_state <= PWRDM_POWER_RET)
- disable_smartreflex(SR1);
+ omap_smartreflex_disable(SR1);
if (core_next_state <= PWRDM_POWER_RET)
- disable_smartreflex(SR2);
+ omap_smartreflex_disable(SR2);
/* CORE */
if (core_next_state < PWRDM_POWER_ON) {
@@ -531,9 +531,9 @@ void omap_sram_idle(void)
* retention or off
*/
if (mpu_next_state <= PWRDM_POWER_RET)
- enable_smartreflex(SR1);
+ omap_smartreflex_enable(SR1);
if (core_next_state <= PWRDM_POWER_RET)
- enable_smartreflex(SR2);
+ omap_smartreflex_enable(SR2);
/* PER */
if (per_next_state < PWRDM_POWER_ON) {
@@ -55,6 +55,7 @@ struct omap_sr {
/* sr_list contains all the instances of smartreflex module */
static LIST_HEAD(sr_list);
+static struct omap_smartreflex_class_data *sr_class;
#define SR_REGADDR(offs) (sr->srbase_addr + offset)
@@ -388,14 +389,86 @@ static int sr_reset_voltage(int srid)
return 0;
}
-static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
+static void sr_start_vddautocomap(int srid)
+{
+ struct omap_sr *sr = _sr_lookup(srid);
+
+ if (!sr) {
+ pr_warning("omap_sr struct corresponding to SR%d not found\n",
+ srid);
+ return;
+ }
+
+ if (!sr_class || !(sr_class->enable)) {
+ pr_warning("smartreflex class driver not registered\n");
+ return;
+ }
+
+ if (sr->is_sr_reset == 1) {
+ sr_clk_enable(sr);
+ sr_configure(sr);
+ }
+
+ sr->is_autocomp_active = 1;
+ if (!sr_class->enable(srid)) {
+ sr->is_autocomp_active = 0;
+ if (sr->is_sr_reset == 1)
+ sr_clk_disable(sr);
+ }
+}
+
+static void sr_stop_vddautocomap(int srid)
+{
+ struct omap_sr *sr = _sr_lookup(srid);
+
+ if (!sr) {
+ pr_warning("omap_sr struct corresponding to SR%d not found\n",
+ srid);
+ return;
+ }
+ if (!sr_class || !(sr_class->disable)) {
+ pr_warning("smartreflex class driver not registered\n");
+ return;
+ }
+
+ if (sr->is_autocomp_active == 1) {
+ sr_class->disable(srid);
+ sr_clk_disable(sr);
+ sr->is_autocomp_active = 0;
+ /* Reset the volatage for current OPP */
+ sr_reset_voltage(srid);
+ }
+
+}
+
+/* Public Functions */
+
+/**
+ * sr_enable : Enables the smartreflex module.
+ * @srid - The id of the sr module to be enabled.
+ * @target_opp_no - The OPP at which the Voltage domain associated with
+ * the smartreflex module is operating at. This is required only to program
+ * the correct Ntarget value.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * enable a smartreflex module. Returns true on success.Returns false if the
+ * target opp id passed is wrong or if ntarget value is wrong.
+ */
+int sr_enable(int srid, u32 target_opp_no)
{
u32 nvalue_reciprocal, v;
+ struct omap_sr *sr = _sr_lookup(srid);
struct omap_opp *opp;
struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
int uvdc;
char vsel;
+ if (!sr) {
+ pr_warning("omap_sr struct corresponding to SR%d not found\n",
+ srid);
+ return false;
+ }
+
if (sr->srid == SR1) {
opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
if (!opp)
@@ -477,8 +550,16 @@ static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
return true;
}
-static void sr_disable(struct omap_sr *sr)
+/**
+ * sr_disable : Disables the smartreflex module.
+ * @srid - The id of the sr module to be disabled.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * disable a smartreflex module.
+ */
+void sr_disable(int srid)
{
+ struct omap_sr *sr = _sr_lookup(srid);
u32 i = 0;
sr->is_sr_reset = 1;
@@ -518,9 +599,19 @@ static void sr_disable(struct omap_sr *sr)
}
}
-
-void sr_start_vddautocomap(int srid, u32 target_opp_no)
+/**
+ * omap_smartreflex_enable : API to enable SR clocks and to call into the
+ * registered smartreflex class enable API.
+ * @srid - The id of the sr module to be enabled.
+ *
+ * This API is to be called from the kernel in order to enable
+ * a particular smartreflex module. This API will do the initial
+ * configurations to turn on the smartreflex module and in turn call
+ * into the registered smartreflex class enable API.
+ */
+void omap_smartreflex_enable(int srid)
{
+ u32 target_opp_no = 0;
struct omap_sr *sr = _sr_lookup(srid);
if (!sr) {
@@ -528,52 +619,8 @@ void sr_start_vddautocomap(int srid, u32 target_opp_no)
srid);
return;
}
-
- if (sr->is_sr_reset == 1) {
- sr_clk_enable(sr);
- sr_configure(sr);
- }
-
- sr->is_autocomp_active = 1;
- if (!sr_enable(sr, target_opp_no)) {
- sr->is_autocomp_active = 0;
- if (sr->is_sr_reset == 1)
- sr_clk_disable(sr);
- }
-}
-EXPORT_SYMBOL(sr_start_vddautocomap);
-
-int sr_stop_vddautocomap(int srid)
-{
- struct omap_sr *sr = _sr_lookup(srid);
-
- if (!sr) {
- pr_warning("omap_sr struct corresponding to SR%d not found\n",
- srid);
- return false;
- }
-
- if (sr->is_autocomp_active == 1) {
- sr_disable(sr);
- sr_clk_disable(sr);
- sr->is_autocomp_active = 0;
- /* Reset the volatage for current OPP */
- sr_reset_voltage(srid);
- return true;
- } else
- return false;
-
-}
-EXPORT_SYMBOL(sr_stop_vddautocomap);
-
-void enable_smartreflex(int srid)
-{
- u32 target_opp_no = 0;
- struct omap_sr *sr = _sr_lookup(srid);
-
- if (!sr) {
- pr_warning("omap_sr struct corresponding to SR%d not found\n",
- srid);
+ if (!sr_class || !(sr_class->enable)) {
+ pr_warning("smartreflex class driver not registered\n");
return;
}
@@ -581,26 +628,24 @@ void enable_smartreflex(int srid)
if (sr->is_sr_reset == 1) {
/* Enable SR clks */
sr_clk_enable(sr);
-
- if (srid == SR1)
- target_opp_no = get_vdd1_opp();
- else if (srid == SR2)
- target_opp_no = get_vdd2_opp();
-
- if (!target_opp_no) {
- pr_info("Current OPP unknown \
- Cannot configure SR\n");
- }
-
sr_configure(sr);
- if (!sr_enable(sr, target_opp_no))
+ if (!sr_class->enable(srid))
sr_clk_disable(sr);
}
}
}
-void disable_smartreflex(int srid)
+/**
+ * omap_smartreflex_disable : API to disable SR clocks and to call into the
+ * registered smartreflex class disable API.
+ * @srid - The id of the sr module to be disabled.
+ *
+ * This API is to be called from the kernel in order to disable
+ * a particular smartreflex module. This API will in turn call
+ * into the registered smartreflex class disable API.
+ */
+void omap_smartreflex_disable(int srid)
{
u32 i = 0;
struct omap_sr *sr = _sr_lookup(srid);
@@ -610,54 +655,43 @@ void disable_smartreflex(int srid)
srid);
return;
}
+ if (!sr_class || !(sr_class->disable)) {
+ pr_warning("smartreflex class driver not registered\n");
+ return;
+ }
if (sr->is_autocomp_active == 1) {
if (sr->is_sr_reset == 0) {
-
- sr->is_sr_reset = 1;
- /* SRCONFIG - disable SR */
- sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE,
- ~SRCONFIG_SRENABLE);
-
+ sr_class->disable(srid);
/* Disable SR clk */
sr_clk_disable(sr);
- if (sr->srid == SR1) {
- /* Wait for VP idle before disabling VP */
- while ((!prm_read_mod_reg(OMAP3430_GR_MOD,
- OMAP3_PRM_VP1_STATUS_OFFSET))
- && i++ < MAX_TRIES)
- udelay(1);
-
- if (i >= MAX_TRIES)
- pr_warning("VP1 not idle, still going \
- ahead with VP1 disable\n");
-
- /* Disable VP1 */
- prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE,
- OMAP3430_GR_MOD,
- OMAP3_PRM_VP1_CONFIG_OFFSET);
- } else if (sr->srid == SR2) {
- /* Wait for VP idle before disabling VP */
- while ((!prm_read_mod_reg(OMAP3430_GR_MOD,
- OMAP3_PRM_VP2_STATUS_OFFSET))
- && i++ < MAX_TRIES)
- udelay(1);
-
- if (i >= MAX_TRIES)
- pr_warning("VP2 not idle, still going \
- ahead with VP2 disable\n");
-
- /* Disable VP2 */
- prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE,
- OMAP3430_GR_MOD,
- OMAP3_PRM_VP2_CONFIG_OFFSET);
- }
/* Reset the volatage for current OPP */
sr_reset_voltage(srid);
}
}
}
+/**
+ * omap_sr_register_class : API to register a smartreflex class parameters.
+ * @class_data - The structure containing various sr class specific data.
+ *
+ * This API is to be called by the smartreflex class driver to register itself
+ * with the smartreflex driver during init.
+ */
+void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
+{
+ if (!class_data) {
+ pr_warning("Smartreflex class data passed is NULL\n");
+ return;
+ }
+
+ if (sr_class) {
+ pr_warning("Smartreflex class driver already registered\n");
+ return;
+ }
+ sr_class = class_data;
+}
+
/* Voltage Scaling using SR VCBYPASS */
int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
u8 target_vsel, u8 current_vsel)
@@ -730,9 +764,9 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
if (sr_status) {
if (vdd == VDD1_OPP)
- sr_start_vddautocomap(SR1, target_opp_no);
+ sr_start_vddautocomap(SR1);
else if (vdd == VDD2_OPP)
- sr_start_vddautocomap(SR2, target_opp_no);
+ sr_start_vddautocomap(SR2);
}
return 0;
@@ -762,17 +796,10 @@ static int omap_sr_autocomp_store(void *data, u64 val)
sr_info->srid);
return 0;
}
- if (val == 0) {
+ if (val == 0)
sr_stop_vddautocomap(sr_info->srid);
- } else {
- u32 current_opp;
-
- if (sr_info->srid == SR1)
- current_opp = get_vdd1_opp();
- else
- current_opp = get_vdd2_opp();
- sr_start_vddautocomap(sr_info->srid, current_opp);
- }
+ else
+ sr_start_vddautocomap(sr_info->srid);
return 0;
}
@@ -243,12 +243,27 @@ extern u32 current_vdd2_opp;
#define SR_TESTING_NVALUES 0
#endif
-/*
- * Smartreflex module enable/disable interface.
- * NOTE: if smartreflex is not enabled from sysfs, these functions will not
- * do anything.
- */
#ifdef CONFIG_OMAP_SMARTREFLEX
+/**
+ * omap_smartreflex_class_data : Structure to be populated by
+ * Smartreflex class driver with corresponding class enable disable API's
+ *
+ * @enable - API to enable a particular class smaartreflex.
+ * @disable - API to disable a particular class smartreflex.
+ * @notify - API to notify the class driver about an event in SR. Not needed
+ * for class3.
+ * @notify_flags - specify the events to be notified to the class driver
+ * @class_type - specify which smartreflex class. Can be used by the SR driver
+ * to tkae any class based decisions.
+ */
+struct omap_smartreflex_class_data {
+ int (*enable)(int sr_id);
+ int (*disable)(int sr_id);
+ int (*notify)(int sr_id, u32 status);
+ u8 notify_flags;
+ u8 class_type;
+};
+
/*
* omap_smartreflex_data - Smartreflex platform data
*
@@ -274,11 +289,26 @@ struct omap_smartreflex_data {
int (*device_idle)(struct platform_device *pdev);
};
-void enable_smartreflex(int srid);
-void disable_smartreflex(int srid);
+/*
+ * Smartreflex module enable/disable interface.
+ * NOTE: if smartreflex is not enabled from sysfs, these functions will not
+ * do anything.
+ */
+void omap_smartreflex_enable(int srid);
+void omap_smartreflex_disable(int srid);
+
+/**
+ * Smartreflex driver hooks to be called from Smartreflex class driver
+ */
+int sr_enable(int srid, u32 target_opp_no);
+void sr_disable(int srid);
+
+/**
+ * API to register the smartreflex class driver with the smartreflex driver
+ */
+void omap_sr_register_class(struct omap_smartreflex_class_data *class_data);
+
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);
-int sr_stop_vddautocomap(int srid);
#else
static inline void enable_smartreflex(int srid) {}
static inline void disable_smartreflex(int srid) {}