1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * camss-csiphy-3ph-1-0.c
4  *
5  * Qualcomm MSM Camera Subsystem - CSIPHY Module 3phase v1.0
6  *
7  * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
8  * Copyright (C) 2016-2018 Linaro Ltd.
9  */
10 
11 #include "camss.h"
12 #include "camss-csiphy.h"
13 
14 #include <linux/delay.h>
15 #include <linux/interrupt.h>
16 #include <linux/io.h>
17 
18 #define CSIPHY_3PH_LNn_CFG1(n)			(0x000 + 0x100 * (n))
19 #define CSIPHY_3PH_LNn_CFG1_SWI_REC_DLY_PRG	(BIT(7) | BIT(6))
20 #define CSIPHY_3PH_LNn_CFG2(n)			(0x004 + 0x100 * (n))
21 #define CSIPHY_3PH_LNn_CFG2_LP_REC_EN_INT	BIT(3)
22 #define CSIPHY_3PH_LNn_CFG3(n)			(0x008 + 0x100 * (n))
23 #define CSIPHY_3PH_LNn_CFG4(n)			(0x00c + 0x100 * (n))
24 #define CSIPHY_3PH_LNn_CFG4_T_HS_CLK_MISS	0xa4
25 #define CSIPHY_3PH_LNn_CFG4_T_HS_CLK_MISS_660	0xa5
26 #define CSIPHY_3PH_LNn_CFG5(n)			(0x010 + 0x100 * (n))
27 #define CSIPHY_3PH_LNn_CFG5_T_HS_DTERM		0x02
28 #define CSIPHY_3PH_LNn_CFG5_HS_REC_EQ_FQ_INT	0x50
29 #define CSIPHY_3PH_LNn_TEST_IMP(n)		(0x01c + 0x100 * (n))
30 #define CSIPHY_3PH_LNn_TEST_IMP_HS_TERM_IMP	0xa
31 #define CSIPHY_3PH_LNn_MISC1(n)			(0x028 + 0x100 * (n))
32 #define CSIPHY_3PH_LNn_MISC1_IS_CLKLANE		BIT(2)
33 #define CSIPHY_3PH_LNn_CFG6(n)			(0x02c + 0x100 * (n))
34 #define CSIPHY_3PH_LNn_CFG6_SWI_FORCE_INIT_EXIT	BIT(0)
35 #define CSIPHY_3PH_LNn_CFG7(n)			(0x030 + 0x100 * (n))
36 #define CSIPHY_3PH_LNn_CFG7_SWI_T_INIT		0x2
37 #define CSIPHY_3PH_LNn_CFG8(n)			(0x034 + 0x100 * (n))
38 #define CSIPHY_3PH_LNn_CFG8_SWI_SKIP_WAKEUP	BIT(0)
39 #define CSIPHY_3PH_LNn_CFG8_SKEW_FILTER_ENABLE	BIT(1)
40 #define CSIPHY_3PH_LNn_CFG9(n)			(0x038 + 0x100 * (n))
41 #define CSIPHY_3PH_LNn_CFG9_SWI_T_WAKEUP	0x1
42 #define CSIPHY_3PH_LNn_CSI_LANE_CTRL15(n)	(0x03c + 0x100 * (n))
43 #define CSIPHY_3PH_LNn_CSI_LANE_CTRL15_SWI_SOT_SYMBOL	0xb8
44 
45 #define CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(n)	(0x800 + 0x4 * (n))
46 #define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B	BIT(0)
47 #define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID	BIT(1)
48 #define CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(n)	(0x8b0 + 0x4 * (n))
49 
50 #define CSIPHY_DEFAULT_PARAMS            0
51 #define CSIPHY_LANE_ENABLE               1
52 #define CSIPHY_SETTLE_CNT_LOWER_BYTE     2
53 #define CSIPHY_SETTLE_CNT_HIGHER_BYTE    3
54 #define CSIPHY_DNP_PARAMS                4
55 #define CSIPHY_2PH_REGS                  5
56 #define CSIPHY_3PH_REGS                  6
57 
58 struct csiphy_reg_t {
59 	s32 reg_addr;
60 	s32 reg_data;
61 	s32 delay;
62 	u32 csiphy_param_type;
63 };
64 
65 static const struct
66 csiphy_reg_t lane_regs_sdm845[5][14] = {
67 	{
68 		{0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
69 		{0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
70 		{0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS},
71 		{0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS},
72 		{0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
73 		{0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS},
74 		{0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS},
75 		{0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS},
76 		{0x0008, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
77 		{0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
78 		{0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
79 		{0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
80 		{0x0060, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
81 		{0x0064, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
82 	},
83 	{
84 		{0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
85 		{0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
86 		{0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS},
87 		{0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS},
88 		{0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
89 		{0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS},
90 		{0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS},
91 		{0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
92 		{0x0708, 0x14, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
93 		{0x070C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS},
94 		{0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
95 		{0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS},
96 		{0x0760, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
97 		{0x0764, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
98 	},
99 	{
100 		{0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
101 		{0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
102 		{0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS},
103 		{0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS},
104 		{0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
105 		{0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS},
106 		{0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS},
107 		{0x0200, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS},
108 		{0x0208, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
109 		{0x020C, 0x00, 0x00, CSIPHY_DNP_PARAMS},
110 		{0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
111 		{0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
112 		{0x0260, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
113 		{0x0264, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
114 	},
115 	{
116 		{0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
117 		{0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
118 		{0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS},
119 		{0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS},
120 		{0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
121 		{0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS},
122 		{0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS},
123 		{0x0400, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS},
124 		{0x0408, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
125 		{0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS},
126 		{0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
127 		{0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
128 		{0x0460, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
129 		{0x0464, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
130 	},
131 	{
132 		{0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
133 		{0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
134 		{0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS},
135 		{0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS},
136 		{0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
137 		{0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS},
138 		{0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS},
139 		{0x0600, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS},
140 		{0x0608, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
141 		{0x060C, 0x00, 0x00, CSIPHY_DNP_PARAMS},
142 		{0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
143 		{0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
144 		{0x0660, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
145 		{0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
146 	},
147 };
148 
149 static void csiphy_hw_version_read(struct csiphy_device *csiphy,
150 				   struct device *dev)
151 {
152 	u32 hw_version;
153 
154 	writel(CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID,
155 	       csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(6));
156 
157 	hw_version = readl_relaxed(csiphy->base +
158 				   CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(12));
159 	hw_version |= readl_relaxed(csiphy->base +
160 				   CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(13)) << 8;
161 	hw_version |= readl_relaxed(csiphy->base +
162 				   CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(14)) << 16;
163 	hw_version |= readl_relaxed(csiphy->base +
164 				   CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(15)) << 24;
165 
166 	dev_err(dev, "CSIPHY 3PH HW Version = 0x%08x\n", hw_version);
167 }
168 
169 /*
170  * csiphy_reset - Perform software reset on CSIPHY module
171  * @csiphy: CSIPHY device
172  */
173 static void csiphy_reset(struct csiphy_device *csiphy)
174 {
175 	writel_relaxed(0x1, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(0));
176 	usleep_range(5000, 8000);
177 	writel_relaxed(0x0, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(0));
178 }
179 
180 static irqreturn_t csiphy_isr(int irq, void *dev)
181 {
182 	struct csiphy_device *csiphy = dev;
183 	int i;
184 
185 	for (i = 0; i < 11; i++) {
186 		int c = i + 22;
187 		u8 val = readl_relaxed(csiphy->base +
188 				       CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(i));
189 
190 		writel_relaxed(val, csiphy->base +
191 				    CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(c));
192 	}
193 
194 	writel_relaxed(0x1, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(10));
195 	writel_relaxed(0x0, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(10));
196 
197 	for (i = 22; i < 33; i++)
198 		writel_relaxed(0x0, csiphy->base +
199 				    CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(i));
200 
201 	return IRQ_HANDLED;
202 }
203 
204 /*
205  * csiphy_settle_cnt_calc - Calculate settle count value
206  *
207  * Helper function to calculate settle count value. This is
208  * based on the CSI2 T_hs_settle parameter which in turn
209  * is calculated based on the CSI2 transmitter link frequency.
210  *
211  * Return settle count value or 0 if the CSI2 link frequency
212  * is not available
213  */
214 static u8 csiphy_settle_cnt_calc(s64 link_freq, u32 timer_clk_rate)
215 {
216 	u32 ui; /* ps */
217 	u32 timer_period; /* ps */
218 	u32 t_hs_prepare_max; /* ps */
219 	u32 t_hs_settle; /* ps */
220 	u8 settle_cnt;
221 
222 	if (link_freq <= 0)
223 		return 0;
224 
225 	ui = div_u64(1000000000000LL, link_freq);
226 	ui /= 2;
227 	t_hs_prepare_max = 85000 + 6 * ui;
228 	t_hs_settle = t_hs_prepare_max;
229 
230 	timer_period = div_u64(1000000000000LL, timer_clk_rate);
231 	settle_cnt = t_hs_settle / timer_period - 6;
232 
233 	return settle_cnt;
234 }
235 
236 static void csiphy_gen1_config_lanes(struct csiphy_device *csiphy,
237 				     struct csiphy_config *cfg,
238 				     u8 settle_cnt)
239 {
240 	struct csiphy_lanes_cfg *c = &cfg->csi2->lane_cfg;
241 	int i, l = 0;
242 	u8 val;
243 
244 	for (i = 0; i <= c->num_data; i++) {
245 		if (i == c->num_data)
246 			l = 7;
247 		else
248 			l = c->data[i].pos * 2;
249 
250 		val = CSIPHY_3PH_LNn_CFG1_SWI_REC_DLY_PRG;
251 		val |= 0x17;
252 		writel_relaxed(val, csiphy->base + CSIPHY_3PH_LNn_CFG1(l));
253 
254 		val = CSIPHY_3PH_LNn_CFG2_LP_REC_EN_INT;
255 		writel_relaxed(val, csiphy->base + CSIPHY_3PH_LNn_CFG2(l));
256 
257 		val = settle_cnt;
258 		writel_relaxed(val, csiphy->base + CSIPHY_3PH_LNn_CFG3(l));
259 
260 		val = CSIPHY_3PH_LNn_CFG5_T_HS_DTERM |
261 			CSIPHY_3PH_LNn_CFG5_HS_REC_EQ_FQ_INT;
262 		writel_relaxed(val, csiphy->base + CSIPHY_3PH_LNn_CFG5(l));
263 
264 		val = CSIPHY_3PH_LNn_CFG6_SWI_FORCE_INIT_EXIT;
265 		writel_relaxed(val, csiphy->base + CSIPHY_3PH_LNn_CFG6(l));
266 
267 		val = CSIPHY_3PH_LNn_CFG7_SWI_T_INIT;
268 		writel_relaxed(val, csiphy->base + CSIPHY_3PH_LNn_CFG7(l));
269 
270 		val = CSIPHY_3PH_LNn_CFG8_SWI_SKIP_WAKEUP |
271 			CSIPHY_3PH_LNn_CFG8_SKEW_FILTER_ENABLE;
272 		writel_relaxed(val, csiphy->base + CSIPHY_3PH_LNn_CFG8(l));
273 
274 		val = CSIPHY_3PH_LNn_CFG9_SWI_T_WAKEUP;
275 		writel_relaxed(val, csiphy->base + CSIPHY_3PH_LNn_CFG9(l));
276 
277 		val = CSIPHY_3PH_LNn_TEST_IMP_HS_TERM_IMP;
278 		writel_relaxed(val, csiphy->base + CSIPHY_3PH_LNn_TEST_IMP(l));
279 
280 		val = CSIPHY_3PH_LNn_CSI_LANE_CTRL15_SWI_SOT_SYMBOL;
281 		writel_relaxed(val, csiphy->base +
282 				    CSIPHY_3PH_LNn_CSI_LANE_CTRL15(l));
283 	}
284 
285 	val = CSIPHY_3PH_LNn_CFG1_SWI_REC_DLY_PRG;
286 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_LNn_CFG1(l));
287 
288 	if (csiphy->camss->version == CAMSS_660)
289 		val = CSIPHY_3PH_LNn_CFG4_T_HS_CLK_MISS_660;
290 	else
291 		val = CSIPHY_3PH_LNn_CFG4_T_HS_CLK_MISS;
292 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_LNn_CFG4(l));
293 
294 	val = CSIPHY_3PH_LNn_MISC1_IS_CLKLANE;
295 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_LNn_MISC1(l));
296 }
297 
298 static void csiphy_gen2_config_lanes(struct csiphy_device *csiphy,
299 				     u8 settle_cnt)
300 {
301 	int i, l;
302 	u32 val;
303 
304 	for (l = 0; l < 5; l++) {
305 		for (i = 0; i < 14; i++) {
306 			const struct csiphy_reg_t *r = &lane_regs_sdm845[l][i];
307 
308 			switch (r->csiphy_param_type) {
309 			case CSIPHY_SETTLE_CNT_LOWER_BYTE:
310 				val = settle_cnt & 0xff;
311 				break;
312 			case CSIPHY_DNP_PARAMS:
313 				continue;
314 			default:
315 				val = r->reg_data;
316 				break;
317 			}
318 			writel_relaxed(val, csiphy->base + r->reg_addr);
319 		}
320 	}
321 }
322 
323 static void csiphy_lanes_enable(struct csiphy_device *csiphy,
324 				struct csiphy_config *cfg,
325 				s64 link_freq, u8 lane_mask)
326 {
327 	struct csiphy_lanes_cfg *c = &cfg->csi2->lane_cfg;
328 	u8 settle_cnt;
329 	u8 val;
330 	int i;
331 
332 	settle_cnt = csiphy_settle_cnt_calc(link_freq, csiphy->timer_clk_rate);
333 
334 	val = BIT(c->clk.pos);
335 	for (i = 0; i < c->num_data; i++)
336 		val |= BIT(c->data[i].pos * 2);
337 
338 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(5));
339 
340 	val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B;
341 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(6));
342 
343 	val = 0x02;
344 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(7));
345 
346 	val = 0x00;
347 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(0));
348 
349 	if (csiphy->camss->version == CAMSS_8x16 ||
350 	    csiphy->camss->version == CAMSS_8x96)
351 		csiphy_gen1_config_lanes(csiphy, cfg, settle_cnt);
352 	else if (csiphy->camss->version == CAMSS_845)
353 		csiphy_gen2_config_lanes(csiphy, settle_cnt);
354 
355 	val = 0xff;
356 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(11));
357 
358 	val = 0xff;
359 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(12));
360 
361 	val = 0xfb;
362 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(13));
363 
364 	val = 0xff;
365 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(14));
366 
367 	val = 0x7f;
368 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(15));
369 
370 	val = 0xff;
371 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(16));
372 
373 	val = 0xff;
374 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(17));
375 
376 	val = 0xef;
377 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(18));
378 
379 	val = 0xff;
380 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(19));
381 
382 	val = 0xff;
383 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(20));
384 
385 	val = 0xff;
386 	writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(21));
387 }
388 
389 static void csiphy_lanes_disable(struct csiphy_device *csiphy,
390 				 struct csiphy_config *cfg)
391 {
392 	writel_relaxed(0, csiphy->base +
393 			  CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(5));
394 
395 	writel_relaxed(0, csiphy->base +
396 			  CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(6));
397 }
398 
399 const struct csiphy_hw_ops csiphy_ops_3ph_1_0 = {
400 	.hw_version_read = csiphy_hw_version_read,
401 	.reset = csiphy_reset,
402 	.lanes_enable = csiphy_lanes_enable,
403 	.lanes_disable = csiphy_lanes_disable,
404 	.isr = csiphy_isr,
405 };
406