ARM: tegra12: set CPU rate to 2.2GHz for sku 0x87
[linux-3.10.git] / arch / arm / mach-tegra / tegra11_clocks.c
index 0c358d2..01746af 100644 (file)
 #include <linux/syscore_ops.h>
 #include <linux/platform_device.h>
 #include <linux/clk/tegra.h>
+#include <linux/tegra-soc.h>
+#include <linux/tegra-powergate.h>
 
 #include <asm/clkdev.h>
 
 #include <mach/edp.h>
-#include <mach/hardware.h>
 #include <mach/mc.h>
-#include <mach/powergate.h>
 
 #include "clock.h"
-#include "fuse.h"
 #include "iomap.h"
 #include "dvfs.h"
 #include "pm.h"
@@ -568,7 +567,6 @@ static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
 static void __iomem *misc_gp_base = IO_ADDRESS(TEGRA_APB_MISC_BASE);
 static void __iomem *reg_xusb_padctl_base = IO_ADDRESS(TEGRA_XUSB_PADCTL_BASE);
 
-#define MISC_GP_HIDREV                         0x804
 #define MISC_GP_TRANSACTOR_SCRATCH_0           0x864
 #define MISC_GP_TRANSACTOR_SCRATCH_LA_ENABLE   (0x1 << 1)
 #define MISC_GP_TRANSACTOR_SCRATCH_DDS_ENABLE  (0x1 << 2)
@@ -590,8 +588,6 @@ static int tegra_periph_clk_enable_refcount[CLK_OUT_ENB_NUM * 32];
        __raw_writel(value, reg_pmc_base + (reg))
 #define pmc_readl(reg) \
        __raw_readl(reg_pmc_base + (reg))
-#define chipid_readl() \
-       __raw_readl(misc_gp_base + MISC_GP_HIDREV)
 #define xusb_padctl_writel(value, reg) \
        __raw_writel(value, reg_xusb_padctl_base + (reg))
 #define xusb_padctl_readl(reg) \
@@ -599,13 +595,15 @@ static int tegra_periph_clk_enable_refcount[CLK_OUT_ENB_NUM * 32];
 
 #define clk_writel_delay(value, reg)                                   \
        do {                                                            \
-               __raw_writel((value), reg_clk_base + (reg));    \
+               __raw_writel((value), reg_clk_base + (reg));            \
+               __raw_readl(reg_clk_base + (reg));                      \
                udelay(2);                                              \
        } while (0)
 
 #define pll_writel_delay(value, reg)                                   \
        do {                                                            \
-               __raw_writel((value), reg_clk_base + (reg));    \
+               __raw_writel((value), reg_clk_base + (reg));            \
+               __raw_readl(reg_clk_base + (reg));                      \
                udelay(1);                                              \
        } while (0)
 
@@ -1489,16 +1487,6 @@ static int tegra11_cpu_cmplx_clk_set_parent(struct clk *c, struct clk *p)
                goto abort;
        }
 
-       /* Disabling old parent scales old mode voltage rail */
-       if (c->refcnt)
-               clk_disable(c->parent);
-       if (p_source_old) {
-               clk_disable(p->parent);
-               clk_disable(p_source_old);
-       }
-
-       clk_reparent(c, p);
-
        /*
         * Lock DFLL now (resume closed loop VDD_CPU control).
         * G CPU operations are resumed on DFLL if it was the last G CPU
@@ -1515,6 +1503,16 @@ static int tegra11_cpu_cmplx_clk_set_parent(struct clk *c, struct clk *p)
                }
        }
 
+       /* Disabling old parent scales old mode voltage rail */
+       if (c->refcnt)
+               clk_disable(c->parent);
+       if (p_source_old) {
+               clk_disable(p->parent);
+               clk_disable(p_source_old);
+       }
+
+       clk_reparent(c, p);
+
        tegra_dvfs_rail_mode_updating(tegra_cpu_rail, false);
        return 0;
 
@@ -3669,11 +3667,17 @@ static int tegra11_use_dfll_cb(const char *arg, const struct kernel_param *kp)
        unsigned long c_flags, p_flags;
        unsigned int old_use_dfll;
        struct clk *c = tegra_get_clock_by_name("cpu");
+       struct clk *dfll = tegra_get_clock_by_name("dfll_cpu");
 
-       if (!c->parent || !c->parent->dvfs)
+       if (!c->parent || !c->parent->dvfs || !dfll)
                return -ENOSYS;
 
        clk_lock_save(c, &c_flags);
