1 /*
2 * Copyright (c) 2020, Seagate Technology LLC
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT nxp_lpc11u6x_i2c
8
9 #include <zephyr/kernel.h>
10 #include <zephyr/drivers/i2c.h>
11 #include <zephyr/drivers/clock_control.h>
12 #include <zephyr/irq.h>
13 #include "i2c_lpc11u6x.h"
14
15 #define DEV_BASE(dev) (((struct lpc11u6x_i2c_config *)(dev->config))->base)
16
lpc11u6x_i2c_set_bus_speed(const struct lpc11u6x_i2c_config * cfg,const struct device * clk_dev,uint32_t speed)17 static void lpc11u6x_i2c_set_bus_speed(const struct lpc11u6x_i2c_config *cfg,
18 const struct device *clk_dev,
19 uint32_t speed)
20 {
21 uint32_t clk, div;
22
23 clock_control_get_rate(clk_dev, (clock_control_subsys_t) cfg->clkid,
24 &clk);
25 div = clk / speed;
26
27 cfg->base->sclh = div / 2;
28 cfg->base->scll = div - (div / 2);
29 }
30
lpc11u6x_i2c_configure(const struct device * dev,uint32_t dev_config)31 static int lpc11u6x_i2c_configure(const struct device *dev,
32 uint32_t dev_config)
33 {
34 const struct lpc11u6x_i2c_config *cfg = dev->config;
35 struct lpc11u6x_i2c_data *data = dev->data;
36 uint32_t speed;
37 int ret;
38 uint8_t mux_selection = PINCTRL_STATE_DEFAULT;
39
40 switch (I2C_SPEED_GET(dev_config)) {
41 case I2C_SPEED_STANDARD:
42 speed = 100000;
43 break;
44 case I2C_SPEED_FAST:
45 speed = 400000;
46 break;
47 case I2C_SPEED_FAST_PLUS:
48 mux_selection = PINCTRL_STATE_FAST_PLUS;
49 speed = 1000000;
50 break;
51 case I2C_SPEED_HIGH:
52 case I2C_SPEED_ULTRA:
53 return -ENOTSUP;
54 default:
55 return -EINVAL;
56 }
57
58 if (dev_config & I2C_ADDR_10_BITS) {
59 return -ENOTSUP;
60 }
61
62 k_mutex_lock(&data->mutex, K_FOREVER);
63 lpc11u6x_i2c_set_bus_speed(cfg, cfg->clock_dev, speed);
64
65 ret = pinctrl_apply_state(cfg->pincfg, mux_selection);
66 if (ret) {
67 k_mutex_unlock(&data->mutex);
68 return ret;
69 }
70 k_mutex_unlock(&data->mutex);
71 return 0;
72 }
73
lpc11u6x_i2c_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)74 static int lpc11u6x_i2c_transfer(const struct device *dev,
75 struct i2c_msg *msgs,
76 uint8_t num_msgs, uint16_t addr)
77 {
78 const struct lpc11u6x_i2c_config *cfg = dev->config;
79 struct lpc11u6x_i2c_data *data = dev->data;
80 int ret = 0;
81
82 if (!num_msgs) {
83 return 0;
84 }
85
86 k_mutex_lock(&data->mutex, K_FOREVER);
87
88 data->transfer.msgs = msgs;
89 data->transfer.curr_buf = msgs->buf;
90 data->transfer.curr_len = msgs->len;
91 data->transfer.nr_msgs = num_msgs;
92 data->transfer.addr = addr;
93
94 /* Reset all control bits */
95 cfg->base->con_clr = LPC11U6X_I2C_CONTROL_SI |
96 LPC11U6X_I2C_CONTROL_STOP | LPC11U6X_I2C_CONTROL_START;
97
98 /* Send start and wait for completion */
99 data->transfer.status = LPC11U6X_I2C_STATUS_BUSY;
100 cfg->base->con_set = LPC11U6X_I2C_CONTROL_START;
101
102 k_sem_take(&data->completion, K_FOREVER);
103
104 if (data->transfer.status != LPC11U6X_I2C_STATUS_OK) {
105 ret = -EIO;
106 }
107 data->transfer.status = LPC11U6X_I2C_STATUS_INACTIVE;
108
109 /* If a slave is registered, put the controller in slave mode */
110 if (data->slave) {
111 cfg->base->con_set = LPC11U6X_I2C_CONTROL_AA;
112 }
113
114 k_mutex_unlock(&data->mutex);
115 return ret;
116 }
117
lpc11u6x_i2c_slave_register(const struct device * dev,struct i2c_target_config * cfg)118 static int lpc11u6x_i2c_slave_register(const struct device *dev,
119 struct i2c_target_config *cfg)
120 {
121 const struct lpc11u6x_i2c_config *dev_cfg = dev->config;
122 struct lpc11u6x_i2c_data *data = dev->data;
123 int ret = 0;
124
125 if (!cfg) {
126 return -EINVAL;
127 }
128
129 if (cfg->flags & I2C_TARGET_FLAGS_ADDR_10_BITS) {
130 return -ENOTSUP;
131 }
132
133 k_mutex_lock(&data->mutex, K_FOREVER);
134 if (data->slave) {
135 ret = -EBUSY;
136 goto exit;
137 }
138
139 data->slave = cfg;
140 /* Configure controller to act as slave */
141 dev_cfg->base->addr0 = (cfg->address << 1);
142 dev_cfg->base->con_clr = LPC11U6X_I2C_CONTROL_START |
143 LPC11U6X_I2C_CONTROL_STOP | LPC11U6X_I2C_CONTROL_SI;
144 dev_cfg->base->con_set = LPC11U6X_I2C_CONTROL_AA;
145
146 exit:
147 k_mutex_unlock(&data->mutex);
148 return ret;
149 }
150
151
lpc11u6x_i2c_slave_unregister(const struct device * dev,struct i2c_target_config * cfg)152 static int lpc11u6x_i2c_slave_unregister(const struct device *dev,
153 struct i2c_target_config *cfg)
154 {
155 const struct lpc11u6x_i2c_config *dev_cfg = dev->config;
156 struct lpc11u6x_i2c_data *data = dev->data;
157
158 if (!cfg) {
159 return -EINVAL;
160 }
161 if (data->slave != cfg) {
162 return -EINVAL;
163 }
164
165 k_mutex_lock(&data->mutex, K_FOREVER);
166 data->slave = NULL;
167 dev_cfg->base->con_clr = LPC11U6X_I2C_CONTROL_AA;
168 k_mutex_unlock(&data->mutex);
169
170 return 0;
171 }
172
lpc11u6x_i2c_isr(const struct device * dev)173 static void lpc11u6x_i2c_isr(const struct device *dev)
174 {
175 struct lpc11u6x_i2c_data *data = dev->data;
176 struct lpc11u6x_i2c_regs *i2c = DEV_BASE(dev);
177 struct lpc11u6x_i2c_current_transfer *transfer = &data->transfer;
178 uint32_t clear = LPC11U6X_I2C_CONTROL_SI;
179 uint32_t set = 0;
180 uint8_t val;
181
182 switch (i2c->stat) {
183 /* Master TX states */
184 case LPC11U6X_I2C_MASTER_TX_START:
185 case LPC11U6X_I2C_MASTER_TX_RESTART:
186 i2c->dat = (transfer->addr << 1) |
187 (transfer->msgs->flags & I2C_MSG_READ);
188 clear |= LPC11U6X_I2C_CONTROL_START;
189 transfer->curr_buf = transfer->msgs->buf;
190 transfer->curr_len = transfer->msgs->len;
191 break;
192
193 case LPC11U6X_I2C_MASTER_TX_ADR_ACK:
194 case LPC11U6X_I2C_MASTER_TX_DAT_ACK:
195 if (!transfer->curr_len) {
196 transfer->msgs++;
197 transfer->nr_msgs--;
198 if (!transfer->nr_msgs) {
199 transfer->status = LPC11U6X_I2C_STATUS_OK;
200 set |= LPC11U6X_I2C_CONTROL_STOP;
201 } else {
202 set |= LPC11U6X_I2C_CONTROL_START;
203 }
204 } else {
205 i2c->dat = transfer->curr_buf[0];
206 transfer->curr_buf++;
207 transfer->curr_len--;
208 }
209 break;
210
211 /* Master RX states */
212 case LPC11U6X_I2C_MASTER_RX_DAT_NACK:
213 transfer->msgs++;
214 transfer->nr_msgs--;
215 set |= (transfer->nr_msgs ? LPC11U6X_I2C_CONTROL_START :
216 LPC11U6X_I2C_CONTROL_STOP);
217 if (!transfer->nr_msgs) {
218 transfer->status = LPC11U6X_I2C_STATUS_OK;
219 }
220 __fallthrough;
221 case LPC11U6X_I2C_MASTER_RX_DAT_ACK:
222 transfer->curr_buf[0] = i2c->dat;
223 transfer->curr_buf++;
224 transfer->curr_len--;
225 __fallthrough;
226 case LPC11U6X_I2C_MASTER_RX_ADR_ACK:
227 if (transfer->curr_len <= 1) {
228 clear |= LPC11U6X_I2C_CONTROL_AA;
229 } else {
230 set |= LPC11U6X_I2C_CONTROL_AA;
231 }
232 break;
233
234 /* Slave States */
235 case LPC11U6X_I2C_SLAVE_RX_ADR_ACK:
236 case LPC11U6X_I2C_SLAVE_RX_ARB_LOST_ADR_ACK:
237 case LPC11U6X_I2C_SLAVE_RX_GC_ACK:
238 case LPC11U6X_I2C_SLAVE_RX_ARB_LOST_GC_ACK:
239 if (data->slave->callbacks->write_requested(data->slave)) {
240 clear |= LPC11U6X_I2C_CONTROL_AA;
241 }
242 break;
243
244 case LPC11U6X_I2C_SLAVE_RX_DAT_ACK:
245 case LPC11U6X_I2C_SLAVE_RX_GC_DAT_ACK:
246 val = i2c->dat;
247 if (data->slave->callbacks->write_received(data->slave, val)) {
248 clear |= LPC11U6X_I2C_CONTROL_AA;
249 }
250 break;
251
252 case LPC11U6X_I2C_SLAVE_RX_DAT_NACK:
253 case LPC11U6X_I2C_SLAVE_RX_GC_DAT_NACK:
254 val = i2c->dat;
255 data->slave->callbacks->write_received(data->slave, val);
256 data->slave->callbacks->stop(data->slave);
257 set |= LPC11U6X_I2C_CONTROL_AA;
258 break;
259
260 case LPC11U6X_I2C_SLAVE_RX_STOP:
261 data->slave->callbacks->stop(data->slave);
262 set |= LPC11U6X_I2C_CONTROL_AA;
263 break;
264
265 case LPC11U6X_I2C_SLAVE_TX_ADR_ACK:
266 case LPC11U6X_I2C_SLAVE_TX_ARB_LOST_ADR_ACK:
267 if (data->slave->callbacks->read_requested(data->slave, &val)) {
268 clear |= LPC11U6X_I2C_CONTROL_AA;
269 }
270 i2c->dat = val;
271 break;
272 case LPC11U6X_I2C_SLAVE_TX_DAT_ACK:
273 if (data->slave->callbacks->read_processed(data->slave, &val)) {
274 clear |= LPC11U6X_I2C_CONTROL_AA;
275 }
276 i2c->dat = val;
277 break;
278 case LPC11U6X_I2C_SLAVE_TX_DAT_NACK:
279 case LPC11U6X_I2C_SLAVE_TX_LAST_BYTE:
280 data->slave->callbacks->stop(data->slave);
281 set |= LPC11U6X_I2C_CONTROL_AA;
282 break;
283
284 /* Error cases */
285 case LPC11U6X_I2C_MASTER_TX_ADR_NACK:
286 case LPC11U6X_I2C_MASTER_RX_ADR_NACK:
287 case LPC11U6X_I2C_MASTER_TX_DAT_NACK:
288 case LPC11U6X_I2C_MASTER_TX_ARB_LOST:
289 transfer->status = LPC11U6X_I2C_STATUS_FAIL;
290 set = LPC11U6X_I2C_CONTROL_STOP;
291 break;
292
293 default:
294 set = LPC11U6X_I2C_CONTROL_STOP;
295 break;
296 }
297
298 i2c->con_clr = clear;
299 i2c->con_set = set;
300 if ((transfer->status != LPC11U6X_I2C_STATUS_BUSY) &&
301 (transfer->status != LPC11U6X_I2C_STATUS_INACTIVE)) {
302 k_sem_give(&data->completion);
303 }
304 }
305
306
lpc11u6x_i2c_init(const struct device * dev)307 static int lpc11u6x_i2c_init(const struct device *dev)
308 {
309 const struct lpc11u6x_i2c_config *cfg = dev->config;
310 struct lpc11u6x_i2c_data *data = dev->data;
311 int err;
312
313 err = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT);
314 if (err) {
315 return err;
316 }
317
318 if (!device_is_ready(cfg->clock_dev)) {
319 return -ENODEV;
320 }
321
322 /* Configure clock and de-assert reset for I2Cx */
323 clock_control_on(cfg->clock_dev, (clock_control_subsys_t) cfg->clkid);
324
325 /* Configure bus speed. Default is 100KHz */
326 lpc11u6x_i2c_set_bus_speed(cfg, cfg->clock_dev, 100000);
327
328 /* Clear all control bytes and enable I2C interface */
329 cfg->base->con_clr = LPC11U6X_I2C_CONTROL_AA | LPC11U6X_I2C_CONTROL_SI |
330 LPC11U6X_I2C_CONTROL_START | LPC11U6X_I2C_CONTROL_I2C_EN;
331 cfg->base->con_set = LPC11U6X_I2C_CONTROL_I2C_EN;
332
333 /* Initialize mutex and semaphore */
334 k_mutex_init(&data->mutex);
335 k_sem_init(&data->completion, 0, 1);
336
337 data->transfer.status = LPC11U6X_I2C_STATUS_INACTIVE;
338 /* Configure IRQ */
339 cfg->irq_config_func(dev);
340 return 0;
341 }
342
343 static DEVICE_API(i2c, i2c_api) = {
344 .configure = lpc11u6x_i2c_configure,
345 .transfer = lpc11u6x_i2c_transfer,
346 .target_register = lpc11u6x_i2c_slave_register,
347 .target_unregister = lpc11u6x_i2c_slave_unregister,
348 #ifdef CONFIG_I2C_RTIO
349 .iodev_submit = i2c_iodev_submit_fallback,
350 #endif
351 };
352
353 #define LPC11U6X_I2C_INIT(idx) \
354 \
355 static void lpc11u6x_i2c_isr_config_##idx(const struct device *dev); \
356 \
357 PINCTRL_DT_INST_DEFINE(idx); \
358 \
359 static const struct lpc11u6x_i2c_config i2c_cfg_##idx = { \
360 .base = \
361 (struct lpc11u6x_i2c_regs *) DT_INST_REG_ADDR(idx), \
362 .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(idx)), \
363 .irq_config_func = lpc11u6x_i2c_isr_config_##idx, \
364 .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \
365 .clkid = DT_INST_PHA_BY_IDX(idx, clocks, 0, clkid), \
366 }; \
367 \
368 static struct lpc11u6x_i2c_data i2c_data_##idx; \
369 \
370 I2C_DEVICE_DT_INST_DEFINE(idx, \
371 lpc11u6x_i2c_init, \
372 NULL, \
373 &i2c_data_##idx, &i2c_cfg_##idx, \
374 PRE_KERNEL_1, CONFIG_I2C_INIT_PRIORITY, \
375 &i2c_api); \
376 \
377 static void lpc11u6x_i2c_isr_config_##idx(const struct device *dev) \
378 { \
379 IRQ_CONNECT(DT_INST_IRQN(idx), \
380 DT_INST_IRQ(idx, priority), \
381 lpc11u6x_i2c_isr, DEVICE_DT_INST_GET(idx), 0); \
382 \
383 irq_enable(DT_INST_IRQN(idx)); \
384 }
385
386 DT_INST_FOREACH_STATUS_OKAY(LPC11U6X_I2C_INIT);
387