ARM: tegra: la: add function to scale LA
Ray Poudrier [Tue, 21 Aug 2012 22:09:09 +0000 (15:09 -0700)]
Add functionality to enable changing of latency
allowance settings. This is used for memory
tables that may have different tick lengths.

Bug 955082

Change-Id: I3055a062846cfdeb992931e691cf687ffb05725c
Signed-off-by: Ray Poudrier <rapoudrier@nvidia.com>
Reviewed-on: http://git-master/r/124979
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Krishna Reddy <vdumpa@nvidia.com>

Rebase-Id: R243cded2f4afaf90b1efa39e1014cad80637fe25

arch/arm/mach-tegra/include/mach/latency_allowance.h
arch/arm/mach-tegra/latency_allowance.c
arch/arm/mach-tegra/tegra3_la_priv.h

index 047bf0a..3f4764b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/arm/mach-tegra/include/mach/latency_allowance.h
  *
- * Copyright (C) 2011-2012 NVIDIA Corporation.
+ * Copyright (C) 2011-2012, NVIDIA CORPORATION. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -106,6 +106,12 @@ static inline int tegra_enable_latency_scaling(enum tegra_la_id id,
 static inline void tegra_disable_latency_scaling(enum tegra_la_id id)
 {
 }
+
+static inline void tegra_latency_allowance_update_tick_length(
+                                               unsigned int new_ns_per_tick)
+{
+       return;
+}
 #else
 int tegra_set_latency_allowance(enum tegra_la_id id,
                                unsigned int bandwidth_in_mbps);
@@ -116,6 +122,7 @@ int tegra_enable_latency_scaling(enum tegra_la_id id,
                                    unsigned int threshold_high);
 
 void tegra_disable_latency_scaling(enum tegra_la_id id);
+void tegra_latency_allowance_update_tick_length(unsigned int new_ns_per_tick);
 #endif
 
 #endif /* _MACH_TEGRA_LATENCY_ALLOWANCE_H_ */
index 4b1860c..6d7a753 100644 (file)
@@ -258,6 +258,37 @@ void tegra_disable_latency_scaling(enum tegra_la_id id)
        spin_unlock(&safety_lock);
 }
 
+void tegra_latency_allowance_update_tick_length(unsigned int new_ns_per_tick)
+{
+       int i = 0;
+       int la;
+       unsigned long reg_read;
+       unsigned long reg_write;
+       unsigned long scale_factor = new_ns_per_tick / ns_per_tick;
+
+       if (scale_factor > 1) {
+               spin_lock(&safety_lock);
+               ns_per_tick = new_ns_per_tick;
+               for (i = 0; i < ARRAY_SIZE(la_info_array) - 1; i++) {
+                       reg_read = readl(la_info_array[i].reg_addr);
+                       la = ((reg_read & la_info_array[i].mask) >>
+                               la_info_array[i].shift) / scale_factor;
+
+                       reg_write = (reg_read & ~la_info_array[i].mask) |
+                                       (la << la_info_array[i].shift);
+                       writel(reg_write, la_info_array[i].reg_addr);
+                       scaling_info[i].la_set = la;
+               }
+               spin_unlock(&safety_lock);
+
+               /* Re-scale G2PR, G2SR, G2DR, G2DW with updated ns_per_tick */
+               tegra_set_latency_allowance(TEGRA_LA_G2PR, 20);
+               tegra_set_latency_allowance(TEGRA_LA_G2SR, 20);
+               tegra_set_latency_allowance(TEGRA_LA_G2DR, 20);
+               tegra_set_latency_allowance(TEGRA_LA_G2DW, 20);
+       }
+}
+
 static int la_regs_show(struct seq_file *s, void *unused)
 {
        unsigned i;
index 7f3fa7c..2a39ea4 100644 (file)
@@ -218,7 +218,7 @@ struct la_scaling_reg_info vi_info[] = {
        }
 };
 
-static const int ns_per_tick = 30;
+static int ns_per_tick = 30;
 /* Tegra3 MC atom size in bytes */
 static const int normal_atom_size = 16;
 #endif