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
);
22 void ccu_frac_helper_enable(struct ccu_common
*common
,
23 struct ccu_frac_internal
*cf
)
28 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
31 spin_lock_irqsave(common
->lock
, flags
);
32 reg
= readl(common
->base
+ common
->reg
);
33 writel(reg
& ~cf
->enable
, common
->base
+ common
->reg
);
34 spin_unlock_irqrestore(common
->lock
, flags
);
37 void ccu_frac_helper_disable(struct ccu_common
*common
,
38 struct ccu_frac_internal
*cf
)
43 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
46 spin_lock_irqsave(common
->lock
, flags
);
47 reg
= readl(common
->base
+ common
->reg
);
48 writel(reg
| cf
->enable
, common
->base
+ common
->reg
);
49 spin_unlock_irqrestore(common
->lock
, flags
);
52 bool ccu_frac_helper_has_rate(struct ccu_common
*common
,
53 struct ccu_frac_internal
*cf
,
56 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
59 return (cf
->rates
[0] == rate
) || (cf
->rates
[1] == rate
);
62 unsigned long ccu_frac_helper_read_rate(struct ccu_common
*common
,
63 struct ccu_frac_internal
*cf
)
67 pr_debug("%s: Read fractional\n", clk_hw_get_name(&common
->hw
));
69 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
72 pr_debug("%s: clock is fractional (rates %lu and %lu)\n",
73 clk_hw_get_name(&common
->hw
), cf
->rates
[0], cf
->rates
[1]);
75 reg
= readl(common
->base
+ common
->reg
);
77 pr_debug("%s: clock reg is 0x%x (select is 0x%x)\n",
78 clk_hw_get_name(&common
->hw
), reg
, cf
->select
);
80 return (reg
& cf
->select
) ? cf
->rates
[1] : cf
->rates
[0];
83 int ccu_frac_helper_set_rate(struct ccu_common
*common
,
84 struct ccu_frac_internal
*cf
,
85 unsigned long rate
, u32 lock
)
90 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
93 if (cf
->rates
[0] == rate
)
95 else if (cf
->rates
[1] == rate
)
100 spin_lock_irqsave(common
->lock
, flags
);
101 reg
= readl(common
->base
+ common
->reg
);
103 writel(reg
| sel
, common
->base
+ common
->reg
);
104 spin_unlock_irqrestore(common
->lock
, flags
);
106 ccu_helper_wait_for_lock(common
, lock
);