Commit a2254930 authored by Stephen Boyd's avatar Stephen Boyd

Merge tag 'sunxi-clk-fixes-for-6.9-1' of...

Merge tag 'sunxi-clk-fixes-for-6.9-1' of https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux into clk-fixes

Pull Allwinner clk driver fixes from Jernej Skrabec:

 - fix H6 CPU rate change via reparenting
 - set A64 MIPI PLL min & max rate

* tag 'sunxi-clk-fixes-for-6.9-1' of https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux:
  clk: sunxi-ng: a64: Set minimum and maximum rate for PLL-MIPI
  clk: sunxi-ng: common: Support minimum and maximum rate
  clk: sunxi-ng: h6: Reparent CPUX during PLL CPUX rate change
parents f8981b0d 69f16d9b
...@@ -182,6 +182,8 @@ static struct ccu_nkm pll_mipi_clk = { ...@@ -182,6 +182,8 @@ static struct ccu_nkm pll_mipi_clk = {
&ccu_nkm_ops, &ccu_nkm_ops,
CLK_SET_RATE_UNGATE | CLK_SET_RATE_PARENT), CLK_SET_RATE_UNGATE | CLK_SET_RATE_PARENT),
.features = CCU_FEATURE_CLOSEST_RATE, .features = CCU_FEATURE_CLOSEST_RATE,
.min_rate = 500000000,
.max_rate = 1400000000,
}, },
}; };
......
...@@ -1181,11 +1181,18 @@ static const u32 usb2_clk_regs[] = { ...@@ -1181,11 +1181,18 @@ static const u32 usb2_clk_regs[] = {
SUN50I_H6_USB3_CLK_REG, 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) static int sun50i_h6_ccu_probe(struct platform_device *pdev)
{ {
void __iomem *reg; void __iomem *reg;
int i, ret;
u32 val; u32 val;
int i;
reg = devm_platform_ioremap_resource(pdev, 0); reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg)) if (IS_ERR(reg))
...@@ -1252,7 +1259,15 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev) ...@@ -1252,7 +1259,15 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
val |= BIT(24); val |= BIT(24);
writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG); 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[] = { static const struct of_device_id sun50i_h6_ccu_ids[] = {
......
...@@ -44,6 +44,16 @@ bool ccu_is_better_rate(struct ccu_common *common, ...@@ -44,6 +44,16 @@ bool ccu_is_better_rate(struct ccu_common *common,
unsigned long current_rate, unsigned long current_rate,
unsigned long best_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) if (common->features & CCU_FEATURE_CLOSEST_RATE)
return abs(current_rate - target_rate) < abs(best_rate - target_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, ...@@ -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++) { for (i = 0; i < desc->hw_clks->num ; i++) {
struct clk_hw *hw = desc->hw_clks->hws[i]; struct clk_hw *hw = desc->hw_clks->hws[i];
struct ccu_common *common = hw_to_ccu_common(hw);
const char *name; const char *name;
if (!hw) if (!hw)
...@@ -136,6 +147,14 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev, ...@@ -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); pr_err("Couldn't register clock %d - %s\n", i, name);
goto err_clk_unreg; 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, ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
......
...@@ -31,6 +31,9 @@ struct ccu_common { ...@@ -31,6 +31,9 @@ struct ccu_common {
u16 lock_reg; u16 lock_reg;
u32 prediv; u32 prediv;
unsigned long min_rate;
unsigned long max_rate;
unsigned long features; unsigned long features;
spinlock_t *lock; spinlock_t *lock;
struct clk_hw hw; struct clk_hw hw;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment