Merge branch 'x86-cpufeature-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / drivers / clk / samsung / clk-exynos4.c
index 7f4a473..ac163d7 100644 (file)
 #define DIV_LEFTBUS            0x4500
 #define GATE_IP_LEFTBUS                0x4800
 #define E4X12_GATE_IP_IMAGE    0x4930
+#define CLKOUT_CMU_LEFTBUS     0x4a00
 #define SRC_RIGHTBUS           0x8200
 #define DIV_RIGHTBUS           0x8500
 #define GATE_IP_RIGHTBUS       0x8800
 #define E4X12_GATE_IP_PERIR    0x8960
+#define CLKOUT_CMU_RIGHTBUS    0x8a00
 #define EPLL_LOCK              0xc010
 #define VPLL_LOCK              0xc020
 #define EPLL_CON0              0xc110
 #define GATE_IP_PERIL          0xc950
 #define E4210_GATE_IP_PERIR    0xc960
 #define GATE_BLOCK             0xc970
+#define CLKOUT_CMU_TOP         0xca00
 #define E4X12_MPLL_LOCK                0x10008
 #define E4X12_MPLL_CON0                0x10108
 #define SRC_DMC                        0x10200
 #define DIV_DMC0               0x10500
 #define DIV_DMC1               0x10504
 #define GATE_IP_DMC            0x10900
+#define CLKOUT_CMU_DMC         0x10a00
 #define APLL_LOCK              0x14000
 #define E4210_MPLL_LOCK                0x14008
 #define APLL_CON0              0x14100
 #define DIV_CPU1               0x14504
 #define GATE_SCLK_CPU          0x14800
 #define GATE_IP_CPU            0x14900
+#define CLKOUT_CMU_CPU         0x14a00
+#define PWR_CTRL1              0x15020
+#define E4X12_PWR_CTRL2                0x15024
 #define E4X12_DIV_ISP0         0x18300
 #define E4X12_DIV_ISP1         0x18304
 #define E4X12_GATE_ISP0                0x18800
 #define E4X12_GATE_ISP1                0x18804
 
