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>
This commit is contained in:
Jian Hu
2019-05-08 19:52:28 +08:00
parent 75eac27815
commit 5c40910fae
5 changed files with 69 additions and 14 deletions

View File

@@ -53,7 +53,7 @@ struct pll_rate_table {
u16 n;
u16 od;
u16 od2;
u16 frac;
u32 frac;
};
struct fclk_rate_table {

View File

@@ -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();

View File

@@ -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]);

View File

@@ -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.*/

View File

@@ -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 */