2 * Copyright (C) 2016 Maxime Ripard
3 * Maxime Ripard <maxime.ripard@free-electrons.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
11 #include <linux/clk-provider.h>
12 #include <linux/spinlock.h>
16 bool ccu_frac_helper_is_enabled(struct ccu_common
*common
,
17 struct ccu_frac_internal
*cf
)
19 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
22 return !(readl(common
->base
+ common
->reg
) & cf
->enable
);
25 void ccu_frac_helper_enable(struct ccu_common
*common
,
26 struct ccu_frac_internal
*cf
)
31 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
34 spin_lock_irqsave(common
->lock
, flags
);
35 reg
= readl(common
->base
+ common
->reg
);
36 writel(reg
& ~cf
->enable
, common
->base
+ common
->reg
);
37 spin_unlock_irqrestore(common
->lock
, flags
);
40 void ccu_frac_helper_disable(struct ccu_common
*common
,
41 struct ccu_frac_internal
*cf
)
46 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
49 spin_lock_irqsave(common
->lock
, flags
);
50 reg
= readl(common
->base
+ common
->reg
);
51 writel(reg
| cf
->enable
, common
->base
+ common
->reg
);
52 spin_unlock_irqrestore(common
->lock
, flags
);
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
);
65 unsigned long ccu_frac_helper_read_rate(struct ccu_common
*common
,
66 struct ccu_frac_internal
*cf
)
70 pr_debug("%s: Read fractional\n", clk_hw_get_name(&common
->hw
));
72 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
75 pr_debug("%s: clock is fractional (rates %lu and %lu)\n",
76 clk_hw_get_name(&common
->hw
), cf
->rates
[0], cf
->rates
[1]);
78 reg
= readl(common
->base
+ common
->reg
);
80 pr_debug("%s: clock reg is 0x%x (select is 0x%x)\n",
81 clk_hw_get_name(&common
->hw
), reg
, cf
->select
);
83 return (reg
& cf
->select
) ? cf
->rates
[1] : cf
->rates
[0];
86 int ccu_frac_helper_set_rate(struct ccu_common
*common
,
87 struct ccu_frac_internal
*cf
,
88 unsigned long rate
, u32 lock
)
93 if (!(common
->features
& CCU_FEATURE_FRACTIONAL
))
96 if (cf
->rates
[0] == rate
)
98 else if (cf
->rates
[1] == rate
)
103 spin_lock_irqsave(common
->lock
, flags
);
104 reg
= readl(common
->base
+ common
->reg
);
106 writel(reg
| sel
, common
->base
+ common
->reg
);
107 spin_unlock_irqrestore(common
->lock
, flags
);
109 ccu_helper_wait_for_lock(common
, lock
);