Merge branch 'drm-fixes-5.0' of git://people.freedesktop.org/~agd5f/linux into drm...
[sfrench/cifs-2.6.git] / drivers / clk / imx / clk-frac-pll.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2018 NXP.
4  *
5  * This driver supports the fractional plls found in the imx8m SOCs
6  *
7  * Documentation for this fractional pll can be found at:
8  *   https://www.nxp.com/docs/en/reference-manual/IMX8MDQLQRM.pdf#page=834
9  */
10
11 #include <linux/clk-provider.h>
12 #include <linux/err.h>
13 #include <linux/iopoll.h>
14 #include <linux/slab.h>
15 #include <linux/bitfield.h>
16
17 #include "clk.h"
18
19 #define PLL_CFG0                0x0
20 #define PLL_CFG1                0x4
21
22 #define PLL_LOCK_STATUS         BIT(31)
23 #define PLL_PD_MASK             BIT(19)
24 #define PLL_BYPASS_MASK         BIT(14)
25 #define PLL_NEWDIV_VAL          BIT(12)
26 #define PLL_NEWDIV_ACK          BIT(11)
27 #define PLL_FRAC_DIV_MASK       GENMASK(30, 7)
28 #define PLL_INT_DIV_MASK        GENMASK(6, 0)
29 #define PLL_OUTPUT_DIV_MASK     GENMASK(4, 0)
30 #define PLL_FRAC_DENOM          0x1000000
31
32 #define PLL_FRAC_LOCK_TIMEOUT   10000
33 #define PLL_FRAC_ACK_TIMEOUT    500000
34
35 struct clk_frac_pll {
36         struct clk_hw   hw;
37         void __iomem    *base;
38 };
39
40 #define to_clk_frac_pll(_hw) container_of(_hw, struct clk_frac_pll, hw)
41
42 static int clk_wait_lock(struct clk_frac_pll *pll)
43 {
44         u32 val;
45
46         return readl_poll_timeout(pll->base, val, val & PLL_LOCK_STATUS, 0,
47                                         PLL_FRAC_LOCK_TIMEOUT);
48 }
49
50 static int clk_wait_ack(struct clk_frac_pll *pll)
51 {
52         u32 val;
53
54         /* return directly if the pll is in powerdown or in bypass */
55         if (readl_relaxed(pll->base) & (PLL_PD_MASK | PLL_BYPASS_MASK))
56                 return 0;
57
58         /* Wait for the pll's divfi and divff to be reloaded */
59         return readl_poll_timeout(pll->base, val, val & PLL_NEWDIV_ACK, 0,
60                                         PLL_FRAC_ACK_TIMEOUT);
61 }
62
63 static int clk_pll_prepare(struct clk_hw *hw)
64 {
65         struct clk_frac_pll *pll = to_clk_frac_pll(hw);
66         u32 val;
67
68         val = readl_relaxed(pll->base + PLL_CFG0);
69         val &= ~PLL_PD_MASK;
70         writel_relaxed(val, pll->base + PLL_CFG0);
71
72         return clk_wait_lock(pll);
73 }
74
75 static void clk_pll_unprepare(struct clk_hw *hw)
76 {
77         struct clk_frac_pll *pll = to_clk_frac_pll(hw);
78         u32 val;
79
80         val = readl_relaxed(pll->base + PLL_CFG0);
81         val |= PLL_PD_MASK;
82         writel_relaxed(val, pll->base + PLL_CFG0);
83 }
84
85 static int clk_pll_is_prepared(struct clk_hw *hw)
86 {
87         struct clk_frac_pll *pll = to_clk_frac_pll(hw);
88         u32 val;
89
90         val = readl_relaxed(pll->base + PLL_CFG0);
91         return (val & PLL_PD_MASK) ? 0 : 1;
92 }
93
94 static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
95                                          unsigned long parent_rate)
96 {
97         struct clk_frac_pll *pll = to_clk_frac_pll(hw);
98         u32 val, divff, divfi, divq;
99         u64 temp64 = parent_rate;
100         u64 rate;
101
102         val = readl_relaxed(pll->base + PLL_CFG0);
103         divq = (FIELD_GET(PLL_OUTPUT_DIV_MASK, val) + 1) * 2;
104         val = readl_relaxed(pll->base + PLL_CFG1);
105         divff = FIELD_GET(PLL_FRAC_DIV_MASK, val);
106         divfi = FIELD_GET(PLL_INT_DIV_MASK, val);
107
108         temp64 *= 8;
109         temp64 *= divff;
110         do_div(temp64, PLL_FRAC_DENOM);
111         do_div(temp64, divq);
112
113         rate = parent_rate * 8 * (divfi + 1);
114         do_div(rate, divq);
115         rate += temp64;
116
117         return rate;
118 }
119
120 static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
121                                unsigned long *prate)
122 {
123         u64 parent_rate = *prate;
124         u32 divff, divfi;
125         u64 temp64;
126
127         parent_rate *= 8;
128         rate *= 2;
129         temp64 = rate;
130         do_div(temp64, parent_rate);
131         divfi = temp64;
132         temp64 = rate - divfi * parent_rate;
133         temp64 *= PLL_FRAC_DENOM;
134         do_div(temp64, parent_rate);
135         divff = temp64;
136
137         temp64 = parent_rate;
138         temp64 *= divff;
139         do_div(temp64, PLL_FRAC_DENOM);
140
141         rate = parent_rate * divfi + temp64;
142
143         return rate / 2;
144 }
145
146 /*
147  * To simplify the clock calculation, we can keep the 'PLL_OUTPUT_VAL' at zero
148  * (means the PLL output will be divided by 2). So the PLL output can use
149  * the below formula:
150  * pllout = parent_rate * 8 / 2 * DIVF_VAL;
151  * where DIVF_VAL = 1 + DIVFI + DIVFF / 2^24.
152  */
153 static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
154                             unsigned long parent_rate)
155 {
156         struct clk_frac_pll *pll = to_clk_frac_pll(hw);
157         u32 val, divfi, divff;
158         u64 temp64;
159         int ret;
160
161         parent_rate *= 8;
162         rate *= 2;
163         divfi = rate / parent_rate;
164         temp64 = parent_rate * divfi;
165         temp64 = rate - temp64;
166         temp64 *= PLL_FRAC_DENOM;
167         do_div(temp64, parent_rate);
168         divff = temp64;
169
170         val = readl_relaxed(pll->base + PLL_CFG1);
171         val &= ~(PLL_FRAC_DIV_MASK | PLL_INT_DIV_MASK);
172         val |= (divff << 7) | (divfi - 1);
173         writel_relaxed(val, pll->base + PLL_CFG1);
174
175         val = readl_relaxed(pll->base + PLL_CFG0);
176         val &= ~0x1f;
177         writel_relaxed(val, pll->base + PLL_CFG0);
178
179         /* Set the NEV_DIV_VAL to reload the DIVFI and DIVFF */
180         val = readl_relaxed(pll->base + PLL_CFG0);
181         val |= PLL_NEWDIV_VAL;
182         writel_relaxed(val, pll->base + PLL_CFG0);
183
184         ret = clk_wait_ack(pll);
185
186         /* clear the NEV_DIV_VAL */
187         val = readl_relaxed(pll->base + PLL_CFG0);
188         val &= ~PLL_NEWDIV_VAL;
189         writel_relaxed(val, pll->base + PLL_CFG0);
190
191         return ret;
192 }
193
194 static const struct clk_ops clk_frac_pll_ops = {
195         .prepare        = clk_pll_prepare,
196         .unprepare      = clk_pll_unprepare,
197         .is_prepared    = clk_pll_is_prepared,
198         .recalc_rate    = clk_pll_recalc_rate,
199         .round_rate     = clk_pll_round_rate,
200         .set_rate       = clk_pll_set_rate,
201 };
202
203 struct clk *imx_clk_frac_pll(const char *name, const char *parent_name,
204                              void __iomem *base)
205 {
206         struct clk_init_data init;
207         struct clk_frac_pll *pll;
208         struct clk_hw *hw;
209         int ret;
210
211         pll = kzalloc(sizeof(*pll), GFP_KERNEL);
212         if (!pll)
213                 return ERR_PTR(-ENOMEM);
214
215         init.name = name;
216         init.ops = &clk_frac_pll_ops;
217         init.flags = 0;
218         init.parent_names = &parent_name;
219         init.num_parents = 1;
220
221         pll->base = base;
222         pll->hw.init = &init;
223
224         hw = &pll->hw;
225
226         ret = clk_hw_register(NULL, hw);
227         if (ret) {
228                 kfree(pll);
229                 return ERR_PTR(ret);
230         }
231
232         return hw->clk;
233 }