diff options
Diffstat (limited to 'drivers/clk/sunxi-ng')
27 files changed, 94 insertions, 7 deletions
diff --git a/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c b/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c index 9d3ffd3fb2c1..0736f6c81269 100644 --- a/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c @@ -125,6 +125,7 @@ static const struct of_device_id sun20i_d1_r_ccu_ids[] = { { .compatible = "allwinner,sun20i-d1-r-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun20i_d1_r_ccu_ids); static struct platform_driver sun20i_d1_r_ccu_driver = { .probe = sun20i_d1_r_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun20i-d1.c b/drivers/clk/sunxi-ng/ccu-sun20i-d1.c index 48a8fb2c43b7..60756aadfad6 100644 --- a/drivers/clk/sunxi-ng/ccu-sun20i-d1.c +++ b/drivers/clk/sunxi-ng/ccu-sun20i-d1.c @@ -1394,6 +1394,7 @@ static const struct of_device_id sun20i_d1_ccu_ids[] = { { .compatible = "allwinner,sun20i-d1-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun20i_d1_ccu_ids); static struct platform_driver sun20i_d1_ccu_driver = { .probe = sun20i_d1_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c index 451ebb7c99a3..14f5c3da652b 100644 --- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c +++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c @@ -1481,6 +1481,7 @@ static const struct of_device_id sun4i_a10_ccu_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(of, sun4i_a10_ccu_ids); static struct platform_driver sun4i_a10_ccu_driver = { .probe = sun4i_a10_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c index fddd6c877cec..3b983bb59bd9 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c @@ -202,6 +202,7 @@ static const struct of_device_id sun50i_a100_r_ccu_ids[] = { { .compatible = "allwinner,sun50i-a100-r-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun50i_a100_r_ccu_ids); static struct platform_driver sun50i_a100_r_ccu_driver = { .probe = sun50i_a100_r_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c index 5f93b5526e13..38aa6e5f298e 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c @@ -1264,6 +1264,7 @@ static const struct of_device_id sun50i_a100_ccu_ids[] = { { .compatible = "allwinner,sun50i-a100-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun50i_a100_ccu_ids); static struct platform_driver sun50i_a100_ccu_driver = { .probe = sun50i_a100_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c index 8951ffc14ff5..491b16cfe368 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c @@ -171,17 +171,21 @@ static struct ccu_nkm pll_mipi_clk = { * user manual, and by experiments the PLL doesn't work without * these bits toggled. */ - .enable = BIT(31) | BIT(23) | BIT(22), - .lock = BIT(28), - .n = _SUNXI_CCU_MULT(8, 4), - .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), - .m = _SUNXI_CCU_DIV(0, 4), + .enable = BIT(31) | BIT(23) | BIT(22), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT(8, 4), + .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), + .m = _SUNXI_CCU_DIV(0, 4), + .max_m_n_ratio = 3, + .min_parent_m_ratio = 24000000, .common = { .reg = 0x040, .hw.init = CLK_HW_INIT("pll-mipi", "pll-video0", &ccu_nkm_ops, CLK_SET_RATE_UNGATE | CLK_SET_RATE_PARENT), .features = CCU_FEATURE_CLOSEST_RATE, + .min_rate = 500000000, + .max_rate = 1400000000, }, }; @@ -978,6 +982,7 @@ static const struct of_device_id sun50i_a64_ccu_ids[] = { { .compatible = "allwinner,sun50i-a64-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun50i_a64_ccu_ids); static struct platform_driver sun50i_a64_ccu_driver = { .probe = sun50i_a64_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c index 02b28cfc5525..e2dc29fa99e7 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c @@ -244,6 +244,7 @@ static const struct of_device_id sun50i_h6_r_ccu_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(of, sun50i_h6_r_ccu_ids); static struct platform_driver sun50i_h6_r_ccu_driver = { .probe = sun50i_h6_r_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c index 42568c616181..e6421c2ba122 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c @@ -1181,11 +1181,18 @@ static const u32 usb2_clk_regs[] = { SUN50I_H6_USB3_CLK_REG, }; +static struct ccu_mux_nb sun50i_h6_cpu_nb = { + .common = &cpux_clk.common, + .cm = &cpux_clk.mux, + .delay_us = 1, + .bypass_index = 0, /* index of 24 MHz oscillator */ +}; + static int sun50i_h6_ccu_probe(struct platform_device *pdev) { void __iomem *reg; + int i, ret; u32 val; - int i; reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) @@ -1252,13 +1259,22 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev) val |= BIT(24); writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG); - return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc); + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc); + if (ret) + return ret; + + /* Reparent CPU during PLL CPUX rate changes */ + ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk, + &sun50i_h6_cpu_nb); + + return 0; } static const struct of_device_id sun50i_h6_ccu_ids[] = { { .compatible = "allwinner,sun50i-h6-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun50i_h6_ccu_ids); static struct platform_driver sun50i_h6_ccu_driver = { .probe = sun50i_h6_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c index 21e918582aa5..45aae1ae5178 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c @@ -1154,6 +1154,7 @@ static const struct of_device_id sun50i_h616_ccu_ids[] = { { .compatible = "allwinner,sun50i-h616-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun50i_h616_ccu_ids); static struct platform_driver sun50i_h616_ccu_driver = { .probe = sun50i_h616_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c index 0762deffb33c..8cb8cbbdbafb 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c @@ -1271,6 +1271,7 @@ static const struct of_device_id sun6i_a31_ccu_ids[] = { { .compatible = "allwinner,sun6i-a31-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun6i_a31_ccu_ids); static struct platform_driver sun6i_a31_ccu_driver = { .probe = sun6i_a31_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c index fdc8ccc586c9..5a98c4e9e667 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c +++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c @@ -336,6 +336,7 @@ static const struct of_device_id sun6i_rtc_ccu_match[] = { }, {}, }; +MODULE_DEVICE_TABLE(of, sun6i_rtc_ccu_match); int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg) { diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c index e80cc3864e44..e748ad612b8f 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c @@ -751,6 +751,7 @@ static const struct of_device_id sun8i_a23_ccu_ids[] = { { .compatible = "allwinner,sun8i-a23-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun8i_a23_ccu_ids); static struct platform_driver sun8i_a23_ccu_driver = { .probe = sun8i_a23_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c index d12878a1ba9e..8a27a1777600 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c @@ -823,6 +823,7 @@ static const struct of_device_id sun8i_a33_ccu_ids[] = { { .compatible = "allwinner,sun8i-a33-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun8i_a33_ccu_ids); static struct platform_driver sun8i_a33_ccu_driver = { .probe = sun8i_a33_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c index 76cbd9e9e89f..93eca47935cf 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c @@ -911,6 +911,7 @@ static const struct of_device_id sun8i_a83t_ccu_ids[] = { { .compatible = "allwinner,sun8i-a83t-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun8i_a83t_ccu_ids); static struct platform_driver sun8i_a83t_ccu_driver = { .probe = sun8i_a83t_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c index 6a043a0a9dd6..b0b8dba239ae 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c @@ -337,6 +337,7 @@ static const struct of_device_id sunxi_de2_clk_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(of, sunxi_de2_clk_ids); static struct platform_driver sunxi_de2_clk_driver = { .probe = sunxi_de2_clk_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c index 74274c17efb3..ca5739fa04f7 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c @@ -1082,6 +1082,7 @@ static const struct of_device_id sun8i_h3_ccu_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(of, sun8i_h3_ccu_ids); static struct platform_driver sun8i_h3_ccu_driver = { .probe = sun8i_h3_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-r.c index 4890a976b1a0..bac7e737db98 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r.c @@ -262,6 +262,7 @@ static const struct of_device_id sun8i_r_ccu_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(of, sun8i_r_ccu_ids); static struct platform_driver sun8i_r_ccu_driver = { .probe = sun8i_r_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c index 31eca0d3bc1e..3774b293e74c 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c @@ -1363,6 +1363,7 @@ static const struct of_device_id sun8i_r40_ccu_ids[] = { { .compatible = "allwinner,sun8i-r40-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun8i_r40_ccu_ids); static struct platform_driver sun8i_r40_ccu_driver = { .probe = sun8i_r40_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c index f3ce8664b288..994258a3ad2e 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c @@ -768,6 +768,7 @@ static const struct of_device_id sun8i_v3s_ccu_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(of, sun8i_v3s_ccu_ids); static struct platform_driver sun8i_v3s_ccu_driver = { .probe = sun8i_v3s_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c index 1d8b1ae1619d..ae7939d3f502 100644 --- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c +++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c @@ -254,6 +254,7 @@ static const struct of_device_id sun9i_a80_de_clk_ids[] = { { .compatible = "allwinner,sun9i-a80-de-clks" }, { } }; +MODULE_DEVICE_TABLE(of, sun9i_a80_de_clk_ids); static struct platform_driver sun9i_a80_de_clk_driver = { .probe = sun9i_a80_de_clk_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c index a0fb0da8f356..bfa2ff9d52a4 100644 --- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c +++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c @@ -127,6 +127,7 @@ static const struct of_device_id sun9i_a80_usb_clk_ids[] = { { .compatible = "allwinner,sun9i-a80-usb-clks" }, { } }; +MODULE_DEVICE_TABLE(of, sun9i_a80_usb_clk_ids); static struct platform_driver sun9i_a80_usb_clk_driver = { .probe = sun9i_a80_usb_clk_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c index 730fd8e28014..c05805e4ad22 100644 --- a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c +++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c @@ -1236,6 +1236,7 @@ static const struct of_device_id sun9i_a80_ccu_ids[] = { { .compatible = "allwinner,sun9i-a80-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun9i_a80_ccu_ids); static struct platform_driver sun9i_a80_ccu_driver = { .probe = sun9i_a80_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c index 0d5b60b123b7..76d3d070b2a7 100644 --- a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c +++ b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c @@ -565,6 +565,7 @@ static const struct of_device_id suniv_f1c100s_ccu_ids[] = { { .compatible = "allwinner,suniv-f1c100s-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, suniv_f1c100s_ccu_ids); static struct platform_driver suniv_f1c100s_ccu_driver = { .probe = suniv_f1c100s_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c index 8babce55302f..ac0091b4ce24 100644 --- a/drivers/clk/sunxi-ng/ccu_common.c +++ b/drivers/clk/sunxi-ng/ccu_common.c @@ -44,6 +44,16 @@ bool ccu_is_better_rate(struct ccu_common *common, unsigned long current_rate, unsigned long best_rate) { + unsigned long min_rate, max_rate; + + clk_hw_get_rate_range(&common->hw, &min_rate, &max_rate); + + if (current_rate > max_rate) + return false; + + if (current_rate < min_rate) + return false; + if (common->features & CCU_FEATURE_CLOSEST_RATE) return abs(current_rate - target_rate) < abs(best_rate - target_rate); @@ -122,6 +132,7 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev, for (i = 0; i < desc->hw_clks->num ; i++) { struct clk_hw *hw = desc->hw_clks->hws[i]; + struct ccu_common *common = hw_to_ccu_common(hw); const char *name; if (!hw) @@ -136,6 +147,14 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev, pr_err("Couldn't register clock %d - %s\n", i, name); goto err_clk_unreg; } + + if (common->max_rate) + clk_hw_set_rate_range(hw, common->min_rate, + common->max_rate); + else + WARN(common->min_rate, + "No max_rate, ignoring min_rate of clock %d - %s\n", + i, name); } ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h index 942a72c09437..329734f8cf42 100644 --- a/drivers/clk/sunxi-ng/ccu_common.h +++ b/drivers/clk/sunxi-ng/ccu_common.h @@ -31,6 +31,9 @@ struct ccu_common { u16 lock_reg; u32 prediv; + unsigned long min_rate; + unsigned long max_rate; + unsigned long features; spinlock_t *lock; struct clk_hw hw; diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c index 853f84398e2b..1168d894d636 100644 --- a/drivers/clk/sunxi-ng/ccu_nkm.c +++ b/drivers/clk/sunxi-ng/ccu_nkm.c @@ -16,6 +16,20 @@ struct _ccu_nkm { unsigned long m, min_m, max_m; }; +static bool ccu_nkm_is_valid_rate(struct ccu_common *common, unsigned long parent, + unsigned long n, unsigned long m) +{ + struct ccu_nkm *nkm = container_of(common, struct ccu_nkm, common); + + if (nkm->max_m_n_ratio && (m > nkm->max_m_n_ratio * n)) + return false; + + if (nkm->min_parent_m_ratio && (parent < nkm->min_parent_m_ratio * m)) + return false; + + return true; +} + static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common *common, struct clk_hw *parent_hw, unsigned long *parent, unsigned long rate, @@ -31,6 +45,10 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common *common unsigned long tmp_rate, tmp_parent; tmp_parent = clk_hw_round_rate(parent_hw, rate * _m / (_n * _k)); + + if (!ccu_nkm_is_valid_rate(common, tmp_parent, _n, _m)) + continue; + tmp_rate = tmp_parent * _n * _k / _m; if (ccu_is_better_rate(common, rate, tmp_rate, best_rate) || @@ -64,6 +82,9 @@ static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate, for (_k = nkm->min_k; _k <= nkm->max_k; _k++) { for (_n = nkm->min_n; _n <= nkm->max_n; _n++) { for (_m = nkm->min_m; _m <= nkm->max_m; _m++) { + if (!ccu_nkm_is_valid_rate(common, parent, _n, _m)) + continue; + unsigned long tmp_rate; tmp_rate = parent * _n * _k / _m; diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h index 6601defb3f38..c409212ee40e 100644 --- a/drivers/clk/sunxi-ng/ccu_nkm.h +++ b/drivers/clk/sunxi-ng/ccu_nkm.h @@ -27,6 +27,8 @@ struct ccu_nkm { struct ccu_mux_internal mux; unsigned int fixed_post_div; + unsigned long max_m_n_ratio; + unsigned long min_parent_m_ratio; struct ccu_common common; }; |