Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

clk: mediatek: clk-pll: Add ops for PLLs using set/clr regs and FENC

MT8196 uses a combination of set/clr registers to control the PLL
enable state, along with a FENC bit to check the preparation status.
Add new set of PLL clock operations with support for set/clr enable and
FENC status logic.

Reviewed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Chen-Yu Tsai <wenst@chromium.org>
Signed-off-by: Laura Nao <laura.nao@collabora.com>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

Laura Nao and committed by
Stephen Boyd
2c327a17 aee9ffa0

+44 -1
+40 -1
drivers/clk/mediatek/clk-pll.c
··· 37 37 return (readl(pll->en_addr) & BIT(pll->data->pll_en_bit)) != 0; 38 38 } 39 39 40 + static int mtk_pll_fenc_is_prepared(struct clk_hw *hw) 41 + { 42 + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); 43 + 44 + return !!(readl(pll->fenc_addr) & BIT(pll->data->fenc_sta_bit)); 45 + } 46 + 40 47 static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin, 41 48 u32 pcw, int postdiv) 42 49 { ··· 281 274 writel(r, pll->pwr_addr); 282 275 } 283 276 277 + static int mtk_pll_prepare_setclr(struct clk_hw *hw) 278 + { 279 + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); 280 + 281 + writel(BIT(pll->data->pll_en_bit), pll->en_set_addr); 282 + 283 + /* Wait 20us after enable for the PLL to stabilize */ 284 + udelay(20); 285 + 286 + return 0; 287 + } 288 + 289 + static void mtk_pll_unprepare_setclr(struct clk_hw *hw) 290 + { 291 + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); 292 + 293 + writel(BIT(pll->data->pll_en_bit), pll->en_clr_addr); 294 + } 295 + 284 296 const struct clk_ops mtk_pll_ops = { 285 297 .is_prepared = mtk_pll_is_prepared, 286 298 .prepare = mtk_pll_prepare, ··· 308 282 .round_rate = mtk_pll_round_rate, 309 283 .set_rate = mtk_pll_set_rate, 310 284 }; 285 + 286 + const struct clk_ops mtk_pll_fenc_clr_set_ops = { 287 + .is_prepared = mtk_pll_fenc_is_prepared, 288 + .prepare = mtk_pll_prepare_setclr, 289 + .unprepare = mtk_pll_unprepare_setclr, 290 + .recalc_rate = mtk_pll_recalc_rate, 291 + .round_rate = mtk_pll_round_rate, 292 + .set_rate = mtk_pll_set_rate, 293 + }; 294 + EXPORT_SYMBOL_GPL(mtk_pll_fenc_clr_set_ops); 311 295 312 296 struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll, 313 297 const struct mtk_pll_data *data, ··· 351 315 pll->hw.init = &init; 352 316 pll->data = data; 353 317 318 + pll->fenc_addr = base + data->fenc_sta_ofs; 319 + 354 320 init.name = data->name; 355 321 init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0; 356 322 init.ops = pll_ops; ··· 375 337 { 376 338 struct mtk_clk_pll *pll; 377 339 struct clk_hw *hw; 340 + const struct clk_ops *pll_ops = data->ops ? data->ops : &mtk_pll_ops; 378 341 379 342 pll = kzalloc(sizeof(*pll), GFP_KERNEL); 380 343 if (!pll) 381 344 return ERR_PTR(-ENOMEM); 382 345 383 - hw = mtk_clk_register_pll_ops(pll, data, base, &mtk_pll_ops); 346 + hw = mtk_clk_register_pll_ops(pll, data, base, pll_ops); 384 347 if (IS_ERR(hw)) 385 348 kfree(pll); 386 349
+4
drivers/clk/mediatek/clk-pll.h
··· 29 29 u32 reg; 30 30 u32 pwr_reg; 31 31 u32 en_mask; 32 + u32 fenc_sta_ofs; 32 33 u32 pd_reg; 33 34 u32 tuner_reg; 34 35 u32 tuner_en_reg; ··· 52 51 u32 en_clr_reg; 53 52 u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */ 54 53 u8 pcw_chg_bit; 54 + u8 fenc_sta_bit; 55 55 }; 56 56 57 57 /* ··· 74 72 void __iomem *en_addr; 75 73 void __iomem *en_set_addr; 76 74 void __iomem *en_clr_addr; 75 + void __iomem *fenc_addr; 77 76 const struct mtk_pll_data *data; 78 77 }; 79 78 ··· 85 82 struct clk_hw_onecell_data *clk_data); 86 83 87 84 extern const struct clk_ops mtk_pll_ops; 85 + extern const struct clk_ops mtk_pll_fenc_clr_set_ops; 88 86 89 87 static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw) 90 88 {