xref: /dpdk/drivers/net/ntnic/nthw/core/nthw_iic.c (revision f665790a5dbad7b645ff46f31d65e977324e7bfc)
1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * Copyright(c) 2023 Napatech A/S
4  */
5 
6 #include "nt_util.h"
7 #include "ntlog.h"
8 
9 #include "nthw_drv.h"
10 #include "nthw_register.h"
11 
12 #include "nthw_iic.h"
13 
14 #define I2C_TRANSMIT_WR (0x00)
15 #define I2C_TRANSMIT_RD (0x01)
16 
17 #define I2C_WAIT_US(x) nt_os_wait_usec(x)
18 
19 /*
20  * Minimum timing values for I2C for a Marvel 88E11111 Phy.
21  * This Phy is used in many Trispeed NIMs.
22  * In order to access this Phy, the I2C clock speed is needed to be set to 100KHz.
23  */
24 static const uint32_t SUSTA = 4700;	/* ns */
25 static const uint32_t SUSTO = 4000;	/* ns */
26 static const uint32_t HDSTA = 4000;	/* ns */
27 static const uint32_t SUDAT = 250;	/* ns */
28 static const uint32_t BUF = 4700;	/* ns */
29 static const uint32_t HIGH = 4000;	/* ns */
30 static const uint32_t LOW = 4700;	/* ns */
31 static const uint32_t HDDAT = 300;	/* ns */
32 
33 static int nthw_iic_reg_control_txfifo_reset(nthw_iic_t *p)
34 {
35 	nthw_field_update_register(p->mp_fld_cr_txfifo_reset);
36 
37 	nthw_field_set_all(p->mp_fld_cr_txfifo_reset);
38 	nthw_field_flush_register(p->mp_fld_cr_txfifo_reset);
39 
40 	nthw_field_clr_all(p->mp_fld_cr_txfifo_reset);
41 	nthw_field_flush_register(p->mp_fld_cr_txfifo_reset);
42 
43 	return 0;
44 }
45 
46 static int nthw_iic_reg_tx_fifo_write(nthw_iic_t *p, uint32_t data, bool start, bool stop)
47 {
48 	if (start)
49 		nthw_field_set_all(p->mp_fld_tx_fifo_start);
50 
51 	else
52 		nthw_field_clr_all(p->mp_fld_tx_fifo_start);
53 
54 	if (stop)
55 		nthw_field_set_all(p->mp_fld_tx_fifo_stop);
56 
57 	else
58 		nthw_field_clr_all(p->mp_fld_tx_fifo_stop);
59 
60 	nthw_field_set_val32(p->mp_fld_tx_fifo_txdata, data);
61 
62 	nthw_register_flush(p->mp_reg_tx_fifo, 1);
63 
64 	return 0;
65 }
66 
67 static int nthw_iic_reg_read_i2c_rx_fifo(nthw_iic_t *p, uint8_t *p_data)
68 {
69 	assert(p_data);
70 
71 	*p_data = (uint8_t)nthw_field_get_updated(p->mp_fld_rx_fifo_rxdata);
72 
73 	return 0;
74 }
75 
76 static int nthw_iic_reg_softr(nthw_iic_t *p)
77 {
78 	nthw_field_update_register(p->mp_fld_cr_en);
79 	nthw_field_set_val_flush32(p->mp_fld_softr_rkey, 0x0A);
80 
81 	return 0;
82 }
83 
84 static int nthw_iic_reg_enable(nthw_iic_t *p)
85 {
86 	nthw_field_update_register(p->mp_fld_cr_en);
87 	nthw_field_set_flush(p->mp_fld_cr_en);
88 
89 	return 0;
90 }
91 
92 static int nthw_iic_reg_busbusy(nthw_iic_t *p, bool *pb_flag)
93 {
94 	assert(pb_flag);
95 
96 	*pb_flag = nthw_field_get_updated(p->mp_fld_sr_bb) ? true : false;
97 
98 	return 0;
99 }
100 
101 static int nthw_iic_reg_rxfifo_empty(nthw_iic_t *p, bool *pb_flag)
102 {
103 	assert(pb_flag);
104 
105 	*pb_flag = nthw_field_get_updated(p->mp_fld_sr_rxfifo_empty) ? true : false;
106 
107 	return 0;
108 }
109 
110 /*
111  * n_iic_cycle_time is the I2C clock cycle time in ns ie 125MHz = 8ns
112  */
113 static int nthw_iic_reg_set_timing(nthw_iic_t *p, uint32_t n_iic_cycle_time)
114 {
115 	uint32_t val;
116 
117 	val = SUSTA / n_iic_cycle_time;
118 	nthw_field_set_val_flush(p->mp_fld_tsusta, &val, 1);
119 
120 	val = SUSTO / n_iic_cycle_time;
121 	nthw_field_set_val_flush(p->mp_fld_tsusto, &val, 1);
122 
123 	val = HDSTA / n_iic_cycle_time;
124 	nthw_field_set_val_flush(p->mp_fld_thdsta, &val, 1);
125 
126 	val = SUDAT / n_iic_cycle_time;
127 	nthw_field_set_val_flush(p->mp_fld_tsudat, &val, 1);
128 
129 	val = BUF / n_iic_cycle_time;
130 	nthw_field_set_val_flush(p->mp_fld_tbuf, &val, 1);
131 
132 	val = HIGH / n_iic_cycle_time;
133 	nthw_field_set_val_flush(p->mp_fld_thigh, &val, 1);
134 
135 	val = LOW / n_iic_cycle_time;
136 	nthw_field_set_val_flush(p->mp_fld_tlow, &val, 1);
137 
138 	val = HDDAT / n_iic_cycle_time;
139 	nthw_field_set_val_flush(p->mp_fld_thddat, &val, 1);
140 
141 	return 0;
142 }
143 
144 nthw_iic_t *nthw_iic_new(void)
145 {
146 	nthw_iic_t *p = malloc(sizeof(nthw_iic_t));
147 
148 	if (p)
149 		memset(p, 0, sizeof(nthw_iic_t));
150 
151 	return p;
152 }
153 
154 int nthw_iic_init(nthw_iic_t *p, nthw_fpga_t *p_fpga, int n_iic_instance,
155 	uint32_t n_iic_cycle_time)
156 {
157 	const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
158 	nthw_module_t *mod = nthw_fpga_query_module(p_fpga, MOD_IIC, n_iic_instance);
159 
160 	if (p == NULL)
161 		return mod == NULL ? -1 : 0;
162 
163 	if (mod == NULL) {
164 		NT_LOG(ERR, NTHW, "%s: I2C %d: no such instance\n", p_adapter_id_str,
165 			n_iic_instance);
166 		return -1;
167 	}
168 
169 	p->mp_fpga = p_fpga;
170 	p->mn_iic_instance = n_iic_instance;
171 
172 	p->mn_iic_cycle_time = n_iic_cycle_time;
173 
174 	nthw_iic_set_retry_params(p, -1, -1, -1, -1, -1);
175 
176 	p->mp_mod_iic = mod;
177 
178 	/* I2C is a primary communication channel - turn off debug by default */
179 	nthw_module_set_debug_mode(p->mp_mod_iic, 0x00);
180 
181 	p->mp_reg_tsusta = nthw_module_get_register(p->mp_mod_iic, IIC_TSUSTA);
182 	p->mp_fld_tsusta = nthw_register_get_field(p->mp_reg_tsusta, IIC_TSUSTA_TSUSTA_VAL);
183 
184 	p->mp_reg_tsusto = nthw_module_get_register(p->mp_mod_iic, IIC_TSUSTO);
185 	p->mp_fld_tsusto = nthw_register_get_field(p->mp_reg_tsusto, IIC_TSUSTO_TSUSTO_VAL);
186 
187 	p->mp_reg_thdsta = nthw_module_get_register(p->mp_mod_iic, IIC_THDSTA);
188 	p->mp_fld_thdsta = nthw_register_get_field(p->mp_reg_thdsta, IIC_THDSTA_THDSTA_VAL);
189 
190 	p->mp_reg_tsudat = nthw_module_get_register(p->mp_mod_iic, IIC_TSUDAT);
191 	p->mp_fld_tsudat = nthw_register_get_field(p->mp_reg_tsudat, IIC_TSUDAT_TSUDAT_VAL);
192 
193 	p->mp_reg_tbuf = nthw_module_get_register(p->mp_mod_iic, IIC_TBUF);
194 	p->mp_fld_tbuf = nthw_register_get_field(p->mp_reg_tbuf, IIC_TBUF_TBUF_VAL);
195 
196 	p->mp_reg_thigh = nthw_module_get_register(p->mp_mod_iic, IIC_THIGH);
197 	p->mp_fld_thigh = nthw_register_get_field(p->mp_reg_thigh, IIC_THIGH_THIGH_VAL);
198 
199 	p->mp_reg_tlow = nthw_module_get_register(p->mp_mod_iic, IIC_TLOW);
200 	p->mp_fld_tlow = nthw_register_get_field(p->mp_reg_tlow, IIC_TLOW_TLOW_VAL);
201 
202 	p->mp_reg_thddat = nthw_module_get_register(p->mp_mod_iic, IIC_THDDAT);
203 	p->mp_fld_thddat = nthw_register_get_field(p->mp_reg_thddat, IIC_THDDAT_THDDAT_VAL);
204 
205 	p->mp_reg_cr = nthw_module_get_register(p->mp_mod_iic, IIC_CR);
206 	p->mp_fld_cr_en = nthw_register_get_field(p->mp_reg_cr, IIC_CR_EN);
207 	p->mp_fld_cr_msms = nthw_register_get_field(p->mp_reg_cr, IIC_CR_MSMS);
208 	p->mp_fld_cr_txfifo_reset = nthw_register_get_field(p->mp_reg_cr, IIC_CR_TXFIFO_RESET);
209 	p->mp_fld_cr_txak = nthw_register_get_field(p->mp_reg_cr, IIC_CR_TXAK);
210 
211 	p->mp_reg_sr = nthw_module_get_register(p->mp_mod_iic, IIC_SR);
212 	p->mp_fld_sr_bb = nthw_register_get_field(p->mp_reg_sr, IIC_SR_BB);
213 	p->mp_fld_sr_rxfifo_full = nthw_register_get_field(p->mp_reg_sr, IIC_SR_RXFIFO_FULL);
214 	p->mp_fld_sr_rxfifo_empty = nthw_register_get_field(p->mp_reg_sr, IIC_SR_RXFIFO_EMPTY);
215 	p->mp_fld_sr_txfifo_full = nthw_register_get_field(p->mp_reg_sr, IIC_SR_TXFIFO_FULL);
216 	p->mp_fld_sr_txfifo_empty = nthw_register_get_field(p->mp_reg_sr, IIC_SR_TXFIFO_EMPTY);
217 
218 	p->mp_reg_tx_fifo = nthw_module_get_register(p->mp_mod_iic, IIC_TX_FIFO);
219 	p->mp_fld_tx_fifo_txdata = nthw_register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_TXDATA);
220 	p->mp_fld_tx_fifo_start = nthw_register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_START);
221 	p->mp_fld_tx_fifo_stop = nthw_register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_STOP);
222 
223 	p->mp_reg_rx_fifo_pirq = nthw_module_get_register(p->mp_mod_iic, IIC_RX_FIFO_PIRQ);
224 	p->mp_fld_rx_fifo_pirq_cmp_val =
225 		nthw_register_get_field(p->mp_reg_rx_fifo_pirq, IIC_RX_FIFO_PIRQ_CMP_VAL);
226 
227 	p->mp_reg_rx_fifo = nthw_module_get_register(p->mp_mod_iic, IIC_RX_FIFO);
228 	p->mp_fld_rx_fifo_rxdata = nthw_register_get_field(p->mp_reg_rx_fifo, IIC_RX_FIFO_RXDATA);
229 
230 	p->mp_reg_softr = nthw_module_get_register(p->mp_mod_iic, IIC_SOFTR);
231 	p->mp_fld_softr_rkey = nthw_register_get_field(p->mp_reg_softr, IIC_SOFTR_RKEY);
232 
233 	/*
234 	 * Initialize I2C controller by applying soft reset and enable the controller
235 	 */
236 	nthw_iic_reg_softr(p);
237 	/* Enable the controller */
238 	nthw_iic_reg_enable(p);
239 
240 	/* Setup controller timing */
241 	if (p->mn_iic_cycle_time) {
242 		NT_LOG(DBG, NTHW, "%s: I2C%d: cycletime=%d\n", p_adapter_id_str,
243 			p->mn_iic_instance, p->mn_iic_cycle_time);
244 		nthw_iic_reg_set_timing(p, p->mn_iic_cycle_time);
245 	}
246 
247 	/* Reset TX fifo - must be after enable */
248 	nthw_iic_reg_control_txfifo_reset(p);
249 	nthw_iic_reg_tx_fifo_write(p, 0, 0, 0);
250 
251 	return 0;
252 }
253 
254 void nthw_iic_delete(nthw_iic_t *p)
255 {
256 	if (p) {
257 		memset(p, 0, sizeof(nthw_iic_t));
258 		free(p);
259 	}
260 }
261 
262 int nthw_iic_set_retry_params(nthw_iic_t *p, const int n_poll_delay, const int n_bus_ready_retry,
263 	const int n_data_ready_retry, const int n_read_data_retry,
264 	const int n_write_data_retry)
265 {
266 	p->mn_poll_delay = n_poll_delay >= 0 ? n_poll_delay : 10;
267 
268 	p->mn_bus_ready_retry = n_bus_ready_retry >= 0 ? n_bus_ready_retry : 1000;
269 	p->mn_data_ready_retry = n_data_ready_retry >= 0 ? n_data_ready_retry : 1000;
270 
271 	p->mn_read_data_retry = n_read_data_retry >= 0 ? n_read_data_retry : 10;
272 	p->mn_write_data_retry = n_write_data_retry >= 0 ? n_write_data_retry : 10;
273 
274 	return 0;
275 }
276 
277 int nthw_iic_read_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t a_reg_addr, uint8_t data_len,
278 	void *p_void)
279 {
280 	const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;
281 	const int n_debug_mode = nthw_module_get_debug_mode(p->mp_mod_iic);
282 
283 	uint8_t *pb = (uint8_t *)p_void;
284 	int retry = (p->mn_read_data_retry >= 0 ? p->mn_read_data_retry : 10);
285 
286 	if (n_debug_mode == 0xff) {
287 		NT_LOG(DBG, NTHW, "%s: adr=0x%2.2x, reg=%d, len=%d\n", p_adapter_id_str, dev_addr,
288 			a_reg_addr, data_len);
289 	}
290 
291 	while (nthw_iic_readbyte(p, dev_addr, a_reg_addr, data_len, pb) != 0) {
292 		retry--;
293 
294 		if (retry <= 0) {
295 			NT_LOG(ERR, NTHW,
296 				"%s: I2C%d: Read retry exhausted (dev_addr=%d a_reg_addr=%d)\n",
297 				p_adapter_id_str, p->mn_iic_instance, dev_addr, a_reg_addr);
298 			return -1;
299 
300 		} else {
301 			NT_LOG(DBG, NTHW, "%s: I2C%d: Read retry=%d (dev_addr=%d a_reg_addr=%d)\n",
302 				p_adapter_id_str, p->mn_iic_instance, retry, dev_addr, a_reg_addr);
303 		}
304 	}
305 
306 	if (n_debug_mode == 0xff) {
307 		NT_LOG(DBG, NTHW, "%s: adr=0x%2.2x, reg=%d, len=%d, retries remaining: %d\n",
308 			p_adapter_id_str, dev_addr, a_reg_addr, data_len, retry);
309 	}
310 
311 	return 0;
312 }
313 
314 int nthw_iic_readbyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t a_reg_addr, uint8_t data_len,
315 	uint8_t *p_byte)
316 {
317 	const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;
318 
319 	uint32_t value;
320 	uint32_t i;
321 
322 	if (nthw_iic_bus_ready(p)) {
323 		/* Reset TX fifo */
324 		nthw_iic_reg_control_txfifo_reset(p);
325 
326 		/* Write device address to TX_FIFO and set start bit!! */
327 		value = (dev_addr << 1) | I2C_TRANSMIT_WR;
328 		nthw_iic_reg_tx_fifo_write(p, value, 1, 0);
329 
330 		/* Write a_reg_addr to TX FIFO */
331 		nthw_iic_reg_tx_fifo_write(p, a_reg_addr, 0, 1);
332 
333 		if (!nthw_iic_bus_ready(p)) {
334 			NT_LOG_DBGX(ERR, NTHW, "%s: error:\n", p_adapter_id_str);
335 			return -1;
336 		}
337 
338 		/* Write device address + RD bit to TX_FIFO and set start bit!! */
339 		value = (dev_addr << 1) | I2C_TRANSMIT_RD;
340 		nthw_iic_reg_tx_fifo_write(p, value, 1, 0);
341 
342 		/* Write data_len to TX_FIFO and set stop bit!! */
343 		nthw_iic_reg_tx_fifo_write(p, data_len, 0, 1);
344 
345 		for (i = 0; i < data_len; i++) {
346 			/* Wait for RX FIFO not empty */
347 			if (!nthw_iic_data_ready(p))
348 				return -1;
349 
350 			/* Read data_len bytes from RX_FIFO */
351 			nthw_iic_reg_read_i2c_rx_fifo(p, p_byte);
352 			p_byte++;
353 		}
354 
355 		return 0;
356 
357 	} else {
358 		NT_LOG_DBGX(ERR, NTHW, "%s: error\n", p_adapter_id_str);
359 		return -1;
360 	}
361 
362 	return 0;
363 }
364 
365 int nthw_iic_write_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t a_reg_addr, uint8_t data_len,
366 	void *p_void)
367 {
368 	const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;
369 	int retry = (p->mn_write_data_retry >= 0 ? p->mn_write_data_retry : 10);
370 	uint8_t *pb = (uint8_t *)p_void;
371 
372 	while (nthw_iic_writebyte(p, dev_addr, a_reg_addr, data_len, pb) != 0) {
373 		retry--;
374 
375 		if (retry <= 0) {
376 			NT_LOG(ERR, NTHW,
377 				"%s: I2C%d: Write retry exhausted (dev_addr=%d a_reg_addr=%d)\n",
378 				p_adapter_id_str, p->mn_iic_instance, dev_addr, a_reg_addr);
379 			return -1;
380 
381 		} else {
382 			NT_LOG(DBG, NTHW,
383 				"%s: I2C%d: Write retry=%d (dev_addr=%d a_reg_addr=%d)\n",
384 				p_adapter_id_str, p->mn_iic_instance, retry, dev_addr, a_reg_addr);
385 		}
386 	}
387 
388 	return 0;
389 }
390 
391 int nthw_iic_writebyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t a_reg_addr, uint8_t data_len,
392 	uint8_t *p_byte)
393 {
394 	const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;
395 	uint32_t value;
396 	int count;
397 	int i;
398 
399 	if (data_len == 0)
400 		return -1;
401 
402 	count = data_len - 1;
403 
404 	if (nthw_iic_bus_ready(p)) {
405 		/* Reset TX fifo */
406 		nthw_iic_reg_control_txfifo_reset(p);
407 
408 		/* Write device address to TX_FIFO and set start bit!! */
409 		value = (dev_addr << 1) | I2C_TRANSMIT_WR;
410 		nthw_iic_reg_tx_fifo_write(p, value, 1, 0);
411 
412 		/* Write a_reg_addr to TX FIFO */
413 		nthw_iic_reg_tx_fifo_write(p, a_reg_addr, 0, 0);
414 
415 		for (i = 0; i < count; i++) {
416 			/* Write data byte to TX fifo and set stop bit */
417 			nthw_iic_reg_tx_fifo_write(p, *p_byte, 0, 0);
418 			p_byte++;
419 		}
420 
421 		/* Write data byte to TX fifo and set stop bit */
422 		nthw_iic_reg_tx_fifo_write(p, *p_byte, 0, 1);
423 
424 		if (!nthw_iic_bus_ready(p)) {
425 			NT_LOG_DBGX(WARNING, NTHW, "%s: warn: !busReady\n", p_adapter_id_str);
426 
427 			while (true)
428 				if (nthw_iic_bus_ready(p)) {
429 					NT_LOG_DBGX(DEBUG, NTHW, "%s: info: busReady\n",
430 					p_adapter_id_str);
431 					break;
432 				}
433 		}
434 
435 		return 0;
436 
437 	} else {
438 		NT_LOG_DBGX(WARNING, NTHW, "%s\n", p_adapter_id_str);
439 		return -1;
440 	}
441 }
442 
443 /*
444  * Support function for read/write functions below. Waits for bus ready.
445  */
446 bool nthw_iic_bus_ready(nthw_iic_t *p)
447 {
448 	int count = (p->mn_bus_ready_retry >= 0 ? p->mn_bus_ready_retry : 1000);
449 	bool b_bus_busy = true;
450 
451 	while (true) {
452 		nthw_iic_reg_busbusy(p, &b_bus_busy);
453 
454 		if (!b_bus_busy)
455 			break;
456 
457 		count--;
458 
459 		if (count <= 0)	/* Test for timeout */
460 			break;
461 
462 		if (p->mn_poll_delay != 0)
463 			I2C_WAIT_US(p->mn_poll_delay);
464 	}
465 
466 	if (count == 0)
467 		return false;
468 
469 	return true;
470 }
471 
472 /*
473  * Support function for read function. Waits for data ready.
474  */
475 bool nthw_iic_data_ready(nthw_iic_t *p)
476 {
477 	int count = (p->mn_data_ready_retry >= 0 ? p->mn_data_ready_retry : 1000);
478 	bool b_rx_fifo_empty = true;
479 
480 	while (true) {
481 		nthw_iic_reg_rxfifo_empty(p, &b_rx_fifo_empty);
482 
483 		if (!b_rx_fifo_empty)
484 			break;
485 
486 		count--;
487 
488 		if (count <= 0)	/* Test for timeout */
489 			break;
490 
491 		if (p->mn_poll_delay != 0)
492 			I2C_WAIT_US(p->mn_poll_delay);
493 	}
494 
495 	if (count == 0)
496 		return false;
497 
498 	return true;
499 }
500 
501 int nthw_iic_scan_dev_addr(nthw_iic_t *p, int n_dev_addr, int n_reg_addr)
502 {
503 	const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;
504 	(void)p_adapter_id_str;
505 	int res;
506 	uint8_t data_val = -1;
507 	res = nthw_iic_readbyte(p, (uint8_t)n_dev_addr, (uint8_t)n_reg_addr, 1, &data_val);
508 
509 	if (res == 0) {
510 		NT_LOG(DBG, NTHW,
511 			"%s: I2C%d: devaddr=0x%02X (%03d) regaddr=%02X val=%02X (%03d) res=%d\n",
512 			p_adapter_id_str, p->mn_iic_instance, n_dev_addr, n_dev_addr, n_reg_addr,
513 			data_val, data_val, res);
514 	}
515 
516 	return res;
517 }
518 
519 int nthw_iic_scan(nthw_iic_t *p)
520 {
521 	int i;
522 
523 	for (i = 0; i < 128; i++)
524 		(void)nthw_iic_scan_dev_addr(p, i, 0x00);
525 
526 	return 0;
527 }
528