1 /*
2 * Copyright (c) 2016 Freescale Semiconductor, Inc.
3 * Copyright (c) 2019, NXP
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #define DT_DRV_COMPAT nxp_imx_lpi2c
9
10 #include <errno.h>
11 #include <drivers/i2c.h>
12 #include <drivers/clock_control.h>
13 #include <fsl_lpi2c.h>
14
15 #include <logging/log.h>
16 LOG_MODULE_REGISTER(mcux_lpi2c);
17
18 #include "i2c-priv.h"
19 /* Wait for the duration of 12 bits to detect a NAK after a bus
20 * address scan. (10 appears sufficient, 20% safety factor.)
21 */
22 #define SCAN_DELAY_US(baudrate) (12 * USEC_PER_SEC / baudrate)
23
24 struct mcux_lpi2c_config {
25 LPI2C_Type *base;
26 const struct device *clock_dev;
27 clock_control_subsys_t clock_subsys;
28 void (*irq_config_func)(const struct device *dev);
29 uint32_t bitrate;
30 uint32_t bus_idle_timeout_ns;
31 };
32
33 struct mcux_lpi2c_data {
34 lpi2c_master_handle_t handle;
35 struct k_sem lock;
36 struct k_sem device_sync_sem;
37 status_t callback_status;
38 };
39
mcux_lpi2c_configure(const struct device * dev,uint32_t dev_config_raw)40 static int mcux_lpi2c_configure(const struct device *dev,
41 uint32_t dev_config_raw)
42 {
43 const struct mcux_lpi2c_config *config = dev->config;
44 struct mcux_lpi2c_data *data = dev->data;
45 LPI2C_Type *base = config->base;
46 uint32_t clock_freq;
47 uint32_t baudrate;
48 int ret;
49
50 if (!(I2C_MODE_MASTER & dev_config_raw)) {
51 return -EINVAL;
52 }
53
54 if (I2C_ADDR_10_BITS & dev_config_raw) {
55 return -EINVAL;
56 }
57
58 switch (I2C_SPEED_GET(dev_config_raw)) {
59 case I2C_SPEED_STANDARD:
60 baudrate = KHZ(100);
61 break;
62 case I2C_SPEED_FAST:
63 baudrate = KHZ(400);
64 break;
65 case I2C_SPEED_FAST_PLUS:
66 baudrate = MHZ(1);
67 break;
68 default:
69 return -EINVAL;
70 }
71
72 if (clock_control_get_rate(config->clock_dev, config->clock_subsys,
73 &clock_freq)) {
74 return -EINVAL;
75 }
76
77 ret = k_sem_take(&data->lock, K_FOREVER);
78 if (ret) {
79 return ret;
80 }
81
82 LPI2C_MasterSetBaudRate(base, clock_freq, baudrate);
83 k_sem_give(&data->lock);
84
85 return 0;
86 }
87
mcux_lpi2c_master_transfer_callback(LPI2C_Type * base,lpi2c_master_handle_t * handle,status_t status,void * userData)88 static void mcux_lpi2c_master_transfer_callback(LPI2C_Type *base,
89 lpi2c_master_handle_t *handle,
90 status_t status, void *userData)
91 {
92 struct mcux_lpi2c_data *data = userData;
93
94 ARG_UNUSED(handle);
95 ARG_UNUSED(base);
96
97 data->callback_status = status;
98 k_sem_give(&data->device_sync_sem);
99 }
100
mcux_lpi2c_convert_flags(int msg_flags)101 static uint32_t mcux_lpi2c_convert_flags(int msg_flags)
102 {
103 uint32_t flags = 0U;
104
105 if (!(msg_flags & I2C_MSG_STOP)) {
106 flags |= kLPI2C_TransferNoStopFlag;
107 }
108
109 if (msg_flags & I2C_MSG_RESTART) {
110 flags |= kLPI2C_TransferRepeatedStartFlag;
111 }
112
113 return flags;
114 }
115
mcux_lpi2c_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)116 static int mcux_lpi2c_transfer(const struct device *dev, struct i2c_msg *msgs,
117 uint8_t num_msgs, uint16_t addr)
118 {
119 const struct mcux_lpi2c_config *config = dev->config;
120 struct mcux_lpi2c_data *data = dev->data;
121 LPI2C_Type *base = config->base;
122 lpi2c_master_transfer_t transfer;
123 status_t status;
124 int ret = 0;
125
126 ret = k_sem_take(&data->lock, K_FOREVER);
127 if (ret) {
128 return ret;
129 }
130
131 /* Iterate over all the messages */
132 for (int i = 0; i < num_msgs; i++) {
133 if (I2C_MSG_ADDR_10_BITS & msgs->flags) {
134 ret = -ENOTSUP;
135 break;
136 }
137
138 /* Initialize the transfer descriptor */
139 transfer.flags = mcux_lpi2c_convert_flags(msgs->flags);
140
141 /* Prevent the controller to send a start condition between
142 * messages, except if explicitly requested.
143 */
144 if (i != 0 && !(msgs->flags & I2C_MSG_RESTART)) {
145 transfer.flags |= kLPI2C_TransferNoStartFlag;
146 }
147
148 transfer.slaveAddress = addr;
149 transfer.direction = (msgs->flags & I2C_MSG_READ)
150 ? kLPI2C_Read : kLPI2C_Write;
151 transfer.subaddress = 0;
152 transfer.subaddressSize = 0;
153 transfer.data = msgs->buf;
154 transfer.dataSize = msgs->len;
155
156 /* Start the transfer */
157 status = LPI2C_MasterTransferNonBlocking(base,
158 &data->handle, &transfer);
159
160 /* Return an error if the transfer didn't start successfully
161 * e.g., if the bus was busy
162 */
163 if (status != kStatus_Success) {
164 LPI2C_MasterTransferAbort(base, &data->handle);
165 ret = -EIO;
166 break;
167 }
168
169 /* Wait for the transfer to complete */
170 k_sem_take(&data->device_sync_sem, K_FOREVER);
171
172 /* Return an error if the transfer didn't complete
173 * successfully. e.g., nak, timeout, lost arbitration
174 */
175 if (data->callback_status != kStatus_Success) {
176 LPI2C_MasterTransferAbort(base, &data->handle);
177 ret = -EIO;
178 break;
179 }
180 if (msgs->len == 0) {
181 k_busy_wait(SCAN_DELAY_US(config->bitrate));
182 if (0 != (base->MSR & LPI2C_MSR_NDF_MASK)) {
183 LPI2C_MasterTransferAbort(base, &data->handle);
184 ret = -EIO;
185 break;
186 }
187 }
188 /* Move to the next message */
189 msgs++;
190 }
191
192 k_sem_give(&data->lock);
193
194 return ret;
195 }
196
mcux_lpi2c_isr(const struct device * dev)197 static void mcux_lpi2c_isr(const struct device *dev)
198 {
199 const struct mcux_lpi2c_config *config = dev->config;
200 struct mcux_lpi2c_data *data = dev->data;
201 LPI2C_Type *base = config->base;
202
203 LPI2C_MasterTransferHandleIRQ(base, &data->handle);
204 }
205
mcux_lpi2c_init(const struct device * dev)206 static int mcux_lpi2c_init(const struct device *dev)
207 {
208 const struct mcux_lpi2c_config *config = dev->config;
209 struct mcux_lpi2c_data *data = dev->data;
210 LPI2C_Type *base = config->base;
211 uint32_t clock_freq, bitrate_cfg;
212 lpi2c_master_config_t master_config;
213 int error;
214
215 k_sem_init(&data->lock, 1, 1);
216 k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT);
217 if (clock_control_get_rate(config->clock_dev, config->clock_subsys,
218 &clock_freq)) {
219 return -EINVAL;
220 }
221
222 LPI2C_MasterGetDefaultConfig(&master_config);
223 master_config.busIdleTimeout_ns = config->bus_idle_timeout_ns;
224 LPI2C_MasterInit(base, &master_config, clock_freq);
225 LPI2C_MasterTransferCreateHandle(base, &data->handle,
226 mcux_lpi2c_master_transfer_callback,
227 data);
228
229 bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);
230
231 error = mcux_lpi2c_configure(dev, I2C_MODE_MASTER | bitrate_cfg);
232 if (error) {
233 return error;
234 }
235
236 config->irq_config_func(dev);
237
238 return 0;
239 }
240
241 static const struct i2c_driver_api mcux_lpi2c_driver_api = {
242 .configure = mcux_lpi2c_configure,
243 .transfer = mcux_lpi2c_transfer,
244 };
245
246 #define I2C_MCUX_LPI2C_INIT(n) \
247 static void mcux_lpi2c_config_func_##n(const struct device *dev); \
248 \
249 static const struct mcux_lpi2c_config mcux_lpi2c_config_##n = { \
250 .base = (LPI2C_Type *)DT_INST_REG_ADDR(n), \
251 .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
252 .clock_subsys = \
253 (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name),\
254 .irq_config_func = mcux_lpi2c_config_func_##n, \
255 .bitrate = DT_INST_PROP(n, clock_frequency), \
256 .bus_idle_timeout_ns = \
257 UTIL_AND(DT_INST_NODE_HAS_PROP(n, bus_idle_timeout),\
258 DT_INST_PROP(n, bus_idle_timeout)), \
259 }; \
260 \
261 static struct mcux_lpi2c_data mcux_lpi2c_data_##n; \
262 \
263 DEVICE_DT_INST_DEFINE(n, &mcux_lpi2c_init, NULL, \
264 &mcux_lpi2c_data_##n, \
265 &mcux_lpi2c_config_##n, POST_KERNEL, \
266 CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
267 &mcux_lpi2c_driver_api); \
268 \
269 static void mcux_lpi2c_config_func_##n(const struct device *dev) \
270 { \
271 IRQ_CONNECT(DT_INST_IRQN(n), \
272 DT_INST_IRQ(n, priority), \
273 mcux_lpi2c_isr, \
274 DEVICE_DT_INST_GET(n), 0); \
275 \
276 irq_enable(DT_INST_IRQN(n)); \
277 }
278
279 DT_INST_FOREACH_STATUS_OKAY(I2C_MCUX_LPI2C_INIT)
280