arm: tegra: la: refactor la code.
Krishna Reddy [Fri, 11 Jan 2013 01:07:47 +0000 (17:07 -0800)]
refactor it to detect soc at run and work.

Change-Id: I0677367384df8bf3378b3e09c26aaa9b70f2cb2f
Signed-off-by: Krishna Reddy <vdumpa@nvidia.com>
Reviewed-on: http://git-master/r/190449
Reviewed-by: Harshada Kale <hkale@nvidia.com>
Tested-by: Harshada Kale <hkale@nvidia.com>

arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/include/mach/latency_allowance.h
arch/arm/mach-tegra/la_priv.h [new file with mode: 0644]
arch/arm/mach-tegra/la_priv_common.h [deleted file]
arch/arm/mach-tegra/latency_allowance.c
arch/arm/mach-tegra/tegra11x_la.c [new file with mode: 0644]
arch/arm/mach-tegra/tegra11x_la_priv.h [deleted file]
arch/arm/mach-tegra/tegra14x_la.c [new file with mode: 0644]
arch/arm/mach-tegra/tegra14x_la_priv.h [deleted file]
arch/arm/mach-tegra/tegra3_la.c [new file with mode: 0644]
arch/arm/mach-tegra/tegra3_la_priv.h [deleted file]

index e2ed380..c051461 100644 (file)
@@ -83,7 +83,10 @@ obj-y                                   += dvfs.o
 obj-$(CONFIG_ARCH_TEGRA_11x_SOC)        += tegra11_dvfs.o
 obj-$(CONFIG_ARCH_TEGRA_14x_SOC)        += tegra14_dvfs.o
 ifeq ($(CONFIG_TEGRA_SILICON_PLATFORM),y)
-obj-$(CONFIG_TEGRA_LATENCY_ALLOWANCE)   += latency_allowance.o
+obj-y                                   += latency_allowance.o
+obj-y                                   += tegra3_la.o
+obj-y                                   += tegra11x_la.o
+obj-y                                   += tegra14x_la.o
 obj-$(CONFIG_TEGRA_EDP_LIMITS)          += edp.o
 obj-$(CONFIG_TEGRA_CORE_EDP_LIMITS)     += edp_core.o
 obj-$(CONFIG_ARCH_TEGRA_11x_SOC)        += tegra11_edp.o
index 74c2d8d..20b718b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/arm/mach-tegra/include/mach/latency_allowance.h
  *
- * Copyright (C) 2011-2012, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (C) 2011-2013, 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
@@ -113,44 +113,16 @@ enum tegra_la_id {
        TEGRA_LA_MAX_ID
 };
 
-#if !defined(CONFIG_TEGRA_LATENCY_ALLOWANCE)
-static inline int tegra_set_latency_allowance(enum tegra_la_id id,
-                                               unsigned int bandwidth_in_mbps)
-{
-       return 0;
-}
-
-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);
 
 void tegra_latency_allowance_update_tick_length(unsigned int new_ns_per_tick);
-#endif
-
-#if !defined(CONFIG_TEGRA_LATENCY_ALLOWANCE_SCALING)
-static inline int tegra_enable_latency_scaling(enum tegra_la_id id,
-                                               unsigned int threshold_low,
-                                               unsigned int threshold_mid,
-                                               unsigned int threshold_high)
-{
-       return 0;
-}
 
-static inline void tegra_disable_latency_scaling(enum tegra_la_id id)
-{
-}
-#else
 int tegra_enable_latency_scaling(enum tegra_la_id id,
                                    unsigned int threshold_low,
                                    unsigned int threshold_mid,
                                    unsigned int threshold_high);
 
 void tegra_disable_latency_scaling(enum tegra_la_id id);
-#endif
 
 #endif /* _MACH_TEGRA_LATENCY_ALLOWANCE_H_ */
