Merge tag 'char-misc-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregk...
[cascardo/linux.git] / drivers / clk / samsung / clk-exynos5420.c
index a4e6cc7..848d602 100644 (file)
@@ -28,6 +28,7 @@
 #define GATE_BUS_CPU           0x700
 #define GATE_SCLK_CPU          0x800
 #define CLKOUT_CMU_CPU         0xa00
+#define SRC_MASK_CPERI         0x4300
 #define GATE_IP_G2D            0x8800
 #define CPLL_LOCK              0x10020
 #define DPLL_LOCK              0x10030
@@ -70,6 +71,8 @@
 #define SRC_TOP11              0x10284
 #define SRC_TOP12              0x10288
 #define SRC_TOP13              0x1028c /* 5800 specific */
+#define SRC_MASK_TOP0          0x10300
+#define SRC_MASK_TOP1          0x10304
 #define SRC_MASK_TOP2          0x10308
 #define SRC_MASK_TOP7          0x1031c
 #define SRC_MASK_DISP10                0x1032c
@@ -77,6 +80,7 @@
 #define SRC_MASK_FSYS          0x10340
 #define SRC_MASK_PERIC0                0x10350
 #define SRC_MASK_PERIC1                0x10354
+#define SRC_MASK_ISP           0x10370
 #define DIV_TOP0               0x10500
 #define DIV_TOP1               0x10504
 #define DIV_TOP2               0x10508
 #define DIV2_RATIO0            0x10590
 #define DIV4_RATIO             0x105a0
 #define GATE_BUS_TOP           0x10700
+#define GATE_BUS_DISP1         0x10728
 #define GATE_BUS_GEN           0x1073c
 #define GATE_BUS_FSYS0         0x10740
 #define GATE_BUS_FSYS2         0x10748
@@ -190,6 +195,10 @@ static unsigned long exynos5x_clk_regs[] __initdata = {
        SRC_MASK_FSYS,
        SRC_MASK_PERIC0,
        SRC_MASK_PERIC1,
+       SRC_MASK_TOP0,
+       SRC_MASK_TOP1,
+       SRC_MASK_MAU,
+       SRC_MASK_ISP,
        SRC_ISP,
        DIV_TOP0,
        DIV_TOP1,
@@ -208,6 +217,7 @@ static unsigned long exynos5x_clk_regs[] __initdata = {
        SCLK_DIV_ISP1,
        DIV2_RATIO0,
        DIV4_RATIO,
+       GATE_BUS_DISP1,
        GATE_BUS_TOP,
        GATE_BUS_GEN,
        GATE_BUS_FSYS0,
@@ -249,6 +259,22 @@ static unsigned long exynos5800_clk_regs[] __initdata = {
        GATE_IP_CAM,
 };
 
+static const struct samsung_clk_reg_dump exynos5420_set_clksrc[] = {
+       { .offset = SRC_MASK_CPERI,             .value = 0xffffffff, },
+       { .offset = SRC_MASK_TOP0,              .value = 0x11111111, },
+       { .offset = SRC_MASK_TOP1,              .value = 0x11101111, },
+       { .offset = SRC_MASK_TOP2,              .value = 0x11111110, },
+       { .offset = SRC_MASK_TOP7,              .value = 0x00111100, },
+       { .offset = SRC_MASK_DISP10,            .value = 0x11111110, },
+       { .offset = SRC_MASK_MAU,               .value = 0x10000000, },
+       { .offset = SRC_MASK_FSYS,              .value = 0x11111110, },
+       { .offset = SRC_MASK_PERIC0,            .value = 0x11111110, },
+       { .offset = SRC_MASK_PERIC1,            .value = 0x11111100, },
+       { .offset = SRC_MASK_ISP,               .value = 0x11111000, },
+       { .offset = GATE_BUS_DISP1,             .value = 0xffffffff, },
+       { .offset = GATE_IP_PERIC,              .value = 0xffffffff, },
+};
+
 static int exynos5420_clk_suspend(void)
 {
        samsung_clk_save(reg_base, exynos5x_save,
@@ -258,6 +284,9 @@ static int exynos5420_clk_suspend(void)
                samsung_clk_save(reg_base, exynos5800_save,
                                ARRAY_SIZE(exynos5800_clk_regs));
 
+       samsung_clk_restore(reg_base, exynos5420_set_clksrc,
+                               ARRAY_SIZE(exynos5420_set_clksrc));
+
        return 0;
 }
 
@@ -1169,6 +1198,28 @@ static struct samsung_gate_clock exynos5x_gate_clks[] __initdata = {
        GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0),
 };
 
+static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] = {
+       PLL_35XX_RATE(2000000000, 250, 3, 0),
+       PLL_35XX_RATE(1900000000, 475, 6, 0),
+       PLL_35XX_RATE(1800000000, 225, 3, 0),
+       PLL_35XX_RATE(1700000000, 425, 6, 0),
+       PLL_35XX_RATE(1600000000, 200, 3, 0),
+       PLL_35XX_RATE(1500000000, 250, 4, 0),
+       PLL_35XX_RATE(1400000000, 175, 3, 0),
+       PLL_35XX_RATE(1300000000, 325, 6, 0),
+       PLL_35XX_RATE(1200000000, 200, 2, 1),
+       PLL_35XX_RATE(1100000000, 275, 3, 1),
+       PLL_35XX_RATE(1000000000, 250, 3, 1),
+       PLL_35XX_RATE(900000000,  150, 2, 1),
+       PLL_35XX_RATE(800000000,  200, 3, 1),
+       PLL_35XX_RATE(700000000,  175, 3, 1),
+       PLL_35XX_RATE(600000000,  200, 2, 2),
+       PLL_35XX_RATE(500000000,  250, 3, 2),
+       PLL_35XX_RATE(400000000,  200, 3, 2),
+       PLL_35XX_RATE(300000000,  200, 2, 3),
+       PLL_35XX_RATE(200000000,  200, 3, 3),
+};
+
 static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
        [apll] = PLL(pll_2550, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
                APLL_CON0, NULL),
@@ -1194,7 +1245,7 @@ static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
                KPLL_CON0, NULL),
 };
 
-static struct of_device_id ext_clk_match[] __initdata = {
+static const struct of_device_id ext_clk_match[] __initconst = {
        { .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
        { },
 };
@@ -1222,6 +1273,12 @@ static void __init exynos5x_clk_init(struct device_node *np,
        samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks,
                        ARRAY_SIZE(exynos5x_fixed_rate_ext_clks),
                        ext_clk_match);
+
+       if (_get_rate("fin_pll") == 24 * MHZ) {
+               exynos5x_plls[apll].rate_table = exynos5420_pll2550x_24mhz_tbl;
+               exynos5x_plls[kpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
+       }
+
        samsung_clk_register_pll(ctx, exynos5x_plls, ARRAY_SIZE(exynos5x_plls),
                                        reg_base);
        samsung_clk_register_fixed_rate(ctx, exynos5x_fixed_rate_clks,
@@ -1253,6 +1310,8 @@ static void __init exynos5x_clk_init(struct device_node *np,
        }
 
        exynos5420_clk_sleep_init();
+
+       samsung_clk_of_add_provider(np, ctx);
 }
 
 static void __init exynos5420_clk_init(struct device_node *np)