1 /* Copyright (C) 2024 BeagleBoard.org Foundation
2  * Copyright (C) 2024 Dhruv Menon <dhruvmenon1104@gmail.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT ti_omap_i2c
8 #include <errno.h>
9 #include <zephyr/kernel.h>
10 #include <zephyr/device.h>
11 #include <zephyr/devicetree.h>
12 #include <zephyr/logging/log.h>
13 #include <zephyr/irq.h>
14 #include <zephyr/drivers/i2c.h>
15 #include <zephyr/drivers/pinctrl.h>
16 
17 #ifdef CONFIG_I2C_OMAP_BUS_RECOVERY
18 #include "i2c_bitbang.h"
19 #endif /* CONFIG_I2C_OMAP_BUS_RECOVERY */
20 
21 LOG_MODULE_REGISTER(omap_i2c, CONFIG_I2C_LOG_LEVEL);
22 
23 #define I2C_OMAP_TIMEOUT     100U
24 /* OCP_SYSSTATUS bit definitions */
25 #define SYSS_RESETDONE_MASK  BIT(0)
26 #define RETRY                -1
27 #define I2C_BITRATE_FAST     400000
28 #define I2C_BITRATE_STANDARD 100000
29 
30 /* I2C Registers */
31 typedef struct {
32 	uint8_t RESERVED_0[0x10]; /**< Reserved, offset: 0x0 */
33 
34 	__IO uint32_t SYSC;          /**< System Configuration, offset: 0x10 */
35 	uint8_t RESERVED_1[0x18];    /**< Reserved, offset: 0x14 - 0x2C */
36 	__IO uint32_t IRQENABLE_SET; /**< Interrupt Enable Set, offset: 0x2C */
37 	uint8_t RESERVED_2[0x4];     /**< Reserved, offset: 0x30 - 0x34 */
38 	__IO uint32_t WE;            /**< Wakeup Enable, offset: 0x34 */
39 	uint8_t RESERVED_3[0x4C];    /**< Reserved, offset: 0x38 - 0x84 */
40 	__IO uint32_t IE;            /**< Interrupt Enable (Legacy), offset: 0x84 */
41 	__IO uint32_t STAT;          /**< Status, offset: 0x88 */
42 	uint8_t RESERVED_4[0x4];     /**< Reserved, offset: 0x8C - 0x90 */
43 	__IO uint32_t SYSS;          /**< System Status, offset: 0x90 */
44 	__IO uint32_t BUF;           /**< Buffer, offset: 0x94 */
45 	__IO uint32_t CNT;           /**< Data Count, offset: 0x98 */
46 	__IO uint32_t DATA;          /**< Data Access, offset: 0x9C */
47 	uint8_t RESERVED_5[0x4];     /**< Reserved, offset: 0xA0 - 0xA4 */
48 	__IO uint32_t CON;           /**< Configuration, offset: 0xA4 */
49 	__IO uint32_t OA;            /**< Own Address, offset: 0xA8 */
50 	__IO uint32_t SA;            /**< Target Address, offset: 0xAC */
51 	__IO uint32_t PSC;           /**< Clock Prescaler, offset: 0xB0 */
52 	__IO uint32_t SCLL;          /**< SCL Low Time, offset: 0xB4 */
53 	__IO uint32_t SCLH;          /**< SCL High Time, offset: 0xB8 */
54 	__IO uint32_t SYSTEST;       /**< System Test, offset: 0xBC */
55 	__IO uint32_t BUFSTAT;       /**< Buffer Status, offset: 0xC0 */
56 } i2c_omap_regs_t;
57 
58 /* I2C Configuration Register (I2C_OMAP_CON) */
59 #define I2C_OMAP_CON_EN        BIT(15) /* I2C module enable */
60 #define I2C_OMAP_CON_OPMODE_HS BIT(12) /* High Speed support */
61 #define I2C_OMAP_CON_MST       BIT(10) /* Controller/target mode */
62 #define I2C_OMAP_CON_TRX       BIT(9)  /* TX/RX mode (controller only) */
63 #define I2C_OMAP_CON_STP       BIT(1)  /* Stop condition (controller only) */
64 #define I2C_OMAP_CON_STT       BIT(0)  /* Start condition (controller) */
65 
66 /* I2C Buffer Configuration Register (I2C_OMAP_BUF): */
67 #define I2C_OMAP_BUF_RXFIF_CLR BIT(14) /* RX FIFO Clear */
68 #define I2C_OMAP_BUF_TXFIF_CLR BIT(6)  /* TX FIFO Clear */
69 
70 /* I2C Status Register (I2C_OMAP_STAT): */
71 #define I2C_OMAP_STAT_XDR  BIT(14) /* TX Buffer draining */
72 #define I2C_OMAP_STAT_RDR  BIT(13) /* RX Buffer draining */
73 #define I2C_OMAP_STAT_BB   BIT(12) /* Bus busy */
74 #define I2C_OMAP_STAT_ROVR BIT(11) /* Receive overrun */
75 #define I2C_OMAP_STAT_XUDF BIT(10) /* Transmit underflow */
76 #define I2C_OMAP_STAT_AAS  BIT(9)  /* Address as target */
77 #define I2C_OMAP_STAT_XRDY BIT(4)  /* Transmit data ready */
78 #define I2C_OMAP_STAT_RRDY BIT(3)  /* Receive data ready */
79 #define I2C_OMAP_STAT_ARDY BIT(2)  /* Register access ready */
80 #define I2C_OMAP_STAT_NACK BIT(1)  /* No ack interrupt enable */
81 #define I2C_OMAP_STAT_AL   BIT(0)  /* Arbitration lost */
82 
83 /* I2C System Test Register (I2C_OMAP_SYSTEST): */
84 #define I2C_OMAP_SYSTEST_ST_EN       BIT(15)   /* System test enable */
85 #define I2C_OMAP_SYSTEST_FREE        BIT(14)   /* Free running mode */
86 #define I2C_OMAP_SYSTEST_TMODE_MASK  (3 << 12) /* Test mode select mask */
87 #define I2C_OMAP_SYSTEST_TMODE_SHIFT (12)      /* Test mode select shift */
88 
89 /* Functional mode */
90 #define I2C_OMAP_SYSTEST_SCL_I_FUNC BIT(8) /* SCL line input value */
91 #define I2C_OMAP_SYSTEST_SDA_I_FUNC BIT(6) /* SDA line input value */
92 
93 /* SDA/SCL IO mode */
94 #define I2C_OMAP_SYSTEST_SCL_I BIT(3) /* SCL line sense in */
95 #define I2C_OMAP_SYSTEST_SCL_O BIT(2) /* SCL line drive out */
96 #define I2C_OMAP_SYSTEST_SDA_I BIT(1) /* SDA line sense in */
97 #define I2C_OMAP_SYSTEST_SDA_O BIT(0) /* SDA line drive out */
98 
99 typedef void (*init_func_t)(const struct device *dev);
100 #define DEV_CFG(dev)      ((const struct i2c_omap_cfg *)(dev)->config)
101 #define DEV_DATA(dev)     ((struct i2c_omap_data *)(dev)->data)
102 #define DEV_I2C_BASE(dev) ((i2c_omap_regs_t *)DEVICE_MMIO_NAMED_GET(dev, base))
103 
104 struct i2c_omap_cfg {
105 	DEVICE_MMIO_NAMED_ROM(base);
106 	uint32_t irq;
107 	uint32_t speed;
108 	const struct pinctrl_dev_config *pcfg;
109 };
110 
111 enum i2c_omap_speed {
112 	I2C_OMAP_SPEED_STANDARD,
113 	I2C_OMAP_SPEED_FAST,
114 	I2C_OMAP_SPEED_FAST_PLUS,
115 };
116 
117 struct i2c_omap_speed_config {
118 	uint32_t pscstate;
119 	uint32_t scllstate;
120 	uint32_t sclhstate;
121 };
122 
123 struct i2c_omap_data {
124 	DEVICE_MMIO_NAMED_RAM(base);
125 	enum i2c_omap_speed speed;
126 	struct i2c_omap_speed_config speed_config;
127 	struct i2c_msg current_msg;
128 	struct k_sem lock;
129 	bool receiver;
130 	bool bb_valid;
131 };
132 
133 /**
134  * @brief Initializes the OMAP I2C driver.
135  *
136  * This function is responsible for initializing the OMAP I2C driver.
137  *
138  * @param dev Pointer to the device structure for the I2C driver instance.
139  */
i2c_omap_init_ll(const struct device * dev)140 static void i2c_omap_init_ll(const struct device *dev)
141 {
142 
143 	struct i2c_omap_data *data = DEV_DATA(dev);
144 	i2c_omap_regs_t *i2c_base_addr = DEV_I2C_BASE(dev);
145 
146 	i2c_base_addr->CON = 0;
147 	i2c_base_addr->PSC = data->speed_config.pscstate;
148 	i2c_base_addr->SCLL = data->speed_config.scllstate;
149 	i2c_base_addr->SCLH = data->speed_config.sclhstate;
150 	i2c_base_addr->CON = I2C_OMAP_CON_EN;
151 }
152 
153 /**
154  * @brief Reset the OMAP I2C controller.
155  *
156  * This function resets the OMAP I2C controller specified by the device pointer.
157  *
158  * @param dev Pointer to the device structure for the I2C controller.
159  * @return 0 on success, negative errno code on failure.
160  */
i2c_omap_reset(const struct device * dev)161 static int i2c_omap_reset(const struct device *dev)
162 {
163 	struct i2c_omap_data *data = DEV_DATA(dev);
164 	i2c_omap_regs_t *i2c_base_addr = DEV_I2C_BASE(dev);
165 	uint64_t timeout;
166 	uint16_t sysc;
167 
168 	sysc = i2c_base_addr->SYSC;
169 	i2c_base_addr->CON &= ~I2C_OMAP_CON_EN;
170 	timeout = k_uptime_get() + I2C_OMAP_TIMEOUT;
171 	i2c_base_addr->CON = I2C_OMAP_CON_EN;
172 	while (!(i2c_base_addr->SYSS & SYSS_RESETDONE_MASK)) {
173 		if (k_uptime_get() > timeout) {
174 			LOG_WRN("timeout waiting for controller reset");
175 			return -ETIMEDOUT;
176 		}
177 		k_busy_wait(100);
178 	}
179 	i2c_base_addr->SYSC = sysc;
180 	data->bb_valid = 0;
181 	return 0;
182 }
183 
184 /**
185  * @brief Set the speed of the OMAP I2C controller.
186  *
187  * This function sets the speed of the OMAP I2C controller based on the
188  * specified speed parameter. The speed can be set to either Fast mode or
189  * Standard mode.
190  *
191  * @param dev The pointer to the device structure.
192  * @param speed The desired speed for the I2C controller.
193  *
194  * @return 0 on success, negative error code on failure.
195  */
i2c_omap_set_speed(const struct device * dev,uint32_t speed)196 static int i2c_omap_set_speed(const struct device *dev, uint32_t speed)
197 {
198 	struct i2c_omap_data *data = DEV_DATA(dev);
199 
200 	/* If configured for High Speed */
201 	switch (speed) {
202 	case I2C_BITRATE_FAST:
203 		/* Fast mode */
204 		data->speed_config = (struct i2c_omap_speed_config){
205 			.pscstate = 9,
206 			.scllstate = 7,
207 			.sclhstate = 5,
208 		};
209 		break;
210 	case I2C_BITRATE_STANDARD:
211 		/* Standard mode */
212 		data->speed_config = (struct i2c_omap_speed_config){
213 			.pscstate = 23,
214 			.scllstate = 13,
215 			.sclhstate = 15,
216 		};
217 		break;
218 	default:
219 		return -ERANGE;
220 	}
221 
222 	return 0;
223 }
224 
225 /**
226  * @brief Configure the OMAP I2C controller with the specified device configuration.
227  *
228  * This function configures the OMAP I2C controller with the specified device configuration.
229  *
230  * @param dev The pointer to the device structure.
231  * @param dev_config The device configuration to be applied.
232  *
233  * @return 0 on success, negative error code on failure.
234  */
i2c_omap_configure(const struct device * dev,uint32_t dev_config)235 static int i2c_omap_configure(const struct device *dev, uint32_t dev_config)
236 {
237 	uint32_t speed_cfg = I2C_BITRATE_STANDARD;
238 	struct i2c_omap_data *data = DEV_DATA(dev);
239 
240 	switch (I2C_SPEED_GET(dev_config)) {
241 	case I2C_SPEED_STANDARD:
242 		speed_cfg = I2C_BITRATE_STANDARD;
243 		break;
244 	case I2C_SPEED_FAST:
245 		speed_cfg = I2C_BITRATE_FAST;
246 		break;
247 	default:
248 		return -ENOTSUP;
249 	}
250 	if ((dev_config & I2C_MODE_CONTROLLER) != I2C_MODE_CONTROLLER) {
251 		return -ENOTSUP;
252 	}
253 	k_sem_take(&data->lock, K_FOREVER);
254 	i2c_omap_set_speed(dev, speed_cfg);
255 	i2c_omap_init_ll(dev);
256 	k_sem_give(&data->lock);
257 	return 0;
258 }
259 
260 /**
261  * @brief Transmit or receive data over I2C bus
262  *
263  * This function transmits or receives data over the I2C bus using the OMAP I2C controller.
264  *
265  * @param dev Pointer to the I2C device structure
266  * @param num_bytes Number of bytes to transmit or receive
267  */
i2c_omap_transmit_receive_data(const struct device * dev,uint8_t num_bytes)268 static void i2c_omap_transmit_receive_data(const struct device *dev, uint8_t num_bytes)
269 {
270 	struct i2c_omap_data *data = DEV_DATA(dev);
271 	i2c_omap_regs_t *i2c_base_addr = DEV_I2C_BASE(dev);
272 	uint8_t *buf_ptr = data->current_msg.buf;
273 
274 	while (num_bytes--) {
275 		if (data->receiver) {
276 			*buf_ptr++ = i2c_base_addr->DATA;
277 		} else {
278 			i2c_base_addr->DATA = *(buf_ptr++);
279 		}
280 	}
281 }
282 
283 /**
284  * @brief Resize the FIFO buffer for the OMAP I2C controller.
285  *
286  * This function resizes the FIFO buffer for the OMAP I2C controller based on the specified size.
287  * It clears the RX threshold and sets the new size for the receiver, or clears the TX threshold
288  * and sets the new size for the transmitter.
289  *
290  * @param dev Pointer to the device structure.
291  * @param size The new size of the FIFO buffer.
292  */
i2c_omap_resize_fifo(const struct device * dev,uint8_t size)293 static void i2c_omap_resize_fifo(const struct device *dev, uint8_t size)
294 {
295 	struct i2c_omap_data *data = DEV_DATA(dev);
296 	i2c_omap_regs_t *i2c_base_addr = DEV_I2C_BASE(dev);
297 
298 	if (data->receiver) {
299 		i2c_base_addr->BUF &= I2C_OMAP_BUF_RXFIF_CLR;
300 		i2c_base_addr->BUF |= ((size) << 8) | I2C_OMAP_BUF_RXFIF_CLR;
301 	} else {
302 		i2c_base_addr->BUF &= I2C_OMAP_BUF_TXFIF_CLR;
303 		i2c_base_addr->BUF |= (size) | I2C_OMAP_BUF_TXFIF_CLR;
304 	}
305 }
306 
307 #ifdef CONFIG_I2C_OMAP_BUS_RECOVERY
308 /**
309  * @brief Get the state of the SDA line.
310  *
311  * This function retrieves the state of the SDA (data) line for the OMAP I2C controller.
312  *
313  * @param io_context The I2C context.
314  * @return The state of the SDA line.
315  */
i2c_omap_get_sda(void * io_context)316 static int i2c_omap_get_sda(void *io_context)
317 {
318 	const struct i2c_omap_cfg *cfg = (const struct i2c_omap_cfg *)io_context;
319 	i2c_omap_regs_t *i2c_base_addr = (i2c_omap_regs_t *)cfg->base.addr;
320 
321 	return (i2c_base_addr->SYSTEST & I2C_OMAP_SYSTEST_SDA_I_FUNC) ? 1 : 0;
322 }
323 
324 /**
325  * @brief Set the state of the SDA line.
326  *
327  * This function sets the state of the SDA (data) line for the OMAP I2C controller.
328  *
329  * @param io_context The I2C context.
330  * @param state The state to set (0 for low, 1 for high).
331  */
i2c_omap_set_sda(void * io_context,int state)332 static void i2c_omap_set_sda(void *io_context, int state)
333 {
334 	const struct i2c_omap_cfg *cfg = (const struct i2c_omap_cfg *)io_context;
335 	i2c_omap_regs_t *i2c_base_addr = (i2c_omap_regs_t *)cfg->base.addr;
336 
337 	if (state) {
338 		i2c_base_addr->SYSTEST |= I2C_OMAP_SYSTEST_SDA_O;
339 	} else {
340 		i2c_base_addr->SYSTEST &= ~I2C_OMAP_SYSTEST_SDA_O;
341 	}
342 }
343 
344 /**
345  * @brief Set the state of the SCL line.
346  *
347  * This function sets the state of the SCL (clock) line for the OMAP I2C controller.
348  *
349  * @param io_context The I2C context.
350  * @param state The state to set (0 for low, 1 for high).
351  */
i2c_omap_set_scl(void * io_context,int state)352 static void i2c_omap_set_scl(void *io_context, int state)
353 {
354 	const struct i2c_omap_cfg *cfg = (const struct i2c_omap_cfg *)io_context;
355 	i2c_omap_regs_t *i2c_base_addr = (i2c_omap_regs_t *)cfg->base.addr;
356 
357 	if (state) {
358 		i2c_base_addr->SYSTEST |= I2C_OMAP_SYSTEST_SCL_O;
359 	} else {
360 		i2c_base_addr->SYSTEST &= ~I2C_OMAP_SYSTEST_SCL_O;
361 	}
362 }
363 /**
364  * @brief Recovers the I2C bus using the OMAP I2C controller.
365  *
366  * This function attempts to recover the I2C bus by performing a bus recovery
367  * sequence using the OMAP I2C controller. It uses the provided device
368  * configuration and bit-banging operations to recover the bus.
369  *
370  * @param dev Pointer to the device structure.
371  * @return 0 on success, negative error code on failure.
372  */
373 
i2c_omap_recover_bus(const struct device * dev)374 static int i2c_omap_recover_bus(const struct device *dev)
375 {
376 	const struct i2c_omap_cfg *cfg = DEV_CFG(dev);
377 	i2c_omap_regs_t *i2c_base_addr = DEV_I2C_BASE(dev);
378 	struct i2c_omap_data *data = DEV_DATA(dev);
379 
380 	struct i2c_bitbang bitbang_omap;
381 	struct i2c_bitbang_io bitbang_omap_io = {
382 		.get_sda = i2c_omap_get_sda,
383 		.set_scl = i2c_omap_set_scl,
384 		.set_sda = i2c_omap_set_sda,
385 	};
386 	int error = 0;
387 
388 	k_sem_take(&data->lock, K_FOREVER);
389 	i2c_base_addr->SYSTEST |= I2C_OMAP_SYSTEST_ST_EN | (3 << I2C_OMAP_SYSTEST_TMODE_SHIFT) |
390 				  I2C_OMAP_SYSTEST_SCL_O | I2C_OMAP_SYSTEST_SDA_O;
391 	i2c_bitbang_init(&bitbang_omap, &bitbang_omap_io, (void *)cfg);
392 	error = i2c_bitbang_recover_bus(&bitbang_omap);
393 	if (error != 0) {
394 		LOG_ERR("failed to recover bus (err %d)", error);
395 		goto restore;
396 	}
397 
398 restore:
399 	i2c_base_addr->SYSTEST &= ~(I2C_OMAP_SYSTEST_ST_EN | I2C_OMAP_SYSTEST_TMODE_MASK |
400 				    I2C_OMAP_SYSTEST_SCL_O | I2C_OMAP_SYSTEST_SDA_O);
401 	i2c_omap_reset(dev);
402 	k_sem_give(&data->lock);
403 	return error;
404 }
405 #endif /* CONFIG_I2C_OMAP_BUS_RECOVERY */
406 
407 /**
408  * @brief Wait for the bus to become free (no longer busy).
409  *
410  * This function waits for the bus to become free by continuously checking the
411  * status register of the OMAP I2C controller. If the bus remains busy for a
412  * certain timeout period, the function will return attempts to recover the bus by calling
413  * i2c_omap_recover_bus().
414  *
415  * @param dev The I2C device structure.
416  * @return 0 if the bus becomes free, or a negative error code if the bus cannot
417  * be recovered.
418  */
i2c_omap_wait_for_bb(const struct device * dev)419 static int i2c_omap_wait_for_bb(const struct device *dev)
420 {
421 	i2c_omap_regs_t *i2c_base_addr = DEV_I2C_BASE(dev);
422 	uint32_t timeout = k_uptime_get_32() + I2C_OMAP_TIMEOUT;
423 
424 	while (i2c_base_addr->STAT & I2C_OMAP_STAT_BB) {
425 		if (k_uptime_get_32() > timeout) {
426 			LOG_ERR("Bus busy timeout");
427 #ifdef CONFIG_I2C_OMAP_BUS_RECOVERY
428 			return i2c_omap_recover_bus(dev);
429 #else
430 			return -ETIMEDOUT;
431 #endif /* CONFIG_I2C_OMAP_BUS_RECOVERY */
432 		}
433 		k_busy_wait(100);
434 	}
435 	return 0;
436 }
437 
438 /**
439  * @brief Performs data transfer for the OMAP I2C driver.
440  *
441  * This function is responsible for handling the data transfer logic for the OMAP I2C driver.
442  * It reads the status register and performs the necessary actions based on the status flags.
443  * It handles both receive and transmit logic, and also handles error conditions such as NACK,
444  * arbitration lost, receive overrun, and transmit underflow.
445  *
446  * @param dev Pointer to the device structure.
447  *
448  * @return Returns 0 on success, or a negative error code on failure.
449  */
i2c_omap_transfer_message_ll(const struct device * dev)450 static int i2c_omap_transfer_message_ll(const struct device *dev)
451 {
452 	struct i2c_omap_data *data = DEV_DATA(dev);
453 	i2c_omap_regs_t *i2c_base_addr = DEV_I2C_BASE(dev);
454 	uint16_t stat = i2c_base_addr->STAT, result = 0;
455 
456 	if (data->receiver) {
457 		stat &= ~(I2C_OMAP_STAT_XDR | I2C_OMAP_STAT_XRDY);
458 	} else {
459 		stat &= ~(I2C_OMAP_STAT_RDR | I2C_OMAP_STAT_RRDY);
460 	}
461 	if (stat & I2C_OMAP_STAT_NACK) {
462 		result |= I2C_OMAP_STAT_NACK;
463 		i2c_base_addr->STAT |= I2C_OMAP_STAT_NACK;
464 	}
465 	if (stat & I2C_OMAP_STAT_AL) {
466 		result |= I2C_OMAP_STAT_AL;
467 		i2c_base_addr->STAT |= I2C_OMAP_STAT_AL;
468 	}
469 	if (stat & I2C_OMAP_STAT_ARDY) {
470 		i2c_base_addr->STAT |= I2C_OMAP_STAT_ARDY;
471 	}
472 	if (stat & (I2C_OMAP_STAT_ARDY | I2C_OMAP_STAT_NACK | I2C_OMAP_STAT_AL)) {
473 
474 		i2c_base_addr->STAT |=
475 			(I2C_OMAP_STAT_RRDY | I2C_OMAP_STAT_RDR | I2C_OMAP_STAT_XRDY |
476 			 I2C_OMAP_STAT_XDR | I2C_OMAP_STAT_ARDY);
477 		return result;
478 	}
479 
480 	/* Handle receive logic */
481 	if (stat & (I2C_OMAP_STAT_RRDY | I2C_OMAP_STAT_RDR)) {
482 		int buffer =
483 			(stat & I2C_OMAP_STAT_RRDY) ? i2c_base_addr->BUF : i2c_base_addr->BUFSTAT;
484 		i2c_omap_transmit_receive_data(dev, buffer);
485 		i2c_base_addr->STAT |=
486 			(stat & I2C_OMAP_STAT_RRDY) ? I2C_OMAP_STAT_RRDY : I2C_OMAP_STAT_RDR;
487 		return RETRY;
488 	}
489 
490 	/* Handle transmit logic */
491 	if (stat & (I2C_OMAP_STAT_XRDY | I2C_OMAP_STAT_XDR)) {
492 		int buffer =
493 			(stat & I2C_OMAP_STAT_XRDY) ? i2c_base_addr->BUF : i2c_base_addr->BUFSTAT;
494 		i2c_omap_transmit_receive_data(dev, buffer);
495 		i2c_base_addr->STAT |=
496 			(stat & I2C_OMAP_STAT_XRDY) ? I2C_OMAP_STAT_XRDY : I2C_OMAP_STAT_XDR;
497 		return RETRY;
498 	}
499 
500 	if (stat & I2C_OMAP_STAT_ROVR) {
501 		i2c_base_addr->STAT |= I2C_OMAP_STAT_ROVR;
502 		return I2C_OMAP_STAT_ROVR;
503 	}
504 	if (stat & I2C_OMAP_STAT_XUDF) {
505 		i2c_base_addr->STAT |= I2C_OMAP_STAT_XUDF;
506 		return I2C_OMAP_STAT_XUDF;
507 	}
508 	return RETRY;
509 }
510 
511 /**
512  * @brief Performs an I2C transfer of a single message.
513  *
514  * This function is responsible for performing an I2C transfer of a single message.
515  * It sets up the necessary configurations, writes the target device address,
516  * sets the buffer and buffer length, and handles various error conditions.
517  *
518  * @param dev The I2C device structure.
519  * @param msg Pointer to the I2C message structure.
520  * @param polling Flag indicating whether to use polling mode or not.
521  * @param addr The target device address.
522  *
523  * @return 0 on success, negative error code on failure.
524  *         Possible error codes include:
525  *         - ETIMEDOUT: Timeout occurred during the transfer.
526  *         - EIO: I/O error due to receiver overrun or transmit underflow.
527  *         - EAGAIN: Arbitration lost error, try again.
528  *         - ENOMSG: Message error due to NACK.
529  */
i2c_omap_transfer_message(const struct device * dev,struct i2c_msg * msg,bool polling,uint16_t addr)530 static int i2c_omap_transfer_message(const struct device *dev, struct i2c_msg *msg, bool polling,
531 				     uint16_t addr)
532 {
533 	struct i2c_omap_data *data = DEV_DATA(dev);
534 	i2c_omap_regs_t *i2c_base_addr = DEV_I2C_BASE(dev);
535 	unsigned long time_left = 1000;
536 	uint16_t control_reg;
537 	int result = 0;
538 	/* Determine message direction (read or write) and update the receiver flag */
539 	data->receiver = msg->flags & I2C_MSG_READ;
540 	/* Adjust the FIFO size according to the message length */
541 	i2c_omap_resize_fifo(dev, msg->len);
542 	/* Set the target I2C address for the transfer */
543 	i2c_base_addr->SA = addr;
544 	/* Store the message in the data structure */
545 	data->current_msg = *msg;
546 	/* Set the message length in the I2C controller */
547 	i2c_base_addr->CNT = msg->len;
548 	/* Clear FIFO buffers */
549 	control_reg = i2c_base_addr->BUF;
550 	control_reg |= I2C_OMAP_BUF_RXFIF_CLR | I2C_OMAP_BUF_TXFIF_CLR;
551 	i2c_base_addr->BUF = control_reg;
552 	/* If we're not polling, reset the command completion semaphore */
553 	if (!polling) {
554 		k_sem_reset(&data->lock);
555 	}
556 	/* Reset the command error status */
557 	/* Prepare the control register for the I2C operation */
558 	control_reg = I2C_OMAP_CON_EN | I2C_OMAP_CON_MST | I2C_OMAP_CON_STT;
559 	/* Enable high-speed mode if required by the transfer speed */
560 	if (data->speed > I2C_BITRATE_FAST) {
561 		control_reg |= I2C_OMAP_CON_OPMODE_HS;
562 	}
563 	/* Set the STOP condition if it's specified in the message flags */
564 	if (msg->flags & I2C_MSG_STOP) {
565 		control_reg |= I2C_OMAP_CON_STP;
566 	}
567 	/* Set the transmission mode based on whether it's a read or write operation */
568 	if (!(msg->flags & I2C_MSG_READ)) {
569 		control_reg |= I2C_OMAP_CON_TRX;
570 	}
571 	/* Start the I2C transfer by writing the control register */
572 	i2c_base_addr->CON = control_reg;
573 	/* Poll for status until the transfer is complete */
574 	/* Call a lower-level function to continue the transfer */
575 	do {
576 		result = i2c_omap_transfer_message_ll(dev);
577 		time_left--;
578 	} while (result == RETRY && time_left);
579 
580 	/* If no errors occurred, return success */
581 	if (!result) {
582 		return 0;
583 	}
584 
585 	/* Handle timeout or specific error conditions */
586 	if (result & (I2C_OMAP_STAT_ROVR | I2C_OMAP_STAT_XUDF)) {
587 		i2c_omap_reset(dev);
588 		i2c_omap_init_ll(dev);
589 		/* Return an error code based on whether it was a timeout or buffer error */
590 		return -EIO; /* Receiver overrun or transmitter underflow */
591 	}
592 	/* Handle arbitration loss and NACK errors */
593 	if (result & (I2C_OMAP_STAT_AL | -EAGAIN)) {
594 		return -EAGAIN;
595 	}
596 	if (result & I2C_OMAP_STAT_NACK) {
597 		/* Issue a STOP condition after NACK */
598 		i2c_base_addr->CON |= I2C_OMAP_CON_STP;
599 		return -ENOMSG; /* Indicate a message error due to NACK */
600 	}
601 
602 	/* Return a general I/O error if no specific error conditions matched */
603 	return -EIO;
604 }
605 
606 /**
607  * @brief Performs a common transfer operation for OMAP I2C devices.
608  *
609  * This function is responsible for transferring multiple I2C messages in a common way
610  * for OMAP I2C devices. It waits for the bus to be idle, then iterates through each
611  * message in the provided array and transfers them one by one using the i2c_omap_transfer_message()
612  * function. After all messages have been transferred, it waits for the bus to be idle again
613  * before returning.
614  *
615  * @param dev The pointer to the I2C device structure.
616  * @param msg An array of I2C messages to be transferred.
617  * @param num The number of messages in the array.
618  * @param polling Specifies whether to use polling or interrupt-based transfer.
619  * @param addr The I2C target address.
620  * @return 0 on success, or a negative error code on failure.
621  */
i2c_omap_transfer_main(const struct device * dev,struct i2c_msg msg[],int num,bool polling,uint16_t addr)622 static int i2c_omap_transfer_main(const struct device *dev, struct i2c_msg msg[], int num,
623 				  bool polling, uint16_t addr)
624 {
625 	int ret;
626 
627 	ret = i2c_omap_wait_for_bb(dev);
628 	struct i2c_omap_data *data = DEV_DATA(dev);
629 
630 	k_sem_take(&data->lock, K_FOREVER);
631 	if (ret < 0) {
632 		return ret;
633 	}
634 	for (int msg_idx = 0; msg_idx < num; msg_idx++) {
635 		ret = i2c_omap_transfer_message(dev, &msg[msg_idx], polling, addr);
636 		if (ret < 0) {
637 			break;
638 		}
639 	}
640 	k_sem_give(&data->lock);
641 	i2c_omap_wait_for_bb(dev);
642 	return ret;
643 }
644 
645 /**
646  * @brief OMAP I2C transfer function using polling.
647  *
648  * This function performs the I2C transfer using the OMAP I2C controller
649  * in polling mode. It calls the common transfer function with the
650  * specified messages, number of messages, and target address.
651  *
652  * @param dev Pointer to the I2C device structure.
653  * @param msgs Array of I2C messages to be transferred.
654  * @param num_msgs Number of I2C messages in the array.
655  * @param addr Target address.
656  * @return 0 on success, negative error code on failure.
657  */
i2c_omap_transfer_polling(const struct device * dev,struct i2c_msg msgs[],uint8_t num_msgs,uint16_t addr)658 static int i2c_omap_transfer_polling(const struct device *dev, struct i2c_msg msgs[],
659 						    uint8_t num_msgs, uint16_t addr)
660 {
661 	return i2c_omap_transfer_main(dev, msgs, num_msgs, true, addr);
662 }
663 
664 static DEVICE_API(i2c, i2c_omap_api) = {
665 	.transfer = i2c_omap_transfer_polling,
666 	.configure = i2c_omap_configure,
667 #ifdef CONFIG_I2C_OMAP_BUS_RECOVERY
668 	.recover_bus = i2c_omap_recover_bus,
669 #endif /* CONFIG_I2C_OMAP_BUS_RECOVERY */
670 };
671 
672 /**
673  * @brief Initialize the OMAP I2C controller.
674  *
675  * This function initializes the OMAP I2C controller by setting the speed and
676  * performing any necessary initialization steps.
677  *
678  * @param dev Pointer to the device structure for the I2C controller.
679  * @return 0 if successful, negative error code otherwise.
680  */
i2c_omap_init(const struct device * dev)681 static int i2c_omap_init(const struct device *dev)
682 {
683 	struct i2c_omap_data *data = DEV_DATA(dev);
684 	const struct i2c_omap_cfg *cfg = DEV_CFG(dev);
685 	int ret;
686 
687 	ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
688 	if (ret < 0) {
689 		LOG_ERR("failed to apply pinctrl");
690 		return ret;
691 	}
692 
693 	k_sem_init(&data->lock, 1, 1);
694 	/* Set the speed for I2C */
695 	if (i2c_omap_set_speed(dev, cfg->speed)) {
696 		LOG_ERR("Failed to set speed");
697 		return -ENOTSUP;
698 	}
699 	i2c_omap_init_ll(dev);
700 	return 0;
701 }
702 
703 #define I2C_OMAP_INIT(inst)                                                                        \
704 	PINCTRL_DT_INST_DEFINE(inst);                                                              \
705 	LOG_INSTANCE_REGISTER(omap_i2c, inst, CONFIG_I2C_LOG_LEVEL);                               \
706 	static const struct i2c_omap_cfg i2c_omap_cfg_##inst = {                                   \
707 		DEVICE_MMIO_NAMED_ROM_INIT(base, DT_DRV_INST(inst)),                               \
708 		.irq = DT_INST_IRQN(inst),                                                         \
709 		.speed = DT_INST_PROP(inst, clock_frequency),                                      \
710 		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst),                                      \
711 	};                                                                                         \
712                                                                                                    \
713 	static struct i2c_omap_data i2c_omap_data_##inst;                                          \
714                                                                                                    \
715 	I2C_DEVICE_DT_INST_DEFINE(inst,                                                            \
716 		i2c_omap_init,                                                                     \
717 		NULL,                                                                              \
718 		&i2c_omap_data_##inst,                                                             \
719 		&i2c_omap_cfg_##inst,                                                              \
720 		POST_KERNEL,                                                                       \
721 		CONFIG_I2C_INIT_PRIORITY,                                                          \
722 		&i2c_omap_api);
723 
724 DT_INST_FOREACH_STATUS_OKAY(I2C_OMAP_INIT)
725