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