+/* Below definitions are used for PWR_CTRL settings */
+#define PWR_CTRL1_CORE2_DOWN_RATIO(x)          (((x) & 0x7) << 28)
+#define PWR_CTRL1_CORE1_DOWN_RATIO(x)          (((x) & 0x7) << 16)
+#define PWR_CTRL1_DIV2_DOWN_EN                 (1 << 9)
+#define PWR_CTRL1_DIV1_DOWN_EN                 (1 << 8)
+#define PWR_CTRL1_USE_CORE3_WFE                        (1 << 7)
+#define PWR_CTRL1_USE_CORE2_WFE                        (1 << 6)
+#define PWR_CTRL1_USE_CORE1_WFE                        (1 << 5)
+#define PWR_CTRL1_USE_CORE0_WFE                        (1 << 4)
+#define PWR_CTRL1_USE_CORE3_WFI                        (1 << 3)
+#define PWR_CTRL1_USE_CORE2_WFI                        (1 << 2)
+#define PWR_CTRL1_USE_CORE1_WFI                        (1 << 1)
+#define PWR_CTRL1_USE_CORE0_WFI                        (1 << 0)
+
 /* the exynos4 soc type */
 enum exynos4_soc {
        EXYNOS4210,
@@ -155,6 +176,7 @@ static unsigned long exynos4210_clk_save[] __initdata = {
        E4210_GATE_IP_LCD1,
        E4210_GATE_IP_PERIR,
        E4210_MPLL_CON0,
+       PWR_CTRL1,
 };
 
 static unsigned long exynos4x12_clk_save[] __initdata = {
@@ -164,6 +186,8 @@ static unsigned long exynos4x12_clk_save[] __initdata = {
        E4X12_DIV_ISP,
        E4X12_DIV_CAM1,
        E4X12_MPLL_CON0,
+       PWR_CTRL1,
+       E4X12_PWR_CTRL2,
 };
 
 static unsigned long exynos4_clk_pll_regs[] __initdata = {
@@ -242,6 +266,11 @@ static unsigned long exynos4_clk_regs[] __initdata = {
        DIV_CPU1,
        GATE_SCLK_CPU,
        GATE_IP_CPU,
+       CLKOUT_CMU_LEFTBUS,
+       CLKOUT_CMU_RIGHTBUS,
+       CLKOUT_CMU_TOP,
+       CLKOUT_CMU_DMC,
+       CLKOUT_CMU_CPU,
 };
 
 static const struct samsung_clk_reg_dump src_mask_suspend[] = {
@@ -397,10 +426,32 @@ PNAME(mout_audio2_p4210) = { "cdclk2", "none", "sclk_hdmi24m",
                                "sclk_epll", "sclk_vpll", };
 PNAME(mout_mixer_p4210)        = { "sclk_dac", "sclk_hdmi", };
 PNAME(mout_dac_p4210)  = { "sclk_vpll", "sclk_hdmiphy", };
+PNAME(mout_pwi_p4210) = { "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
+                               "sclk_usbphy1", "sclk_hdmiphy", "none",
+                               "sclk_epll", "sclk_vpll" };
+PNAME(clkout_left_p4210) = { "sclk_mpll_div_2", "sclk_apll_div_2",
+                               "div_gdl", "div_gpl" };
+PNAME(clkout_right_p4210) = { "sclk_mpll_div_2", "sclk_apll_div_2",
+                               "div_gdr", "div_gpr" };
+PNAME(clkout_top_p4210) = { "fout_epll", "fout_vpll", "sclk_hdmi24m",
+                               "sclk_usbphy0", "sclk_usbphy1", "sclk_hdmiphy",
+                               "cdclk0", "cdclk1", "cdclk2", "spdif_extclk",
+                               "aclk160", "aclk133", "aclk200", "aclk100",
+                               "sclk_mfc", "sclk_g3d", "sclk_g2d",
+                               "cam_a_pclk", "cam_b_pclk", "s_rxbyteclkhs0_2l",
+                               "s_rxbyteclkhs0_4l" };
+PNAME(clkout_dmc_p4210) = { "div_dmcd", "div_dmcp", "div_acp_pclk", "div_dmc",
+                               "div_dphy", "none", "div_pwi" };
+PNAME(clkout_cpu_p4210) = { "fout_apll_div_2", "none", "fout_mpll_div_2",
+                               "none", "arm_clk_div_2", "div_corem0",
+                               "div_corem1", "div_corem0", "div_atb",
+                               "div_periph", "div_pclk_dbg", "div_hpm" };
 
 /* Exynos 4x12-specific parent groups */
 PNAME(mout_mpll_user_p4x12) = { "fin_pll", "sclk_mpll", };
 PNAME(mout_core_p4x12) = { "mout_apll", "mout_mpll_user_c", };
+PNAME(mout_gdl_p4x12)  = { "mout_mpll_user_l", "sclk_apll", };
+PNAME(mout_gdr_p4x12)  = { "mout_mpll_user_r", "sclk_apll", };
 PNAME(sclk_ampll_p4x12)        = { "mout_mpll_user_t", "sclk_apll", };
 PNAME(group1_p4x12)    = { "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
                                "none", "sclk_hdmiphy", "mout_mpll_user_t",
@@ -418,6 +469,32 @@ PNAME(aclk_p4412)  = { "mout_mpll_user_t", "sclk_apll", };
 PNAME(mout_user_aclk400_mcuisp_p4x12) = {"fin_pll", "div_aclk400_mcuisp", };
 PNAME(mout_user_aclk200_p4x12) = {"fin_pll", "div_aclk200", };
 PNAME(mout_user_aclk266_gps_p4x12) = {"fin_pll", "div_aclk266_gps", };
+PNAME(mout_pwi_p4x12) = { "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
+                               "none", "sclk_hdmiphy", "sclk_mpll",
+                               "sclk_epll", "sclk_vpll" };
+PNAME(clkout_left_p4x12) = { "sclk_mpll_user_l_div_2", "sclk_apll_div_2",
+                               "div_gdl", "div_gpl" };
+PNAME(clkout_right_p4x12) = { "sclk_mpll_user_r_div_2", "sclk_apll_div_2",
+                               "div_gdr", "div_gpr" };
+PNAME(clkout_top_p4x12) = { "fout_epll", "fout_vpll", "sclk_hdmi24m",
+                               "sclk_usbphy0", "none", "sclk_hdmiphy",
+                               "cdclk0", "cdclk1", "cdclk2", "spdif_extclk",
+                               "aclk160", "aclk133", "aclk200", "aclk100",
+                               "sclk_mfc", "sclk_g3d", "aclk400_mcuisp",
+                               "cam_a_pclk", "cam_b_pclk", "s_rxbyteclkhs0_2l",
+                               "s_rxbyteclkhs0_4l", "rx_half_byte_clk_csis0",
+                               "rx_half_byte_clk_csis1", "div_jpeg",
+                               "sclk_pwm_isp", "sclk_spi0_isp",
+                               "sclk_spi1_isp", "sclk_uart_isp",
+                               "sclk_mipihsi", "sclk_hdmi", "sclk_fimd0",
+                               "sclk_pcm0" };
+PNAME(clkout_dmc_p4x12) = { "div_dmcd", "div_dmcp", "aclk_acp", "div_acp_pclk",
+                               "div_dmc", "div_dphy", "fout_mpll_div_2",
+                               "div_pwi", "none", "div_c2c", "div_c2c_aclk" };
+PNAME(clkout_cpu_p4x12) = { "fout_apll_div_2", "none", "none", "none",
+                               "arm_clk_div_2", "div_corem0", "div_corem1",
+                               "div_cores", "div_atb", "div_periph",
+                               "div_pclk_dbg", "div_hpm" };
 
 /* fixed rate clocks generated outside the soc */
 static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = {
@@ -436,6 +513,24 @@ static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata =
        FRATE(0, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
 };
 
+static struct samsung_fixed_factor_clock exynos4_fixed_factor_clks[] __initdata = {
+       FFACTOR(0, "sclk_apll_div_2", "sclk_apll", 1, 2, 0),
+       FFACTOR(0, "fout_mpll_div_2", "fout_mpll", 1, 2, 0),
+       FFACTOR(0, "fout_apll_div_2", "fout_apll", 1, 2, 0),
+       FFACTOR(0, "arm_clk_div_2", "arm_clk", 1, 2, 0),
+};
+
+static struct samsung_fixed_factor_clock exynos4210_fixed_factor_clks[] __initdata = {
+       FFACTOR(0, "sclk_mpll_div_2", "sclk_mpll", 1, 2, 0),
+};
+
+static struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initdata = {
+       FFACTOR(0, "sclk_mpll_user_l_div_2", "mout_mpll_user_l", 1, 2, 0),
+       FFACTOR(0, "sclk_mpll_user_r_div_2", "mout_mpll_user_r", 1, 2, 0),
+       FFACTOR(0, "sclk_mpll_user_t_div_2", "mout_mpll_user_t", 1, 2, 0),
+       FFACTOR(0, "sclk_mpll_user_c_div_2", "mout_mpll_user_c", 1, 2, 0),
+};
+
 /* list of mux clocks supported in all exynos4 soc's */
 static struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
        MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
@@ -451,6 +546,9 @@ static struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
        MUX(0, "mout_onenand1", mout_onenand1_p, SRC_TOP0, 0, 1),
        MUX(CLK_SCLK_EPLL, "sclk_epll", mout_epll_p, SRC_TOP0, 4, 1),
        MUX(0, "mout_onenand", mout_onenand_p, SRC_TOP0, 28, 1),
+
+       MUX(0, "mout_dmc_bus", sclk_ampll_p4210, SRC_DMC, 4, 1),
+       MUX(0, "mout_dphy", sclk_ampll_p4210, SRC_DMC, 8, 1),
 };
 
 /* list of mux clocks supported in exynos4210 soc */
@@ -459,6 +557,14 @@ static struct samsung_mux_clock exynos4210_mux_early[] __initdata = {
 };
 
 static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
+       MUX(0, "mout_gdl", sclk_ampll_p4210, SRC_LEFTBUS, 0, 1),
+       MUX(0, "mout_clkout_leftbus", clkout_left_p4210,
+                       CLKOUT_CMU_LEFTBUS, 0, 5),
+
+       MUX(0, "mout_gdr", sclk_ampll_p4210, SRC_RIGHTBUS, 0, 1),
+       MUX(0, "mout_clkout_rightbus", clkout_right_p4210,
+                       CLKOUT_CMU_RIGHTBUS, 0, 5),
+
        MUX(0, "mout_aclk200", sclk_ampll_p4210, SRC_TOP0, 12, 1),
        MUX(0, "mout_aclk100", sclk_ampll_p4210, SRC_TOP0, 16, 1),
        MUX(0, "mout_aclk160", sclk_ampll_p4210, SRC_TOP0, 20, 1),
@@ -472,6 +578,7 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
        MUX(0, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4),
        MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1),
        MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4210, SRC_CPU, 16, 1),
+       MUX(0, "mout_hpm", mout_core_p4210, SRC_CPU, 20, 1),
        MUX(CLK_SCLK_VPLL, "sclk_vpll", sclk_vpll_p4210, SRC_TOP0, 8, 1),
        MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4),
        MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4210, SRC_CAM, 4, 4),
@@ -503,12 +610,30 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
        MUX(0, "mout_spi0", group1_p4210, SRC_PERIL1, 16, 4),
        MUX(0, "mout_spi1", group1_p4210, SRC_PERIL1, 20, 4),
        MUX(0, "mout_spi2", group1_p4210, SRC_PERIL1, 24, 4),
+       MUX(0, "mout_clkout_top", clkout_top_p4210, CLKOUT_CMU_TOP, 0, 5),
+
+       MUX(0, "mout_pwi", mout_pwi_p4210, SRC_DMC, 16, 4),
+       MUX(0, "mout_clkout_dmc", clkout_dmc_p4210, CLKOUT_CMU_DMC, 0, 5),
+
+       MUX(0, "mout_clkout_cpu", clkout_cpu_p4210, CLKOUT_CMU_CPU, 0, 5),
 };
 
 /* list of mux clocks supported in exynos4x12 soc */
 static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
