Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / arch / arm / mach-tegra / tegra2_clocks.c
index 59e77ba..6d7c4ee 100644 (file)
@@ -159,6 +159,12 @@ static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
  */
 static DEFINE_SPINLOCK(clock_register_lock);
 
+/*
+ * Some peripheral clocks share an enable bit, so refcount the enable bits
+ * in registers CLK_ENABLE_L, CLK_ENABLE_H, and CLK_ENABLE_U
+ */
+static int tegra_periph_clk_enable_refcount[3 * 32];
+
 #define clk_writel(value, reg) \
        __raw_writel(value, (u32)reg_clk_base + (reg))
 #define clk_readl(reg) \
@@ -892,9 +898,9 @@ static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate)
                divider = clk_div71_get_divider(parent_rate, rate);
                if (divider < 0)
                        return divider;
-               return parent_rate * 2 / (divider + 2);
+               return DIV_ROUND_UP(parent_rate * 2, divider + 2);
        } else if (c->flags & DIV_2) {
-               return parent_rate / 2;
+               return DIV_ROUND_UP(parent_rate, 2);
        }
        return -EINVAL;
 }
@@ -940,9 +946,14 @@ static void tegra2_periph_clk_init(struct clk *c)
        }
 
        c->state = ON;
+
+       if (!c->u.periph.clk_num)
+               return;
+
        if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
                        PERIPH_CLK_TO_ENB_BIT(c)))
                c->state = OFF;
+
        if (!(c->flags & PERIPH_NO_RESET))
                if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) &
                                PERIPH_CLK_TO_ENB_BIT(c))
@@ -952,8 +963,20 @@ static void tegra2_periph_clk_init(struct clk *c)
 static int tegra2_periph_clk_enable(struct clk *c)
 {
        u32 val;
+       unsigned long flags;
+       int refcount;
        pr_debug("%s on clock %s\n", __func__, c->name);
 
+       if (!c->u.periph.clk_num)
+               return 0;
+
+       spin_lock_irqsave(&clock_register_lock, flags);
+
+       refcount = tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++;
+
+       if (refcount > 1)
+               goto out;
+
        clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
                CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
        if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET))
@@ -966,15 +989,32 @@ static int tegra2_periph_clk_enable(struct clk *c)
                val |= 0x3 << 24;
                clk_writel(val, c->reg);
        }
+
+out:
+       spin_unlock_irqrestore(&clock_register_lock, flags);
+
        return 0;
 }
 
 static void tegra2_periph_clk_disable(struct clk *c)
 {
+       unsigned long flags;
+
        pr_debug("%s on clock %s\n", __func__, c->name);
 
-       clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-               CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+       if (!c->u.periph.clk_num)
+               return;
+
+       spin_lock_irqsave(&clock_register_lock, flags);
+
+       if (c->refcnt)
+               tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
+
+       if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] == 0)
+               clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+                       CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+
+       spin_unlock_irqrestore(&clock_register_lock, flags);
 }
 
 static void tegra2_periph_clk_reset(struct clk *c, bool assert)
@@ -983,6 +1023,9 @@ static void tegra2_periph_clk_reset(struct clk *c, bool assert)
 
        pr_debug("%s %s on clock %s\n", __func__,
                 assert ? "assert" : "deassert", c->name);
+
+       BUG_ON(!c->u.periph.clk_num);
+
        if (!(c->flags & PERIPH_NO_RESET))
                clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
                           base + PERIPH_CLK_TO_ENB_SET_REG(c));
@@ -1063,12 +1106,12 @@ static long tegra2_periph_clk_round_rate(struct clk *c,
                if (divider < 0)
                        return divider;
 
-               return parent_rate * 2 / (divider + 2);
+               return DIV_ROUND_UP(parent_rate * 2, divider + 2);
        } else if (c->flags & DIV_U16) {
                divider = clk_div16_get_divider(parent_rate, rate);
                if (divider < 0)
                        return divider;
-               return parent_rate / (divider + 1);
+               return DIV_ROUND_UP(parent_rate, divider + 1);
        }
        return -EINVAL;
 }
@@ -1153,6 +1196,10 @@ static void tegra2_clk_double_init(struct clk *c)
        c->mul = 2;
        c->div = 1;
        c->state = ON;
+
+       if (!c->u.periph.clk_num)
+               return;
+
        if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
                        PERIPH_CLK_TO_ENB_BIT(c)))
                c->state = OFF;
@@ -1240,6 +1287,9 @@ static void tegra2_cdev_clk_init(struct clk *c)
        /* We could un-tristate the cdev1 or cdev2 pingroup here; this is
         * currently done in the pinmux code. */
        c->state = ON;
+
+       BUG_ON(!c->u.periph.clk_num);
+
        if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
                        PERIPH_CLK_TO_ENB_BIT(c)))
                c->state = OFF;
