1 /*
2 * Copyright (c), 2023 Basalte bv
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT nxp_sc18im704_i2c
8
9 #include <errno.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/device.h>
12 #include <zephyr/init.h>
13 #include <zephyr/drivers/gpio.h>
14 #include <zephyr/drivers/i2c.h>
15 #include <zephyr/drivers/uart.h>
16
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(i2c_sc18im, CONFIG_I2C_LOG_LEVEL);
19
20 #include "i2c_sc18im704.h"
21
22 struct i2c_sc18im_config {
23 const struct device *bus;
24 uint32_t bus_speed;
25 const struct gpio_dt_spec reset_gpios;
26 };
27
28 struct i2c_sc18im_data {
29 struct k_mutex lock;
30 uint32_t i2c_config;
31 };
32
sc18im704_claim(const struct device * dev)33 int sc18im704_claim(const struct device *dev)
34 {
35 struct i2c_sc18im_data *data = dev->data;
36
37 return k_mutex_lock(&data->lock, K_FOREVER);
38 }
39
sc18im704_release(const struct device * dev)40 int sc18im704_release(const struct device *dev)
41 {
42 struct i2c_sc18im_data *data = dev->data;
43
44 return k_mutex_unlock(&data->lock);
45 }
46
sc18im704_transfer(const struct device * dev,const uint8_t * tx_data,uint8_t tx_len,uint8_t * rx_data,uint8_t rx_len)47 int sc18im704_transfer(const struct device *dev,
48 const uint8_t *tx_data, uint8_t tx_len,
49 uint8_t *rx_data, uint8_t rx_len)
50 {
51 const struct i2c_sc18im_config *cfg = dev->config;
52 struct i2c_sc18im_data *data = dev->data;
53 int ret = 0;
54
55 ret = k_mutex_lock(&data->lock, K_FOREVER);
56 if (ret < 0) {
57 return ret;
58 }
59
60 if (tx_data != NULL) {
61 for (uint8_t i = 0; i < tx_len; ++i) {
62 uart_poll_out(cfg->bus, tx_data[i]);
63 }
64 }
65
66 if (rx_data != NULL) {
67 uint64_t end;
68
69 for (uint8_t i = 0; i < rx_len && ret == 0; ++i) {
70 /* Make sure we don't wait forever */
71 end = sys_clock_timeout_end_calc(K_SECONDS(1));
72
73 do {
74 ret = uart_poll_in(cfg->bus, &rx_data[i]);
75 } while (ret == -1 && end > k_uptime_ticks());
76 }
77
78 /* -1 indicates we timed out */
79 ret = ret == -1 ? -EAGAIN : ret;
80
81 if (ret < 0) {
82 LOG_ERR("Failed to read data (%d)", ret);
83 }
84 }
85
86 k_mutex_unlock(&data->lock);
87
88 return ret;
89 }
90
i2c_sc18im_configure(const struct device * dev,uint32_t config)91 static int i2c_sc18im_configure(const struct device *dev, uint32_t config)
92 {
93 struct i2c_sc18im_data *data = dev->data;
94
95 if (!(I2C_MODE_CONTROLLER & config)) {
96 return -EINVAL;
97 }
98
99 if (I2C_ADDR_10_BITS & config) {
100 return -EINVAL;
101 }
102
103 if (I2C_SPEED_GET(config) != I2C_SPEED_GET(data->i2c_config)) {
104 uint8_t buf[] = {
105 SC18IM704_CMD_WRITE_REG,
106 SC18IM704_REG_I2C_CLK_L,
107 0,
108 SC18IM704_CMD_STOP,
109 };
110 int ret;
111
112 /* CLK value is calculated as 15000000 / (8 * freq), see datasheet */
113 switch (I2C_SPEED_GET(config)) {
114 case I2C_SPEED_STANDARD:
115 buf[2] = 0x13; /* 99 kHz */
116 break;
117 case I2C_SPEED_FAST:
118 buf[2] = 0x05; /* 375 kHz */
119 break;
120 default:
121 return -EINVAL;
122 }
123
124 ret = sc18im704_transfer(dev, buf, sizeof(buf), NULL, 0);
125 if (ret < 0) {
126 LOG_ERR("Failed to set I2C speed (%d)", ret);
127 return -EIO;
128 }
129 }
130
131 data->i2c_config = config;
132
133 return 0;
134 }
135
i2c_sc18im_get_config(const struct device * dev,uint32_t * config)136 static int i2c_sc18im_get_config(const struct device *dev, uint32_t *config)
137 {
138 struct i2c_sc18im_data *data = dev->data;
139
140 *config = data->i2c_config;
141
142 return 0;
143 }
144
i2c_sc18im_transfer_msg(const struct device * dev,struct i2c_msg * msg,uint16_t addr)145 static int i2c_sc18im_transfer_msg(const struct device *dev,
146 struct i2c_msg *msg,
147 uint16_t addr)
148 {
149 uint8_t start[] = {
150 SC18IM704_CMD_I2C_START,
151 0x00,
152 0x00,
153 };
154 uint8_t stop = SC18IM704_CMD_STOP;
155 int ret;
156
157 if (msg->flags & I2C_MSG_ADDR_10_BITS || msg->len > UINT8_MAX) {
158 return -EINVAL;
159 }
160
161 start[1] = addr | (msg->flags & I2C_MSG_RW_MASK);
162 start[2] = msg->len;
163
164 ret = sc18im704_transfer(dev, start, sizeof(start), NULL, 0);
165 if (ret < 0) {
166 return ret;
167 }
168
169 if (msg->flags & I2C_MSG_READ) {
170 /* Send the stop character before reading */
171 ret = sc18im704_transfer(dev, &stop, 1, msg->buf, msg->len);
172 if (ret < 0) {
173 return ret;
174 }
175
176 } else {
177 ret = sc18im704_transfer(dev, msg->buf, msg->len, NULL, 0);
178 if (ret < 0) {
179 return ret;
180 }
181
182 if (msg->flags & I2C_MSG_STOP) {
183 ret = sc18im704_transfer(dev, &stop, 1, NULL, 0);
184 if (ret < 0) {
185 return ret;
186 }
187 }
188 }
189
190 return 0;
191 }
192
i2c_sc18im_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)193 static int i2c_sc18im_transfer(const struct device *dev,
194 struct i2c_msg *msgs,
195 uint8_t num_msgs, uint16_t addr)
196 {
197 int ret;
198
199 if (num_msgs == 0) {
200 return 0;
201 }
202
203 ret = sc18im704_claim(dev);
204 if (ret < 0) {
205 LOG_ERR("Failed to claim I2C bridge (%d)", ret);
206 return ret;
207 }
208
209 for (uint8_t i = 0; i < num_msgs && ret == 0; ++i) {
210 ret = i2c_sc18im_transfer_msg(dev, &msgs[i], addr);
211 }
212
213 #ifdef CONFIG_I2C_SC18IM704_VERIFY
214 if (ret == 0) {
215 uint8_t buf[] = {
216 SC18IM704_CMD_READ_REG,
217 SC18IM704_REG_I2C_STAT,
218 SC18IM704_CMD_STOP,
219 };
220 uint8_t data;
221
222 ret = sc18im704_transfer(dev, buf, sizeof(buf), &data, 1);
223
224 if (ret == 0 && data != SC18IM704_I2C_STAT_OK) {
225 ret = -EIO;
226 }
227 }
228 #endif /* CONFIG_I2C_SC18IM704_VERIFY */
229
230 sc18im704_release(dev);
231
232 return ret;
233 }
234
i2c_sc18im_init(const struct device * dev)235 static int i2c_sc18im_init(const struct device *dev)
236 {
237 const struct i2c_sc18im_config *cfg = dev->config;
238 struct i2c_sc18im_data *data = dev->data;
239 int ret;
240
241 /* The device baudrate after reset is 9600 */
242 struct uart_config uart_cfg = {
243 .baudrate = 9600,
244 .parity = UART_CFG_PARITY_NONE,
245 .stop_bits = UART_CFG_STOP_BITS_1,
246 .data_bits = UART_CFG_DATA_BITS_8,
247 .flow_ctrl = UART_CFG_FLOW_CTRL_NONE,
248 };
249
250 k_mutex_init(&data->lock);
251
252 if (!device_is_ready(cfg->bus)) {
253 LOG_ERR("UART bus not ready");
254 return -ENODEV;
255 }
256
257 ret = uart_configure(cfg->bus, &uart_cfg);
258 if (ret < 0) {
259 LOG_ERR("Failed to configure UART (%d)", ret);
260 return ret;
261 }
262
263 if (cfg->reset_gpios.port) {
264 uint8_t buf[2];
265
266 if (!device_is_ready(cfg->reset_gpios.port)) {
267 LOG_ERR("Reset GPIO device not ready");
268 return -ENODEV;
269 }
270
271 ret = gpio_pin_configure_dt(&cfg->reset_gpios, GPIO_OUTPUT_ACTIVE);
272 if (ret < 0) {
273 LOG_ERR("Failed to configure reset GPIO (%d)", ret);
274 return ret;
275 }
276
277 ret = gpio_pin_set_dt(&cfg->reset_gpios, 0);
278 if (ret < 0) {
279 LOG_ERR("Failed to set reset GPIO (%d)", ret);
280 return ret;
281 }
282
283 /* The device sends "OK" */
284 ret = sc18im704_transfer(dev, NULL, 0, buf, sizeof(buf));
285 if (ret < 0) {
286 LOG_ERR("Failed to get OK (%d)", ret);
287 return ret;
288 }
289 }
290
291 if (cfg->bus_speed != 9600) {
292 uint16_t brg = (7372800 / cfg->bus_speed) - 16;
293 uint8_t buf[] = {
294 SC18IM704_CMD_WRITE_REG,
295 SC18IM704_REG_BRG0,
296 brg & 0xff,
297 SC18IM704_REG_BRG1,
298 brg >> 8,
299 SC18IM704_CMD_STOP,
300 };
301
302 ret = sc18im704_transfer(dev, buf, sizeof(buf), NULL, 0);
303 if (ret < 0) {
304 LOG_ERR("Failed to set baudrate (%d)", ret);
305 return ret;
306 }
307
308 /* Make sure UART buffer is sent */
309 k_msleep(1);
310
311 /* Re-configure the UART controller with the new baudrate */
312 uart_cfg.baudrate = cfg->bus_speed;
313 ret = uart_configure(cfg->bus, &uart_cfg);
314 if (ret < 0) {
315 LOG_ERR("Failed to re-configure UART (%d)", ret);
316 return ret;
317 }
318 }
319
320 return 0;
321 }
322
323 static const struct i2c_driver_api i2c_sc18im_driver_api = {
324 .configure = i2c_sc18im_configure,
325 .get_config = i2c_sc18im_get_config,
326 .transfer = i2c_sc18im_transfer,
327 };
328
329 #define I2C_SC18IM_DEFINE(n) \
330 \
331 static const struct i2c_sc18im_config i2c_sc18im_config_##n = { \
332 .bus = DEVICE_DT_GET(DT_BUS(DT_INST_PARENT(n))), \
333 .bus_speed = DT_PROP_OR(DT_INST_PARENT(n), target_speed, 9600), \
334 .reset_gpios = GPIO_DT_SPEC_GET_OR(DT_INST_PARENT(n), reset_gpios, {0}), \
335 }; \
336 static struct i2c_sc18im_data i2c_sc18im_data_##n = { \
337 .i2c_config = I2C_MODE_CONTROLLER | (I2C_SPEED_STANDARD << I2C_SPEED_SHIFT), \
338 }; \
339 \
340 DEVICE_DT_INST_DEFINE(n, i2c_sc18im_init, NULL, \
341 &i2c_sc18im_data_##n, &i2c_sc18im_config_##n, \
342 POST_KERNEL, CONFIG_I2C_SC18IM704_INIT_PRIORITY, \
343 &i2c_sc18im_driver_api);
344
345 DT_INST_FOREACH_STATUS_OKAY(I2C_SC18IM_DEFINE)
346