1 /*
2 * Copyright (c) 2019 Derek Hageman <hageman@inthat.cloud>
3 * Copyright (c) 2024 Gerson Fernando Budke <nandojve@gmail.com>
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #define DT_DRV_COMPAT atmel_sam0_i2c
9
10 #include <errno.h>
11 #include <zephyr/device.h>
12 #include <zephyr/init.h>
13 #include <soc.h>
14 #include <zephyr/drivers/i2c.h>
15 #include <zephyr/drivers/dma.h>
16 #include <zephyr/drivers/pinctrl.h>
17
18 #include <zephyr/logging/log.h>
19 #include <zephyr/irq.h>
20 LOG_MODULE_REGISTER(i2c_sam0, CONFIG_I2C_LOG_LEVEL);
21
22 /* clang-format off */
23
24 #include "i2c-priv.h"
25
26 #ifndef SERCOM_I2CM_CTRLA_MODE_I2C_MASTER
27 #define SERCOM_I2CM_CTRLA_MODE_I2C_MASTER SERCOM_I2CM_CTRLA_MODE(5)
28 #endif
29
30 #if CONFIG_I2C_SAM0_TRANSFER_TIMEOUT
31 #define I2C_TRANSFER_TIMEOUT_MSEC K_MSEC(CONFIG_I2C_SAM0_TRANSFER_TIMEOUT)
32 #else
33 #define I2C_TRANSFER_TIMEOUT_MSEC K_FOREVER
34 #endif
35
36 struct i2c_sam0_dev_config {
37 SercomI2cm *regs;
38 const struct pinctrl_dev_config *pcfg;
39 uint32_t bitrate;
40 volatile uint32_t *mclk;
41 uint32_t mclk_mask;
42 uint32_t gclk_gen;
43 uint16_t gclk_id;
44 void (*irq_config_func)(const struct device *dev);
45
46 #ifdef CONFIG_I2C_SAM0_DMA_DRIVEN
47 const struct device *dma_dev;
48 uint8_t write_dma_request;
49 uint8_t read_dma_request;
50 uint8_t dma_channel;
51 #endif
52 };
53
54 struct i2c_sam0_msg {
55 uint8_t *buffer;
56 uint32_t size;
57 uint32_t status;
58 };
59
60 struct i2c_sam0_dev_data {
61 struct k_sem lock;
62 struct k_sem sem;
63 struct i2c_sam0_msg msg;
64 struct i2c_msg *msgs;
65 uint8_t num_msgs;
66 };
67
wait_synchronization(SercomI2cm * regs)68 static void wait_synchronization(SercomI2cm *regs)
69 {
70 #if defined(SERCOM_I2CM_SYNCBUSY_MASK)
71 /* SYNCBUSY is a register */
72 while ((regs->SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_MASK) != 0) {
73 }
74 #elif defined(SERCOM_I2CM_STATUS_SYNCBUSY)
75 /* SYNCBUSY is a bit */
76 while ((regs->STATUS.reg & SERCOM_I2CM_STATUS_SYNCBUSY) != 0) {
77 }
78 #else
79 #error Unsupported device
80 #endif
81 }
82
i2c_sam0_terminate_on_error(const struct device * dev)83 static bool i2c_sam0_terminate_on_error(const struct device *dev)
84 {
85 struct i2c_sam0_dev_data *data = dev->data;
86 const struct i2c_sam0_dev_config *const cfg = dev->config;
87 SercomI2cm *i2c = cfg->regs;
88
89 if (!(i2c->STATUS.reg & (SERCOM_I2CM_STATUS_ARBLOST |
90 SERCOM_I2CM_STATUS_RXNACK |
91 #ifdef SERCOM_I2CM_STATUS_LENERR
92 SERCOM_I2CM_STATUS_LENERR |
93 #endif
94 #ifdef SERCOM_I2CM_STATUS_SEXTTOUT
95 SERCOM_I2CM_STATUS_SEXTTOUT |
96 #endif
97 #ifdef SERCOM_I2CM_STATUS_MEXTTOUT
98 SERCOM_I2CM_STATUS_MEXTTOUT |
99 #endif
100 SERCOM_I2CM_STATUS_LOWTOUT |
101 SERCOM_I2CM_STATUS_BUSERR))) {
102 return false;
103 }
104
105 #ifdef CONFIG_I2C_SAM0_DMA_DRIVEN
106 if (cfg->dma_channel != 0xFF) {
107 dma_stop(cfg->dma_dev, cfg->dma_channel);
108 }
109 #endif
110
111 data->msg.status = i2c->STATUS.reg;
112
113 /*
114 * Clear all the flags that require an explicit clear
115 * (as opposed to being cleared by ADDR writes, etc)
116 */
117 i2c->STATUS.reg = SERCOM_I2CM_STATUS_ARBLOST |
118 #ifdef SERCOM_I2CM_STATUS_LENERR
119 SERCOM_I2CM_STATUS_LENERR |
120 #endif
121 SERCOM_I2CM_STATUS_LOWTOUT |
122 SERCOM_I2CM_STATUS_BUSERR;
123 wait_synchronization(i2c);
124
125 i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK;
126 if (i2c->INTFLAG.reg & (SERCOM_I2CM_INTFLAG_MB | SERCOM_I2CM_INTFLAG_SB)) {
127 i2c->CTRLB.bit.CMD = 3;
128 }
129 k_sem_give(&data->sem);
130 return true;
131 }
132
i2c_sam0_isr(const struct device * dev)133 static void i2c_sam0_isr(const struct device *dev)
134 {
135 struct i2c_sam0_dev_data *data = dev->data;
136 const struct i2c_sam0_dev_config *const cfg = dev->config;
137 SercomI2cm *i2c = cfg->regs;
138
139 /* Get present interrupts and clear them */
140 uint32_t status = i2c->INTFLAG.reg;
141
142 i2c->INTFLAG.reg = status;
143
144 if (i2c_sam0_terminate_on_error(dev)) {
145 return;
146 }
147
148 /*
149 * Directly send/receive next message if it is in the same direction and
150 * the current message has no stop flag and the next message has no
151 * restart flag.
152 */
153 const bool continue_next = (data->msg.size == 1) && (data->num_msgs > 1) &&
154 ((data->msgs[0].flags & I2C_MSG_RW_MASK) ==
155 (data->msgs[1].flags & I2C_MSG_RW_MASK)) &&
156 !(data->msgs[0].flags & I2C_MSG_STOP) &&
157 !(data->msgs[1].flags & I2C_MSG_RESTART) &&
158 ((status & (SERCOM_I2CM_INTFLAG_MB | SERCOM_I2CM_INTFLAG_SB)));
159
160 if (status & SERCOM_I2CM_INTFLAG_MB) {
161 if (!data->msg.size) {
162 i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK;
163
164 /*
165 * Decide whether to issue a repeated start, or a stop condition...
166 * - A repeated start can either be accomplished by writing a 0x1
167 * to the CMD field, or by writing to ADDR - which is what this
168 * driver does in i2c_sam0_transfer().
169 * - A stop is accomplished by writing a 0x3 to CMD (below).
170 *
171 * This decision is not the same as continue_next, as the value of
172 * data->msg.size is already zero (not one), and i2c_sam0_transfer()
173 * is responsible for advancing to the next message, not the ISR.
174 */
175 if ((data->num_msgs <= 1)
176 || (data->msgs[0].flags & I2C_MSG_STOP)
177 || !(data->msgs[1].flags & I2C_MSG_RESTART)) {
178 i2c->CTRLB.bit.CMD = 3;
179 }
180
181 k_sem_give(&data->sem);
182 return;
183 }
184
185 i2c->DATA.reg = *data->msg.buffer;
186 data->msg.buffer++;
187 data->msg.size--;
188 } else if (status & SERCOM_I2CM_INTFLAG_SB) {
189 if (!continue_next && (data->msg.size == 1)) {
190 /*
191 * If this is the last byte, then prepare for an auto
192 * NACK before doing the actual read. This does not
193 * require write synchronization.
194 */
195 i2c->CTRLB.bit.ACKACT = 1;
196 i2c->CTRLB.bit.CMD = 3;
197 }
198
199 *data->msg.buffer = i2c->DATA.reg;
200 data->msg.buffer++;
201 data->msg.size--;
202
203 if (!continue_next && !data->msg.size) {
204 i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK;
205 k_sem_give(&data->sem);
206 return;
207 }
208 }
209
210 if (continue_next) {
211 data->msgs++;
212 data->num_msgs--;
213
214 data->msg.buffer = data->msgs->buf;
215 data->msg.size = data->msgs->len;
216 data->msg.status = 0;
217 }
218 }
219
220 #ifdef CONFIG_I2C_SAM0_DMA_DRIVEN
221
i2c_sam0_dma_write_done(const struct device * dma_dev,void * arg,uint32_t id,int error_code)222 static void i2c_sam0_dma_write_done(const struct device *dma_dev, void *arg,
223 uint32_t id, int error_code)
224 {
225 const struct device *dev = arg;
226 struct i2c_sam0_dev_data *data = dev->data;
227 const struct i2c_sam0_dev_config *const cfg = dev->config;
228 SercomI2cm *i2c = cfg->regs;
229
230 ARG_UNUSED(dma_dev);
231 ARG_UNUSED(id);
232
233 unsigned int key = irq_lock();
234
235 if (i2c_sam0_terminate_on_error(dev)) {
236 irq_unlock(key);
237 return;
238 }
239
240 if (error_code < 0) {
241 LOG_ERR("DMA write error on %s: %d", dev->name, error_code);
242 i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK;
243 irq_unlock(key);
244
245 data->msg.status = error_code;
246
247 k_sem_give(&data->sem);
248 return;
249 }
250
251 irq_unlock(key);
252
253 /*
254 * DMA has written the whole message now, so just wait for the
255 * final I2C IRQ to indicate that it's finished transmitting.
256 */
257 data->msg.size = 0;
258 i2c->INTENSET.reg = SERCOM_I2CM_INTENSET_MB;
259 }
260
i2c_sam0_dma_write_start(const struct device * dev)261 static bool i2c_sam0_dma_write_start(const struct device *dev)
262 {
263 struct i2c_sam0_dev_data *data = dev->data;
264 const struct i2c_sam0_dev_config *const cfg = dev->config;
265 SercomI2cm *i2c = cfg->regs;
266 int retval;
267
268 if (cfg->dma_channel == 0xFF) {
269 return false;
270 }
271
272 if (data->msg.size <= 1) {
273 /*
274 * Catch empty writes and skip DMA on single byte transfers.
275 */
276 return false;
277 }
278
279 struct dma_config dma_cfg = { 0 };
280 struct dma_block_config dma_blk = { 0 };
281
282 dma_cfg.channel_direction = MEMORY_TO_PERIPHERAL;
283 dma_cfg.source_data_size = 1;
284 dma_cfg.dest_data_size = 1;
285 dma_cfg.user_data = (void *)dev;
286 dma_cfg.dma_callback = i2c_sam0_dma_write_done;
287 dma_cfg.block_count = 1;
288 dma_cfg.head_block = &dma_blk;
289 dma_cfg.dma_slot = cfg->write_dma_request;
290
291 dma_blk.block_size = data->msg.size;
292 dma_blk.source_address = (uint32_t)data->msg.buffer;
293 dma_blk.dest_address = (uint32_t)(&(i2c->DATA.reg));
294 dma_blk.dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
295
296 retval = dma_config(cfg->dma_dev, cfg->dma_channel, &dma_cfg);
297 if (retval != 0) {
298 LOG_ERR("Write DMA configure on %s failed: %d",
299 dev->name, retval);
300 return false;
301 }
302
303 retval = dma_start(cfg->dma_dev, cfg->dma_channel);
304 if (retval != 0) {
305 LOG_ERR("Write DMA start on %s failed: %d",
306 dev->name, retval);
307 return false;
308 }
309
310 return true;
311 }
312
i2c_sam0_dma_read_done(const struct device * dma_dev,void * arg,uint32_t id,int error_code)313 static void i2c_sam0_dma_read_done(const struct device *dma_dev, void *arg,
314 uint32_t id, int error_code)
315 {
316 const struct device *dev = arg;
317 struct i2c_sam0_dev_data *data = dev->data;
318 const struct i2c_sam0_dev_config *const cfg = dev->config;
319 SercomI2cm *i2c = cfg->regs;
320
321 ARG_UNUSED(dma_dev);
322 ARG_UNUSED(id);
323
324 unsigned int key = irq_lock();
325
326 if (i2c_sam0_terminate_on_error(dev)) {
327 irq_unlock(key);
328 return;
329 }
330
331 if (error_code < 0) {
332 LOG_ERR("DMA read error on %s: %d", dev->name, error_code);
333 i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK;
334 irq_unlock(key);
335
336 data->msg.status = error_code;
337
338 k_sem_give(&data->sem);
339 return;
340 }
341
342 irq_unlock(key);
343
344 /*
345 * DMA has read all but the last byte now, so let the ISR handle
346 * that and the terminating NACK.
347 */
348 data->msg.buffer += data->msg.size - 1;
349 data->msg.size = 1;
350 i2c->INTENSET.reg = SERCOM_I2CM_INTENSET_SB;
351 }
352
i2c_sam0_dma_read_start(const struct device * dev)353 static bool i2c_sam0_dma_read_start(const struct device *dev)
354 {
355 struct i2c_sam0_dev_data *data = dev->data;
356 const struct i2c_sam0_dev_config *const cfg = dev->config;
357 SercomI2cm *i2c = cfg->regs;
358 int retval;
359
360 if (cfg->dma_channel == 0xFF) {
361 return false;
362 }
363
364 if (data->msg.size <= 2) {
365 /*
366 * The last byte is always handled by the I2C ISR so
367 * just skip a two length read as well.
368 */
369 return false;
370 }
371
372 struct dma_config dma_cfg = { 0 };
373 struct dma_block_config dma_blk = { 0 };
374
375 dma_cfg.channel_direction = PERIPHERAL_TO_MEMORY;
376 dma_cfg.source_data_size = 1;
377 dma_cfg.dest_data_size = 1;
378 dma_cfg.user_data = (void *)dev;
379 dma_cfg.dma_callback = i2c_sam0_dma_read_done;
380 dma_cfg.block_count = 1;
381 dma_cfg.head_block = &dma_blk;
382 dma_cfg.dma_slot = cfg->read_dma_request;
383
384 dma_blk.block_size = data->msg.size - 1;
385 dma_blk.dest_address = (uint32_t)data->msg.buffer;
386 dma_blk.source_address = (uint32_t)(&(i2c->DATA.reg));
387 dma_blk.source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
388
389 retval = dma_config(cfg->dma_dev, cfg->dma_channel, &dma_cfg);
390 if (retval != 0) {
391 LOG_ERR("Read DMA configure on %s failed: %d",
392 dev->name, retval);
393 return false;
394 }
395
396 retval = dma_start(cfg->dma_dev, cfg->dma_channel);
397 if (retval != 0) {
398 LOG_ERR("Read DMA start on %s failed: %d",
399 dev->name, retval);
400 return false;
401 }
402
403 return true;
404 }
405
406 #endif
407
i2c_sam0_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)408 static int i2c_sam0_transfer(const struct device *dev, struct i2c_msg *msgs,
409 uint8_t num_msgs, uint16_t addr)
410 {
411 struct i2c_sam0_dev_data *data = dev->data;
412 const struct i2c_sam0_dev_config *const cfg = dev->config;
413 SercomI2cm *i2c = cfg->regs;
414 uint32_t addr_reg;
415 int ret;
416
417 if (!num_msgs) {
418 return 0;
419 }
420
421 k_sem_take(&data->lock, K_FOREVER);
422
423 data->num_msgs = num_msgs;
424 data->msgs = msgs;
425
426 for (; data->num_msgs > 0;) {
427 if (!data->msgs->len) {
428 if ((data->msgs->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) {
429 ret = -EINVAL;
430 goto unlock;
431 }
432 }
433
434 i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK;
435 i2c->INTFLAG.reg = SERCOM_I2CM_INTFLAG_MASK;
436
437 i2c->STATUS.reg = SERCOM_I2CM_STATUS_ARBLOST |
438 #ifdef SERCOM_I2CM_STATUS_LENERR
439 SERCOM_I2CM_STATUS_LENERR |
440 #endif
441 SERCOM_I2CM_STATUS_LOWTOUT |
442 SERCOM_I2CM_STATUS_BUSERR;
443 wait_synchronization(i2c);
444
445 data->msg.buffer = data->msgs->buf;
446 data->msg.size = data->msgs->len;
447 data->msg.status = 0;
448
449 addr_reg = addr << 1U;
450 if ((data->msgs->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) {
451 addr_reg |= 1U;
452
453 /* Set to auto ACK */
454 i2c->CTRLB.bit.ACKACT = 0;
455 wait_synchronization(i2c);
456 }
457
458 if (data->msgs->flags & I2C_MSG_ADDR_10_BITS) {
459 #ifdef SERCOM_I2CM_ADDR_TENBITEN
460 addr_reg |= SERCOM_I2CM_ADDR_TENBITEN;
461 #else
462 ret = -ENOTSUP;
463 goto unlock;
464 #endif
465 }
466
467 unsigned int key = irq_lock();
468
469 /*
470 * Writing the address starts the transaction, issuing
471 * a start/repeated start as required.
472 */
473 i2c->ADDR.reg = addr_reg;
474
475 /*
476 * Have to wait here to make sure the address write
477 * clears any pending requests or errors before DMA or
478 * ISR tries to handle it.
479 */
480 wait_synchronization(i2c);
481
482 #ifdef SERCOM_I2CM_INTENSET_ERROR
483 i2c->INTENSET.reg = SERCOM_I2CM_INTENSET_ERROR;
484 #endif
485
486 if ((data->msgs->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) {
487 /*
488 * Always set MB even when reading, since that's how
489 * some errors are indicated.
490 */
491 i2c->INTENSET.reg = SERCOM_I2CM_INTENSET_MB;
492
493 #ifdef CONFIG_I2C_SAM0_DMA_DRIVEN
494 if (!i2c_sam0_dma_read_start(dev))
495 #endif
496 {
497 i2c->INTENSET.reg = SERCOM_I2CM_INTENSET_SB;
498 }
499
500 } else {
501 #ifdef CONFIG_I2C_SAM0_DMA_DRIVEN
502 if (!i2c_sam0_dma_write_start(dev))
503 #endif
504 {
505 i2c->INTENSET.reg = SERCOM_I2CM_INTENSET_MB;
506 }
507 }
508
509 irq_unlock(key);
510
511 /* Now wait for the ISR to handle everything */
512 ret = k_sem_take(&data->sem, I2C_TRANSFER_TIMEOUT_MSEC);
513
514 if (ret != 0) {
515 ret = -EIO;
516 goto unlock;
517 }
518
519 if (data->msg.status) {
520 if (data->msg.status & SERCOM_I2CM_STATUS_ARBLOST) {
521 LOG_DBG("Arbitration lost on %s",
522 dev->name);
523 ret = -EAGAIN;
524 goto unlock;
525 }
526
527 LOG_ERR("Transaction error on %s: %08X",
528 dev->name, data->msg.status);
529 ret = -EIO;
530 goto unlock;
531 }
532
533 data->num_msgs--;
534 data->msgs++;
535 }
536
537 ret = 0;
538 unlock:
539 k_sem_give(&data->lock);
540
541 return ret;
542 }
543
i2c_sam0_set_apply_bitrate(const struct device * dev,uint32_t config)544 static int i2c_sam0_set_apply_bitrate(const struct device *dev,
545 uint32_t config)
546 {
547 const struct i2c_sam0_dev_config *const cfg = dev->config;
548 SercomI2cm *i2c = cfg->regs;
549 uint32_t baud;
550 uint32_t baud_low;
551 uint32_t baud_high;
552
553 uint32_t CTRLA = i2c->CTRLA.reg;
554
555 #ifdef SERCOM_I2CM_CTRLA_SPEED_Msk
556 CTRLA &= ~SERCOM_I2CM_CTRLA_SPEED_Msk;
557 #endif
558 CTRLA &= ~SERCOM_I2CM_CTRLA_SDAHOLD_Msk;
559
560 switch (I2C_SPEED_GET(config)) {
561 case I2C_SPEED_STANDARD:
562 #ifdef SERCOM_I2CM_CTRLA_SPEED
563 CTRLA |= SERCOM_I2CM_CTRLA_SPEED(0);
564 #endif
565 CTRLA |= SERCOM_I2CM_CTRLA_SDAHOLD(0x0);
566 i2c->CTRLA.reg = CTRLA;
567 wait_synchronization(i2c);
568
569 /* 5 is the nominal 100ns rise time from the app notes */
570 baud = (SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / 100000U - 5U - 10U) / 2U;
571 if (baud > 255U || baud < 1U) {
572 return -ERANGE;
573 }
574
575 LOG_DBG("Setting %s to standard mode with divisor %u",
576 dev->name, baud);
577
578 i2c->BAUD.reg = SERCOM_I2CM_BAUD_BAUD(baud);
579 break;
580
581 case I2C_SPEED_FAST:
582 CTRLA |= SERCOM_I2CM_CTRLA_SDAHOLD(0x0);
583 i2c->CTRLA.reg = CTRLA;
584 wait_synchronization(i2c);
585
586 /* 5 is the nominal 100ns rise time from the app notes */
587 baud = (SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / 400000U - 5U - 10U) / 2U;
588 if (baud > 255U || baud < 1U) {
589 return -ERANGE;
590 }
591
592 LOG_DBG("Setting %s to fast mode with divisor %u",
593 dev->name, baud);
594
595 i2c->BAUD.reg = SERCOM_I2CM_BAUD_BAUD(baud);
596 break;
597
598 case I2C_SPEED_FAST_PLUS:
599 #ifdef SERCOM_I2CM_CTRLA_SPEED
600 CTRLA |= SERCOM_I2CM_CTRLA_SPEED(1);
601 #endif
602 CTRLA |= SERCOM_I2CM_CTRLA_SDAHOLD(0x2);
603 i2c->CTRLA.reg = CTRLA;
604 wait_synchronization(i2c);
605
606 /* 5 is the nominal 100ns rise time from the app notes */
607 baud = (SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / 1000000U - 5U - 10U);
608
609 /* 2:1 low:high ratio */
610 baud_high = baud;
611 baud_high /= 3U;
612 baud_high = CLAMP(baud_high, 1U, 255U);
613 baud_low = baud - baud_high;
614 if (baud_low < 1U && baud_high > 1U) {
615 --baud_high;
616 ++baud_low;
617 }
618
619 if (baud_low < 1U || baud_low > 255U) {
620 return -ERANGE;
621 }
622
623 LOG_DBG("Setting %s to fast mode plus with divisors %u/%u",
624 dev->name, baud_high, baud_low);
625
626 i2c->BAUD.reg = SERCOM_I2CM_BAUD_BAUD(baud_high) |
627 SERCOM_I2CM_BAUD_BAUDLOW(baud_low);
628 break;
629
630 case I2C_SPEED_HIGH:
631 #ifdef SERCOM_I2CM_CTRLA_SPEED
632 CTRLA |= SERCOM_I2CM_CTRLA_SPEED(2);
633 #endif
634 CTRLA |= SERCOM_I2CM_CTRLA_SDAHOLD(0x2);
635 i2c->CTRLA.reg = CTRLA;
636 wait_synchronization(i2c);
637
638 baud = (SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / 3400000U) - 2U;
639
640 /* 2:1 low:high ratio */
641 baud_high = baud;
642 baud_high /= 3U;
643 baud_high = CLAMP(baud_high, 1U, 255U);
644 baud_low = baud - baud_high;
645 if (baud_low < 1U && baud_high > 1U) {
646 --baud_high;
647 ++baud_low;
648 }
649
650 if (baud_low < 1U || baud_low > 255U) {
651 return -ERANGE;
652 }
653
654 #ifdef SERCOM_I2CM_BAUD_HSBAUD
655 LOG_DBG("Setting %s to high speed with divisors %u/%u",
656 dev->name, baud_high, baud_low);
657
658 /*
659 * 48 is just from the app notes, but the datasheet says
660 * it's ignored
661 */
662 i2c->BAUD.reg = SERCOM_I2CM_BAUD_HSBAUD(baud_high) |
663 SERCOM_I2CM_BAUD_HSBAUDLOW(baud_low) |
664 SERCOM_I2CM_BAUD_BAUD(48) |
665 SERCOM_I2CM_BAUD_BAUDLOW(48);
666 #else
667 return -ENOTSUP;
668 #endif
669 break;
670
671 default:
672 return -ENOTSUP;
673 }
674
675 wait_synchronization(i2c);
676 return 0;
677 }
678
i2c_sam0_configure(const struct device * dev,uint32_t config)679 static int i2c_sam0_configure(const struct device *dev, uint32_t config)
680 {
681 const struct i2c_sam0_dev_config *const cfg = dev->config;
682 SercomI2cm *i2c = cfg->regs;
683 int retval;
684
685 if (!(config & I2C_MODE_CONTROLLER)) {
686 return -EINVAL;
687 }
688
689 if (config & I2C_SPEED_MASK) {
690 i2c->CTRLA.bit.ENABLE = 0;
691 wait_synchronization(i2c);
692
693 retval = i2c_sam0_set_apply_bitrate(dev, config);
694
695 i2c->CTRLA.bit.ENABLE = 1;
696 wait_synchronization(i2c);
697
698 if (retval != 0) {
699 return retval;
700 }
701 }
702
703 return 0;
704 }
705
i2c_sam0_initialize(const struct device * dev)706 static int i2c_sam0_initialize(const struct device *dev)
707 {
708 struct i2c_sam0_dev_data *data = dev->data;
709 const struct i2c_sam0_dev_config *const cfg = dev->config;
710 SercomI2cm *i2c = cfg->regs;
711 int retval;
712
713 *cfg->mclk |= cfg->mclk_mask;
714
715 #ifdef MCLK
716 GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN
717 | GCLK_PCHCTRL_GEN(cfg->gclk_gen);
718 #else
719 GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN
720 | GCLK_CLKCTRL_GEN(cfg->gclk_gen)
721 | GCLK_CLKCTRL_ID(cfg->gclk_id);
722 #endif
723
724 /* Disable all I2C interrupts */
725 i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK;
726
727 retval = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
728 if (retval < 0) {
729 return retval;
730 }
731
732 /* I2C mode, enable timeouts */
733 i2c->CTRLA.reg = SERCOM_I2CM_CTRLA_MODE_I2C_MASTER |
734 #ifdef SERCOM_I2CM_CTRLA_LOWTOUTEN
735 SERCOM_I2CM_CTRLA_LOWTOUTEN |
736 #endif
737 SERCOM_I2CM_CTRLA_INACTOUT(0x3);
738 wait_synchronization(i2c);
739
740 /* Enable smart mode (auto ACK) */
741 i2c->CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN;
742 wait_synchronization(i2c);
743
744 retval = i2c_sam0_set_apply_bitrate(dev,
745 i2c_map_dt_bitrate(cfg->bitrate));
746 if (retval != 0) {
747 return retval;
748 }
749
750 k_sem_init(&data->lock, 1, 1);
751 k_sem_init(&data->sem, 0, 1);
752
753 cfg->irq_config_func(dev);
754
755 #ifdef CONFIG_I2C_SAM0_DMA_DRIVEN
756 if (!device_is_ready(cfg->dma_dev)) {
757 return -ENODEV;
758 }
759 #endif
760
761 i2c->CTRLA.bit.ENABLE = 1;
762 wait_synchronization(i2c);
763
764 /* Force bus idle */
765 i2c->STATUS.bit.BUSSTATE = 1;
766 wait_synchronization(i2c);
767
768 return 0;
769 }
770
771 static DEVICE_API(i2c, i2c_sam0_driver_api) = {
772 .configure = i2c_sam0_configure,
773 .transfer = i2c_sam0_transfer,
774 #ifdef CONFIG_I2C_RTIO
775 .iodev_submit = i2c_iodev_submit_fallback,
776 #endif
777 };
778
779 #ifdef CONFIG_I2C_SAM0_DMA_DRIVEN
780 #define I2C_SAM0_DMA_CHANNELS(n) \
781 .dma_dev = DEVICE_DT_GET(ATMEL_SAM0_DT_INST_DMA_CTLR(n, tx)), \
782 .write_dma_request = ATMEL_SAM0_DT_INST_DMA_TRIGSRC(n, tx), \
783 .read_dma_request = ATMEL_SAM0_DT_INST_DMA_TRIGSRC(n, rx), \
784 .dma_channel = ATMEL_SAM0_DT_INST_DMA_CHANNEL(n, rx),
785 #else
786 #define I2C_SAM0_DMA_CHANNELS(n)
787 #endif
788
789 #define SAM0_I2C_IRQ_CONNECT(n, m) \
790 do { \
791 IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, m, irq), \
792 DT_INST_IRQ_BY_IDX(n, m, priority), \
793 i2c_sam0_isr, \
794 DEVICE_DT_INST_GET(n), 0); \
795 irq_enable(DT_INST_IRQ_BY_IDX(n, m, irq)); \
796 } while (false)
797
798 #if DT_INST_IRQ_HAS_IDX(0, 3)
799 #define I2C_SAM0_IRQ_HANDLER(n) \
800 static void i2c_sam0_irq_config_##n(const struct device *dev) \
801 { \
802 SAM0_I2C_IRQ_CONNECT(n, 0); \
803 SAM0_I2C_IRQ_CONNECT(n, 1); \
804 SAM0_I2C_IRQ_CONNECT(n, 2); \
805 SAM0_I2C_IRQ_CONNECT(n, 3); \
806 }
807 #else
808 #define I2C_SAM0_IRQ_HANDLER(n) \
809 static void i2c_sam0_irq_config_##n(const struct device *dev) \
810 { \
811 SAM0_I2C_IRQ_CONNECT(n, 0); \
812 }
813 #endif
814
815 #define ASSIGNED_CLOCKS_CELL_BY_NAME \
816 ATMEL_SAM0_DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME
817
818 #ifdef MCLK
819 #define I2C_SAM0_CONFIG(n) \
820 static const struct i2c_sam0_dev_config i2c_sam0_dev_config_##n = { \
821 .regs = (SercomI2cm *)DT_INST_REG_ADDR(n), \
822 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
823 .bitrate = DT_INST_PROP(n, clock_frequency), \
824 .gclk_gen = ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \
825 .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \
826 .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \
827 .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \
828 .irq_config_func = &i2c_sam0_irq_config_##n, \
829 I2C_SAM0_DMA_CHANNELS(n) \
830 }
831 #else /* !MCLK */
832 #define I2C_SAM0_CONFIG(n) \
833 static const struct i2c_sam0_dev_config i2c_sam0_dev_config_##n = { \
834 .regs = (SercomI2cm *)DT_INST_REG_ADDR(n), \
835 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
836 .bitrate = DT_INST_PROP(n, clock_frequency), \
837 .gclk_gen = ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \
838 .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \
839 .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \
840 .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \
841 .irq_config_func = &i2c_sam0_irq_config_##n, \
842 I2C_SAM0_DMA_CHANNELS(n) \
843 }
844 #endif
845
846 #define I2C_SAM0_DEVICE(n) \
847 PINCTRL_DT_INST_DEFINE(n); \
848 static void i2c_sam0_irq_config_##n(const struct device *dev); \
849 I2C_SAM0_CONFIG(n); \
850 static struct i2c_sam0_dev_data i2c_sam0_dev_data_##n; \
851 I2C_DEVICE_DT_INST_DEFINE(n, \
852 i2c_sam0_initialize, \
853 NULL, \
854 &i2c_sam0_dev_data_##n, \
855 &i2c_sam0_dev_config_##n, POST_KERNEL, \
856 CONFIG_I2C_INIT_PRIORITY, \
857 &i2c_sam0_driver_api); \
858 I2C_SAM0_IRQ_HANDLER(n)
859
860 DT_INST_FOREACH_STATUS_OKAY(I2C_SAM0_DEVICE)
861
862 /* clang-format on */
863