summaryrefslogtreecommitdiffstats
path: root/drivers/clk/samsung/clk-exynos5250.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/samsung/clk-exynos5250.c')
-rw-r--r--drivers/clk/samsung/clk-exynos5250.c118
1 files changed, 107 insertions, 11 deletions
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index e7ee4420da81..1fad4c5e3f5d 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -24,10 +24,14 @@
#define APLL_CON0 0x100
#define SRC_CPU 0x200
#define DIV_CPU0 0x500
+#define PWR_CTRL1 0x1020
+#define PWR_CTRL2 0x1024
#define MPLL_LOCK 0x4000
#define MPLL_CON0 0x4100
#define SRC_CORE1 0x4204
#define GATE_IP_ACP 0x8800
+#define GATE_IP_ISP0 0xc800
+#define GATE_IP_ISP1 0xc804
#define CPLL_LOCK 0x10020
#define EPLL_LOCK 0x10030
#define VPLL_LOCK 0x10040
@@ -37,6 +41,7 @@
#define VPLL_CON0 0x10140
#define GPLL_CON0 0x10150
#define SRC_TOP0 0x10210
+#define SRC_TOP1 0x10214
#define SRC_TOP2 0x10218
#define SRC_TOP3 0x1021c
#define SRC_GSCL 0x10220
@@ -71,6 +76,7 @@
#define GATE_IP_GSCL 0x10920
#define GATE_IP_DISP1 0x10928
#define GATE_IP_MFC 0x1092c
+#define GATE_IP_G3D 0x10930
#define GATE_IP_GEN 0x10934
#define GATE_IP_FSYS 0x10944
#define GATE_IP_PERIC 0x10950
@@ -80,6 +86,23 @@
#define SRC_CDREX 0x20200
#define PLL_DIV2_SEL 0x20a24
+/*Below definitions are used for PWR_CTRL settings*/
+#define PWR_CTRL1_CORE2_DOWN_RATIO (7 << 28)
+#define PWR_CTRL1_CORE1_DOWN_RATIO (7 << 16)
+#define PWR_CTRL1_DIV2_DOWN_EN (1 << 9)
+#define PWR_CTRL1_DIV1_DOWN_EN (1 << 8)
+#define PWR_CTRL1_USE_CORE1_WFE (1 << 5)
+#define PWR_CTRL1_USE_CORE0_WFE (1 << 4)
+#define PWR_CTRL1_USE_CORE1_WFI (1 << 1)
+#define PWR_CTRL1_USE_CORE0_WFI (1 << 0)
+
+#define PWR_CTRL2_DIV2_UP_EN (1 << 25)
+#define PWR_CTRL2_DIV1_UP_EN (1 << 24)
+#define PWR_CTRL2_DUR_STANDBY2_VAL (1 << 16)
+#define PWR_CTRL2_DUR_STANDBY1_VAL (1 << 8)
+#define PWR_CTRL2_CORE2_UP_RATIO (1 << 4)
+#define PWR_CTRL2_CORE1_UP_RATIO (1 << 0)
+
/* list of PLLs to be registered */
enum exynos5250_plls {
apll, mpll, cpll, epll, vpll, gpll, bpll,
@@ -98,8 +121,11 @@ static struct samsung_clk_reg_dump *exynos5250_save;
static unsigned long exynos5250_clk_regs[] __initdata = {
SRC_CPU,
DIV_CPU0,
+ PWR_CTRL1,
+ PWR_CTRL2,
SRC_CORE1,
SRC_TOP0,
+ SRC_TOP1,
SRC_TOP2,
SRC_TOP3,
SRC_GSCL,
@@ -133,6 +159,7 @@ static unsigned long exynos5250_clk_regs[] __initdata = {
DIV_PERIC5,
GATE_IP_GSCL,
GATE_IP_MFC,
+ GATE_IP_G3D,
GATE_IP_GEN,
GATE_IP_FSYS,
GATE_IP_PERIC,
@@ -141,6 +168,8 @@ static unsigned long exynos5250_clk_regs[] __initdata = {
PLL_DIV2_SEL,
GATE_IP_DISP1,
GATE_IP_ACP,
+ GATE_IP_ISP0,
+ GATE_IP_ISP1,
};
static int exynos5250_clk_suspend(void)
@@ -189,13 +218,16 @@ PNAME(mout_vpllsrc_p) = { "fin_pll", "sclk_hdmi27m" };
PNAME(mout_vpll_p) = { "mout_vpllsrc", "fout_vpll" };
PNAME(mout_cpll_p) = { "fin_pll", "fout_cpll" };
PNAME(mout_epll_p) = { "fin_pll", "fout_epll" };
+PNAME(mout_gpll_p) = { "fin_pll", "fout_gpll" };
PNAME(mout_mpll_user_p) = { "fin_pll", "mout_mpll" };
PNAME(mout_bpll_user_p) = { "fin_pll", "mout_bpll" };
PNAME(mout_aclk166_p) = { "mout_cpll", "mout_mpll_user" };
PNAME(mout_aclk200_p) = { "mout_mpll_user", "mout_bpll_user" };
+PNAME(mout_aclk400_p) = { "mout_aclk400_g3d_mid", "mout_gpll" };
PNAME(mout_aclk200_sub_p) = { "fin_pll", "div_aclk200" };
PNAME(mout_aclk266_sub_p) = { "fin_pll", "div_aclk266" };
PNAME(mout_aclk333_sub_p) = { "fin_pll", "div_aclk333" };
+PNAME(mout_aclk400_isp_sub_p) = { "fin_pll", "div_aclk400_isp" };
PNAME(mout_hdmi_p) = { "div_hdmi_pixel", "sclk_hdmiphy" };
PNAME(mout_usb3_p) = { "mout_mpll_user", "mout_cpll" };
PNAME(mout_group1_p) = { "fin_pll", "fin_pll", "sclk_hdmi27m",
@@ -273,15 +305,23 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
MUX(0, "mout_aclk166", mout_aclk166_p, SRC_TOP0, 8, 1),
MUX(0, "mout_aclk200", mout_aclk200_p, SRC_TOP0, 12, 1),
MUX(0, "mout_aclk333", mout_aclk166_p, SRC_TOP0, 16, 1),
+ MUX(0, "mout_aclk400_g3d_mid", mout_aclk200_p, SRC_TOP0, 20, 1),
+
+ MUX(0, "mout_aclk400_isp", mout_aclk200_p, SRC_TOP1, 24, 1),
+ MUX(0, "mout_aclk400_g3d", mout_aclk400_p, SRC_TOP1, 28, 1),
MUX(0, "mout_cpll", mout_cpll_p, SRC_TOP2, 8, 1),
MUX(0, "mout_epll", mout_epll_p, SRC_TOP2, 12, 1),
MUX(0, "mout_vpll", mout_vpll_p, SRC_TOP2, 16, 1),
MUX(0, "mout_mpll_user", mout_mpll_user_p, SRC_TOP2, 20, 1),
MUX(0, "mout_bpll_user", mout_bpll_user_p, SRC_TOP2, 24, 1),
+ MUX(CLK_MOUT_GPLL, "mout_gpll", mout_gpll_p, SRC_TOP2, 28, 1),
MUX(0, "mout_aclk200_disp1_sub", mout_aclk200_sub_p, SRC_TOP3, 4, 1),
MUX(0, "mout_aclk266_gscl_sub", mout_aclk266_sub_p, SRC_TOP3, 8, 1),
+ MUX(0, "mout_aclk_266_isp_sub", mout_aclk266_sub_p, SRC_TOP3, 16, 1),
+ MUX(0, "mout_aclk_400_isp_sub", mout_aclk400_isp_sub_p,
+ SRC_TOP3, 20, 1),
MUX(0, "mout_aclk333_sub", mout_aclk333_sub_p, SRC_TOP3, 24, 1),
MUX(0, "mout_cam_bayer", mout_group1_p, SRC_GSCL, 12, 4),
@@ -351,7 +391,10 @@ static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
DIV(0, "div_aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
DIV(0, "div_aclk266", "mout_mpll_user", DIV_TOP0, 16, 3),
DIV(0, "div_aclk333", "mout_aclk333", DIV_TOP0, 20, 3),
+ DIV(0, "div_aclk400_g3d", "mout_aclk400_g3d", DIV_TOP0,
+ 24, 3),
+ DIV(0, "div_aclk400_isp", "mout_aclk400_isp", DIV_TOP1, 20, 3),
DIV(0, "div_aclk66_pre", "mout_mpll_user", DIV_TOP1, 24, 3),
DIV(0, "div_cam_bayer", "mout_cam_bayer", DIV_GSCL, 12, 4),
@@ -428,6 +471,7 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
* CMU_ACP
*/
GATE(CLK_MDMA0, "mdma0", "div_aclk266", GATE_IP_ACP, 1, 0, 0),
+ GATE(CLK_SSS, "sss", "div_aclk266", GATE_IP_ACP, 2, 0, 0),
GATE(CLK_G2D, "g2d", "div_aclk200", GATE_IP_ACP, 3, 0, 0),
GATE(CLK_SMMU_MDMA0, "smmu_mdma0", "div_aclk266", GATE_IP_ACP, 5, 0, 0),
@@ -533,7 +577,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
0),
GATE(CLK_SMMU_MFCL, "smmu_mfcl", "mout_aclk333_sub", GATE_IP_MFC, 2, 0,
0),
-
+ GATE(CLK_G3D, "g3d", "div_aclk400_g3d", GATE_IP_G3D, 0,
+ CLK_SET_RATE_PARENT, 0),
GATE(CLK_ROTATOR, "rotator", "div_aclk266", GATE_IP_GEN, 1, 0, 0),
GATE(CLK_JPEG, "jpeg", "div_aclk166", GATE_IP_GEN, 2, 0, 0),
GATE(CLK_MDMA1, "mdma1", "div_aclk266", GATE_IP_GEN, 4, 0, 0),
@@ -615,6 +660,31 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
GATE(CLK_WDT, "wdt", "div_aclk66", GATE_IP_PERIS, 19, 0, 0),
GATE(CLK_RTC, "rtc", "div_aclk66", GATE_IP_PERIS, 20, 0, 0),
GATE(CLK_TMU, "tmu", "div_aclk66", GATE_IP_PERIS, 21, 0, 0),
+ GATE(CLK_SMMU_TV, "smmu_tv", "mout_aclk200_disp1_sub",
+ GATE_IP_DISP1, 2, 0, 0),
+ GATE(CLK_SMMU_FIMD1, "smmu_fimd1", "mout_aclk200_disp1_sub",
+ GATE_IP_DISP1, 8, 0, 0),
+ GATE(CLK_SMMU_2D, "smmu_2d", "div_aclk200", GATE_IP_ACP, 7, 0, 0),
+ GATE(CLK_SMMU_FIMC_ISP, "smmu_fimc_isp", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP0, 8, 0, 0),
+ GATE(CLK_SMMU_FIMC_DRC, "smmu_fimc_drc", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP0, 9, 0, 0),
+ GATE(CLK_SMMU_FIMC_FD, "smmu_fimc_fd", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP0, 10, 0, 0),
+ GATE(CLK_SMMU_FIMC_SCC, "smmu_fimc_scc", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP0, 11, 0, 0),
+ GATE(CLK_SMMU_FIMC_SCP, "smmu_fimc_scp", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP0, 12, 0, 0),
+ GATE(CLK_SMMU_FIMC_MCU, "smmu_fimc_mcu", "mout_aclk_400_isp_sub",
+ GATE_IP_ISP0, 13, 0, 0),
+ GATE(CLK_SMMU_FIMC_ODC, "smmu_fimc_odc", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP1, 4, 0, 0),
+ GATE(CLK_SMMU_FIMC_DIS0, "smmu_fimc_dis0", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP1, 5, 0, 0),
+ GATE(CLK_SMMU_FIMC_DIS1, "smmu_fimc_dis1", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP1, 6, 0, 0),
+ GATE(CLK_SMMU_FIMC_3DNR, "smmu_fimc_3dnr", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP1, 7, 0, 0),
};
static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = {
@@ -686,6 +756,9 @@ static struct of_device_id ext_clk_match[] __initdata = {
/* register exynox5250 clocks */
static void __init exynos5250_clk_init(struct device_node *np)
{
+ struct samsung_clk_provider *ctx;
+ unsigned int tmp;
+
if (np) {
reg_base = of_iomap(np, 0);
if (!reg_base)
@@ -694,11 +767,13 @@ static void __init exynos5250_clk_init(struct device_node *np)
panic("%s: unable to determine soc\n", __func__);
}
- samsung_clk_init(np, reg_base, CLK_NR_CLKS);
- samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
+ ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
+ if (!ctx)
+ panic("%s: unable to allocate context.\n", __func__);
+ samsung_clk_of_register_fixed_ext(ctx, exynos5250_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
ext_clk_match);
- samsung_clk_register_mux(exynos5250_pll_pmux_clks,
+ samsung_clk_register_mux(ctx, exynos5250_pll_pmux_clks,
ARRAY_SIZE(exynos5250_pll_pmux_clks));
if (_get_rate("fin_pll") == 24 * MHZ) {
@@ -709,19 +784,40 @@ static void __init exynos5250_clk_init(struct device_node *np)
if (_get_rate("mout_vpllsrc") == 24 * MHZ)
exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl;
- samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
- reg_base);
- samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
+ samsung_clk_register_pll(ctx, exynos5250_plls,
+ ARRAY_SIZE(exynos5250_plls),
+ reg_base);
+ samsung_clk_register_fixed_rate(ctx, exynos5250_fixed_rate_clks,
ARRAY_SIZE(exynos5250_fixed_rate_clks));
- samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks,
+ samsung_clk_register_fixed_factor(ctx, exynos5250_fixed_factor_clks,
ARRAY_SIZE(exynos5250_fixed_factor_clks));
- samsung_clk_register_mux(exynos5250_mux_clks,
+ samsung_clk_register_mux(ctx, exynos5250_mux_clks,
ARRAY_SIZE(exynos5250_mux_clks));
- samsung_clk_register_div(exynos5250_div_clks,
+ samsung_clk_register_div(ctx, exynos5250_div_clks,
ARRAY_SIZE(exynos5250_div_clks));
- samsung_clk_register_gate(exynos5250_gate_clks,
+ samsung_clk_register_gate(ctx, exynos5250_gate_clks,
ARRAY_SIZE(exynos5250_gate_clks));
+ /*
+ * Enable arm clock down (in idle) and set arm divider
+ * ratios in WFI/WFE state.
+ */
+ tmp = (PWR_CTRL1_CORE2_DOWN_RATIO | PWR_CTRL1_CORE1_DOWN_RATIO |
+ 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);
+ __raw_writel(tmp, reg_base + PWR_CTRL1);
+
+ /*
+ * Enable arm clock up (on exiting idle). Set arm divider
+ * ratios when not in idle along with the standby duration
+ * ratios.
+ */
+ tmp = (PWR_CTRL2_DIV2_UP_EN | PWR_CTRL2_DIV1_UP_EN |
+ PWR_CTRL2_DUR_STANDBY2_VAL | PWR_CTRL2_DUR_STANDBY1_VAL |
+ PWR_CTRL2_CORE2_UP_RATIO | PWR_CTRL2_CORE1_UP_RATIO);
+ __raw_writel(tmp, reg_base + PWR_CTRL2);
+
exynos5250_clk_sleep_init();
pr_info("Exynos5250: clock setup completed, armclk=%ld\n",