ARM:tegra:emc: scale latency allowance by tick len
Ray Poudrier [Tue, 21 Aug 2012 19:23:51 +0000 (12:23 -0700)]
Calculate the tick length of the EMC DFS table
and scale the latency allowance settings.

Bug 955082

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

arch/arm/mach-tegra/common-t3.c
arch/arm/mach-tegra/tegra3_emc.c
arch/arm/mach-tegra/tegra3_emc.h

index 2da656f..7618872 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Tegra 3 SoC-specific initialization (memory controller, etc.)
  *
- * Copyright (c) 2010-2012, NVIDIA Corporation.
+ * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -44,6 +44,8 @@
        ((MC_EMEM_ARB_TIMING_W2R - MC_EMEM_ARB_CFG) / 4 + 1)
 #define MC_TIMING_REG_NUM2 \
        ((MC_EMEM_ARB_MISC1 - MC_EMEM_ARB_DA_TURNS) / 4 + 1)
+#define MC_TIMING_REG_NUM3 \
+       ((MC_LATENCY_ALLOWANCE_VI_2 - MC_LATENCY_ALLOWANCE_AFI) / 4 + 1)
 
 struct mc_client {
        const char *name;
@@ -59,7 +61,8 @@ static void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE);
 
 
 #ifdef CONFIG_PM_SLEEP
-static u32 mc_boot_timing[MC_TIMING_REG_NUM1 + MC_TIMING_REG_NUM2 + 4];
+static u32 mc_boot_timing[MC_TIMING_REG_NUM1 + MC_TIMING_REG_NUM2
+                               + MC_TIMING_REG_NUM3 + 4];
 
 static void tegra_mc_timing_save(void)
 {
@@ -76,6 +79,10 @@ static void tegra_mc_timing_save(void)
        *ctx++ = readl((u32)mc + MC_EMEM_ARB_OVERRIDE);
        *ctx++ = readl((u32)mc + MC_RESERVED_RSV);
 
+       for (off = MC_LATENCY_ALLOWANCE_AFI; off <= MC_LATENCY_ALLOWANCE_VI_2;
+               off += 4)
+               *ctx++ = readl((u32)mc + off);
+
        *ctx++ = readl((u32)mc + MC_INT_MASK);
 }
 
@@ -94,6 +101,10 @@ void tegra_mc_timing_restore(void)
        __raw_writel(*ctx++, (u32)mc + MC_EMEM_ARB_OVERRIDE);
        __raw_writel(*ctx++, (u32)mc + MC_RESERVED_RSV);
 
+       for (off = MC_LATENCY_ALLOWANCE_AFI; off <= MC_LATENCY_ALLOWANCE_VI_2;
+               off += 4)
+               __raw_writel(*ctx++, (u32)mc + off);
+
        writel(*ctx++, (u32)mc + MC_INT_MASK);
        off = readl((u32)mc + MC_INT_MASK);
 
index 57a673b..4c06bf9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/arm/mach-tegra/tegra3_emc.c
  *
- * Copyright (C) 2012 NVIDIA Corporation
+ * Copyright (C) 2011-2012, NVIDIA CORPORATION. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -33,6 +33,7 @@
 #include <asm/cacheflush.h>
 
 #include <mach/iomap.h>
+#include <mach/latency_allowance.h>
 
 #include "clock.h"
 #include "dvfs.h"
@@ -1018,6 +1019,31 @@ static struct notifier_block tegra_emc_resume_nb = {
        .priority = -1,
 };
 
+static int tegra_emc_get_table_ns_per_tick(unsigned int emc_rate,
+                                       unsigned int table_tick_len)
+{
+       unsigned int ns_per_tick = 0;
+       unsigned int mc_period_10ns = 0;
+       unsigned int reg;
+
+       reg = mc_readl(MC_EMEM_ARB_MISC0) & MC_EMEM_ARB_MISC0_EMC_SAME_FREQ;
+
+       mc_period_10ns = ((reg ? (NSEC_PER_MSEC * 10) : (20 * NSEC_PER_MSEC)) /
+                       (emc_rate));
+       ns_per_tick = ((table_tick_len & MC_EMEM_ARB_CFG_CYCLE_MASK)
+               * mc_period_10ns) / (10 *
+               (1 + ((table_tick_len & MC_EMEM_ARB_CFG_EXTRA_TICK_MASK)
+               >> MC_EMEM_ARB_CFG_EXTRA_TICK_SHIFT)));
+
+       /* round new_ns_per_tick to 30/60 */
+       if (ns_per_tick < 45)
+               ns_per_tick = 30;
+       else
+               ns_per_tick = 60;
+
+       return ns_per_tick;
+}
+
 void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
 {
        int i, mv;
@@ -1025,6 +1051,8 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
        bool max_entry = false;
        unsigned long boot_rate, max_rate;
        struct clk *cbus = tegra_get_clock_by_name("cbus");
+       unsigned int ns_per_tick = 0;
+       unsigned int cur_ns_per_tick = 0;
 
        emc_stats.clkchange_count = 0;
        spin_lock_init(&emc_stats.spinlock);
@@ -1085,6 +1113,19 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
 
                if (table_rate == max_rate)
                        max_entry = true;
+
+               cur_ns_per_tick = tegra_emc_get_table_ns_per_tick(table_rate,
+                               table[i].burst_regs[MC_EMEM_ARB_CFG_INDEX]);
+
+               if (ns_per_tick == 0) {
+                       ns_per_tick = cur_ns_per_tick;
+               } else if (ns_per_tick != cur_ns_per_tick) {
+                       pr_err("tegra: invalid EMC DFS table: "
+                               "mismatched DFS tick lengths "
+                               "within table!\n");
+                       ns_per_tick = 0;
+                       return;
+               }
        }
 
        /* Validate EMC rate and voltage limits */