+       MUX(0, "mout_mpll_user_l", mout_mpll_p, SRC_LEFTBUS, 4, 1),
+       MUX(0, "mout_gdl", mout_gdl_p4x12, SRC_LEFTBUS, 0, 1),
+       MUX(0, "mout_clkout_leftbus", clkout_left_p4x12,
+                       CLKOUT_CMU_LEFTBUS, 0, 5),
+
+       MUX(0, "mout_mpll_user_r", mout_mpll_p, SRC_RIGHTBUS, 4, 1),
+       MUX(0, "mout_gdr", mout_gdr_p4x12, SRC_RIGHTBUS, 0, 1),
+       MUX(0, "mout_clkout_rightbus", clkout_right_p4x12,
+                       CLKOUT_CMU_RIGHTBUS, 0, 5),
+
        MUX(CLK_MOUT_MPLL_USER_C, "mout_mpll_user_c", mout_mpll_user_p4x12,
                        SRC_CPU, 24, 1),
+       MUX(0, "mout_clkout_cpu", clkout_cpu_p4x12, CLKOUT_CMU_CPU, 0, 5),
+
        MUX(0, "mout_aclk266_gps", aclk_p4412, SRC_TOP1, 4, 1),
        MUX(0, "mout_aclk400_mcuisp", aclk_p4412, SRC_TOP1, 8, 1),
        MUX(CLK_MOUT_MPLL_USER_T, "mout_mpll_user_t", mout_mpll_user_p4x12,
@@ -531,6 +656,7 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
        MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_DMC, 12, 1),
        MUX(CLK_SCLK_VPLL, "sclk_vpll", mout_vpll_p, SRC_TOP0, 8, 1),
        MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4x12, SRC_CPU, 16, 1),
