arm: tegra: API for cluster switching
Nitin Agrawal [Wed, 21 Nov 2012 05:23:23 +0000 (10:23 +0530)]
API for doing cluster switching so that we can do cluster
switching within the kernel from another process explictly.

Bug 1058804

Reviewed-on: http://git-master/r/141961
(cherry picked from commit 96e05643a4b1ea2c566ab5cf07642645f4f935bb)

Signed-off-by: Nitin Agrawal <nitina@nvidia.com>
Change-Id: Ic4821fbd507327d7c951ab74ae7b1febc6f5bbe6
Reviewed-on: http://git-master/r/161869
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Bob Johnston <bjohnston@nvidia.com>
Reviewed-by: Sumeet Gupta <sumeetg@nvidia.com>
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Nagaraj Kolur <nkolur@nvidia.com>
Reviewed-by: Bo Yan <byan@nvidia.com>

arch/arm/mach-tegra/pm-t3.c
arch/arm/mach-tegra/pm.h

index 7222b76..b6773f4 100644 (file)
@@ -484,6 +484,60 @@ int tegra_cluster_control(unsigned int us, unsigned int flags)
 
        return 0;
 }
+
+int tegra_switch_to_lp_cluster()
+{
+       struct clk *cpu_clk = tegra_get_clock_by_name("cpu");
+       struct clk *cpu_lp_clk = tegra_get_clock_by_name("cpu_lp");
+       int rate = clk_get_rate(cpu_clk);
+       int e;
+
+       if (is_lp_cluster())
+               return 0;
+
+       /* Change the Clock Rate to desired LP CPU's clock rate */
+
+       if (rate > cpu_lp_clk->max_rate) {
+               e = clk_set_rate(cpu_clk, cpu_lp_clk->max_rate);
+               if (e) {
+                       pr_err("cluster_swtich: Failed to set clock %d", e);
+                       return e;
+               }
+       }
+
+       e = clk_set_parent(cpu_clk, cpu_lp_clk);
+       if (e) {
+               pr_err("cluster switching request failed (%d)\n", e);
+               return e;
+       }
+       return e;
+}
+
+int tegra_switch_to_g_cluster()
+{
+       struct clk *cpu_clk = tegra_get_clock_by_name("cpu");
+       struct clk *cpu_g_clk = tegra_get_clock_by_name("cpu_g");
+       int e;
+
+       if (!is_lp_cluster())
+               return 0;
+
+       e = clk_set_parent(cpu_clk, cpu_g_clk);
+       if (e) {
+               pr_err("cluster switching request failed (%d)\n", e);
+               return e;
+       }
+
+       /* Switch back to G Cluster Cpu Max Clock rate */
+
+       e = clk_set_rate(cpu_clk, cpu_g_clk->max_rate);
+       if (e) {
+               pr_err("cluster_swtich: Failed to increase the clock %d\n", e);
+               return e;
+       }
+       return e;
+}
+
 #endif
 
 #ifdef CONFIG_PM_SLEEP
index aebe205..b2c7bf8 100644 (file)
@@ -155,6 +155,8 @@ static inline unsigned int is_lp_cluster(void)
 int tegra_cluster_control(unsigned int us, unsigned int flags);
 void tegra_cluster_switch_prolog(unsigned int flags);
 void tegra_cluster_switch_epilog(unsigned int flags);
+int tegra_switch_to_g_cluster(void);
+int tegra_switch_to_lp_cluster(void);
 #else
 #define INSTRUMENT_CLUSTER_SWITCH 0    /* Must be zero for ARCH_TEGRA_2x_SOC */
 #define DEBUG_CLUSTER_SWITCH 0         /* Must be zero for ARCH_TEGRA_2x_SOC */
@@ -168,6 +170,14 @@ static inline int tegra_cluster_control(unsigned int us, unsigned int flags)
 }
 static inline void tegra_cluster_switch_prolog(unsigned int flags) {}
 static inline void tegra_cluster_switch_epilog(unsigned int flags) {}
+static inline int tegra_switch_to_g_cluster(void)
+{
+       return -EPERM;
+}
+static inline int tegra_switch_to_lp_cluster(void)
+{
+       return -EPERM;
+}
 #endif
 
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
@@ -260,4 +270,5 @@ extern struct clk *debug_uart_clk;
 void tegra_console_uart_suspend(void);
 void tegra_console_uart_resume(void);
 
+
 #endif /* _MACH_TEGRA_PM_H_ */