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