+       MUX(0, "mout_hpm", mout_core_p4x12, SRC_CPU, 20, 1),
        MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4),
        MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4),
        MUX(CLK_MOUT_FIMC2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4),
@@ -565,15 +691,39 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
        MUX(0, "mout_spi0_isp", group1_p4x12, E4X12_SRC_ISP, 4, 4),
        MUX(0, "mout_spi1_isp", group1_p4x12, E4X12_SRC_ISP, 8, 4),
        MUX(0, "mout_uart_isp", group1_p4x12, E4X12_SRC_ISP, 12, 4),
+       MUX(0, "mout_clkout_top", clkout_top_p4x12, CLKOUT_CMU_TOP, 0, 5),
+
+       MUX(0, "mout_c2c", sclk_ampll_p4210, SRC_DMC, 0, 1),
+       MUX(0, "mout_pwi", mout_pwi_p4x12, SRC_DMC, 16, 4),
        MUX(0, "mout_g2d0", sclk_ampll_p4210, SRC_DMC, 20, 1),
        MUX(0, "mout_g2d1", sclk_evpll_p, SRC_DMC, 24, 1),
        MUX(0, "mout_g2d", mout_g2d_p, SRC_DMC, 28, 1),
+       MUX(0, "mout_clkout_dmc", clkout_dmc_p4x12, CLKOUT_CMU_DMC, 0, 5),
 };
 
 /* list of divider clocks supported in all exynos4 soc's */
 static struct samsung_div_clock exynos4_div_clks[] __initdata = {
+       DIV(0, "div_gdl", "mout_gdl", DIV_LEFTBUS, 0, 3),
+       DIV(0, "div_gpl", "div_gdl", DIV_LEFTBUS, 4, 3),
+       DIV(0, "div_clkout_leftbus", "mout_clkout_leftbus",
+                       CLKOUT_CMU_LEFTBUS, 8, 6),
+
+       DIV(0, "div_gdr", "mout_gdr", DIV_RIGHTBUS, 0, 3),
+       DIV(0, "div_gpr", "div_gdr", DIV_RIGHTBUS, 4, 3),
+       DIV(0, "div_clkout_rightbus", "mout_clkout_rightbus",
+                       CLKOUT_CMU_RIGHTBUS, 8, 6),
+
        DIV(0, "div_core", "mout_core", DIV_CPU0, 0, 3),
+       DIV(0, "div_corem0", "div_core2", DIV_CPU0, 4, 3),
+       DIV(0, "div_corem1", "div_core2", DIV_CPU0, 8, 3),
+       DIV(0, "div_periph", "div_core2", DIV_CPU0, 12, 3),
+       DIV(0, "div_atb", "mout_core", DIV_CPU0, 16, 3),
+       DIV(0, "div_pclk_dbg", "div_atb", DIV_CPU0, 20, 3),
        DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3),
+       DIV(0, "div_copy", "mout_hpm", DIV_CPU1, 0, 3),
+       DIV(0, "div_hpm", "div_copy", DIV_CPU1, 4, 3),
+       DIV(0, "div_clkout_cpu", "mout_clkout_cpu", CLKOUT_CMU_CPU, 8, 6),
+
        DIV(0, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
        DIV(0, "div_fimc1", "mout_fimc1", DIV_CAM, 4, 4),
        DIV(0, "div_fimc2", "mout_fimc2", DIV_CAM, 8, 4),
@@ -631,6 +781,16 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
                        CLK_SET_RATE_PARENT, 0),
        DIV_F(0, "div_mmc_pre3", "div_mmc3", DIV_FSYS2, 24, 8,
                        CLK_SET_RATE_PARENT, 0),
+       DIV(0, "div_clkout_top", "mout_clkout_top", CLKOUT_CMU_TOP, 8, 6),
+
+       DIV(0, "div_acp", "mout_dmc_bus", DIV_DMC0, 0, 3),
+       DIV(0, "div_acp_pclk", "div_acp", DIV_DMC0, 4, 3),
+       DIV(0, "div_dphy", "mout_dphy", DIV_DMC0, 8, 3),
+       DIV(0, "div_dmc", "mout_dmc_bus", DIV_DMC0, 12, 3),
+       DIV(0, "div_dmcd", "div_dmc", DIV_DMC0, 16, 3),
+       DIV(0, "div_dmcp", "div_dmcd", DIV_DMC0, 20, 3),
+       DIV(0, "div_pwi", "mout_pwi", DIV_DMC1, 8, 4),
+       DIV(0, "div_clkout_dmc", "mout_clkout_dmc", CLKOUT_CMU_DMC, 8, 6),
 };
 
 /* list of divider clocks supported in exynos4210 soc */
@@ -671,6 +831,8 @@ static struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
        DIV_F(CLK_DIV_MCUISP1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1,
                                                8, 3, CLK_GET_RATE_NOCACHE, 0),
        DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4),
