1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2016 Maxime Ripard
4 * Maxime Ripard <maxime.ripard@free-electrons.com>
7 #include <linux/clk-provider.h>
9 #include <linux/spinlock.h>
13 bool ccu_frac_helper_is_enabled(struct ccu_common
*common
,
14 struct ccu_frac_internal
*cf
)
16 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
19 return !(readl(common
->base
+ common
->reg
) & cf
->enable
);
21 EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_is_enabled
, "SUNXI_CCU");
23 void ccu_frac_helper_enable(struct ccu_common
*common
,
24 struct ccu_frac_internal
*cf
)
29 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
32 spin_lock_irqsave(common
->lock
, flags
);
33 reg
= readl(common
->base
+ common
->reg
);
34 writel(reg
& ~cf
->enable
, common
->base
+ common
->reg
);
35 spin_unlock_irqrestore(common
->lock
, flags
);
37 EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_enable
, "SUNXI_CCU");
39 void ccu_frac_helper_disable(struct ccu_common
*common
,
40 struct ccu_frac_internal
*cf
)
45 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
48 spin_lock_irqsave(common
->lock
, flags
);
49 reg
= readl(common
->base
+ common
->reg
);
50 writel(reg
| cf
->enable
, common
->base
+ common
->reg
);
51 spin_unlock_irqrestore(common
->lock
, flags
);
53 EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_disable
, "SUNXI_CCU");
55 bool ccu_frac_helper_has_rate(struct ccu_common
*common
,
56 struct ccu_frac_internal
*cf
,
59 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
62 return (cf
->rates
[0] == rate
) || (cf
->rates
[1] == rate
);
64 EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_has_rate
, "SUNXI_CCU");
66 unsigned long ccu_frac_helper_read_rate(struct ccu_common
*common
,
67 struct ccu_frac_internal
*cf
)
71 pr_debug("%s: Read fractional\n", clk_hw_get_name(&common
->hw
));
73 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
76 pr_debug("%s: clock is fractional (rates %lu and %lu)\n",
77 clk_hw_get_name(&common
->hw
), cf
->rates
[0], cf
->rates
[1]);
79 reg
= readl(common
->base
+ common
->reg
);
81 pr_debug("%s: clock reg is 0x%x (select is 0x%x)\n",
82 clk_hw_get_name(&common
->hw
), reg
, cf
->select
);
84 return (reg
& cf
->select
) ? cf
->rates
[1] : cf
->rates
[0];
86 EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_read_rate
, "SUNXI_CCU");
88 int ccu_frac_helper_set_rate(struct ccu_common
*common
,
89 struct ccu_frac_internal
*cf
,
90 unsigned long rate
, u32 lock
)
95 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
98 if (cf
->rates
[0] == rate
)
100 else if (cf
->rates
[1] == rate
)
105 spin_lock_irqsave(common
->lock
, flags
);
106 reg
= readl(common
->base
+ common
->reg
);
108 writel(reg
| sel
, common
->base
+ common
->reg
);
109 spin_unlock_irqrestore(common
->lock
, flags
);
111 ccu_helper_wait_for_lock(common
, lock
);
115 EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_set_rate
, "SUNXI_CCU");