ARM: tegra11: clock: Modify dqs preset operation
Alex Frid [Sun, 16 Sep 2012 06:44:30 +0000 (23:44 -0700)]
Modified dqs preset operation during EMC clock change to work on
separate settings for EMC channel 0 and 1.

Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/133065
(cherry picked from commit b487cbda920e8eaf783d3b8ea0fb7a9dba0a5f4f)

Change-Id: Ia802a3194495df784a198859f33ee6ea004af6bd
Signed-off-by: Bharat Nihalani <bnihalani@nvidia.com>
Reviewed-on: http://git-master/r/146247

arch/arm/mach-tegra/tegra11_emc.c

index 30db73b..db6f58a 100644 (file)
@@ -242,6 +242,13 @@ enum {
 };
 #undef DEFINE_REG
 
+#define DEFINE_REG(base, reg)  reg##_TRIM_INDEX
+enum {
+       EMC_TRIMMERS_REG_LIST
+};
+#undef DEFINE_REG
+
+
 struct emc_sel {
        struct clk      *input;
        u32             value;
@@ -283,6 +290,14 @@ static inline void emc_writel(u32 val, unsigned long addr)
 {
        writel(val, (u32)emc_base + addr);
 }
+static inline void emc0_writel(u32 val, unsigned long addr)
+{
+       writel(val, (u32)emc0_base + addr);
+}
+static inline void emc1_writel(u32 val, unsigned long addr)
+{
+       writel(val, (u32)emc1_base + addr);
+}
 static inline u32 emc_readl(unsigned long addr)
 {
        return readl((u32)emc_base + addr);
@@ -363,7 +378,6 @@ static inline void auto_cal_disable(void)
 static inline bool dqs_preset(const struct tegra11_emc_table *next_timing,
                              const struct tegra11_emc_table *last_timing)
 {
-#ifdef TEGRA_EMC_DQS_PRESET
        bool ret = false;
 
 #define DQS_SET(reg, bit)                                                    \
@@ -378,13 +392,24 @@ static inline bool dqs_preset(const struct tegra11_emc_table *next_timing,
                }                                                             \
        } while (0)
 
+
+#define DQS_SET_TRIM(reg, bit, ch)                                            \
+       do {                                                                   \
+               if ((next_timing->emc_trimmers_##ch[EMC_##reg##_TRIM_INDEX]    \
+                    & EMC_##reg##_##bit##_ENABLE) &&                          \
+                   (!(last_timing->emc_trimmers_##ch[EMC_##reg##_TRIM_INDEX]  \
+                      & EMC_##reg##_##bit##_ENABLE)))   {                     \
+                       emc##ch##_writel(last_timing->emc_trimmers_##ch[EMC_##reg##_TRIM_INDEX] \
+                                  | EMC_##reg##_##bit##_ENABLE, EMC_##reg);   \
+                       ret = true;                                            \
+               }                                                              \
+       } while (0)
+
        DQS_SET(XM2DQSPADCTRL2, VREF);
-       DQS_SET(XM2DQSPADCTRL3, VREF);
+       DQS_SET_TRIM(XM2DQSPADCTRL3, VREF, 0);
+       DQS_SET_TRIM(XM2DQSPADCTRL3, VREF, 1);
 
        return ret;
-#else
-       return true;
-#endif
 }
 
 static inline void overwrite_mrs_wait_cnt(
@@ -626,14 +651,20 @@ static inline void emc_get_timing(struct tegra11_emc_table *timing)
 {
        int i;
 
-       /* burst array update depends on previous state; burst_up_down
-          and trimmers are stateless */
+       /* burst and trimmers updates depends on previous state; burst_up_down
+          are stateless */
        for (i = 0; i < timing->burst_regs_num; i++) {
                if (burst_reg_addr[i])
                        timing->burst_regs[i] = __raw_readl(burst_reg_addr[i]);
                else
                        timing->burst_regs[i] = 0;
        }
+       for (i = 0; i < timing->emc_trimmers_num; i++) {
+               timing->emc_trimmers_0[i] =
+                       __raw_readl((u32)emc0_base + emc_trimmer_offs[i]);
+               timing->emc_trimmers_1[i] =
+                       __raw_readl((u32)emc1_base + emc_trimmer_offs[i]);
+       }
        timing->emc_acal_interval = 0;
        timing->emc_zcal_cnt_long = 0;
        timing->emc_mode_reset = 0;
@@ -954,6 +985,7 @@ static int init_emc_table(const struct tegra11_emc_table *table, int table_size)
        switch (table[0].rev) {
        case 0x40:
                start_timing.burst_regs_num = table[0].burst_regs_num;
+               start_timing.emc_trimmers_num = table[0].emc_trimmers_num;
                break;
        default:
                pr_err("tegra: invalid EMC DFS table: unknown rev 0x%x\n",