ARM: tegra: clock: Account for memory BW efficiency
Alex Frid [Sun, 18 Mar 2012 07:01:02 +0000 (00:01 -0700)]
Account for memory efficiency when processing requests from Tegra3
EMC shared bandwidth users. Do not round requests from these users
until they are aggregated.

The respective debugfs node: /d/tegra_emc/efficiency (in %).

Bug 952739

Signed-off-by: Alex Frid <afrid@nvidia.com>
(cherry picked from commit 86929087f68c4366d6179101eb9a6a6473a4f084)

Change-Id: I4acdd89f44de1401ce5dad8fc4936932df014458
Reviewed-on: http://git-master/r/103499
Reviewed-by: Automatic_Commit_Validation_User
Tested-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Jihoon Bang <jbang@nvidia.com>
Reviewed-by: Jon Mayo <jmayo@nvidia.com>
GVS: Gerrit_Virtual_Submit

arch/arm/mach-tegra/tegra3_clocks.c
arch/arm/mach-tegra/tegra3_emc.c
arch/arm/mach-tegra/tegra3_emc.h

index acb386a..2dfdb1d 100644 (file)
@@ -3011,7 +3011,8 @@ static int tegra3_clk_shared_bus_update(struct clk *bus)
                    (c->u.shared_bus_user.mode == SHARED_CEILING)) {
                        switch (c->u.shared_bus_user.mode) {
                        case SHARED_BW:
-                               bw += c->u.shared_bus_user.rate;
+                               if (bw < bus->max_rate)
+                                       bw += c->u.shared_bus_user.rate;
                                break;
                        case SHARED_CEILING:
                                ceiling = min(c->u.shared_bus_user.rate,
@@ -3024,6 +3025,16 @@ static int tegra3_clk_shared_bus_update(struct clk *bus)
                        }
                }
        }
+
+       if (bw) {
+               if (bus->flags & PERIPH_EMC_ENB) {
+                       bw = tegra_emc_bw_efficiency ?
+                               (bw / tegra_emc_bw_efficiency) : bus->max_rate;
+                       bw = (bw < bus->max_rate / 100) ?
+                               (bw * 100) : bus->max_rate;
+               }
+               bw = clk_round_rate_locked(bus, bw);
+       }
        rate = min(max(rate, bw), ceiling);
 
        old_rate = clk_get_rate_locked(bus);
@@ -3072,6 +3083,10 @@ static long tegra_clk_shared_bus_round_rate(struct clk *c, unsigned long rate)
        if (c->u.shared_bus_user.mode == SHARED_AUTO)
                rate = 0;
 
+       /* BW users should not be rounded until aggregated */
+       if (c->u.shared_bus_user.mode == SHARED_BW)
+               return rate;
+
        return clk_round_rate(c->parent, rate);
 }
 
index 83136e3..2b19848 100644 (file)
@@ -45,6 +45,8 @@ static bool emc_enable;
 #endif
 module_param(emc_enable, bool, 0644);
 
+u8 tegra_emc_bw_efficiency = 35;
+
 #define EMC_MIN_RATE_DDR3              25500000
 #define EMC_STATUS_UPDATE_TIMEOUT      100
 #define TEGRA_EMC_TABLE_MAX_SIZE       16
@@ -1267,6 +1269,22 @@ static int eack_state_set(void *data, u64 val)
 DEFINE_SIMPLE_ATTRIBUTE(eack_state_fops, eack_state_get,
                        eack_state_set, "%llu\n");
 
+static int efficiency_get(void *data, u64 *val)
+{
+       *val = tegra_emc_bw_efficiency;
+       return 0;
+}
+static int efficiency_set(void *data, u64 val)
+{
+       tegra_emc_bw_efficiency = (val > 100) ? 100 : val;
+       if (emc)
+               tegra_clk_shared_bus_update(emc);
+
+       return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(efficiency_fops, efficiency_get,
+                       efficiency_set, "%llu\n");
+
 static int __init tegra_emc_debug_init(void)
 {
        if (!tegra_emc_table)
@@ -1292,6 +1310,10 @@ static int __init tegra_emc_debug_init(void)
                "eack_state", S_IRUGO | S_IWUGO, emc_debugfs_root, NULL, &eack_state_fops))
                goto err_out;
 
+       if (!debugfs_create_file("efficiency", S_IRUGO | S_IWUSR,
+                                emc_debugfs_root, NULL, &efficiency_fops))
+               goto err_out;
+
        return 0;
 
 err_out:
index 03bde19..185d777 100644 (file)
@@ -27,6 +27,8 @@
 #define TEGRA_EMC_BRIDGE_RATE_MIN      300000000
 #define TEGRA_EMC_BRIDGE_MVOLTS_MIN    1200
 
+extern u8 tegra_emc_bw_efficiency;
+
 struct tegra_emc_table {
        u8 rev;
        unsigned long rate;