ARM: tegra: clock: Update LP-cluster related interfaces
Alex Frid [Wed, 29 Dec 2010 19:30:52 +0000 (11:30 -0800)]
Original-Change-Id: Ifde476a05bd01cdce8c3f4802b268a193a832a1b
Reviewed-on: http://git-master/r/14584
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Tested-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Scott Williams <scwilliams@nvidia.com>
Original-Change-Id: I41204d17c5d8092b1a24b3138efe12cfbd16d7e7

Rebase-Id: R9754ff5e07ecabd945edfccdbc0f9d9586be6e23

arch/arm/mach-tegra/clock.c
arch/arm/mach-tegra/pm-t3.c
arch/arm/mach-tegra/pm.h
arch/arm/mach-tegra/tegra3_clocks.c

index 0096f6f..7203486 100644 (file)
@@ -115,6 +115,14 @@ static unsigned long clk_predict_rate_from_parent(struct clk *c, struct clk *p)
        return rate;
 }
 
+static unsigned long clk_get_max_rate(struct clk *c)
+{
+       if (c->ops && c->ops->get_max_rate)
+               return c->ops->get_max_rate(c);
+       else
+               return c->max_rate;
+}
+
 /* Must be called with clk_lock(c) held */
 unsigned long clk_get_rate_locked(struct clk *c)
 {
@@ -319,9 +327,7 @@ int clk_set_rate_locked(struct clk *c, unsigned long rate)
 
        old_rate = clk_get_rate_locked(c);
 
-       max_rate = c->max_rate;
-       if (c->ops && c->ops->get_max_rate)
-               max_rate = c->ops->get_max_rate(c);
+       max_rate = clk_get_max_rate(c);
        if (rate > max_rate)
                rate = max_rate;
 
@@ -408,9 +414,7 @@ long clk_round_rate(struct clk *c, unsigned long rate)
                goto out;
        }
 
-       max_rate = c->max_rate;
-       if (c->ops && c->ops->get_max_rate)
-               max_rate = c->ops->get_max_rate(c);
+       max_rate = clk_get_max_rate(c);
        if (rate > max_rate)
                rate = max_rate;
 
@@ -690,10 +694,7 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
        const char *state = "uninit";
        char div[8] = {0};
        unsigned long rate = clk_get_rate_all_locked(c);
-       unsigned long max_rate = c->max_rate;
-
-       if (c->ops && c->ops->get_max_rate)
-               max_rate = c->ops->get_max_rate(c);
+       unsigned long max_rate = clk_get_max_rate(c);;
 
        if (c->state == ON)
                state = "on";
index 8efae69..651053d 100644 (file)
@@ -177,9 +177,10 @@ static int cluster_switch_prolog_clock(unsigned int flags)
 
                        struct clk *c = tegra_get_clock_by_name("cpu");
                        unsigned long cur_rate = clk_get_rate(c);
-                       unsigned long max_rate = clk_get_rate(c); /* !!!FIXME!!! clk_alt_max_rate(c); */
+                       unsigned long max_rate = tegra_get_lpcpu_max_rate();
                        int err;
 
