On Tue, 7 Nov 2023 at 03:36, Stephen Boyd <sboyd@xxxxxxxxxx> wrote: > > Quoting Stephen Boyd (2023-11-03 18:24:47) > > Quoting Dmitry Baryshkov (2023-10-03 18:23:07) > > > + > > > + ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg); > > > + if (ret) > > > + return ret; > > > + > > > + return FIELD_GET(CFG_SRC_SEL_MASK, cfg) != rcg->safe_src_index; > > > +} > > > + > > > +static int clk_rcg2_parked_init(struct clk_hw *hw) > > > +{ > > > + struct clk_rcg2 *rcg = to_clk_rcg2(hw); > > > + const struct freq_tbl *f = rcg->freq_tbl; > > > + > > > + regmap_read(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), &rcg->parked_cfg); > > > > I need this part today to fix a stuck clk problem I see on trogdor.lazor > > where during registration a call to clk_ops::get_parent() sees the clk > > isn't enabled at boot (because there isn't a clk_ops::is_enabled() > > function) so clk_rcg2_shared_get_parent() reads the parent from the > > 'parked_cfg' value, which is zero. If the hardware actually has non-zero > > for the parent then the framework will get the wrong parent, which is > > what happens on trogdor when the devmode screen is shown. The parent is > > the display PLL instead of XO. I haven't dug far enough to understand > > why disabling unused clks wedges the branch when we try to enable it > > again, but not disabling unused clks fixes the problem or reading the > > config register at registration to get the proper parent also fixes it. > > I guess the problem is that we're switching the RCG value when we > > shouldn't be doing that. > > > > I looked at this more today. It seems that I need to both read the > config register at init and also move over the rcg to the safe source at > init (i.e. park the clk at init). That's doable with a call to > clk_rcg2_shared_disable() for the clk_ops::init callback. Otherwise I > get a stuck clk warning. > > Either > > disp_cc_mdss_mdp_clk status stuck at 'off' > > or > > disp_cc_mdss_rot_clk status stuck at 'on' > > When I don't park the rcg, the disp_cc_mdss_rot_clk gets stuck during > disabling of unused clks. I think I understand that problem. What > happens is disp_cc_mdss_mdp_clk_src and disp_cc_mdss_rot_clk_src are > both sourcing from disp_cc_pll0 at boot. Fixing the parent mapping makes > it so that enabling and then disabling disp_cc_mdss_ahb_clk causes > disp_cc_pll0 to be turned off when disp_cc_mdss_rot_clk_src is sourced > from it (and the branch disp_cc_mdss_rot_clk is enabled). If we park > both the rcgs at clk registration time we avoid this problem because the > PLL is disabled but nothing is actually a child clk. The act of reading > the config register and stashing that in the 'parked_cfg' only helps > avoid duplicate calls to change the rate, and doesn't help when we try > to repoint the clk at XO when the parent PLL is off. > > The part I still don't understand is why reading the config register at > init and stashing that in 'parked_cfg' fixes the disp_cc_mdss_mdp_clk > stuck at off problem. I see that the branch clk is turned off and on > many times during boot and there aren't any warnings regardless of > stashing the config register. That means we should be moving the RCG to > XO source, between forcibly enabling and disabling the RCG, which > presumably would complain about being unable to update the config > register, but it doesn't. Only after late init does the clk fail to > enable, and the source is still XO at that time. Something else must be > happening that wedges the branch to the point that it can't be > recovered. But simply reporting the proper parent is enough for > disp_cc_mdss_mdp_clk. I suppose that the issue is caused by mdss_gdsc or mmcx also being shut down at the late_init. And if I remember correctly, properly parking disp_cc_mdss_mdp_clk to the XO solves this issue. This is where is_enabled comes to play. Adding it changes the clk_disable_unused behaviour. -- With best wishes Dmitry