diff options
Diffstat (limited to 'drivers/clk/sunxi-ng/ccu-sun50i-h616.c')
-rw-r--r-- | drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c index b001d0c03534..190816c35da9 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c @@ -1107,11 +1107,24 @@ static const u32 usb2_clk_regs[] = { SUN50I_H616_USB3_CLK_REG, }; +static struct ccu_mux_nb sun50i_h616_cpu_nb = { + .common = &cpux_clk.common, + .cm = &cpux_clk.mux, + .delay_us = 1, /* manual doesn't really say */ + .bypass_index = 4, /* PLL_PERI0@600MHz, as recommended by manual */ +}; + +static struct ccu_pll_nb sun50i_h616_pll_cpu_nb = { + .common = &pll_cpux_clk.common, + .enable = BIT(29), /* LOCK_ENABLE */ + .lock = BIT(28), +}; + static int sun50i_h616_ccu_probe(struct platform_device *pdev) { void __iomem *reg; u32 val; - int i; + int ret, i; reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) @@ -1166,7 +1179,18 @@ static int sun50i_h616_ccu_probe(struct platform_device *pdev) val |= BIT(24); writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG); - return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h616_ccu_desc); + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h616_ccu_desc); + if (ret) + return ret; + + /* Reparent CPU during CPU PLL rate changes */ + ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk, + &sun50i_h616_cpu_nb); + + /* Re-lock the CPU PLL after any rate changes */ + ccu_pll_notifier_register(&sun50i_h616_pll_cpu_nb); + + return 0; } static const struct of_device_id sun50i_h616_ccu_ids[] = { @@ -1185,6 +1209,6 @@ static struct platform_driver sun50i_h616_ccu_driver = { }; module_platform_driver(sun50i_h616_ccu_driver); -MODULE_IMPORT_NS(SUNXI_CCU); +MODULE_IMPORT_NS("SUNXI_CCU"); MODULE_DESCRIPTION("Support for the Allwinner H616 CCU"); MODULE_LICENSE("GPL"); |