@@ -1247,6 +1297,8 @@ static void tegra2_cdev_clk_init(struct clk *c)
 
 static int tegra2_cdev_clk_enable(struct clk *c)
 {
+       BUG_ON(!c->u.periph.clk_num);
+
        clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
                CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
        return 0;
@@ -1254,6 +1306,8 @@ static int tegra2_cdev_clk_enable(struct clk *c)
 
 static void tegra2_cdev_clk_disable(struct clk *c)
 {
+       BUG_ON(!c->u.periph.clk_num);
+
        clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
                CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
 }
@@ -1769,8 +1823,8 @@ static struct clk tegra_clk_d = {
 };
 
 /* dap_mclk1, belongs to the cdev1 pingroup. */
-static struct clk tegra_dev1_clk = {
-       .name      = "clk_dev1",
+static struct clk tegra_clk_cdev1 = {
+       .name      = "cdev1",
        .ops       = &tegra_cdev_clk_ops,
        .rate      = 26000000,
        .max_rate  = 26000000,
@@ -1780,8 +1834,8 @@ static struct clk tegra_dev1_clk = {
 };
 
 /* dap_mclk2, belongs to the cdev2 pingroup. */
-static struct clk tegra_dev2_clk = {
-       .name      = "clk_dev2",
+static struct clk tegra_clk_cdev2 = {
+       .name      = "cdev2",
        .ops       = &tegra_cdev_clk_ops,
        .rate      = 26000000,
        .max_rate  = 26000000,
@@ -2074,9 +2128,8 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("apbdma",    "tegra-dma",            NULL,   34,     0,      108000000, mux_pclk,                    0),
        PERIPH_CLK("rtc",       "rtc-tegra",            NULL,   4,      0,      32768,     mux_clk_32k,                 PERIPH_NO_RESET),
        PERIPH_CLK("timer",     "timer",                NULL,   5,      0,      26000000,  mux_clk_m,                   0),
-       PERIPH_CLK("i2s1",      "i2s.0",                NULL,   11,     0x100,  26000000,  mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
-       PERIPH_CLK("i2s2",      "i2s.1",                NULL,   18,     0x104,  26000000,  mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
-       /* FIXME: spdif has 2 clocks but 1 enable */
+       PERIPH_CLK("i2s1",      "tegra-i2s.0",          NULL,   11,     0x100,  26000000,  mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
+       PERIPH_CLK("i2s2",      "tegra-i2s.1",          NULL,   18,     0x104,  26000000,  mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
        PERIPH_CLK("spdif_out", "spdif_out",            NULL,   10,     0x108,  100000000, mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
        PERIPH_CLK("spdif_in",  "spdif_in",             NULL,   10,     0x10c,  100000000, mux_pllp_pllc_pllm,          MUX | DIV_U71),
        PERIPH_CLK("pwm",       "pwm",                  NULL,   17,     0x110,  432000000, mux_pllp_pllc_audio_clkm_clk32,      MUX | DIV_U71),
@@ -2089,7 +2142,6 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("sbc4",      "spi_tegra.3",          NULL,   68,     0x1b4,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
        PERIPH_CLK("ide",       "ide",                  NULL,   25,     0x144,  100000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* requires min voltage */
        PERIPH_CLK("ndflash",   "tegra_nand",           NULL,   13,     0x160,  164000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
-       /* FIXME: vfir shares an enable with uartb */
        PERIPH_CLK("vfir",      "vfir",                 NULL,   7,      0x168,  72000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
        PERIPH_CLK("sdmmc1",    "sdhci-tegra.0",        NULL,   14,     0x150,  52000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
        PERIPH_CLK("sdmmc2",    "sdhci-tegra.1",        NULL,   9,      0x154,  52000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
@@ -2120,13 +2172,11 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("uarte",     "uart.4",               NULL,   66,     0x1c4,  600000000, mux_pllp_pllc_pllm_clkm,     MUX),
        PERIPH_CLK("3d",        "3d",                   NULL,   24,     0x158,  300000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */
        PERIPH_CLK("2d",        "2d",                   NULL,   21,     0x15c,  300000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
-       /* FIXME: vi and vi_sensor share an enable */
        PERIPH_CLK("vi",        "tegra_camera",         "vi",   20,     0x148,  150000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
        PERIPH_CLK("vi_sensor", "tegra_camera",         "vi_sensor",    20,     0x1a8,  150000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */
        PERIPH_CLK("epp",       "epp",                  NULL,   19,     0x16c,  300000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
        PERIPH_CLK("mpe",       "mpe",                  NULL,   60,     0x170,  250000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
        PERIPH_CLK("host1x",    "host1x",               NULL,   28,     0x180,  166000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
-       /* FIXME: cve and tvo share an enable   */
        PERIPH_CLK("cve",       "cve",                  NULL,   49,     0x140,  250000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
        PERIPH_CLK("tvo",       "tvo",                  NULL,   49,     0x188,  250000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
        PERIPH_CLK("hdmi",      "hdmi",                 NULL,   51,     0x18c,  600000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
@@ -2226,8 +2276,8 @@ struct clk *tegra_ptr_clks[] = {
        &tegra_clk_hclk,
        &tegra_clk_pclk,
        &tegra_clk_d,
-       &tegra_dev1_clk,
-       &tegra_dev2_clk,
+       &tegra_clk_cdev1,
+       &tegra_clk_cdev2,
        &tegra_clk_virtual_cpu,
        &tegra_clk_blink,
        &tegra_clk_cop,