Lines Matching +full:fast +full:- +full:plus

4  * SPDX-License-Identifier: Apache-2.0
21 #include "i2c-priv.h"
73 while ((regs->SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_MASK) != 0) { in wait_synchronization()
77 while ((regs->STATUS.reg & SERCOM_I2CM_STATUS_SYNCBUSY) != 0) { in wait_synchronization()
86 struct i2c_sam0_dev_data *data = dev->data; in i2c_sam0_terminate_on_error()
87 const struct i2c_sam0_dev_config *const cfg = dev->config; in i2c_sam0_terminate_on_error()
88 SercomI2cm *i2c = cfg->regs; in i2c_sam0_terminate_on_error()
90 if (!(i2c->STATUS.reg & (SERCOM_I2CM_STATUS_ARBLOST | in i2c_sam0_terminate_on_error()
107 if (cfg->dma_channel != 0xFF) { in i2c_sam0_terminate_on_error()
108 dma_stop(cfg->dma_dev, cfg->dma_channel); in i2c_sam0_terminate_on_error()
112 data->msg.status = i2c->STATUS.reg; in i2c_sam0_terminate_on_error()
118 i2c->STATUS.reg = SERCOM_I2CM_STATUS_ARBLOST | in i2c_sam0_terminate_on_error()
126 i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK; in i2c_sam0_terminate_on_error()
127 if (i2c->INTFLAG.reg & (SERCOM_I2CM_INTFLAG_MB | SERCOM_I2CM_INTFLAG_SB)) { in i2c_sam0_terminate_on_error()
128 i2c->CTRLB.bit.CMD = 3; in i2c_sam0_terminate_on_error()
130 k_sem_give(&data->sem); in i2c_sam0_terminate_on_error()
136 struct i2c_sam0_dev_data *data = dev->data; in i2c_sam0_isr()
137 const struct i2c_sam0_dev_config *const cfg = dev->config; in i2c_sam0_isr()
138 SercomI2cm *i2c = cfg->regs; in i2c_sam0_isr()
141 uint32_t status = i2c->INTFLAG.reg; in i2c_sam0_isr()
143 i2c->INTFLAG.reg = status; in i2c_sam0_isr()
154 const bool continue_next = (data->msg.size == 1) && (data->num_msgs > 1) && in i2c_sam0_isr()
155 ((data->msgs[0].flags & I2C_MSG_RW_MASK) == in i2c_sam0_isr()
156 (data->msgs[1].flags & I2C_MSG_RW_MASK)) && in i2c_sam0_isr()
157 !(data->msgs[0].flags & I2C_MSG_STOP) && in i2c_sam0_isr()
158 !(data->msgs[1].flags & I2C_MSG_RESTART) && in i2c_sam0_isr()
162 if (!data->msg.size) { in i2c_sam0_isr()
163 i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK; in i2c_sam0_isr()
167 * - A repeated start can either be accomplished by writing a 0x1 in i2c_sam0_isr()
168 * to the CMD field, or by writing to ADDR - which is what this in i2c_sam0_isr()
170 * - A stop is accomplished by writing a 0x3 to CMD (below). in i2c_sam0_isr()
173 * data->msg.size is already zero (not one), and i2c_sam0_transfer() in i2c_sam0_isr()
176 if ((data->num_msgs <= 1) in i2c_sam0_isr()
177 || (data->msgs[0].flags & I2C_MSG_STOP) in i2c_sam0_isr()
178 || !(data->msgs[1].flags & I2C_MSG_RESTART)) { in i2c_sam0_isr()
179 i2c->CTRLB.bit.CMD = 3; in i2c_sam0_isr()
182 k_sem_give(&data->sem); in i2c_sam0_isr()
186 i2c->DATA.reg = *data->msg.buffer; in i2c_sam0_isr()
187 data->msg.buffer++; in i2c_sam0_isr()
188 data->msg.size--; in i2c_sam0_isr()
190 if (!continue_next && (data->msg.size == 1)) { in i2c_sam0_isr()
196 i2c->CTRLB.bit.ACKACT = 1; in i2c_sam0_isr()
197 i2c->CTRLB.bit.CMD = 3; in i2c_sam0_isr()
200 *data->msg.buffer = i2c->DATA.reg; in i2c_sam0_isr()
201 data->msg.buffer++; in i2c_sam0_isr()
202 data->msg.size--; in i2c_sam0_isr()
204 if (!continue_next && !data->msg.size) { in i2c_sam0_isr()
205 i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK; in i2c_sam0_isr()
206 k_sem_give(&data->sem); in i2c_sam0_isr()
212 data->msgs++; in i2c_sam0_isr()
213 data->num_msgs--; in i2c_sam0_isr()
215 data->msg.buffer = data->msgs->buf; in i2c_sam0_isr()
216 data->msg.size = data->msgs->len; in i2c_sam0_isr()
217 data->msg.status = 0; in i2c_sam0_isr()
227 struct i2c_sam0_dev_data *data = dev->data; in i2c_sam0_dma_write_done()
228 const struct i2c_sam0_dev_config *const cfg = dev->config; in i2c_sam0_dma_write_done()
229 SercomI2cm *i2c = cfg->regs; in i2c_sam0_dma_write_done()
242 LOG_ERR("DMA write error on %s: %d", dev->name, error_code); in i2c_sam0_dma_write_done()
243 i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK; in i2c_sam0_dma_write_done()
246 data->msg.status = error_code; in i2c_sam0_dma_write_done()
248 k_sem_give(&data->sem); in i2c_sam0_dma_write_done()
258 data->msg.size = 0; in i2c_sam0_dma_write_done()
259 i2c->INTENSET.reg = SERCOM_I2CM_INTENSET_MB; in i2c_sam0_dma_write_done()
264 struct i2c_sam0_dev_data *data = dev->data; in i2c_sam0_dma_write_start()
265 const struct i2c_sam0_dev_config *const cfg = dev->config; in i2c_sam0_dma_write_start()
266 SercomI2cm *i2c = cfg->regs; in i2c_sam0_dma_write_start()
269 if (cfg->dma_channel == 0xFF) { in i2c_sam0_dma_write_start()
273 if (data->msg.size <= 1) { in i2c_sam0_dma_write_start()
290 dma_cfg.dma_slot = cfg->write_dma_request; in i2c_sam0_dma_write_start()
292 dma_blk.block_size = data->msg.size; in i2c_sam0_dma_write_start()
293 dma_blk.source_address = (uint32_t)data->msg.buffer; in i2c_sam0_dma_write_start()
294 dma_blk.dest_address = (uint32_t)(&(i2c->DATA.reg)); in i2c_sam0_dma_write_start()
297 retval = dma_config(cfg->dma_dev, cfg->dma_channel, &dma_cfg); in i2c_sam0_dma_write_start()
300 dev->name, retval); in i2c_sam0_dma_write_start()
304 retval = dma_start(cfg->dma_dev, cfg->dma_channel); in i2c_sam0_dma_write_start()
307 dev->name, retval); in i2c_sam0_dma_write_start()
318 struct i2c_sam0_dev_data *data = dev->data; in i2c_sam0_dma_read_done()
319 const struct i2c_sam0_dev_config *const cfg = dev->config; in i2c_sam0_dma_read_done()
320 SercomI2cm *i2c = cfg->regs; in i2c_sam0_dma_read_done()
333 LOG_ERR("DMA read error on %s: %d", dev->name, error_code); in i2c_sam0_dma_read_done()
334 i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK; in i2c_sam0_dma_read_done()
337 data->msg.status = error_code; in i2c_sam0_dma_read_done()
339 k_sem_give(&data->sem); in i2c_sam0_dma_read_done()
349 data->msg.buffer += data->msg.size - 1; in i2c_sam0_dma_read_done()
350 data->msg.size = 1; in i2c_sam0_dma_read_done()
351 i2c->INTENSET.reg = SERCOM_I2CM_INTENSET_SB; in i2c_sam0_dma_read_done()
356 struct i2c_sam0_dev_data *data = dev->data; in i2c_sam0_dma_read_start()
357 const struct i2c_sam0_dev_config *const cfg = dev->config; in i2c_sam0_dma_read_start()
358 SercomI2cm *i2c = cfg->regs; in i2c_sam0_dma_read_start()
361 if (cfg->dma_channel == 0xFF) { in i2c_sam0_dma_read_start()
365 if (data->msg.size <= 2) { in i2c_sam0_dma_read_start()
383 dma_cfg.dma_slot = cfg->read_dma_request; in i2c_sam0_dma_read_start()
385 dma_blk.block_size = data->msg.size - 1; in i2c_sam0_dma_read_start()
386 dma_blk.dest_address = (uint32_t)data->msg.buffer; in i2c_sam0_dma_read_start()
387 dma_blk.source_address = (uint32_t)(&(i2c->DATA.reg)); in i2c_sam0_dma_read_start()
390 retval = dma_config(cfg->dma_dev, cfg->dma_channel, &dma_cfg); in i2c_sam0_dma_read_start()
393 dev->name, retval); in i2c_sam0_dma_read_start()
397 retval = dma_start(cfg->dma_dev, cfg->dma_channel); in i2c_sam0_dma_read_start()
400 dev->name, retval); in i2c_sam0_dma_read_start()
412 struct i2c_sam0_dev_data *data = dev->data; in i2c_sam0_transfer()
413 const struct i2c_sam0_dev_config *const cfg = dev->config; in i2c_sam0_transfer()
414 SercomI2cm *i2c = cfg->regs; in i2c_sam0_transfer()
422 k_sem_take(&data->lock, K_FOREVER); in i2c_sam0_transfer()
424 data->num_msgs = num_msgs; in i2c_sam0_transfer()
425 data->msgs = msgs; in i2c_sam0_transfer()
427 for (; data->num_msgs > 0;) { in i2c_sam0_transfer()
428 if (!data->msgs->len) { in i2c_sam0_transfer()
429 if ((data->msgs->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) { in i2c_sam0_transfer()
430 ret = -EINVAL; in i2c_sam0_transfer()
435 i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK; in i2c_sam0_transfer()
436 i2c->INTFLAG.reg = SERCOM_I2CM_INTFLAG_MASK; in i2c_sam0_transfer()
438 i2c->STATUS.reg = SERCOM_I2CM_STATUS_ARBLOST | in i2c_sam0_transfer()
446 data->msg.buffer = data->msgs->buf; in i2c_sam0_transfer()
447 data->msg.size = data->msgs->len; in i2c_sam0_transfer()
448 data->msg.status = 0; in i2c_sam0_transfer()
451 if ((data->msgs->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) { in i2c_sam0_transfer()
455 i2c->CTRLB.bit.ACKACT = 0; in i2c_sam0_transfer()
459 if (data->msgs->flags & I2C_MSG_ADDR_10_BITS) { in i2c_sam0_transfer()
463 ret = -ENOTSUP; in i2c_sam0_transfer()
474 i2c->ADDR.reg = addr_reg; in i2c_sam0_transfer()
484 i2c->INTENSET.reg = SERCOM_I2CM_INTENSET_ERROR; in i2c_sam0_transfer()
487 if ((data->msgs->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) { in i2c_sam0_transfer()
492 i2c->INTENSET.reg = SERCOM_I2CM_INTENSET_MB; in i2c_sam0_transfer()
498 i2c->INTENSET.reg = SERCOM_I2CM_INTENSET_SB; in i2c_sam0_transfer()
506 i2c->INTENSET.reg = SERCOM_I2CM_INTENSET_MB; in i2c_sam0_transfer()
513 ret = k_sem_take(&data->sem, I2C_TRANSFER_TIMEOUT_MSEC); in i2c_sam0_transfer()
516 ret = -EIO; in i2c_sam0_transfer()
520 if (data->msg.status) { in i2c_sam0_transfer()
521 if (data->msg.status & SERCOM_I2CM_STATUS_ARBLOST) { in i2c_sam0_transfer()
523 dev->name); in i2c_sam0_transfer()
524 ret = -EAGAIN; in i2c_sam0_transfer()
529 dev->name, data->msg.status); in i2c_sam0_transfer()
530 ret = -EIO; in i2c_sam0_transfer()
534 data->num_msgs--; in i2c_sam0_transfer()
535 data->msgs++; in i2c_sam0_transfer()
540 k_sem_give(&data->lock); in i2c_sam0_transfer()
548 const struct i2c_sam0_dev_config *const cfg = dev->config; in i2c_sam0_set_apply_bitrate()
549 SercomI2cm *i2c = cfg->regs; in i2c_sam0_set_apply_bitrate()
554 uint32_t CTRLA = i2c->CTRLA.reg; in i2c_sam0_set_apply_bitrate()
567 i2c->CTRLA.reg = CTRLA; in i2c_sam0_set_apply_bitrate()
571 baud = (SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / 100000U - 5U - 10U) / 2U; in i2c_sam0_set_apply_bitrate()
573 return -ERANGE; in i2c_sam0_set_apply_bitrate()
577 dev->name, baud); in i2c_sam0_set_apply_bitrate()
579 i2c->BAUD.reg = SERCOM_I2CM_BAUD_BAUD(baud); in i2c_sam0_set_apply_bitrate()
584 i2c->CTRLA.reg = CTRLA; in i2c_sam0_set_apply_bitrate()
588 baud = (SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / 400000U - 5U - 10U) / 2U; in i2c_sam0_set_apply_bitrate()
590 return -ERANGE; in i2c_sam0_set_apply_bitrate()
593 LOG_DBG("Setting %s to fast mode with divisor %u", in i2c_sam0_set_apply_bitrate()
594 dev->name, baud); in i2c_sam0_set_apply_bitrate()
596 i2c->BAUD.reg = SERCOM_I2CM_BAUD_BAUD(baud); in i2c_sam0_set_apply_bitrate()
604 i2c->CTRLA.reg = CTRLA; in i2c_sam0_set_apply_bitrate()
608 baud = (SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / 1000000U - 5U - 10U); in i2c_sam0_set_apply_bitrate()
614 baud_low = baud - baud_high; in i2c_sam0_set_apply_bitrate()
616 --baud_high; in i2c_sam0_set_apply_bitrate()
621 return -ERANGE; in i2c_sam0_set_apply_bitrate()
624 LOG_DBG("Setting %s to fast mode plus with divisors %u/%u", in i2c_sam0_set_apply_bitrate()
625 dev->name, baud_high, baud_low); in i2c_sam0_set_apply_bitrate()
627 i2c->BAUD.reg = SERCOM_I2CM_BAUD_BAUD(baud_high) | in i2c_sam0_set_apply_bitrate()
636 i2c->CTRLA.reg = CTRLA; in i2c_sam0_set_apply_bitrate()
639 baud = (SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / 3400000U) - 2U; in i2c_sam0_set_apply_bitrate()
645 baud_low = baud - baud_high; in i2c_sam0_set_apply_bitrate()
647 --baud_high; in i2c_sam0_set_apply_bitrate()
652 return -ERANGE; in i2c_sam0_set_apply_bitrate()
657 dev->name, baud_high, baud_low); in i2c_sam0_set_apply_bitrate()
663 i2c->BAUD.reg = SERCOM_I2CM_BAUD_HSBAUD(baud_high) | in i2c_sam0_set_apply_bitrate()
668 return -ENOTSUP; in i2c_sam0_set_apply_bitrate()
673 return -ENOTSUP; in i2c_sam0_set_apply_bitrate()
682 const struct i2c_sam0_dev_config *const cfg = dev->config; in i2c_sam0_configure()
683 SercomI2cm *i2c = cfg->regs; in i2c_sam0_configure()
687 return -EINVAL; in i2c_sam0_configure()
691 i2c->CTRLA.bit.ENABLE = 0; in i2c_sam0_configure()
696 i2c->CTRLA.bit.ENABLE = 1; in i2c_sam0_configure()
709 struct i2c_sam0_dev_data *data = dev->data; in i2c_sam0_initialize()
710 const struct i2c_sam0_dev_config *const cfg = dev->config; in i2c_sam0_initialize()
711 SercomI2cm *i2c = cfg->regs; in i2c_sam0_initialize()
716 GCLK->PCHCTRL[cfg->gclk_core_id].reg = GCLK_PCHCTRL_GEN_GCLK0 | in i2c_sam0_initialize()
719 *cfg->mclk |= cfg->mclk_mask; in i2c_sam0_initialize()
722 GCLK->CLKCTRL.reg = cfg->gclk_clkctrl_id | GCLK_CLKCTRL_GEN_GCLK0 | in i2c_sam0_initialize()
726 PM->APBCMASK.reg |= cfg->pm_apbcmask; in i2c_sam0_initialize()
729 i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK; in i2c_sam0_initialize()
731 retval = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); in i2c_sam0_initialize()
737 i2c->CTRLA.reg = SERCOM_I2CM_CTRLA_MODE_I2C_MASTER | in i2c_sam0_initialize()
745 i2c->CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN; in i2c_sam0_initialize()
749 i2c_map_dt_bitrate(cfg->bitrate)); in i2c_sam0_initialize()
754 k_sem_init(&data->lock, 1, 1); in i2c_sam0_initialize()
755 k_sem_init(&data->sem, 0, 1); in i2c_sam0_initialize()
757 cfg->irq_config_func(dev); in i2c_sam0_initialize()
760 if (!device_is_ready(cfg->dma_dev)) { in i2c_sam0_initialize()
761 return -ENODEV; in i2c_sam0_initialize()
765 i2c->CTRLA.bit.ENABLE = 1; in i2c_sam0_initialize()
769 i2c->STATUS.bit.BUSSTATE = 1; in i2c_sam0_initialize()