summaryrefslogtreecommitdiff
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.c83
1 files changed, 72 insertions, 11 deletions
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index e7ee4420da81..1416c9703266 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -24,6 +24,8 @@
#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
@@ -37,6 +39,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 +74,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 +84,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 +119,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 +157,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,
@@ -189,10 +214,12 @@ 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" };
@@ -273,12 +300,16 @@ 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_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),
@@ -351,6 +382,8 @@ 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_aclk66_pre", "mout_mpll_user", DIV_TOP1, 24, 3),
@@ -428,6 +461,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 +567,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),
@@ -686,6 +721,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 +732,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 +749,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",