author | Jian Hu <jian.hu@amlogic.com> | 2019-05-08 11:52:28 (GMT) |
---|---|---|
committer | Jian Hu <jian.hu@amlogic.com> | 2019-08-01 11:29:39 (GMT) |
commit | 5c40910faec42ff81772f94a1f3539c687261b0c (patch) | |
tree | 5c97d1e769fbcca6f02e336905653173a7323ee8 | |
parent | 75eac27815f36c778c8c509299ff0a967eafd5a9 (diff) | |
download | common-5c40910faec42ff81772f94a1f3539c687261b0c.zip common-5c40910faec42ff81772f94a1f3539c687261b0c.tar.gz common-5c40910faec42ff81772f94a1f3539c687261b0c.tar.bz2 |
clk: tl1: add clk81 mux clock [1/1]
PD#SWPL-8215
Problem:
1.clk81 can not switch to 24M
2.fixed pll can set rate
call clk_prepare_enable to open it
call clk_disable_unprepare to close it
Solution:
1.add clk81 mux clock
2.change fixed pll callback Read only to R/W
Verify:
test passed on tm2 ab301
Change-Id: I426d4307f19647afcb0166a23c1988df1b504807
Signed-off-by: Jian Hu <jian.hu@amlogic.com>
-rw-r--r-- | drivers/amlogic/clk/clkc.h | 2 | ||||
-rw-r--r-- | drivers/amlogic/clk/tl1/tl1.c | 29 | ||||
-rw-r--r-- | drivers/amlogic/clk/tl1/tl1_ao.c | 2 | ||||
-rw-r--r-- | drivers/amlogic/clk/tl1/tl1_clk-pll.c | 44 | ||||
-rw-r--r-- | include/dt-bindings/clock/amlogic,tl1-clkc.h | 6 |
5 files changed, 69 insertions, 14 deletions
diff --git a/drivers/amlogic/clk/clkc.h b/drivers/amlogic/clk/clkc.h index 7deac3e..b23fd61 100644 --- a/drivers/amlogic/clk/clkc.h +++ b/drivers/amlogic/clk/clkc.h @@ -53,7 +53,7 @@ struct pll_rate_table { u16 n; u16 od; u16 od2; - u16 frac; + u32 frac; }; struct fclk_rate_table { diff --git a/drivers/amlogic/clk/tl1/tl1.c b/drivers/amlogic/clk/tl1/tl1.c index 86207a9..ee90068 100644 --- a/drivers/amlogic/clk/tl1/tl1.c +++ b/drivers/amlogic/clk/tl1/tl1.c @@ -185,6 +185,10 @@ static struct meson_clk_pll tl1_adc_pll = { }; #endif +static const struct pll_rate_table tl1_fixed_pll_rate_table[] = { + PLL_FRAC_RATE(2000000000ULL, 166, 1, 1, 0, 0x3F15555), +}; + static struct meson_clk_pll tl1_fixed_pll = { .m = { .reg_off = HHI_FIX_PLL_CNTL0, @@ -207,12 +211,14 @@ static struct meson_clk_pll tl1_fixed_pll = { .width = 19, }, .lock = &clk_lock, + .rate_table = tl1_fixed_pll_rate_table, + .rate_count = ARRAY_SIZE(tl1_fixed_pll_rate_table), .hw.init = &(struct clk_init_data){ .name = "fixed_pll", - .ops = &meson_tl1_pll_ro_ops, + .ops = &meson_tl1_pll_ops, .parent_names = (const char *[]){ "xtal" }, .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, + .flags = CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED, }, }; @@ -676,6 +682,19 @@ static struct clk_gate tl1_clk81 = { }, }; +static struct clk_mux tl1_switch_clk81 = { + .reg = (void *)HHI_MPEG_CLK_CNTL, + .mask = 0x1, + .shift = 8, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "switch_clk81", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "xtal", "clk81" }, + .num_parents = 2, + }, +}; + /* Everything Else (EE) domain gates */ /* HHI_GCLK_MPEG0 26 bits valid */ static MESON_GATE_TL1(tl1_ddr, HHI_GCLK_MPEG0, 0); @@ -881,6 +900,7 @@ static struct clk_hw *tl1_clk_hws[] = { [CLKID_DSU_PRE_PARENT0] = &tl1_dsu_pre0_clk.hw, [CLKID_DSU_PRE_CLK] = &tl1_dsu_pre_clk.hw, [CLKID_DSU_CLK] = &tl1_dsu_clk.hw, + [CLKID_SWITCH_CLK81] = &tl1_switch_clk81.hw, }; /* Convenience tables to populate base addresses in .probe */ @@ -1101,6 +1121,9 @@ static void __init tl1_clkc_init(struct device_node *np) tl1_dsu_clk.reg = clk_base + (unsigned long)tl1_dsu_clk.reg; + tl1_switch_clk81.reg = clk_base + + (unsigned long)tl1_switch_clk81.reg; + /* Populate base address for gates */ for (i = 0; i < ARRAY_SIZE(tl1_clk_gates); i++) tl1_clk_gates[i]->reg = clk_base + @@ -1127,6 +1150,8 @@ static void __init tl1_clkc_init(struct device_node *np) WARN_ON(IS_ERR(clks[clkid])); } } + clks[CLKID_SWITCH_CLK81] = clk_register(NULL, &tl1_switch_clk81.hw); + WARN_ON(IS_ERR(clks[CLKID_SWITCH_CLK81])); meson_tl1_sdemmc_init(); meson_tl1_media_init(); diff --git a/drivers/amlogic/clk/tl1/tl1_ao.c b/drivers/amlogic/clk/tl1/tl1_ao.c index b3c099c..ab6bca5 100644 --- a/drivers/amlogic/clk/tl1/tl1_ao.c +++ b/drivers/amlogic/clk/tl1/tl1_ao.c @@ -172,7 +172,7 @@ static int tl1_aoclkc_probe(struct platform_device *pdev) tl1_saradc_div.reg = aoclk_base + (unsigned long)tl1_saradc_div.reg; tl1_saradc_gate.reg = aoclk_base + (unsigned long)tl1_saradc_gate.reg; - for (clkid = CLKID_AO_BASE; clkid < NR_CLKS; clkid++) { + for (clkid = CLKID_AO_BASE; clkid < CLKID_AO_END; clkid++) { if (tl1_ao_clk_hws[clkid-CLKID_AO_BASE]) { clks[clkid] = clk_register(NULL, tl1_ao_clk_hws[clkid-CLKID_AO_BASE]); diff --git a/drivers/amlogic/clk/tl1/tl1_clk-pll.c b/drivers/amlogic/clk/tl1/tl1_clk-pll.c index 69eac78..473e644 100644 --- a/drivers/amlogic/clk/tl1/tl1_clk-pll.c +++ b/drivers/amlogic/clk/tl1/tl1_clk-pll.c @@ -55,6 +55,14 @@ #define TL1_SYS_PLL_CNTL4 0x88770290 #define TL1_SYS_PLL_CNTL5 0x39272000 +#define TL1_FIXED_PLL_CNTL0 0xD00104A6 +#define TL1_FIXED_PLL_CNTL1 0x3F15555 +#define TL1_FIXED_PLL_CNTL2 0x00000000 +#define TL1_FIXED_PLL_CNTL3 0x6A285C60 +#define TL1_FIXED_PLL_CNTL4 0x65771290 +#define TL1_FIXED_PLL_CNTL5 0x39272000 +#define TL1_FIXED_PLL_CNTL6 0x56540000 +#define TL1_FIXED_PLL_TST 0xA000004F #define TL1_GP0_PLL_CNTL1 0x00000000 #define TL1_GP0_PLL_CNTL2 0x00000000 @@ -165,16 +173,20 @@ static long meson_tl1_pll_round_rate(struct clk_hw *hw, unsigned long rate, for (i = 0; i < pll->rate_count; i++) { if (rate <= rate_table[i].rate) { ret_rate = rate_table[i].rate; - if (!strcmp(clk_hw_get_name(hw), "sys_pll")) + if (!strcmp(clk_hw_get_name(hw), "sys_pll") + || !strcmp(clk_hw_get_name(hw), "fixed_pll")) do_div(ret_rate, 1000); + return ret_rate; } } /* else return the smallest value */ ret_rate = rate_table[0].rate; - if (!strcmp(clk_hw_get_name(hw), "sys_pll")) + if (!strcmp(clk_hw_get_name(hw), "sys_pll") + || !strcmp(clk_hw_get_name(hw), "fixed_pll")) do_div(ret_rate, 1000); + return ret_rate; } @@ -223,7 +235,8 @@ static int meson_tl1_pll_set_rate(struct clk_hw *hw, unsigned long rate, if (parent_rate == 0 || rate == 0) return -EINVAL; - if (!strcmp(clk_hw_get_name(hw), "sys_pll")) + if (!strcmp(clk_hw_get_name(hw), "sys_pll") + || !strcmp(clk_hw_get_name(hw), "fixed_pll")) rate *= 1000; old_rate = rate; @@ -331,14 +344,30 @@ static int meson_tl1_pll_set_rate(struct clk_hw *hw, unsigned long rate, cntlbase + (unsigned long)(0*4)); writel(TM2_PCIE_PLL_CNTL2_, cntlbase + (unsigned long)(7*4)); + } else if (!strcmp(clk_hw_get_name(hw), "fixed_pll")) { + writel((readl(cntlbase) | MESON_PLL_RESET) + & (~MESON_PLL_ENABLE), cntlbase); + + udelay(100); + writel(TL1_FIXED_PLL_CNTL1, + cntlbase + (unsigned long)(1*4)); + writel(TL1_FIXED_PLL_CNTL2, + cntlbase + (unsigned long)(2*4)); + writel(TL1_FIXED_PLL_CNTL3, + cntlbase + (unsigned long)(3*4)); + writel(TL1_FIXED_PLL_CNTL4, + cntlbase + (unsigned long)(4*4)); + writel(TL1_FIXED_PLL_CNTL5, + cntlbase + (unsigned long)(5*4)); + writel(TL1_FIXED_PLL_CNTL6, + cntlbase + (unsigned long)(6*4)); + udelay(10); } else { pr_err("%s: %s pll not found!!!\n", __func__, clk_hw_get_name(hw)); return -EINVAL; } - /* when set rate for pcie pll, do not set M/N/OD/frac registers bit */ - if (strcmp(clk_hw_get_name(hw), "pcie_pll")) { reg = readl(pll->base + p->reg_off); tmp = rate_set->n; @@ -379,7 +408,6 @@ static int meson_tl1_pll_set_rate(struct clk_hw *hw, unsigned long rate, reg = PARM_SET(p->width, p->shift, reg, tmp); writel(reg, pll->base + p->reg_off); } - } p = &pll->n; /* PLL reset */ @@ -427,7 +455,8 @@ static int meson_tl1_pll_enable(struct clk_hw *hw) if (!strcmp(clk_hw_get_name(hw), "gp0_pll") || !strcmp(clk_hw_get_name(hw), "gp1_pll") || !strcmp(clk_hw_get_name(hw), "hifi_pll") - || !strcmp(clk_hw_get_name(hw), "sys_pll")) { + || !strcmp(clk_hw_get_name(hw), "sys_pll") + || !strcmp(clk_hw_get_name(hw), "fixed_pll")) { void *cntlbase = pll->base + p->reg_off; if (readl(cntlbase + (unsigned long)(6*4)) @@ -435,7 +464,6 @@ static int meson_tl1_pll_enable(struct clk_hw *hw) first_set = 0; } - parent = clk_hw_get_parent(hw); /*First init, just set minimal rate.*/ diff --git a/include/dt-bindings/clock/amlogic,tl1-clkc.h b/include/dt-bindings/clock/amlogic,tl1-clkc.h index 733d470..a37705b 100644 --- a/include/dt-bindings/clock/amlogic,tl1-clkc.h +++ b/include/dt-bindings/clock/amlogic,tl1-clkc.h @@ -161,7 +161,6 @@ #define CLKID_VCLK2_VENCLMMC (GATE_OTHER + 14) #define CLKID_VCLK2_VENCL (GATE_OTHER + 15) #define CLKID_VCLK2_OTHER1 (GATE_OTHER + 16) - /*HHI_GCLK_OTHER: 0x55*/ #define GATE_AO_BASE (GATE_OTHER + 17) @@ -298,5 +297,8 @@ #define CLKID_AO_UART2 (CLKID_AO_BASE + 10) #define CLKID_AO_IR_BLASTER (CLKID_AO_BASE + 11) #define CLKID_AO_SAR_ADC (CLKID_AO_BASE + 12) -#define NR_CLKS (CLKID_AO_BASE + 13) +#define CLKID_AO_END (CLKID_AO_BASE + 13) +#define CLKID_SWITCH_CLK81 (CLKID_AO_BASE + 13) +#define NR_CLKS (CLKID_AO_BASE + 14) + #endif /* __DT_BINDINGS_TL1_CLKC_H */ |