@@ -1094,6 +1135,8 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
                return;
        }
 
+       tegra_latency_allowance_update_tick_length(ns_per_tick);
+
        tegra_emc_table = table;
 
        adjust_emc_dvfs_table(tegra_emc_table, tegra_emc_table_size);
index 29b4556..43ef636 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/arm/mach-tegra/tegra3_emc.h
  *
- * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
+ * Copyright (C) 2011-2012, NVIDIA CORPORATION. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -267,6 +267,10 @@ enum {
 
 #define MC_EMEM_ADR_CFG                                0x54
 #define MC_EMEM_ARB_CFG                                0x90
+#define MC_EMEM_ARB_CFG_CYCLE_MASK             0x1ff
+#define MC_EMEM_ARB_CFG_EXTRA_TICK_SHIFT       16
+#define MC_EMEM_ARB_CFG_EXTRA_TICK_MASK                \
+       (0x1f << MC_EMEM_ARB_CFG_EXTRA_TICK_SHIFT)
 #define MC_EMEM_ARB_OUTSTANDING_REQ            0x94
 #define MC_EMEM_ARB_OUTSTANDING_REQ_MAX_SHIFT  0
 #define MC_EMEM_ARB_OUTSTANDING_REQ_MAX_MASK   \
@@ -295,6 +299,43 @@ enum {
 #define MC_EMEM_ARB_OVERRIDE                   0xe8
 #define MC_EMEM_ARB_OVERRIDE_EACK_MASK         (0x3 << 0)
 #define MC_TIMING_CONTROL                      0xfc
+#define MC_LATENCY_ALLOWANCE_AFI               0x2e0
+#define MC_LATENCY_ALLOWANCE_AVPC              0x2e4
+#define MC_LATENCY_ALLOWANCE_DC_0              0x2e8
+#define MC_LATENCY_ALLOWANCE_DC_1              0x2ec
+#define MC_LATENCY_ALLOWANCE_DC_2              0x2f0
+#define MC_LATENCY_ALLOWANCE_DCB_0             0x2f4
+#define MC_LATENCY_ALLOWANCE_DCB_1             0x2f8
+#define MC_LATENCY_ALLOWANCE_DCB_2             0x2fc
+#define MC_LATENCY_ALLOWANCE_EPP_0             0x300
+#define MC_LATENCY_ALLOWANCE_EPP_1             0x304
+#define MC_LATENCY_ALLOWANCE_G2_0              0x308
+#define MC_LATENCY_ALLOWANCE_G2_1              0x30c
+#define MC_LATENCY_ALLOWANCE_HC_0              0x310
+#define MC_LATENCY_ALLOWANCE_HC_1              0x314
+#define MC_LATENCY_ALLOWANCE_HDA               0x318
+#define MC_LATENCY_ALLOWANCE_ISP               0x31c
+#define MC_LATENCY_ALLOWANCE_MPCORE            0x320
+#define MC_LATENCY_ALLOWANCE_MPCORELP          0x324
+#define MC_LATENCY_ALLOWANCE_MPE_0             0x328
+#define MC_LATENCY_ALLOWANCE_MPE_1             0x32c
+#define MC_LATENCY_ALLOWANCE_MPE_2             0x330
+#define MC_LATENCY_ALLOWANCE_NV_0              0x334
+#define MC_LATENCY_ALLOWANCE_NV_1              0x338
+#define MC_LATENCY_ALLOWANCE_NV2_0             0x33c
+#define MC_LATENCY_ALLOWANCE_NV2_1             0x340
+#define MC_LATENCY_ALLOWANCE_PPCS_0            0x344
+#define MC_LATENCY_ALLOWANCE_PPCS_1            0x348
+#define MC_LATENCY_ALLOWANCE_PTC               0x34c
+#define MC_LATENCY_ALLOWANCE_SATA              0x350
+#define MC_LATENCY_ALLOWANCE_VDE_0             0x354
+#define MC_LATENCY_ALLOWANCE_VDE_1             0x358
+#define MC_LATENCY_ALLOWANCE_VDE_2             0x35c
+#define MC_LATENCY_ALLOWANCE_VDE_3             0x360
+#define MC_LATENCY_ALLOWANCE_VI_0              0x364
+#define MC_LATENCY_ALLOWANCE_VI_1              0x368
+#define MC_LATENCY_ALLOWANCE_VI_2              0x36c
+
 #define MC_RESERVED_RSV                                0x3fc
 
 #endif