On Wed 21 Sep 2022 at 17:01, Yu Tu <yu.tu@xxxxxxxxxxx> wrote: > Hi Jerome, > > On 2022/8/30 16:20, Yu Tu wrote: >> On 2022/8/29 20:19, Jerome Brunet wrote: >>> [ EXTERNAL EMAIL ] >>> >>> >>> On Tue 16 Aug 2022 at 20:00, Yu Tu <yu.tu@xxxxxxxxxxx> wrote: >>> >>> Please trim your replies >>> >>>>>> diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig >>>>>> index f4244edc7b28..ec6beb9284d3 100644 >>>>>> --- a/drivers/clk/meson/Kconfig >>>>>> +++ b/drivers/clk/meson/Kconfig >>>>>> @@ -127,4 +127,17 @@ config COMMON_CLK_S4_PLL >>>>>> Support for the pll clock controller on Amlogic S805X2 and >>>>>> S905Y4 devices, >>>>>> aka s4. Amlogic S805X2 and S905Y4 devices include AQ222 and >>>>>> AQ229. >>>>>> Say Y if you want peripherals and CPU frequency scaling to >>>>>> work. >>>>>> + >>>>>> +config COMMON_CLK_S4 >>>>>> + tristate "S4 SoC Peripherals clock controllers support" >>>>>> + depends on ARM64 >>>>>> + default y >>>>>> + select COMMON_CLK_MESON_REGMAP >>>>>> + select COMMON_CLK_MESON_DUALDIV >>>>>> + select COMMON_CLK_MESON_VID_PLL_DIV >>>>>> + select COMMON_CLK_S4_PLL >>>>> Do you really this ? your driver does not even include the related >>>>> header. >>>> If the PLL driver is not turned on in DTS, will it not cause an error? >>>>> >>> >>> I don't get the question. >>> Kconfig list compile deps. S4 PLL is not a compile dep of the peripheral >>> controller. >>> >>> If you really want to, you may use 'imply'. >> V4 has been changed as you suggested. > > The next edition is being changed according to your requirements. Please > give us your valuable opinions. > >> >>>>> >>>>>> +static const struct clk_parent_data sys_ab_clk_parent_data[] = { >>>>>> + { .fw_name = "xtal" }, >>>>>> + { .fw_name = "fclk_div2" }, >>>>>> + { .fw_name = "fclk_div3" }, >>>>>> + { .fw_name = "fclk_div4" }, >>>>>> + { .fw_name = "fclk_div5" }, >>>>>> + { .fw_name = "fclk_div7" }, >>>>>> + { .hw = &s4_rtc_clk.hw } >>>>>> +}; >>>>>> + >>>>>> +static struct clk_regmap s4_sysclk_b_sel = { >>>>>> + .data = &(struct clk_regmap_mux_data){ >>>>>> + .offset = CLKCTRL_SYS_CLK_CTRL0, >>>>>> + .mask = 0x7, >>>>>> + .shift = 26, >>>>>> + .table = mux_table_sys_ab_clk_sel, >>>>>> + }, >>>>>> + .hw.init = &(struct clk_init_data){ >>>>>> + .name = "sysclk_b_sel", >>>>>> + .ops = &clk_regmap_mux_ro_ops, >>>>> Why is this using the RO ops ? >>>> Sys_clk is initialized during the Uboot phase and is fixed at >>>> 166.666MHz. So I'm going to change it to ro. >>> >>> That really much depends on the bootloader and is a pretty weak design. >>> The bootloader deps should be kept as minimal as possible. >>> >>> I see no reason for RO. >>> >>> You may cut rate propagation on the user if you need to and continue to >>> whatever you want in your u-boot >> I think I know what you mean. But we let the user be in control and not >> set the frequency, which can be risky. If you insist, I will change it as >> you suggest. > > It has been changed as you requested. > >> >>> >>>>> >>>>>> + .parent_data = sys_ab_clk_parent_data, >>>>>> + .num_parents = ARRAY_SIZE(sys_ab_clk_parent_data), >>>>>> + }, >>>>>> +}; >>>>>> + >>>>>> +static struct clk_regmap s4_sysclk_b_div = { >>>>>> + .data = &(struct clk_regmap_div_data){ >>>>>> + .offset = CLKCTRL_SYS_CLK_CTRL0, >>>>>> + .shift = 16, >>>>>> + .width = 10, >>>>>> + }, >>>>>> + .hw.init = &(struct clk_init_data){ >>>>>> + .name = "sysclk_b_div", >>>>>> + .ops = &clk_regmap_divider_ro_ops, >>>>> Same here and for the rest of the sys part >>>> Same above. >>> >>> We can play that game for a while >> Ah, you're so funny. >> >>> >>>>>> + >>>>>> +/* Video Clocks */ >>>>>> +static struct clk_regmap s4_vid_pll_div = { >>>>>> + .data = &(struct meson_vid_pll_div_data){ >>>>>> + .val = { >>>>>> + .reg_off = CLKCTRL_VID_PLL_CLK_DIV, >>>>>> + .shift = 0, >>>>>> + .width = 15, >>>>>> + }, >>>>>> + .sel = { >>>>>> + .reg_off = CLKCTRL_VID_PLL_CLK_DIV, >>>>>> + .shift = 16, >>>>>> + .width = 2, >>>>>> + }, >>>>>> + }, >>>>>> + .hw.init = &(struct clk_init_data) { >>>>>> + .name = "vid_pll_div", >>>>>> + .ops = &meson_vid_pll_div_ro_ops, >>>>> Why RO ? applies to the rest of the video part. >>>> Because vid_pll_div parent is HDMI_PLL, and HDMI_PLL is a fixed >>>> frequency. Flags is CLK_SET_RATE_PARENT. So we use RO. >>> >>> If the HDMI_PLL is fixed somehow, that is not reason for this clock to >>> be RO >>> >>>> Can I remove RO and use CLK_SET_RATE_NO_REPARENT instead, which one do >>>> you >>>> think is more reasonable? >>> >>> Neither. CLK_SET_RATE_NO_REPARENT makes no sense, it is not mux >>> >> "drivers/clk/meson/vid-pll-div.c" >> This file only provides ro_ops. Maybe the submission records will give us >> the answer. >> In fact, our hardware design is the same as the G12 series. > > I don't know if you checked this commit, but there is only one "ro_ops"in > this place right now. > > The S4 SoC is consistent with the G12A/B and GX series. > I missed the vid_pll type, Ok then. >> >>>> >>>>> >>>>>> + .parent_data = (const struct clk_parent_data []) { >>>>>> + { .fw_name = "hdmi_pll", } >>>>>> + }, >>>>>> + .num_parents = 1, >>>>>> + .flags = CLK_SET_RATE_PARENT, >>>>>> + }, >>>>>> +}; >>>>>> + >>>>>> +static struct clk_regmap s4_vid_pll_sel = { >>>>>> + .data = &(struct clk_regmap_mux_data){ >>>>>> + .offset = CLKCTRL_VID_PLL_CLK_DIV, >>>>>> + .mask = 0x1, >>>>>> + .shift = 18, >>>>>> + }, >>>>>> + .hw.init = &(struct clk_init_data){ >>>>>> + .name = "vid_pll_sel", >>>>>> + .ops = &clk_regmap_mux_ops, >>>>>> + /* >>>>>> + * bit 18 selects from 2 possible parents: >>>>>> + * vid_pll_div or hdmi_pll >>>>>> + */ >>>>>> + .parent_data = (const struct clk_parent_data []) { >>>>>> + { .hw = &s4_vid_pll_div.hw }, >>>>>> + { .fw_name = "hdmi_pll", } >>>>>> + }, >>>>>> + .num_parents = 2, >>>>>> + .flags = CLK_SET_RATE_NO_REPARENT, >>>>> Why ? are you planning to DT assigned clocks to statically set this ? >>>> Because vid_pll_sel one parent is HDMI_PLL, and HDMI_PLL is a fixed >>>> frequency. To prevent modification, use CLK_SET_RATE_NO_REPARENT. >>> >>> Again, this makes no sense. >> Unfortunately you don't read V4, in fact I have corrected in V4. >> ".flags = CLK_SET_RATE_PARENT," in V4. Is that okay with you? > > I don't know what you think? > ok >> >>> >>>>> >>>>>> + }, >>>>>> +}; >>>>>> + >>>>>> +static struct clk_regmap s4_vid_pll = { >>>>>> + .data = &(struct clk_regmap_gate_data){ >>>>>> + .offset = CLKCTRL_VID_PLL_CLK_DIV, >>>>>> + .bit_idx = 19, >>>>>> + }, >>>>>> + .hw.init = &(struct clk_init_data) { >>>>>> + .name = "vid_pll", >>>>>> + .ops = &clk_regmap_gate_ops, >>>>>> + .parent_hws = (const struct clk_hw *[]) { >>>>>> + &s4_vid_pll_sel.hw >>>>>> + }, >>>>>> + .num_parents = 1, >>>>>> + .flags = CLK_SET_RATE_PARENT, >>>>>> + }, >>>>>> +}; >>>>>> + >>>>>> +static const struct clk_parent_data s4_vclk_parent_data[] = { >>>>>> + { .hw = &s4_vid_pll.hw }, >>>>>> + { .fw_name = "gp0_pll", }, >>>>>> + { .fw_name = "hifi_pll", }, >>>>>> + { .fw_name = "mpll1", }, >>>>>> + { .fw_name = "fclk_div3", }, >>>>>> + { .fw_name = "fclk_div4", }, >>>>>> + { .fw_name = "fclk_div5", }, >>>>>> + { .fw_name = "fclk_div7", }, >>>>>> +}; >>>>>> + >>>>>> +static struct clk_regmap s4_vclk_sel = { >>>>>> + .data = &(struct clk_regmap_mux_data){ >>>>>> + .offset = CLKCTRL_VID_CLK_CTRL, >>>>>> + .mask = 0x7, >>>>>> + .shift = 16, >>>>>> + }, >>>>>> + .hw.init = &(struct clk_init_data){ >>>>>> + .name = "vclk_sel", >>>>>> + .ops = &clk_regmap_mux_ops, >>>>>> + .parent_data = s4_vclk_parent_data, >>>>>> + .num_parents = ARRAY_SIZE(s4_vclk_parent_data), >>>>>> + .flags = CLK_SET_RATE_NO_REPARENT, >>>>> Same >>>> Since fclk_div* is a fixed frequency value, mplL1 and hifi_pll and >>>> gp0_pll >>>> are used by other specialized modules, vid_pll has >>>> CLK_SET_RATE_PARENT. The >>>> parent of vid_pll is that vid_pll_sel uses CLK_SET_RATE_NO_REPARENT. >>> >>> Still not good. >>> >>> You don't have CLK_SET_RATE, propagation is stopped and parent clock >>> will not changed. The best parent will be picked but not changed. >>> >>> If one parent MUST NOT be picked, just remove it from the list and add a >>> explaining why >>> >>> [...] >> Okay. > > In the next edition I will change it to ".flags = CLK_SET_RATE_PARENT". > If you clock rate propagation is ok, then OK >> >>> >>>>>> + >>>>>> +static struct clk_regmap s4_ts_clk_div = { >>>>>> + .data = &(struct clk_regmap_div_data){ >>>>>> + .offset = CLKCTRL_TS_CLK_CTRL, >>>>>> + .shift = 0, >>>>>> + .width = 8, >>>>>> + }, >>>>>> + .hw.init = &(struct clk_init_data){ >>>>>> + .name = "ts_clk_div", >>>>>> + .ops = &clk_regmap_divider_ops, >>>>>> + .parent_data = &(const struct clk_parent_data) { >>>>>> + .fw_name = "xtal", >>>>>> + }, >>>>>> + .num_parents = 1, >>>>> propagation stopped ? >>>> Its parent is xtal, so I should use CLK_SET_RATE_NO_REPARENT. >>> >>> Still no. You seem to have problem with the meaning of >>> CLK_SET_RATE_NO_REPARENT. >>> >>> * CLK_SET_RATE_NO_REPARENT: means the parent will no be changed, even if >>> selecting another parent would result in a closer rate to the >>> request. It makes sense only if the clock has several parents >>> >>> * CLK_SET_RATE_PARENT: means rate change may propagate the parent, >>> meaning the rate of the parent may change if it help the child achieve >>> a closer rate to the request >> Thank you for explaining.I got it. >> >>> >>>>> >>>>>> + }, >>>>>> +}; >>>>>> + >>>>>> +static struct clk_regmap s4_ts_clk_gate = { >>>>>> + .data = &(struct clk_regmap_gate_data){ >>>>>> + .offset = CLKCTRL_TS_CLK_CTRL, >>>>>> + .bit_idx = 8, >>>>>> + }, >>>>>> + .hw.init = &(struct clk_init_data){ >>>>>> + .name = "ts_clk", >>>>>> + .ops = &clk_regmap_gate_ops, >>>>>> + .parent_hws = (const struct clk_hw *[]) { >>>>>> + &s4_ts_clk_div.hw >>>>>> + }, >>>>>> + .num_parents = 1, >>>>>> + }, >>>>> propagation stopped ? >>>> I will add CLK_SET_RATE_PARENT. >>> >>> [...] >>> >>>>>> +/* EMMC/NAND clock */ >>>>>> + >>>>>> +static const struct clk_parent_data s4_sd_emmc_clk0_parent_data[] = { >>>>>> + { .fw_name = "xtal", }, >>>>>> + { .fw_name = "fclk_div2", }, >>>>>> + { .fw_name = "fclk_div3", }, >>>>>> + { .fw_name = "hifi_pll", }, >>>>>> + { .fw_name = "fclk_div2p5", }, >>>>>> + /* >>>>>> + * Following these parent clocks, we should also have had mpll2, >>>>>> mpll3 >>>>>> + * and gp0_pll but these clocks are too precious to be used >>>>>> here. All >>>>>> + * the necessary rates for MMC and NAND operation can be >>>>>> acheived using >>>>>> + * hifi_pll or fclk_div clocks >>>>>> + */ >>>>> You don't want to list mplls but hifi_pll is fine ? seems dangerous. >>>> hifi pll is for EMMC and NAND on this SoC. >>> >>> That deserve a better explanation. >>> Why can't it use fdiv2 and xtal like the previous SoCs ? >>> >>> Which PLLs are you using for Audio then ? >>> Typical operation on these SoCs usually require 3 PLLs to acheive all >>> rates >>> >> I'll list all the clocks and let the driver itself select Parent as >> needed. > > I don't know what you think? > ok >> >>>>> >>> >>> >>>>>> +/* >>>>>> + * gen clk is designed for debug/monitor some internal clock >>>>>> quality. Some of the >>>>>> + * corresponding clock sources are not described in the clock tree, >>>>>> so they are skipped. >>>>>> + */ >>>>> Still feels a bit light, don't you think ? Among all the clocks, can't >>>>> you add a bit more parents here ? It would certainly help debug down >>>>> the road >>>> [16:12] is gen_clk source select.All is: >>>> 0: cts_oscin_clk >>>> 1:cts_rtc_clk >>>> 2:sys_pll_div16 (internal clock) >>>> 3:ddr_pll_div32 (internal clock) >>>> 4: vid_pll >>>> 5: gp0_pll >>>> 7: hifi_pll >>>> 10:adc_dpll_clk_b3 (internal clock for debug) >>>> 11:adc_dpll_intclk (internal clock for debug) >>>> 12:clk_msr_src(select from all internal clock except PLLs); >>>> 16: no used >>>> 17: sys_cpu_clk_div16 (internal clock) >>>> 19: fclk_div2 >>>> 20: fclk_div2p5 >>>> 21: fclk_div3 >>>> 22: fclk_div4 >>>> 23: fclk_div5 >>>> 24: fclk_div7 >>>> 25: mpll0 >>>> 26: mpll1 >>>> 27: mpll2 >>>> 28: mpll3 >>>> So i only added the clocks that will actually be used, and some >>>> debugging >>>> clock peripherals will not be used. >>> >>> you may at least add vid_pll >> Okay. > > It has been changed as you suggested. > >> >>> >>>>> >>>>>> +static u32 s4_gen_clk_mux_table[] = { 0, 5, 7, 19, 21, 22, >>>>>> + 23, 24, 25, 26, 27, 28 }; >>>>>> +static const struct clk_parent_data s4_gen_clk_parent_data[] = { >>>>>> + { .fw_name = "xtal", }, >>>>>> + { .fw_name = "gp0_pll", }, >>>>>> + { .fw_name = "hifi_pll", }, >>>>>> + { .fw_name = "fclk_div2", }, >>>>>> + { .fw_name = "fclk_div3", }, >>>>>> + { .fw_name = "fclk_div4", }, >>>>>> + { .fw_name = "fclk_div5", }, >>>>>> + { .fw_name = "fclk_div7", }, >>>>>> + { .fw_name = "mpll0", }, >>>>>> + { .fw_name = "mpll1", }, >>>>>> + { .fw_name = "mpll2", }, >>>>>> + { .fw_name = "mpll3", }, >>>>>> +}; >>> >>> .