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