1 /*
2 * Copyright 2024 Microchip Technology Inc. and its subsidiaries.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <string.h>
7
8 #include <device_mec5.h>
9 #include "mec_defs.h"
10 #include "mec_pcfg.h"
11 #include "mec_ecia_api.h"
12 #include "mec_pcr_api.h"
13 #include "mec_retval.h"
14
15 #include "mec_i3c_pvt.h"
16
17
18 /**
19 * @brief Get interrupt status
20 *
21 * @param regs Pointer to controller registers
22 */
_i3c_intr_sts_get(struct mec_i3c_host_regs * regs)23 uint32_t _i3c_intr_sts_get(struct mec_i3c_host_regs *regs)
24 {
25 return regs->INTR_STS;
26 }
27
28 /**
29 * @brief clear all interrupt status
30 *
31 * @param regs Pointer to controller registers
32 */
_i3c_intr_sts_clear(struct mec_i3c_host_regs * regs,uint32_t mask)33 void _i3c_intr_sts_clear(struct mec_i3c_host_regs *regs, uint32_t mask)
34 {
35 regs->INTR_STS = mask;
36 }
37
38 /**
39 * @brief Enable interrupt status
40 *
41 * @param regs Pointer to controller registers
42 */
_i3c_intr_sts_enable(struct mec_i3c_host_regs * regs,uint32_t mask)43 void _i3c_intr_sts_enable(struct mec_i3c_host_regs *regs, uint32_t mask)
44 {
45 regs->INTR_EN = mask;
46 }
47
48 /**
49 * @brief Enable IBI interrupt
50 *
51 * @param regs Pointer to controller registers
52 */
_i3c_intr_IBI_enable(struct mec_i3c_host_regs * regs)53 void _i3c_intr_IBI_enable(struct mec_i3c_host_regs *regs)
54 {
55 regs->INTR_EN |= sbit_IBI_THLD_STS;
56
57 regs->INTR_SIG_EN |= sbit_IBI_THLD_STS;
58 }
59
60 /**
61 * @brief Disable IBI interrupt
62 *
63 * @param regs Pointer to controller registers
64 */
_i3c_intr_IBI_disable(struct mec_i3c_host_regs * regs)65 void _i3c_intr_IBI_disable(struct mec_i3c_host_regs *regs)
66 {
67 regs->INTR_EN &= (uint32_t)~sbit_IBI_THLD_STS;
68
69 regs->INTR_SIG_EN &= (uint32_t)~sbit_IBI_THLD_STS;
70 }
71
72 /**
73 * @brief Enable the TX Threshold interrupt
74 *
75 * @param regs Pointer to controller registers
76 */
_i3c_intr_thresholds_tx_enable(struct mec_i3c_host_regs * regs)77 void _i3c_intr_thresholds_tx_enable(struct mec_i3c_host_regs *regs)
78 {
79 regs->INTR_EN |= sbit_TX_THLD_STS;
80
81 regs->INTR_SIG_EN |= sbit_TX_THLD_STS;
82 }
83
84 /**
85 * @brief Disable the TX Threshold interrupt
86 *
87 * @param regs Pointer to controller registers
88 */
_i3c_intr_thresholds_tx_disable(struct mec_i3c_host_regs * regs)89 void _i3c_intr_thresholds_tx_disable(struct mec_i3c_host_regs *regs)
90 {
91 regs->INTR_EN &= (uint32_t)~sbit_TX_THLD_STS;
92
93 regs->INTR_SIG_EN &= (uint32_t)~sbit_TX_THLD_STS;
94 }
95
96 /**
97 * @brief Enable the RX Threshold interrupt
98 *
99 * @param regs Pointer to controller registers
100 */
_i3c_intr_thresholds_rx_enable(struct mec_i3c_host_regs * regs)101 void _i3c_intr_thresholds_rx_enable(struct mec_i3c_host_regs *regs)
102 {
103 regs->INTR_EN |= sbit_RX_THLD_STS;
104
105 regs->INTR_SIG_EN |= sbit_RX_THLD_STS;
106 }
107
108 /**
109 * @brief Disable the RX Threshold interrupt
110 *
111 * @param regs Pointer to controller registers
112 */
_i3c_intr_thresholds_rx_disable(struct mec_i3c_host_regs * regs)113 void _i3c_intr_thresholds_rx_disable(struct mec_i3c_host_regs *regs)
114 {
115 regs->INTR_EN &= (uint32_t)~sbit_RX_THLD_STS;
116
117 regs->INTR_SIG_EN &= (uint32_t)~sbit_RX_THLD_STS;
118 }
119
120 /**
121 * @brief Enable interrupt signal
122 *
123 * @param regs Pointer to controller registers
124 */
_i3c_intr_sgnl_enable(struct mec_i3c_host_regs * regs,uint32_t mask)125 void _i3c_intr_sgnl_enable(struct mec_i3c_host_regs *regs, uint32_t mask)
126 {
127 regs->INTR_SIG_EN = mask;
128 }
129
130 /**
131 * @brief Set Response Buffer Threshold to trigger interrupt
132 *
133 * @param regs Pointer to controller registers
134 */
_i3c_resp_queue_threshold_set(struct mec_i3c_host_regs * regs,uint8_t threshold)135 void _i3c_resp_queue_threshold_set(struct mec_i3c_host_regs *regs, uint8_t threshold)
136 {
137 if (threshold < I3C_RESPONSE_BUFFER_DEPTH)
138 {
139 regs->QUE_THLD_CTRL &= (uint32_t)~(0xFFu << QUEUE_THLD_RESP_QUEUE_BITPOS);
140 regs->QUE_THLD_CTRL |= (threshold << QUEUE_THLD_RESP_QUEUE_BITPOS);
141 }
142 }
143
144 /**
145 * @brief Reads the Response Buffer Level Value
146 *
147 * @param regs Pointer to controller registers
148 */
_i3c_resp_buf_level_get(struct mec_i3c_host_regs * regs)149 uint8_t _i3c_resp_buf_level_get(struct mec_i3c_host_regs *regs)
150 {
151 volatile uint8_t level = 0;
152
153 level = (regs->QUE_STS_LVL >> Q_STS_LVL_RESP_BUFFER_BIT_POS) & 0xFF;
154
155 return level;
156 }
157
158 /**
159 * @brief Reads the IBI status count
160 *
161 * @param regs Pointer to controller registers
162 */
_i3c_ibi_status_count_get(struct mec_i3c_host_regs * regs)163 uint8_t _i3c_ibi_status_count_get(struct mec_i3c_host_regs *regs)
164 {
165 volatile uint8_t level = 0;
166
167 level = (regs->QUE_STS_LVL >> Q_STS_LVL_IBI_STS_CNT_BIT_POS) & 0x1F;
168
169 return level;
170 }
171
172 /**
173 * @brief Reads the IBI status queue
174 *
175 * @param regs Pointer to controller registers
176 */
_i3c_ibi_queue_status_get(struct mec_i3c_host_regs * regs)177 uint32_t _i3c_ibi_queue_status_get(struct mec_i3c_host_regs *regs)
178 {
179 volatile uint32_t queue_sts = 0;
180
181 queue_sts = regs->IBI_QUE_STS;
182
183 return queue_sts;
184 }
185
186 /**
187 * @brief Reads the Response Buffer Level Value
188 *
189 * @param regs Pointer to controller registers
190 */
_i3c_response_sts_get(struct mec_i3c_host_regs * regs,uint16_t * len,uint8_t * tid)191 uint8_t _i3c_response_sts_get(struct mec_i3c_host_regs *regs, uint16_t *len, uint8_t *tid)
192 {
193 volatile uint32_t response = 0;
194 uint8_t resp_sts;
195
196 response = regs->RESP;
197
198 *len = response & 0xFFFFu;
199 *tid = (response & RESPONSE_TID_BITMASK) >> RESPONSE_TID_BITPOS;
200
201 resp_sts = (response & RESPONSE_ERR_STS_BITMASK) >> RESPONSE_ERR_STS_BITPOS;
202
203 return resp_sts;
204 }
205
206 /**
207 * @brief Reads the Response Buffer Level Value
208 *
209 * @param regs Pointer to controller registers
210 */
_i3c_tgt_response_sts_get(struct mec_i3c_sec_regs * regs,uint16_t * len,uint8_t * tid,bool * rx_response)211 uint8_t _i3c_tgt_response_sts_get(struct mec_i3c_sec_regs *regs, uint16_t *len, uint8_t *tid,
212 bool *rx_response)
213 {
214 volatile uint32_t response = 0;
215 uint8_t resp_sts, rx_rsp_bit;
216
217 response = regs->RESP;
218
219 *len = response & 0xFFFFu;
220 *tid = (response & RESPONSE_TID_TGT_BITMASK) >> RESPONSE_TID_BITPOS;
221
222 resp_sts = (response & RESPONSE_ERR_STS_BITMASK) >> RESPONSE_ERR_STS_BITPOS;
223
224 rx_rsp_bit = (response & RESPONSE_RX_RESP_BITMASK) >> RESPONSE_RX_RESP_BITPOS;
225
226 if (rx_rsp_bit) {
227 *rx_response = true;
228 }
229
230 return resp_sts;
231 }
232
233 /**
234 * @brief
235 *
236 * @param regs Pointer to controller registers
237 */
_i3c_cmd_queue_threshold_set(struct mec_i3c_host_regs * regs,uint32_t val)238 void _i3c_cmd_queue_threshold_set(struct mec_i3c_host_regs *regs, uint32_t val)
239 {
240 regs->QUE_THLD_CTRL &= (uint32_t)~(0xFFu << QUEUE_THLD_CMD_QUEUE_BITPOS);
241 regs->QUE_THLD_CTRL |= (val << QUEUE_THLD_CMD_QUEUE_BITPOS);
242 }
243
244 /**
245 * @brief
246 *
247 * @param regs Pointer to controller registers
248 */
_i3c_ibi_data_threshold_set(struct mec_i3c_host_regs * regs,uint32_t val)249 void _i3c_ibi_data_threshold_set(struct mec_i3c_host_regs *regs, uint32_t val)
250 {
251 regs->QUE_THLD_CTRL &= (uint32_t)~(0xFFu << QUEUE_THLD_IBI_DATA_BITPOS);
252 regs->QUE_THLD_CTRL |= (val << QUEUE_THLD_IBI_DATA_BITPOS);
253 }
254
255 /**
256 * @brief
257 *
258 * @param regs Pointer to controller registers
259 */
_i3c_ibi_status_threshold_set(struct mec_i3c_host_regs * regs,uint32_t val)260 void _i3c_ibi_status_threshold_set(struct mec_i3c_host_regs *regs, uint32_t val)
261 {
262 regs->QUE_THLD_CTRL &= (uint32_t)~(0xFFu << QUEUE_THLD_IBI_STATUS_BITPOS);
263 regs->QUE_THLD_CTRL |= (val << QUEUE_THLD_IBI_STATUS_BITPOS);
264 }
265
266 /**
267 * @brief
268 *
269 * @param regs Pointer to controller registers
270 */
_i3c_tx_buf_threshold_set(struct mec_i3c_host_regs * regs,uint32_t val)271 void _i3c_tx_buf_threshold_set(struct mec_i3c_host_regs *regs, uint32_t val)
272 {
273 regs->DB_THLD_CTRL &= (uint32_t)~(0xFFu << DATA_BUF_THLD_TX_FIFO_EMPTY_BITPOS);
274 regs->DB_THLD_CTRL |= (val << DATA_BUF_THLD_TX_FIFO_EMPTY_BITPOS);
275 }
276
277 /**
278 * @brief
279 *
280 * @param regs Pointer to controller registers
281 */
_i3c_rx_buf_threshold_set(struct mec_i3c_host_regs * regs,uint32_t val)282 void _i3c_rx_buf_threshold_set(struct mec_i3c_host_regs *regs, uint32_t val)
283 {
284 regs->DB_THLD_CTRL &= (uint32_t)~(0xFFu << DATA_BUF_THLD_RX_FIFO_BITPOS);
285 regs->DB_THLD_CTRL |= (val << DATA_BUF_THLD_RX_FIFO_BITPOS);
286 }
287
288 /**
289 * @brief
290 *
291 * @param regs Pointer to controller registers
292 */
_i3c_tx_start_threshold_set(struct mec_i3c_host_regs * regs,uint32_t val)293 void _i3c_tx_start_threshold_set(struct mec_i3c_host_regs *regs, uint32_t val)
294 {
295 regs->DB_THLD_CTRL &= (uint32_t)~(0xFFu << DATA_BUF_THLD_TX_FIFO_START_BITPOS);
296 regs->DB_THLD_CTRL |= (val << DATA_BUF_THLD_TX_FIFO_START_BITPOS);
297 }
298
299 /**
300 * @brief
301 *
302 * @param regs Pointer to controller registers
303 */
_i3c_rx_start_threshold_set(struct mec_i3c_host_regs * regs,uint32_t val)304 void _i3c_rx_start_threshold_set(struct mec_i3c_host_regs *regs, uint32_t val)
305 {
306 regs->DB_THLD_CTRL &= ~(0xFF << DATA_BUF_THLD_RX_FIFO_START_BITPOS);
307 regs->DB_THLD_CTRL |= (val << DATA_BUF_THLD_RX_FIFO_START_BITPOS);
308 }
309
310 /**
311 * @brief
312 *
313 * @param regs Pointer to controller registers
314 */
_i3c_notify_sir_reject(struct mec_i3c_host_regs * regs,bool opt)315 void _i3c_notify_sir_reject(struct mec_i3c_host_regs *regs, bool opt)
316 {
317 regs->IBI_QUE_CTRL = (opt << IBI_QUEUE_CTRL_SIR_REJ_BITPOS);
318 }
319
320 /**
321 * @brief
322 *
323 * @param regs Pointer to controller registers
324 */
_i3c_notify_mr_reject(struct mec_i3c_host_regs * regs,bool opt)325 void _i3c_notify_mr_reject(struct mec_i3c_host_regs *regs, bool opt)
326 {
327 regs->IBI_QUE_CTRL = (opt << IBI_QUEUE_CTRL_MR_REJ_BITPOS);
328 }
329
330 /**
331 * @brief
332 *
333 * @param regs Pointer to controller registers
334 */
_i3c_notify_hj_reject(struct mec_i3c_host_regs * regs,bool opt)335 void _i3c_notify_hj_reject(struct mec_i3c_host_regs *regs, bool opt)
336 {
337 regs->IBI_QUE_CTRL = (opt << IBI_QUEUE_CTRL_HJ_REJ_BITPOS);
338 }
339
340 /**
341 * @brief Set the dynamic address of the controller
342 *
343 * @param regs Pointer to controller registers
344 * @param address 7-bit dynamic address
345 */
_i3c_dynamic_addr_set(struct mec_i3c_host_regs * regs,uint8_t address)346 void _i3c_dynamic_addr_set(struct mec_i3c_host_regs *regs, uint8_t address)
347 {
348 regs->DEV_ADDR = ((address & 0x7F) << DEVICE_ADDR_DYNAMIC_ADDR_BITPOS) |
349 sbit_DEVICE_ADDR_DYNAMIC_ADDR_VALID;
350 }
351
352 /**
353 * @brief Set the static address of the controller
354 *
355 * @param regs Pointer to controller registers
356 * @param address 7-bit static address
357 */
_i3c_static_addr_set(struct mec_i3c_host_regs * regs,uint8_t address)358 void _i3c_static_addr_set(struct mec_i3c_host_regs *regs, uint8_t address)
359 {
360 volatile uint32_t reg_val;
361
362 reg_val = regs->DEV_ADDR;
363
364 reg_val |= ((address & 0x7F) | sbit_DEVICE_ADDR_STATIC_ADDR_VALID);
365
366 regs->DEV_ADDR = reg_val;
367 }
368
369 /**
370 * @brief Set the operation mode of the controller
371 *
372 * @param regs Pointer to controller registers
373 * @param mode device mode - 0-Controller, 1-Target
374 */
_i3c_operation_mode_set(struct mec_i3c_host_regs * regs,uint8_t mode)375 void _i3c_operation_mode_set(struct mec_i3c_host_regs *regs, uint8_t mode)
376 {
377 regs->DEV_EXT_CTRL = mode & 0x1;
378 }
379
380 /**
381 * @brief Enable the controller
382 *
383 * @param regs Pointer to controller registers
384 * @param mode device mode - 0-Controller, 1-Target
385 */
_i3c_enable(struct mec_i3c_host_regs * regs,uint8_t mode,bool enable_dma)386 void _i3c_enable(struct mec_i3c_host_regs *regs, uint8_t mode, bool enable_dma)
387 {
388 uint32_t val;
389
390 /* Read the control register */
391 val = regs->DEV_CTRL;
392
393 val |= sbit_ENABLE;
394
395 if (DEV_OPERATION_MODE_CTL == mode)
396 {
397 /* I3C Broadcast Address is included for private transfers */
398 val |= sbit_IBA_INCLUDE;
399 }
400
401 if (enable_dma) {
402 val |= sbit_DMA_ENABLE;
403 }
404
405 regs->DEV_CTRL = val;
406 }
407
408 /**
409 * @brief Disable the controller
410 *
411 * @param regs Pointer to controller registers
412 */
_i3c_disable(struct mec_i3c_host_regs * regs)413 void _i3c_disable(struct mec_i3c_host_regs *regs)
414 {
415 volatile uint32_t val = 0;
416
417 /* Read the control register */
418 val = regs->DEV_CTRL;
419
420 val &= ~sbit_ENABLE;
421
422 regs->DEV_CTRL = val;
423 }
424
425 /**
426 * @brief Resume the controller
427 *
428 * @param regs Pointer to controller registers
429 */
_i3c_resume(struct mec_i3c_host_regs * regs)430 void _i3c_resume(struct mec_i3c_host_regs *regs)
431 {
432 regs->DEV_CTRL |= sbit_RESUME;
433 }
434
435 /**
436 * @brief Clears transfer error status in Interrupt Status
437 *
438 * @param regs Pointer to controller registers
439 */
_i3c_xfer_err_sts_clr(struct mec_i3c_host_regs * regs)440 void _i3c_xfer_err_sts_clr(struct mec_i3c_host_regs *regs)
441 {
442 volatile uint32_t sts = 0;
443
444 sts = regs->INTR_STS;
445
446 if (sts & sbit_TRANSFER_ERR_STS) {
447 /* W1C */
448 regs->INTR_STS = sbit_TRANSFER_ERR_STS;
449 }
450 }
451
452 /**
453 * @brief Disable hot join
454 * used in master mode of operation
455 *
456 * @param regs Pointer to controller registers
457 */
_i3c_hot_join_disable(struct mec_i3c_host_regs * regs)458 void _i3c_hot_join_disable(struct mec_i3c_host_regs *regs)
459 {
460 volatile uint32_t val = 0;
461
462 /* Read the control register */
463 val = regs->DEV_CTRL;
464
465 /* sbit_HOT_JOIN_CTRL = 1 for NACK and send broadcast CCC
466 * to disable Hot-join */
467 val |= sbit_HOT_JOIN_CTRL;
468
469 regs->DEV_CTRL = val;
470 }
471
472 /**
473 * @brief Disable hot join
474 * used in target mode of operation
475 *
476 * @param regs Pointer to secondary controller registers
477 */
_i3c_tgt_hot_join_disable(struct mec_i3c_sec_regs * regs)478 void _i3c_tgt_hot_join_disable(struct mec_i3c_sec_regs *regs)
479 {
480 volatile uint32_t val = 0;
481
482 /* Read the target event status register */
483 val = regs->TGT_EVT_STS;
484
485 val &= (uint32_t)~sbit_HJ_ENABLE;
486
487 regs->DEV_CTRL = val;
488 }
489
490 /**
491 * @brief Enable hot join
492 * used in master mode of operation
493 *
494 * @param regs Pointer to controller registers
495 */
_i3c_hot_join_enable(struct mec_i3c_host_regs * regs)496 void _i3c_hot_join_enable(struct mec_i3c_host_regs *regs)
497 {
498 volatile uint32_t val = 0;
499
500 /* Read the control register */
501 val = regs->DEV_CTRL;
502
503 /* sbit_HOT_JOIN_CTRL = 0 ACK Hot-Join requests */
504 val &= ~sbit_HOT_JOIN_CTRL;
505
506 regs->DEV_CTRL = val;
507 }
508
509 /**
510 * @brief Program I2C Fast Mode Timing Register
511 *
512 * @param regs Pointer to controller registers
513 * @param core_clk_freq_ns Core clock frequency in nanoseconds
514 */
_i2c_fm_timing_set(struct mec_i3c_host_regs * regs,uint32_t core_clk_freq_ns)515 void _i2c_fm_timing_set(struct mec_i3c_host_regs *regs, uint32_t core_clk_freq_ns)
516 {
517 uint16_t low_count, high_count;
518 uint32_t timing_val;
519
520 high_count = (uint16_t)MEC_DIV_ROUND_UP(I2C_FM_SCL_MIN_HIGH_PERIOD_NS, core_clk_freq_ns);
521 if(high_count < I3C_SCL_TIMING_COUNT_MIN) {
522 high_count = I3C_SCL_TIMING_COUNT_MIN;
523 }
524
525 low_count = (uint16_t)MEC_DIV_ROUND_UP(I2C_FM_SCL_MIN_LOW_PERIOD_NS, core_clk_freq_ns);
526 if(low_count < I3C_SCL_TIMING_COUNT_MIN) {
527 low_count = I3C_SCL_TIMING_COUNT_MIN;
528 }
529
530 /* Program the I3C Push Pull Timing Register */
531 timing_val = (high_count << 16) | low_count;
532 regs->SCL_I2C_FM_TM = timing_val;
533
534 /* This is a Mixed Bus system
535 * Hence program the Bus Free Time (Master Mode) to tLOW of I2C Timing
536 */
537 regs->BUS_FREE_TM = low_count;
538 }
539
540 /**
541 * @brief Program the I3C Bus Free Timing Register
542 *
543 * @param regs Pointer to controller registers
544 * @param core_clk_freq_ns Core clock frequency in nanoseconds
545 */
_i3c_bus_free_timing_set(struct mec_i3c_sec_regs * regs,uint32_t core_clk_freq_ns)546 void _i3c_bus_free_timing_set(struct mec_i3c_sec_regs *regs, uint32_t core_clk_freq_ns)
547 {
548 uint32_t bus_free_timing_count;
549
550 /* To review */
551 bus_free_timing_count = (uint32_t)MEC_DIV_ROUND_UP(TGT_BUS_FREE_DURATION_ns, core_clk_freq_ns);
552 if(bus_free_timing_count < I3C_SCL_TIMING_COUNT_MIN) {
553 bus_free_timing_count = I3C_SCL_TIMING_COUNT_MIN;
554 }
555
556 regs->BUS_FREE_TM |= (bus_free_timing_count & 0xffffu);
557 }
558
559 /**
560 * @brief Program the I3C Bus Free Timing Register
561 *
562 * @param regs Pointer to controller registers
563 * @param core_clk_freq_ns Core clock frequency in nanoseconds
564 */
_i3c_bus_available_timing_set(struct mec_i3c_sec_regs * regs,uint32_t core_clk_freq_ns)565 void _i3c_bus_available_timing_set(struct mec_i3c_sec_regs *regs, uint32_t core_clk_freq_ns)
566 {
567 uint32_t bus_avail_timing_count;
568
569 bus_avail_timing_count = (uint32_t)MEC_DIV_ROUND_UP(TGT_BUS_AVAIL_COND_ns, core_clk_freq_ns);
570 if(bus_avail_timing_count < I3C_SCL_TIMING_COUNT_MIN) {
571 bus_avail_timing_count = I3C_SCL_TIMING_COUNT_MIN;
572 }
573
574 regs->BUS_FREE_TM = (bus_avail_timing_count << 16);
575 }
576
577 /**
578 * @brief Program the I3C Bus Free Timing Register
579 *
580 * @param regs Pointer to controller registers
581 * @param core_clk_freq_ns Core clock frequency in nanoseconds
582 */
_i3c_bus_idle_timing_set(struct mec_i3c_sec_regs * regs,uint32_t core_clk_freq_ns)583 void _i3c_bus_idle_timing_set(struct mec_i3c_sec_regs *regs, uint32_t core_clk_freq_ns)
584 {
585 uint32_t idle_count;
586
587 idle_count = (uint32_t)MEC_DIV_ROUND_UP(TGT_BUS_IDLE_COND_ns, core_clk_freq_ns);
588 if(idle_count < I3C_SCL_TIMING_COUNT_MIN) {
589 idle_count = I3C_SCL_TIMING_COUNT_MIN;
590 }
591
592 regs->BUS_IDLE_TM = idle_count;
593 }
594
595 /**
596 * @brief Program the I3C SDA Hold Switch Timing Register
597 *
598 * @param regs Pointer to controller registers
599 * @param core_clk_freq_ns Core clock frequency in nanoseconds
600 */
_i3c_sda_hld_switch_delay_timing_set(struct mec_i3c_sec_regs * regs,uint8_t sda_od_pp_switch_dly,uint8_t sda_pp_od_switch_dly,uint8_t sda_tx_hold)601 void _i3c_sda_hld_switch_delay_timing_set(struct mec_i3c_sec_regs *regs,
602 uint8_t sda_od_pp_switch_dly,
603 uint8_t sda_pp_od_switch_dly,
604 uint8_t sda_tx_hold)
605 {
606 regs->SDA_HMSD_TM = (sda_od_pp_switch_dly << SDA_OD_PP_SWITCH_DLY_BITPOS);
607 regs->SDA_HMSD_TM |= (sda_pp_od_switch_dly << SDA_PP_OD_SWITCH_DLY_BITPOS);
608 regs->SDA_HMSD_TM |= (sda_tx_hold << SDA_TX_HOLD_BITPOS);
609 }
610
611 /**
612 * @brief Program the I3C SDA Hold time control value
613 *
614 * @param regs Pointer to controller registers
615 * @param sda_tx_hold SDA TX Hold time control
616 */
_i3c_sda_hld_timing_set(struct mec_i3c_host_regs * regs,uint8_t sda_tx_hold)617 void _i3c_sda_hld_timing_set(struct mec_i3c_host_regs *regs,
618 uint8_t sda_tx_hold)
619 {
620 uint32_t reg_value = 0;
621
622 reg_value = regs->SDA_HMSD_TM;
623 regs->SDA_HMSD_TM = (reg_value & 0xFFF8FFFF) | (sda_tx_hold << SDA_TX_HOLD_BITPOS);
624 }
625
626 /**
627 * @brief Program the I3C read termination bit low count
628 *
629 * @param regs Pointer to controller registers
630 * @param sda_tx_hold SDA TX Hold time control
631 */
_i3c_read_term_bit_low_count_set(struct mec_i3c_host_regs * regs,uint8_t read_term_low_count)632 void _i3c_read_term_bit_low_count_set(struct mec_i3c_host_regs *regs,
633 uint8_t read_term_low_count)
634 {
635 uint32_t reg_value = 0;
636
637 reg_value = regs->SCL_TBLC_TM;
638 regs->SCL_TBLC_TM = (reg_value & 0xFFFFFFF0) | (read_term_low_count);
639 }
640
641 /**
642 * @brief Program the I3C SCL Low Master Extended Timeout register
643 *
644 * @param regs Pointer to controller registers
645 * @param core_clk_freq_ns Core clock frequency in nanoseconds
646 */
_i3c_scl_low_mst_tout_set(struct mec_i3c_sec_regs * regs,uint32_t tout_val)647 void _i3c_scl_low_mst_tout_set(struct mec_i3c_sec_regs *regs, uint32_t tout_val)
648 {
649 regs->SCL_LMST_TM = tout_val;
650 }
651
652 /**
653 * @brief Inform the core that I2C targets are present on the bus
654 *
655 * @param regs Pointer to controller registers
656 */
_i2c_target_present_set(struct mec_i3c_host_regs * regs)657 void _i2c_target_present_set(struct mec_i3c_host_regs *regs)
658 {
659 regs->DEV_CTRL |= sbit_I2C_TGT_PRESENT;
660 }
661
662 /**
663 * @brief Inform the core that I2C targets are not present on the bus
664 *
665 * @param regs Pointer to controller registers
666 */
_i2c_target_present_reset(struct mec_i3c_host_regs * regs)667 void _i2c_target_present_reset(struct mec_i3c_host_regs *regs)
668 {
669 regs->DEV_CTRL &= ~sbit_I2C_TGT_PRESENT;
670 }
671
672 /**
673 * @brief Program I2C Fast Mode Plus Timing Register
674 *
675 * @param regs Pointer to controller registers
676 * @param core_clk_freq_ns Core clock frequency in nanoseconds
677 */
_i2c_fmp_timing_set(struct mec_i3c_host_regs * regs,uint32_t core_clk_freq_ns)678 void _i2c_fmp_timing_set(struct mec_i3c_host_regs *regs, uint32_t core_clk_freq_ns)
679 {
680 uint32_t low_count, high_count;
681 uint32_t timing_val;
682
683 high_count = (uint32_t)MEC_DIV_ROUND_UP(I2C_FMP_SCL_MIN_HIGH_PERIOD_NS, core_clk_freq_ns);
684 if(high_count < I3C_SCL_TIMING_COUNT_MIN) {
685 high_count = I3C_SCL_TIMING_COUNT_MIN;
686 }
687
688 low_count = (uint32_t)MEC_DIV_ROUND_UP(I2C_FMP_SCL_MIN_LOW_PERIOD_NS, core_clk_freq_ns);
689 if(low_count < I3C_SCL_TIMING_COUNT_MIN) {
690 low_count = I3C_SCL_TIMING_COUNT_MIN;
691 }
692
693 /* Program the I3C Push Pull Timing Register */
694 timing_val = (high_count << 16) | low_count;
695 regs->SCL_I2C_FMP_TM = timing_val;
696 }
697
698 /**
699 * @brief Program I3C Push Pull Timing Register
700 *
701 * @param regs Pointer to controller registers
702 * @param core_clk_freq_ns Core clock frequency in nanoseconds
703 */
_i3c_push_pull_timing_set(struct mec_i3c_host_regs * regs,uint32_t core_clk_freq_ns,uint32_t i3c_freq_ns)704 void _i3c_push_pull_timing_set(struct mec_i3c_host_regs *regs, uint32_t core_clk_freq_ns,
705 uint32_t i3c_freq_ns)
706 {
707 uint32_t low_count = 0, high_count = 0, base_count = 0;
708 uint32_t timing_val = 0, sdr_ext_lcount = 0;
709
710 base_count = (uint32_t)MEC_DIV_ROUND_UP(I3C_PUSH_PULL_SCL_MIN_HIGH_PERIOD_NS, core_clk_freq_ns);
711
712 if(base_count < I3C_SCL_TIMING_COUNT_MIN) {
713 base_count = I3C_SCL_TIMING_COUNT_MIN;
714 }
715
716 high_count = (uint32_t)MEC_DIV_ROUND_UP(base_count * i3c_freq_ns, I3C_SCL_12_5MHZ_PERIOD_NS);
717
718 if(high_count < I3C_SCL_TIMING_COUNT_MIN) {
719 high_count = I3C_SCL_TIMING_COUNT_MIN;
720 }
721
722 low_count = high_count;
723
724 /* Program the I3C Push Pull Timing Register */
725 timing_val = (high_count << 16) | low_count;
726 regs->SCL_PP_TM = timing_val;
727
728 /* If this is a PURE I3C bus
729 * Program the Bus Free Time (Master Mode) to tCAS parameter
730 */
731 if (!(regs->DEV_CTRL & sbit_I2C_TGT_PRESENT))
732 {
733 regs->BUS_FREE_TM = low_count;
734 }
735
736 sdr_ext_lcount = MEC_DIV_ROUND_UP(I3C_BUS_SDR4_SCL_PERIOD_NS, core_clk_freq_ns) - high_count;
737 sdr_ext_lcount = sdr_ext_lcount << 8;
738 sdr_ext_lcount |= MEC_DIV_ROUND_UP(I3C_BUS_SDR3_SCL_PERIOD_NS, core_clk_freq_ns) - high_count;
739 sdr_ext_lcount = sdr_ext_lcount << 8;
740 sdr_ext_lcount |= MEC_DIV_ROUND_UP(I3C_BUS_SDR2_SCL_PERIOD_NS, core_clk_freq_ns) - high_count;
741 sdr_ext_lcount = sdr_ext_lcount << 8;
742 sdr_ext_lcount |= MEC_DIV_ROUND_UP(I3C_BUS_SDR1_SCL_PERIOD_NS, core_clk_freq_ns) - high_count;
743 sdr_ext_lcount = sdr_ext_lcount << 8;
744
745 regs->SCL_ELC_TM = sdr_ext_lcount;
746 }
747
748 /**
749 * @brief Program I3C Open Drain Timing Register
750 *
751 * @param regs Pointer to controller registers
752 * @param core_clk_freq_ns Core clock frequency in nanoseconds
753 */
_i3c_open_drain_timing_set(struct mec_i3c_host_regs * regs,uint32_t core_clk_freq_ns,uint32_t i3c_freq_ns)754 void _i3c_open_drain_timing_set(struct mec_i3c_host_regs *regs, uint32_t core_clk_freq_ns,
755 uint32_t i3c_freq_ns)
756 {
757 uint32_t low_count = 0, high_count = 0;
758 uint32_t timing_val;
759
760 high_count = (uint32_t)MEC_DIV_ROUND_UP(I3C_OPEN_DRAIN_SCL_MIN_HIGH_PERIOD_NS, core_clk_freq_ns);
761
762 high_count = (uint32_t)MEC_DIV_ROUND_UP(high_count * i3c_freq_ns, I3C_SCL_12_5MHZ_PERIOD_NS);
763
764 if(high_count < I3C_SCL_TIMING_COUNT_MIN) {
765 high_count = I3C_SCL_TIMING_COUNT_MIN;
766 }
767
768 low_count = (uint32_t)MEC_DIV_ROUND_UP(I3C_OPEN_DRAIN_SCL_MIN_LOW_PERIOD_NS, core_clk_freq_ns);
769
770 low_count = (uint32_t)MEC_DIV_ROUND_UP(low_count * i3c_freq_ns, I3C_SCL_12_5MHZ_PERIOD_NS);
771
772 if(low_count < I3C_SCL_TIMING_COUNT_MIN) {
773 low_count = I3C_SCL_TIMING_COUNT_MIN;
774 }
775
776 /* Program the I3C Push Pull Timing Register */
777 timing_val = (high_count << 16) | low_count;
778 regs->SCL_OD_TM = timing_val;
779 }
780
781 /**
782 * @brief
783 *
784 * @param regs Pointer to controller registers
785 */
_i3c_host_dma_tx_burst_length_set(struct mec_i3c_host_regs * regs,uint32_t val)786 void _i3c_host_dma_tx_burst_length_set(struct mec_i3c_host_regs *regs, uint32_t val)
787 {
788 regs->HOST_CFG &= (uint32_t)~(0x03u << HOST_CFG_DMA_TX_BURST_LENGTH_BIT_POS);
789 regs->HOST_CFG |= (val << HOST_CFG_DMA_TX_BURST_LENGTH_BIT_POS);
790 }
791
792 /**
793 * @brief
794 *
795 * @param regs Pointer to controller registers
796 */
_i3c_host_dma_rx_burst_length_set(struct mec_i3c_host_regs * regs,uint32_t val)797 void _i3c_host_dma_rx_burst_length_set(struct mec_i3c_host_regs *regs, uint32_t val)
798 {
799 regs->HOST_CFG &= (uint32_t)~(0x03u << HOST_CFG_DMA_RX_BURST_LENGTH_BIT_POS);
800 regs->HOST_CFG |= (val << HOST_CFG_DMA_RX_BURST_LENGTH_BIT_POS);
801 }
802
803 /**
804 * @brief
805 *
806 * @param regs Pointer to controller registers
807 */
_i3c_host_port_set(struct mec_i3c_host_regs * regs,uint32_t val)808 void _i3c_host_port_set(struct mec_i3c_host_regs *regs, uint32_t val)
809 {
810 regs->HOST_CFG &= (uint32_t)~(0x0Fu << HOST_CFG_PORT_SEL_BIT_POS);
811 regs->HOST_CFG |= (val << HOST_CFG_PORT_SEL_BIT_POS);
812 }
813
814 /**
815 * @brief
816 *
817 * @param regs Pointer to controller registers
818 */
_i3c_host_stuck_sda_config(struct mec_i3c_host_regs * regs,uint32_t en,uint32_t tout_val)819 void _i3c_host_stuck_sda_config(struct mec_i3c_host_regs *regs, uint32_t en, uint32_t tout_val)
820 {
821 regs->HOST_CFG &= (uint32_t)~(0x01u << HOST_CFG_STUCK_SDA_EN_BIT_POS);
822 regs->HOST_CFG |= (en << HOST_CFG_STUCK_SDA_EN_BIT_POS);
823 if(en) {
824 regs->STK_SDA_TMOUT = tout_val;
825 } else {
826 regs->STK_SDA_TMOUT = 0U;
827 }
828 }
829
830 /**
831 * @brief
832 *
833 * @param regs Pointer to controller registers
834 */
_i3c_host_tx_dma_tout_config(struct mec_i3c_host_regs * regs,uint32_t en,uint32_t tout_val)835 void _i3c_host_tx_dma_tout_config(struct mec_i3c_host_regs *regs, uint32_t en, uint32_t tout_val)
836 {
837 regs->HOST_CFG &= (uint32_t)~(0x01u << HOST_CFG_TX_DMA_TOUT_BITPOS);
838 regs->HOST_CFG |= (en << HOST_CFG_TX_DMA_TOUT_BITPOS);
839 if(en) {
840 regs->HOST_DMA_TX_TMOUT = tout_val;
841 } else {
842 regs->HOST_DMA_TX_TMOUT = 0U;
843 }
844 }
845
846 /**
847 * @brief
848 *
849 * @param regs Pointer to controller registers
850 */
_i3c_host_rx_dma_tout_config(struct mec_i3c_host_regs * regs,uint32_t en,uint32_t tout_val)851 void _i3c_host_rx_dma_tout_config(struct mec_i3c_host_regs *regs, uint32_t en, uint32_t tout_val)
852 {
853 regs->HOST_CFG &= (uint32_t)~(0x01u << HOST_CFG_TX_DMA_TOUT_BITPOS);
854 regs->HOST_CFG |= (en << HOST_CFG_TX_DMA_TOUT_BITPOS);
855 if(en) {
856 regs->HOST_DMA_RX_TMOUT = tout_val;
857 } else {
858 regs->HOST_DMA_RX_TMOUT = 0U;
859 }
860 }
861
862 /**
863 * @brief
864 *
865 * @param regs Pointer to controller registers
866 */
_i3c_sec_host_dma_tx_burst_length_set(struct mec_i3c_sec_regs * regs,uint32_t val)867 void _i3c_sec_host_dma_tx_burst_length_set(struct mec_i3c_sec_regs *regs, uint32_t val)
868 {
869 regs->SEC_CFG &= (uint32_t)~(0x03u << SEC_HOST_CFG_DMA_TX_BURST_LENGTH_BIT_POS);
870 regs->SEC_CFG |= (val << SEC_HOST_CFG_DMA_TX_BURST_LENGTH_BIT_POS);
871 }
872
873 /**
874 * @brief
875 *
876 * @param regs Pointer to controller registers
877 */
_i3c_sec_host_dma_rx_burst_length_set(struct mec_i3c_sec_regs * regs,uint32_t val)878 void _i3c_sec_host_dma_rx_burst_length_set(struct mec_i3c_sec_regs *regs, uint32_t val)
879 {
880 regs->SEC_CFG &= (uint32_t)~(0x03u << SEC_HOST_CFG_DMA_RX_BURST_LENGTH_BIT_POS);
881 regs->SEC_CFG |= (val << SEC_HOST_CFG_DMA_RX_BURST_LENGTH_BIT_POS);
882 }
883
884 /**
885 * @brief
886 *
887 * @param regs Pointer to controller registers
888 */
_i3c_sec_host_port_set(struct mec_i3c_sec_regs * regs,uint32_t val)889 void _i3c_sec_host_port_set(struct mec_i3c_sec_regs *regs, uint32_t val)
890 {
891 regs->SEC_CFG &= (uint32_t)~(0x0Fu << SEC_HOST_CFG_PORT_SEL_BIT_POS);
892 regs->SEC_CFG |= (val << SEC_HOST_CFG_PORT_SEL_BIT_POS);
893 }
894
895 /**
896 * @brief
897 *
898 * @param regs Pointer to controller registers
899 */
_i3c_sec_host_stuck_sda_scl_config(struct mec_i3c_sec_regs * regs,uint32_t en,uint32_t sda_tout_val,uint32_t scl_tout_val)900 void _i3c_sec_host_stuck_sda_scl_config(struct mec_i3c_sec_regs *regs, uint32_t en,
901 uint32_t sda_tout_val, uint32_t scl_tout_val)
902 {
903 regs->SEC_CFG &= (uint32_t)~(0x01u << SEC_HOST_CFG_STUCK_SDA_EN_BIT_POS);
904 regs->SEC_CFG |= (en << SEC_HOST_CFG_STUCK_SDA_EN_BIT_POS);
905 if(en) {
906 regs->STK_SDA_TMOUT =
907 ((sda_tout_val & (uint32_t)MEC_GENMASK(9 , 0)) << SEC_HOST_CFG_STUCK_SDA_TOUT_BITPOS);
908 regs->STK_SDA_TMOUT =
909 ((scl_tout_val & (uint32_t)MEC_GENMASK(9 , 0)) << SEC_HOST_CFG_STUCK_SCL_TOUT_BITPOS);
910 } else {
911 regs->STK_SDA_TMOUT = 0U;
912 }
913 }
914
915 /**
916 * @brief
917 *
918 * @param regs Pointer to controller registers
919 */
_i3c_sec_host_tx_dma_tout_config(struct mec_i3c_sec_regs * regs,uint32_t en,uint32_t tout_val)920 void _i3c_sec_host_tx_dma_tout_config(struct mec_i3c_sec_regs *regs, uint32_t en, uint32_t tout_val)
921 {
922 if(en) {
923 regs->HOST_DMA_TX_TMOUT = tout_val;
924 } else {
925 regs->HOST_DMA_TX_TMOUT = 0U;
926 }
927 }
928
929 /**
930 * @brief
931 *
932 * @param regs Pointer to controller registers
933 */
_i3c_sec_host_rx_dma_tout_config(struct mec_i3c_sec_regs * regs,uint32_t en,uint32_t tout_val)934 void _i3c_sec_host_rx_dma_tout_config(struct mec_i3c_sec_regs *regs, uint32_t en, uint32_t tout_val)
935 {
936 if(en) {
937 regs->HOST_DMA_RX_TMOUT = tout_val;
938 } else {
939 regs->HOST_DMA_RX_TMOUT = 0U;
940 }
941 }
942
943 /**
944 * @brief
945 *
946 * @param regs Pointer to controller registers
947 */
_i3c_sec_host_dma_fsm_enable(struct mec_i3c_sec_regs * regs)948 void _i3c_sec_host_dma_fsm_enable(struct mec_i3c_sec_regs *regs)
949 {
950 uint32_t bitmask;
951
952 bitmask = (SEC_HOST_CFG_TX_DMA_FSM_ENABLE << SEC_HOST_CFG_TX_DMA_FSM_BITPOS) | \
953 (SEC_HOST_CFG_RX_DMA_FSM_ENABLE << SEC_HOST_CFG_RX_DMA_FSM_BITPOS);
954
955 regs->SEC_CFG |= bitmask;
956 }
957
958 /**
959 * @brief Read the Device Address Table Pointer Register
960 *
961 * @param regs Pointer to controller registers
962 * @param start_addr return the start address of device address table
963 * @param depth return the depth of device address table
964 */
_i3c_dev_addr_table_ptr_get(struct mec_i3c_host_regs * regs,uint16_t * start_addr,uint16_t * depth)965 void _i3c_dev_addr_table_ptr_get(struct mec_i3c_host_regs *regs, uint16_t *start_addr,
966 uint16_t *depth)
967 {
968 uint32_t val;
969
970 val = regs->DAT_PTR;
971
972 *start_addr = val & 0xFFFFu;
973 *depth = (uint16_t)((val >> 16) & 0xFFFFu);
974 }
975
976 /**
977 * @brief Read the Device Characteristics Table Pointer Register
978 *
979 * @param regs Pointer to controller registers
980 * @param start_addr return the start address of device characteristics table
981 * @param depth return the depth of device characteristics table
982 */
_i3c_dev_char_table_ptr_get(struct mec_i3c_host_regs * regs,uint16_t * start_addr,uint16_t * depth)983 void _i3c_dev_char_table_ptr_get(struct mec_i3c_host_regs *regs, uint16_t *start_addr,
984 uint16_t *depth)
985 {
986 uint32_t val;
987
988 val = regs->DCT_PTR;
989
990 *start_addr = val & 0xFFFu; /* Bits 0 to 11 */
991 *depth = (val >> 12) & 0x7Fu; /* Bits 12 to 18 */
992 }
993
994 /**
995 * @brief Retrieve the current operation of the the device
996 *
997 * @param regs Pointer to controller registers
998 */
_i3c_dev_operation_mode_get(struct mec_i3c_host_regs * regs)999 uint8_t _i3c_dev_operation_mode_get(struct mec_i3c_host_regs *regs)
1000 {
1001 return (uint8_t)(regs->DEV_EXT_CTRL & 0x03U);
1002 }
1003
1004 /**
1005 * @brief Retrieve the current operation mode of the controller
1006 * (active or secondary)
1007 *
1008 * @param regs Pointer to controller registers
1009 */
_i3c_dev_controller_role_get(struct mec_i3c_host_regs * regs)1010 uint8_t _i3c_dev_controller_role_get(struct mec_i3c_host_regs *regs)
1011 {
1012 return (uint8_t)(regs->PRES_STATE & 0x04U);
1013 }
1014
1015 /**
1016 * @brief Retrieve the HW configured role of the core
1017 * (controller only or secondary controller or target only)
1018 *
1019 * @param regs Pointer to controller registers
1020 */
_i3c_dev_role_config_get(struct mec_i3c_host_regs * regs)1021 uint8_t _i3c_dev_role_config_get(struct mec_i3c_host_regs *regs)
1022 {
1023 return (uint8_t)(regs->HW_CAP & 0x07U);
1024 }
1025
1026 /**
1027 * @brief Writes the DAT entry
1028 *
1029 * @param regs Pointer to controller registers
1030 * @param DAT_start Start location of DAT
1031 * @param DAT_idx Position in the Device Address table
1032 * @param val 32-bit value to program
1033 */
_i3c_DAT_write(struct mec_i3c_host_regs * regs,uint16_t DAT_start,uint8_t DAT_idx,uint32_t val)1034 void _i3c_DAT_write(struct mec_i3c_host_regs *regs, uint16_t DAT_start, uint8_t DAT_idx,
1035 uint32_t val)
1036 {
1037 uint32_t *entry_addr;
1038
1039 entry_addr = (uint32_t *)((uint32_t)regs + ((uint32_t)DAT_start + ((uint32_t)DAT_idx * 4u)));
1040
1041 *entry_addr = val;
1042 }
1043
1044 /**
1045 * @brief Reads the DAT entry
1046 *
1047 * @param regs Pointer to controller registers
1048 * @param DAT_start Start location of DAT
1049 * @param DAT_idx Position in the Device Address table
1050 * @return val 32-bit DAT value
1051 */
_i3c_DAT_read(struct mec_i3c_host_regs * regs,uint16_t DAT_start,uint8_t DAT_idx)1052 uint32_t _i3c_DAT_read(struct mec_i3c_host_regs *regs, uint16_t DAT_start, uint8_t DAT_idx)
1053 {
1054 uint32_t *entry_addr;
1055 uint32_t val;
1056
1057 entry_addr = (uint32_t *)((uint32_t)regs + ((uint32_t)DAT_start + ((uint32_t)DAT_idx * 4u)));
1058
1059 val = *entry_addr;
1060
1061 return val;
1062 }
1063
1064 /**
1065 * @brief Read the DCT
1066 *
1067 * @param regs Pointer to controller registers
1068 * @param DAT_start Start location of DCT
1069 * @param DAT_idx Position in the Device Characteristics table
1070 * @param info DCT information read
1071 */
_i3c_DCT_read(struct mec_i3c_host_regs * regs,uint16_t DCT_start,uint8_t DCT_idx,struct mec_i3c_DCT_info * info)1072 void _i3c_DCT_read(struct mec_i3c_host_regs *regs, uint16_t DCT_start, uint8_t DCT_idx,
1073 struct mec_i3c_DCT_info *info)
1074 {
1075 uint32_t *entry_addr;
1076 uint64_t prov_id = 0;
1077
1078 entry_addr =
1079 (uint32_t *)((uint32_t)regs + ((uint32_t)DCT_start + ((uint32_t)DCT_idx * 4u * 4u)));
1080
1081 prov_id = *entry_addr;
1082
1083 entry_addr++;
1084 info->pid = (prov_id << 16) | (*entry_addr & 0xFFFF);
1085
1086 entry_addr++;
1087 info->dcr = *entry_addr & 0xFF;
1088 info->bcr = (*entry_addr >> 8) & 0xFF;
1089
1090 entry_addr++;
1091 info->dynamic_addr = *entry_addr & 0x7F;
1092 }
1093
1094 /**
1095 * @brief Read the Secondary DCT
1096 *
1097 * @param regs Pointer to controller registers
1098 * @param DAT_start Start location of DCT
1099 * @param DAT_idx Position in the Device Characteristics table
1100 * @param info SDCT information read
1101 */
_i3c_SDCT_read(struct mec_i3c_host_regs * regs,uint16_t DCT_start,uint8_t idx,struct mec_i3c_SDCT_info * info)1102 void _i3c_SDCT_read(struct mec_i3c_host_regs *regs, uint16_t DCT_start, uint8_t idx,
1103 struct mec_i3c_SDCT_info *info)
1104 {
1105 uint32_t *entry_addr;
1106 uint32_t sdct_val = 0;
1107
1108 entry_addr = (uint32_t *)((uint32_t)regs + ((uint32_t)DCT_start + ((uint32_t)idx * 4u)));
1109
1110 sdct_val = *entry_addr;
1111
1112 info->dynamic_addr = sdct_val & 0xFFu;
1113 info->dcr = (sdct_val >> 8) & 0xFFu;
1114 info->bcr = (sdct_val >> 16) & 0xFFu;
1115 info->static_addr = (uint8_t)((sdct_val >> 24) & 0xFFu);
1116 }
1117
1118 /**
1119 * @brief Write the FIFO with data
1120 *
1121 * @param regs Pointer to controller registers
1122 * @param buffer buffer with data
1123 * @param len Length of data in the buffer
1124 */
_i3c_fifo_write(struct mec_i3c_host_regs * regs,uint8_t * buffer,uint16_t len)1125 void _i3c_fifo_write(struct mec_i3c_host_regs *regs, uint8_t *buffer, uint16_t len)
1126 {
1127 uint32_t *dword_ptr;
1128 uint32_t last_dword = 0;
1129 uint16_t i, remaining_bytes;
1130
1131 if (len >= 4) {
1132
1133 dword_ptr = (uint32_t *)buffer;
1134
1135 for (i = 0; i < len / 4; i++) {
1136 regs->TX_DATA = dword_ptr[i];
1137 }
1138 }
1139
1140 remaining_bytes = len % 4;
1141
1142 if (remaining_bytes) {
1143 memcpy(&last_dword, buffer + (len & ~0x3), remaining_bytes);
1144 regs->TX_DATA = last_dword;
1145 }
1146 }
1147
1148 /**
1149 * @brief Read from FIFO
1150 *
1151 * @param regs Pointer to controller registers
1152 * @param buffer buffer to copy data
1153 * @param len Length of data to read
1154 */
_i3c_fifo_read(struct mec_i3c_host_regs * regs,uint8_t * buffer,uint16_t len)1155 void _i3c_fifo_read(struct mec_i3c_host_regs *regs, uint8_t *buffer, uint16_t len)
1156 {
1157 uint32_t *dword_ptr;
1158 uint32_t last_dword = 0;
1159 uint16_t i =0, remaining_bytes = 0;
1160
1161 if (len >= 4) {
1162
1163 dword_ptr = (uint32_t *)buffer;
1164
1165 for (i = 0; i < len / 4; i++) {
1166 dword_ptr[i] = regs->RX_DATA;
1167 }
1168 }
1169
1170 remaining_bytes = len % 4;
1171
1172 if (remaining_bytes) {
1173 last_dword = regs->RX_DATA;
1174 memcpy(buffer + (len & ~0x3), &last_dword, remaining_bytes);
1175 }
1176 }
1177
1178 /**
1179 * @brief Read from IBI Queue
1180 *
1181 * @param regs Pointer to controller registers
1182 * @param buffer buffer to copy data
1183 * @param len Length of data to read
1184 */
_i3c_ibi_data_read(struct mec_i3c_host_regs * regs,uint8_t * buffer,uint16_t len)1185 void _i3c_ibi_data_read(struct mec_i3c_host_regs *regs, uint8_t *buffer, uint16_t len)
1186 {
1187 uint32_t *dword_ptr;
1188 uint32_t last_dword = 0;
1189 uint16_t i =0, remaining_bytes = 0;
1190 volatile uint32_t drain_dword;
1191 bool drain_flag = false;
1192
1193 if (NULL == buffer) {
1194 drain_flag = true;
1195 }
1196
1197 if (len >= 4) {
1198
1199 if (drain_flag) {
1200 for (i = 0; i < len / 4; i++) {
1201 drain_dword |= regs->IBI_QUE_STS;
1202 }
1203 } else {
1204 dword_ptr = (uint32_t *)buffer;
1205
1206 for (i = 0; i < len / 4; i++) {
1207 dword_ptr[i] = regs->IBI_QUE_STS;
1208 }
1209 }
1210 }
1211
1212 remaining_bytes = len % 4;
1213
1214 if (remaining_bytes) {
1215 last_dword = regs->IBI_QUE_STS;
1216 if (!drain_flag) {
1217 memcpy(buffer + (len & ~0x3), &last_dword, remaining_bytes);
1218 }
1219 }
1220 }
1221
1222 /**
1223 * @brief Reset all transfers
1224 *
1225 * @param regs Pointer to controller registers
1226 */
_i3c_xfers_reset(struct mec_i3c_host_regs * regs)1227 void _i3c_xfers_reset(struct mec_i3c_host_regs *regs)
1228 {
1229 volatile uint32_t reg_val = 1;
1230
1231 regs->RST_CTRL = RESET_CTRL_RX_FIFO_RST | RESET_CTRL_TX_FIFO_RST |
1232 RESET_CTRL_RES_Q_RST | RESET_CTRL_CMD_Q_RST;
1233
1234 while (reg_val) {
1235 reg_val = regs->RST_CTRL;
1236 }
1237 }
1238
1239 /**
1240 * @brief clears residual data by flushing transmit fifo
1241 *
1242 * @param regs Pointer to controller registers
1243 */
_i3c_tx_fifo_rst(struct mec_i3c_host_regs * regs)1244 void _i3c_tx_fifo_rst(struct mec_i3c_host_regs *regs)
1245 {
1246 regs->RST_CTRL = RESET_CTRL_TX_FIFO_RST;
1247 }
1248
1249 /**
1250 * @brief resets RX Fifo
1251 *
1252 * @param regs Pointer to controller registers
1253 */
_i3c_rx_fifo_rst(struct mec_i3c_host_regs * regs)1254 void _i3c_rx_fifo_rst(struct mec_i3c_host_regs *regs)
1255 {
1256 regs->RST_CTRL = RESET_CTRL_RX_FIFO_RST;
1257 }
1258
1259 /**
1260 * @brief Resets Command Queue
1261 *
1262 * @param regs Pointer to controller registers
1263 */
_i3c_cmd_queue_rst(struct mec_i3c_host_regs * regs)1264 void _i3c_cmd_queue_rst(struct mec_i3c_host_regs *regs)
1265 {
1266 regs->RST_CTRL = RESET_CTRL_CMD_Q_RST;
1267 }
1268
1269 /**
1270 * @brief I3C core software reset
1271 *
1272 * @param regs Pointer to controller registers
1273 */
_i3c_soft_reset(struct mec_i3c_host_regs * regs)1274 void _i3c_soft_reset(struct mec_i3c_host_regs *regs)
1275 {
1276 volatile uint32_t reg_val = 1;
1277
1278 regs->RST_CTRL = RESET_CTRL_SOFT_RST;
1279
1280 while (reg_val & RESET_CTRL_SOFT_RST) {
1281 reg_val = regs->RST_CTRL;
1282 }
1283 }
1284 /**
1285 * @brief Write the command in the Command Queue Port
1286 *
1287 * @param regs Pointer to controller registers
1288 * @param cmd The Command
1289 */
_i3c_command_write(struct mec_i3c_host_regs * regs,uint32_t cmd)1290 void _i3c_command_write(struct mec_i3c_host_regs *regs, uint32_t cmd)
1291 {
1292 regs->CMD = cmd;
1293 }
1294
1295 /**
1296 * @brief Retrieve the depth of the TX FIFO
1297 * in bytes
1298 */
_i3c_tx_fifo_depth_get(struct mec_i3c_host_regs * regs)1299 uint8_t _i3c_tx_fifo_depth_get(struct mec_i3c_host_regs *regs)
1300 {
1301 return (uint8_t)((FIFO_DEPTH_MIN_DWORD << ((regs->QUE_SIZE_CAP & MEC_GENMASK(3, 0)) >> Q_CAP_TX_FIFO_DEPTH_BITPOS)) * 4u);
1302 }
1303
1304 /**
1305 * @brief Retrieve the depth of the RX FIFO
1306 * in bytes
1307 */
_i3c_rx_fifo_depth_get(struct mec_i3c_host_regs * regs)1308 uint8_t _i3c_rx_fifo_depth_get(struct mec_i3c_host_regs *regs)
1309 {
1310 return (uint8_t)((FIFO_DEPTH_MIN_DWORD << ((regs->QUE_SIZE_CAP & MEC_GENMASK(7, 4)) >> Q_CAP_RX_FIFO_DEPTH_BITPOS)) * 4u);
1311 }
1312
1313 /**
1314 * @brief Retrieve the depth of the command FIFO
1315 * in bytes
1316 */
_i3c_cmd_fifo_depth_get(struct mec_i3c_host_regs * regs)1317 uint8_t _i3c_cmd_fifo_depth_get(struct mec_i3c_host_regs *regs)
1318 {
1319 return (uint8_t)(FIFO_DEPTH_MIN_DWORD << ((regs->QUE_SIZE_CAP & MEC_GENMASK(11, 8)) >> Q_CAP_CMD_FIFO_DEPTH_BITPOS));
1320 }
1321
1322 /**
1323 * @brief Retrieve the depth of the response FIFO
1324 * in bytes
1325 */
_i3c_resp_fifo_depth_get(struct mec_i3c_host_regs * regs)1326 uint8_t _i3c_resp_fifo_depth_get(struct mec_i3c_host_regs *regs)
1327 {
1328 return (uint8_t)(FIFO_DEPTH_MIN_DWORD << ((regs->QUE_SIZE_CAP & MEC_GENMASK(15, 12)) >> Q_CAP_RESP_FIFO_DEPTH_BITPOS));
1329 }
1330
1331 /**
1332 * @brief Retrieve the depth of the IBI FIFO
1333 * in bytes
1334 */
_i3c_ibi_fifo_depth_get(struct mec_i3c_host_regs * regs)1335 uint8_t _i3c_ibi_fifo_depth_get(struct mec_i3c_host_regs *regs)
1336 {
1337 return (uint8_t)(FIFO_DEPTH_MIN_DWORD << ((regs->QUE_SIZE_CAP & MEC_GENMASK(19, 16)) >> Q_CAP_IBI_FIFO_DEPTH_BITPOS));
1338 }
1339
1340 /**
1341 * @brief Set the PID of secondary controller (in target mode)
1342 */
_i3c_tgt_pid_set(struct mec_i3c_sec_regs * regs,uint16_t tgt_mipi_mfg_id,bool is_random_prov_id,uint16_t tgt_part_id,uint8_t tgt_inst_id,uint16_t tgt_pid_dcr)1343 void _i3c_tgt_pid_set(struct mec_i3c_sec_regs *regs,
1344 uint16_t tgt_mipi_mfg_id,
1345 bool is_random_prov_id,
1346 uint16_t tgt_part_id,
1347 uint8_t tgt_inst_id,
1348 uint16_t tgt_pid_dcr)
1349 {
1350 regs->MIPI_MAN_ID = (tgt_mipi_mfg_id << TGT_MIPI_MFG_ID_BITPOS);
1351
1352 if(false == is_random_prov_id) {
1353 regs->NORM_PROV_ID = (tgt_part_id << TGT_PART_ID_BITPOS) |
1354 (tgt_inst_id << TGT_INST_ID_BITPOS) |
1355 (tgt_pid_dcr << TGT_PID_DCR_BITPOS);
1356 }
1357 }
1358
1359 /**
1360 * @brief Get the Dynamic address valid bit
1361 * of secondary controller (in target mode)
1362 */
_i3c_tgt_dyn_addr_valid_get(struct mec_i3c_sec_regs * regs)1363 bool _i3c_tgt_dyn_addr_valid_get(struct mec_i3c_sec_regs *regs)
1364 {
1365 return (bool)(regs->DEV_ADDR & sbit_DEVICE_ADDR_DYNAMIC_ADDR_VALID);
1366 }
1367
1368 /**
1369 * @brief Get the Dynamic address
1370 * of secondary controller (in target mode)
1371 */
_i3c_tgt_dyn_addr_get(struct mec_i3c_sec_regs * regs)1372 uint8_t _i3c_tgt_dyn_addr_get(struct mec_i3c_sec_regs *regs)
1373 {
1374 return (uint8_t)((regs->DEV_ADDR & MEC_GENMASK(22, 16)) >> DEVICE_ADDR_DYNAMIC_ADDR_BITPOS);
1375 }
1376
1377 /**
1378 * @brief Set the MRL of secondary controller (in target mode)
1379 */
_i3c_tgt_mrl_set(struct mec_i3c_sec_regs * regs,uint16_t mrl)1380 void _i3c_tgt_mrl_set(struct mec_i3c_sec_regs *regs, uint16_t mrl)
1381 {
1382 regs->MAX_RW_LEN = (regs->MAX_RW_LEN & ~(MEC_GENMASK(31, 16))) | (mrl << MRL_BITPOS);
1383 }
1384
1385 /**
1386 * @brief Set the MWL of secondary controller (in target mode)
1387 */
_i3c_tgt_mwl_set(struct mec_i3c_sec_regs * regs,uint16_t mwl)1388 void _i3c_tgt_mwl_set(struct mec_i3c_sec_regs *regs, uint16_t mwl)
1389 {
1390 regs->MAX_RW_LEN = (regs->MAX_RW_LEN & ~(MEC_GENMASK(15, 0))) | (mwl << MWL_BITPOS);
1391 }
1392
1393 /**
1394 * @brief Set the MXDS value of secondary controller (in target mode)
1395 */
_i3c_tgt_mxds_set(struct mec_i3c_sec_regs * regs,uint8_t wr_speed,uint8_t rd_speed,uint8_t tsco,uint32_t rd_trnd_us)1396 void _i3c_tgt_mxds_set(struct mec_i3c_sec_regs *regs,
1397 uint8_t wr_speed,
1398 uint8_t rd_speed,
1399 uint8_t tsco,
1400 uint32_t rd_trnd_us)
1401 {
1402 regs->MAX_DS = (wr_speed << MXDS_MAX_WR_SPEED_BITPOS) |
1403 (rd_speed << MXDS_MAX_RD_SPEED_BITPOS) |
1404 (tsco << MXDS_TSCO_BITPOS);
1405 regs->MAX_RD_TAR = MXDS_MAX_RD_TURN_MASK(rd_trnd_us);
1406 }
1407
1408 /**
1409 * @brief Check if SIR is enabled by the controller
1410 */
_i3c_tgt_SIR_enabled(struct mec_i3c_sec_regs * regs)1411 bool _i3c_tgt_SIR_enabled(struct mec_i3c_sec_regs *regs)
1412 {
1413 bool ret = false;
1414 if (regs->TGT_EVT_STS & TGT_EVT_STS_SIR_EN) {
1415 ret = true;
1416 }
1417
1418 return ret;
1419 }
1420
1421 /**
1422 * @brief Check if SIR is enabled by the controller
1423 */
_i3c_tgt_MR_enabled(struct mec_i3c_sec_regs * regs)1424 bool _i3c_tgt_MR_enabled(struct mec_i3c_sec_regs *regs)
1425 {
1426 bool ret = false;
1427 if (regs->TGT_EVT_STS & TGT_EVT_STS_MIR_EN) {
1428 ret = true;
1429 }
1430
1431 return ret;
1432 }
1433
1434 /**
1435 * @brief Raise IBI Target Interrupt Request (SIR)
1436 */
_i3c_tgt_raise_ibi_SIR(struct mec_i3c_sec_regs * regs,uint8_t * sir_data,uint8_t sir_datalen,uint8_t mdb)1437 void _i3c_tgt_raise_ibi_SIR(struct mec_i3c_sec_regs *regs, uint8_t *sir_data, uint8_t sir_datalen,
1438 uint8_t mdb)
1439 {
1440 uint32_t sir_data_dword = 0;
1441
1442 regs->TARG_IREQ = (mdb << TGT_INTR_REQ_MDB_BITPOS) |
1443 (sir_datalen << TGT_INTR_REQ_SIR_DATALEN_BITPOS);
1444
1445 if (sir_datalen ) {
1446 for (int i = 0; i < sir_datalen; i++) {
1447 sir_data_dword <<= 8;
1448 sir_data_dword |= sir_data[i];
1449 }
1450 regs->TARG_IREQ_DATA = sir_data_dword;
1451 }
1452 regs->TARG_IREQ |= TGT_INTR_REQ_SIR;
1453 }
1454
1455 /**
1456 * @brief Raise IBI Master Request (MR)
1457 */
_i3c_tgt_raise_ibi_MR(struct mec_i3c_sec_regs * regs)1458 void _i3c_tgt_raise_ibi_MR(struct mec_i3c_sec_regs *regs)
1459 {
1460 regs->TARG_IREQ = TGT_INTR_REQ_MR;
1461
1462 /* Enable ACK for GETACCMST CCC from master */
1463 regs->DEV_EXT_CTRL &= ~(DEV_REQMST_ACK_CTRL_NACK);
1464 }
1465
1466 /**
1467 * @brief Retrieve the IBI response from IBI Response register
1468 */
_i3c_tgt_ibi_resp_get(struct mec_i3c_sec_regs * regs,uint8_t * sir_rem_datalen)1469 bool _i3c_tgt_ibi_resp_get(struct mec_i3c_sec_regs *regs, uint8_t *sir_rem_datalen)
1470 {
1471 bool ret = false;
1472 /* Databook mentions SIR RESP DATA LENGTH as bits 8 t0 23, but we are using only
1473 * 8 bits because IBI Datalen is not supposed to be more than 4
1474 */
1475 *sir_rem_datalen = (regs->TARG_IBI_RESP >> TGT_IBI_RESP_DATALEN_BITPOS) & 0xFF;
1476
1477 if (TGT_IBI_RESP_SUCCESS == (regs->TARG_IBI_RESP & 0x3)) {
1478 ret = true;
1479 }
1480
1481 return ret;
1482 }
1483
1484 /**
1485 * @brief Retrieve target max read length
1486 */
_i3c_tgt_MRL_get(struct mec_i3c_sec_regs * regs,uint16_t * max_rd_len)1487 void _i3c_tgt_MRL_get(struct mec_i3c_sec_regs *regs, uint16_t *max_rd_len)
1488 {
1489 *max_rd_len = (uint16_t)(regs->MAX_RW_LEN >> 16);
1490 }
1491
1492 /**
1493 * @brief Retrieve target max write length
1494 */
_i3c_tgt_MWL_get(struct mec_i3c_sec_regs * regs,uint16_t * max_wr_len)1495 void _i3c_tgt_MWL_get(struct mec_i3c_sec_regs *regs, uint16_t *max_wr_len)
1496 {
1497 *max_wr_len = (uint16_t)(regs->MAX_RW_LEN & 0xFFFF);
1498 }
1499
1500 /**
1501 * @brief Set target max read and write length
1502 */
_i3c_tgt_MRL_MWL_set(struct mec_i3c_sec_regs * regs,uint16_t max_rd_len,uint16_t max_wr_len)1503 void _i3c_tgt_MRL_MWL_set(struct mec_i3c_sec_regs *regs, uint16_t max_rd_len, uint16_t max_wr_len)
1504 {
1505 regs->MAX_RW_LEN = ((uint32_t)max_rd_len << 16) | max_wr_len;
1506 }
1507
1508 /**
1509 * @brief Retrieve target max write length
1510 */
_i3c_tgt_MWL_set(struct mec_i3c_sec_regs * regs,uint16_t * max_wr_len)1511 void _i3c_tgt_MWL_set(struct mec_i3c_sec_regs *regs, uint16_t *max_wr_len)
1512 {
1513 *max_wr_len = (uint16_t)(regs->MAX_RW_LEN & 0xFFFFu);
1514 }
1515
1516 /**
1517 * @brief Returns true if controller updated MRL
1518 */
_i3c_tgt_MRL_updated(struct mec_i3c_sec_regs * regs)1519 bool _i3c_tgt_MRL_updated(struct mec_i3c_sec_regs *regs)
1520 {
1521 bool ret = false;
1522
1523 if (regs->TGT_EVT_STS & TGT_EVT_STS_MRL_UPDATED) {
1524 ret = true;
1525 /* Write 1 to clear */
1526 regs->TGT_EVT_STS = TGT_EVT_STS_MRL_UPDATED;
1527 }
1528
1529 return ret;
1530 }
1531
1532 /**
1533 * @brief Returns true if controller updated MWL
1534 */
_i3c_tgt_MWL_updated(struct mec_i3c_sec_regs * regs)1535 bool _i3c_tgt_MWL_updated(struct mec_i3c_sec_regs *regs)
1536 {
1537 bool ret = false;
1538
1539 if (regs->TGT_EVT_STS & TGT_EVT_STS_MWL_UPDATED) {
1540 ret = true;
1541 /* Write 1 to clear */
1542 regs->TGT_EVT_STS = TGT_EVT_STS_MWL_UPDATED;
1543 }
1544
1545 return ret;
1546 }
1547
1548 /**
1549 * @brief Set target max read and write speed
1550 */
_i3c_tgt_max_speed_update(struct mec_i3c_sec_regs * regs,uint8_t max_rd_speed,uint8_t max_wr_speed)1551 void _i3c_tgt_max_speed_update(struct mec_i3c_sec_regs *regs, uint8_t max_rd_speed,
1552 uint8_t max_wr_speed)
1553 {
1554 regs->MAX_DS &= (uint32_t)~(TGT_MAX_WR_DATA_SPEED_MASK << TGT_MAX_WR_DATA_SPEED_POS);
1555 regs->MAX_DS &= (uint32_t)~(TGT_MAX_RD_DATA_SPEED_MASK << TGT_MAX_RD_DATA_SPEED_POS);
1556
1557 regs->MAX_DS |= (max_wr_speed << TGT_MAX_WR_DATA_SPEED_POS);
1558 regs->MAX_DS |= (max_rd_speed << TGT_MAX_RD_DATA_SPEED_POS);
1559 }
1560
1561 /**
1562 * @brief Set target max read and write speed
1563 */
_i3c_tgt_clk_to_data_turn_update(struct mec_i3c_sec_regs * regs,uint8_t clk_data_turn_time)1564 void _i3c_tgt_clk_to_data_turn_update(struct mec_i3c_sec_regs *regs, uint8_t clk_data_turn_time)
1565 {
1566 regs->MAX_DS &= (uint32_t)~(TGT_CLK_TO_DATA_TURN_MASK << TGT_CLK_TO_DATA_TURN_POS);
1567
1568 regs->MAX_DS |= ((uint32_t)clk_data_turn_time << TGT_CLK_TO_DATA_TURN_POS);
1569 }
1570