diff mbox

[PATCHv2,07/17] OMAP3: PM: Smartreflex class related changes for smartreflex.c

Message ID 1268903755-4151-8-git-send-email-thara@ti.com (mailing list archive)
State Superseded
Delegated to: Kevin Hilman
Headers show

Commit Message

Thara Gopinath March 18, 2010, 9:15 a.m. UTC
None
diff mbox

Patch

diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index c0345e7..76c749a 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -57,6 +57,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;
 
 static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
 {
@@ -428,12 +429,84 @@  static int sr_reset_voltage(int srid)
 	return 0;
 }
 
-static int sr_enable(struct omap_sr *sr, unsigned long volt)
+static void sr_start_vddautocomp(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_vddautocomp(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, unsigned long volt)
 {
 	u32 nvalue_reciprocal, v;
 	struct omap_sr_volt_data volt_data;
+	struct omap_sr *sr = _sr_lookup(srid);
 	char vsel;
 
+	if (!sr) {
+		pr_warning("omap_sr struct corresponding to SR%d not found\n",
+								srid);
+		return false;
+	}
+
 	if (!sr_match_volt(sr, volt, &volt_data))
 		return false;
 	nvalue_reciprocal = volt_data.sr_nvalue;
@@ -495,10 +568,24 @@  static int sr_enable(struct omap_sr *sr, unsigned long volt)
 	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;
 
+	if (!sr) {
+		pr_warning("omap_sr struct corresponding to SR%d not found\n",
+								srid);
+		return;
+	}
+
 	sr->is_sr_reset = 1;
 
 	/* SRCONFIG - disable SR */
@@ -536,8 +623,17 @@  static void sr_disable(struct omap_sr *sr)
 	}
 }
 
-
-void sr_start_vddautocomp(int srid, unsigned long volt)
+/**
+ * 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)
 {
 	struct omap_sr *sr = _sr_lookup(srid);
 
@@ -547,51 +643,8 @@  void sr_start_vddautocomp(int srid, unsigned long volt)
 		return;
 	}
 
-	if (sr->is_sr_reset == 1) {
-		sr_clk_enable(sr);
-		sr_configure(sr);
-	}
-
-	sr->is_autocomp_active = 1;
-	if (!sr_enable(sr, volt)) {
-		sr->is_autocomp_active = 0;
-		if (sr->is_sr_reset == 1)
-			sr_clk_disable(sr);
-	}
-}
-EXPORT_SYMBOL(sr_start_vddautocomp);
-
-int sr_stop_vddautocomp(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_vddautocomp);
-
-void omap_smartreflex_enable(int srid)
-{
-	unsigned long curr_volt = 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;
 	}
 
@@ -599,28 +652,24 @@  void omap_smartreflex_enable(int srid)
 		if (sr->is_sr_reset == 1) {
 			/* Enable SR clks */
 			sr_clk_enable(sr);
-
-			if (srid == SR1)
-				curr_volt = get_curr_vdd1_voltage();
-			else if (srid == SR2)
-				curr_volt = get_curr_vdd2_voltage();
-
-			if (!curr_volt) {
-				pr_info("Current voltage unknown \
-						 Cannot configure SR\n");
-			}
-
 			sr_configure(sr);
-
-			if (!sr_enable(sr, curr_volt))
+			if (!sr_class->enable(srid))
 				sr_clk_disable(sr);
 		}
 	}
 }
 
+/**
+ * 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);
 
 	if (!sr) {
@@ -629,53 +678,43 @@  void omap_smartreflex_disable(int 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)
@@ -747,13 +786,10 @@  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_vddautocomp(SR1, volt);
+			sr_start_vddautocomp(SR1);
 		else if (vdd == VDD2_OPP)
-			sr_start_vddautocomp(SR2, volt);
+			sr_start_vddautocomp(SR2);
 	}
 
 	return 0;
@@ -783,17 +819,10 @@  static int omap_sr_autocomp_store(void *data, u64 val)
 							sr_info->srid);
 		return 0;
 	}
-	if (val == 0) {
+	if (val == 0)
 		sr_stop_vddautocomp(sr_info->srid);
-	} else {
-		unsigned long curr_volt;
-
-		if (sr_info->srid == SR1)
-			curr_volt = get_curr_vdd1_voltage();
-		else
-			curr_volt = get_curr_vdd2_voltage();
-		sr_start_vddautocomp(sr_info->srid, curr_volt);
-	}
+	else
+		sr_start_vddautocomp(sr_info->srid);
 	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 365a21d..50ea4a8 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -241,13 +241,28 @@  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 take 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_sr_volt_data - Smartreflex voltage specific data
  *
  * @voltage	: The possible voltage value
@@ -286,11 +301,26 @@  struct omap_smartreflex_data {
 	int (*device_idle)(struct platform_device *pdev);
 };
 
+/*
+ * 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, unsigned long volt);
+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_vddautocomp(int srid, unsigned long volt);
-int sr_stop_vddautocomp(int srid);
 #else
 static inline void enable_smartreflex(int srid) {}
 static inline void disable_smartreflex(int srid) {}