Lines Matching +full:master +full:- +full:access +full:- +full:mask
3 * Copyright (c) 2020-2023 Gerson Fernando Budke <nandojve@gmail.com>
5 * SPDX-License-Identifier: Apache-2.0
13 * I2C Master Mode with 7/10 bit addressing is currently supported.
33 #include "i2c-priv.h"
48 /** Status Clear Register Mask for No Acknowledgements */
50 /** Status Register Mask for No Acknowledgements */
52 /** Interrupt Enable Register Mask for No Acknowledgements */
54 /** Frequently used Interrupt Enable Register Mask */
56 /** Frequently used Status Clear Register Mask */
109 const struct i2c_sam_twim_dev_cfg *const cfg = dev->config; in i2c_clk_set()
110 Twim *const twim = cfg->regs; in i2c_clk_set()
126 return -EIO; in i2c_clk_set()
130 TWIM_HSCWGR_HIGH(f_prescaled - in i2c_clk_set()
140 twim->HSCWGR = cwgr_reg_val; in i2c_clk_set()
142 twim->CWGR = cwgr_reg_val; in i2c_clk_set()
150 twim->SRR = ((speed == BUS_SPEED_PLUS_HZ) ? TWIM_SRR_FILTER(2) : in i2c_clk_set()
152 TWIM_SRR_CLSLEW(cfg->std_clk_slew_lim) | in i2c_clk_set()
153 TWIM_SRR_CLDRIVEL(cfg->std_clk_strength_low) | in i2c_clk_set()
154 TWIM_SRR_DASLEW(cfg->std_data_slew_lim) | in i2c_clk_set()
155 TWIM_SRR_DADRIVEL(cfg->std_data_strength_low); in i2c_clk_set()
157 twim->HSSRR = TWIM_HSSRR_FILTER(1) | in i2c_clk_set()
158 TWIM_HSSRR_CLSLEW(cfg->hs_clk_slew_lim) | in i2c_clk_set()
159 TWIM_HSSRR_CLDRIVEH(cfg->hs_clk_strength_high) | in i2c_clk_set()
160 TWIM_HSSRR_CLDRIVEL(cfg->hs_clk_strength_low) | in i2c_clk_set()
161 TWIM_HSSRR_DASLEW(cfg->hs_data_slew_lim) | in i2c_clk_set()
162 TWIM_HSSRR_DADRIVEL(cfg->hs_data_strength_low); in i2c_clk_set()
173 LOG_ERR("Master Mode is not enabled"); in i2c_sam_twim_configure()
174 return -EIO; in i2c_sam_twim_configure()
178 LOG_ERR("I2C 10-bit addressing is currently not supported"); in i2c_sam_twim_configure()
180 return -EIO; in i2c_sam_twim_configure()
199 return -EIO; in i2c_sam_twim_configure()
215 if (data->next_nb_bytes > TWIM_MAX_NBYTES_PER_XFER) { in i2c_prepare_xfer_data()
216 data->cur_remaining = TWIM_MAX_NBYTES_PER_XFER; in i2c_prepare_xfer_data()
218 data->next_nb_bytes -= TWIM_MAX_NBYTES_PER_XFER; in i2c_prepare_xfer_data()
219 data->next_is_valid = true; in i2c_prepare_xfer_data()
220 data->next_need_rs = false; in i2c_prepare_xfer_data()
222 data->cur_remaining = data->next_nb_bytes; in i2c_prepare_xfer_data()
224 if ((data->msg_next_idx + 1) < data->msg_max_idx) { in i2c_prepare_xfer_data()
225 next_msg = &data->msgs[++data->msg_next_idx]; in i2c_prepare_xfer_data()
227 data->next_nb_bytes = next_msg->len; in i2c_prepare_xfer_data()
228 data->next_is_valid = true; in i2c_prepare_xfer_data()
229 data->next_need_rs = true; in i2c_prepare_xfer_data()
231 data->next_nb_bytes = 0; in i2c_prepare_xfer_data()
232 data->next_is_valid = false; in i2c_prepare_xfer_data()
233 data->next_need_rs = false; in i2c_prepare_xfer_data()
242 struct i2c_msg *next_msg = &data->msgs[next_msg_idx]; in i2c_prepare_xfer_cmd()
251 next_msg_is_read = ((next_msg->flags & I2C_MSG_RW_MASK) == in i2c_prepare_xfer_cmd()
258 if (data->next_need_rs) { in i2c_prepare_xfer_cmd()
265 if (data->next_nb_bytes > TWIM_MAX_NBYTES_PER_XFER) { in i2c_prepare_xfer_cmd()
272 next_nb_remaining = data->next_nb_bytes; in i2c_prepare_xfer_cmd()
275 if ((next_msg_idx + 1) >= data->msg_max_idx) { in i2c_prepare_xfer_cmd()
285 const struct i2c_sam_twim_dev_cfg *const cfg = dev->config; in i2c_start_xfer()
286 struct i2c_sam_twim_dev_data *data = dev->data; in i2c_start_xfer()
287 struct i2c_msg *msg = &data->msgs[0]; in i2c_start_xfer()
288 Twim *const twim = cfg->regs; in i2c_start_xfer()
294 twim->CR = TWIM_CR_MEN; in i2c_start_xfer()
295 twim->CR = TWIM_CR_SWRST; in i2c_start_xfer()
296 twim->CR = TWIM_CR_MDIS; in i2c_start_xfer()
297 twim->IDR = ~0UL; /* Clear the interrupt flags */ in i2c_start_xfer()
298 twim->SCR = ~0UL; /* Clear the status flags */ in i2c_start_xfer()
301 data->msg_cur_idx = 0; in i2c_start_xfer()
302 data->msg_next_idx = 0; in i2c_start_xfer()
304 /* pre-load current message to infer next */ in i2c_start_xfer()
305 data->next_nb_bytes = data->msgs[data->msg_next_idx].len; in i2c_start_xfer()
306 data->next_is_valid = false; in i2c_start_xfer()
307 data->next_need_rs = false; in i2c_start_xfer()
308 data->cur_remaining = 0; in i2c_start_xfer()
309 data->cur_idx = 0; in i2c_start_xfer()
311 LOG_DBG("Config first/next Transfer: msgs: %d", data->msg_max_idx); in i2c_start_xfer()
316 if (I2C_SPEED_GET(msg->flags) >= I2C_SPEED_HIGH) { in i2c_start_xfer()
318 TWIM_CMDR_HSMCODE(cfg->hs_master_code); in i2c_start_xfer()
321 if (msg->flags & I2C_MSG_ADDR_10_BITS) { in i2c_start_xfer()
325 if ((msg->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ && in i2c_start_xfer()
326 (msg->flags & I2C_MSG_ADDR_10_BITS)) { in i2c_start_xfer()
331 twim->CMDR = cmdr_reg | TWIM_CMDR_START; in i2c_start_xfer()
335 * previous transfer in order to enter master receiver mode. in i2c_start_xfer()
342 data->msg_next_idx = 0; in i2c_start_xfer()
345 cmdr_reg |= TWIM_CMDR_NBYTES(data->cur_remaining); in i2c_start_xfer()
346 twim->NCMDR = cmdr_reg | TWIM_CMDR_START; in i2c_start_xfer()
352 cmdr_reg |= TWIM_CMDR_NBYTES(data->cur_remaining); in i2c_start_xfer()
353 twim->CMDR = cmdr_reg | TWIM_CMDR_START; in i2c_start_xfer()
356 if (data->next_is_valid) { in i2c_start_xfer()
358 data->msg_next_idx); in i2c_start_xfer()
360 twim->NCMDR = cmdr_reg; in i2c_start_xfer()
365 twim->CMDR, twim->NCMDR); in i2c_start_xfer()
368 cmdr_reg = twim->CMDR; in i2c_start_xfer()
371 /* Enable master transfer */ in i2c_start_xfer()
372 twim->CR = TWIM_CR_MEN; in i2c_start_xfer()
374 twim->IER = TWIM_IER_STD_MASK | in i2c_start_xfer()
382 struct i2c_msg *msg = &data->msgs[data->msg_cur_idx]; in i2c_prepare_next()
388 if (data->cur_idx == msg->len) { in i2c_prepare_next()
389 data->cur_idx = 0; in i2c_prepare_next()
390 data->msg_cur_idx++; in i2c_prepare_next()
397 while ((twim->NCMDR & TWIM_NCMDR_VALID) && (ncmdr_wait--)) { in i2c_prepare_next()
401 cmdr_reg = twim->CMDR; in i2c_prepare_next()
403 twim->IER |= (cur_is_read ? TWIM_IER_RXRDY : TWIM_IER_TXRDY); in i2c_prepare_next()
406 if (data->next_nb_bytes == 0) { in i2c_prepare_next()
410 data_size = i2c_prepare_xfer_cmd(data, &cmdr_reg, data->msg_next_idx); in i2c_prepare_next()
412 twim->NCMDR = cmdr_reg; in i2c_prepare_next()
414 LOG_DBG("ld xfer: NCMDR: 0x%08x", twim->NCMDR); in i2c_prepare_next()
419 const struct i2c_sam_twim_dev_cfg *const cfg = dev->config; in i2c_sam_twim_isr()
420 struct i2c_sam_twim_dev_data *const data = dev->data; in i2c_sam_twim_isr()
421 Twim *const twim = cfg->regs; in i2c_sam_twim_isr()
422 struct i2c_msg *msg = &data->msgs[data->msg_cur_idx]; in i2c_sam_twim_isr()
426 isr_status = twim->SR & twim->IMR; in i2c_sam_twim_isr()
434 * otherwise the command will be re-sent. in i2c_sam_twim_isr()
436 twim->NCMDR &= ~TWIM_NCMDR_VALID; in i2c_sam_twim_isr()
437 twim->CMDR &= ~TWIM_CMDR_VALID; in i2c_sam_twim_isr()
439 data->cur_sr = isr_status; in i2c_sam_twim_isr()
443 data->cur_sr = 0; in i2c_sam_twim_isr()
447 msg->buf[data->cur_idx++] = twim->RHR; in i2c_sam_twim_isr()
448 data->cur_remaining--; in i2c_sam_twim_isr()
450 if (data->cur_remaining > 0) { in i2c_sam_twim_isr()
454 twim->IDR = TWIM_IDR_RXRDY; in i2c_sam_twim_isr()
457 if (data->next_is_valid && data->next_nb_bytes > 0) { in i2c_sam_twim_isr()
460 data->next_nb_bytes = 0; in i2c_sam_twim_isr()
467 if (data->cur_idx < msg->len) { in i2c_sam_twim_isr()
468 twim->THR = msg->buf[data->cur_idx++]; in i2c_sam_twim_isr()
469 data->cur_remaining--; in i2c_sam_twim_isr()
474 twim->IDR = TWIM_IDR_TXRDY; in i2c_sam_twim_isr()
477 if (data->next_is_valid && data->next_nb_bytes > 0) { in i2c_sam_twim_isr()
493 twim->IDR = ~0UL; in i2c_sam_twim_isr()
496 twim->SCR = ~0UL; in i2c_sam_twim_isr()
499 k_sem_give(&data->sem); in i2c_sam_twim_isr()
506 struct i2c_sam_twim_dev_data *data = dev->data; in i2c_sam_twim_transfer()
510 k_mutex_lock(&data->bus_mutex, K_FOREVER); in i2c_sam_twim_transfer()
513 data->msgs = msgs; in i2c_sam_twim_transfer()
514 data->msg_max_idx = num_msgs; in i2c_sam_twim_transfer()
519 k_sem_take(&data->sem, K_FOREVER); in i2c_sam_twim_transfer()
521 if (data->cur_sr & TWIM_SR_STD_MASK) { in i2c_sam_twim_transfer()
522 ret = -EIO; in i2c_sam_twim_transfer()
525 data->msg_cur_idx, in i2c_sam_twim_transfer()
526 (data->cur_sr & TWIM_SR_ANAK) > 0, in i2c_sam_twim_transfer()
527 (data->cur_sr & TWIM_SR_ARBLST) > 0); in i2c_sam_twim_transfer()
530 k_mutex_unlock(&data->bus_mutex); in i2c_sam_twim_transfer()
537 const struct i2c_sam_twim_dev_cfg *const cfg = dev->config; in i2c_sam_twim_initialize()
538 struct i2c_sam_twim_dev_data *data = dev->data; in i2c_sam_twim_initialize()
539 Twim *const twim = cfg->regs; in i2c_sam_twim_initialize()
544 cfg->irq_config(); in i2c_sam_twim_initialize()
548 * place to guarantee that each one is atomic and has exclusive access in i2c_sam_twim_initialize()
551 k_mutex_init(&data->bus_mutex); in i2c_sam_twim_initialize()
554 k_sem_init(&data->sem, 0, 1); in i2c_sam_twim_initialize()
557 ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); in i2c_sam_twim_initialize()
564 (clock_control_subsys_t)&cfg->clock_cfg); in i2c_sam_twim_initialize()
567 twim->CR = TWIM_CR_MEN; in i2c_sam_twim_initialize()
570 twim->CR |= TWIM_CR_SWRST; in i2c_sam_twim_initialize()
573 twim->SCR = ~0UL; in i2c_sam_twim_initialize()
575 bitrate_cfg = i2c_map_dt_bitrate(cfg->bitrate); in i2c_sam_twim_initialize()
579 LOG_ERR("Failed to initialize %s device", dev->name); in i2c_sam_twim_initialize()
584 irq_enable(cfg->irq_id); in i2c_sam_twim_initialize()
586 LOG_INF("Device %s initialized", dev->name); in i2c_sam_twim_initialize()