1 /*
2  * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or
3  * an affiliate of Cypress Semiconductor Corporation
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 /**
9  * @brief I2C driver for Infineon XMC MCU family.
10  */
11 
12 #define DT_DRV_COMPAT infineon_xmc4xxx_i2c
13 
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(i2c_infineon_xmc4, CONFIG_I2C_LOG_LEVEL);
16 
17 #include <zephyr/drivers/i2c.h>
18 #include <zephyr/drivers/pinctrl.h>
19 
20 #include "i2c-priv.h"
21 
22 #include <xmc_i2c.h>
23 #include <xmc_usic.h>
24 
25 #define USIC_IRQ_MIN  84
26 #define IRQS_PER_USIC 6
27 
28 #define I2C_XMC_EVENTS_MASK ( \
29 	XMC_I2C_CH_EVENT_RECEIVE_START | \
30 	XMC_I2C_CH_EVENT_DATA_LOST | \
31 	XMC_I2C_CH_EVENT_TRANSMIT_SHIFT | \
32 	XMC_I2C_CH_EVENT_TRANSMIT_BUFFER | \
33 	XMC_I2C_CH_EVENT_STANDARD_RECEIVE | \
34 	XMC_I2C_CH_EVENT_ALTERNATIVE_RECEIVE | \
35 	XMC_I2C_CH_EVENT_BAUD_RATE_GENERATOR | \
36 	XMC_I2C_CH_EVENT_START_CONDITION_RECEIVED | \
37 	XMC_I2C_CH_EVENT_REPEATED_START_CONDITION_RECEIVED | \
38 	XMC_I2C_CH_EVENT_STOP_CONDITION_RECEIVED | \
39 	XMC_I2C_CH_EVENT_NACK | \
40 	XMC_I2C_CH_EVENT_ARBITRATION_LOST | \
41 	XMC_I2C_CH_EVENT_SLAVE_READ_REQUEST | \
42 	XMC_I2C_CH_EVENT_ERROR | \
43 	XMC_I2C_CH_EVENT_ACK)
44 
45 #define I2C_XMC_STATUS_FLAG_ERROR_MASK ( \
46 	XMC_I2C_CH_STATUS_FLAG_WRONG_TDF_CODE_FOUND | \
47 	XMC_I2C_CH_STATUS_FLAG_NACK_RECEIVED | \
48 	XMC_I2C_CH_STATUS_FLAG_ARBITRATION_LOST | \
49 	XMC_I2C_CH_STATUS_FLAG_ERROR | \
50 	XMC_I2C_CH_STATUS_FLAG_DATA_LOST_INDICATION)
51 
52 /* I2C speed */
53 #define XMC4_I2C_SPEED_STANDARD     (100000UL)
54 #define XMC4_I2C_SPEED_FAST         (400000UL)
55 
56 /* Data structure */
57 struct ifx_xmc4_i2c_data {
58 	XMC_I2C_CH_CONFIG_t cfg;
59 	struct k_sem operation_sem;
60 	struct k_sem target_sem;
61 	struct i2c_target_config *p_target_config;
62 	uint32_t dev_config;
63 	uint8_t target_wr_byte;
64 	uint8_t target_wr_buffer[CONFIG_I2C_INFINEON_XMC4_TARGET_BUF];
65 	bool ignore_slave_select;
66 	bool is_configured;
67 };
68 
69 /* Device config structure */
70 struct ifx_xmc4_i2c_config {
71 	XMC_USIC_CH_t *i2c;
72 	const struct pinctrl_dev_config *pcfg;
73 	uint8_t scl_src;
74 	uint8_t sda_src;
75 	uint32_t bitrate;
76 	void (*irq_config_func)(const struct device *dev);
77 };
78 
ifx_xmc4_i2c_configure(const struct device * dev,uint32_t dev_config)79 static int ifx_xmc4_i2c_configure(const struct device *dev, uint32_t dev_config)
80 {
81 	struct ifx_xmc4_i2c_data *data = dev->data;
82 	const struct ifx_xmc4_i2c_config *config = dev->config;
83 
84 	/* This is deprecated and could be ignored in the future */
85 	if (dev_config & I2C_ADDR_10_BITS) {
86 		LOG_ERR("Use I2C_MSG_ADDR_10_BITS instead of I2C_ADDR_10_BITS");
87 		return -EIO;
88 	}
89 
90 	switch (I2C_SPEED_GET(dev_config)) {
91 	case I2C_SPEED_STANDARD:
92 		data->cfg.baudrate = XMC4_I2C_SPEED_STANDARD;
93 		break;
94 	case I2C_SPEED_FAST:
95 		data->cfg.baudrate = XMC4_I2C_SPEED_FAST;
96 		break;
97 	default:
98 		LOG_ERR("Unsupported speed");
99 		return -ERANGE;
100 	}
101 
102 	data->dev_config = dev_config;
103 
104 	/* Acquire semaphore (block I2C operation for another thread) */
105 	if (k_sem_take(&data->operation_sem, K_FOREVER)) {
106 		return -EIO;
107 	}
108 
109 	XMC_I2C_CH_Stop(config->i2c);
110 
111 	/* Configure the I2C resource */
112 	data->cfg.normal_divider_mode = false;
113 	XMC_I2C_CH_Init(config->i2c, &data->cfg);
114 	XMC_I2C_CH_SetInputSource(config->i2c, XMC_I2C_CH_INPUT_SCL, config->scl_src);
115 	XMC_I2C_CH_SetInputSource(config->i2c, XMC_I2C_CH_INPUT_SDA, config->sda_src);
116 	if (data->dev_config & I2C_MODE_CONTROLLER) {
117 		XMC_USIC_CH_SetFractionalDivider(config->i2c,
118 						 XMC_USIC_CH_BRG_CLOCK_DIVIDER_MODE_FRACTIONAL,
119 						 1023U);
120 	} else {
121 		config->irq_config_func(dev);
122 	}
123 	XMC_I2C_CH_Start(config->i2c);
124 	data->is_configured = true;
125 
126 	/* Release semaphore */
127 	k_sem_give(&data->operation_sem);
128 
129 	return 0;
130 }
131 
ifx_xmc4_i2c_get_config(const struct device * dev,uint32_t * dev_config)132 static int ifx_xmc4_i2c_get_config(const struct device *dev, uint32_t *dev_config)
133 {
134 	struct ifx_xmc4_i2c_data *data = dev->data;
135 	const struct ifx_xmc4_i2c_config *config = dev->config;
136 
137 	if (!data->is_configured) {
138 		/* if not yet configured return configuration that will be used */
139 		/* when transfer() is called */
140 		uint32_t bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);
141 
142 		*dev_config = I2C_MODE_CONTROLLER | bitrate_cfg;
143 		return 0;
144 	}
145 
146 	*dev_config = data->dev_config;
147 
148 	return 0;
149 }
150 
ifx_xmc4_i2c_msg_validate(struct i2c_msg * msg,uint8_t num_msgs)151 static int ifx_xmc4_i2c_msg_validate(struct i2c_msg *msg, uint8_t num_msgs)
152 {
153 	for (uint32_t i = 0u; i < num_msgs; i++) {
154 		if ((I2C_MSG_ADDR_10_BITS & msg[i].flags) || (msg[i].buf == NULL)) {
155 			return -EINVAL;
156 		}
157 	}
158 	return 0;
159 }
160 
ifx_xmc4_i2c_transfer(const struct device * dev,struct i2c_msg * msg,uint8_t num_msgs,uint16_t addr)161 static int ifx_xmc4_i2c_transfer(const struct device *dev, struct i2c_msg *msg, uint8_t num_msgs,
162 				 uint16_t addr)
163 {
164 	struct ifx_xmc4_i2c_data *data = dev->data;
165 	const struct ifx_xmc4_i2c_config *config = dev->config;
166 	XMC_I2C_CH_CMD_t cmd_type;
167 
168 	if (!num_msgs) {
169 		return 0;
170 	}
171 
172 	if (!data->is_configured) {
173 		int ret;
174 		uint32_t bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);
175 
176 		ret = ifx_xmc4_i2c_configure(dev, I2C_MODE_CONTROLLER | bitrate_cfg);
177 		if (ret) {
178 			return ret;
179 		}
180 	}
181 
182 	/* Acquire semaphore (block I2C transfer for another thread) */
183 	if (k_sem_take(&data->operation_sem, K_FOREVER)) {
184 		return -EIO;
185 	}
186 
187 	/* This function checks if msg.buf is not NULL and if target address is not 10 bit. */
188 	if (ifx_xmc4_i2c_msg_validate(msg, num_msgs) != 0) {
189 		k_sem_give(&data->operation_sem);
190 		return -EINVAL;
191 	}
192 
193 	for (uint32_t msg_index = 0u; msg_index < num_msgs; msg_index++) {
194 		XMC_I2C_CH_ClearStatusFlag(config->i2c, 0xFFFFFFFF);
195 
196 		if ((msg_index == 0) || (msg[msg_index].flags & I2C_MSG_RESTART)) {
197 			/* Send START condition */
198 			cmd_type = ((msg[msg_index].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) ?
199 				XMC_I2C_CH_CMD_READ : XMC_I2C_CH_CMD_WRITE;
200 
201 			if (msg[msg_index].flags & I2C_MSG_RESTART) {
202 				XMC_I2C_CH_MasterRepeatedStart(config->i2c, addr << 1, cmd_type);
203 			} else {
204 				XMC_I2C_CH_MasterStart(config->i2c, addr << 1, cmd_type);
205 			}
206 
207 			/* Wait for acknowledge */
208 			while ((XMC_I2C_CH_GetStatusFlag(config->i2c) &
209 				XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U) {
210 				/* wait for ACK from slave */
211 				if (XMC_I2C_CH_GetStatusFlag(config->i2c) &
212 				    I2C_XMC_STATUS_FLAG_ERROR_MASK) {
213 					k_sem_give(&data->operation_sem);
214 					return -EIO;
215 				}
216 			}
217 			XMC_I2C_CH_ClearStatusFlag(config->i2c,
218 						   XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
219 		}
220 
221 		for (uint32_t buf_index = 0u; buf_index < msg[msg_index].len; buf_index++) {
222 			if (cmd_type == XMC_I2C_CH_CMD_WRITE) {
223 				/* Transmit next command from I2C master to I2C slave */
224 				XMC_I2C_CH_MasterTransmit(config->i2c,
225 							  msg[msg_index].buf[buf_index]);
226 
227 				/* Wait for acknowledge */
228 				while ((XMC_I2C_CH_GetStatusFlag(config->i2c) &
229 					XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U) {
230 					/* wait for ACK from slave */
231 					if (XMC_I2C_CH_GetStatusFlag(config->i2c) &
232 					    I2C_XMC_STATUS_FLAG_ERROR_MASK) {
233 						k_sem_give(&data->operation_sem);
234 						return -EIO;
235 					}
236 				}
237 				XMC_I2C_CH_ClearStatusFlag(config->i2c,
238 							   XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
239 
240 				/* Wait until TX FIFO is empty */
241 				while (!XMC_USIC_CH_TXFIFO_IsEmpty(config->i2c)) {
242 					/* wait until all data is sent by HW */
243 					if (XMC_I2C_CH_GetStatusFlag(config->i2c) &
244 					    I2C_XMC_STATUS_FLAG_ERROR_MASK) {
245 						k_sem_give(&data->operation_sem);
246 						return -EIO;
247 					}
248 				}
249 			} else {
250 				if (buf_index == (msg[msg_index].len - 1)) {
251 					XMC_I2C_CH_MasterReceiveNack(config->i2c);
252 				} else {
253 					XMC_I2C_CH_MasterReceiveAck(config->i2c);
254 				}
255 
256 				while ((XMC_I2C_CH_GetStatusFlag(config->i2c) &
257 				       (XMC_I2C_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION |
258 					XMC_I2C_CH_STATUS_FLAG_RECEIVE_INDICATION)) == 0U) {
259 					/* wait for data byte from slave */
260 					if (XMC_I2C_CH_GetStatusFlag(config->i2c) &
261 					    I2C_XMC_STATUS_FLAG_ERROR_MASK) {
262 						k_sem_give(&data->operation_sem);
263 						return -EIO;
264 					}
265 				}
266 				XMC_I2C_CH_ClearStatusFlag(config->i2c,
267 					XMC_I2C_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION |
268 					XMC_I2C_CH_STATUS_FLAG_RECEIVE_INDICATION);
269 
270 				msg[msg_index].buf[buf_index] =
271 					XMC_I2C_CH_GetReceivedData(config->i2c);
272 			}
273 		}
274 
275 		/* Send STOP condition */
276 		if (msg[msg_index].flags & I2C_MSG_STOP) {
277 			XMC_I2C_CH_MasterStop(config->i2c);
278 		}
279 	}
280 
281 	/* Release semaphore (After I2C transfer is complete) */
282 	k_sem_give(&data->operation_sem);
283 	return 0;
284 }
285 
ifx_xmc4_i2c_init(const struct device * dev)286 static int ifx_xmc4_i2c_init(const struct device *dev)
287 {
288 	struct ifx_xmc4_i2c_data *data = dev->data;
289 	const struct ifx_xmc4_i2c_config *config = dev->config;
290 	int ret;
291 
292 	/* Configure semaphores */
293 	ret = k_sem_init(&data->operation_sem, 1, 1);
294 	if (ret) {
295 		return ret;
296 	}
297 
298 	ret = k_sem_init(&data->target_sem, 1, 1);
299 	if (ret) {
300 		return ret;
301 	}
302 
303 	/* Configure dt provided device signals when available */
304 	return pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
305 }
306 
ifx_xmc4_i2c_target_register(const struct device * dev,struct i2c_target_config * cfg)307 static int ifx_xmc4_i2c_target_register(const struct device *dev, struct i2c_target_config *cfg)
308 {
309 	struct ifx_xmc4_i2c_data *data = dev->data;
310 	const struct ifx_xmc4_i2c_config *config = dev->config;
311 	uint32_t bitrate_cfg;
312 
313 	if (!cfg ||
314 	    !cfg->callbacks->read_requested ||
315 	    !cfg->callbacks->read_processed ||
316 	    !cfg->callbacks->write_requested ||
317 	    !cfg->callbacks->write_received ||
318 	    !cfg->callbacks->stop) {
319 		return -EINVAL;
320 	}
321 
322 	if (cfg->flags & I2C_TARGET_FLAGS_ADDR_10_BITS) {
323 		return -ENOTSUP;
324 	}
325 
326 	/* Acquire semaphore (block I2C operation for another thread) */
327 	if (k_sem_take(&data->target_sem, K_FOREVER)) {
328 		return -EIO;
329 	}
330 
331 	data->p_target_config = cfg;
332 	data->cfg.address = cfg->address << 1;
333 
334 	if (data->is_configured) {
335 		uint32_t bitrate;
336 
337 		bitrate = I2C_SPEED_GET(data->dev_config);
338 		bitrate_cfg = i2c_map_dt_bitrate(bitrate);
339 	} else {
340 		bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);
341 	}
342 
343 	if (ifx_xmc4_i2c_configure(dev, bitrate_cfg) != 0) {
344 		/* Release semaphore */
345 		k_sem_give(&data->target_sem);
346 		return -EIO;
347 	}
348 
349 	k_sem_give(&data->target_sem);
350 	return 0;
351 }
352 
ifx_xmc4_i2c_target_unregister(const struct device * dev,struct i2c_target_config * cfg)353 static int ifx_xmc4_i2c_target_unregister(const struct device *dev, struct i2c_target_config *cfg)
354 {
355 	struct ifx_xmc4_i2c_data *data = dev->data;
356 	const struct ifx_xmc4_i2c_config *config = dev->config;
357 
358 	/* Acquire semaphore (block I2C operation for another thread) */
359 	if (k_sem_take(&data->operation_sem, K_FOREVER)) {
360 		return -EIO;
361 	}
362 
363 	data->p_target_config = NULL;
364 	XMC_I2C_CH_DisableEvent(config->i2c, I2C_XMC_EVENTS_MASK);
365 
366 	/* Release semaphore */
367 	k_sem_give(&data->operation_sem);
368 	return 0;
369 }
370 
371 
i2c_xmc4_isr(const struct device * dev)372 static void i2c_xmc4_isr(const struct device *dev)
373 {
374 	struct ifx_xmc4_i2c_data *data = dev->data;
375 	const struct ifx_xmc4_i2c_config *config = dev->config;
376 	const struct i2c_target_callbacks *callbacks = data->p_target_config->callbacks;
377 	uint32_t status = XMC_I2C_CH_GetStatusFlag(config->i2c);
378 
379 	while (status) {
380 		XMC_I2C_CH_ClearStatusFlag(config->i2c, status);
381 
382 		if (status & XMC_I2C_CH_STATUS_FLAG_STOP_CONDITION_RECEIVED) {
383 			/* Flush the TX buffer */
384 			XMC_USIC_CH_SetTransmitBufferStatus(config->i2c,
385 							    XMC_USIC_CH_TBUF_STATUS_SET_IDLE);
386 
387 			callbacks->stop(data->p_target_config);
388 			break;
389 		}
390 
391 		if (!data->ignore_slave_select && (status & XMC_I2C_CH_STATUS_FLAG_SLAVE_SELECT)) {
392 			data->ignore_slave_select = true;
393 
394 			/* Start a slave read */
395 			if (status & XMC_I2C_CH_STATUS_FLAG_SLAVE_READ_REQUESTED) {
396 				callbacks->read_requested(data->p_target_config,
397 							  &data->target_wr_byte);
398 				XMC_I2C_CH_SlaveTransmit(config->i2c, data->target_wr_byte);
399 			} else {
400 				callbacks->write_requested(data->p_target_config);
401 			}
402 		}
403 
404 		/* Continue a slave read */
405 		if (status & XMC_I2C_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION) {
406 			callbacks->read_processed(data->p_target_config, &data->target_wr_byte);
407 			XMC_I2C_CH_SlaveTransmit(config->i2c, data->target_wr_byte);
408 		}
409 
410 		/* Start/Continue a slave write */
411 		if (status & (XMC_I2C_CH_STATUS_FLAG_RECEIVE_INDICATION |
412 		    XMC_I2C_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION)) {
413 			callbacks->write_received(data->p_target_config,
414 						  XMC_I2C_CH_GetReceivedData(config->i2c));
415 		}
416 
417 		if ((status & XMC_I2C_CH_STATUS_FLAG_START_CONDITION_RECEIVED) ||
418 		    (status & XMC_I2C_CH_STATUS_FLAG_REPEATED_START_CONDITION_RECEIVED)) {
419 			data->ignore_slave_select = false;
420 		}
421 
422 		status = XMC_I2C_CH_GetStatusFlag(config->i2c);
423 	}
424 }
425 
426 
427 /* I2C API structure */
428 static DEVICE_API(i2c, i2c_xmc4_driver_api) = {
429 	.configure = ifx_xmc4_i2c_configure,
430 	.transfer = ifx_xmc4_i2c_transfer,
431 	.get_config = ifx_xmc4_i2c_get_config,
432 	.target_register = ifx_xmc4_i2c_target_register,
433 	.target_unregister = ifx_xmc4_i2c_target_unregister,
434 #ifdef CONFIG_I2C_RTIO
435 	.iodev_submit = i2c_iodev_submit_fallback,
436 #endif
437 };
438 
439 /* Macros for I2C instance declaration */
440 #define XMC4_IRQ_HANDLER_INIT(index)                                                               \
441 	static void i2c_xmc4_irq_setup_##index(const struct device *dev)                           \
442 	{                                                                                          \
443 		const struct ifx_xmc4_i2c_config *config = dev->config;                            \
444 		uint8_t irq_num = DT_INST_IRQN(index);                                             \
445 		uint8_t service_request = (irq_num - USIC_IRQ_MIN) % IRQS_PER_USIC;                \
446 												   \
447 		XMC_I2C_CH_SelectInterruptNodePointer(config->i2c,                                 \
448 			XMC_I2C_CH_INTERRUPT_NODE_POINTER_RECEIVE, service_request);               \
449 		XMC_I2C_CH_SelectInterruptNodePointer(config->i2c,                                 \
450 			XMC_I2C_CH_INTERRUPT_NODE_POINTER_ALTERNATE_RECEIVE, service_request);     \
451 												   \
452 		XMC_I2C_CH_EnableEvent(config->i2c, I2C_XMC_EVENTS_MASK);                          \
453 												   \
454 		IRQ_CONNECT(DT_INST_IRQN(index), DT_INST_IRQ(index, priority), i2c_xmc4_isr,       \
455 			    DEVICE_DT_INST_GET(index), 0);                                         \
456 												   \
457 		irq_enable(irq_num);                                                               \
458 	}
459 
460 #define XMC4_IRQ_HANDLER_STRUCT_INIT(index) .irq_config_func = i2c_xmc4_irq_setup_##index
461 
462 #define INFINEON_XMC4_I2C_INIT(n)                                                                  \
463 	PINCTRL_DT_INST_DEFINE(n);                                                                 \
464 	XMC4_IRQ_HANDLER_INIT(n)                                                                   \
465                                                                                                    \
466 	static struct ifx_xmc4_i2c_data ifx_xmc4_i2c_data##n;                                      \
467                                                                                                    \
468 	static const struct ifx_xmc4_i2c_config i2c_xmc4_cfg_##n = {                               \
469 		.i2c = (XMC_USIC_CH_t *)DT_INST_REG_ADDR(n),                                       \
470 		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),                                         \
471 		.scl_src = DT_INST_ENUM_IDX(n, scl_src),                                           \
472 		.sda_src = DT_INST_ENUM_IDX(n, sda_src),                                           \
473 		.bitrate = DT_INST_PROP_OR(n, clock_frequency, I2C_SPEED_STANDARD),                \
474 		XMC4_IRQ_HANDLER_STRUCT_INIT(n)                                                    \
475 	};                                                                                         \
476                                                                                                    \
477 	I2C_DEVICE_DT_INST_DEFINE(n, ifx_xmc4_i2c_init, NULL, &ifx_xmc4_i2c_data##n,               \
478 				  &i2c_xmc4_cfg_##n, POST_KERNEL,                                  \
479 				  CONFIG_I2C_INIT_PRIORITY, &i2c_xmc4_driver_api);
480 
481 DT_INST_FOREACH_STATUS_OKAY(INFINEON_XMC4_I2C_INIT)
482