+       DIV(0, "div_c2c", "mout_c2c", DIV_DMC1, 4, 3),
+       DIV(0, "div_c2c_aclk", "div_c2c", DIV_DMC1, 12, 3),
 };
 
 /* list of gate clocks supported in all exynos4 soc's */
@@ -680,6 +842,8 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
         * the device name and clock alias names specified below for some
         * of the clocks can be removed.
         */
+       GATE(CLK_PPMULEFT, "ppmuleft", "aclk200", GATE_IP_LEFTBUS, 1, 0, 0),
+       GATE(CLK_PPMURIGHT, "ppmuright", "aclk200", GATE_IP_RIGHTBUS, 1, 0, 0),
        GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi", SRC_MASK_TV, 0, 0, 0),
        GATE(CLK_SCLK_SPDIF, "sclk_spdif", "mout_spdif", SRC_MASK_PERIL1, 8, 0,
                0),
@@ -695,11 +859,13 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
        GATE(CLK_SROMC, "sromc", "aclk133", GATE_IP_FSYS, 11, 0, 0),
        GATE(CLK_SCLK_G3D, "sclk_g3d", "div_g3d", GATE_IP_G3D, 0,
                        CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PPMUG3D, "ppmug3d", "aclk200", GATE_IP_G3D, 1, 0, 0),
        GATE(CLK_USB_DEVICE, "usb_device", "aclk133", GATE_IP_FSYS, 13, 0, 0),
        GATE(CLK_ONENAND, "onenand", "aclk133", GATE_IP_FSYS, 15, 0, 0),
        GATE(CLK_NFCON, "nfcon", "aclk133", GATE_IP_FSYS, 16, 0, 0),
        GATE(CLK_GPS, "gps", "aclk133", GATE_IP_GPS, 0, 0, 0),
        GATE(CLK_SMMU_GPS, "smmu_gps", "aclk133", GATE_IP_GPS, 1, 0, 0),
+       GATE(CLK_PPMUGPS, "ppmugps", "aclk200", GATE_IP_GPS, 2, 0, 0),
        GATE(CLK_SLIMBUS, "slimbus", "aclk100", GATE_IP_PERIL, 25, 0, 0),
        GATE(CLK_SCLK_CAM0, "sclk_cam0", "div_cam0", GATE_SCLK_CAM, 4,
                        CLK_SET_RATE_PARENT, 0),
@@ -781,19 +947,24 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
                        0, 0),
        GATE(CLK_SMMU_JPEG, "smmu_jpeg", "aclk160", GATE_IP_CAM, 11,
                        0, 0),
+       GATE(CLK_PPMUCAMIF, "ppmucamif", "aclk160", GATE_IP_CAM, 16, 0, 0),
        GATE(CLK_PIXELASYNCM0, "pxl_async0", "aclk160", GATE_IP_CAM, 17, 0, 0),
        GATE(CLK_PIXELASYNCM1, "pxl_async1", "aclk160", GATE_IP_CAM, 18, 0, 0),
        GATE(CLK_SMMU_TV, "smmu_tv", "aclk160", GATE_IP_TV, 4,
                        0, 0),
+       GATE(CLK_PPMUTV, "ppmutv", "aclk160", GATE_IP_TV, 5, 0, 0),
        GATE(CLK_MFC, "mfc", "aclk100", GATE_IP_MFC, 0, 0, 0),
        GATE(CLK_SMMU_MFCL, "smmu_mfcl", "aclk100", GATE_IP_MFC, 1,
                        0, 0),
        GATE(CLK_SMMU_MFCR, "smmu_mfcr", "aclk100", GATE_IP_MFC, 2,
                        0, 0),
+       GATE(CLK_PPMUMFC_L, "ppmumfc_l", "aclk100", GATE_IP_MFC, 3, 0, 0),
+       GATE(CLK_PPMUMFC_R, "ppmumfc_r", "aclk100", GATE_IP_MFC, 4, 0, 0),
        GATE(CLK_FIMD0, "fimd0", "aclk160", GATE_IP_LCD0, 0,
                        0, 0),
        GATE(CLK_SMMU_FIMD0, "smmu_fimd0", "aclk160", GATE_IP_LCD0, 4,
                        0, 0),