+                       BUG_ON(max_rate == 0);
                        if (cur_rate/2 > max_rate) {
                                /* PLLX is running too fast for the LP CPU.
                                   Reduce it to LP maximum rate which must
index f5c6b3e..e8452cc 100644 (file)
@@ -76,11 +76,14 @@ static inline int tegra_cluster_control(unsigned int us, unsigned int flags)
 #define tegra_cluster_switch_epilog(flags) do {} while(0)
 static inline unsigned int is_lp_cluster(void)
 { return 0; }
+static inline unsigned long tegra_get_lpcpu_max_rate(void)
+{ return 0; }
 #else
 int tegra_cluster_control(unsigned int us, unsigned int flags);
 void tegra_cluster_switch_prolog(unsigned int flags);
 void tegra_cluster_switch_epilog(unsigned int flags);
 unsigned int is_lp_cluster(void);
+unsigned long tegra_get_lpcpu_max_rate(void);
 #endif
 
 static inline void flowctrl_writel(unsigned long val, unsigned int offs)
index 8de7f04..ca1dc3b 100644 (file)
 #define        SUPER_IDLE_SOURCE_SHIFT         0
 
 #define SUPER_CLK_DIVIDER              0x04
-#define IS_PLLX_DIV2_BYPASS            (clk_readl(0x370) & (1<<16))
-/* FIXME: replace with global is_lp_cluster() ? */
-#define IS_LP_CLUSTER                  (flow_readl(0x2c) & 1)
+#define IS_PLLX_DIV2                   (!(clk_readl(0x370) & (1<<16)) && is_lp_cluster())
 
 #define BUS_CLK_DISABLE                        (1<<3)
 #define BUS_CLK_DIV_MASK               0x3
 
 static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
 static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
-static void __iomem *reg_flow_base = IO_ADDRESS(TEGRA_FLOW_CTRL_BASE);
 
 /*
  * Some peripheral clocks share an enable bit, so refcount the enable bits
@@ -219,8 +216,6 @@ static int tegra_periph_clk_enable_refcount[CLK_OUT_ENB_NUM * 32];
        __raw_writel(value, (u32)reg_pmc_base + (reg))
 #define pmc_readl(reg) \
        __raw_readl((u32)reg_pmc_base + (reg))
-#define flow_readl(reg) \
-       __raw_readl((u32)reg_flow_base + (reg))
 
 static inline u32 periph_clk_to_reg(
        struct clk *c, u32 reg_L, u32 reg_V, int offs)
@@ -549,7 +544,7 @@ out:
 
 static unsigned long tegra3_cpu_get_max_rate(struct clk *c)
 {
-       if (IS_LP_CLUSTER)
+       if (is_lp_cluster())
                return c->u.cpu.lp_max_rate;
        else
                return c->max_rate;
@@ -918,30 +913,31 @@ static struct clk_ops tegra_pll_ops = {
 /* Clock divider ops */
 static void tegra3_pll_div_clk_init(struct clk *c)
 {
-       u32 val = clk_readl(c->reg);
-       u32 divu71;
-       val >>= c->reg_shift;
-       c->state = (val & PLL_OUT_CLKEN) ? ON : OFF;
-       if (!(val & PLL_OUT_RESET_DISABLE))
-               c->state = OFF;
-
        if (c->flags & DIV_U71) {
+               u32 divu71;
+               u32 val = clk_readl(c->reg);
+               val >>= c->reg_shift;
+               c->state = (val & PLL_OUT_CLKEN) ? ON : OFF;
+               if (!(val & PLL_OUT_RESET_DISABLE))
+                       c->state = OFF;
+
                divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT;
                c->div = (divu71 + 2);
                c->mul = 2;
        } else if (c->flags & DIV_2) {
+               c->state = ON;
                if (c->flags & PLLD) {
                        c->div = 2;
                        c->mul = 1;
                }
                else if (c->flags & PLLX) {
-                       c->div = (IS_LP_CLUSTER &&
-                                       (!IS_PLLX_DIV2_BYPASS)) ? 2 : 1;
+                       c->div = (IS_PLLX_DIV2) ? 2 : 1;
                        c->mul = 1;
                }
                else
                        BUG();
        } else {
+               c->state = ON;
                c->div = 1;
                c->mul = 1;
        }
@@ -1020,7 +1016,7 @@ static int tegra3_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
                        return clk_set_rate(c->parent, rate * 2);
                }
                else if (c->flags & PLLX) {
-                       if (IS_LP_CLUSTER && (!IS_PLLX_DIV2_BYPASS))
+                       if (IS_PLLX_DIV2)
                                rate *= 2;
                        return clk_set_rate(c->parent, rate);
                }
@@ -1045,7 +1041,7 @@ static long tegra3_pll_div_clk_round_rate(struct clk *c, unsigned long rate)
 
 static void tegra3_pllx_div_clk_recalculate_rate(struct clk *c)
 {
-       c->div = (IS_LP_CLUSTER && (!IS_PLLX_DIV2_BYPASS)) ? 2 : 1;
+       c->div = (IS_PLLX_DIV2) ? 2 : 1;
 }
 
 static struct clk_ops tegra_pll_div_ops = {
@@ -2207,7 +2203,6 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("bsea",      "tegra-avp",            "bsea", 62,     0,      250000000, mux_clk_m,                   0),
        PERIPH_CLK("vde",       "tegra-avp",            "vde",  61,     0x1c8,  250000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage and process_id */
        PERIPH_CLK("csite",     "csite",                NULL,   73,     0x1d4,  144000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* max rate ??? */
-       /* FIXME: what is la? */
        PERIPH_CLK("la",        "la",                   NULL,   76,     0x1f8,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
        PERIPH_CLK("owr",       "tegra_w1",             NULL,   71,     0x1cc,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
        PERIPH_CLK("nor",       "nor",                  NULL,   42,     0x1d0,  92000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* requires min voltage */
@@ -2244,6 +2239,7 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("usbd",      "fsl-tegra-udc",        NULL,   22,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
        PERIPH_CLK("usb2",      "tegra-ehci.1",         NULL,   58,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
        PERIPH_CLK("usb3",      "tegra-ehci.2",         NULL,   59,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
+       /* FIXME: EMC should be separated as shared bus for EMC DVFS */
        PERIPH_CLK("emc",       "emc",                  NULL,   57,     0x19c,  800000000, mux_pllm_pllc_pllp_clkm,     MUX | DIV_U71 | PERIPH_EMC_ENB),
        PERIPH_CLK("dsi",       "dsi",                  NULL,   48,     0,      500000000, mux_plld_out0,               0), /* scales with voltage */
        PERIPH_CLK("csi",       "tegra_camera",         "csi",  52,     0,      72000000,  mux_pllp_out3,               0),
@@ -2331,7 +2327,6 @@ static void tegra3_init_one_clock(struct clk *c)
        clkdev_add(&c->lookup);
 }
 
-//FIXME: void __init tegra3_init_clocks(void)
 void __init tegra_soc_init_clocks(void)
 {
        int i;
@@ -2366,6 +2361,11 @@ void __init tegra_soc_init_clocks(void)
 static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM +
                           PERIPH_CLK_SOURCE_NUM + 15];
 
+unsigned long tegra_get_lpcpu_max_rate(void)
+{
+       return tegra_clk_virtual_cpu.u.cpu.lp_max_rate;
+}
+
 void tegra_clk_suspend(void)
 {
        unsigned long off;