]> Git Repo - linux.git/blob - drivers/gpu/drm/sprd/megacores_pll.c
Merge tag 'mtd/for-5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux
[linux.git] / drivers / gpu / drm / sprd / megacores_pll.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020 Unisoc Inc.
4  */
5
6 #include <asm/div64.h>
7 #include <linux/delay.h>
8 #include <linux/init.h>
9 #include <linux/kernel.h>
10 #include <linux/regmap.h>
11 #include <linux/string.h>
12
13 #include "sprd_dsi.h"
14
15 #define L                                               0
16 #define H                                               1
17 #define CLK                                             0
18 #define DATA                                    1
19 #define INFINITY                                0xffffffff
20 #define MIN_OUTPUT_FREQ                 (100)
21
22 #define AVERAGE(a, b) (min(a, b) + abs((b) - (a)) / 2)
23
24 /* sharkle */
25 #define VCO_BAND_LOW    750
26 #define VCO_BAND_MID    1100
27 #define VCO_BAND_HIGH   1500
28 #define PHY_REF_CLK     26000
29
30 static int dphy_calc_pll_param(struct dphy_pll *pll)
31 {
32         const u32 khz = 1000;
33         const u32 mhz = 1000000;
34         const unsigned long long factor = 100;
35         unsigned long long tmp;
36         int i;
37
38         pll->potential_fvco = pll->freq / khz;
39         pll->ref_clk = PHY_REF_CLK / khz;
40
41         for (i = 0; i < 4; ++i) {
42                 if (pll->potential_fvco >= VCO_BAND_LOW &&
43                     pll->potential_fvco <= VCO_BAND_HIGH) {
44                         pll->fvco = pll->potential_fvco;
45                         pll->out_sel = BIT(i);
46                         break;
47                 }
48                 pll->potential_fvco <<= 1;
49         }
50         if (pll->fvco == 0)
51                 return -EINVAL;
52
53         if (pll->fvco >= VCO_BAND_LOW && pll->fvco <= VCO_BAND_MID) {
54                 /* vco band control */
55                 pll->vco_band = 0x0;
56                 /* low pass filter control */
57                 pll->lpf_sel = 1;
58         } else if (pll->fvco > VCO_BAND_MID && pll->fvco <= VCO_BAND_HIGH) {
59                 pll->vco_band = 0x1;
60                 pll->lpf_sel = 0;
61         } else {
62                 return -EINVAL;
63         }
64
65         pll->nint = pll->fvco / pll->ref_clk;
66         tmp = pll->fvco * factor * mhz;
67         do_div(tmp, pll->ref_clk);
68         tmp = tmp - pll->nint * factor * mhz;
69         tmp *= BIT(20);
70         do_div(tmp, 100000000);
71         pll->kint = (u32)tmp;
72         pll->refin = 3; /* pre-divider bypass */
73         pll->sdm_en = true; /* use fraction N PLL */
74         pll->fdk_s = 0x1; /* fraction */
75         pll->cp_s = 0x0;
76         pll->det_delay = 0x1;
77
78         return 0;
79 }
80
81 static void dphy_set_pll_reg(struct dphy_pll *pll, struct regmap *regmap)
82 {
83         u8 reg_val[9] = {0};
84         int i;
85
86         u8 reg_addr[] = {
87                 0x03, 0x04, 0x06, 0x08, 0x09,
88                 0x0a, 0x0b, 0x0e, 0x0f
89         };
90
91         reg_val[0] = 1 | (1 << 1) |  (pll->lpf_sel << 2);
92         reg_val[1] = pll->div | (1 << 3) | (pll->cp_s << 5) | (pll->fdk_s << 7);
93         reg_val[2] = pll->nint;
94         reg_val[3] = pll->vco_band | (pll->sdm_en << 1) | (pll->refin << 2);
95         reg_val[4] = pll->kint >> 12;
96         reg_val[5] = pll->kint >> 4;
97         reg_val[6] = pll->out_sel | ((pll->kint << 4) & 0xf);
98         reg_val[7] = 1 << 4;
99         reg_val[8] = pll->det_delay;
100
101         for (i = 0; i < sizeof(reg_addr); ++i) {
102                 regmap_write(regmap, reg_addr[i], reg_val[i]);
103                 DRM_DEBUG("%02x: %02x\n", reg_addr[i], reg_val[i]);
104         }
105 }
106
107 int dphy_pll_config(struct dsi_context *ctx)
108 {
109         struct sprd_dsi *dsi = container_of(ctx, struct sprd_dsi, ctx);
110         struct regmap *regmap = ctx->regmap;
111         struct dphy_pll *pll = &ctx->pll;
112         int ret;
113
114         pll->freq = dsi->slave->hs_rate;
115
116         /* FREQ = 26M * (NINT + KINT / 2^20) / out_sel */
117         ret = dphy_calc_pll_param(pll);
118         if (ret) {
119                 drm_err(dsi->drm, "failed to calculate dphy pll parameters\n");
120                 return ret;
121         }
122         dphy_set_pll_reg(pll, regmap);
123
124         return 0;
125 }
126
127 static void dphy_set_timing_reg(struct regmap *regmap, int type, u8 val[])
128 {
129         switch (type) {
130         case REQUEST_TIME:
131                 regmap_write(regmap, 0x31, val[CLK]);
132                 regmap_write(regmap, 0x41, val[DATA]);
133                 regmap_write(regmap, 0x51, val[DATA]);
134                 regmap_write(regmap, 0x61, val[DATA]);
135                 regmap_write(regmap, 0x71, val[DATA]);
136
137                 regmap_write(regmap, 0x90, val[CLK]);
138                 regmap_write(regmap, 0xa0, val[DATA]);
139                 regmap_write(regmap, 0xb0, val[DATA]);
140                 regmap_write(regmap, 0xc0, val[DATA]);
141                 regmap_write(regmap, 0xd0, val[DATA]);
142                 break;
143         case PREPARE_TIME:
144                 regmap_write(regmap, 0x32, val[CLK]);
145                 regmap_write(regmap, 0x42, val[DATA]);
146                 regmap_write(regmap, 0x52, val[DATA]);
147                 regmap_write(regmap, 0x62, val[DATA]);
148                 regmap_write(regmap, 0x72, val[DATA]);
149
150                 regmap_write(regmap, 0x91, val[CLK]);
151                 regmap_write(regmap, 0xa1, val[DATA]);
152                 regmap_write(regmap, 0xb1, val[DATA]);
153                 regmap_write(regmap, 0xc1, val[DATA]);
154                 regmap_write(regmap, 0xd1, val[DATA]);
155                 break;
156         case ZERO_TIME:
157                 regmap_write(regmap, 0x33, val[CLK]);
158                 regmap_write(regmap, 0x43, val[DATA]);
159                 regmap_write(regmap, 0x53, val[DATA]);
160                 regmap_write(regmap, 0x63, val[DATA]);
161                 regmap_write(regmap, 0x73, val[DATA]);
162
163                 regmap_write(regmap, 0x92, val[CLK]);
164                 regmap_write(regmap, 0xa2, val[DATA]);
165                 regmap_write(regmap, 0xb2, val[DATA]);
166                 regmap_write(regmap, 0xc2, val[DATA]);
167                 regmap_write(regmap, 0xd2, val[DATA]);
168                 break;
169         case TRAIL_TIME:
170                 regmap_write(regmap, 0x34, val[CLK]);
171                 regmap_write(regmap, 0x44, val[DATA]);
172                 regmap_write(regmap, 0x54, val[DATA]);
173                 regmap_write(regmap, 0x64, val[DATA]);
174                 regmap_write(regmap, 0x74, val[DATA]);
175
176                 regmap_write(regmap, 0x93, val[CLK]);
177                 regmap_write(regmap, 0xa3, val[DATA]);
178                 regmap_write(regmap, 0xb3, val[DATA]);
179                 regmap_write(regmap, 0xc3, val[DATA]);
180                 regmap_write(regmap, 0xd3, val[DATA]);
181                 break;
182         case EXIT_TIME:
183                 regmap_write(regmap, 0x36, val[CLK]);
184                 regmap_write(regmap, 0x46, val[DATA]);
185                 regmap_write(regmap, 0x56, val[DATA]);
186                 regmap_write(regmap, 0x66, val[DATA]);
187                 regmap_write(regmap, 0x76, val[DATA]);
188
189                 regmap_write(regmap, 0x95, val[CLK]);
190                 regmap_write(regmap, 0xA5, val[DATA]);
191                 regmap_write(regmap, 0xB5, val[DATA]);
192                 regmap_write(regmap, 0xc5, val[DATA]);
193                 regmap_write(regmap, 0xd5, val[DATA]);
194                 break;
195         case CLKPOST_TIME:
196                 regmap_write(regmap, 0x35, val[CLK]);
197                 regmap_write(regmap, 0x94, val[CLK]);
198                 break;
199
200         /* the following just use default value */
201         case SETTLE_TIME:
202                 fallthrough;
203         case TA_GET:
204                 fallthrough;
205         case TA_GO:
206                 fallthrough;
207         case TA_SURE:
208                 fallthrough;
209         default:
210                 break;
211         }
212 }
213
214 void dphy_timing_config(struct dsi_context *ctx)
215 {
216         struct regmap *regmap = ctx->regmap;
217         struct dphy_pll *pll = &ctx->pll;
218         const u32 factor = 2;
219         const u32 scale = 100;
220         u32 t_ui, t_byteck, t_half_byteck;
221         u32 range[2], constant;
222         u8 val[2];
223         u32 tmp = 0;
224
225         /* t_ui: 1 ui, byteck: 8 ui, half byteck: 4 ui */
226         t_ui = 1000 * scale / (pll->freq / 1000);
227         t_byteck = t_ui << 3;
228         t_half_byteck = t_ui << 2;
229         constant = t_ui << 1;
230
231         /* REQUEST_TIME: HS T-LPX: LP-01
232          * For T-LPX, mipi spec defined min value is 50ns,
233          * but maybe it shouldn't be too small, because BTA,
234          * LP-10, LP-00, LP-01, all of this is related to T-LPX.
235          */
236         range[L] = 50 * scale;
237         range[H] = INFINITY;
238         val[CLK] = DIV_ROUND_UP(range[L] * (factor << 1), t_byteck) - 2;
239         val[DATA] = val[CLK];
240         dphy_set_timing_reg(regmap, REQUEST_TIME, val);
241
242         /* PREPARE_TIME: HS sequence: LP-00 */
243         range[L] = 38 * scale;
244         range[H] = 95 * scale;
245         tmp = AVERAGE(range[L], range[H]);
246         val[CLK] = DIV_ROUND_UP(AVERAGE(range[L], range[H]), t_half_byteck) - 1;
247         range[L] = 40 * scale + 4 * t_ui;
248         range[H] = 85 * scale + 6 * t_ui;
249         tmp |= AVERAGE(range[L], range[H]) << 16;
250         val[DATA] = DIV_ROUND_UP(AVERAGE(range[L], range[H]), t_half_byteck) - 1;
251         dphy_set_timing_reg(regmap, PREPARE_TIME, val);
252
253         /* ZERO_TIME: HS-ZERO */
254         range[L] = 300 * scale;
255         range[H] = INFINITY;
256         val[CLK] = DIV_ROUND_UP(range[L] * factor + (tmp & 0xffff)
257                         - 525 * t_byteck / 100, t_byteck) - 2;
258         range[L] = 145 * scale + 10 * t_ui;
259         val[DATA] = DIV_ROUND_UP(range[L] * factor
260                         + ((tmp >> 16) & 0xffff) - 525 * t_byteck / 100,
261                         t_byteck) - 2;
262         dphy_set_timing_reg(regmap, ZERO_TIME, val);
263
264         /* TRAIL_TIME: HS-TRAIL */
265         range[L] = 60 * scale;
266         range[H] = INFINITY;
267         val[CLK] = DIV_ROUND_UP(range[L] * factor - constant, t_half_byteck);
268         range[L] = max(8 * t_ui, 60 * scale + 4 * t_ui);
269         val[DATA] = DIV_ROUND_UP(range[L] * 3 / 2 - constant, t_half_byteck) - 2;
270         dphy_set_timing_reg(regmap, TRAIL_TIME, val);
271
272         /* EXIT_TIME: */
273         range[L] = 100 * scale;
274         range[H] = INFINITY;
275         val[CLK] = DIV_ROUND_UP(range[L] * factor, t_byteck) - 2;
276         val[DATA] = val[CLK];
277         dphy_set_timing_reg(regmap, EXIT_TIME, val);
278
279         /* CLKPOST_TIME: */
280         range[L] = 60 * scale + 52 * t_ui;
281         range[H] = INFINITY;
282         val[CLK] = DIV_ROUND_UP(range[L] * factor, t_byteck) - 2;
283         val[DATA] = val[CLK];
284         dphy_set_timing_reg(regmap, CLKPOST_TIME, val);
285
286         /* SETTLE_TIME:
287          * This time is used for receiver. So for transmitter,
288          * it can be ignored.
289          */
290
291         /* TA_GO:
292          * transmitter drives bridge state(LP-00) before releasing control,
293          * reg 0x1f default value: 0x04, which is good.
294          */
295
296         /* TA_SURE:
297          * After LP-10 state and before bridge state(LP-00),
298          * reg 0x20 default value: 0x01, which is good.
299          */
300
301         /* TA_GET:
302          * receiver drives Bridge state(LP-00) before releasing control
303          * reg 0x21 default value: 0x03, which is good.
304          */
305 }
This page took 0.050184 seconds and 4 git commands to generate.