+       GATE(CLK_PPMULCD0, "ppmulcd0", "aclk160", GATE_IP_LCD0, 5, 0, 0),
        GATE(CLK_PDMA0, "pdma0", "aclk133", GATE_IP_FSYS, 0,
                        0, 0),
        GATE(CLK_PDMA1, "pdma1", "aclk133", GATE_IP_FSYS, 1,
@@ -806,6 +977,7 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
                        0, 0),
        GATE(CLK_SDMMC3, "sdmmc3", "aclk133", GATE_IP_FSYS, 8,
                        0, 0),
+       GATE(CLK_PPMUFILE, "ppmufile", "aclk133", GATE_IP_FSYS, 17, 0, 0),
        GATE(CLK_UART0, "uart0", "aclk100", GATE_IP_PERIL, 0,
                        0, 0),
        GATE(CLK_UART1, "uart1", "aclk100", GATE_IP_PERIL, 1,
@@ -852,6 +1024,21 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
                        0, 0),
        GATE(CLK_AC97, "ac97", "aclk100", GATE_IP_PERIL, 27,
                        0, 0),
+       GATE(CLK_PPMUDMC0, "ppmudmc0", "aclk133", GATE_IP_DMC, 8, 0, 0),
+       GATE(CLK_PPMUDMC1, "ppmudmc1", "aclk133", GATE_IP_DMC, 9, 0, 0),
+       GATE(CLK_PPMUCPU, "ppmucpu", "aclk133", GATE_IP_DMC, 10, 0, 0),
+       GATE(CLK_PPMUACP, "ppmuacp", "aclk133", GATE_IP_DMC, 16, 0, 0),
+
+       GATE(CLK_OUT_LEFTBUS, "clkout_leftbus", "div_clkout_leftbus",
+                       CLKOUT_CMU_LEFTBUS, 16, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_OUT_RIGHTBUS, "clkout_rightbus", "div_clkout_rightbus",
+                       CLKOUT_CMU_RIGHTBUS, 16, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_OUT_TOP, "clkout_top", "div_clkout_top",
+                       CLKOUT_CMU_TOP, 16, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_OUT_DMC, "clkout_dmc", "div_clkout_dmc",
+                       CLKOUT_CMU_DMC, 16, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_OUT_CPU, "clkout_cpu", "div_clkout_cpu",
+                       CLKOUT_CMU_CPU, 16, CLK_SET_RATE_PARENT, 0),
 };
 
 /* list of gate clocks supported in exynos4210 soc */
@@ -863,6 +1050,9 @@ static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
        GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk200", E4210_GATE_IP_IMAGE, 3, 0, 0),
        GATE(CLK_SMMU_MDMA, "smmu_mdma", "aclk200", E4210_GATE_IP_IMAGE, 5, 0,
                0),
+       GATE(CLK_PPMUIMAGE, "ppmuimage", "aclk200", E4210_GATE_IP_IMAGE, 9, 0,
+               0),
+       GATE(CLK_PPMULCD1, "ppmulcd1", "aclk160", E4210_GATE_IP_LCD1, 5, 0, 0),
        GATE(CLK_PCIE_PHY, "pcie_phy", "aclk133", GATE_IP_FSYS, 2, 0, 0),
        GATE(CLK_SATA_PHY, "sata_phy", "aclk133", GATE_IP_FSYS, 3, 0, 0),
        GATE(CLK_SATA, "sata", "aclk133", GATE_IP_FSYS, 10, 0, 0),
@@ -906,6 +1096,8 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
        GATE(CLK_MDMA, "mdma", "aclk200", E4X12_GATE_IP_IMAGE, 2, 0, 0),
        GATE(CLK_SMMU_MDMA, "smmu_mdma", "aclk200", E4X12_GATE_IP_IMAGE, 5, 0,
                0),
+       GATE(CLK_PPMUIMAGE, "ppmuimage", "aclk200", E4X12_GATE_IP_IMAGE, 9, 0,
+               0),
        GATE(CLK_MIPI_HSI, "mipi_hsi", "aclk133", GATE_IP_FSYS, 10, 0, 0),
        GATE(CLK_CHIPID, "chipid", "aclk100", E4X12_GATE_IP_PERIR, 0, 0, 0),
        GATE(CLK_SYSREG, "sysreg", "aclk100", E4X12_GATE_IP_PERIR, 1,
@@ -1062,7 +1254,7 @@ static void __init exynos4_clk_register_finpll(struct samsung_clk_provider *ctx)
 
 }
 
