Lines Matching +full:fifo +full:- +full:read +full:- +full:threshold

1 /* dw_i2c.c - I2C file for Design Ware */
5 * Copyright (c) 2022 Andrei-Edward Popa
7 * SPDX-License-Identifier: Apache-2.0
49 #include "i2c-priv.h"
76 const struct i2c_dw_rom_config *const rom = dev->config; in cb_i2c_idma_transfer()
77 struct i2c_dw_dev_config *const dw = dev->data; in cb_i2c_idma_transfer()
79 dma_stop(rom->dma_dev, channel); in cb_i2c_idma_transfer()
83 dw->xfr_status = true; in cb_i2c_idma_transfer()
85 dw->xfr_status = false; in cb_i2c_idma_transfer()
94 write_rdlr(fifo_depth - 1, reg_base); in i2c_dw_set_fifo_th()
99 struct i2c_dw_dev_config *const dw = dev->data; in i2c_dw_dr_phy_addr()
101 return (void *)(dw->phy_addr + DW_IC_REG_DATA_CMD); in i2c_dw_dr_phy_addr()
106 struct i2c_dw_dev_config *const dw = dev->data; in i2c_dw_idma_rx_transfer()
107 const struct i2c_dw_rom_config *const rom = dev->config; in i2c_dw_idma_rx_transfer()
112 if (!device_is_ready(rom->dma_dev)) { in i2c_dw_idma_rx_transfer()
114 return -ENODEV; in i2c_dw_idma_rx_transfer()
130 dma_block_cfg.block_size = dw->xfr_len; in i2c_dw_idma_rx_transfer()
131 dma_block_cfg.dest_address = (uint64_t)&dw->xfr_buf[0]; in i2c_dw_idma_rx_transfer()
133 dw->xfr_status = false; in i2c_dw_idma_rx_transfer()
135 if (dma_config(rom->dma_dev, DMA_INTEL_LPSS_RX_CHAN, &dma_cfg)) { in i2c_dw_idma_rx_transfer()
137 return -EIO; in i2c_dw_idma_rx_transfer()
140 if (dma_start(rom->dma_dev, DMA_INTEL_LPSS_RX_CHAN)) { in i2c_dw_idma_rx_transfer()
142 return -EIO; in i2c_dw_idma_rx_transfer()
153 const struct i2c_dw_rom_config *const rom = dev->config; in i2c_dw_idma_tx_transfer()
154 struct i2c_dw_dev_config *const dw = dev->data; in i2c_dw_idma_tx_transfer()
159 if (!device_is_ready(rom->dma_dev)) { in i2c_dw_idma_tx_transfer()
161 return -ENODEV; in i2c_dw_idma_tx_transfer()
180 dw->xfr_status = false; in i2c_dw_idma_tx_transfer()
182 if (dma_config(rom->dma_dev, DMA_INTEL_LPSS_TX_CHAN, &dma_cfg)) { in i2c_dw_idma_tx_transfer()
184 return -EIO; in i2c_dw_idma_tx_transfer()
187 if (dma_start(rom->dma_dev, DMA_INTEL_LPSS_TX_CHAN)) { in i2c_dw_idma_tx_transfer()
189 return -EIO; in i2c_dw_idma_tx_transfer()
200 struct i2c_dw_dev_config *const dw = dev->data; in i2c_dw_data_ask()
210 if (dw->request_bytes == 0U) { in i2c_dw_data_ask()
215 /* Get the FIFO depth that could be from 2 to 256 from HW spec */ in i2c_dw_data_ask()
221 rx_empty = (rx_buffer_depth - read_rxflr(reg_base)) - dw->rx_pending; in i2c_dw_data_ask()
224 /* RX FIFO expected to be full. in i2c_dw_data_ask()
230 /* How many empty slots in TX FIFO (as command queue) */ in i2c_dw_data_ask()
231 tx_empty = tx_buffer_depth - read_txflr(reg_base); in i2c_dw_data_ask()
234 cnt = MIN(rx_buffer_depth, dw->request_bytes); in i2c_dw_data_ask()
242 if (dw->xfr_flags & I2C_MSG_RESTART) { in i2c_dw_data_ask()
244 dw->xfr_flags &= ~(I2C_MSG_RESTART); in i2c_dw_data_ask()
248 if ((dw->xfr_flags & I2C_MSG_STOP) && (dw->request_bytes == 1U)) { in i2c_dw_data_ask()
258 dw->rx_pending++; in i2c_dw_data_ask()
259 dw->request_bytes--; in i2c_dw_data_ask()
260 cnt--; in i2c_dw_data_ask()
266 struct i2c_dw_dev_config *const dw = dev->data; in i2c_dw_data_read()
270 if (test_bit_status_rfne(reg_base) && (dw->xfr_len > 0)) { in i2c_dw_data_read()
272 dw->xfr_len = 0; in i2c_dw_data_read()
273 dw->rx_pending = 0; in i2c_dw_data_read()
276 while (test_bit_status_rfne(reg_base) && (dw->xfr_len > 0)) { in i2c_dw_data_read()
277 dw->xfr_buf[0] = (uint8_t)read_cmd_data(reg_base); in i2c_dw_data_read()
279 dw->xfr_buf++; in i2c_dw_data_read()
280 dw->xfr_len--; in i2c_dw_data_read()
281 dw->rx_pending--; in i2c_dw_data_read()
283 if (dw->xfr_len == 0U) { in i2c_dw_data_read()
289 if (dw->xfr_len == 0U) { in i2c_dw_data_read()
290 dw->state &= ~I2C_DW_CMD_RECV; in i2c_dw_data_read()
297 struct i2c_dw_dev_config *const dw = dev->data; in i2c_dw_data_send()
302 if (dw->xfr_len == 0U) { in i2c_dw_data_send()
305 dw->state &= ~I2C_DW_CMD_SEND; in i2c_dw_data_send()
310 while (test_bit_status_tfnt(reg_base) && (dw->xfr_len > 0)) { in i2c_dw_data_send()
312 data = dw->xfr_buf[0]; in i2c_dw_data_send()
315 if (dw->xfr_flags & I2C_MSG_RESTART) { in i2c_dw_data_send()
317 dw->xfr_flags &= ~(I2C_MSG_RESTART); in i2c_dw_data_send()
321 if ((dw->xfr_len == 1U) && (dw->xfr_flags & I2C_MSG_STOP)) { in i2c_dw_data_send()
330 dw->xfr_len--; in i2c_dw_data_send()
331 dw->xfr_buf++; in i2c_dw_data_send()
334 return -EIO; in i2c_dw_data_send()
343 struct i2c_dw_dev_config *const dw = dev->data; in i2c_dw_transfer_complete()
350 k_sem_give(&dw->device_sync_sem); in i2c_dw_transfer_complete()
361 struct i2c_dw_dev_config *const dw = port->data; in i2c_dw_isr()
367 /* Cache ic_intr_stat for processing, so there is no need to read in i2c_dw_isr()
374 * - STOP condition is detected in i2c_dw_isr()
375 * - Transfer is aborted in i2c_dw_isr()
376 * - Transmit FIFO is empty in i2c_dw_isr()
377 * - Transmit FIFO has overflowed in i2c_dw_isr()
378 * - Receive FIFO is full in i2c_dw_isr()
379 * - Receive FIFO has overflowed in i2c_dw_isr()
380 * - Received FIFO has underrun in i2c_dw_isr()
381 * - Transmit data is required (tx_req) in i2c_dw_isr()
382 * - Receive data is available (rx_avail) in i2c_dw_isr()
393 const struct i2c_dw_rom_config *const rom = port->config; in i2c_dw_isr()
395 dma_intel_lpss_isr(rom->dma_dev); in i2c_dw_isr()
403 dw->state = I2C_DW_CMD_ERROR; in i2c_dw_isr()
407 /* Check if the RX FIFO reached threshold */ in i2c_dw_isr()
413 /* Check if the TX FIFO is ready for commands. in i2c_dw_isr()
414 * TX FIFO also serves as command queue where read requests in i2c_dw_isr()
415 * are written to TX FIFO. in i2c_dw_isr()
417 if ((dw->xfr_flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) { in i2c_dw_isr()
423 if ((dw->xfr_flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) { in i2c_dw_isr()
432 if (((dw->xfr_len == 0U) && !(dw->xfr_flags & I2C_MSG_STOP)) || in i2c_dw_isr()
446 const struct i2c_target_callbacks *slave_cb = dw->slave_cfg->callbacks; in i2c_dw_isr()
453 if (dw->state != I2C_DW_CMD_SEND) { in i2c_dw_isr()
454 dw->state = I2C_DW_CMD_SEND; in i2c_dw_isr()
455 if (slave_cb->write_requested) { in i2c_dw_isr()
456 slave_cb->write_requested(dw->slave_cfg); in i2c_dw_isr()
459 /* FIFO needs to be drained here so we don't miss the next interrupt */ in i2c_dw_isr()
462 if (slave_cb->write_received) { in i2c_dw_isr()
463 slave_cb->write_received(dw->slave_cfg, data); in i2c_dw_isr()
471 dw->state = I2C_DW_CMD_RECV; in i2c_dw_isr()
472 if (slave_cb->read_requested) { in i2c_dw_isr()
473 slave_cb->read_requested(dw->slave_cfg, &data); in i2c_dw_isr()
476 if (slave_cb->read_processed) { in i2c_dw_isr()
477 slave_cb->read_processed(dw->slave_cfg, &data); in i2c_dw_isr()
492 struct i2c_dw_dev_config *const dw = dev->data; in i2c_dw_setup()
509 /* Set master or slave mode - (initialization = slave) */ in i2c_dw_setup()
510 if (I2C_MODE_CONTROLLER & dw->app_config) { in i2c_dw_setup()
519 return -EINVAL; in i2c_dw_setup()
524 /* Set addressing mode - (initialization = 7 bit) */ in i2c_dw_setup()
525 if (I2C_ADDR_10_BITS & dw->app_config) { in i2c_dw_setup()
526 LOG_DBG("I2C: using 10-bit address"); in i2c_dw_setup()
532 switch (I2C_SPEED_GET(dw->app_config)) { in i2c_dw_setup()
535 write_ss_scl_lcnt(dw->lcnt, reg_base); in i2c_dw_setup()
536 write_ss_scl_hcnt(dw->hcnt, reg_base); in i2c_dw_setup()
544 write_fs_scl_lcnt(dw->lcnt, reg_base); in i2c_dw_setup()
545 write_fs_scl_hcnt(dw->hcnt, reg_base); in i2c_dw_setup()
550 if (!dw->support_hs_mode) { in i2c_dw_setup()
551 return -EINVAL; in i2c_dw_setup()
555 write_hs_scl_lcnt(dw->lcnt, reg_base); in i2c_dw_setup()
556 write_hs_scl_hcnt(dw->hcnt, reg_base); in i2c_dw_setup()
562 return -EINVAL; in i2c_dw_setup()
565 LOG_DBG("I2C: lcnt = %d", dw->lcnt); in i2c_dw_setup()
566 LOG_DBG("I2C: hcnt = %d", dw->hcnt); in i2c_dw_setup()
571 /* Set RX fifo threshold level. in i2c_dw_setup()
575 * TODO: extend the threshold for multi-byte RX. in i2c_dw_setup()
579 /* Set TX fifo threshold level. in i2c_dw_setup()
581 * TX FIFO is truly empty. So that we can let in i2c_dw_setup()
583 * before we need to fill the FIFO again. This may in i2c_dw_setup()
602 * its transfers in 7-bit or 10-bit addressing mode. in i2c_dw_setup()
604 if (I2C_MODE_CONTROLLER & dw->app_config) { in i2c_dw_setup()
605 if (I2C_ADDR_10_BITS & dw->app_config) { in i2c_dw_setup()
620 struct i2c_dw_dev_config *const dw = dev->data; in i2c_dw_transfer()
633 ret = k_mutex_lock(&dw->bus_mutex, K_FOREVER); in i2c_dw_transfer()
639 if (test_bit_status_activity(reg_base) || (dw->state & I2C_DW_BUSY)) { in i2c_dw_transfer()
640 ret = -EBUSY; in i2c_dw_transfer()
644 dw->state |= I2C_DW_BUSY; in i2c_dw_transfer()
671 if ((cur_msg->len == 0) && (cur_msg->buf != NULL)) { in i2c_dw_transfer()
672 cur_msg->len = 1; in i2c_dw_transfer()
675 pflags = dw->xfr_flags; in i2c_dw_transfer()
677 dw->xfr_buf = cur_msg->buf; in i2c_dw_transfer()
678 dw->xfr_len = cur_msg->len; in i2c_dw_transfer()
679 dw->xfr_flags = cur_msg->flags; in i2c_dw_transfer()
680 dw->rx_pending = 0U; in i2c_dw_transfer()
683 if ((pflags & I2C_MSG_RW_MASK) != (dw->xfr_flags & I2C_MSG_RW_MASK)) { in i2c_dw_transfer()
684 dw->xfr_flags |= I2C_MSG_RESTART; in i2c_dw_transfer()
687 dw->state &= ~(I2C_DW_CMD_SEND | I2C_DW_CMD_RECV); in i2c_dw_transfer()
689 if ((dw->xfr_flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) { in i2c_dw_transfer()
690 dw->state |= I2C_DW_CMD_SEND; in i2c_dw_transfer()
691 dw->request_bytes = 0U; in i2c_dw_transfer()
693 dw->state |= I2C_DW_CMD_RECV; in i2c_dw_transfer()
694 dw->request_bytes = dw->xfr_len; in i2c_dw_transfer()
708 ret = k_sem_take(&dw->device_sync_sem, K_MSEC(CONFIG_I2C_DW_RW_TIMEOUT_MS)); in i2c_dw_transfer()
715 if (dw->state & I2C_DW_CMD_ERROR) { in i2c_dw_transfer()
716 ret = -EIO; in i2c_dw_transfer()
721 if (dw->xfr_len > 0) { in i2c_dw_transfer()
722 ret = -EIO; in i2c_dw_transfer()
727 msg_left--; in i2c_dw_transfer()
733 dw->state = I2C_DW_STATE_READY; in i2c_dw_transfer()
734 k_mutex_unlock(&dw->bus_mutex); in i2c_dw_transfer()
741 struct i2c_dw_dev_config *const dw = dev->data; in i2c_dw_runtime_configure()
742 const struct i2c_dw_rom_config *const rom = dev->config; in i2c_dw_runtime_configure()
747 dw->app_config = config; in i2c_dw_runtime_configure()
751 switch (I2C_SPEED_GET(dw->app_config)) { in i2c_dw_runtime_configure()
756 value = I2C_STD_LCNT + rom->lcnt_offset; in i2c_dw_runtime_configure()
761 dw->lcnt = value; in i2c_dw_runtime_configure()
766 value = I2C_STD_HCNT + rom->hcnt_offset; in i2c_dw_runtime_configure()
771 dw->hcnt = value; in i2c_dw_runtime_configure()
778 value = I2C_FS_LCNT + rom->lcnt_offset; in i2c_dw_runtime_configure()
783 dw->lcnt = value; in i2c_dw_runtime_configure()
789 value = I2C_FS_HCNT + rom->hcnt_offset; in i2c_dw_runtime_configure()
794 dw->hcnt = value; in i2c_dw_runtime_configure()
801 value = I2C_FSP_LCNT + rom->lcnt_offset; in i2c_dw_runtime_configure()
806 dw->lcnt = value; in i2c_dw_runtime_configure()
812 value = I2C_FSP_HCNT + rom->hcnt_offset; in i2c_dw_runtime_configure()
817 dw->hcnt = value; in i2c_dw_runtime_configure()
820 if (dw->support_hs_mode) { in i2c_dw_runtime_configure()
821 value = I2C_HS_LCNT + rom->lcnt_offset; in i2c_dw_runtime_configure()
826 dw->lcnt = value; in i2c_dw_runtime_configure()
828 value = I2C_HS_HCNT + rom->hcnt_offset; in i2c_dw_runtime_configure()
833 dw->hcnt = value; in i2c_dw_runtime_configure()
835 rc = -EINVAL; in i2c_dw_runtime_configure()
840 rc = -EINVAL; in i2c_dw_runtime_configure()
849 * TEMPORARY HACK - The I2C does not work in any mode other than Master in i2c_dw_runtime_configure()
853 dw->app_config |= I2C_MODE_CONTROLLER; in i2c_dw_runtime_configure()
863 if (!test_bit_status_rfne(reg_base)) { /* Rx FIFO must not be empty */ in i2c_dw_read_byte_non_blocking()
864 return -EIO; in i2c_dw_read_byte_non_blocking()
874 if (!test_bit_status_tfnt(reg_base)) { /* Tx FIFO must not be full */ in i2c_dw_write_byte_non_blocking()
935 struct i2c_dw_dev_config *const dw = dev->data; in i2c_dw_slave_register()
939 dw->slave_cfg = cfg; in i2c_dw_slave_register()
940 ret = i2c_dw_set_slave_mode(dev, cfg->address); in i2c_dw_slave_register()
950 struct i2c_dw_dev_config *const dw = dev->data; in i2c_dw_slave_unregister()
953 dw->state = I2C_DW_STATE_READY; in i2c_dw_slave_unregister()
961 struct i2c_dw_dev_config *const dw = dev->data; in i2c_dw_slave_read_clear_intr_bits()
965 const struct i2c_target_callbacks *slave_cb = dw->slave_cfg->callbacks; in i2c_dw_slave_read_clear_intr_bits()
971 dw->state = I2C_DW_STATE_READY; in i2c_dw_slave_read_clear_intr_bits()
976 dw->state = I2C_DW_STATE_READY; in i2c_dw_slave_read_clear_intr_bits()
981 dw->state = I2C_DW_STATE_READY; in i2c_dw_slave_read_clear_intr_bits()
986 dw->state = I2C_DW_STATE_READY; in i2c_dw_slave_read_clear_intr_bits()
991 dw->state = I2C_DW_STATE_READY; in i2c_dw_slave_read_clear_intr_bits()
996 dw->state = I2C_DW_STATE_READY; in i2c_dw_slave_read_clear_intr_bits()
1001 dw->state = I2C_DW_STATE_READY; in i2c_dw_slave_read_clear_intr_bits()
1002 if (slave_cb->stop) { in i2c_dw_slave_read_clear_intr_bits()
1003 slave_cb->stop(dw->slave_cfg); in i2c_dw_slave_read_clear_intr_bits()
1009 dw->state = I2C_DW_STATE_READY; in i2c_dw_slave_read_clear_intr_bits()
1014 dw->state = I2C_DW_STATE_READY; in i2c_dw_slave_read_clear_intr_bits()
1033 const struct i2c_dw_rom_config *const rom = dev->config; in i2c_dw_initialize()
1034 struct i2c_dw_dev_config *const dw = dev->data; in i2c_dw_initialize()
1039 if (rom->reset.dev) { in i2c_dw_initialize()
1040 ret = reset_line_toggle_dt(&rom->reset); in i2c_dw_initialize()
1048 ret = pinctrl_apply_state(rom->pcfg, PINCTRL_STATE_DEFAULT); in i2c_dw_initialize()
1055 if (rom->pcie) { in i2c_dw_initialize()
1058 if (rom->pcie->bdf == PCIE_BDF_NONE) { in i2c_dw_initialize()
1059 return -EINVAL; in i2c_dw_initialize()
1062 pcie_probe_mbar(rom->pcie->bdf, 0, &mbar); in i2c_dw_initialize()
1063 pcie_set_cmd(rom->pcie->bdf, PCIE_CONF_CMDSTAT_MEM, true); in i2c_dw_initialize()
1067 pcie_set_cmd(rom->pcie->bdf, PCIE_CONF_CMDSTAT_MASTER, true); in i2c_dw_initialize()
1073 dma_intel_lpss_set_base(rom->dma_dev, base); in i2c_dw_initialize()
1074 dma_intel_lpss_setup(rom->dma_dev); in i2c_dw_initialize()
1077 dw->phy_addr = mbar.phys_addr; in i2c_dw_initialize()
1078 dw->base_addr = (uint32_t)(DEVICE_MMIO_GET(dev) + DMA_INTEL_LPSS_OFFSET); in i2c_dw_initialize()
1079 sys_write32((uint32_t)dw->phy_addr, in i2c_dw_initialize()
1081 sys_write32((uint32_t)(dw->phy_addr >> DMA_INTEL_LPSS_ADDR_RIGHT_SHIFT), in i2c_dw_initialize()
1083 LOG_DBG("i2c instance physical addr: [0x%lx], virtual addr: [0x%lx]", dw->phy_addr, in i2c_dw_initialize()
1084 dw->base_addr); in i2c_dw_initialize()
1092 k_sem_init(&dw->device_sync_sem, 0, K_SEM_MAX_LIMIT); in i2c_dw_initialize()
1093 k_mutex_init(&dw->bus_mutex); in i2c_dw_initialize()
1103 return -EIO; in i2c_dw_initialize()
1114 dw->support_hs_mode = true; in i2c_dw_initialize()
1117 dw->support_hs_mode = false; in i2c_dw_initialize()
1120 rom->config_func(dev); in i2c_dw_initialize()
1122 dw->app_config = I2C_MODE_CONTROLLER | i2c_map_dt_bitrate(rom->bitrate); in i2c_dw_initialize()
1124 if (i2c_dw_runtime_configure(dev, dw->app_config) != 0) { in i2c_dw_initialize()
1126 return -EIO; in i2c_dw_initialize()
1129 dw->state = I2C_DW_STATE_READY; in i2c_dw_initialize()
1181 const struct i2c_dw_rom_config *const dev_cfg = port->config; \
1182 unsigned int irq = pcie_alloc_irq(dev_cfg->pcie->bdf); \
1186 pcie_connect_dynamic_irq(dev_cfg->pcie->bdf, irq, DT_INST_IRQ(n, priority), \
1189 pcie_irq_enable(dev_cfg->pcie->bdf, irq); \