1 /*
2 * Copyright (c) 2023 Intel Corporation
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include "sedi_driver_dma.h"
8 #include "sedi_driver_pm.h"
9 #include <sedi_driver_i2c.h>
10 #include <sedi_i2c_regs.h>
11 #include "sedi_driver_core.h"
12
13 #define I2C_MAX_BLOCK_TS (4096)
14
15 #define I2C_SDA_HOLD_DEFAULT (133)
16 #define I2C_FIFO_DEFAULT_WATERMARK (I2C_FIFO_DEPTH / 2U)
17
18 #define LBW_CLK_MHZ (sedi_pm_get_lbw_clock() / 1000000)
19
20 enum { I2C_SPEED_STANDARD = 0, I2C_SPEED_FAST, I2C_SPEED_FAST_PLUS, I2C_SPEED_HIGH, I2C_SPEED_MAX };
21
22 #define BSETS_ABORT_SOURCE_NO_ACK \
23 (SEDI_RBFVM(I2C, TX_ABRT_SOURCE, ABRT_7B_ADDR_NOACK, ACTIVE) | \
24 SEDI_RBFVM(I2C, TX_ABRT_SOURCE, ABRT_10ADDR1_NOACK, ACTIVE) | \
25 SEDI_RBFVM(I2C, TX_ABRT_SOURCE, ABRT_10ADDR2_NOACK, ACTIVE) | \
26 SEDI_RBFVM(I2C, TX_ABRT_SOURCE, ABRT_TXDATA_NOACK, ABRT_TXDATA_NOACK_GENERATED) | \
27 SEDI_RBFVM(I2C, TX_ABRT_SOURCE, ABRT_GCALL_NOACK, ABRT_GCALL_NOACK_GENERATED))
28
29 #define BSETS_DMA_ENABLE \
30 (SEDI_RBFVM(I2C, DMA_CR, RDMAE, ENABLED) | \
31 SEDI_RBFVM(I2C, DMA_CR, TDMAE, ENABLED))
32
33 #define BSETS_INTR_ERROR \
34 (SEDI_RBFVM(I2C, INTR_STAT, R_RX_UNDER, ACTIVE) | \
35 SEDI_RBFVM(I2C, INTR_STAT, R_RX_OVER, ACTIVE) | \
36 SEDI_RBFVM(I2C, INTR_STAT, R_TX_OVER, ACTIVE) | \
37 SEDI_RBFVM(I2C, INTR_STAT, R_TX_ABRT, ACTIVE))
38
39 #define BSETS_INTR_SEND \
40 (SEDI_RBFVM(I2C, INTR_STAT, R_TX_EMPTY, ACTIVE) | \
41 SEDI_RBFVM(I2C, INTR_STAT, R_STOP_DET, ACTIVE) | \
42 BSETS_INTR_ERROR)
43
44 #define BSETS_INTR_RECV \
45 (SEDI_RBFVM(I2C, INTR_STAT, R_TX_EMPTY, ACTIVE) | \
46 SEDI_RBFVM(I2C, INTR_STAT, R_RX_FULL, ACTIVE) | \
47 SEDI_RBFVM(I2C, INTR_STAT, R_STOP_DET, ACTIVE) | \
48 BSETS_INTR_ERROR)
49
50 #define BSETS_INTR_SLAVE \
51 (SEDI_RBFVM(I2C, INTR_STAT, R_RD_REQ, ACTIVE) | \
52 SEDI_RBFVM(I2C, INTR_STAT, R_RX_FULL, ACTIVE) | \
53 SEDI_RBFVM(I2C, INTR_STAT, R_STOP_DET, ACTIVE) | \
54 BSETS_INTR_ERROR | \
55 SEDI_RBFVM(I2C, INTR_STAT, R_START_DET, ACTIVE) | \
56 SEDI_RBFVM(I2C, INTR_STAT, R_RESTART_DET, ACTIVE))
57
58 #define BSETS_MASTER_DEFAULT \
59 (SEDI_RBFVM(I2C, CON, IC_SLAVE_DISABLE, SLAVE_DISABLED) | \
60 SEDI_RBFVM(I2C, CON, IC_RESTART_EN, ENABLED) | \
61 SEDI_RBFVM(I2C, CON, MASTER_MODE, ENABLED) | \
62 SEDI_RBFVM(I2C, CON, TX_EMPTY_CTRL, ENABLED))
63
64 typedef enum {
65 I2C_DMA_DIRECTION_TX = 0,
66 I2C_DMA_DIRECTION_RX = 1,
67 I2C_DMA_DIRECTION_RX_CMD = 2
68 } i2c_dma_diretion_t;
69
70 struct i2c_context {
71 uint32_t base;
72
73 sedi_i2c_capabilities_t capability;
74 sedi_i2c_status_t status;
75 sedi_i2c_event_cb_t cb_event;
76
77 uint8_t *buf;
78 uint32_t buf_size;
79 uint32_t buf_index;
80 uint32_t rx_cmd_index;
81
82 volatile uint8_t pending;
83
84 uint32_t isr_flag;
85 uint32_t isr_data;
86
87 int tx_dma_dev;
88 int tx_dma_chan;
89 int tx_dma_handshake;
90 int rx_dma_dev;
91 int rx_dma_chan;
92 int rx_dma_handshake;
93
94 dma_memory_type_t tx_memory_type;
95 dma_memory_type_t rx_memory_type;
96
97 int speed;
98 sedi_i2c_bus_clk_t *clk_info;
99 sedi_i2c_bus_info_t bus_info;
100 };
101
102 static uint32_t regval_speed[I2C_SPEED_MAX] = {
103 SEDI_RBFVM(I2C, CON, SPEED, STANDARD),
104 SEDI_RBFVM(I2C, CON, SPEED, FAST),
105 SEDI_RBFVM(I2C, CON, SPEED, FAST),
106 SEDI_RBFVM(I2C, CON, SPEED, HIGH)
107 };
108
109 /*
110 * For example, standard mode is 100KHz, 10000ns per period, 5000ns for
111 * SCL low & high level.
112 */
113 #define I2C_SS_SCL_HIGH 4000
114 #define I2C_SS_SCL_LOW 4700
115 #define I2C_FS_SCL_HIGH 600
116 #define I2C_FS_SCL_LOW 1300
117 #define I2C_FSP_SCL_HIGH 300
118 #define I2C_FSP_SCL_LOW 600
119 #ifndef I2C_SCL_400PF
120 #define I2C_HS_SCL_HIGH 70
121 #define I2C_HS_SCL_LOW 590
122 #else
123 #define I2C_HS_SCL_HIGH 160
124 #define I2C_HS_SCL_LOW 320
125 #endif
126
127 #define I2C_CONTEXT_INIT(x) \
128 { \
129 .base = SEDI_IREG_BASE(I2C, x), .speed = I2C_SPEED_FAST, \
130 .tx_dma_handshake = DMA_HWID_I2C##x##_TX, .rx_dma_handshake = DMA_HWID_I2C##x##_RX,\
131 .tx_memory_type = DMA_SRAM_MEM, .rx_memory_type = DMA_SRAM_MEM \
132 }
133 struct i2c_context contexts[SEDI_I2C_NUM] = { I2C_CONTEXT_INIT(0), I2C_CONTEXT_INIT(1),
134 I2C_CONTEXT_INIT(2) };
135
136 static void i2c_isr_complete(sedi_i2c_t i2c_device, bool is_error);
init_i2c_prescale(sedi_i2c_bus_info_t * bus_info)137 static void init_i2c_prescale(sedi_i2c_bus_info_t *bus_info)
138 {
139 if (bus_info->std_clk.hcnt == 0) {
140
141 bus_info->std_clk.sda_hold = LBW_CLK_MHZ * I2C_SDA_HOLD_DEFAULT / NS_PER_US;
142 bus_info->fst_clk.sda_hold = LBW_CLK_MHZ * I2C_SDA_HOLD_DEFAULT / NS_PER_US;
143 bus_info->fsp_clk.sda_hold = LBW_CLK_MHZ * I2C_SDA_HOLD_DEFAULT / NS_PER_US;
144 bus_info->high_clk.sda_hold = LBW_CLK_MHZ * I2C_SDA_HOLD_DEFAULT / NS_PER_US;
145
146 bus_info->std_clk.hcnt = LBW_CLK_MHZ * I2C_SS_SCL_HIGH / NS_PER_US;
147 bus_info->fst_clk.hcnt = LBW_CLK_MHZ * I2C_FS_SCL_HIGH / NS_PER_US;
148 bus_info->fsp_clk.hcnt = LBW_CLK_MHZ * I2C_FSP_SCL_HIGH / NS_PER_US;
149 bus_info->high_clk.hcnt = LBW_CLK_MHZ * I2C_HS_SCL_HIGH / NS_PER_US;
150
151 bus_info->std_clk.lcnt = LBW_CLK_MHZ * I2C_SS_SCL_LOW / NS_PER_US;
152 bus_info->fst_clk.lcnt = LBW_CLK_MHZ * I2C_FS_SCL_LOW / NS_PER_US;
153 bus_info->fsp_clk.lcnt = LBW_CLK_MHZ * I2C_FSP_SCL_LOW / NS_PER_US;
154 bus_info->high_clk.lcnt = LBW_CLK_MHZ * I2C_HS_SCL_LOW / NS_PER_US;
155 }
156 }
157
dw_i2c_enable(uint32_t base)158 static void dw_i2c_enable(uint32_t base)
159 {
160 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)base;
161
162 if (SEDI_PREG_RBFV_IS_SET(I2C, ENABLE_STATUS, IC_EN, ENABLED, &i2c->enable_status)) {
163 return;
164 }
165
166 /* prevent tx empty interrupt after enable */
167 i2c->intr_mask = 0;
168
169 i2c->enable = SEDI_RBFVM(I2C, ENABLE, ENABLE, ENABLED);
170 while (SEDI_PREG_RBFV_IS_SET(I2C, ENABLE_STATUS, IC_EN, DISABLED, &i2c->enable_status))
171 ;
172 }
173
dw_i2c_disable(uint32_t base)174 static int dw_i2c_disable(uint32_t base)
175 {
176 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)base;
177
178 /* If already disabled, return */
179 if (SEDI_PREG_RBFV_IS_SET(I2C, ENABLE, ENABLE, DISABLED, &i2c->enable)) {
180 return 0;
181 }
182
183 i2c->dma_cr = 0;
184 i2c->intr_mask = 0;
185
186 if (SEDI_PREG_RBFV_IS_SET(I2C, STATUS, MST_ACTIVITY, ACTIVE, &i2c->status)) {
187 SEDI_PREG_RBFV_SET(I2C, ENABLE, ABORT, ENABLED, &i2c->enable);
188 while (SEDI_PREG_RBFV_IS_SET(I2C, ENABLE, ABORT, ENABLED, &i2c->enable))
189 ;
190 }
191
192 while (SEDI_PREG_RBFV_IS_SET(I2C, STATUS, MST_ACTIVITY, ACTIVE, &i2c->status))
193 ;
194
195 i2c->enable = 0;
196 while (SEDI_PREG_RBFV_IS_SET(I2C, ENABLE_STATUS, IC_EN, ENABLED, &i2c->enable_status))
197 ;
198
199 return 0;
200 }
201
dw_i2c_config_addr(uint32_t base,uint16_t slave_addr)202 static int dw_i2c_config_addr(uint32_t base, uint16_t slave_addr)
203 {
204 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)base;
205
206 i2c->tar = SEDI_RBFM_VALUE(I2C, TAR, IC_TAR, slave_addr);
207 if (slave_addr & SEDI_I2C_ADDRESS_10BIT) {
208 SEDI_PREG_RBFV_SET(I2C, TAR, IC_10BITADDR_MASTER, ADDR_10BITS, &i2c->tar);
209 }
210
211 return 0;
212 }
213
dw_i2c_config_speed(uint32_t base,int speed,sedi_i2c_bus_clk_t * cfg)214 static int dw_i2c_config_speed(uint32_t base, int speed,
215 sedi_i2c_bus_clk_t *cfg)
216 {
217 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)base;
218
219 if (SEDI_PREG_RBFV_IS_SET(I2C, ENABLE_STATUS, IC_EN, ENABLED, &i2c->enable_status)) {
220 return -1;
221 }
222
223 i2c->con = BSETS_MASTER_DEFAULT | regval_speed[speed];
224
225 /* config sda_hold if needed */
226 if (cfg->sda_hold) {
227 i2c->sda_hold = cfg->sda_hold;
228 }
229
230 switch (speed) {
231 case I2C_SPEED_STANDARD:
232 i2c->ss_scl_hcnt = cfg->hcnt;
233 i2c->ss_scl_lcnt = cfg->lcnt;
234 break;
235 case I2C_SPEED_FAST:
236 case I2C_SPEED_FAST_PLUS:
237 i2c->fs_scl_hcnt = cfg->hcnt;
238 i2c->fs_scl_lcnt = cfg->lcnt;
239 break;
240 case I2C_SPEED_HIGH:
241 i2c->hs_scl_hcnt = cfg->hcnt;
242 i2c->hs_scl_lcnt = cfg->lcnt;
243 break;
244 default:
245 return SEDI_DRIVER_ERROR_UNSUPPORTED;
246 }
247
248 return 0;
249 }
250
dw_i2c_config_txfifo(uint32_t base,uint32_t watermark)251 static int dw_i2c_config_txfifo(uint32_t base, uint32_t watermark)
252 {
253 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)base;
254
255 SEDI_PREG_RBF_SET(I2C, TX_TL, TX_TL, watermark, &i2c->tx_tl);
256
257 return 0;
258 }
259
dw_i2c_config_rxfifo(uint32_t base,uint32_t watermark)260 static int dw_i2c_config_rxfifo(uint32_t base, uint32_t watermark)
261 {
262 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)base;
263
264 SEDI_PREG_RBF_SET(I2C, RX_TL, RX_TL, watermark - 1, &i2c->rx_tl);
265
266 return 0;
267 }
268
dw_i2c_poll_write(uint32_t base,const uint8_t * buffer,uint32_t length,bool pending)269 static int dw_i2c_poll_write(uint32_t base, const uint8_t *buffer, uint32_t length, bool pending)
270 {
271 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)base;
272
273 uint32_t cmd = SEDI_RBFVM(I2C, DATA_CMD, CMD, WRITE);
274
275 for (uint32_t i = 0; i < length; i++) {
276 if ((i == length - 1) && (!pending)) {
277 cmd |= SEDI_RBFVM(I2C, DATA_CMD, STOP, ENABLE);
278 }
279
280 i2c->data_cmd = buffer[i] | cmd;
281 /* Check abort and error */
282 do {
283 if (i2c->raw_intr_stat & BSETS_INTR_ERROR) {
284 return -1;
285 }
286
287 } while (SEDI_PREG_RBFV_IS_SET(I2C, STATUS, TFNF, FULL, &i2c->status));
288 }
289
290 /* Wait for end */
291 while (SEDI_PREG_RBFV_IS_SET(I2C, STATUS, ACTIVITY, ACTIVE, &i2c->status)) {
292 }
293
294 return 0;
295 }
296
dw_i2c_poll_read(uint32_t base,uint8_t * buffer,uint32_t length,bool pending)297 static int dw_i2c_poll_read(uint32_t base, uint8_t *buffer, uint32_t length, bool pending)
298 {
299 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)base;
300 uint32_t cmd = SEDI_RBFVM(I2C, DATA_CMD, CMD, READ);
301
302 for (uint32_t i = 0; i < length; i++) {
303 if ((i == length - 1) && (!pending)) {
304 cmd |= SEDI_RBFVM(I2C, DATA_CMD, STOP, ENABLE);
305 }
306
307 i2c->data_cmd = cmd;
308 do {
309 /* Check abort and error*/
310 if (i2c->raw_intr_stat & BSETS_INTR_ERROR) {
311 return -1;
312 }
313
314 } while (SEDI_PREG_RBFV_IS_SET(I2C, STATUS, RFNE, EMPTY, &i2c->status));
315
316 buffer[i] = (uint8_t)(i2c->data_cmd & 0xFF);
317 }
318
319 /* Wait for end */
320 while (SEDI_PREG_RBFV_IS_SET(I2C, STATUS, ACTIVITY, ACTIVE, &i2c->status)) {
321 }
322
323 return 0;
324 }
325
dw_i2c_irq_config(uint32_t base,uint32_t config)326 static inline void dw_i2c_irq_config(uint32_t base, uint32_t config)
327 {
328 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)base;
329
330 i2c->intr_mask = config;
331 }
332
dw_i2c_clear_interrupt(uint32_t base)333 static uint32_t dw_i2c_clear_interrupt(uint32_t base)
334 {
335 sedi_i2c_regs_t *i2c = (void *)base;
336 uint32_t value;
337 uint32_t stat;
338
339 stat = i2c->intr_stat;
340
341 value = i2c->clr_rx_under;
342 value = i2c->clr_rx_over;
343 value = i2c->clr_tx_over;
344 value = i2c->clr_tx_abrt;
345 value = i2c->clr_stop_det;
346 value = i2c->clr_intr;
347 PARAM_UNUSED(value);
348
349 return stat;
350 }
351
dw_i2c_dma_enable(uint32_t base,int fifo_depth)352 static void dw_i2c_dma_enable(uint32_t base, int fifo_depth)
353 {
354 sedi_i2c_regs_t *i2c = (void *)base;
355
356 i2c->dma_tdlr = SEDI_RBFM_VALUE(I2C, DMA_TDLR, DMATDL, fifo_depth);
357 i2c->dma_rdlr = SEDI_RBFM_VALUE(I2C, DMA_RDLR, DMARDL, fifo_depth - 1);
358
359 i2c->dma_cr = BSETS_DMA_ENABLE;
360 }
361
362 /* force enter IDLE mode */
dw_i2c_abort(struct i2c_context * context)363 static void dw_i2c_abort(struct i2c_context *context)
364 {
365 sedi_i2c_regs_t *i2c = (void *)context->base;
366 uint32_t value;
367
368 if (SEDI_PREG_RBFV_IS_SET(I2C, ENABLE, ENABLE, DISABLED, &i2c->enable)) {
369 return;
370 }
371
372 i2c->dma_cr = 0;
373 i2c->intr_mask = 0;
374
375 SEDI_PREG_RBFV_SET(I2C, ENABLE, ABORT, ENABLED, &i2c->enable);
376
377 /* Waiting for abort operation finished, HW can clear */
378 while (SEDI_PREG_RBFV_IS_SET(I2C, RAW_INTR_STAT, TX_ABRT, INACTIVE, &i2c->raw_intr_stat)) {
379 ;
380 }
381
382 while (SEDI_PREG_RBFV_GET(I2C, RXFLR, RXFLR, &i2c->rxflr) != 0) {
383 value = i2c->data_cmd;
384 }
385
386 dw_i2c_irq_config(context->base, 0);
387
388 dw_i2c_config_txfifo(context->base, 0);
389 dw_i2c_config_rxfifo(context->base, 0);
390
391 /* Clear the abort state */
392 dw_i2c_clear_interrupt(context->base);
393 PARAM_UNUSED(value);
394 }
395
dw_i2c_dr_address(uint32_t base)396 static uint32_t dw_i2c_dr_address(uint32_t base)
397 {
398 sedi_i2c_regs_t *i2c = (void *)base;
399
400 return (uint32_t)&i2c->data_cmd;
401 }
402
dw_i2c_abort_analysis(uint32_t base)403 static uint32_t dw_i2c_abort_analysis(uint32_t base)
404 {
405 sedi_i2c_regs_t *i2c = (void *)base;
406 uint32_t abort_src, event = SEDI_I2C_EVENT_TRANSFER_INCOMPLETE;
407
408 abort_src = i2c->tx_abrt_source;
409
410 if (abort_src & BSETS_ABORT_SOURCE_NO_ACK) {
411 event |= SEDI_I2C_EVENT_ADDRESS_NACK;
412 }
413
414 if (SEDI_PREG_RBFV_IS_SET(I2C, TX_ABRT_SOURCE, ARB_LOST, ABRT_LOST_GENERATED, &abort_src)) {
415 event |= SEDI_I2C_EVENT_ARBITRATION_LOST;
416 }
417
418 return event;
419 }
420
421 /* Used for sending cmd for I2C read operation */
i2c_ask_data(sedi_i2c_t i2c_device)422 static void i2c_ask_data(sedi_i2c_t i2c_device)
423 {
424 struct i2c_context *context = &contexts[i2c_device];
425 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)(context->base);
426
427 uint32_t tx_fifo_space = 0, rx_fifo_space = 0;
428 uint32_t rx_pending = context->rx_cmd_index - context->buf_index;
429 uint32_t size = context->buf_size - context->rx_cmd_index;
430 uint32_t fifo_size = 0;
431 uint32_t data = SEDI_RBFVM(I2C, DATA_CMD, CMD, READ);
432 bool last_data = false;
433
434 /* No need to send anymore */
435 if (context->rx_cmd_index == context->buf_size) {
436 return;
437 }
438
439 /* Decide how many space there are */
440 if ((I2C_FIFO_DEPTH - SEDI_PREG_RBFV_GET(I2C, TXFLR, TXFLR, &i2c->txflr)) <= rx_pending) {
441 return;
442 }
443
444 tx_fifo_space = I2C_FIFO_DEPTH - SEDI_PREG_RBFV_GET(I2C, TXFLR, TXFLR, &i2c->txflr) -
445 rx_pending;
446
447 /* To prevent RX FIFO overflow, need to make sure command number less
448 * than the space in RX FIFO.
449 */
450 rx_fifo_space = I2C_FIFO_DEPTH - SEDI_PREG_RBFV_GET(I2C, RXFLR, RXFLR, &i2c->rxflr);
451
452 if (tx_fifo_space < rx_fifo_space) {
453 fifo_size = tx_fifo_space;
454 } else {
455 fifo_size = rx_fifo_space;
456 }
457
458 if (size <= fifo_size) {
459 last_data = true;
460 } else {
461 size = fifo_size;
462 }
463
464 while (size > 0) {
465 /* If it is first data, need RESTART */
466 if (context->rx_cmd_index == 0) {
467 data |= SEDI_RBFVM(I2C, DATA_CMD, RESTART, ENABLE);
468 }
469
470 /* Last data need STOP flag */
471 if ((size == 1) && last_data && (!(context->pending))) {
472 data |= SEDI_RBFVM(I2C, DATA_CMD, STOP, ENABLE);
473 /* Disable tx empty interrupt */
474 i2c->intr_mask &= ~SEDI_RBFVM(I2C, INTR_MASK, M_TX_EMPTY, DISABLED);
475 }
476
477 i2c->data_cmd = data;
478 context->rx_cmd_index++;
479 size--;
480
481 /* Reset data */
482 data = SEDI_RBFVM(I2C, DATA_CMD, CMD, READ);
483 }
484 }
485
i2c_send(sedi_i2c_t i2c_device)486 static void i2c_send(sedi_i2c_t i2c_device)
487 {
488 struct i2c_context *context = &contexts[i2c_device];
489 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)(context->base);
490
491 uint32_t tx_fifo_space = 0;
492 uint32_t size = context->buf_size - context->buf_index;
493 uint32_t data = 0;
494 uint8_t *buf = context->buf;
495 bool last_data = false;
496
497 if (context->buf_index == context->buf_size) {
498 return;
499 }
500
501 /* Decide how many space there are */
502 tx_fifo_space = I2C_FIFO_DEPTH - SEDI_PREG_RBFV_GET(I2C, TXFLR, TXFLR, &i2c->txflr);
503
504 if (size <= tx_fifo_space) {
505 last_data = true;
506 } else {
507 size = tx_fifo_space;
508 }
509
510 /* Not last data */
511 while (size > 1) {
512 data = buf[context->buf_index];
513 i2c->data_cmd = data;
514 size--;
515 context->buf_index++;
516 }
517
518 /* Last data transfer */
519 data = buf[context->buf_index];
520
521 /* If it is the last data for whole transfer */
522 if (last_data) {
523 /* NO need to send STOP, but need to change watermark
524 * to 0, this will have a interrupt while all data sent out
525 */
526 if (context->pending) {
527 SEDI_PREG_RBF_SET(I2C, TX_TL, TX_TL, 0, &i2c->tx_tl);
528 } else {
529 SEDI_PREG_RBFV_SET(I2C, DATA_CMD, STOP, ENABLE, &data);
530 /* Disable tx empty interrupt */
531 i2c->intr_mask &= ~SEDI_RBFVM(I2C, INTR_MASK, M_TX_EMPTY, DISABLED);
532 }
533 }
534
535 i2c->data_cmd = data;
536 context->buf_index++;
537 }
538
539 /******************************************************************************
540 * SEDI interface
541 *****************************************************************************/
542
543 #define SEDI_I2C_DRV_VERSION SEDI_DRIVER_VERSION_MAJOR_MINOR(1, 0)
544 #define SEDI_I2C_DMA_CHANNEL_UNUSED (-1)
545
546 static const sedi_driver_version_t driver_version = { SEDI_I2C_API_VERSION, SEDI_I2C_DRV_VERSION };
547
548 static sedi_i2c_capabilities_t driver_capabilities[SEDI_I2C_NUM] = { 0 };
549 /* Used for I2C DMA Rx */
550 static uint8_t dma_cmd __attribute__((aligned(32))) = 1;
551
sedi_i2c_get_version(void)552 sedi_driver_version_t sedi_i2c_get_version(void)
553 {
554 return driver_version;
555 }
556
sedi_i2c_get_capabilities(IN sedi_i2c_t i2c_device,sedi_i2c_capabilities_t * cap)557 int sedi_i2c_get_capabilities(IN sedi_i2c_t i2c_device, sedi_i2c_capabilities_t *cap)
558 {
559 struct i2c_context *context = &contexts[i2c_device];
560 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)(context->base);
561
562 DBG_CHECK(i2c_device < SEDI_I2C_NUM, SEDI_DRIVER_ERROR_PARAMETER);
563
564 if (sedi_dev_is_self_owned(SEDI_DEVID_I2C0 + i2c_device)) {
565 driver_capabilities[i2c_device].is_available = 1;
566 } else {
567 driver_capabilities[i2c_device].is_available = 0;
568 }
569
570 driver_capabilities[i2c_device].rx_buffer_depth =
571 SEDI_PREG_RBFV_GET(I2C, COMP_PARAM_1, RX_BUFFER_DEPTH, &i2c->comp_param_1) + 1;
572 driver_capabilities[i2c_device].tx_buffer_depth =
573 SEDI_PREG_RBFV_GET(I2C, COMP_PARAM_1, TX_BUFFER_DEPTH, &i2c->comp_param_1) + 1;
574 driver_capabilities[i2c_device].dma =
575 SEDI_PREG_RBFV_GET(I2C, COMP_PARAM_1, HAS_DMA, &i2c->comp_param_1);
576
577 *cap = driver_capabilities[i2c_device];
578
579 return SEDI_DRIVER_OK;
580 }
581
sedi_i2c_init(IN sedi_i2c_t i2c_device,IN sedi_i2c_event_cb_t cb_event,IN uint32_t base)582 int32_t sedi_i2c_init(IN sedi_i2c_t i2c_device,
583 IN sedi_i2c_event_cb_t cb_event, IN uint32_t base)
584 {
585 DBG_CHECK(i2c_device < SEDI_I2C_NUM, SEDI_DRIVER_ERROR_PARAMETER);
586
587 struct i2c_context *context = &contexts[i2c_device];
588
589 if (!sedi_dev_is_self_owned(SEDI_DEVID_I2C0 + i2c_device)) {
590 return SEDI_DRIVER_ERROR_NO_DEV;
591 }
592
593 context->cb_event = cb_event;
594 context->tx_dma_chan = SEDI_I2C_DMA_CHANNEL_UNUSED;
595 context->rx_dma_chan = SEDI_I2C_DMA_CHANNEL_UNUSED;
596
597 init_i2c_prescale(&(context->bus_info));
598
599 context->base = base;
600
601 /* i2c default configuration */
602 context->speed = I2C_SPEED_STANDARD;
603 context->clk_info = &(context->bus_info.std_clk);
604 dw_i2c_config_speed(context->base, context->speed, context->clk_info);
605
606 return SEDI_DRIVER_OK;
607 }
608
sedi_i2c_uninit(IN sedi_i2c_t i2c_device)609 int32_t sedi_i2c_uninit(IN sedi_i2c_t i2c_device)
610 {
611 DBG_CHECK(i2c_device < SEDI_I2C_NUM, SEDI_DRIVER_ERROR_PARAMETER);
612
613 struct i2c_context *context = &contexts[i2c_device];
614
615 context->cb_event = NULL;
616
617 return SEDI_DRIVER_OK;
618 }
619
sedi_i2c_set_power(IN sedi_i2c_t i2c_device,IN sedi_power_state_t state)620 int32_t sedi_i2c_set_power(IN sedi_i2c_t i2c_device, IN sedi_power_state_t state)
621 {
622 DBG_CHECK(i2c_device < SEDI_I2C_NUM, SEDI_DRIVER_ERROR_PARAMETER);
623
624 struct i2c_context *context = &contexts[i2c_device];
625 sedi_devid_t id = SEDI_DEVID_I2C0 + i2c_device;
626 int32_t ret = SEDI_DRIVER_OK;
627
628 switch (state) {
629 case SEDI_POWER_FULL:
630 sedi_pm_set_device_power(id, state);
631 dw_i2c_clear_interrupt(context->base);
632 dw_i2c_irq_config(context->base, 0);
633 dw_i2c_disable(context->base);
634 dw_i2c_config_speed(context->base, context->speed,
635 context->clk_info);
636 break;
637 case SEDI_POWER_SUSPEND:
638 case SEDI_POWER_FORCE_SUSPEND:
639 case SEDI_POWER_LOW:
640 dw_i2c_irq_config(context->base, 0);
641 sedi_pm_set_device_power(id, state);
642 break;
643 case SEDI_POWER_OFF:
644 default:
645 ret = SEDI_DRIVER_ERROR_UNSUPPORTED;
646 break;
647 }
648
649 return ret;
650 }
651
callback_tx_dma_transfer(const sedi_dma_t dma,const int chan,const int event,void * param)652 static void callback_tx_dma_transfer(const sedi_dma_t dma, const int chan, const int event,
653 void *param)
654 {
655 struct i2c_context *context = &contexts[(int)param];
656 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)(context->base);
657 uint32_t i2c_event = SEDI_I2C_EVENT_TRANSFER_INCOMPLETE | SEDI_I2C_EVENT_DMA_ERROR;
658
659 PARAM_UNUSED(dma);
660 PARAM_UNUSED(chan);
661
662 /* DMA error, go to end */
663 if (event != SEDI_DMA_EVENT_TRANSFER_DONE) {
664 context->status.event = i2c_event;
665 i2c_isr_complete((sedi_i2c_t)param, true);
666 return;
667 }
668
669 SEDI_PREG_RBFV_SET(I2C, DMA_CR, TDMAE, DISABLED, &i2c->dma_cr);
670 context->buf_index = context->buf_size;
671 context->tx_dma_chan = SEDI_I2C_DMA_CHANNEL_UNUSED;
672
673 if (context->pending) {
674 /* If no STOP, all data sent by DMA, enable TX_EMPTY interrupt
675 * to get stop condition.
676 */
677 SEDI_PREG_RBF_SET(I2C, TX_TL, TX_TL, 0, &i2c->tx_tl);
678 SEDI_PREG_RBFV_SET(I2C, INTR_MASK, M_TX_EMPTY, DISABLED, &i2c->intr_mask);
679 } else {
680 /* WA for I2C DMA transfer, wait until FIFO not full*/
681 /* If need STOP, last data sent by interrupt */
682 while (SEDI_PREG_RBFV_GET(I2C, TXFLR, TXFLR, &i2c->txflr) == I2C_FIFO_DEPTH) {
683 }
684 i2c->data_cmd = context->buf[context->buf_size - 1] |
685 SEDI_RBFVM(I2C, DATA_CMD, STOP, ENABLE);
686 }
687 }
688
callback_rx_dma_transfer(const sedi_dma_t dma,const int chan,const int event,void * param)689 static void callback_rx_dma_transfer(const sedi_dma_t dma, const int chan, const int event,
690 void *param)
691 {
692 struct i2c_context *context = &contexts[(int)param];
693 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)(context->base);
694 uint32_t i2c_event = SEDI_I2C_EVENT_TRANSFER_INCOMPLETE | SEDI_I2C_EVENT_DMA_ERROR;
695
696 PARAM_UNUSED(dma);
697 PARAM_UNUSED(chan);
698
699 /* DMA error, go to end */
700 if (event != SEDI_DMA_EVENT_TRANSFER_DONE) {
701 context->status.event = i2c_event;
702 i2c_isr_complete((sedi_i2c_t)param, true);
703 return;
704 }
705
706 /* Disable the Rx dma request */
707 SEDI_PREG_RBFV_SET(I2C, DMA_CR, RDMAE, DISABLED, &i2c->dma_cr);
708 context->buf_index = context->buf_size;
709 context->rx_dma_chan = SEDI_I2C_DMA_CHANNEL_UNUSED;
710 }
711
callback_rx_cmd_dma_transfer(const sedi_dma_t dma,const int chan,const int event,void * param)712 static void callback_rx_cmd_dma_transfer(const sedi_dma_t dma, const int chan, const int event,
713 void *param)
714 {
715 struct i2c_context *context = &contexts[(int)param];
716 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)(context->base);
717 uint32_t i2c_event = SEDI_I2C_EVENT_TRANSFER_INCOMPLETE | SEDI_I2C_EVENT_DMA_ERROR;
718
719 PARAM_UNUSED(dma);
720 PARAM_UNUSED(chan);
721
722 /* DMA error, go to end */
723 if (event != SEDI_DMA_EVENT_TRANSFER_DONE) {
724 context->status.event = i2c_event;
725 i2c_isr_complete((sedi_i2c_t)param, true);
726 return;
727 }
728
729 context->tx_dma_chan = SEDI_I2C_DMA_CHANNEL_UNUSED;
730
731 /* Send the last command, which is different from previous one*/
732 while (SEDI_PREG_RBFV_GET(I2C, TXFLR, TXFLR, &i2c->txflr) == I2C_FIFO_DEPTH) {
733 }
734 if (context->pending) {
735 i2c->data_cmd = SEDI_RBFVM(I2C, DATA_CMD, CMD, READ);
736 } else {
737 i2c->data_cmd = SEDI_RBFVM(I2C, DATA_CMD, CMD, READ) | SEDI_RBFVM(I2C, DATA_CMD,
738 STOP, ENABLE);
739 }
740 }
741
config_and_enable_dma_channel(sedi_i2c_t i2c_dev,int dma,int handshake,int chan,uint32_t src,uint32_t dst,uint32_t len,i2c_dma_diretion_t dir)742 static int config_and_enable_dma_channel(sedi_i2c_t i2c_dev, int dma, int handshake, int chan,
743 uint32_t src, uint32_t dst, uint32_t len,
744 i2c_dma_diretion_t dir)
745 {
746 int ret;
747 int dma_dir;
748 int dma_per_dir;
749
750 if (dir == I2C_DMA_DIRECTION_TX) {
751 dma_dir = DMA_MEMORY_TO_PERIPHERAL;
752 dma_per_dir = DMA_HS_PER_TX;
753 ret = sedi_dma_init(dma, chan, callback_tx_dma_transfer, (void *)i2c_dev);
754 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
755 } else if (dir == I2C_DMA_DIRECTION_RX) {
756 dma_dir = DMA_PERIPHERAL_TO_MEMORY;
757 dma_per_dir = DMA_HS_PER_RX;
758 ret = sedi_dma_init(dma, chan, callback_rx_dma_transfer, (void *)i2c_dev);
759 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
760 } else {
761 dma_dir = DMA_PERIPHERAL_TO_PERIPHERAL;
762 dma_per_dir = DMA_HS_PER_TX;
763 ret = sedi_dma_init(dma, chan, callback_rx_cmd_dma_transfer, (void *)i2c_dev);
764 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
765 }
766
767 ret = sedi_dma_set_power(dma, chan, SEDI_POWER_FULL);
768 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
769
770 ret = sedi_dma_control(dma, chan, SEDI_CONFIG_DMA_BURST_LENGTH, DMA_BURST_TRANS_LENGTH_1);
771 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
772
773 ret = sedi_dma_control(dma, chan, SEDI_CONFIG_DMA_SR_TRANS_WIDTH, DMA_TRANS_WIDTH_8);
774 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
775
776 ret = sedi_dma_control(dma, chan, SEDI_CONFIG_DMA_DT_TRANS_WIDTH, DMA_TRANS_WIDTH_8);
777 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
778
779 ret = sedi_dma_control(dma, chan, SEDI_CONFIG_DMA_HS_DEVICE_ID, handshake);
780 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
781
782 ret = sedi_dma_control(dma, chan, SEDI_CONFIG_DMA_HS_POLARITY, DMA_HS_POLARITY_HIGH);
783 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
784
785 ret = sedi_dma_control(dma, chan, SEDI_CONFIG_DMA_DIRECTION, dma_dir);
786 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
787
788 ret = sedi_dma_control(dma, chan, SEDI_CONFIG_DMA_HS_DEVICE_ID_PER_DIR, dma_per_dir);
789 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
790
791 ret = sedi_dma_start_transfer(dma, chan, src, dst, len);
792 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
793
794 return ret;
795 }
796
sedi_i2c_master_write_dma(IN sedi_i2c_t i2c_device,IN uint32_t addr,IN uint8_t * data,IN uint32_t num,IN bool pending,IN uint32_t dma_dev,IN uint32_t dma_chan)797 int32_t sedi_i2c_master_write_dma(IN sedi_i2c_t i2c_device, IN uint32_t addr, IN uint8_t *data,
798 IN uint32_t num, IN bool pending, IN uint32_t dma_dev, IN uint32_t dma_chan)
799 {
800 DBG_CHECK(i2c_device < SEDI_I2C_NUM, SEDI_DRIVER_ERROR_PARAMETER);
801 DBG_CHECK(0 != (addr & SEDI_RBFM(I2C, TAR, IC_TAR)), SEDI_DRIVER_ERROR_PARAMETER);
802 DBG_CHECK(NULL != data, SEDI_DRIVER_ERROR_PARAMETER);
803
804 struct i2c_context *context = &contexts[i2c_device];
805
806 /* dma max block ts 4095, need slicing if exceed, tbd */
807 if (num <= SEDI_I2C_DMA_LENGTH_LIMIT || num > I2C_MAX_BLOCK_TS) {
808 return SEDI_DRIVER_ERROR_PARAMETER;
809 }
810
811 if (context->status.busy) {
812 return SEDI_DRIVER_ERROR_BUSY;
813 }
814
815 dw_i2c_clear_interrupt(context->base);
816 dw_i2c_config_addr(context->base, addr);
817 dw_i2c_enable(context->base);
818
819 context->status.busy = 1U;
820 context->status.direction = 0U;
821 context->status.event = SEDI_I2C_EVENT_TRANSFER_NONE;
822 context->pending = pending;
823 context->buf = (void *)data;
824 context->buf_size = num;
825 context->buf_index = 0;
826 context->tx_dma_dev = dma_dev;
827 context->tx_dma_chan = dma_chan;
828
829 dw_i2c_irq_config(context->base,
830 BSETS_INTR_ERROR | SEDI_RBFVM(I2C, INTR_MASK, M_STOP_DET, DISABLED));
831
832 dw_i2c_dma_enable(context->base, 1);
833
834 config_and_enable_dma_channel(i2c_device, context->tx_dma_dev, context->tx_dma_handshake,
835 context->tx_dma_chan, (uint32_t)data, dw_i2c_dr_address(context->base),
836 pending ? num : num - 1, I2C_DMA_DIRECTION_TX);
837
838 return SEDI_DRIVER_OK;
839 }
840
sedi_i2c_master_read_dma(IN sedi_i2c_t i2c_device,IN uint32_t addr,OUT uint8_t * data,IN uint32_t num,IN bool pending,IN uint32_t rx_dma_dev,IN uint32_t rx_dma_chan,IN uint32_t cmd_dma_dev,IN uint32_t cmd_dma_chan)841 int32_t sedi_i2c_master_read_dma(IN sedi_i2c_t i2c_device, IN uint32_t addr, OUT uint8_t *data,
842 IN uint32_t num, IN bool pending, IN uint32_t rx_dma_dev, IN uint32_t rx_dma_chan,
843 IN uint32_t cmd_dma_dev, IN uint32_t cmd_dma_chan)
844 {
845 DBG_CHECK(i2c_device < SEDI_I2C_NUM, SEDI_DRIVER_ERROR_PARAMETER);
846 DBG_CHECK(0 != (addr & SEDI_RBFM(I2C, TAR, IC_TAR)), SEDI_DRIVER_ERROR_PARAMETER);
847 DBG_CHECK(NULL != data, SEDI_DRIVER_ERROR_PARAMETER);
848
849 struct i2c_context *context = &contexts[i2c_device];
850 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)(context->base);
851
852 /* dma max block ts 4095, need slicing if exceed, tbd */
853 if (num <= SEDI_I2C_DMA_LENGTH_LIMIT || num > I2C_MAX_BLOCK_TS) {
854 return SEDI_DRIVER_ERROR_PARAMETER;
855 }
856
857 if (context->status.busy) {
858 return SEDI_DRIVER_ERROR_BUSY;
859 }
860
861 dw_i2c_clear_interrupt(context->base);
862 dw_i2c_config_addr(context->base, addr);
863 dw_i2c_enable(context->base);
864
865 context->status.busy = 1U;
866 context->status.direction = 1U;
867 context->status.event = SEDI_I2C_EVENT_TRANSFER_NONE;
868 context->pending = pending;
869 context->buf = data;
870 context->buf_size = num;
871 context->buf_index = 0;
872 context->rx_dma_dev = rx_dma_dev;
873 context->rx_dma_chan = rx_dma_chan;
874 context->tx_dma_dev = cmd_dma_dev;
875 context->tx_dma_chan = cmd_dma_chan;
876
877 dw_i2c_irq_config(context->base,
878 BSETS_INTR_ERROR | SEDI_RBFVM(I2C, INTR_MASK, M_STOP_DET, DISABLED));
879
880 /* First write the command into register and clean cache */
881 i2c->data_cmd = SEDI_RBFVM(I2C, DATA_CMD, CMD, READ) |
882 SEDI_RBFVM(I2C, DATA_CMD, RESTART, ENABLE);
883 sedi_core_clean_dcache_by_addr((uint32_t *)(&dma_cmd), sizeof(dma_cmd));
884
885 dw_i2c_dma_enable(context->base, 1);
886
887 /* Command is written for next read per request */
888 config_and_enable_dma_channel(i2c_device, context->tx_dma_dev, context->tx_dma_handshake,
889 context->tx_dma_chan, (uint32_t)&dma_cmd, dw_i2c_dr_address(context->base) + 1,
890 num - 2, I2C_DMA_DIRECTION_RX_CMD);
891
892 /* data transfer */
893 config_and_enable_dma_channel(i2c_device, context->rx_dma_dev, context->rx_dma_handshake,
894 context->rx_dma_chan, dw_i2c_dr_address(context->base), (uint32_t)data, num,
895 I2C_DMA_DIRECTION_RX);
896
897 return SEDI_DRIVER_OK;
898 }
899
sedi_i2c_master_write_async(IN sedi_i2c_t i2c_device,IN uint32_t addr,IN uint8_t * data,IN uint32_t num,IN bool pending)900 int32_t sedi_i2c_master_write_async(IN sedi_i2c_t i2c_device, IN uint32_t addr, IN uint8_t *data,
901 IN uint32_t num, IN bool pending)
902 {
903 uint32_t irq = BSETS_INTR_SEND;
904
905 DBG_CHECK(i2c_device < SEDI_I2C_NUM, SEDI_DRIVER_ERROR_PARAMETER);
906 DBG_CHECK(0 != (addr & SEDI_RBFM(I2C, TAR, IC_TAR)), SEDI_DRIVER_ERROR_PARAMETER);
907 DBG_CHECK(NULL != data, SEDI_DRIVER_ERROR_PARAMETER);
908 DBG_CHECK(0 != num, SEDI_DRIVER_ERROR_PARAMETER);
909
910 struct i2c_context *context = &contexts[i2c_device];
911
912 if (context->status.busy) {
913 return SEDI_DRIVER_ERROR_BUSY;
914 }
915
916 /* Clear all status first */
917 dw_i2c_clear_interrupt(context->base);
918 dw_i2c_config_addr(context->base, addr);
919
920 /* Set watermark */
921 if (num < I2C_FIFO_DEFAULT_WATERMARK) {
922 /* If less than half FIFO, just set watermark to transfer size
923 */
924 dw_i2c_config_txfifo(context->base, num);
925 } else {
926 dw_i2c_config_txfifo(context->base, I2C_FIFO_DEFAULT_WATERMARK);
927 }
928
929 /* Enable I2C */
930 dw_i2c_enable(context->base);
931
932 /* Set internal state */
933 context->status.busy = 1U;
934 context->status.direction = 0U;
935 /* Reset event to default */
936 context->status.event = SEDI_I2C_EVENT_TRANSFER_NONE;
937
938 context->buf = (uint8_t *)data;
939 context->buf_size = num;
940 context->rx_cmd_index = 0;
941 context->buf_index = 0;
942 context->pending = pending;
943
944 /* FIFO fill */
945 i2c_send(i2c_device);
946 if (context->buf_index == num && !pending)
947 irq &= ~SEDI_RBFVM(I2C, INTR_MASK, M_TX_EMPTY, DISABLED);
948
949 dw_i2c_irq_config(context->base, irq);
950
951 return SEDI_DRIVER_OK;
952 }
953
sedi_i2c_master_read_async(IN sedi_i2c_t i2c_device,IN uint32_t addr,OUT uint8_t * data,IN uint32_t num,IN bool pending)954 int32_t sedi_i2c_master_read_async(IN sedi_i2c_t i2c_device, IN uint32_t addr, OUT uint8_t *data,
955 IN uint32_t num, IN bool pending)
956 {
957 uint32_t irq = BSETS_INTR_RECV;
958
959 DBG_CHECK(i2c_device < SEDI_I2C_NUM, SEDI_DRIVER_ERROR_PARAMETER);
960 DBG_CHECK(0 != (addr & SEDI_RBFM(I2C, TAR, IC_TAR)), SEDI_DRIVER_ERROR_PARAMETER);
961 DBG_CHECK(NULL != data, SEDI_DRIVER_ERROR_PARAMETER);
962 DBG_CHECK(0 != num, SEDI_DRIVER_ERROR_PARAMETER);
963
964 struct i2c_context *context = &contexts[i2c_device];
965
966 if (context->status.busy) {
967 return SEDI_DRIVER_ERROR_BUSY;
968 }
969
970 /* Clear all status first */
971 dw_i2c_clear_interrupt(context->base);
972 dw_i2c_config_addr(context->base, addr);
973
974 /* Set watermark, receive needs both tx and rx */
975 if (num < I2C_FIFO_DEFAULT_WATERMARK) {
976 /* If less than half FIFO, just set watermark to transfer size
977 */
978 dw_i2c_config_rxfifo(context->base, num);
979 dw_i2c_config_txfifo(context->base, 0);
980 } else {
981 dw_i2c_config_rxfifo(context->base, I2C_FIFO_DEFAULT_WATERMARK);
982 dw_i2c_config_txfifo(context->base, I2C_FIFO_DEFAULT_WATERMARK);
983 }
984
985 /* Enable I2C */
986 dw_i2c_enable(context->base);
987
988 context->status.busy = 1U;
989 context->status.direction = 1U;
990 /* Reset event to default */
991 context->status.event = SEDI_I2C_EVENT_TRANSFER_NONE;
992
993 context->buf = (uint8_t *)data;
994 context->buf_size = num;
995 context->buf_index = 0;
996 context->rx_cmd_index = 0;
997 context->pending = pending;
998
999 /* FIFO fill */
1000 i2c_ask_data(i2c_device);
1001 if (context->rx_cmd_index == num && !pending)
1002 irq &= ~SEDI_RBFVM(I2C, INTR_MASK, M_TX_EMPTY, DISABLED);
1003
1004 dw_i2c_irq_config(context->base, irq);
1005
1006 return SEDI_DRIVER_OK;
1007 }
1008
sedi_i2c_master_poll_write(IN sedi_i2c_t i2c_device,IN uint32_t addr,IN uint8_t * data,IN uint32_t num,IN bool pending)1009 int32_t sedi_i2c_master_poll_write(IN sedi_i2c_t i2c_device, IN uint32_t addr, IN uint8_t *data,
1010 IN uint32_t num, IN bool pending)
1011 {
1012 DBG_CHECK(i2c_device < SEDI_I2C_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1013 DBG_CHECK(0 != (addr & SEDI_RBFM(I2C, TAR, IC_TAR)), SEDI_DRIVER_ERROR_PARAMETER);
1014 DBG_CHECK(NULL != data, SEDI_DRIVER_ERROR_PARAMETER);
1015 DBG_CHECK(0 != num, SEDI_DRIVER_ERROR_PARAMETER);
1016
1017 int ret;
1018 struct i2c_context *context = &contexts[i2c_device];
1019
1020 if (context->status.busy) {
1021 return SEDI_DRIVER_ERROR_BUSY;
1022 }
1023
1024 /* Clear all status first */
1025 dw_i2c_clear_interrupt(context->base);
1026 dw_i2c_config_addr(context->base, addr);
1027
1028 context->status.busy = 1U;
1029 context->status.direction = 0U;
1030 /* Reset event to default */
1031 context->status.event = SEDI_I2C_EVENT_TRANSFER_NONE;
1032
1033 dw_i2c_enable(context->base);
1034
1035 ret = dw_i2c_poll_write(context->base, data, num, pending);
1036
1037 if (ret != 0) {
1038 context->status.event = dw_i2c_abort_analysis(context->base);
1039 dw_i2c_clear_interrupt(context->base);
1040 dw_i2c_disable(context->base);
1041 } else {
1042 context->status.event = SEDI_I2C_EVENT_TRANSFER_DONE;
1043 }
1044 context->status.busy = 0U;
1045 context->buf_index = num;
1046
1047 return (ret == 0) ? SEDI_DRIVER_OK : SEDI_DRIVER_ERROR;
1048 }
1049
sedi_i2c_master_poll_read(IN sedi_i2c_t i2c_device,IN uint32_t addr,OUT uint8_t * data,IN uint32_t num,IN bool pending)1050 int32_t sedi_i2c_master_poll_read(IN sedi_i2c_t i2c_device, IN uint32_t addr, OUT uint8_t *data,
1051 IN uint32_t num, IN bool pending)
1052 {
1053 DBG_CHECK(i2c_device < SEDI_I2C_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1054 DBG_CHECK(0 != (addr & SEDI_RBFM(I2C, TAR, IC_TAR)), SEDI_DRIVER_ERROR_PARAMETER);
1055 DBG_CHECK(NULL != data, SEDI_DRIVER_ERROR_PARAMETER);
1056 DBG_CHECK(0 != num, SEDI_DRIVER_ERROR_PARAMETER);
1057
1058 int ret;
1059 struct i2c_context *context = &contexts[i2c_device];
1060
1061 if (context->status.busy) {
1062 return SEDI_DRIVER_ERROR_BUSY;
1063 }
1064
1065 /* Clear all status first */
1066 dw_i2c_clear_interrupt(context->base);
1067 dw_i2c_config_addr(context->base, addr);
1068
1069 /* Enable I2C */
1070 dw_i2c_enable(context->base);
1071
1072 context->status.busy = 1U;
1073 context->status.direction = 1U;
1074 /* Reset event to default */
1075 context->status.event = SEDI_I2C_EVENT_TRANSFER_DONE;
1076
1077 ret = dw_i2c_poll_read(context->base, data, num, pending);
1078
1079 if (ret != 0) {
1080 context->status.event = dw_i2c_abort_analysis(context->base);
1081 dw_i2c_clear_interrupt(context->base);
1082 dw_i2c_disable(context->base);
1083 }
1084 context->status.busy = 0U;
1085 context->buf_index = num;
1086
1087 return (ret == 0) ? SEDI_DRIVER_OK : SEDI_DRIVER_ERROR;
1088 }
1089
sedi_i2c_get_data_count(IN sedi_i2c_t i2c_device)1090 int32_t sedi_i2c_get_data_count(IN sedi_i2c_t i2c_device)
1091 {
1092 DBG_CHECK(i2c_device < SEDI_I2C_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1093
1094 struct i2c_context *context = &contexts[i2c_device];
1095
1096 return context->buf_index;
1097 }
1098
sedi_i2c_control(IN sedi_i2c_t i2c_device,IN uint32_t control,IN uint32_t arg)1099 int32_t sedi_i2c_control(IN sedi_i2c_t i2c_device, IN uint32_t control, IN uint32_t arg)
1100 {
1101 DBG_CHECK(i2c_device < SEDI_I2C_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1102
1103 int ret = 0;
1104 struct i2c_context *context = &contexts[i2c_device];
1105
1106 switch (control) {
1107 case SEDI_I2C_BUS_SPEED:
1108 if (arg == SEDI_I2C_BUS_SPEED_STANDARD) {
1109 context->speed = I2C_SPEED_STANDARD;
1110 context->clk_info = &(context->bus_info.std_clk);
1111 } else if (arg == SEDI_I2C_BUS_SPEED_FAST) {
1112 context->speed = I2C_SPEED_FAST;
1113 context->clk_info = &(context->bus_info.fst_clk);
1114 } else if (arg == SEDI_I2C_BUS_SPEED_FAST_PLUS) {
1115 context->speed = I2C_SPEED_FAST_PLUS;
1116 context->clk_info = &(context->bus_info.fsp_clk);
1117 } else if (arg == SEDI_I2C_BUS_SPEED_HIGH) {
1118 context->speed = I2C_SPEED_HIGH;
1119 context->clk_info = &(context->bus_info.high_clk);
1120 } else {
1121 ret = SEDI_DRIVER_ERROR;
1122 }
1123 dw_i2c_disable(context->base);
1124 dw_i2c_config_speed(context->base, context->speed,
1125 context->clk_info);
1126 break;
1127
1128 /* force i2c enter IDLE mode */
1129 case SEDI_I2C_ABORT_TRANSFER:
1130 if (context->tx_dma_chan > SEDI_I2C_DMA_CHANNEL_UNUSED) {
1131 sedi_dma_abort_transfer(context->tx_dma_dev,
1132 context->tx_dma_chan);
1133 context->tx_dma_chan = SEDI_I2C_DMA_CHANNEL_UNUSED;
1134 }
1135 if (context->rx_dma_chan > SEDI_I2C_DMA_CHANNEL_UNUSED) {
1136 sedi_dma_abort_transfer(context->rx_dma_dev,
1137 context->rx_dma_chan);
1138 context->rx_dma_chan = SEDI_I2C_DMA_CHANNEL_UNUSED;
1139 }
1140 dw_i2c_abort(context);
1141 context->pending = 0;
1142 context->status.busy = 0;
1143 break;
1144 case SEDI_I2C_SET_TX_MEMORY_TYPE:
1145 context->tx_memory_type = arg;
1146 break;
1147 case SEDI_I2C_SET_RX_MEMORY_TYPE:
1148 context->rx_memory_type = arg;
1149 break;
1150 default:
1151 ret = SEDI_DRIVER_ERROR;
1152 break;
1153 }
1154
1155 if (ret != 0) {
1156 return SEDI_DRIVER_ERROR;
1157 }
1158
1159 return SEDI_DRIVER_OK;
1160 }
1161
sedi_i2c_get_status(IN sedi_i2c_t i2c_device,sedi_i2c_status_t * status)1162 int sedi_i2c_get_status(IN sedi_i2c_t i2c_device, sedi_i2c_status_t *status)
1163 {
1164 DBG_CHECK(i2c_device < SEDI_I2C_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1165 DBG_CHECK(NULL != status, SEDI_DRIVER_ERROR_PARAMETER);
1166
1167 struct i2c_context *context = &contexts[i2c_device];
1168
1169 *status = context->status;
1170
1171 return SEDI_DRIVER_OK;
1172 }
1173
i2c_isr_recv(sedi_i2c_t i2c_device)1174 static void i2c_isr_recv(sedi_i2c_t i2c_device)
1175 {
1176 struct i2c_context *context = &contexts[i2c_device];
1177 sedi_i2c_regs_t *i2c = (sedi_i2c_regs_t *)(context->base);
1178 uint32_t data_remain;
1179
1180 /* Receive all data from FIFO */
1181 uint32_t size = SEDI_PREG_RBFV_GET(I2C, RXFLR, RXFLR, &i2c->rxflr);
1182
1183 if (context->rx_cmd_index < size) {
1184 uint32_t dummy;
1185
1186 while (size) {
1187 dummy = i2c->data_cmd;
1188 size--;
1189 }
1190 (void)dummy;
1191
1192 return;
1193 }
1194
1195 while (size > 0) {
1196 context->buf[context->buf_index] = SEDI_PREG_RBFV_GET(I2C,
1197 DATA_CMD, DAT, &i2c->data_cmd);
1198 context->buf_index++;
1199 size--;
1200 }
1201
1202 /* If need to change watermark */
1203 data_remain = context->buf_size - context->buf_index;
1204 if ((data_remain <= SEDI_PREG_RBFV_GET(I2C, RX_TL, RX_TL, &i2c->rx_tl)) &&
1205 (data_remain != 0)) {
1206 SEDI_PREG_RBF_SET(I2C, RX_TL, RX_TL, data_remain - 1, &i2c->rx_tl);
1207 }
1208 }
1209
i2c_isr_complete(sedi_i2c_t i2c_device,bool is_error)1210 static void i2c_isr_complete(sedi_i2c_t i2c_device, bool is_error)
1211 {
1212 struct i2c_context *context = &contexts[i2c_device];
1213 sedi_i2c_regs_t *regs = (void *)context->base;
1214 uint32_t val;
1215
1216 dw_i2c_irq_config(context->base, 0);
1217
1218 dw_i2c_config_txfifo(context->base, 0);
1219 dw_i2c_config_rxfifo(context->base, 0);
1220
1221 if (context->status.event == SEDI_I2C_EVENT_TRANSFER_NONE) {
1222 if (is_error) {
1223 context->status.event = dw_i2c_abort_analysis(context->base);
1224 } else {
1225 context->status.event = SEDI_I2C_EVENT_TRANSFER_DONE;
1226 }
1227 }
1228
1229 /* Flush FIFO */
1230 if (context->status.event != SEDI_I2C_EVENT_TRANSFER_DONE) {
1231 dw_i2c_disable(context->base);
1232 }
1233
1234 context->pending = 0;
1235 context->status.busy = 0;
1236
1237 /* Clear all interrupt, this will clear abort source register*/
1238 val = regs->clr_intr;
1239 dw_i2c_clear_interrupt(context->base);
1240
1241 if (context->cb_event) {
1242 context->cb_event(context->status.event);
1243 }
1244 PARAM_UNUSED(val);
1245 }
1246
sedi_i2c_isr_handler(IN sedi_i2c_t i2c_device)1247 void sedi_i2c_isr_handler(IN sedi_i2c_t i2c_device)
1248 {
1249 struct i2c_context *context = &contexts[i2c_device];
1250 sedi_i2c_regs_t *regs = (void *)context->base;
1251 uint32_t stat, val;
1252
1253 /* Return if enter into isr unexpectedly */
1254 if (context->status.busy == 0) {
1255 return;
1256 }
1257
1258 /* Get interrupt status */
1259 stat = regs->intr_stat;
1260
1261 /* If error happened, go to end*/
1262 if (stat & BSETS_INTR_ERROR) {
1263 i2c_isr_complete(i2c_device, true);
1264 return;
1265 }
1266
1267 /* check if there is a entity in rx fifo */
1268 if (SEDI_PREG_RBFV_IS_SET(I2C, INTR_STAT, R_RX_FULL, ACTIVE, &stat)) {
1269 i2c_isr_recv(i2c_device);
1270 /* For receive with no STOP, while all data received, ended */
1271 if ((context->buf_index == context->buf_size) && (context->pending)) {
1272 i2c_isr_complete(i2c_device, false);
1273 return;
1274 }
1275 }
1276
1277 /* For transfer need STOP flag, use STOP as transfer end condition */
1278 if ((SEDI_PREG_RBFV_IS_SET(I2C, INTR_STAT, R_STOP_DET, ACTIVE, &stat)) &&
1279 (context->pending == 0)) {
1280 /* Clear stop detect interrupt */
1281 val = regs->clr_stop_det;
1282 i2c_isr_complete(i2c_device, false);
1283 return;
1284 }
1285 /* For send with no STOP, while TX FIFO empty, ended */
1286 if ((context->pending) && (context->buf_index == context->buf_size) &&
1287 (SEDI_PREG_RBFV_IS_SET(I2C, INTR_STAT, R_TX_EMPTY, ACTIVE, &stat))) {
1288 i2c_isr_complete(i2c_device, false);
1289 return;
1290 }
1291
1292 /* TX empty condition */
1293 if (SEDI_PREG_RBFV_IS_SET(I2C, INTR_STAT, R_TX_EMPTY, ACTIVE, &stat)) {
1294 /*If it is read operation, need to send cmd*/
1295 if (context->status.direction == 1) {
1296 i2c_ask_data(i2c_device);
1297 } else {
1298 i2c_send(i2c_device);
1299 }
1300 }
1301 PARAM_UNUSED(val);
1302 }
1303