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