-static struct of_device_id ext_clk_match[] __initdata = {
+static const struct of_device_id ext_clk_match[] __initconst = {
        { .compatible = "samsung,clock-xxti", .data = (void *)0, },
        { .compatible = "samsung,clock-xusbxti", .data = (void *)1, },
        {},
@@ -1164,6 +1356,32 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = {
                        VPLL_LOCK, VPLL_CON0, NULL),
 };
 
+static void __init exynos4_core_down_clock(enum exynos4_soc soc)
+{
+       unsigned int tmp;
+
+       /*
+        * Enable arm clock down (in idle) and set arm divider
+        * ratios in WFI/WFE state.
+        */
+       tmp = (PWR_CTRL1_CORE2_DOWN_RATIO(7) | PWR_CTRL1_CORE1_DOWN_RATIO(7) |
+               PWR_CTRL1_DIV2_DOWN_EN | PWR_CTRL1_DIV1_DOWN_EN |
+               PWR_CTRL1_USE_CORE1_WFE | PWR_CTRL1_USE_CORE0_WFE |
+               PWR_CTRL1_USE_CORE1_WFI | PWR_CTRL1_USE_CORE0_WFI);
+       /* On Exynos4412 enable it also on core 2 and 3 */
+       if (num_possible_cpus() == 4)
+               tmp |= PWR_CTRL1_USE_CORE3_WFE | PWR_CTRL1_USE_CORE2_WFE |
+                      PWR_CTRL1_USE_CORE3_WFI | PWR_CTRL1_USE_CORE2_WFI;
+       __raw_writel(tmp, reg_base + PWR_CTRL1);
+
+       /*
+        * Disable the clock up feature on Exynos4x12, in case it was
+        * enabled by bootloader.
+        */
+       if (exynos4_soc == EXYNOS4X12)
+               __raw_writel(0x0, reg_base + E4X12_PWR_CTRL2);
+}
+
 /* register exynos4 clocks */
 static void __init exynos4_clk_init(struct device_node *np,
                                    enum exynos4_soc soc)
@@ -1224,6 +1442,8 @@ static void __init exynos4_clk_init(struct device_node *np,
                        ARRAY_SIZE(exynos4_div_clks));
        samsung_clk_register_gate(ctx, exynos4_gate_clks,
                        ARRAY_SIZE(exynos4_gate_clks));
+       samsung_clk_register_fixed_factor(ctx, exynos4_fixed_factor_clks,
+                       ARRAY_SIZE(exynos4_fixed_factor_clks));
 
        if (exynos4_soc == EXYNOS4210) {
                samsung_clk_register_fixed_rate(ctx, exynos4210_fixed_rate_clks,
@@ -1236,6 +1456,9 @@ static void __init exynos4_clk_init(struct device_node *np,
                        ARRAY_SIZE(exynos4210_gate_clks));
                samsung_clk_register_alias(ctx, exynos4210_aliases,
                        ARRAY_SIZE(exynos4210_aliases));
+               samsung_clk_register_fixed_factor(ctx,
+                       exynos4210_fixed_factor_clks,
+                       ARRAY_SIZE(exynos4210_fixed_factor_clks));
        } else {
                samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
                        ARRAY_SIZE(exynos4x12_mux_clks));
@@ -1245,13 +1468,19 @@ static void __init exynos4_clk_init(struct device_node *np,
                        ARRAY_SIZE(exynos4x12_gate_clks));
                samsung_clk_register_alias(ctx, exynos4x12_aliases,
                        ARRAY_SIZE(exynos4x12_aliases));
+               samsung_clk_register_fixed_factor(ctx,
+                       exynos4x12_fixed_factor_clks,
+                       ARRAY_SIZE(exynos4x12_fixed_factor_clks));
        }
 
        samsung_clk_register_alias(ctx, exynos4_aliases,
                        ARRAY_SIZE(exynos4_aliases));
 
+       exynos4_core_down_clock(soc);
        exynos4_clk_sleep_init();
 
+       samsung_clk_of_add_provider(np, ctx);
+
        pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
                "\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n",
                exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",