1 /*
2 * Copyright (c) 2018 Diego Sueiro, <diego.sueiro@gmail.com>
3 * Copyright 2022 NXP
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #define DT_DRV_COMPAT fsl_imx21_i2c
9
10 #include <errno.h>
11 #include <zephyr/drivers/i2c.h>
12 #include <soc.h>
13 #include <i2c_imx.h>
14 #include <zephyr/sys/util.h>
15 #include <zephyr/drivers/pinctrl.h>
16
17 #include <zephyr/logging/log.h>
18 #include <zephyr/irq.h>
19 LOG_MODULE_REGISTER(i2c_imx);
20
21 #include "i2c-priv.h"
22
23 #define DEV_BASE(dev) \
24 ((I2C_Type *)((const struct i2c_imx_config * const)(dev)->config)->base)
25
26 struct i2c_imx_config {
27 I2C_Type *base;
28 void (*irq_config_func)(const struct device *dev);
29 uint32_t bitrate;
30 const struct pinctrl_dev_config *pincfg;
31 };
32
33 struct i2c_master_transfer {
34 const uint8_t *txBuff;
35 volatile uint8_t *rxBuff;
36 volatile uint32_t cmdSize;
37 volatile uint32_t txSize;
38 volatile uint32_t rxSize;
39 volatile bool isBusy;
40 volatile uint32_t currentDir;
41 volatile uint32_t currentMode;
42 volatile bool ack;
43 };
44
45 struct i2c_imx_data {
46 struct i2c_master_transfer transfer;
47 struct k_sem device_sync_sem;
48 };
49
i2c_imx_write(const struct device * dev,uint8_t * txBuffer,uint32_t txSize)50 static bool i2c_imx_write(const struct device *dev, uint8_t *txBuffer,
51 uint32_t txSize)
52 {
53 I2C_Type *base = DEV_BASE(dev);
54 struct i2c_imx_data *data = dev->data;
55 struct i2c_master_transfer *transfer = &data->transfer;
56
57 transfer->isBusy = true;
58
59 /* Clear I2C interrupt flag to avoid spurious interrupt */
60 I2C_ClearStatusFlag(base, i2cStatusInterrupt);
61
62 /* Set I2C work under Tx mode */
63 I2C_SetDirMode(base, i2cDirectionTransmit);
64 transfer->currentDir = i2cDirectionTransmit;
65
66 transfer->txBuff = txBuffer;
67 transfer->txSize = txSize;
68
69 I2C_WriteByte(base, *transfer->txBuff);
70 transfer->txBuff++;
71 transfer->txSize--;
72
73 /* Enable I2C interrupt, subsequent data transfer will be handled
74 * in ISR.
75 */
76 I2C_SetIntCmd(base, true);
77
78 /* Wait for the transfer to complete */
79 k_sem_take(&data->device_sync_sem, K_FOREVER);
80
81 return transfer->ack;
82 }
83
i2c_imx_read(const struct device * dev,uint8_t * rxBuffer,uint32_t rxSize)84 static void i2c_imx_read(const struct device *dev, uint8_t *rxBuffer,
85 uint32_t rxSize)
86 {
87 I2C_Type *base = DEV_BASE(dev);
88 struct i2c_imx_data *data = dev->data;
89 struct i2c_master_transfer *transfer = &data->transfer;
90
91 transfer->isBusy = true;
92
93 /* Clear I2C interrupt flag to avoid spurious interrupt */
94 I2C_ClearStatusFlag(base, i2cStatusInterrupt);
95
96 /* Change to receive state. */
97 I2C_SetDirMode(base, i2cDirectionReceive);
98 transfer->currentDir = i2cDirectionReceive;
99
100 transfer->rxBuff = rxBuffer;
101 transfer->rxSize = rxSize;
102
103 if (transfer->rxSize == 1U) {
104 /* Send Nack */
105 I2C_SetAckBit(base, false);
106 } else {
107 /* Send Ack */
108 I2C_SetAckBit(base, true);
109 }
110
111 /* dummy read to clock in 1st byte */
112 I2C_ReadByte(base);
113
114 /* Enable I2C interrupt, subsequent data transfer will be handled
115 * in ISR.
116 */
117 I2C_SetIntCmd(base, true);
118
119 /* Wait for the transfer to complete */
120 k_sem_take(&data->device_sync_sem, K_FOREVER);
121
122 }
123
i2c_imx_configure(const struct device * dev,uint32_t dev_config_raw)124 static int i2c_imx_configure(const struct device *dev,
125 uint32_t dev_config_raw)
126 {
127 I2C_Type *base = DEV_BASE(dev);
128 struct i2c_imx_data *data = dev->data;
129 struct i2c_master_transfer *transfer = &data->transfer;
130 uint32_t baudrate;
131
132 if (!(I2C_MODE_CONTROLLER & dev_config_raw)) {
133 return -EINVAL;
134 }
135
136 if (I2C_ADDR_10_BITS & dev_config_raw) {
137 return -EINVAL;
138 }
139
140 /* Initialize I2C state structure content. */
141 transfer->txBuff = 0;
142 transfer->rxBuff = 0;
143 transfer->cmdSize = 0U;
144 transfer->txSize = 0U;
145 transfer->rxSize = 0U;
146 transfer->isBusy = false;
147 transfer->currentDir = i2cDirectionReceive;
148 transfer->currentMode = i2cModeSlave;
149
150 switch (I2C_SPEED_GET(dev_config_raw)) {
151 case I2C_SPEED_STANDARD:
152 baudrate = KHZ(100);
153 break;
154 case I2C_SPEED_FAST:
155 baudrate = KHZ(400);
156 break;
157 case I2C_SPEED_FAST_PLUS:
158 baudrate = MHZ(1);
159 break;
160 default:
161 return -EINVAL;
162 }
163
164 /* Setup I2C init structure. */
165 i2c_init_config_t i2cInitConfig = {
166 .baudRate = baudrate,
167 .slaveAddress = 0x00
168 };
169
170 i2cInitConfig.clockRate = get_i2c_clock_freq(base);
171
172 I2C_Init(base, &i2cInitConfig);
173
174 I2C_Enable(base);
175
176 return 0;
177 }
178
i2c_imx_send_addr(const struct device * dev,uint16_t addr,uint8_t flags)179 static int i2c_imx_send_addr(const struct device *dev, uint16_t addr,
180 uint8_t flags)
181 {
182 uint8_t byte0 = addr << 1;
183
184 byte0 |= (flags & I2C_MSG_RW_MASK) == I2C_MSG_READ;
185 return i2c_imx_write(dev, &byte0, 1);
186 }
187
i2c_imx_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)188 static int i2c_imx_transfer(const struct device *dev, struct i2c_msg *msgs,
189 uint8_t num_msgs, uint16_t addr)
190 {
191 I2C_Type *base = DEV_BASE(dev);
192 struct i2c_imx_data *data = dev->data;
193 struct i2c_master_transfer *transfer = &data->transfer;
194 uint16_t timeout = UINT16_MAX;
195 int result = -EIO;
196
197 if (!num_msgs) {
198 return 0;
199 }
200
201 /* Wait until bus not busy */
202 while ((I2C_I2SR_REG(base) & i2cStatusBusBusy) && (--timeout)) {
203 }
204
205 if (timeout == 0U) {
206 return result;
207 }
208
209 /* Make sure we're in a good state so slave recognises the Start */
210 I2C_SetWorkMode(base, i2cModeSlave);
211 transfer->currentMode = i2cModeSlave;
212 /* Switch back to Rx direction. */
213 I2C_SetDirMode(base, i2cDirectionReceive);
214 transfer->currentDir = i2cDirectionReceive;
215 /* Start condition */
216 I2C_SetDirMode(base, i2cDirectionTransmit);
217 transfer->currentDir = i2cDirectionTransmit;
218 I2C_SetWorkMode(base, i2cModeMaster);
219 transfer->currentMode = i2cModeMaster;
220
221 /* Send address after any Start condition */
222 if (!i2c_imx_send_addr(dev, addr, msgs->flags)) {
223 goto finish; /* No ACK received */
224 }
225
226 do {
227 if (msgs->flags & I2C_MSG_RESTART) {
228 I2C_SendRepeatStart(base);
229 if (!i2c_imx_send_addr(dev, addr, msgs->flags)) {
230 goto finish; /* No ACK received */
231 }
232 }
233
234 /* Transfer data */
235 if (msgs->len) {
236 if ((msgs->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) {
237 i2c_imx_read(dev, msgs->buf, msgs->len);
238 } else {
239 if (!i2c_imx_write(dev, msgs->buf, msgs->len)) {
240 goto finish; /* No ACK received */
241 }
242 }
243 }
244
245 if (msgs->flags & I2C_MSG_STOP) {
246 I2C_SetWorkMode(base, i2cModeSlave);
247 transfer->currentMode = i2cModeSlave;
248 I2C_SetDirMode(base, i2cDirectionReceive);
249 transfer->currentDir = i2cDirectionReceive;
250 }
251
252 /* Next message */
253 msgs++;
254 num_msgs--;
255 } while (num_msgs);
256
257 /* Complete without error */
258 result = 0;
259 return result;
260
261 finish:
262 I2C_SetWorkMode(base, i2cModeSlave);
263 transfer->currentMode = i2cModeSlave;
264 I2C_SetDirMode(base, i2cDirectionReceive);
265 transfer->currentDir = i2cDirectionReceive;
266
267 return result;
268 }
269
270
i2c_imx_isr(const struct device * dev)271 static void i2c_imx_isr(const struct device *dev)
272 {
273 I2C_Type *base = DEV_BASE(dev);
274 struct i2c_imx_data *data = dev->data;
275 struct i2c_master_transfer *transfer = &data->transfer;
276
277 /* Clear interrupt flag. */
278 I2C_ClearStatusFlag(base, i2cStatusInterrupt);
279
280
281 /* Exit the ISR if no transfer is happening for this instance. */
282 if (!transfer->isBusy) {
283 return;
284 }
285
286 if (i2cModeMaster == transfer->currentMode) {
287 if (i2cDirectionTransmit == transfer->currentDir) {
288 /* Normal write operation. */
289 transfer->ack =
290 !(I2C_GetStatusFlag(base, i2cStatusReceivedAck));
291
292 if (transfer->txSize == 0U) {
293 /* Close I2C interrupt. */
294 I2C_SetIntCmd(base, false);
295 /* Release I2C Bus. */
296 transfer->isBusy = false;
297 k_sem_give(&data->device_sync_sem);
298 } else {
299 I2C_WriteByte(base, *transfer->txBuff);
300 transfer->txBuff++;
301 transfer->txSize--;
302 }
303 } else {
304 /* Normal read operation. */
305 if (transfer->rxSize == 2U) {
306 /* Send Nack */
307 I2C_SetAckBit(base, false);
308 } else {
309 /* Send Ack */
310 I2C_SetAckBit(base, true);
311 }
312
313 if (transfer->rxSize == 1U) {
314 /* Switch back to Tx direction to avoid
315 * additional I2C bus read.
316 */
317 I2C_SetDirMode(base, i2cDirectionTransmit);
318 transfer->currentDir = i2cDirectionTransmit;
319 }
320
321 *transfer->rxBuff = I2C_ReadByte(base);
322 transfer->rxBuff++;
323 transfer->rxSize--;
324
325 /* receive finished. */
326 if (transfer->rxSize == 0U) {
327 /* Close I2C interrupt. */
328 I2C_SetIntCmd(base, false);
329 /* Release I2C Bus. */
330 transfer->isBusy = false;
331 k_sem_give(&data->device_sync_sem);
332 }
333 }
334 }
335 }
336
i2c_imx_init(const struct device * dev)337 static int i2c_imx_init(const struct device *dev)
338 {
339 const struct i2c_imx_config *config = dev->config;
340 struct i2c_imx_data *data = dev->data;
341 uint32_t bitrate_cfg;
342 int error;
343
344 k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT);
345
346 error = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
347 if (error) {
348 return error;
349 }
350
351 bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);
352
353 error = i2c_imx_configure(dev, I2C_MODE_CONTROLLER | bitrate_cfg);
354 if (error) {
355 return error;
356 }
357
358 config->irq_config_func(dev);
359
360 return 0;
361 }
362
363 static const struct i2c_driver_api i2c_imx_driver_api = {
364 .configure = i2c_imx_configure,
365 .transfer = i2c_imx_transfer,
366 };
367
368 #define I2C_IMX_INIT(n) \
369 PINCTRL_DT_INST_DEFINE(n); \
370 static void i2c_imx_config_func_##n(const struct device *dev); \
371 \
372 static const struct i2c_imx_config i2c_imx_config_##n = { \
373 .base = (I2C_Type *)DT_INST_REG_ADDR(n), \
374 .irq_config_func = i2c_imx_config_func_##n, \
375 .bitrate = DT_INST_PROP(n, clock_frequency), \
376 .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
377 }; \
378 \
379 static struct i2c_imx_data i2c_imx_data_##n; \
380 \
381 I2C_DEVICE_DT_INST_DEFINE(n, \
382 i2c_imx_init, \
383 NULL, \
384 &i2c_imx_data_##n, &i2c_imx_config_##n, \
385 POST_KERNEL, \
386 CONFIG_I2C_INIT_PRIORITY, \
387 &i2c_imx_driver_api); \
388 \
389 static void i2c_imx_config_func_##n(const struct device *dev) \
390 { \
391 ARG_UNUSED(dev); \
392 \
393 IRQ_CONNECT(DT_INST_IRQN(n), \
394 DT_INST_IRQ(n, priority), \
395 i2c_imx_isr, DEVICE_DT_INST_GET(n), 0); \
396 \
397 irq_enable(DT_INST_IRQN(n)); \
398 }
399
400 DT_INST_FOREACH_STATUS_OKAY(I2C_IMX_INIT)
401