diff --git a/arch/arm/mach-tegra/la_priv.h b/arch/arm/mach-tegra/la_priv.h
new file mode 100644 (file)
index 0000000..3a8efb6
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * arch/arm/mach-tegra/la_priv.h
+ *
+ * Copyright (C) 2012-2013, 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
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _MACH_TEGRA_LA_PRIV_H_
+#define _MACH_TEGRA_LA_PRIV_H_
+
+#define ENABLE_LA_DEBUG                0
+
+#define la_debug(fmt, ...) \
+do { \
+       if (ENABLE_LA_DEBUG) { \
+               printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__); \
+       } \
+} while (0)
+
+#define MASK(x) \
+       ((0xFFFFFFFFUL >> (31 - (1 ? x) + (0 ? x))) << (0 ? x))
+#define SHIFT(x) \
+       (0 ? x)
+#define ID(id) \
+       TEGRA_LA_##id
+
+#define VALIDATE_ID(id, p) \
+do { \
+       if (id >= TEGRA_LA_MAX_ID || (p)->id_to_index[(id)] == 0xFFFF) { \
+               WARN_ONCE(1, "%s: invalid Id=%d", __func__, (id)); \
+               return -EINVAL; \
+       } \
+       BUG_ON((p)->la_info_array[(p)->id_to_index[(id)]].id != (id)); \
+} while (0)
+
+#define VALIDATE_BW(bw_in_mbps) \
+do { \
+       if (bw_in_mbps >= 4096) \
+               return -EINVAL; \
+} while (0)
+
+#define VALIDATE_THRESHOLDS(tl, tm, th) \
+do { \
+       if ((tl) > 100 || (tm) > 100 || (th) > 100) \
+               return -EINVAL; \
+} while (0)
+
+struct la_client_info {
+       unsigned int fifo_size_in_atoms;
+       unsigned int expiration_in_ns;  /* worst case expiration value */
+       unsigned long reg_addr;
+       unsigned long mask;
+       unsigned long shift;
+       enum tegra_la_id id;
+       char *name;
+       bool scaling_supported;
+       unsigned int init_la;           /* initial la to set for client */
+};
+
+struct la_scaling_info {
+       unsigned int threshold_low;
+       unsigned int threshold_mid;
+       unsigned int threshold_high;
+       int scaling_ref_count;
+       int actual_la_to_set;
+       int la_set;
+};
+
+struct la_scaling_reg_info {
+       enum tegra_la_id id;
+       unsigned int tl_reg_addr;
+       unsigned int tl_mask;
+       unsigned int tl_shift;
+       unsigned int tm_reg_addr;
+       unsigned int tm_mask;
+       unsigned int tm_shift;
+       unsigned int th_reg_addr;
+       unsigned int th_mask;
+       unsigned int th_shift;
+};
+
+struct la_chip_specific {
+       int ns_per_tick;
+       int atom_size;
+       int la_max_value;
+       spinlock_t lock;
+       int la_info_array_size;
+       struct la_client_info *la_info_array;
+       unsigned short id_to_index[ID(MAX_ID) + 1];
+       unsigned int disp_bw_array[ID(DISPLAY_HCB) - ID(DISPLAY_0A) + 1];
+       struct la_scaling_info scaling_info[ID(MAX_ID)];
+       int la_scaling_enable_count;
+       struct dentry *latency_debug_dir;
+
+       void (*init_ptsa)(void);
+       void (*update_display_ptsa_rate)(unsigned int *disp_bw_array);
+       int (*set_la)(enum tegra_la_id id, unsigned int bw_mbps);
+       int (*enable_la_scaling)(enum tegra_la_id id,
+                               unsigned int threshold_low,
+                               unsigned int threshold_mid,
+                               unsigned int threshold_high);
+       void (*disable_la_scaling)(enum tegra_la_id id);
+};
+
+void tegra_la_get_t3_specific(struct la_chip_specific *cs);
+void tegra_la_get_t14x_specific(struct la_chip_specific *cs);
+void tegra_la_get_t11x_specific(struct la_chip_specific *cs);
+
+#endif /* _MACH_TEGRA_LA_PRIV_H_ */
diff --git a/arch/arm/mach-tegra/la_priv_common.h b/arch/arm/mach-tegra/la_priv_common.h
deleted file mode 100644 (file)
index eca361d..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * arch/arm/mach-tegra/la_priv_common.h
- *
- * Copyright (C) 2012 NVIDIA Corporation.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _MACH_TEGRA_LA_PRIV_H_
-#define _MACH_TEGRA_LA_PRIV_H_
-
-/* maximum valid value for latency allowance */
-#define MC_LA_MAX_VALUE                255
-
-#define MC_RA(r) \
-       ((u32)IO_ADDRESS(TEGRA_MC_BASE) + (MC_##r))
-#define RA(r) \
-       ((u32)IO_ADDRESS(TEGRA_MC_BASE) + (MC_LA_##r))
-
-#define MASK(x) \
-       ((0xFFFFFFFFUL >> (31 - (1 ? x) + (0 ? x))) << (0 ? x))
-#define SHIFT(x) \
-       (0 ? x)
-#define ID(id) \
-       TEGRA_LA_##id
-
-#define LA_INFO(f, e, a, r, i, ss, la) \
-{ \
-       .fifo_size_in_atoms = f, \
-       .expiration_in_ns = e, \
-       .reg_addr = RA(a), \
-       .mask = MASK(r), \
-       .shift = SHIFT(r), \
-       .id = ID(i), \
-       .name = __stringify(i), \
-       .scaling_supported = ss, \
-       .init_la = la, \
-}
-
-struct la_client_info {
-       unsigned int fifo_size_in_atoms;
-       unsigned int expiration_in_ns;  /* worst case expiration value */
-       unsigned long reg_addr;
-       unsigned long mask;
-       unsigned long shift;
-       enum tegra_la_id id;
-       char *name;
-       bool scaling_supported;
-       unsigned int init_la;           /* initial la to set for client */
-};
-
-struct la_scaling_info {
-       unsigned int threshold_low;
-       unsigned int threshold_mid;
-       unsigned int threshold_high;
-       int scaling_ref_count;
-       int actual_la_to_set;
-       int la_set;
-};
-
-struct la_scaling_reg_info {
-       enum tegra_la_id id;
-       unsigned int tl_reg_addr;
-       unsigned int tl_mask;
-       unsigned int tl_shift;
-       unsigned int tm_reg_addr;
-       unsigned int tm_mask;
-       unsigned int tm_shift;
-       unsigned int th_reg_addr;
-       unsigned int th_mask;
-       unsigned int th_shift;
-};
-
-#endif /* _MACH_TEGRA_LA_PRIV_H_ */
index e780da3..de4c62d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/arm/mach-tegra/latency_allowance.c
  *
- * Copyright (C) 2011-2012, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (C) 2011-2013, 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
 #include <asm/bug.h>
 #include <asm/io.h>
 #include <asm/string.h>
+#include <mach/hardware.h>
 #include <mach/iomap.h>
 #include <mach/io.h>
 #include <mach/clk.h>
 #include <mach/latency_allowance.h>
-#include "la_priv_common.h"
-#include "tegra3_la_priv.h"
-#include "tegra11x_la_priv.h"
-#include "tegra14x_la_priv.h"
+#include "la_priv.h"
 
-#define ENABLE_LA_DEBUG                0
 #define TEST_LA_CODE           0
 
-#define la_debug(fmt, ...) \
-       if (ENABLE_LA_DEBUG) { \
-               printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__); \
-       }
-
 /* Bug 995270 */
 #define HACK_LA_FIFO 1
+static int default_set_la(enum tegra_la_id id, unsigned int bw_mbps);
 
-#ifdef CONFIG_TEGRA_MC_PTSA
-
-static unsigned int get_ptsa_rate(unsigned int bw)
+static struct la_chip_specific cs;
+static void init_chip_specific(void)
 {
-       /* 16 = 2 channels * 2 ddr * 4 bytes */
-       unsigned int base_memory_bw = 16 * BASE_EMC_FREQ_MHZ;
-       unsigned int rate = 281 * bw / base_memory_bw;
-       if (rate > 255)
-               rate = 255;
-       return rate;
-}
+       enum tegra_chipid cid;
 
-static unsigned int disp_bw_array[10];
+       if (!tegra_platform_is_silicon())
+               return;
 
-static void update_display_ptsa_rate(void)
-{
-       unsigned int num_active = (disp_bw_array[0] != 0) +
-                                 (disp_bw_array[1] != 0) +
-                                 (disp_bw_array[2] != 0);
-       unsigned int num_activeb = (disp_bw_array[5] != 0) +
-                                  (disp_bw_array[6] != 0) +
-                                  (disp_bw_array[7] != 0);
-       unsigned int max_bw = disp_bw_array[0];
-       unsigned int max_bwb = disp_bw_array[5];
-       unsigned int rate_dis;
-       unsigned int rate_disb;
-       unsigned long ring1_rate;
-
-       max_bw = max(disp_bw_array[0], disp_bw_array[1]);
-       max_bw = max(max_bw, disp_bw_array[2]);
-
-       max_bwb = max(disp_bw_array[5], disp_bw_array[6]);
-       max_bwb = max(max_bwb, disp_bw_array[7]);
-
-       rate_dis = get_ptsa_rate(num_active * max_bw);
-       rate_disb = get_ptsa_rate(num_activeb * max_bwb);
-
-       writel(rate_dis, MC_RA(DIS_PTSA_RATE_0));
-       writel(rate_disb, MC_RA(DISB_PTSA_RATE_0));
-
-
-       ring1_rate = readl(MC_RA(DIS_PTSA_RATE_0)) +
-                    readl(MC_RA(DISB_PTSA_RATE_0)) +
-                    readl(MC_RA(VE_PTSA_RATE_0)) +
-                    readl(MC_RA(RING2_PTSA_RATE_0));
-       la_debug("max_bw=0x%x, max_bwb=0x%x, num_active=0x%x, num_activeb=0x%x,"
-               "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x ",
-               max_bw, max_bwb, num_active, num_activeb, disp_bw_array[0],disp_bw_array[1],
-               disp_bw_array[2],disp_bw_array[5],disp_bw_array[6],disp_bw_array[7]);
-       la_debug("dis=0x%x, disb=0x%x, ve=0x%x, rng2=0x%x, rng1=0x%lx",
-               readl(MC_RA(DIS_PTSA_RATE_0)), readl(MC_RA(DISB_PTSA_RATE_0)),
-               readl(MC_RA(VE_PTSA_RATE_0)), readl(MC_RA(RING2_PTSA_RATE_0)), ring1_rate);
-#if defined(CONFIG_TEGRA_ERRATA_977223)
-       ring1_rate /= 2;
-#endif
-       writel(ring1_rate, MC_RA(RING1_PTSA_RATE_0));
+       cs.set_la = default_set_la;
+       memset(&cs.id_to_index[0], 0xFF, sizeof(cs.id_to_index));
+       spin_lock_init(&cs.lock);
+
+       cid = tegra_get_chipid();
+
+       switch (cid) {
+       case TEGRA_CHIPID_TEGRA3:
+               tegra_la_get_t3_specific(&cs);
+               break;
+       case TEGRA_CHIPID_TEGRA11:
+               tegra_la_get_t11x_specific(&cs);
+               break;
+       default:
+               cs.set_la = NULL;
+       }
 }
 
-#endif
-
-static struct dentry *latency_debug_dir;
-static DEFINE_SPINLOCK(safety_lock);
-static unsigned short id_to_index[ID(MAX_ID) + 1];
-static struct la_scaling_info scaling_info[TEGRA_LA_MAX_ID];
-static int la_scaling_enable_count;
-
-#define VALIDATE_ID(id) \
-       do { \
-               if (id >= TEGRA_LA_MAX_ID || id_to_index[id] == 0xFFFF) { \
-                       WARN_ONCE(1, "%s: invalid Id=%d", __func__, id); \
-                       return -EINVAL; \
-               } \
-               BUG_ON(la_info_array[id_to_index[id]].id != id); \
-       } while (0)
-
-#define VALIDATE_BW(bw_in_mbps) \
-       do { \
-               if (bw_in_mbps >= 4096) \
-                       return -EINVAL; \
-       } while (0)
-
-#define VALIDATE_THRESHOLDS(tl, tm, th) \
-       do { \
-               if (tl > 100 || tm > 100 || th > 100) \
-                       return -EINVAL; \
-       } while (0)
-
-
 static void set_la(struct la_client_info *ci, int la)
 {
        unsigned long reg_read;
        unsigned long reg_write;
-       int idx = id_to_index[ci->id];
+       int idx = cs.id_to_index[ci->id];
 
-       spin_lock(&safety_lock);
+       spin_lock(&cs.lock);
        reg_read = readl(ci->reg_addr);
        reg_write = (reg_read & ~ci->mask) |
                        (la << ci->shift);
        writel(reg_write, ci->reg_addr);
-       scaling_info[idx].la_set = la;
+       cs.scaling_info[idx].la_set = la;
        la_debug("reg_addr=0x%x, read=0x%x, write=0x%x",
                (u32)ci->reg_addr, (u32)reg_read, (u32)reg_write);
-       spin_unlock(&safety_lock);
+       spin_unlock(&cs.lock);
 }
 
-/* Sets latency allowance based on clients memory bandwitdh requirement.
- * Bandwidth passed is in mega bytes per second.
- */
-int tegra_set_latency_allowance(enum tegra_la_id id,
-                               unsigned int bandwidth_in_mbps)
+static int default_set_la(enum tegra_la_id id, unsigned int bw_mbps)
 {
        int ideal_la;
        int la_to_set;
        unsigned int fifo_size_in_atoms;
-       int bytes_per_atom = normal_atom_size;
+       int bytes_per_atom = cs.atom_size;
        const int fifo_scale = 4;               /* 25% of the FIFO */
        struct la_client_info *ci;
-       int idx = id_to_index[id];
+       int idx = cs.id_to_index[id];
 
-       VALIDATE_ID(id);
-       VALIDATE_BW(bandwidth_in_mbps);
+       VALIDATE_ID(id, &cs);
+       VALIDATE_BW(bw_mbps);
 
-       ci = &la_info_array[idx];
+       ci = &cs.la_info_array[idx];
        fifo_size_in_atoms = ci->fifo_size_in_atoms;
 
 #ifdef CONFIG_TEGRA_MC_PTSA
        if (id >= TEGRA_LA_DISPLAY_0A && id <= TEGRA_LA_DISPLAY_HCB) {
-               disp_bw_array[id - TEGRA_LA_DISPLAY_0A] = bandwidth_in_mbps;
-               update_display_ptsa_rate();
+               cs.disp_bw_array[id - TEGRA_LA_DISPLAY_0A] = bw_mbps;
+               if (cs.update_display_ptsa_rate)
+                       cs.update_display_ptsa_rate(cs.disp_bw_array);
        }
 #endif
 #if HACK_LA_FIFO
@@ -185,81 +113,33 @@ int tegra_set_latency_allowance(enum tegra_la_id id,
                fifo_size_in_atoms /= fifo_scale;
 #endif
 
-       if (bandwidth_in_mbps == 0) {
-               la_to_set = MC_LA_MAX_VALUE;
+       if (bw_mbps == 0) {
+               la_to_set = cs.la_max_value;
        } else {
                ideal_la = (fifo_size_in_atoms * bytes_per_atom * 1000) /
-                          (bandwidth_in_mbps * ns_per_tick);
-               la_to_set = ideal_la - (ci->expiration_in_ns/ns_per_tick) - 1;
+                          (bw_mbps * cs.ns_per_tick);
+               la_to_set = ideal_la -
+                           (ci->expiration_in_ns / cs.ns_per_tick) - 1;
        }
 
        la_debug("\n%s:id=%d,idx=%d, bw=%dmbps, la_to_set=%d",
-               __func__, id, idx, bandwidth_in_mbps, la_to_set);
+               __func__, id, idx, bw_mbps, la_to_set);
        la_to_set = (la_to_set < 0) ? 0 : la_to_set;
-       scaling_info[idx].actual_la_to_set = la_to_set;
-       la_to_set = (la_to_set > MC_LA_MAX_VALUE) ? MC_LA_MAX_VALUE : la_to_set;
+       cs.scaling_info[idx].actual_la_to_set = la_to_set;
+       la_to_set = (la_to_set > cs.la_max_value) ? cs.la_max_value : la_to_set;
 
        set_la(ci, la_to_set);
        return 0;
 }
 
-#if defined(CONFIG_TEGRA_LATENCY_ALLOWANCE_SCALING)
-static void set_thresholds(struct la_scaling_reg_info *info,
-                           enum tegra_la_id id)
-{
-       unsigned long reg_read;
-       unsigned long reg_write;
-       unsigned int thresh_low;
-       unsigned int thresh_mid;
-       unsigned int thresh_high;
-       int la_set;
-       int idx = id_to_index[id];
-
-       reg_read = readl(la_info_array[idx].reg_addr);
-       la_set = (reg_read & la_info_array[idx].mask) >>
-                la_info_array[idx].shift;
-       /* la should be set before enabling scaling. */
-       BUG_ON(la_set != scaling_info[idx].la_set);
-
-       thresh_low = (scaling_info[idx].threshold_low * la_set) / 100;
-       thresh_mid = (scaling_info[idx].threshold_mid * la_set) / 100;
-       thresh_high = (scaling_info[idx].threshold_high * la_set) / 100;
-       la_debug("%s: la_set=%d, thresh_low=%d(%d%%), thresh_mid=%d(%d%%),"
-               " thresh_high=%d(%d%%) ", __func__, la_set,
-               thresh_low, scaling_info[idx].threshold_low,
-               thresh_mid, scaling_info[idx].threshold_mid,
-               thresh_high, scaling_info[idx].threshold_high);
-
-       reg_read = readl(info->tl_reg_addr);
-       reg_write = (reg_read & ~info->tl_mask) |
-               (thresh_low << info->tl_shift);
-       writel(reg_write, info->tl_reg_addr);
-       la_debug("reg_addr=0x%x, read=0x%x, write=0x%x",
-               (u32)info->tl_reg_addr, (u32)reg_read, (u32)reg_write);
-
-       reg_read = readl(info->tm_reg_addr);
-       reg_write = (reg_read & ~info->tm_mask) |
-               (thresh_mid << info->tm_shift);
-       writel(reg_write, info->tm_reg_addr);
-       la_debug("reg_addr=0x%x, read=0x%x, write=0x%x",
-               (u32)info->tm_reg_addr, (u32)reg_read, (u32)reg_write);
-
-       reg_read = readl(info->th_reg_addr);
-       reg_write = (reg_read & ~info->th_mask) |
-               (thresh_high << info->th_shift);
-       writel(reg_write, info->th_reg_addr);
-       la_debug("reg_addr=0x%x, read=0x%x, write=0x%x",
-               (u32)info->th_reg_addr, (u32)reg_read, (u32)reg_write);
-}
-
-static void set_disp_latency_thresholds(enum tegra_la_id id)
-{
-       set_thresholds(&disp_info[id - ID(DISPLAY_0A)], id);
-}
-
-static void set_vi_latency_thresholds(enum tegra_la_id id)
+/* Sets latency allowance based on clients memory bandwitdh requirement.
+ * Bandwidth passed is in mega bytes per second.
+ */
+int tegra_set_latency_allowance(enum tegra_la_id id, unsigned int bw_mbps)
 {
-       set_thresholds(&vi_info[id - ID(VI_WSB)], id);
+       if (cs.set_la)
+               return cs.set_la(id, bw_mbps);
+       return 0;
 }
 
 /* Thresholds for scaling are specified in % of fifo freeness.
@@ -276,66 +156,18 @@ int tegra_enable_latency_scaling(enum tegra_la_id id,
                                    unsigned int threshold_mid,
                                    unsigned int threshold_high)
 {
-       unsigned long reg;
-       void __iomem *scaling_enable_reg = (void __iomem *)(MC_RA(ARB_OVERRIDE));
-       int idx = id_to_index[id];
-
-       VALIDATE_ID(id);
-       VALIDATE_THRESHOLDS(threshold_low, threshold_mid, threshold_high);
-
-       if (la_info_array[idx].scaling_supported == false)
-               goto exit;
-
-       spin_lock(&safety_lock);
-
-       la_debug("\n%s: id=%d, tl=%d, tm=%d, th=%d", __func__,
-               id, threshold_low, threshold_mid, threshold_high);
-       scaling_info[idx].threshold_low = threshold_low;
-       scaling_info[idx].threshold_mid = threshold_mid;
-       scaling_info[idx].threshold_high = threshold_high;
-       scaling_info[idx].scaling_ref_count++;
-
-       if (id >= ID(DISPLAY_0A) && id <= ID(DISPLAY_1BB))
-               set_disp_latency_thresholds(id);
-       else if (id >= ID(VI_WSB) && id <= ID(VI_WY))
-               set_vi_latency_thresholds(id);
-       if (!la_scaling_enable_count++) {
-               reg = readl(scaling_enable_reg);
-               reg |= (1 << GLOBAL_LATENCY_SCALING_ENABLE_BIT);
-               writel(reg,  scaling_enable_reg);
-               la_debug("enabled scaling.");
-       }
-       spin_unlock(&safety_lock);
-exit:
+       if (cs.enable_la_scaling)
+               return cs.enable_la_scaling(id, threshold_low,
+                       threshold_mid, threshold_high);
        return 0;
 }
 
 void tegra_disable_latency_scaling(enum tegra_la_id id)
 {
-       unsigned long reg;
-       void __iomem *scaling_enable_reg = (void __iomem *)(MC_RA(ARB_OVERRIDE));
-       int idx;
-
-       BUG_ON(id >= TEGRA_LA_MAX_ID);
-       idx = id_to_index[id];
-       BUG_ON(la_info_array[idx].id != id);
-
-       if (la_info_array[idx].scaling_supported == false)
-               return;
-       spin_lock(&safety_lock);
-       la_debug("\n%s: id=%d", __func__, id);
-       scaling_info[idx].scaling_ref_count--;
-       BUG_ON(scaling_info[idx].scaling_ref_count < 0);
-
-       if (!--la_scaling_enable_count) {
-               reg = readl(scaling_enable_reg);
-               reg = reg & ~(1 << GLOBAL_LATENCY_SCALING_ENABLE_BIT);
-               writel(reg, scaling_enable_reg);
-               la_debug("disabled scaling.");
+       if (cs.disable_la_scaling) {
+               cs.disable_la_scaling(id);
        }
-       spin_unlock(&safety_lock);
 }
-#endif
 
 void tegra_latency_allowance_update_tick_length(unsigned int new_ns_per_tick)
 {
@@ -343,22 +175,22 @@ void tegra_latency_allowance_update_tick_length(unsigned int new_ns_per_tick)
        int la;
        unsigned long reg_read;
        unsigned long reg_write;
-       unsigned long scale_factor = new_ns_per_tick / ns_per_tick;
+       unsigned long scale_factor = new_ns_per_tick / cs.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_lock(&cs.lock);
+               cs.ns_per_tick = new_ns_per_tick;
+               for (i = 0; i < cs.la_info_array_size - 1; i++) {
+                       reg_read = readl(cs.la_info_array[i].reg_addr);
+                       la = ((reg_read & cs.la_info_array[i].mask) >>
+                               cs.la_info_array[i].shift) / scale_factor;
+
+                       reg_write = (reg_read & ~cs.la_info_array[i].mask) |
+                                       (la << cs.la_info_array[i].shift);
+                       writel(reg_write, cs.la_info_array[i].reg_addr);
+                       cs.scaling_info[i].la_set = la;
                }
-               spin_unlock(&safety_lock);
+               spin_unlock(&cs.lock);
 
 #if defined(CONFIG_ARCH_TEGRA_3x_SOC)
                /* Re-scale G2PR, G2SR, G2DR, G2DW with updated ns_per_tick */
@@ -372,14 +204,14 @@ void tegra_latency_allowance_update_tick_length(unsigned int new_ns_per_tick)
 
 static int la_regs_show(struct seq_file *s, void *unused)
 {
-       unsigned i;
+       int i;
        unsigned long la;
 
        /* iterate the list, but don't print MAX_ID */
-       for (i = 0; i < ARRAY_SIZE(la_info_array) - 1; i++) {
-               la = (readl(la_info_array[i].reg_addr) & la_info_array[i].mask)
-                       >> la_info_array[i].shift;
-               seq_printf(s, "%-16s: %4lu\n", la_info_array[i].name, la);
+       for (i = 0; i < cs.la_info_array_size - 1; i++) {
+               la = (readl(cs.la_info_array[i].reg_addr) &
+                       cs.la_info_array[i].mask) >> cs.la_info_array[i].shift;
+               seq_printf(s, "%-16s: %4lu\n", cs.la_info_array[i].name, la);
        }
 
        return 0;
@@ -399,12 +231,12 @@ static const struct file_operations regs_fops = {
 
 static int __init tegra_latency_allowance_debugfs_init(void)
 {
-       if (latency_debug_dir)
+       if (cs.latency_debug_dir)
                return 0;
 
-       latency_debug_dir = debugfs_create_dir("tegra_latency", NULL);
+       cs.latency_debug_dir = debugfs_create_dir("tegra_latency", NULL);
 
-       debugfs_create_file("la_info", S_IRUGO, latency_debug_dir, NULL,
+       debugfs_create_file("la_info", S_IRUGO, cs.latency_debug_dir, NULL,
                &regs_fops);
 
        return 0;
@@ -415,21 +247,16 @@ late_initcall(tegra_latency_allowance_debugfs_init);
 static int __init tegra_latency_allowance_init(void)
 {
        unsigned int i;
-       struct clk *emc_clk __attribute__((unused));
-       unsigned long emc_freq __attribute__((unused));
-       unsigned long same_freq __attribute__((unused));
-       unsigned long grant_dec __attribute__((unused));
-       unsigned long ring1_rate __attribute__((unused));
 
-       la_scaling_enable_count = 0;
-       memset(&id_to_index[0], 0xFF, sizeof(id_to_index));
+       init_chip_specific();
 
-       for (i = 0; i < ARRAY_SIZE(la_info_array); i++)
-               id_to_index[la_info_array[i].id] = i;
+       for (i = 0; i < cs.la_info_array_size; i++)
+               cs.id_to_index[cs.la_info_array[i].id] = i;
 
-       for (i = 0; i < ARRAY_SIZE(la_info_array); i++) {
-               if (la_info_array[i].init_la)
-                       set_la(&la_info_array[i], la_info_array[i].init_la);
+       for (i = 0; i < cs.la_info_array_size; i++) {
+               if (cs.la_info_array[i].init_la)
+                       set_la(&cs.la_info_array[i],
+                               cs.la_info_array[i].init_la);
        }
 #if defined(CONFIG_ARCH_TEGRA_3x_SOC)
        tegra_set_latency_allowance(TEGRA_LA_G2PR, 20);
@@ -438,65 +265,8 @@ static int __init tegra_latency_allowance_init(void)
        tegra_set_latency_allowance(TEGRA_LA_G2DW, 20);
 #endif
 
-#ifdef CONFIG_TEGRA_MC_PTSA
-       emc_clk = clk_get(NULL, "emc");
-       la_debug("**** emc clk_rate=%luMHz", clk_get_rate(emc_clk)/1000000);
-
-       emc_freq = clk_get_rate(emc_clk);
-       emc_freq /= 1000000;
-       /* Compute initial value for grant dec */
-       same_freq = readl(MC_RA(EMEM_ARB_MISC0_0));
-       same_freq = same_freq >> 27 & 1;
-       grant_dec = 256 * (same_freq ? 2 : 1) * emc_freq;
-       if (grant_dec > 511)
-               grant_dec = 511;
-       writel(grant_dec, MC_RA(PTSA_GRANT_DECREMENT_0));
-
-       writel(0x3d, MC_RA(DIS_PTSA_MIN_0));
-       writel(0x14, MC_RA(DIS_PTSA_MAX_0));
-
-       writel(0x3d, MC_RA(DISB_PTSA_MIN_0));
-       writel(0x14, MC_RA(DISB_PTSA_MAX_0));
-
-       writel(get_ptsa_rate(MAX_CAMERA_BW_MHZ), MC_RA(VE_PTSA_RATE_0));
-       writel(0x3d, MC_RA(VE_PTSA_MIN_0));
-       writel(0x14, MC_RA(VE_PTSA_MAX_0));
-
-       writel(0x01, MC_RA(RING2_PTSA_RATE_0));
-       writel(0x3f, MC_RA(RING2_PTSA_MIN_0));
-       writel(0x05, MC_RA(RING2_PTSA_MAX_0));
-
-       writel(38 * emc_freq / BASE_EMC_FREQ_MHZ,
-               MC_RA(MLL_MPCORER_PTSA_RATE_0));
-       writel(0x3f, MC_RA(MLL_MPCORER_PTSA_MIN_0));
-       writel(0x05, MC_RA(MLL_MPCORER_PTSA_MAX_0));
-
-       writel(0x01, MC_RA(SMMU_SMMU_PTSA_RATE_0));
-       writel(0x01, MC_RA(SMMU_SMMU_PTSA_MIN_0));
-       writel(0x01, MC_RA(SMMU_SMMU_PTSA_MAX_0));
-
-       writel(0x00, MC_RA(R0_DIS_PTSA_RATE_0));
-       writel(0x3f, MC_RA(R0_DIS_PTSA_MIN_0));
-       writel(0x3f, MC_RA(R0_DIS_PTSA_MAX_0));
-
-       writel(0x00, MC_RA(R0_DISB_PTSA_RATE_0));
-       writel(0x3f, MC_RA(R0_DISB_PTSA_MIN_0));
-       writel(0x3f, MC_RA(R0_DISB_PTSA_MAX_0));
-
-       ring1_rate = readl(MC_RA(DIS_PTSA_RATE_0)) +
-                    readl(MC_RA(DISB_PTSA_RATE_0)) +
-                    readl(MC_RA(VE_PTSA_RATE_0)) +
-                    readl(MC_RA(RING2_PTSA_RATE_0));
-#if defined(CONFIG_TEGRA_ERRATA_977223)
-       ring1_rate /= 2;
-#endif
-       writel(ring1_rate, MC_RA(RING1_PTSA_RATE_0));
-       writel(0x36, MC_RA(RING1_PTSA_MIN_0));
-       writel(0x1f, MC_RA(RING1_PTSA_MAX_0));
-
-       writel(0x00, MC_RA(DIS_EXTRA_SNAP_LEVELS_0));
-       writel(0x03, MC_RA(HEG_EXTRA_SNAP_LEVELS_0));
-#endif
+       if (cs.init_ptsa)
+               cs.init_ptsa();
        return 0;
 }
 
@@ -513,7 +283,7 @@ static int __init test_la(void)
 
 #if PRINT_ID_IDX_MAPPING
        for (i = 0; i < ID(MAX_ID); i++)
-               pr_info("ID=0x%x, Idx=0x%x", i, id_to_index[i]);
+               pr_info("ID=0x%x, Idx=0x%x", i, cs.id_to_index[i]);
 #endif
 
        do {
@@ -536,7 +306,7 @@ static int __init test_la(void)
                }
 
                la_debug("la_scaling_enable_count =%d",
-                       la_scaling_enable_count);
+                       cs.la_scaling_enable_count);
                for (id = 0; id < TEGRA_LA_MAX_ID; id++) {
                        if (id >= ID(DISPLAY_0AB) && id <= ID(DISPLAY_HCB))
                                continue;
@@ -545,7 +315,7 @@ static int __init test_la(void)
                        tegra_disable_latency_scaling(id);
                }
                la_debug("la_scaling_enable_count=%d",
-                       la_scaling_enable_count);
+                       cs.la_scaling_enable_count);
        } while (--repeat_count);
        return 0;
 }
diff --git a/arch/arm/mach-tegra/tegra11x_la.c b/arch/arm/mach-tegra/tegra11x_la.c
new file mode 100644 (file)
index 0000000..f330bc7
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * arch/arm/mach-tegra/tegra11x_la.c
+ *
+ * Copyright (C) 2012-2013, 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
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/stringify.h>
+#include <linux/clk.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/iomap.h>
+#include <mach/io.h>
+#include <mach/clk.h>
+#include <mach/latency_allowance.h>
+#include "la_priv.h"
+
+#define T11X_MC_LA_AVPC_ARM7_0         0x2e4
+#define T11X_MC_LA_DC_0                        0x2e8
+#define T11X_MC_LA_DC_1                        0x2ec
+#define T11X_MC_LA_DC_2                        0x2f0
+#define T11X_MC_LA_DCB_0               0x2f4
+#define T11X_MC_LA_DCB_1               0x2f8
+#define T11X_MC_LA_DCB_2               0x2fc
+#define T11X_MC_LA_EPP_0               0x300
+#define T11X_MC_LA_EPP_1               0x304
+#define T11X_MC_LA_G2_0                        0x308
+#define T11X_MC_LA_G2_1                        0x30c
+#define T11X_MC_LA_HC_0                        0x310
+#define T11X_MC_LA_HC_1                        0x314
+#define T11X_MC_LA_HDA_0               0x318
+#define T11X_MC_LA_ISP_0               0x31C
+#define T11X_MC_LA_MPCORE_0            0x320
+#define T11X_MC_LA_MPCORELP_0          0x324
+#define T11X_MC_LA_MSENC_0             0x328
+#define T11X_MC_LA_NV_0                        0x334
+#define T11X_MC_LA_NV_1                        0x338
+#define T11X_MC_LA_NV2_0               0x33c
+#define T11X_MC_LA_NV2_1               0x340
+#define T11X_MC_LA_PPCS_0              0x344
+#define T11X_MC_LA_PPCS_1              0x348
+#define T11X_MC_LA_PTC_0               0x34c
+
+#define T11X_MC_LA_VDE_0               0x354
+#define T11X_MC_LA_VDE_1               0x358
+#define T11X_MC_LA_VDE_2               0x35c
+#define T11X_MC_LA_VDE_3               0x360
+#define T11X_MC_LA_VI_0                        0x364
+#define T11X_MC_LA_VI_1                        0x368
+#define T11X_MC_LA_VI_2                        0x36c
+
+#define T11X_MC_LA_XUSB_0              0x37c /* T11x specific*/
+#define T11X_MC_LA_XUSB_1              0x380 /* T11x specific*/
+#define T11X_MC_LA_NV_2                        0x384 /* T11x specific*/
+#define T11X_MC_LA_NV_3                        0x388 /* T11x specific*/
+
+#define T11X_MC_LA_EMUCIF_0            0x38c
+#define T11X_MC_LA_TSEC_0              0x390
+
+#define T11X_MC_DIS_PTSA_RATE_0                        0x41c
+#define T11X_MC_DIS_PTSA_MIN_0                 0x420
+#define T11X_MC_DIS_PTSA_MAX_0                 0x424
+#define T11X_MC_DISB_PTSA_RATE_0               0x428
+#define T11X_MC_DISB_PTSA_MIN_0                        0x42c
+#define T11X_MC_DISB_PTSA_MAX_0                        0x430
+#define T11X_MC_VE_PTSA_RATE_0                 0x434
+#define T11X_MC_VE_PTSA_MIN_0                  0x438
+#define T11X_MC_VE_PTSA_MAX_0                  0x43c
+#define T11X_MC_RING2_PTSA_RATE_0              0x440
+#define T11X_MC_RING2_PTSA_MIN_0               0x444
+#define T11X_MC_RING2_PTSA_MAX_0               0x448
+#define T11X_MC_MLL_MPCORER_PTSA_RATE_0                0x44c
+#define T11X_MC_MLL_MPCORER_PTSA_MIN_0         0x450
+#define T11X_MC_MLL_MPCORER_PTSA_MAX_0         0x454
+#define T11X_MC_SMMU_SMMU_PTSA_RATE_0          0x458
+#define T11X_MC_SMMU_SMMU_PTSA_MIN_0           0x45c
+#define T11X_MC_SMMU_SMMU_PTSA_MAX_0           0x460
+#define T11X_MC_R0_DIS_PTSA_RATE_0             0x464
+#define T11X_MC_R0_DIS_PTSA_MIN_0              0x468
+#define T11X_MC_R0_DIS_PTSA_MAX_0              0x46c
+#define T11X_MC_R0_DISB_PTSA_RATE_0            0x470
+#define T11X_MC_R0_DISB_PTSA_MIN_0             0x474
+#define T11X_MC_R0_DISB_PTSA_MAX_0             0x478
+#define T11X_MC_RING1_PTSA_RATE_0              0x47c
+#define T11X_MC_RING1_PTSA_MIN_0               0x480
+#define T11X_MC_RING1_PTSA_MAX_0               0x484
+
+#define T11X_MC_DIS_EXTRA_SNAP_LEVELS_0                0x2ac
+#define T11X_MC_HEG_EXTRA_SNAP_LEVELS_0                0x2b0
+#define T11X_MC_EMEM_ARB_MISC0_0               0x0d8
+#define T11X_MC_PTSA_GRANT_DECREMENT_0         0x960
+
+#define T11X_BASE_EMC_FREQ_MHZ         500
+#define T11X_MAX_CAMERA_BW_MHZ         528
+
+/* maximum valid value for latency allowance */
+#define T11X_MC_LA_MAX_VALUE           255
+
+#define T11X_MC_RA(r) \
+       ((u32)IO_ADDRESS(TEGRA_MC_BASE) + (T11X_MC_##r))
+#define T11X_RA(r) \
+       ((u32)IO_ADDRESS(TEGRA_MC_BASE) + (T11X_MC_LA_##r))
+
+#define T11X_LA(f, e, a, r, i, ss, la) \
+{ \
+       .fifo_size_in_atoms = f, \
+       .expiration_in_ns = e, \
+       .reg_addr = T11X_RA(a), \
+       .mask = MASK(r), \
+       .shift = SHIFT(r), \
+       .id = ID(i), \
+       .name = __stringify(i), \
+       .scaling_supported = ss, \
+       .init_la = la, \
+}
+
+/*
+ * The consensus for getting the fifo_size_in_atoms is:
+ * 1.If REORDER_DEPTH exists, use it(default is overridden).
+ * 2.Else if (write_client) use RFIFO_DEPTH.
+ * 3.Else (read client) use RDFIFO_DEPTH.
+ * Multiply the value by 2 for dual channel.
+ * Multiply the value by 2 for wide clients.
+ * A client is wide, if CMW is larger than MW.
+ * Refer to project.h file.
+ */
+struct la_client_info t11x_la_info_array[] = {
+       T11X_LA(3,      150,    AVPC_ARM7_0, 7 : 0,     AVPC_ARM7R,     false,  0),
+       T11X_LA(3,      150,    AVPC_ARM7_0, 23 : 16,   AVPC_ARM7W,     false,  0),
+       T11X_LA(256,    1050,   DC_0,   7 : 0,          DISPLAY_0A,     true,   0),
+       T11X_LA(256,    1050,   DC_0,   23 : 16,        DISPLAY_0B,     true,   0),
+       T11X_LA(256,    1050,   DC_1,   7 : 0,          DISPLAY_0C,     true,   0),
+       T11X_LA(96,     1050,   DC_2,   7 : 0,          DISPLAY_HC,     false,  0),
+       T11X_LA(256,    1050,   DCB_0,  7 : 0,          DISPLAY_0AB,    true,   0),
+       T11X_LA(256,    1050,   DCB_0,  23 : 16,        DISPLAY_0BB,    true,   0),
+       T11X_LA(256,    1050,   DCB_1,  7 : 0,          DISPLAY_0CB,    true,   0),
+       T11X_LA(96,     1050,   DCB_2,  7 : 0,          DISPLAY_HCB,    false,  0),
+       T11X_LA(16,     150,    EPP_0,  7 : 0,          EPPUP,          false,  0),
+       T11X_LA(64,     150,    EPP_0,  23 : 16,        EPPU,           false,  0),
+       T11X_LA(64,     150,    EPP_1,  7 : 0,          EPPV,           false,  0),
+       T11X_LA(64,     150,    EPP_1,  23 : 16,        EPPY,           false,  0),
+       T11X_LA(128,    150,    G2_0,   7 : 0,          G2PR,           false,  0),
+       T11X_LA(128,    150,    G2_0,   23 : 16,        G2SR,           false,  0),
+       T11X_LA(96,     150,    G2_1,   7 : 0,          G2DR,           false,  0),
+       T11X_LA(256,    150,    G2_1,   23 : 16,        G2DW,           false,  0),
+       T11X_LA(32,     150,    HC_0,   7 : 0,          HOST1X_DMAR,    false,  0),
+       T11X_LA(16,     150,    HC_0,   23 : 16,        HOST1XR,        false,  0),
+       T11X_LA(64,     150,    HC_1,   7 : 0,          HOST1XW,        false,  0),
+       T11X_LA(32,     150,    HDA_0,  7 : 0,          HDAR,           false,  0),
+       T11X_LA(32,     150,    HDA_0,  23 : 16,        HDAW,           false,  0),
+       T11X_LA(128,    150,    ISP_0,  7 : 0,          ISPW,           false,  0),
+       T11X_LA(96,     150,    MPCORE_0,   7 : 0,      MPCORER,        false,  0),
+       T11X_LA(128,    150,    MPCORE_0,   23 : 16,    MPCOREW,        false,  0),
+       T11X_LA(96,     150,    MPCORELP_0, 7 : 0,      MPCORE_LPR,     false,  0),
+       T11X_LA(128,    150,    MPCORELP_0, 23 : 16,    MPCORE_LPW,     false,  0),
+       T11X_LA(128,    150,    NV_0,   7 : 0,          FDCDRD,         false,  0),
+       T11X_LA(256,    150,    NV_0,   23 : 16,        IDXSRD,         false,  0),
+       T11X_LA(432,    150,    NV_1,   7 : 0,          TEXL2SRD,       false,  0),
+       T11X_LA(128,    150,    NV_1,   23 : 16,        FDCDWR,         false,  0),
+       T11X_LA(128,    150,    NV2_0,  7 : 0,          FDCDRD2,        false,  0),
+       T11X_LA(128,    150,    NV2_1,  23 : 16,        FDCDWR2,        false,  0),
+       T11X_LA(8,      150,    PPCS_0, 7 : 0,          PPCS_AHBDMAR,   false,  0),
+       T11X_LA(80,     150,    PPCS_0, 23 : 16,        PPCS_AHBSLVR,   false,  0),
+       T11X_LA(16,     150,    PPCS_1, 7 : 0,          PPCS_AHBDMAW,   false,  0),
+       T11X_LA(80,     150,    PPCS_1, 23 : 16,        PPCS_AHBSLVW,   false,  0),
+       T11X_LA(40,     150,    PTC_0,  7 : 0,          PTCR,           false,  0),
+       T11X_LA(16,     150,    VDE_0,  7 : 0,          VDE_BSEVR,      false,  131),
+       T11X_LA(8,      150,    VDE_0,  23 : 16,        VDE_MBER,       false,  131),
+       T11X_LA(64,     150,    VDE_1,  7 : 0,          VDE_MCER,       false,  50),
+       T11X_LA(32,     150,    VDE_1,  23 : 16,        VDE_TPER,       false,  123),
+       T11X_LA(8,      150,    VDE_2,  7 : 0,          VDE_BSEVW,      false,  131),
+       T11X_LA(32,     150,    VDE_2,  23 : 16,        VDE_DBGW,       false,  131),
+       T11X_LA(16,     150,    VDE_3,  7 : 0,          VDE_MBEW,       false,  70),
+       T11X_LA(32,     150,    VDE_3,  23 : 16,        VDE_TPMW,       false,  76),
+       T11X_LA(128,    1050,   VI_0,   23 : 16,        VI_WSB,         true,   0),
+       T11X_LA(128,    1050,   VI_1,   7 : 0,          VI_WU,          true,   0),
+       T11X_LA(128,    1050,   VI_1,   23 : 16,        VI_WV,          true,   0),
+       T11X_LA(128,    1050,   VI_2,   7 : 0,          VI_WY,          true,   0),
+
+       T11X_LA(128,    150,    MSENC_0,    7 : 0,      MSENCSRD,       false,  128),
+       T11X_LA(32,     150,    MSENC_0,    23 : 16,    MSENCSWR,       false,  41),
+       T11X_LA(160,    150,    XUSB_0,     7 : 0,      XUSB_HOSTR,     false,  0),
+       T11X_LA(160,    150,    XUSB_0,     23 : 16,    XUSB_HOSTW,     false,  0),
+       T11X_LA(160,    150,    XUSB_1,     7 : 0,      XUSB_DEVR,      false,  0),
+       T11X_LA(160,    150,    XUSB_1,     23 : 16,    XUSB_DEVW,      false,  0),
+       T11X_LA(128,    150,    NV_2,       7 : 0,      FDCDRD3,        false,  0),
+       T11X_LA(128,    150,    NV_2,       23 : 16,    FDCDRD4,        false,  0),
+       T11X_LA(128,    150,    NV_3,       7 : 0,      FDCDWR3,        false,  0),
+       T11X_LA(128,    150,    NV_3,       23 : 16,    FDCDWR4,        false,  0),
+       T11X_LA(28,     150,    EMUCIF_0,   7 : 0,      EMUCIFR,        false,  0),
+       T11X_LA(48,     150,    EMUCIF_0,   23 : 16,    EMUCIFW,        false,  0),
+       T11X_LA(32,     150,    TSEC_0,     7 : 0,      TSECSRD,        false,  0),
+       T11X_LA(32,     150,    TSEC_0,     23 : 16,    TSECSWR,        false,  0),
+
+/* end of list. */
+       T11X_LA(0,      0,      TSEC_0,     0 : 0,      MAX_ID,         false,  0)
+};
+
+static unsigned int t11x_get_ptsa_rate(unsigned int bw)
+{
+       /* 16 = 2 channels * 2 ddr * 4 bytes */
+       unsigned int base_memory_bw = 16 * T11X_BASE_EMC_FREQ_MHZ;
+       unsigned int rate = 281 * bw / base_memory_bw;
+       if (rate > 255)
+               rate = 255;
+       return rate;
+}
+
+static void t11x_init_ptsa(void)
+{
+       struct clk *emc_clk __attribute__((unused));
+       unsigned long emc_freq __attribute__((unused));
+       unsigned long same_freq __attribute__((unused));
+       unsigned long grant_dec __attribute__((unused));
+       unsigned long ring1_rate __attribute__((unused));
+
+       emc_clk = clk_get(NULL, "emc");
+       la_debug("**** emc clk_rate=%luMHz", clk_get_rate(emc_clk)/1000000);
+
+       emc_freq = clk_get_rate(emc_clk);
+       emc_freq /= 1000000;
+       /* Compute initial value for grant dec */
+       same_freq = readl(T11X_MC_RA(EMEM_ARB_MISC0_0));
+       same_freq = same_freq >> 27 & 1;
+       grant_dec = 256 * (same_freq ? 2 : 1) * emc_freq;
+       if (grant_dec > 511)
+               grant_dec = 511;
+       writel(grant_dec, T11X_MC_RA(PTSA_GRANT_DECREMENT_0));
+
+       writel(0x3d, T11X_MC_RA(DIS_PTSA_MIN_0));
+       writel(0x14, T11X_MC_RA(DIS_PTSA_MAX_0));
+
+       writel(0x3d, T11X_MC_RA(DISB_PTSA_MIN_0));
+       writel(0x14, T11X_MC_RA(DISB_PTSA_MAX_0));
+
+       writel(t11x_get_ptsa_rate(T11X_MAX_CAMERA_BW_MHZ),
+               T11X_MC_RA(VE_PTSA_RATE_0));
+       writel(0x3d, T11X_MC_RA(VE_PTSA_MIN_0));
+       writel(0x14, T11X_MC_RA(VE_PTSA_MAX_0));
+
+       writel(0x01, T11X_MC_RA(RING2_PTSA_RATE_0));
+       writel(0x3f, T11X_MC_RA(RING2_PTSA_MIN_0));
+       writel(0x05, T11X_MC_RA(RING2_PTSA_MAX_0));
+
+       writel(38 * emc_freq / T11X_BASE_EMC_FREQ_MHZ,
+               T11X_MC_RA(MLL_MPCORER_PTSA_RATE_0));
+       writel(0x3f, T11X_MC_RA(MLL_MPCORER_PTSA_MIN_0));
+       writel(0x05, T11X_MC_RA(MLL_MPCORER_PTSA_MAX_0));
+
+       writel(0x01, T11X_MC_RA(SMMU_SMMU_PTSA_RATE_0));
+       writel(0x01, T11X_MC_RA(SMMU_SMMU_PTSA_MIN_0));
+       writel(0x01, T11X_MC_RA(SMMU_SMMU_PTSA_MAX_0));
+
+       writel(0x00, T11X_MC_RA(R0_DIS_PTSA_RATE_0));
+       writel(0x3f, T11X_MC_RA(R0_DIS_PTSA_MIN_0));
+       writel(0x3f, T11X_MC_RA(R0_DIS_PTSA_MAX_0));
+
+       writel(0x00, T11X_MC_RA(R0_DISB_PTSA_RATE_0));
+       writel(0x3f, T11X_MC_RA(R0_DISB_PTSA_MIN_0));
+       writel(0x3f, T11X_MC_RA(R0_DISB_PTSA_MAX_0));
+
+       ring1_rate = readl(T11X_MC_RA(DIS_PTSA_RATE_0)) +
+                    readl(T11X_MC_RA(DISB_PTSA_RATE_0)) +
+                    readl(T11X_MC_RA(VE_PTSA_RATE_0)) +
+                    readl(T11X_MC_RA(RING2_PTSA_RATE_0));
+#if defined(CONFIG_TEGRA_ERRATA_977223)
+       ring1_rate /= 2;
+#endif
+       writel(ring1_rate, T11X_MC_RA(RING1_PTSA_RATE_0));
+       writel(0x36, T11X_MC_RA(RING1_PTSA_MIN_0));
+       writel(0x1f, T11X_MC_RA(RING1_PTSA_MAX_0));
+
+       writel(0x00, T11X_MC_RA(DIS_EXTRA_SNAP_LEVELS_0));
+       writel(0x03, T11X_MC_RA(HEG_EXTRA_SNAP_LEVELS_0));
+}
+
+static void t11x_update_display_ptsa_rate(unsigned int *disp_bw_array)
+{
+       unsigned int num_active = (disp_bw_array[0] != 0) +
+                                 (disp_bw_array[1] != 0) +
+                                 (disp_bw_array[2] != 0);
+       unsigned int num_activeb = (disp_bw_array[5] != 0) +
+                                  (disp_bw_array[6] != 0) +
+                                  (disp_bw_array[7] != 0);
+       unsigned int max_bw = disp_bw_array[0];
+       unsigned int max_bwb = disp_bw_array[5];
+       unsigned int rate_dis;
+       unsigned int rate_disb;
+       unsigned long ring1_rate;
+
+       max_bw = max(disp_bw_array[0], disp_bw_array[1]);
+       max_bw = max(max_bw, disp_bw_array[2]);
+
+       max_bwb = max(disp_bw_array[5], disp_bw_array[6]);
+       max_bwb = max(max_bwb, disp_bw_array[7]);
+
+       rate_dis = t11x_get_ptsa_rate(num_active * max_bw);
+       rate_disb = t11x_get_ptsa_rate(num_activeb * max_bwb);
+
+       writel(rate_dis, T11X_MC_RA(DIS_PTSA_RATE_0));
+       writel(rate_disb, T11X_MC_RA(DISB_PTSA_RATE_0));
+
+
+       ring1_rate = readl(T11X_MC_RA(DIS_PTSA_RATE_0)) +
+                    readl(T11X_MC_RA(DISB_PTSA_RATE_0)) +
+                    readl(T11X_MC_RA(VE_PTSA_RATE_0)) +
+                    readl(T11X_MC_RA(RING2_PTSA_RATE_0));
+       la_debug("max_bw=0x%x, max_bwb=0x%x, num_active=0x%x,"
+               "num_activeb=0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x ",
+               max_bw, max_bwb, num_active, num_activeb, disp_bw_array[0],
+               disp_bw_array[1], disp_bw_array[2], disp_bw_array[5],
+               disp_bw_array[6], disp_bw_array[7]);
+       la_debug("dis=0x%x, disb=0x%x, ve=0x%x, rng2=0x%x, rng1=0x%lx",
+               readl(T11X_MC_RA(DIS_PTSA_RATE_0)),
+               readl(T11X_MC_RA(DISB_PTSA_RATE_0)),
+               readl(T11X_MC_RA(VE_PTSA_RATE_0)),
+               readl(T11X_MC_RA(RING2_PTSA_RATE_0)), ring1_rate);
+#if defined(CONFIG_TEGRA_ERRATA_977223)
+       ring1_rate /= 2;
+#endif
+       writel(ring1_rate, T11X_MC_RA(RING1_PTSA_RATE_0));
+}
+
+void tegra_la_get_t11x_specific(struct la_chip_specific *cs)
+{
+       cs->ns_per_tick = 30;
+       cs->atom_size = 16;
+       cs->la_max_value = T11X_MC_LA_MAX_VALUE;
+       cs->la_info_array = t11x_la_info_array;
+       cs->la_info_array_size = ARRAY_SIZE(t11x_la_info_array);
+       cs->init_ptsa = t11x_init_ptsa;
+       cs->update_display_ptsa_rate = t11x_update_display_ptsa_rate;
+}
diff --git a/arch/arm/mach-tegra/tegra11x_la_priv.h b/arch/arm/mach-tegra/tegra11x_la_priv.h
deleted file mode 100644 (file)
index 1eac0a7..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * arch/arm/mach-tegra/tegra11x_la_priv.h
- *
- * Copyright (C) 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
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _MACH_TEGRA_TEGRA11x_LA_PRIV_H_
-#define _MACH_TEGRA_TEGRA11x_LA_PRIV_H_
-
-#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
-
-#define MC_LA_AVPC_ARM7_0      0x2e4
-#define MC_LA_DC_0             0x2e8
-#define MC_LA_DC_1             0x2ec
-#define MC_LA_DC_2             0x2f0
-#define MC_LA_DCB_0            0x2f4
-#define MC_LA_DCB_1            0x2f8
-#define MC_LA_DCB_2            0x2fc
-#define MC_LA_EPP_0            0x300
-#define MC_LA_EPP_1            0x304
-#define MC_LA_G2_0             0x308
-#define MC_LA_G2_1             0x30c
-#define MC_LA_HC_0             0x310
-#define MC_LA_HC_1             0x314
-#define MC_LA_HDA_0            0x318
-#define MC_LA_ISP_0            0x31C
-#define MC_LA_MPCORE_0         0x320
-#define MC_LA_MPCORELP_0       0x324
-#define MC_LA_MSENC_0          0x328
-#define MC_LA_NV_0             0x334
-#define MC_LA_NV_1             0x338
-#define MC_LA_NV2_0            0x33c
-#define MC_LA_NV2_1            0x340
-#define MC_LA_PPCS_0           0x344
-#define MC_LA_PPCS_1           0x348
-#define MC_LA_PTC_0            0x34c
-
-#define MC_LA_VDE_0            0x354
-#define MC_LA_VDE_1            0x358
-#define MC_LA_VDE_2            0x35c
-#define MC_LA_VDE_3            0x360
-#define MC_LA_VI_0             0x364
-#define MC_LA_VI_1             0x368
-#define MC_LA_VI_2             0x36c
-
-#define MC_LA_XUSB_0           0x37c /* T11x specific*/
-#define MC_LA_XUSB_1           0x380 /* T11x specific*/
-#define MC_LA_NV_2             0x384 /* T11x specific*/
-#define MC_LA_NV_3             0x388 /* T11x specific*/
-
-#define MC_LA_EMUCIF_0         0x38c
-#define MC_LA_TSEC_0           0x390
-
-#define MC_DIS_PTSA_RATE_0             0x41c
-#define MC_DIS_PTSA_MIN_0              0x420
-#define MC_DIS_PTSA_MAX_0              0x424
-#define MC_DISB_PTSA_RATE_0            0x428
-#define MC_DISB_PTSA_MIN_0             0x42c
-#define MC_DISB_PTSA_MAX_0             0x430
-#define MC_VE_PTSA_RATE_0              0x434
-#define MC_VE_PTSA_MIN_0               0x438
-#define MC_VE_PTSA_MAX_0               0x43c
-#define MC_RING2_PTSA_RATE_0           0x440
-#define MC_RING2_PTSA_MIN_0            0x444
-#define MC_RING2_PTSA_MAX_0            0x448
-#define MC_MLL_MPCORER_PTSA_RATE_0     0x44c
-#define MC_MLL_MPCORER_PTSA_MIN_0      0x450
-#define MC_MLL_MPCORER_PTSA_MAX_0      0x454
-#define MC_SMMU_SMMU_PTSA_RATE_0       0x458
-#define MC_SMMU_SMMU_PTSA_MIN_0                0x45c
-#define MC_SMMU_SMMU_PTSA_MAX_0                0x460
-#define MC_R0_DIS_PTSA_RATE_0          0x464
-#define MC_R0_DIS_PTSA_MIN_0           0x468
-#define MC_R0_DIS_PTSA_MAX_0           0x46c
-#define MC_R0_DISB_PTSA_RATE_0         0x470
-#define MC_R0_DISB_PTSA_MIN_0          0x474
-#define MC_R0_DISB_PTSA_MAX_0          0x478
-#define MC_RING1_PTSA_RATE_0           0x47c
-#define MC_RING1_PTSA_MIN_0            0x480
-#define MC_RING1_PTSA_MAX_0            0x484
-
-#define MC_DIS_EXTRA_SNAP_LEVELS_0     0x2ac
-#define MC_HEG_EXTRA_SNAP_LEVELS_0     0x2b0
-#define MC_EMEM_ARB_MISC0_0            0x0d8
-#define MC_PTSA_GRANT_DECREMENT_0      0x960
-
-#define BASE_EMC_FREQ_MHZ              500
-#define MAX_CAMERA_BW_MHZ              528
-
-
-/*
- * The rule for getting the fifo_size_in_atoms is:
- * 1.If REORDER_DEPTH exists, use it(default is overridden).
- * 2.Else if (write_client) use RFIFO_DEPTH.
- * 3.Else (read client) use RDFIFO_DEPTH.
- * Multiply the value by 2 for dual channel.
- * Multiply the value by 2 for wide clients.
- * A client is wide, if CMW is larger than MW.
- * Refer to project.h file.
- */
-struct la_client_info la_info_array[] = {
-       LA_INFO(3,      150,    AVPC_ARM7_0, 7 : 0,     AVPC_ARM7R,     false,  0),
-       LA_INFO(3,      150,    AVPC_ARM7_0, 23 : 16,   AVPC_ARM7W,     false,  0),
-       LA_INFO(256,    1050,   DC_0,   7 : 0,          DISPLAY_0A,     true,   0),
-       LA_INFO(256,    1050,   DC_0,   23 : 16,        DISPLAY_0B,     true,   0),
-       LA_INFO(256,    1050,   DC_1,   7 : 0,          DISPLAY_0C,     true,   0),
-       LA_INFO(96,     1050,   DC_2,   7 : 0,          DISPLAY_HC,     false,  0),
-       LA_INFO(256,    1050,   DCB_0,  7 : 0,          DISPLAY_0AB,    true,   0),
-       LA_INFO(256,    1050,   DCB_0,  23 : 16,        DISPLAY_0BB,    true,   0),
-       LA_INFO(256,    1050,   DCB_1,  7 : 0,          DISPLAY_0CB,    true,   0),
-       LA_INFO(96,     1050,   DCB_2,  7 : 0,          DISPLAY_HCB,    false,  0),
-       LA_INFO(16,     150,    EPP_0,  7 : 0,          EPPUP,          false,  0),
-       LA_INFO(64,     150,    EPP_0,  23 : 16,        EPPU,           false,  0),
-       LA_INFO(64,     150,    EPP_1,  7 : 0,          EPPV,           false,  0),
-       LA_INFO(64,     150,    EPP_1,  23 : 16,        EPPY,           false,  0),
-       LA_INFO(128,    150,    G2_0,   7 : 0,          G2PR,           false,  0),
-       LA_INFO(128,    150,    G2_0,   23 : 16,        G2SR,           false,  0),
-       LA_INFO(96,     150,    G2_1,   7 : 0,          G2DR,           false,  0),
-       LA_INFO(256,    150,    G2_1,   23 : 16,        G2DW,           false,  0),
-       LA_INFO(32,     150,    HC_0,   7 : 0,          HOST1X_DMAR,    false,  0),
-       LA_INFO(16,     150,    HC_0,   23 : 16,        HOST1XR,        false,  0),
-       LA_INFO(64,     150,    HC_1,   7 : 0,          HOST1XW,        false,  0),
-       LA_INFO(32,     150,    HDA_0,  7 : 0,          HDAR,           false,  0),
-       LA_INFO(32,     150,    HDA_0,  23 : 16,        HDAW,           false,  0),
-       LA_INFO(128,    150,    ISP_0,  7 : 0,          ISPW,           false,  0),
-       LA_INFO(96,     150,    MPCORE_0,   7 : 0,      MPCORER,        false,  0),
-       LA_INFO(128,    150,    MPCORE_0,   23 : 16,    MPCOREW,        false,  0),
-       LA_INFO(96,     150,    MPCORELP_0, 7 : 0,      MPCORE_LPR,     false,  0),
-       LA_INFO(128,    150,    MPCORELP_0, 23 : 16,    MPCORE_LPW,     false,  0),
-       LA_INFO(128,    150,    NV_0,   7 : 0,          FDCDRD,         false,  0),
-       LA_INFO(256,    150,    NV_0,   23 : 16,        IDXSRD,         false,  0),
-       LA_INFO(432,    150,    NV_1,   7 : 0,          TEXL2SRD,       false,  0),
-       LA_INFO(128,    150,    NV_1,   23 : 16,        FDCDWR,         false,  0),
-       LA_INFO(128,    150,    NV2_0,  7 : 0,          FDCDRD2,        false,  0),
-       LA_INFO(128,    150,    NV2_1,  23 : 16,        FDCDWR2,        false,  0),
-       LA_INFO(8,      150,    PPCS_0, 7 : 0,          PPCS_AHBDMAR,   false,  0),
-       LA_INFO(80,     150,    PPCS_0, 23 : 16,        PPCS_AHBSLVR,   false,  0),
-       LA_INFO(16,     150,    PPCS_1, 7 : 0,          PPCS_AHBDMAW,   false,  0),
-       LA_INFO(80,     150,    PPCS_1, 23 : 16,        PPCS_AHBSLVW,   false,  0),
-       LA_INFO(40,     150,    PTC_0,  7 : 0,          PTCR,           false,  0),
-       LA_INFO(16,     150,    VDE_0,  7 : 0,          VDE_BSEVR,      false,  131),
-       LA_INFO(8,      150,    VDE_0,  23 : 16,        VDE_MBER,       false,  131),
-       LA_INFO(64,     150,    VDE_1,  7 : 0,          VDE_MCER,       false,  50),
-       LA_INFO(32,     150,    VDE_1,  23 : 16,        VDE_TPER,       false,  123),
-       LA_INFO(8,      150,    VDE_2,  7 : 0,          VDE_BSEVW,      false,  131),
-       LA_INFO(32,     150,    VDE_2,  23 : 16,        VDE_DBGW,       false,  131),
-       LA_INFO(16,     150,    VDE_3,  7 : 0,          VDE_MBEW,       false,  70),
-       LA_INFO(32,     150,    VDE_3,  23 : 16,        VDE_TPMW,       false,  76),
-       LA_INFO(128,    1050,   VI_0,   23 : 16,        VI_WSB,         true,   0),
-       LA_INFO(128,    1050,   VI_1,   7 : 0,          VI_WU,          true,   0),
-       LA_INFO(128,    1050,   VI_1,   23 : 16,        VI_WV,          true,   0),
-       LA_INFO(128,    1050,   VI_2,   7 : 0,          VI_WY,          true,   0),
-
-       LA_INFO(128,    150,    MSENC_0,    7 : 0,      MSENCSRD,       false,  128),
-       LA_INFO(32,     150,    MSENC_0,    23 : 16,    MSENCSWR,       false,  41),
-       LA_INFO(160,    150,    XUSB_0,     7 : 0,      XUSB_HOSTR,     false,  0),
-       LA_INFO(160,    150,    XUSB_0,     23 : 16,    XUSB_HOSTW,     false,  0),
-       LA_INFO(160,    150,    XUSB_1,     7 : 0,      XUSB_DEVR,      false,  0),
-       LA_INFO(160,    150,    XUSB_1,     23 : 16,    XUSB_DEVW,      false,  0),
-       LA_INFO(128,    150,    NV_2,       7 : 0,      FDCDRD3,        false,  0),
-       LA_INFO(128,    150,    NV_2,       23 : 16,    FDCDRD4,        false,  0),
-       LA_INFO(128,    150,    NV_3,       7 : 0,      FDCDWR3,        false,  0),
-       LA_INFO(128,    150,    NV_3,       23 : 16,    FDCDWR4,        false,  0),
-       LA_INFO(28,     150,    EMUCIF_0,   7 : 0,      EMUCIFR,        false,  0),
-       LA_INFO(48,     150,    EMUCIF_0,   23 : 16,    EMUCIFW,        false,  0),
-       LA_INFO(32,     150,    TSEC_0,     7 : 0,      TSECSRD,        false,  0),
-       LA_INFO(32,     150,    TSEC_0,     23 : 16,    TSECSWR,        false,  0),
-
-/* end of list. */
-       LA_INFO(0,      0,      TSEC_0,     0 : 0,      MAX_ID,         false,  0)
-};
-
-static int ns_per_tick = 30;
-/* MC atom size in bytes */
-static const int normal_atom_size = 16;
-#endif
-
-#endif /* _MACH_TEGRA_TEGRA11x_LA_PRIV_H_ */
diff --git a/arch/arm/mach-tegra/tegra14x_la.c b/arch/arm/mach-tegra/tegra14x_la.c
new file mode 100644 (file)
index 0000000..297f00c
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * arch/arm/mach-tegra/tegra14x_la.c
+ *
+ * Copyright (C) 2012-2013, 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
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/stringify.h>
+#include <linux/clk.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/iomap.h>
+#include <mach/io.h>
+#include <mach/clk.h>
+#include <mach/latency_allowance.h>
+#include "la_priv.h"
+
+#define T14X_MC_LA_AVPC_ARM7_0 0x2e4
+#define T14X_MC_LA_DC_0                0x2e8
+#define T14X_MC_LA_DC_1                0x2ec
+#define T14X_MC_LA_DC_2                0x2f0
+#define T14X_MC_LA_DCB_0               0x2f4
+#define T14X_MC_LA_DCB_1               0x2f8
+#define T14X_MC_LA_DCB_2               0x2fc
+#define T14X_MC_LA_EPP_0               0x300
+#define T14X_MC_LA_EPP_1               0x304
+#define T14X_MC_LA_G2_0                0x308
+#define T14X_MC_LA_G2_1                0x30c
+#define T14X_MC_LA_HC_0                0x310
+#define T14X_MC_LA_HC_1                0x314
+#define T14X_MC_LA_HDA_0               0x318
+#define T14X_MC_LA_ISP_0               0x31C
+#define T14X_MC_LA_MPCORE_0            0x320
+#define T14X_MC_LA_MPCORELP_0  0x324
+#define T14X_MC_LA_MSENC_0             0x328
+#define T14X_MC_LA_NV_0                0x334
+#define T14X_MC_LA_NV_1                0x338
+#define T14X_MC_LA_NV2_0               0x33c
+#define T14X_MC_LA_NV2_1               0x340
+#define T14X_MC_LA_PPCS_0              0x344
+#define T14X_MC_LA_PPCS_1              0x348
+#define T14X_MC_LA_PTC_0               0x34c
+
+#define T14X_MC_LA_VDE_0               0x354
+#define T14X_MC_LA_VDE_1               0x358
+#define T14X_MC_LA_VDE_2               0x35c
+#define T14X_MC_LA_VDE_3               0x360
+#define T14X_MC_LA_VI_0                0x364
+#define T14X_MC_LA_VI_1                0x368
+#define T14X_MC_LA_VI_2                0x36c
+#define T14X_MC_LA_ISP2_0              0x370 /* T14x specific*/
+#define T14X_MC_LA_ISP2_1              0x374 /* T14x specific*/
+
+#define T14X_MC_LA_EMUCIF_0            0x38c
+#define T14X_MC_LA_TSEC_0              0x390
+
+#define T14X_MC_LA_BBMCI_0             0x394 /* T14x specific*/
+#define T14X_MC_LA_BBMCILL_0           0x398 /* T14x specific*/
+#define T14X_MC_LA_DC_3                0x39c /* T14x specific*/
+
+#define T14X_MC_DIS_PTSA_RATE_0                        0x41c
+#define T14X_MC_DIS_PTSA_MIN_0                 0x420
+#define T14X_MC_DIS_PTSA_MAX_0                 0x424
+#define T14X_MC_DISB_PTSA_RATE_0               0x428
+#define T14X_MC_DISB_PTSA_MIN_0                        0x42c
+#define T14X_MC_DISB_PTSA_MAX_0                        0x430
+#define T14X_MC_VE_PTSA_RATE_0                 0x434
+#define T14X_MC_VE_PTSA_MIN_0                  0x438
+#define T14X_MC_VE_PTSA_MAX_0                  0x43c
+#define T14X_MC_RING2_PTSA_RATE_0              0x440
+#define T14X_MC_RING2_PTSA_MIN_0               0x444
+#define T14X_MC_RING2_PTSA_MAX_0               0x448
+#define T14X_MC_MLL_MPCORER_PTSA_RATE_0                0x44c
+#define T14X_MC_MLL_MPCORER_PTSA_MIN_0         0x450
+#define T14X_MC_MLL_MPCORER_PTSA_MAX_0         0x454
+#define T14X_MC_SMMU_SMMU_PTSA_RATE_0          0x458
+#define T14X_MC_SMMU_SMMU_PTSA_MIN_0           0x45c
+#define T14X_MC_SMMU_SMMU_PTSA_MAX_0           0x460
+#define T14X_MC_R0_DIS_PTSA_RATE_0             0x464
+#define T14X_MC_R0_DIS_PTSA_MIN_0              0x468
+#define T14X_MC_R0_DIS_PTSA_MAX_0              0x46c
+#define T14X_MC_R0_DISB_PTSA_RATE_0            0x470
+#define T14X_MC_R0_DISB_PTSA_MIN_0             0x474
+#define T14X_MC_R0_DISB_PTSA_MAX_0             0x478
+#define T14X_MC_RING1_PTSA_RATE_0              0x47c
+#define T14X_MC_RING1_PTSA_MIN_0               0x480
+#define T14X_MC_RING1_PTSA_MAX_0               0x484
+
+#define T14X_MC_DIS_EXTRA_SNAP_LEVELS_0                0x2ac
+#define T14X_MC_HEG_EXTRA_SNAP_LEVELS_0                0x2b0
+#define T14X_MC_EMEM_ARB_MISC0_0               0x0d8
+#define T14X_MC_PTSA_GRANT_DECREMENT_0         0x960
+
+#define T14X_BASE_EMC_FREQ_MHZ         500
+#define T14X_MAX_CAMERA_BW_MHZ         528
+
+/* maximum valid value for latency allowance */
+#define T14X_MC_LA_MAX_VALUE           255
+
+#define T14X_MC_RA(r) \
+       ((u32)IO_ADDRESS(TEGRA_MC_BASE) + (T14X_MC_##r))
+#define T14X_RA(r) \
+       ((u32)IO_ADDRESS(TEGRA_MC_BASE) + (T14X_MC_LA_##r))
+
+#define T14X_LA(f, e, a, r, i, ss, la) \
+{ \
+       .fifo_size_in_atoms = f, \
+       .expiration_in_ns = e, \
+       .reg_addr = T14X_RA(a), \
+       .mask = MASK(r), \
+       .shift = SHIFT(r), \
+       .id = ID(i), \
+       .name = __stringify(i), \
+       .scaling_supported = ss, \
+       .init_la = la, \
+}
+
+/*
+ * The consensus for getting the fifo_size_in_atoms is:
+ * 1.If REORDER_DEPTH exists, use it(default is overridden).
+ * 2.Else if (write_client) use RFIFO_DEPTH.
+ * 3.Else (read client) use RDFIFO_DEPTH.
+ * Multiply the value by 2 for dual channel.
+ * Multiply the value by 2 for wide clients.
+ * A client is wide, if CMW is larger than MW.
+ * Refer to project.h file.
+ */
+struct la_client_info t14x_la_info_array[] = {
+       T14X_LA(4,      150,    AVPC_ARM7_0, 7 : 0,     AVPC_ARM7R,     false,  0),
+       T14X_LA(8,      150,    AVPC_ARM7_0, 23 : 16,   AVPC_ARM7W,     false,  0),
+       T14X_LA(128,    1050,   DC_0,   7 : 0,          DISPLAY_0A,     true,   0),
+       T14X_LA(128,    1050,   DC_0,   23 : 16,        DISPLAY_0B,     true,   0),
+       T14X_LA(128,    1050,   DC_1,   7 : 0,          DISPLAY_0C,     true,   0),
+       T14X_LA(192,    1050,   DC_2,   7 : 0,          DISPLAY_HC,     false,  0),
+       T14X_LA(128,    1050,   DCB_0,  7 : 0,          DISPLAY_0AB,    true,   0),
+       T14X_LA(128,    1050,   DCB_0,  23 : 16,        DISPLAY_0BB,    true,   0),
+       T14X_LA(128,    1050,   DCB_1,  7 : 0,          DISPLAY_0CB,    true,   0),
+       T14X_LA(192,    1050,   DCB_2,  7 : 0,          DISPLAY_HCB,    false,  0),
+       T14X_LA(32,     150,    EPP_0,  7 : 0,          EPPUP,          false,  0),
+       T14X_LA(32,     150,    EPP_0,  23 : 16,        EPPU,           false,  0),
+       T14X_LA(32,     150,    EPP_1,  7 : 0,          EPPV,           false,  0),
+       T14X_LA(32,     150,    EPP_1,  23 : 16,        EPPY,           false,  0),
+       T14X_LA(128,    150,    G2_0,   7 : 0,          G2PR,           false,  0),
+       T14X_LA(128,    150,    G2_0,   23 : 16,        G2SR,           false,  0),
+       T14X_LA(72,     150,    G2_1,   7 : 0,          G2DR,           false,  0),
+       T14X_LA(128,    150,    G2_1,   23 : 16,        G2DW,           false,  0),
+       T14X_LA(16,     150,    HC_0,   7 : 0,          HOST1X_DMAR,    false,  0),
+       T14X_LA(8,      150,    HC_0,   23 : 16,        HOST1XR,        false,  0),
+       T14X_LA(32,     150,    HC_1,   7 : 0,          HOST1XW,        false,  0),
+       T14X_LA(64,     150,    HDA_0,  7 : 0,          HDAR,           false,  0),
+       T14X_LA(64,     150,    HDA_0,  23 : 16,        HDAW,           false,  0),
+       T14X_LA(64,     150,    ISP_0,  7 : 0,          ISPW,           false,  0),
+       T14X_LA(40,     150,    MPCORE_0,   7 : 0,      MPCORER,        false,  0),
+       T14X_LA(42,     150,    MPCORE_0,   23 : 16,    MPCOREW,        false,  0),
+       T14X_LA(24,     150,    MPCORELP_0, 7 : 0,      MPCORE_LPR,     false,  0),
+       T14X_LA(24,     150,    MPCORELP_0, 23 : 16,    MPCORE_LPW,     false,  0),
+       T14X_LA(160,    150,    NV_0,   7 : 0,          FDCDRD,         false,  0),
+       T14X_LA(256,    150,    NV_0,   23 : 16,        IDXSRD,         false,  0),
+       T14X_LA(256,    150,    NV_1,   7 : 0,          TEXL2SRD,       false,  0),
+       T14X_LA(128,    150,    NV_1,   23 : 16,        FDCDWR,         false,  0),
+       T14X_LA(160,    150,    NV2_0,  7 : 0,          FDCDRD2,        false,  0),
+       T14X_LA(128,    150,    NV2_1,  23 : 16,        FDCDWR2,        false,  0),
+       T14X_LA(4,      150,    PPCS_0, 7 : 0,          PPCS_AHBDMAR,   false,  0),
+       T14X_LA(29,     150,    PPCS_0, 23 : 16,        PPCS_AHBSLVR,   false,  0),
+       T14X_LA(8,      150,    PPCS_1, 7 : 0,          PPCS_AHBDMAW,   false,  0),
+       T14X_LA(8,      150,    PPCS_1, 23 : 16,        PPCS_AHBSLVW,   false,  0),
+       T14X_LA(20,     150,    PTC_0,  7 : 0,          PTCR,           false,  0),
+       T14X_LA(8,      150,    VDE_0,  7 : 0,          VDE_BSEVR,      false,  0),
+       T14X_LA(9,      150,    VDE_0,  23 : 16,        VDE_MBER,       false,  0),
+       T14X_LA(64,     150,    VDE_1,  7 : 0,          VDE_MCER,       false,  0),
+       T14X_LA(32,     150,    VDE_1,  23 : 16,        VDE_TPER,       false,  0),
+       T14X_LA(4,      150,    VDE_2,  7 : 0,          VDE_BSEVW,      false,  0),
+       T14X_LA(4,      150,    VDE_2,  23 : 16,        VDE_DBGW,       false,  0),
+       T14X_LA(8,      150,    VDE_3,  7 : 0,          VDE_MBEW,       false,  0),
+       T14X_LA(32,     150,    VDE_3,  23 : 16,        VDE_TPMW,       false,  0),
+       T14X_LA(200,    1050,   VI_0,   7 : 0,          VI_WSB,         true,   0),
+       T14X_LA(200,    1050,   VI_1,   7 : 0,          VI_WU,          true,   0),
+       T14X_LA(200,    1050,   VI_1,   23 : 16,        VI_WV,          true,   0),
+       T14X_LA(200,    1050,   VI_2,   7 : 0,          VI_WY,          true,   0),
+
+       T14X_LA(64,     150,    MSENC_0,    7 : 0,      MSENCSRD,       false,  0),
+       T14X_LA(16,     150,    MSENC_0,    23 : 16,    MSENCSWR,       false,  0),
+       T14X_LA(14,     150,    EMUCIF_0,   7 : 0,      EMUCIFR,        false,  0),
+       T14X_LA(24,     150,    EMUCIF_0,   23 : 16,    EMUCIFW,        false,  0),
+       T14X_LA(32,     150,    TSEC_0,     7 : 0,      TSECSRD,        false,  0),
+       T14X_LA(32,     150,    TSEC_0,     23 : 16,    TSECSWR,        false,  0),
+
+       T14X_LA(192,    150,    DC_2,       23 : 16,    DISPLAY_T,      false,  0),
+       T14X_LA(125,    150,    VI_0,       23 : 16,    VI_W,           false,  0),
+       T14X_LA(75,     150,    ISP2_0,     7 : 0,      ISP_RA,         false,  0),
+       T14X_LA(150,    150,    ISP2_1,     7 : 0,      ISP_WA,         false,  0),
+       T14X_LA(64,     150,    ISP2_1,     23 : 16,    ISP_WB,         false,  0),
+       T14X_LA(32,     150,    BBMCI_0,    7 : 0,      BBCR,           false,  0),
+       T14X_LA(32,     150,    BBMCI_0,    23 : 16,    BBCW,           false,  0),
+       T14X_LA(16,     150,    BBMCILL_0,  7 : 0,      BBCLLR,         false,  0),
+       T14X_LA(192,    150,    DC_3,       7 : 0,      DISPLAYD,       false,  0),
+
+/* end of list. */
+       T14X_LA(0,      0,      DC_3,   0 : 0,          MAX_ID,         false,  0)
+};
+
+static unsigned int t14x_get_ptsa_rate(unsigned int bw)
+{
+       /* 16 = 2 channels * 2 ddr * 4 bytes */
+       unsigned int base_memory_bw = 16 * T14X_BASE_EMC_FREQ_MHZ;
+       unsigned int rate = 281 * bw / base_memory_bw;
+       if (rate > 255)
+               rate = 255;
+       return rate;
+}
+
+static void t14x_init_ptsa(void)
+{
+       struct clk *emc_clk __attribute__((unused));
+       unsigned long emc_freq __attribute__((unused));
+       unsigned long same_freq __attribute__((unused));
+       unsigned long grant_dec __attribute__((unused));
+       unsigned long ring1_rate __attribute__((unused));
+
+       emc_clk = clk_get(NULL, "emc");
+       la_debug("**** emc clk_rate=%luMHz", clk_get_rate(emc_clk)/1000000);
+
+       emc_freq = clk_get_rate(emc_clk);
+       emc_freq /= 1000000;
+       /* Compute initial value for grant dec */
+       same_freq = readl(T14X_MC_RA(EMEM_ARB_MISC0_0));
+       same_freq = same_freq >> 27 & 1;
+       grant_dec = 256 * (same_freq ? 2 : 1) * emc_freq;
+       if (grant_dec > 511)
+               grant_dec = 511;
+       writel(grant_dec, T14X_MC_RA(PTSA_GRANT_DECREMENT_0));
+
+       writel(0x3d, T14X_MC_RA(DIS_PTSA_MIN_0));
+       writel(0x14, T14X_MC_RA(DIS_PTSA_MAX_0));
+
+       writel(0x3d, T14X_MC_RA(DISB_PTSA_MIN_0));
+       writel(0x14, T14X_MC_RA(DISB_PTSA_MAX_0));
+
+       writel(t14x_get_ptsa_rate(T14X_MAX_CAMERA_BW_MHZ),
+               T14X_MC_RA(VE_PTSA_RATE_0));
+       writel(0x3d, T14X_MC_RA(VE_PTSA_MIN_0));
+       writel(0x14, T14X_MC_RA(VE_PTSA_MAX_0));
+
+       writel(0x01, T14X_MC_RA(RING2_PTSA_RATE_0));
+       writel(0x3f, T14X_MC_RA(RING2_PTSA_MIN_0));
+       writel(0x05, T14X_MC_RA(RING2_PTSA_MAX_0));
+
+       writel(38 * emc_freq / T14X_BASE_EMC_FREQ_MHZ,
+               T14X_MC_RA(MLL_MPCORER_PTSA_RATE_0));
+       writel(0x3f, T14X_MC_RA(MLL_MPCORER_PTSA_MIN_0));
+       writel(0x05, T14X_MC_RA(MLL_MPCORER_PTSA_MAX_0));
+
+       writel(0x01, T14X_MC_RA(SMMU_SMMU_PTSA_RATE_0));
+       writel(0x01, T14X_MC_RA(SMMU_SMMU_PTSA_MIN_0));
+       writel(0x01, T14X_MC_RA(SMMU_SMMU_PTSA_MAX_0));
+
+       writel(0x00, T14X_MC_RA(R0_DIS_PTSA_RATE_0));
+       writel(0x3f, T14X_MC_RA(R0_DIS_PTSA_MIN_0));
+       writel(0x3f, T14X_MC_RA(R0_DIS_PTSA_MAX_0));
+
+       writel(0x00, T14X_MC_RA(R0_DISB_PTSA_RATE_0));
+       writel(0x3f, T14X_MC_RA(R0_DISB_PTSA_MIN_0));
+       writel(0x3f, T14X_MC_RA(R0_DISB_PTSA_MAX_0));
+
+       ring1_rate = readl(T14X_MC_RA(DIS_PTSA_RATE_0)) +
+                    readl(T14X_MC_RA(DISB_PTSA_RATE_0)) +
+                    readl(T14X_MC_RA(VE_PTSA_RATE_0)) +
+                    readl(T14X_MC_RA(RING2_PTSA_RATE_0));
+#if defined(CONFIG_TEGRA_ERRATA_977223)
+       ring1_rate /= 2;
+#endif
+       writel(ring1_rate, T14X_MC_RA(RING1_PTSA_RATE_0));
+       writel(0x36, T14X_MC_RA(RING1_PTSA_MIN_0));
+       writel(0x1f, T14X_MC_RA(RING1_PTSA_MAX_0));
+
+       writel(0x00, T14X_MC_RA(DIS_EXTRA_SNAP_LEVELS_0));
+       writel(0x03, T14X_MC_RA(HEG_EXTRA_SNAP_LEVELS_0));
+}
+
+static void t14x_update_display_ptsa_rate(unsigned int *disp_bw_array)
+{
+       unsigned int num_active = (disp_bw_array[0] != 0) +
+                                 (disp_bw_array[1] != 0) +
+                                 (disp_bw_array[2] != 0);
+       unsigned int num_activeb = (disp_bw_array[5] != 0) +
+                                  (disp_bw_array[6] != 0) +
+                                  (disp_bw_array[7] != 0);
+       unsigned int max_bw = disp_bw_array[0];
+       unsigned int max_bwb = disp_bw_array[5];
+       unsigned int rate_dis;
+       unsigned int rate_disb;
+       unsigned long ring1_rate;
+
+       max_bw = max(disp_bw_array[0], disp_bw_array[1]);
+       max_bw = max(max_bw, disp_bw_array[2]);
+
+       max_bwb = max(disp_bw_array[5], disp_bw_array[6]);
+       max_bwb = max(max_bwb, disp_bw_array[7]);
+
+       rate_dis = t14x_get_ptsa_rate(num_active * max_bw);
+       rate_disb = t14x_get_ptsa_rate(num_activeb * max_bwb);
+
+       writel(rate_dis, T14X_MC_RA(DIS_PTSA_RATE_0));
+       writel(rate_disb, T14X_MC_RA(DISB_PTSA_RATE_0));
+
+
+       ring1_rate = readl(T14X_MC_RA(DIS_PTSA_RATE_0)) +
+                    readl(T14X_MC_RA(DISB_PTSA_RATE_0)) +
+                    readl(T14X_MC_RA(VE_PTSA_RATE_0)) +
+                    readl(T14X_MC_RA(RING2_PTSA_RATE_0));
+       la_debug("max_bw=0x%x, max_bwb=0x%x, num_active=0x%x,"
+               " num_activeb=0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x ",
+               max_bw, max_bwb, num_active, num_activeb, disp_bw_array[0],
+               disp_bw_array[1], disp_bw_array[2], disp_bw_array[5],
+               disp_bw_array[6], disp_bw_array[7]);
+       la_debug("dis=0x%x, disb=0x%x, ve=0x%x, rng2=0x%x, rng1=0x%lx",
+               readl(T14X_MC_RA(DIS_PTSA_RATE_0)),
+               readl(T14X_MC_RA(DISB_PTSA_RATE_0)),
+               readl(T14X_MC_RA(VE_PTSA_RATE_0)),
+               readl(T14X_MC_RA(RING2_PTSA_RATE_0)), ring1_rate);
+#if defined(CONFIG_TEGRA_ERRATA_977223)
+       ring1_rate /= 2;
+#endif
+       writel(ring1_rate, T14X_MC_RA(RING1_PTSA_RATE_0));
+}
+
+void tegra_la_get_t14x_specific(struct la_chip_specific *cs)
+{
+       cs->ns_per_tick = 30;
+       cs->atom_size = 16;
+       cs->la_max_value = T14X_MC_LA_MAX_VALUE;
+       cs->la_info_array = t14x_la_info_array;
+       cs->la_info_array_size = ARRAY_SIZE(t14x_la_info_array);
+       cs->init_ptsa = t14x_init_ptsa;
+       cs->update_display_ptsa_rate = t14x_update_display_ptsa_rate;
+}
diff --git a/arch/arm/mach-tegra/tegra14x_la_priv.h b/arch/arm/mach-tegra/tegra14x_la_priv.h
deleted file mode 100644 (file)
index a364c98..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * arch/arm/mach-tegra/tegra14x_la_priv.h
- *
- * Copyright (C) 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
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _MACH_TEGRA_TEGRA14x_LA_PRIV_H_
-#define _MACH_TEGRA_TEGRA14x_LA_PRIV_H_
-
-#if defined(CONFIG_ARCH_TEGRA_14x_SOC)
-
-#define MC_LA_AVPC_ARM7_0      0x2e4
-#define MC_LA_DC_0             0x2e8
-#define MC_LA_DC_1             0x2ec
-#define MC_LA_DC_2             0x2f0
-#define MC_LA_DCB_0            0x2f4
-#define MC_LA_DCB_1            0x2f8
-#define MC_LA_DCB_2            0x2fc
-#define MC_LA_EPP_0            0x300
-#define MC_LA_EPP_1            0x304
-#define MC_LA_G2_0             0x308
-#define MC_LA_G2_1             0x30c
-#define MC_LA_HC_0             0x310
-#define MC_LA_HC_1             0x314
-#define MC_LA_HDA_0            0x318
-#define MC_LA_ISP_0            0x31C
-#define MC_LA_MPCORE_0         0x320
-#define MC_LA_MPCORELP_0       0x324
-#define MC_LA_MSENC_0          0x328
-#define MC_LA_NV_0             0x334
-#define MC_LA_NV_1             0x338
-#define MC_LA_NV2_0            0x33c
-#define MC_LA_NV2_1            0x340
-#define MC_LA_PPCS_0           0x344
-#define MC_LA_PPCS_1           0x348
-#define MC_LA_PTC_0            0x34c
-
-#define MC_LA_VDE_0            0x354
-#define MC_LA_VDE_1            0x358
-#define MC_LA_VDE_2            0x35c
-#define MC_LA_VDE_3            0x360
-#define MC_LA_VI_0             0x364
-#define MC_LA_VI_1             0x368
-#define MC_LA_VI_2             0x36c
-#define MC_LA_ISP2_0           0x370 /* T14x specific*/
-#define MC_LA_ISP2_1           0x374 /* T14x specific*/
-
-#define MC_LA_EMUCIF_0         0x38c
-#define MC_LA_TSEC_0           0x390
-
-#define MC_LA_BBMCI_0          0x394 /* T14x specific*/
-#define MC_LA_BBMCILL_0                0x398 /* T14x specific*/
-#define MC_LA_DC_3             0x39c /* T14x specific*/
-
-
-/*
- * The rule for getting the fifo_size_in_atoms is:
- * 1.If REORDER_DEPTH exists, use it(default is overridden).
- * 2.Else if (write_client) use RFIFO_DEPTH.
- * 3.Else (read client) use RDFIFO_DEPTH.
- * Multiply the value by 2 for dual channel.
- * Multiply the value by 2 for wide clients.
- * A client is wide, if CMW is larger than MW.
- * Refer to project.h file.
- */
-struct la_client_info la_info_array[] = {
-       LA_INFO(4,      150,    AVPC_ARM7_0, 7 : 0,     AVPC_ARM7R,     false,  0),
-       LA_INFO(8,      150,    AVPC_ARM7_0, 23 : 16,   AVPC_ARM7W,     false,  0),
-       LA_INFO(128,    1050,   DC_0,   7 : 0,          DISPLAY_0A,     true,   0),
-       LA_INFO(128,    1050,   DC_0,   23 : 16,        DISPLAY_0B,     true,   0),
-       LA_INFO(128,    1050,   DC_1,   7 : 0,          DISPLAY_0C,     true,   0),
-       LA_INFO(192,    1050,   DC_2,   7 : 0,          DISPLAY_HC,     false,  0),
-       LA_INFO(128,    1050,   DCB_0,  7 : 0,          DISPLAY_0AB,    true,   0),
-       LA_INFO(128,    1050,   DCB_0,  23 : 16,        DISPLAY_0BB,    true,   0),
-       LA_INFO(128,    1050,   DCB_1,  7 : 0,          DISPLAY_0CB,    true,   0),
-       LA_INFO(192,    1050,   DCB_2,  7 : 0,          DISPLAY_HCB,    false,  0),
-       LA_INFO(32,     150,    EPP_0,  7 : 0,          EPPUP,          false,  0),
-       LA_INFO(32,     150,    EPP_0,  23 : 16,        EPPU,           false,  0),
-       LA_INFO(32,     150,    EPP_1,  7 : 0,          EPPV,           false,  0),
-       LA_INFO(32,     150,    EPP_1,  23 : 16,        EPPY,           false,  0),
-       LA_INFO(128,    150,    G2_0,   7 : 0,          G2PR,           false,  0),
-       LA_INFO(128,    150,    G2_0,   23 : 16,        G2SR,           false,  0),
-       LA_INFO(72,     150,    G2_1,   7 : 0,          G2DR,           false,  0),
-       LA_INFO(128,    150,    G2_1,   23 : 16,        G2DW,           false,  0),
-       LA_INFO(16,     150,    HC_0,   7 : 0,          HOST1X_DMAR,    false,  0),
-       LA_INFO(8,      150,    HC_0,   23 : 16,        HOST1XR,        false,  0),
-       LA_INFO(32,     150,    HC_1,   7 : 0,          HOST1XW,        false,  0),
-       LA_INFO(64,     150,    HDA_0,  7 : 0,          HDAR,           false,  0),
-       LA_INFO(64,     150,    HDA_0,  23 : 16,        HDAW,           false,  0),
-       LA_INFO(64,     150,    ISP_0,  7 : 0,          ISPW,           false,  0),
-       LA_INFO(40,     150,    MPCORE_0,   7 : 0,      MPCORER,        false,  0),
-       LA_INFO(42,     150,    MPCORE_0,   23 : 16,    MPCOREW,        false,  0),
-       LA_INFO(24,     150,    MPCORELP_0, 7 : 0,      MPCORE_LPR,     false,  0),
-       LA_INFO(24,     150,    MPCORELP_0, 23 : 16,    MPCORE_LPW,     false,  0),
-       LA_INFO(160,    150,    NV_0,   7 : 0,          FDCDRD,         false,  0),
-       LA_INFO(256,    150,    NV_0,   23 : 16,        IDXSRD,         false,  0),
-       LA_INFO(256,    150,    NV_1,   7 : 0,          TEXL2SRD,       false,  0),
-       LA_INFO(128,    150,    NV_1,   23 : 16,        FDCDWR,         false,  0),
-       LA_INFO(160,    150,    NV2_0,  7 : 0,          FDCDRD2,        false,  0),
-       LA_INFO(128,    150,    NV2_1,  23 : 16,        FDCDWR2,        false,  0),
-       LA_INFO(4,      150,    PPCS_0, 7 : 0,          PPCS_AHBDMAR,   false,  0),
-       LA_INFO(29,     150,    PPCS_0, 23 : 16,        PPCS_AHBSLVR,   false,  0),
-       LA_INFO(8,      150,    PPCS_1, 7 : 0,          PPCS_AHBDMAW,   false,  0),
-       LA_INFO(8,      150,    PPCS_1, 23 : 16,        PPCS_AHBSLVW,   false,  0),
-       LA_INFO(20,     150,    PTC_0,  7 : 0,          PTCR,           false,  0),
-       LA_INFO(8,      150,    VDE_0,  7 : 0,          VDE_BSEVR,      false,  0),
-       LA_INFO(9,      150,    VDE_0,  23 : 16,        VDE_MBER,       false,  0),
-       LA_INFO(64,     150,    VDE_1,  7 : 0,          VDE_MCER,       false,  0),
-       LA_INFO(32,     150,    VDE_1,  23 : 16,        VDE_TPER,       false,  0),
-       LA_INFO(4,      150,    VDE_2,  7 : 0,          VDE_BSEVW,      false,  0),
-       LA_INFO(4,      150,    VDE_2,  23 : 16,        VDE_DBGW,       false,  0),
-       LA_INFO(8,      150,    VDE_3,  7 : 0,          VDE_MBEW,       false,  0),
-       LA_INFO(32,     150,    VDE_3,  23 : 16,        VDE_TPMW,       false,  0),
-       LA_INFO(200,    1050,   VI_0,   7 : 0,          VI_WSB,         true,   0),
-       LA_INFO(200,    1050,   VI_1,   7 : 0,          VI_WU,          true,   0),
-       LA_INFO(200,    1050,   VI_1,   23 : 16,        VI_WV,          true,   0),
-       LA_INFO(200,    1050,   VI_2,   7 : 0,          VI_WY,          true,   0),
-
-       LA_INFO(64,     150,    MSENC_0,    7 : 0,      MSENCSRD,       false,  0),
-       LA_INFO(16,     150,    MSENC_0,    23 : 16,    MSENCSWR,       false,  0),
-       LA_INFO(14,     150,    EMUCIF_0,   7 : 0,      EMUCIFR,        false,  0),
-       LA_INFO(24,     150,    EMUCIF_0,   23 : 16,    EMUCIFW,        false,  0),
-       LA_INFO(32,     150,    TSEC_0,     7 : 0,      TSECSRD,        false,  0),
-       LA_INFO(32,     150,    TSEC_0,     23 : 16,    TSECSWR,        false,  0),
-
-       LA_INFO(192,    150,    DC_2,       23 : 16,    DISPLAY_T,      false,  0),
-       LA_INFO(125,    150,    VI_0,       23 : 16,    VI_W,           false,  0),
-       LA_INFO(75,     150,    ISP2_0,     7 : 0,      ISP_RA,         false,  0),
-       LA_INFO(150,    150,    ISP2_1,     7 : 0,      ISP_WA,         false,  0),
-       LA_INFO(64,     150,    ISP2_1,     23 : 16,    ISP_WB,         false,  0),
-       LA_INFO(32,     150,    BBMCI_0,    7 : 0,      BBCR,           false,  0),
-       LA_INFO(32,     150,    BBMCI_0,    23 : 16,    BBCW,           false,  0),
-       LA_INFO(16,     150,    BBMCILL_0,  7 : 0,      BBCLLR,         false,  0),
-       LA_INFO(192,    150,    DC_3,       7 : 0,      DISPLAYD,       false,  0),
-
-/* end of list. */
-       LA_INFO(0,      0,      DC_3,   0 : 0,          MAX_ID,         false,  0)
-};
-
-static int ns_per_tick = 30;
-/* MC atom size in bytes */
-static const int normal_atom_size = 16;
-
-#endif
-
-#endif /* _MACH_TEGRA_TEGRA14x_LA_PRIV_H_ */
diff --git a/arch/arm/mach-tegra/tegra3_la.c b/arch/arm/mach-tegra/tegra3_la.c
new file mode 100644 (file)
index 0000000..7d1f04d
--- /dev/null
@@ -0,0 +1,396 @@
+/*
+ * arch/arm/mach-tegra/tegra3_la.c
+ *
+ * Copyright (C) 2012-2013, 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
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/stringify.h>
+#include <linux/clk.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/iomap.h>
+#include <mach/io.h>
+#include <mach/clk.h>
+#include <mach/latency_allowance.h>
+#include "la_priv.h"
+
+#define T3_MC_LA_AFI_0         0x2e0
+#define T3_MC_LA_AVPC_ARM7_0   0x2e4
+#define T3_MC_LA_DC_0          0x2e8
+#define T3_MC_LA_DC_1          0x2ec
+#define T3_MC_LA_DC_2          0x2f0
+#define T3_MC_LA_DCB_0         0x2f4
+#define T3_MC_LA_DCB_1         0x2f8
+#define T3_MC_LA_DCB_2         0x2fc
+#define T3_MC_LA_EPP_0         0x300
+#define T3_MC_LA_EPP_1         0x304
+#define T3_MC_LA_G2_0          0x308
+#define T3_MC_LA_G2_1          0x30c
+#define T3_MC_LA_HC_0          0x310
+#define T3_MC_LA_HC_1          0x314
+#define T3_MC_LA_HDA_0         0x318
+#define T3_MC_LA_ISP_0         0x31C
+#define T3_MC_LA_MPCORE_0              0x320
+#define T3_MC_LA_MPCORELP_0    0x324
+#define T3_MC_LA_MPE_0         0x328
+#define T3_MC_LA_MPE_1         0x32c
+#define T3_MC_LA_MPE_2         0x330
+#define T3_MC_LA_NV_0          0x334
+#define T3_MC_LA_NV_1          0x338
+#define T3_MC_LA_NV2_0         0x33c
+#define T3_MC_LA_NV2_1         0x340
+#define T3_MC_LA_PPCS_0                0x344
+#define T3_MC_LA_PPCS_1                0x348
+#define T3_MC_LA_PTC_0         0x34c
+#define T3_MC_LA_SATA_0                0x350
+#define T3_MC_LA_VDE_0         0x354
+#define T3_MC_LA_VDE_1         0x358
+#define T3_MC_LA_VDE_2         0x35c
+#define T3_MC_LA_VDE_3         0x360
+#define T3_MC_LA_VI_0          0x364
+#define T3_MC_LA_VI_1          0x368
+#define T3_MC_LA_VI_2          0x36c
+
+#define T3_MC_ARB_OVERRIDE             0xe8
+#define GLOBAL_LATENCY_SCALING_ENABLE_BIT 7
+
+#define DS_DISP_MCCIF_DISPLAY0A_HYST (0x481 * 4)
+#define DS_DISP_MCCIF_DISPLAY0B_HYST (0x482 * 4)
+#define DS_DISP_MCCIF_DISPLAY0C_HYST (0x483 * 4)
+#define DS_DISP_MCCIF_DISPLAY1B_HYST (0x484 * 4)
+
+#define DS_DISP_MCCIF_DISPLAY0AB_HYST (0x481 * 4)
+#define DS_DISP_MCCIF_DISPLAY0BB_HYST (0x482 * 4)
+#define DS_DISP_MCCIF_DISPLAY0CB_HYST (0x483 * 4)
+#define DS_DISP_MCCIF_DISPLAY1BB_HYST (0x484 * 4)
+
+#define VI_MCCIF_VIWSB_HYST    (0x9a * 4)
+#define VI_MCCIF_VIWU_HYST     (0x9b * 4)
+#define VI_MCCIF_VIWV_HYST     (0x9c * 4)
+#define VI_MCCIF_VIWY_HYST     (0x9d * 4)
+
+#define VI_TIMEOUT_WOCAL_VI    (0x70 * 4)
+#define VI_RESERVE_3           (0x97 * 4)
+#define VI_RESERVE_4           (0x98 * 4)
+
+/* maximum valid value for latency allowance */
+#define T3_MC_LA_MAX_VALUE             255
+
+#define T3_MC_RA(r) \
+       ((u32)IO_ADDRESS(TEGRA_MC_BASE) + (T3_MC_##r))
+#define T3_RA(r) \
+       ((u32)IO_ADDRESS(TEGRA_MC_BASE) + (T3_MC_LA_##r))
+
+#define T3_LA(f, e, a, r, i, ss, la) \
+{ \
+       .fifo_size_in_atoms = f, \
+       .expiration_in_ns = e, \
+       .reg_addr = T3_RA(a), \
+       .mask = MASK(r), \
+       .shift = SHIFT(r), \
+       .id = ID(i), \
+       .name = __stringify(i), \
+       .scaling_supported = ss, \
+       .init_la = la, \
+}
+
+/*
+ * The consensus for getting the fifo_size_in_atoms is:
+ * 1.If REORDER_DEPTH exists, use it(default is overridden).
+ * 2.Else if (write_client) use RFIFO_DEPTH.
+ * 3.Else (read client) use RDFIFO_DEPTH.
+ * Multiply the value by 2 for wide clients.
+ * A client is wide, if CMW is larger than MW.
+ * Refer to project.h file.
+ */
+struct la_client_info t3_la_info_array[] = {
+       T3_LA(32,       150,    AFI_0,  7 : 0,          AFIR,           false,  0),
+       T3_LA(32,       150,    AFI_0,  23 : 16,        AFIW,           false,  0),
+       T3_LA(2,        150,    AVPC_ARM7_0, 7 : 0,     AVPC_ARM7R,     false,  0),
+       T3_LA(2,        150,    AVPC_ARM7_0, 23 : 16,   AVPC_ARM7W,     false,  0),
+       T3_LA(128,      1050,   DC_0,   7 : 0,          DISPLAY_0A,     true,   0),
+       T3_LA(64,       1050,   DC_0,   23 : 16,        DISPLAY_0B,     true,   0),
+       T3_LA(128,      1050,   DC_1,   7 : 0,          DISPLAY_0C,     true,   0),
+       T3_LA(64,       1050,   DC_1,   23 : 16,        DISPLAY_1B,     true,   0),
+       T3_LA(2,        1050,   DC_2,   7 : 0,          DISPLAY_HC,     false,  0),
+       T3_LA(128,      1050,   DCB_0,  7 : 0,          DISPLAY_0AB,    true,   0),
+       T3_LA(64,       1050,   DCB_0,  23 : 16,        DISPLAY_0BB,    true,   0),
+       T3_LA(128,      1050,   DCB_1,  7 : 0,          DISPLAY_0CB,    true,   0),
+       T3_LA(64,       1050,   DCB_1,  23 : 16,        DISPLAY_1BB,    true,   0),
+       T3_LA(2,        1050,   DCB_2,  7 : 0,          DISPLAY_HCB,    false,  0),
+       T3_LA(8,        150,    EPP_0,  7 : 0,          EPPUP,          false,  0),
+       T3_LA(64,       150,    EPP_0,  23 : 16,        EPPU,           false,  0),
+       T3_LA(64,       150,    EPP_1,  7 : 0,          EPPV,           false,  0),
+       T3_LA(64,       150,    EPP_1,  23 : 16,        EPPY,           false,  0),
+       T3_LA(64,       150,    G2_0,   7 : 0,          G2PR,           false,  0),
+       T3_LA(64,       150,    G2_0,   23 : 16,        G2SR,           false,  0),
+       T3_LA(48,       150,    G2_1,   7 : 0,          G2DR,           false,  0),
+       T3_LA(128,      150,    G2_1,   23 : 16,        G2DW,           false,  0),
+       T3_LA(16,       150,    HC_0,   7 : 0,          HOST1X_DMAR,    false,  0),
+       T3_LA(8,        150,    HC_0,   23 : 16,        HOST1XR,        false,  0),
+       T3_LA(32,       150,    HC_1,   7 : 0,          HOST1XW,        false,  0),
+       T3_LA(16,       150,    HDA_0,  7 : 0,          HDAR,           false,  0),
+       T3_LA(16,       150,    HDA_0,  23 : 16,        HDAW,           false,  0),
+       T3_LA(64,       150,    ISP_0,  7 : 0,          ISPW,           false,  0),
+       T3_LA(14,       150,    MPCORE_0, 7 : 0,        MPCORER,        false,  0),
+       T3_LA(24,       150,    MPCORE_0, 23 : 16,      MPCOREW,        false,  0),
+       T3_LA(14,       150,    MPCORELP_0, 7 : 0,      MPCORE_LPR,     false,  0),
+       T3_LA(24,       150,    MPCORELP_0, 23 : 16,    MPCORE_LPW,     false,  0),
+       T3_LA(8,        150,    MPE_0,  7 : 0,          MPE_UNIFBR,     false,  0),
+       T3_LA(2,        150,    MPE_0,  23 : 16,        MPE_IPRED,      false,  0),
+       T3_LA(64,       150,    MPE_1,  7 : 0,          MPE_AMEMRD,     false,  0),
+       T3_LA(8,        150,    MPE_1,  23 : 16,        MPE_CSRD,       false,  0),
+       T3_LA(8,        150,    MPE_2,  7 : 0,          MPE_UNIFBW,     false,  0),
+       T3_LA(8,        150,    MPE_2,  23 : 16,        MPE_CSWR,       false,  0),
+       T3_LA(96,       150,    NV_0,   7 : 0,          FDCDRD,         false,  0),
+       T3_LA(64,       150,    NV_0,   23 : 16,        IDXSRD,         false,  0),
+       T3_LA(64,       150,    NV_1,   7 : 0,          TEXSRD,         false,  0),
+       T3_LA(96,       150,    NV_1,   23 : 16,        FDCDWR,         false,  0),
+       T3_LA(96,       150,    NV2_0,  7 : 0,          FDCDRD2,        false,  0),
+       T3_LA(64,       150,    NV2_0,  23 : 16,        IDXSRD2,        false,  0),
+       T3_LA(64,       150,    NV2_1,  7 : 0,          TEXSRD2,        false,  0),
+       T3_LA(96,       150,    NV2_1,  23 : 16,        FDCDWR2,        false,  0),
+       T3_LA(2,        150,    PPCS_0, 7 : 0,          PPCS_AHBDMAR,   false,  0),
+       T3_LA(8,        150,    PPCS_0, 23 : 16,        PPCS_AHBSLVR,   false,  0),
+       T3_LA(2,        150,    PPCS_1, 7 : 0,          PPCS_AHBDMAW,   false,  0),
+       T3_LA(4,        150,    PPCS_1, 23 : 16,        PPCS_AHBSLVW,   false,  0),
+       T3_LA(2,        150,    PTC_0,  7 : 0,          PTCR,           false,  0),
+       T3_LA(32,       150,    SATA_0, 7 : 0,          SATAR,          false,  0),
+       T3_LA(32,       150,    SATA_0, 23 : 16,        SATAW,          false,  0),
+       T3_LA(8,        150,    VDE_0,  7 : 0,          VDE_BSEVR,      false,  0),
+       T3_LA(4,        150,    VDE_0,  23 : 16,        VDE_MBER,       false,  0),
+       T3_LA(16,       150,    VDE_1,  7 : 0,          VDE_MCER,       false,  0),
+       T3_LA(16,       150,    VDE_1,  23 : 16,        VDE_TPER,       false,  0),
+       T3_LA(4,        150,    VDE_2,  7 : 0,          VDE_BSEVW,      false,  0),
+       T3_LA(16,       150,    VDE_2,  23 : 16,        VDE_DBGW,       false,  0),
+       T3_LA(2,        150,    VDE_3,  7 : 0,          VDE_MBEW,       false,  0),
+       T3_LA(16,       150,    VDE_3,  23 : 16,        VDE_TPMW,       false,  0),
+       T3_LA(8,        1050,   VI_0,   7 : 0,          VI_RUV,         false,  0),
+       T3_LA(64,       1050,   VI_0,   23 : 16,        VI_WSB,         true,   0),
+       T3_LA(64,       1050,   VI_1,   7 : 0,          VI_WU,          true,   0),
+       T3_LA(64,       1050,   VI_1,   23 : 16,        VI_WV,          true,   0),
+       T3_LA(64,       1050,   VI_2,   7 : 0,          VI_WY,          true,   0),
+
+/* end of list. */
+       T3_LA(0,        0,      AFI_0,  0 : 0,          MAX_ID,         false,  0)
+};
+
+#define DISP1_RA(r) \
+       ((u32)IO_ADDRESS(TEGRA_DISPLAY_BASE) + DS_DISP_MCCIF_##r##_HYST)
+#define DISP2_RA(r) \
+       ((u32)IO_ADDRESS(TEGRA_DISPLAY2_BASE) + DS_DISP_MCCIF_##r##_HYST)
+
+#define DISP_SCALING_REG_INFO(id, r, ra) \
+       { \
+               ID(id), \
+               ra(r), MASK(15 : 8), SHIFT(15 : 8), \
+               ra(r), MASK(23 : 16), SHIFT(15 : 8), \
+               ra(r), MASK(7 : 0), SHIFT(15 : 8) \
+       }
+
+struct la_scaling_reg_info disp_info[] = {
+       DISP_SCALING_REG_INFO(DISPLAY_0A, DISPLAY0A, DISP1_RA),
+       DISP_SCALING_REG_INFO(DISPLAY_0B, DISPLAY0B, DISP1_RA),
+       DISP_SCALING_REG_INFO(DISPLAY_0C, DISPLAY0C, DISP1_RA),
+       DISP_SCALING_REG_INFO(DISPLAY_1B, DISPLAY1B, DISP1_RA),
+       DISP_SCALING_REG_INFO(MAX_ID,     DISPLAY1B, DISP1_RA), /*dummy entry*/
+       DISP_SCALING_REG_INFO(DISPLAY_0AB, DISPLAY0AB, DISP2_RA),
+       DISP_SCALING_REG_INFO(DISPLAY_0BB, DISPLAY0BB, DISP2_RA),
+       DISP_SCALING_REG_INFO(DISPLAY_0CB, DISPLAY0CB, DISP2_RA),
+       DISP_SCALING_REG_INFO(DISPLAY_1BB, DISPLAY1BB, DISP2_RA),
+};
+
+#define VI_TH_RA(r) \
+       ((u32)IO_ADDRESS(TEGRA_VI_BASE) + VI_MCCIF_##r##_HYST)
+#define VI_TM_RA(r) \
+       ((u32)IO_ADDRESS(TEGRA_VI_BASE) + VI_TIMEOUT_WOCAL_VI)
+#define VI_TL_RA(r) \
+       ((u32)IO_ADDRESS(TEGRA_VI_BASE) + VI_RESERVE_##r)
+
+struct la_scaling_reg_info vi_info[] = {
+       {
+               ID(VI_WSB),
+               VI_TL_RA(4), MASK(7 : 0), SHIFT(7 : 0),
+               VI_TM_RA(0), MASK(7 : 0), SHIFT(7 : 0),
+               VI_TH_RA(VIWSB), MASK(7 : 0), SHIFT(7 : 0)
+       },
+       {
+               ID(VI_WU),
+               VI_TL_RA(3), MASK(15 : 8), SHIFT(15 : 8),
+               VI_TM_RA(0), MASK(15 : 8), SHIFT(15 : 8),
+               VI_TH_RA(VIWU), MASK(7 : 0), SHIFT(7 : 0)
+       },
+       {
+               ID(VI_WV),
+               VI_TL_RA(3), MASK(7 : 0), SHIFT(7 : 0),
+               VI_TM_RA(0), MASK(23 : 16), SHIFT(23 : 16),
+               VI_TH_RA(VIWV), MASK(7 : 0), SHIFT(7 : 0)
+       },
+       {
+               ID(VI_WY),
+               VI_TL_RA(4), MASK(15 : 8), SHIFT(15 : 8),
+               VI_TM_RA(0), MASK(31 : 24), SHIFT(31 : 24),
+               VI_TH_RA(VIWY), MASK(7 : 0), SHIFT(7 : 0)
+       }
+};
+
+static struct la_chip_specific *cs;
+
+static void set_thresholds(struct la_scaling_reg_info *info,
+                           enum tegra_la_id id)
+{
+       unsigned long reg_read;
+       unsigned long reg_write;
+       unsigned int thresh_low;
+       unsigned int thresh_mid;
+       unsigned int thresh_high;
+       int la_set;
+       int idx = cs->id_to_index[id];
+
+       reg_read = readl(cs->la_info_array[idx].reg_addr);
+       la_set = (reg_read & cs->la_info_array[idx].mask) >>
+                cs->la_info_array[idx].shift;
+       /* la should be set before enabling scaling. */
+       BUG_ON(la_set != cs->scaling_info[idx].la_set);
+
+       thresh_low = (cs->scaling_info[idx].threshold_low * la_set) / 100;
+       thresh_mid = (cs->scaling_info[idx].threshold_mid * la_set) / 100;
+       thresh_high = (cs->scaling_info[idx].threshold_high * la_set) / 100;
+       la_debug("%s: la_set=%d, thresh_low=%d(%d%%), thresh_mid=%d(%d%%),"
+               " thresh_high=%d(%d%%) ", __func__, la_set,
+               thresh_low, cs->scaling_info[idx].threshold_low,
+               thresh_mid, cs->scaling_info[idx].threshold_mid,
+               thresh_high, cs->scaling_info[idx].threshold_high);
+
+       reg_read = readl(info->tl_reg_addr);
+       reg_write = (reg_read & ~info->tl_mask) |
+               (thresh_low << info->tl_shift);
+       writel(reg_write, info->tl_reg_addr);
+       la_debug("reg_addr=0x%x, read=0x%x, write=0x%x",
+               (u32)info->tl_reg_addr, (u32)reg_read, (u32)reg_write);
+
+       reg_read = readl(info->tm_reg_addr);
+       reg_write = (reg_read & ~info->tm_mask) |
+               (thresh_mid << info->tm_shift);
+       writel(reg_write, info->tm_reg_addr);
+       la_debug("reg_addr=0x%x, read=0x%x, write=0x%x",
+               (u32)info->tm_reg_addr, (u32)reg_read, (u32)reg_write);
+
+       reg_read = readl(info->th_reg_addr);
+       reg_write = (reg_read & ~info->th_mask) |
+               (thresh_high << info->th_shift);
+       writel(reg_write, info->th_reg_addr);
+       la_debug("reg_addr=0x%x, read=0x%x, write=0x%x",
+               (u32)info->th_reg_addr, (u32)reg_read, (u32)reg_write);
+}
+
+static void set_disp_latency_thresholds(enum tegra_la_id id)
+{
+       set_thresholds(&disp_info[id - ID(DISPLAY_0A)], id);
+}
+
+static void set_vi_latency_thresholds(enum tegra_la_id id)
+{
+       set_thresholds(&vi_info[id - ID(VI_WSB)], id);
+}
+
+/* Thresholds for scaling are specified in % of fifo freeness.
+ * If threshold_low is specified as 20%, it means when the fifo free
+ * between 0 to 20%, use la as programmed_la.
+ * If threshold_mid is specified as 50%, it means when the fifo free
+ * between 20 to 50%, use la as programmed_la/2 .
+ * If threshold_high is specified as 80%, it means when the fifo free
+ * between 50 to 80%, use la as programmed_la/4.
+ * When the fifo is free between 80 to 100%, use la as 0(highest priority).
+ */
+int t3_enable_la_scaling(enum tegra_la_id id,
+                                   unsigned int threshold_low,
+                                   unsigned int threshold_mid,
+                                   unsigned int threshold_high)
+{
+       unsigned long reg;
+       void __iomem *scaling_enable_reg =
+                               (void __iomem *)(T3_MC_RA(ARB_OVERRIDE));
+       int idx = cs->id_to_index[id];
+
+       VALIDATE_ID(id, cs);
+       VALIDATE_THRESHOLDS(threshold_low, threshold_mid, threshold_high);
+
+       if (cs->la_info_array[idx].scaling_supported == false)
+               goto exit;
+
+       spin_lock(&cs->lock);
+
+       la_debug("\n%s: id=%d, tl=%d, tm=%d, th=%d", __func__,
+               id, threshold_low, threshold_mid, threshold_high);
+       cs->scaling_info[idx].threshold_low = threshold_low;
+       cs->scaling_info[idx].threshold_mid = threshold_mid;
+       cs->scaling_info[idx].threshold_high = threshold_high;
+       cs->scaling_info[idx].scaling_ref_count++;
+
+       if (id >= ID(DISPLAY_0A) && id <= ID(DISPLAY_1BB))
+               set_disp_latency_thresholds(id);
+       else if (id >= ID(VI_WSB) && id <= ID(VI_WY))
+               set_vi_latency_thresholds(id);
+       if (!cs->la_scaling_enable_count++) {
+               reg = readl(scaling_enable_reg);
+               reg |= (1 << GLOBAL_LATENCY_SCALING_ENABLE_BIT);
+               writel(reg,  scaling_enable_reg);
+               la_debug("enabled scaling.");
+       }
+       spin_unlock(&cs->lock);
+exit:
+       return 0;
+}
+
+void t3_disable_la_scaling(enum tegra_la_id id)
+{
+       unsigned long reg;
+       void __iomem *scaling_enable_reg =
+                               (void __iomem *)(T3_MC_RA(ARB_OVERRIDE));
+       int idx;
+
+       BUG_ON(id >= TEGRA_LA_MAX_ID);
+       idx = cs->id_to_index[id];
+       BUG_ON(cs->la_info_array[idx].id != id);
+
+       if (cs->la_info_array[idx].scaling_supported == false)
+               return;
+       spin_lock(&cs->lock);
+       la_debug("\n%s: id=%d", __func__, id);
+       cs->scaling_info[idx].scaling_ref_count--;
+       BUG_ON(cs->scaling_info[idx].scaling_ref_count < 0);
+
+       if (!--cs->la_scaling_enable_count) {
+               reg = readl(scaling_enable_reg);
+               reg = reg & ~(1 << GLOBAL_LATENCY_SCALING_ENABLE_BIT);
+               writel(reg, scaling_enable_reg);
+               la_debug("disabled scaling.");
+       }
+       spin_unlock(&cs->lock);
+}
+
+void tegra_la_get_t3_specific(struct la_chip_specific *cs_la)
+{
+       cs_la->ns_per_tick = 30;
+       cs_la->atom_size = 16;
+       cs_la->la_max_value = T3_MC_LA_MAX_VALUE;
+       cs_la->la_info_array = t3_la_info_array;
+       cs_la->la_info_array_size = ARRAY_SIZE(t3_la_info_array);
+       cs_la->enable_la_scaling = t3_enable_la_scaling;
+       cs_la->disable_la_scaling = t3_disable_la_scaling;
+       cs = cs_la;
+}
diff --git a/arch/arm/mach-tegra/tegra3_la_priv.h b/arch/arm/mach-tegra/tegra3_la_priv.h
deleted file mode 100644 (file)
index 77fe1cb..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * arch/arm/mach-tegra/tegra3_la_priv.h
- *
- * Copyright (C) 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
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _MACH_TEGRA_TEGRA3_LA_PRIV_H_
-#define _MACH_TEGRA_TEGRA3_LA_PRIV_H_
-
-#if defined(CONFIG_ARCH_TEGRA_3x_SOC)
-
-#define MC_LA_AFI_0            0x2e0
-#define MC_LA_AVPC_ARM7_0      0x2e4
-#define MC_LA_DC_0             0x2e8
-#define MC_LA_DC_1             0x2ec
-#define MC_LA_DC_2             0x2f0
-#define MC_LA_DCB_0            0x2f4
-#define MC_LA_DCB_1            0x2f8
-#define MC_LA_DCB_2            0x2fc
-#define MC_LA_EPP_0            0x300
-#define MC_LA_EPP_1            0x304
-#define MC_LA_G2_0             0x308
-#define MC_LA_G2_1             0x30c
-#define MC_LA_HC_0             0x310
-#define MC_LA_HC_1             0x314
-#define MC_LA_HDA_0            0x318
-#define MC_LA_ISP_0            0x31C
-#define MC_LA_MPCORE_0         0x320
-#define MC_LA_MPCORELP_0       0x324
-#define MC_LA_MPE_0            0x328
-#define MC_LA_MPE_1            0x32c
-#define MC_LA_MPE_2            0x330
-#define MC_LA_NV_0             0x334
-#define MC_LA_NV_1             0x338
-#define MC_LA_NV2_0            0x33c
-#define MC_LA_NV2_1            0x340
-#define MC_LA_PPCS_0           0x344
-#define MC_LA_PPCS_1           0x348
-#define MC_LA_PTC_0            0x34c
-#define MC_LA_SATA_0           0x350
-#define MC_LA_VDE_0            0x354
-#define MC_LA_VDE_1            0x358
-#define MC_LA_VDE_2            0x35c
-#define MC_LA_VDE_3            0x360
-#define MC_LA_VI_0             0x364
-#define MC_LA_VI_1             0x368
-#define MC_LA_VI_2             0x36c
-
-#define MC_ARB_OVERRIDE                0xe8
-#define GLOBAL_LATENCY_SCALING_ENABLE_BIT 7
-
-#define DS_DISP_MCCIF_DISPLAY0A_HYST (0x481 * 4)
-#define DS_DISP_MCCIF_DISPLAY0B_HYST (0x482 * 4)
-#define DS_DISP_MCCIF_DISPLAY0C_HYST (0x483 * 4)
-#define DS_DISP_MCCIF_DISPLAY1B_HYST (0x484 * 4)
-
-#define DS_DISP_MCCIF_DISPLAY0AB_HYST (0x481 * 4)
-#define DS_DISP_MCCIF_DISPLAY0BB_HYST (0x482 * 4)
-#define DS_DISP_MCCIF_DISPLAY0CB_HYST (0x483 * 4)
-#define DS_DISP_MCCIF_DISPLAY1BB_HYST (0x484 * 4)
-
-#define VI_MCCIF_VIWSB_HYST    (0x9a * 4)
-#define VI_MCCIF_VIWU_HYST     (0x9b * 4)
-#define VI_MCCIF_VIWV_HYST     (0x9c * 4)
-#define VI_MCCIF_VIWY_HYST     (0x9d * 4)
-
-#define VI_TIMEOUT_WOCAL_VI    (0x70 * 4)
-#define VI_RESERVE_3           (0x97 * 4)
-#define VI_RESERVE_4           (0x98 * 4)
-
-/*
- * The rule for getting the fifo_size_in_atoms is:
- * 1.If REORDER_DEPTH exists, use it(default is overridden).
- * 2.Else if (write_client) use RFIFO_DEPTH.
- * 3.Else (read client) use RDFIFO_DEPTH.
- * Multiply the value by 2 for wide clients.
- * A client is wide, if CMW is larger than MW.
- * Refer to project.h file.
- */
-struct la_client_info la_info_array[] = {
-       LA_INFO(32,     150,    AFI_0,  7 : 0,          AFIR,           false,  0),
-       LA_INFO(32,     150,    AFI_0,  23 : 16,        AFIW,           false,  0),
-       LA_INFO(2,      150,    AVPC_ARM7_0, 7 : 0,     AVPC_ARM7R,     false,  0),
-       LA_INFO(2,      150,    AVPC_ARM7_0, 23 : 16,   AVPC_ARM7W,     false,  0),
-       LA_INFO(128,    1050,   DC_0,   7 : 0,          DISPLAY_0A,     true,   0),
-       LA_INFO(64,     1050,   DC_0,   23 : 16,        DISPLAY_0B,     true,   0),
-       LA_INFO(128,    1050,   DC_1,   7 : 0,          DISPLAY_0C,     true,   0),
-       LA_INFO(64,     1050,   DC_1,   23 : 16,        DISPLAY_1B,     true,   0),
-       LA_INFO(2,      1050,   DC_2,   7 : 0,          DISPLAY_HC,     false,  0),
-       LA_INFO(128,    1050,   DCB_0,  7 : 0,          DISPLAY_0AB,    true,   0),
-       LA_INFO(64,     1050,   DCB_0,  23 : 16,        DISPLAY_0BB,    true,   0),
-       LA_INFO(128,    1050,   DCB_1,  7 : 0,          DISPLAY_0CB,    true,   0),
-       LA_INFO(64,     1050,   DCB_1,  23 : 16,        DISPLAY_1BB,    true,   0),
-       LA_INFO(2,      1050,   DCB_2,  7 : 0,          DISPLAY_HCB,    false,  0),
-       LA_INFO(8,      150,    EPP_0,  7 : 0,          EPPUP,          false,  0),
-       LA_INFO(64,     150,    EPP_0,  23 : 16,        EPPU,           false,  0),
-       LA_INFO(64,     150,    EPP_1,  7 : 0,          EPPV,           false,  0),
-       LA_INFO(64,     150,    EPP_1,  23 : 16,        EPPY,           false,  0),
-       LA_INFO(64,     150,    G2_0,   7 : 0,          G2PR,           false,  0),
-       LA_INFO(64,     150,    G2_0,   23 : 16,        G2SR,           false,  0),
-       LA_INFO(48,     150,    G2_1,   7 : 0,          G2DR,           false,  0),
-       LA_INFO(128,    150,    G2_1,   23 : 16,        G2DW,           false,  0),
-       LA_INFO(16,     150,    HC_0,   7 : 0,          HOST1X_DMAR,    false,  0),
-       LA_INFO(8,      150,    HC_0,   23 : 16,        HOST1XR,        false,  0),
-       LA_INFO(32,     150,    HC_1,   7 : 0,          HOST1XW,        false,  0),
-       LA_INFO(16,     150,    HDA_0,  7 : 0,          HDAR,           false,  0),
-       LA_INFO(16,     150,    HDA_0,  23 : 16,        HDAW,           false,  0),
-       LA_INFO(64,     150,    ISP_0,  7 : 0,          ISPW,           false,  0),
-       LA_INFO(14,     150,    MPCORE_0, 7 : 0,        MPCORER,        false,  0),
-       LA_INFO(24,     150,    MPCORE_0, 23 : 16,      MPCOREW,        false,  0),
-       LA_INFO(14,     150,    MPCORELP_0, 7 : 0,      MPCORE_LPR,     false,  0),
-       LA_INFO(24,     150,    MPCORELP_0, 23 : 16,    MPCORE_LPW,     false,  0),
-       LA_INFO(8,      150,    MPE_0,  7 : 0,          MPE_UNIFBR,     false,  0),
-       LA_INFO(2,      150,    MPE_0,  23 : 16,        MPE_IPRED,      false,  0),
-       LA_INFO(64,     150,    MPE_1,  7 : 0,          MPE_AMEMRD,     false,  0),
-       LA_INFO(8,      150,    MPE_1,  23 : 16,        MPE_CSRD,       false,  0),
-       LA_INFO(8,      150,    MPE_2,  7 : 0,          MPE_UNIFBW,     false,  0),
-       LA_INFO(8,      150,    MPE_2,  23 : 16,        MPE_CSWR,       false,  0),
-       LA_INFO(96,     150,    NV_0,   7 : 0,          FDCDRD,         false,  0),
-       LA_INFO(64,     150,    NV_0,   23 : 16,        IDXSRD,         false,  0),
-       LA_INFO(64,     150,    NV_1,   7 : 0,          TEXSRD,         false,  0),
-       LA_INFO(96,     150,    NV_1,   23 : 16,        FDCDWR,         false,  0),
-       LA_INFO(96,     150,    NV2_0,  7 : 0,          FDCDRD2,        false,  0),
-       LA_INFO(64,     150,    NV2_0,  23 : 16,        IDXSRD2,        false,  0),
-       LA_INFO(64,     150,    NV2_1,  7 : 0,          TEXSRD2,        false,  0),
-       LA_INFO(96,     150,    NV2_1,  23 : 16,        FDCDWR2,        false,  0),
-       LA_INFO(2,      150,    PPCS_0, 7 : 0,          PPCS_AHBDMAR,   false,  0),
-       LA_INFO(8,      150,    PPCS_0, 23 : 16,        PPCS_AHBSLVR,   false,  0),
-       LA_INFO(2,      150,    PPCS_1, 7 : 0,          PPCS_AHBDMAW,   false,  0),
-       LA_INFO(4,      150,    PPCS_1, 23 : 16,        PPCS_AHBSLVW,   false,  0),
-       LA_INFO(2,      150,    PTC_0,  7 : 0,          PTCR,           false,  0),
-       LA_INFO(32,     150,    SATA_0, 7 : 0,          SATAR,          false,  0),
-       LA_INFO(32,     150,    SATA_0, 23 : 16,        SATAW,          false,  0),
-       LA_INFO(8,      150,    VDE_0,  7 : 0,          VDE_BSEVR,      false,  0),
-       LA_INFO(4,      150,    VDE_0,  23 : 16,        VDE_MBER,       false,  0),
-       LA_INFO(16,     150,    VDE_1,  7 : 0,          VDE_MCER,       false,  0),
-       LA_INFO(16,     150,    VDE_1,  23 : 16,        VDE_TPER,       false,  0),
-       LA_INFO(4,      150,    VDE_2,  7 : 0,          VDE_BSEVW,      false,  0),
-       LA_INFO(16,     150,    VDE_2,  23 : 16,        VDE_DBGW,       false,  0),
-       LA_INFO(2,      150,    VDE_3,  7 : 0,          VDE_MBEW,       false,  0),
-       LA_INFO(16,     150,    VDE_3,  23 : 16,        VDE_TPMW,       false,  0),
-       LA_INFO(8,      1050,   VI_0,   7 : 0,          VI_RUV,         false,  0),
-       LA_INFO(64,     1050,   VI_0,   23 : 16,        VI_WSB,         true,   0),
-       LA_INFO(64,     1050,   VI_1,   7 : 0,          VI_WU,          true,   0),
-       LA_INFO(64,     1050,   VI_1,   23 : 16,        VI_WV,          true,   0),
-       LA_INFO(64,     1050,   VI_2,   7 : 0,          VI_WY,          true,   0),
-
-/* end of list. */
-       LA_INFO(0,      0,      AFI_0,  0 : 0,          MAX_ID,         false,  0)
-};
-
-#define DISP1_RA(r) \
-       ((u32)IO_ADDRESS(TEGRA_DISPLAY_BASE) + DS_DISP_MCCIF_##r##_HYST)
-#define DISP2_RA(r) \
-       ((u32)IO_ADDRESS(TEGRA_DISPLAY2_BASE) + DS_DISP_MCCIF_##r##_HYST)
-
-#define DISP_SCALING_REG_INFO(id, r, ra) \
-       { \
-               ID(id), \
-               ra(r), MASK(15 : 8), SHIFT(15 : 8), \
-               ra(r), MASK(23 : 16), SHIFT(15 : 8), \
-               ra(r), MASK(7 : 0), SHIFT(15 : 8) \
-       }
-
-struct la_scaling_reg_info disp_info[] = {
-       DISP_SCALING_REG_INFO(DISPLAY_0A, DISPLAY0A, DISP1_RA),
-       DISP_SCALING_REG_INFO(DISPLAY_0B, DISPLAY0B, DISP1_RA),
-       DISP_SCALING_REG_INFO(DISPLAY_0C, DISPLAY0C, DISP1_RA),
-       DISP_SCALING_REG_INFO(DISPLAY_1B, DISPLAY1B, DISP1_RA),
-       DISP_SCALING_REG_INFO(MAX_ID,     DISPLAY1B, DISP1_RA), /*dummy entry*/
-       DISP_SCALING_REG_INFO(DISPLAY_0AB, DISPLAY0AB, DISP2_RA),
-       DISP_SCALING_REG_INFO(DISPLAY_0BB, DISPLAY0BB, DISP2_RA),
-       DISP_SCALING_REG_INFO(DISPLAY_0CB, DISPLAY0CB, DISP2_RA),
-       DISP_SCALING_REG_INFO(DISPLAY_1BB, DISPLAY1BB, DISP2_RA),
-};
-
-#define VI_TH_RA(r) \
-       ((u32)IO_ADDRESS(TEGRA_VI_BASE) + VI_MCCIF_##r##_HYST)
-#define VI_TM_RA(r) \
-       ((u32)IO_ADDRESS(TEGRA_VI_BASE) + VI_TIMEOUT_WOCAL_VI)
-#define VI_TL_RA(r) \
-       ((u32)IO_ADDRESS(TEGRA_VI_BASE) + VI_RESERVE_##r)
-
-struct la_scaling_reg_info vi_info[] = {
-       {
-               ID(VI_WSB),
-               VI_TL_RA(4), MASK(7 : 0), SHIFT(7 : 0),
-               VI_TM_RA(0), MASK(7 : 0), SHIFT(7 : 0),
-               VI_TH_RA(VIWSB), MASK(7 : 0), SHIFT(7 : 0)
-       },
-       {
-               ID(VI_WU),
-               VI_TL_RA(3), MASK(15 : 8), SHIFT(15 : 8),
-               VI_TM_RA(0), MASK(15 : 8), SHIFT(15 : 8),
-               VI_TH_RA(VIWU), MASK(7 : 0), SHIFT(7 : 0)
-       },
-       {
-               ID(VI_WV),
-               VI_TL_RA(3), MASK(7 : 0), SHIFT(7 : 0),
-               VI_TM_RA(0), MASK(23 : 16), SHIFT(23 : 16),
-               VI_TH_RA(VIWV), MASK(7 : 0), SHIFT(7 : 0)
-       },
-       {
-               ID(VI_WY),
-               VI_TL_RA(4), MASK(15 : 8), SHIFT(15 : 8),
-               VI_TM_RA(0), MASK(31 : 24), SHIFT(31 : 24),
-               VI_TH_RA(VIWY), MASK(7 : 0), SHIFT(7 : 0)
-       }
-};
-
-static int ns_per_tick = 30;
-/* Tegra3 MC atom size in bytes */
-static const int normal_atom_size = 16;
-#endif
-
-#endif /* _MACH_TEGRA_TEGRA3_LA_PRIV_H_ */