+       if (dfll->state == UNINITIALIZED) {
+               pr_err("%s: DFLL is not initialized\n", __func__);
+               clk_unlock_restore(c, &c_flags);
+               return -ENOSYS;
+       }
        if (c->parent->u.cpu.mode == MODE_LP) {
                pr_err("%s: DFLL is not used on LP CPU\n", __func__);
                clk_unlock_restore(c, &c_flags);
@@ -3933,6 +3937,13 @@ static void tegra11_periph_clk_init(struct clk *c)
                c->parent = c->inputs[0].input;
        }
 
+       /* if peripheral is left under reset - enforce safe rate */
+       if (!(c->flags & PERIPH_NO_RESET) &&
+           (clk_readl(PERIPH_CLK_TO_RST_REG(c)) & PERIPH_CLK_TO_BIT(c))) {
+               tegra_periph_clk_safe_rate_init(c);
+                val = clk_readl(c->reg);
+       }
+
        if (c->flags & DIV_U71) {
                u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
                if (c->flags & DIV_U71_IDLE) {
@@ -4020,7 +4031,7 @@ static void tegra11_periph_clk_disable(struct clk *c)
                 * flush the write operation in apb bus. This will avoid the
                 * peripheral access after disabling clock*/
                if (c->flags & PERIPH_ON_APB)
-                       val = chipid_readl();
+                       val = tegra_read_chipid();
 
                clk_writel_delay(
                        PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_CLR_REG(c));
@@ -4044,7 +4055,7 @@ static void tegra11_periph_clk_reset(struct clk *c, bool assert)
                         * will avoid the peripheral access after disabling
                         * clock */
                        if (c->flags & PERIPH_ON_APB)
-                               val = chipid_readl();
+                               val = tegra_read_chipid();
 
                        clk_writel(PERIPH_CLK_TO_BIT(c),
                                   PERIPH_CLK_TO_RST_SET_REG(c));
@@ -4886,7 +4897,10 @@ static long tegra11_clk_cbus_round_updown(struct clk *c, unsigned long rate,
                        c->dvfs->freqs[n-2] + CBUS_FINE_GRANULARITY_RANGE);
                threshold -= CBUS_FINE_GRANULARITY_RANGE;
 
-               if (rate <= threshold)
+               if (rate == threshold)
+                       return threshold;
+
+               if (rate < threshold)
                        return up ? threshold : c->dvfs->freqs[n-2];
 
                rate = (up ? DIV_ROUND_UP(rate, CBUS_FINE_GRANULARITY) :
@@ -6875,8 +6889,8 @@ struct clk tegra_list_clks[] = {
        D_AUDIO_CLK("dam0",     "tegra30-dam.0",        NULL,   108,    0x3d8,  19910000,  mux_d_audio_clk,     MUX | DIV_U71 | PERIPH_ON_APB),
        D_AUDIO_CLK("dam1",     "tegra30-dam.1",        NULL,   109,    0x3dc,  19910000,  mux_d_audio_clk,     MUX | DIV_U71 | PERIPH_ON_APB),
        D_AUDIO_CLK("dam2",     "tegra30-dam.2",        NULL,   110,    0x3e0,  19910000,  mux_d_audio_clk,     MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("adx",       "adx",                  NULL,   154,    0x638,  19910000,  mux_plla_pllc_pllp_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("amx",       "amx",                  NULL,   153,    0x63c,  19910000,  mux_plla_pllc_pllp_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("adx",       "adx",                  NULL,   154,    0x638,  24730000,  mux_plla_pllc_pllp_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("amx",       "amx",                  NULL,   153,    0x63c,  24730000,  mux_plla_pllc_pllp_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("hda",       "tegra30-hda",          "hda",          125,    0x428,  48000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("hda2codec_2x",      "tegra30-hda",  "hda2codec",    111,    0x3e4,  48000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("hda2hdmi",  "tegra30-hda",          "hda2hdmi",     128,    0,      48000000,  mux_clk_m,                   PERIPH_ON_APB),
@@ -6909,7 +6923,7 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("i2c3",      "tegra11-i2c.2",        "div-clk",      67,     0x1b8,  136000000, mux_pllp_clkm,       MUX | DIV_U16 | PERIPH_ON_APB),
        PERIPH_CLK("i2c4",      "tegra11-i2c.3",        "div-clk",      103,    0x3c4,  136000000, mux_pllp_clkm,       MUX | DIV_U16 | PERIPH_ON_APB),
        PERIPH_CLK("i2c5",      "tegra11-i2c.4",        "div-clk",      47,     0x128,  64000000,  mux_pllp_clkm,       MUX | DIV_U16 | PERIPH_ON_APB),
-       PERIPH_CLK("mipi-cal",  "mipi-cal",             NULL,   56,     0,      60000000,  mux_clk_m,   0),
+       PERIPH_CLK("mipi-cal",  "mipi-cal",             NULL,   56,     0,      60000000,  mux_clk_m,                   PERIPH_ON_APB),
        PERIPH_CLK("mipi-cal-fixed", "mipi-cal-fixed",  NULL,   0,      0,      108000000, mux_pllp_out3,       PERIPH_NO_ENB),
        PERIPH_CLK("uarta",     "serial-tegra.0",       NULL,   6,      0x178,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
        PERIPH_CLK("uartb",     "serial-tegra.1",       NULL,   7,      0x17c,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
@@ -6977,9 +6991,12 @@ struct clk tegra_list_clks[] = {
        SHARED_CLK("override.sclk", "override_sclk",    NULL,   &tegra_clk_sbus_cmplx, NULL, 0, SHARED_OVERRIDE),
 
        SHARED_EMC_CLK("avp.emc",       "tegra-avp",    "emc",  &tegra_clk_emc, NULL, 0, 0, 0),
-       SHARED_EMC_CLK("cpu.emc",       "cpu",          "emc",  &tegra_clk_emc, NULL, 0, 0, 0),
-       SHARED_EMC_CLK("disp1.emc",     "tegradc.0",    "emc",  &tegra_clk_emc, NULL, 0, SHARED_ISO_BW, BIT(EMC_USER_DC1)),
-       SHARED_EMC_CLK("disp2.emc",     "tegradc.1",    "emc",  &tegra_clk_emc, NULL, 0, SHARED_ISO_BW, BIT(EMC_USER_DC2)),
+       SHARED_EMC_CLK("disp1.emc", "tegradc.0",        "emc",  &tegra_clk_emc,
+                               NULL, 0, SHARED_ISO_BW, BIT(EMC_USER_DC1)),
+       SHARED_EMC_CLK("disp2.emc", "tegradc.1",        "emc",  &tegra_clk_emc,
+                               NULL, 0, SHARED_ISO_BW, BIT(EMC_USER_DC2)),
+       SHARED_EMC_CLK("mon_cpu.emc",   "tegra_mon",            "cpu_emc",
+                                               &tegra_clk_emc, NULL, 0, 0, 0),
        SHARED_EMC_CLK("hdmi.emc",      "hdmi",         "emc",  &tegra_clk_emc, NULL, 0, 0, 0),
        SHARED_EMC_CLK("usbd.emc",      "tegra-udc.0",  "emc",  &tegra_clk_emc, NULL, 0, 0, 0),
        SHARED_EMC_CLK("usb1.emc",      "tegra-ehci.0", "emc",  &tegra_clk_emc, NULL, 0, 0, 0),
@@ -7046,6 +7063,13 @@ struct clk tegra_list_clks[] = {
        SHARED_CLK("floor.host1x", "floor.host1x",      NULL,     &tegra_clk_host1x, NULL,  0, 0),
        SHARED_CLK("override.host1x", "override.host1x", NULL,    &tegra_clk_host1x, NULL,  0, SHARED_OVERRIDE),
        SHARED_CLK("floor.profile.host1x", "profile.host1x", NULL, &tegra_clk_host1x, NULL,  0, 0),
+
+       SHARED_CLK("sbc1.sclk", "spi_tegra.0", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
+       SHARED_CLK("sbc2.sclk", "spi_tegra.1", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
+       SHARED_CLK("sbc3.sclk", "spi_tegra.2", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
+       SHARED_CLK("sbc4.sclk", "spi_tegra.3", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
+       SHARED_CLK("sbc5.sclk", "spi_tegra.4", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
+       SHARED_CLK("sbc6.sclk", "spi_tegra.5", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
 };
 
 
@@ -7947,6 +7971,8 @@ static void tegra11_clk_resume(void)
 static struct syscore_ops tegra_clk_syscore_ops = {
        .suspend = tegra11_clk_suspend,
        .resume = tegra11_clk_resume,
+       .save = tegra11_clk_suspend,
+       .restore = tegra11_clk_resume,
 };
 #endif