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