1 /*
2 * Copyright (c) 2016 Freescale Semiconductor, Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT nxp_kinetis_i2c
8
9 #include <errno.h>
10 #include <zephyr/drivers/i2c.h>
11 #include <zephyr/kernel.h>
12 #include <soc.h>
13 #include <fsl_i2c.h>
14 #include <fsl_clock.h>
15 #include <zephyr/sys/util.h>
16
17 #include <zephyr/drivers/pinctrl.h>
18
19 #include <zephyr/logging/log.h>
20 #include <zephyr/irq.h>
21 LOG_MODULE_REGISTER(i2c_mcux);
22
23 #include "i2c-priv.h"
24
25 #define DEV_BASE(dev) \
26 ((I2C_Type *)((const struct i2c_mcux_config * const)(dev)->config)->base)
27
28 struct i2c_mcux_config {
29 I2C_Type *base;
30 clock_name_t clock_source;
31 void (*irq_config_func)(const struct device *dev);
32 uint32_t bitrate;
33 const struct pinctrl_dev_config *pincfg;
34 };
35
36 struct i2c_mcux_data {
37 i2c_master_handle_t handle;
38 struct k_sem lock;
39 struct k_sem device_sync_sem;
40 status_t callback_status;
41 #ifdef CONFIG_I2C_CALLBACK
42 uint16_t addr;
43 uint32_t msg;
44 struct i2c_msg *msgs;
45 uint32_t num_msgs;
46 i2c_callback_t cb;
47 void *userdata;
48 #endif /* CONFIG_I2C_CALLBACK */
49 };
50
i2c_mcux_configure(const struct device * dev,uint32_t dev_config_raw)51 static int i2c_mcux_configure(const struct device *dev,
52 uint32_t dev_config_raw)
53 {
54 I2C_Type *base = DEV_BASE(dev);
55 struct i2c_mcux_data *data = dev->data;
56 const struct i2c_mcux_config *config = dev->config;
57 uint32_t clock_freq;
58 uint32_t baudrate;
59
60 if (!(I2C_MODE_CONTROLLER & dev_config_raw)) {
61 return -EINVAL;
62 }
63
64 if (I2C_ADDR_10_BITS & dev_config_raw) {
65 return -EINVAL;
66 }
67
68 switch (I2C_SPEED_GET(dev_config_raw)) {
69 case I2C_SPEED_STANDARD:
70 baudrate = KHZ(100);
71 break;
72 case I2C_SPEED_FAST:
73 baudrate = KHZ(400);
74 break;
75 case I2C_SPEED_FAST_PLUS:
76 baudrate = MHZ(1);
77 break;
78 default:
79 return -EINVAL;
80 }
81
82 clock_freq = CLOCK_GetFreq(config->clock_source);
83 k_sem_take(&data->lock, K_FOREVER);
84 I2C_MasterSetBaudRate(base, baudrate, clock_freq);
85 k_sem_give(&data->lock);
86
87 return 0;
88 }
89
90 #ifdef CONFIG_I2C_CALLBACK
91
92 static void i2c_mcux_async_done(const struct device *dev, struct i2c_mcux_data *data, int result);
93 static void i2c_mcux_async_iter(const struct device *dev);
94
95 #endif
96
i2c_mcux_master_transfer_callback(I2C_Type * base,i2c_master_handle_t * handle,status_t status,void * userdata)97 static void i2c_mcux_master_transfer_callback(I2C_Type *base,
98 i2c_master_handle_t *handle,
99 status_t status, void *userdata)
100 {
101
102 ARG_UNUSED(handle);
103 ARG_UNUSED(base);
104
105 struct device *dev = userdata;
106 struct i2c_mcux_data *data = dev->data;
107
108 #ifdef CONFIG_I2C_CALLBACK
109 if (data->cb != NULL) {
110 /* Async transfer */
111 if (status != kStatus_Success) {
112 I2C_MasterTransferAbort(base, &data->handle);
113 i2c_mcux_async_done(dev, data, -EIO);
114 } else if (data->msg == data->num_msgs - 1) {
115 i2c_mcux_async_done(dev, data, 0);
116 } else {
117 data->msg++;
118 i2c_mcux_async_iter(dev);
119 }
120 return;
121 }
122 #endif /* CONFIG_I2C_CALLBACK */
123
124 data->callback_status = status;
125
126 k_sem_give(&data->device_sync_sem);
127 }
128
i2c_mcux_convert_flags(int msg_flags)129 static uint32_t i2c_mcux_convert_flags(int msg_flags)
130 {
131 uint32_t flags = 0U;
132
133 if (!(msg_flags & I2C_MSG_STOP)) {
134 flags |= kI2C_TransferNoStopFlag;
135 }
136
137 if (msg_flags & I2C_MSG_RESTART) {
138 flags |= kI2C_TransferRepeatedStartFlag;
139 }
140
141 return flags;
142 }
143
i2c_mcux_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)144 static int i2c_mcux_transfer(const struct device *dev, struct i2c_msg *msgs,
145 uint8_t num_msgs, uint16_t addr)
146 {
147 I2C_Type *base = DEV_BASE(dev);
148 struct i2c_mcux_data *data = dev->data;
149 i2c_master_transfer_t transfer;
150 status_t status;
151 int ret = 0;
152
153 k_sem_take(&data->lock, K_FOREVER);
154
155 /* Iterate over all the messages */
156 for (int i = 0; i < num_msgs; i++) {
157 if (I2C_MSG_ADDR_10_BITS & msgs->flags) {
158 ret = -ENOTSUP;
159 break;
160 }
161
162 /* Initialize the transfer descriptor */
163 transfer.flags = i2c_mcux_convert_flags(msgs->flags);
164 transfer.slaveAddress = addr;
165 transfer.direction = (msgs->flags & I2C_MSG_READ)
166 ? kI2C_Read : kI2C_Write;
167 transfer.subaddress = 0;
168 transfer.subaddressSize = 0;
169 transfer.data = msgs->buf;
170 transfer.dataSize = msgs->len;
171
172 /* Prevent the controller to send a start condition between
173 * messages, except if explicitly requested.
174 */
175 if (i != 0 && !(msgs->flags & I2C_MSG_RESTART)) {
176 transfer.flags |= kI2C_TransferNoStartFlag;
177 }
178
179 /* Start the transfer */
180 status = I2C_MasterTransferNonBlocking(base,
181 &data->handle, &transfer);
182
183 /* Return an error if the transfer didn't start successfully
184 * e.g., if the bus was busy
185 */
186 if (status != kStatus_Success) {
187 I2C_MasterTransferAbort(base, &data->handle);
188 ret = -EIO;
189 break;
190 }
191
192 /* Wait for the transfer to complete */
193 k_sem_take(&data->device_sync_sem, K_FOREVER);
194
195 /* Return an error if the transfer didn't complete
196 * successfully. e.g., nak, timeout, lost arbitration
197 */
198 if (data->callback_status != kStatus_Success) {
199 I2C_MasterTransferAbort(base, &data->handle);
200 ret = -EIO;
201 break;
202 }
203
204 /* Move to the next message */
205 msgs++;
206 }
207
208 k_sem_give(&data->lock);
209
210 return ret;
211 }
212
213 #ifdef CONFIG_I2C_CALLBACK
214
i2c_mcux_async_done(const struct device * dev,struct i2c_mcux_data * data,int result)215 static void i2c_mcux_async_done(const struct device *dev, struct i2c_mcux_data *data, int result)
216 {
217
218 i2c_callback_t cb = data->cb;
219 void *userdata = data->userdata;
220
221 data->msg = 0;
222 data->msgs = NULL;
223 data->num_msgs = 0;
224 data->cb = NULL;
225 data->userdata = NULL;
226 data->addr = 0;
227
228 k_sem_give(&data->lock);
229
230 /* Callback may wish to start another transfer */
231 cb(dev, result, userdata);
232 }
233
234 /* Start a transfer asynchronously */
i2c_mcux_async_iter(const struct device * dev)235 static void i2c_mcux_async_iter(const struct device *dev)
236 {
237 I2C_Type *base = DEV_BASE(dev);
238 struct i2c_mcux_data *data = dev->data;
239 i2c_master_transfer_t transfer;
240 status_t status;
241 struct i2c_msg *msg = &data->msgs[data->msg];
242
243 if (I2C_MSG_ADDR_10_BITS & msg->flags) {
244 i2c_mcux_async_done(dev, data, -ENOTSUP);
245 return;
246 }
247
248 /* Initialize the transfer descriptor */
249 transfer.flags = i2c_mcux_convert_flags(msg->flags);
250 transfer.slaveAddress = data->addr;
251 transfer.direction = (msg->flags & I2C_MSG_READ) ? kI2C_Read : kI2C_Write;
252 transfer.subaddress = 0;
253 transfer.subaddressSize = 0;
254 transfer.data = msg->buf;
255 transfer.dataSize = msg->len;
256
257 /* Prevent the controller to send a start condition between
258 * messages, except if explicitly requested.
259 */
260 if (data->msg != 0 && !(msg->flags & I2C_MSG_RESTART)) {
261 transfer.flags |= kI2C_TransferNoStartFlag;
262 }
263
264 /* Start the transfer */
265 status = I2C_MasterTransferNonBlocking(base, &data->handle, &transfer);
266
267 /* Return an error if the transfer didn't start successfully
268 * e.g., if the bus was busy
269 */
270 if (status != kStatus_Success) {
271 I2C_MasterTransferAbort(base, &data->handle);
272 i2c_mcux_async_done(dev, data, -EIO);
273 }
274 }
275
i2c_mcux_transfer_cb(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr,i2c_callback_t cb,void * userdata)276 static int i2c_mcux_transfer_cb(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs,
277 uint16_t addr, i2c_callback_t cb, void *userdata)
278 {
279 struct i2c_mcux_data *data = dev->data;
280
281 int res = k_sem_take(&data->lock, K_NO_WAIT);
282
283 if (res != 0) {
284 return -EWOULDBLOCK;
285 }
286
287 data->msg = 0;
288 data->msgs = msgs;
289 data->num_msgs = num_msgs;
290 data->addr = addr;
291 data->cb = cb;
292 data->userdata = userdata;
293 data->addr = addr;
294
295 i2c_mcux_async_iter(dev);
296
297 return 0;
298 }
299
300 #endif /* CONFIG_I2C_CALLBACK */
301
i2c_mcux_isr(const struct device * dev)302 static void i2c_mcux_isr(const struct device *dev)
303 {
304 I2C_Type *base = DEV_BASE(dev);
305 struct i2c_mcux_data *data = dev->data;
306
307 I2C_MasterTransferHandleIRQ(base, &data->handle);
308 }
309
i2c_mcux_init(const struct device * dev)310 static int i2c_mcux_init(const struct device *dev)
311 {
312 I2C_Type *base = DEV_BASE(dev);
313 const struct i2c_mcux_config *config = dev->config;
314 struct i2c_mcux_data *data = dev->data;
315 uint32_t clock_freq, bitrate_cfg;
316 i2c_master_config_t master_config;
317 int error;
318
319 k_sem_init(&data->lock, 1, 1);
320 k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT);
321
322 clock_freq = CLOCK_GetFreq(config->clock_source);
323 I2C_MasterGetDefaultConfig(&master_config);
324 I2C_MasterInit(base, &master_config, clock_freq);
325 I2C_MasterTransferCreateHandle(base, &data->handle,
326 i2c_mcux_master_transfer_callback, (void *)dev);
327
328 bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);
329
330 error = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
331 if (error) {
332 return error;
333 }
334
335 error = i2c_mcux_configure(dev, I2C_MODE_CONTROLLER | bitrate_cfg);
336 if (error) {
337 return error;
338 }
339
340 config->irq_config_func(dev);
341
342 return 0;
343 }
344
345 static DEVICE_API(i2c, i2c_mcux_driver_api) = {
346 .configure = i2c_mcux_configure,
347 .transfer = i2c_mcux_transfer,
348 #ifdef CONFIG_I2C_CALLBACK
349 .transfer_cb = i2c_mcux_transfer_cb,
350 #endif
351 #ifdef CONFIG_I2C_RTIO
352 .iodev_submit = i2c_iodev_submit_fallback,
353 #endif
354 };
355
356 #define I2C_DEVICE_INIT_MCUX(n) \
357 PINCTRL_DT_INST_DEFINE(n); \
358 \
359 static void i2c_mcux_config_func_ ## n(const struct device *dev); \
360 \
361 static const struct i2c_mcux_config i2c_mcux_config_ ## n = { \
362 .base = (I2C_Type *)DT_INST_REG_ADDR(n),\
363 .clock_source = I2C ## n ## _CLK_SRC, \
364 .irq_config_func = i2c_mcux_config_func_ ## n, \
365 .bitrate = DT_INST_PROP(n, clock_frequency), \
366 .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
367 }; \
368 \
369 static struct i2c_mcux_data i2c_mcux_data_ ## n; \
370 \
371 I2C_DEVICE_DT_INST_DEFINE(n, \
372 i2c_mcux_init, NULL, \
373 &i2c_mcux_data_ ## n, \
374 &i2c_mcux_config_ ## n, POST_KERNEL, \
375 CONFIG_I2C_INIT_PRIORITY, \
376 &i2c_mcux_driver_api); \
377 \
378 static void i2c_mcux_config_func_ ## n(const struct device *dev) \
379 { \
380 IRQ_CONNECT(DT_INST_IRQN(n), \
381 DT_INST_IRQ(n, priority), \
382 i2c_mcux_isr, \
383 DEVICE_DT_INST_GET(n), 0); \
384 \
385 irq_enable(DT_INST_IRQN(n)); \
386 }
387
388 DT_INST_FOREACH_STATUS_OKAY(I2C_DEVICE_INIT_MCUX)
389