static int i2c_mcux_configure(struct device *dev, u32_t dev_config_raw) { I2C_Type *base = DEV_BASE(dev); const struct i2c_mcux_config *config = DEV_CFG(dev); u32_t clock_freq; u32_t baudrate; if (!(I2C_MODE_MASTER & dev_config_raw)) { return -EINVAL; } if (I2C_ADDR_10_BITS & dev_config_raw) { return -EINVAL; } switch (I2C_SPEED_GET(dev_config_raw)) { case I2C_SPEED_STANDARD: baudrate = KHZ(100); break; case I2C_SPEED_FAST: baudrate = MHZ(1); break; default: return -EINVAL; } clock_freq = CLOCK_GetFreq(config->clock_source); I2C_MasterSetBaudRate(base, baudrate, clock_freq); return 0; }
int stm32_i2c_configure_timing(struct device *dev, u32_t clock) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); struct i2c_stm32_data *data = DEV_DATA(dev); I2C_TypeDef *i2c = cfg->i2c; u32_t i2c_hold_time_min, i2c_setup_time_min; u32_t i2c_h_min_time, i2c_l_min_time; u32_t presc = 1; u32_t timing = 0; switch (I2C_SPEED_GET(data->dev_config)) { case I2C_SPEED_STANDARD: i2c_h_min_time = 4000; i2c_l_min_time = 4700; i2c_hold_time_min = 500; i2c_setup_time_min = 1250; break; case I2C_SPEED_FAST: i2c_h_min_time = 600; i2c_l_min_time = 1300; i2c_hold_time_min = 375; i2c_setup_time_min = 500; break; default: return -EINVAL; } /* Calculate period until prescaler matches */ do { u32_t t_presc = clock / presc; u32_t ns_presc = NSEC_PER_SEC / t_presc; u32_t sclh = i2c_h_min_time / ns_presc; u32_t scll = i2c_l_min_time / ns_presc; u32_t sdadel = i2c_hold_time_min / ns_presc; u32_t scldel = i2c_setup_time_min / ns_presc; if ((sclh - 1) > 255 || (scll - 1) > 255) { ++presc; continue; } if (sdadel > 15 || (scldel - 1) > 15) { ++presc; continue; } timing = __LL_I2C_CONVERT_TIMINGS(presc - 1, scldel - 1, sdadel, sclh - 1, scll - 1); break; } while (presc < 16); if (presc >= 16) { SYS_LOG_DBG("I2C:failed to find prescaler value"); return -EINVAL; } LL_I2C_SetTiming(i2c, timing); return 0; }
static int i2c_imx_configure(struct device *dev, u32_t dev_config_raw) { I2C_Type *base = DEV_BASE(dev); struct i2c_imx_data *data = DEV_DATA(dev); struct i2c_master_transfer *transfer = &data->transfer; u32_t baudrate; if (!(I2C_MODE_MASTER & dev_config_raw)) { return -EINVAL; } if (I2C_ADDR_10_BITS & dev_config_raw) { return -EINVAL; } /* Initialize I2C state structure content. */ transfer->txBuff = 0; transfer->rxBuff = 0; transfer->cmdSize = 0U; transfer->txSize = 0U; transfer->rxSize = 0U; transfer->isBusy = false; transfer->currentDir = i2cDirectionReceive; transfer->currentMode = i2cModeSlave; switch (I2C_SPEED_GET(dev_config_raw)) { case I2C_SPEED_STANDARD: baudrate = KHZ(100); break; case I2C_SPEED_FAST: baudrate = MHZ(1); break; default: return -EINVAL; } /* Setup I2C init structure. */ i2c_init_config_t i2cInitConfig = { .baudRate = baudrate, .slaveAddress = 0x00 }; i2cInitConfig.clockRate = get_i2c_clock_freq(base); I2C_Init(base, &i2cInitConfig); I2C_Enable(base); return 0; } static int i2c_imx_send_addr(struct device *dev, u16_t addr, u8_t flags) { u8_t byte0 = addr << 1; byte0 |= (flags & I2C_MSG_RW_MASK) == I2C_MSG_READ; return i2c_imx_write(dev, &byte0, 1); }
static int i2c_sam_twi_configure(struct device *dev, u32_t config) { const struct i2c_sam_twi_dev_cfg *const dev_cfg = DEV_CFG(dev); Twi *const twi = dev_cfg->regs; u32_t bitrate; int ret; if (!(config & I2C_MODE_MASTER)) { LOG_ERR("Master Mode is not enabled"); return -EIO; } if (config & I2C_ADDR_10_BITS) { LOG_ERR("I2C 10-bit addressing is currently not supported"); LOG_ERR("Please submit a patch"); return -EIO; } /* Configure clock */ switch (I2C_SPEED_GET(config)) { case I2C_SPEED_STANDARD: bitrate = BUS_SPEED_STANDARD_HZ; break; case I2C_SPEED_FAST: bitrate = BUS_SPEED_FAST_HZ; break; default: LOG_ERR("Unsupported I2C speed value"); return -EIO; } /* Setup clock waveform */ ret = i2c_clk_set(twi, bitrate); if (ret < 0) { return ret; } /* Disable Slave Mode */ twi->TWI_CR = TWI_CR_SVDIS; /* Enable Master Mode */ twi->TWI_CR = TWI_CR_MSEN; return 0; }
static int i2c_qmsi_configure(struct device *dev, u32_t config) { qm_i2c_t instance = GET_CONTROLLER_INSTANCE(dev); struct i2c_qmsi_driver_data *driver_data = GET_DRIVER_DATA(dev); qm_i2c_reg_t *const controller = QM_I2C[instance]; int rc; qm_i2c_config_t qm_cfg; /* This driver only supports master mode. */ if (!(I2C_MODE_MASTER & config)) return -EINVAL; qm_cfg.mode = QM_I2C_MASTER; if (I2C_ADDR_10_BITS & config) { qm_cfg.address_mode = QM_I2C_10_BIT; } else { qm_cfg.address_mode = QM_I2C_7_BIT; } switch (I2C_SPEED_GET(config)) { case I2C_SPEED_STANDARD: qm_cfg.speed = QM_I2C_SPEED_STD; break; case I2C_SPEED_FAST: qm_cfg.speed = QM_I2C_SPEED_FAST; break; case I2C_SPEED_FAST_PLUS: qm_cfg.speed = QM_I2C_SPEED_FAST_PLUS; break; default: return -EINVAL; } k_sem_take(&driver_data->sem, K_FOREVER); rc = qm_i2c_set_config(instance, &qm_cfg); k_sem_give(&driver_data->sem); controller->ic_sda_hold = (CONFIG_I2C_SDA_RX_HOLD << 16) + CONFIG_I2C_SDA_TX_HOLD; controller->ic_sda_setup = CONFIG_I2C_SDA_SETUP; return rc; }
static int i2c_dw_runtime_configure(struct device *dev, u32_t config) { struct i2c_dw_dev_config * const dw = dev->driver_data; u32_t value = 0; u32_t rc = 0; volatile struct i2c_dw_registers * const regs = (struct i2c_dw_registers *)dw->base_address; dw->app_config = config; /* Make sure we have a supported speed for the DesignWare model */ /* and have setup the clock frequency and speed mode */ switch (I2C_SPEED_GET(dw->app_config)) { case I2C_SPEED_STANDARD: /* Following the directions on DW spec page 59, IC_SS_SCL_LCNT * must have register values larger than IC_FS_SPKLEN + 7 */ if (I2C_STD_LCNT <= (regs->ic_fs_spklen + 7)) { value = regs->ic_fs_spklen + 8; } else { value = I2C_STD_LCNT; } dw->lcnt = value; /* Following the directions on DW spec page 59, IC_SS_SCL_HCNT * must have register values larger than IC_FS_SPKLEN + 5 */ if (I2C_STD_HCNT <= (regs->ic_fs_spklen + 5)) { value = regs->ic_fs_spklen + 6; } else { value = I2C_STD_HCNT; } dw->hcnt = value; break; case I2C_SPEED_FAST: /* fall through */ case I2C_SPEED_FAST_PLUS: /* * Following the directions on DW spec page 59, IC_FS_SCL_LCNT * must have register values larger than IC_FS_SPKLEN + 7 */ if (I2C_FS_LCNT <= (regs->ic_fs_spklen + 7)) { value = regs->ic_fs_spklen + 8; } else { value = I2C_FS_LCNT; } dw->lcnt = value; /* * Following the directions on DW spec page 59, IC_FS_SCL_HCNT * must have register values larger than IC_FS_SPKLEN + 5 */ if (I2C_FS_HCNT <= (regs->ic_fs_spklen + 5)) { value = regs->ic_fs_spklen + 6; } else { value = I2C_FS_HCNT; } dw->hcnt = value; break; case I2C_SPEED_HIGH: if (dw->support_hs_mode) { if (I2C_HS_LCNT <= (regs->ic_hs_spklen + 7)) { value = regs->ic_hs_spklen + 8; } else { value = I2C_HS_LCNT; } dw->lcnt = value; if (I2C_HS_HCNT <= (regs->ic_hs_spklen + 5)) { value = regs->ic_hs_spklen + 6; } else { value = I2C_HS_HCNT; } dw->hcnt = value; } else { rc = -EINVAL; } break; default: /* TODO change */ rc = -EINVAL; } /* * Clear any interrupts currently waiting in the controller */ value = regs->ic_clr_intr; /* * TEMPORARY HACK - The I2C does not work in any mode other than Master * currently. This "hack" forces us to always be configured for master * mode, until we can verify that Slave mode works correctly. */ dw->app_config |= I2C_MODE_MASTER; return rc; }
static int _i2c_dw_setup(struct device *dev, u16_t slave_address) { struct i2c_dw_dev_config * const dw = dev->driver_data; u32_t value; union ic_con_register ic_con; volatile struct i2c_dw_registers * const regs = (struct i2c_dw_registers *)dw->base_address; ic_con.raw = 0; /* Disable the device controller to be able set TAR */ regs->ic_enable.bits.enable = 0; /* Disable interrupts */ regs->ic_intr_mask.raw = 0; /* Clear interrupts */ value = regs->ic_clr_intr; /* Set master or slave mode - (initialization = slave) */ if (I2C_MODE_MASTER & dw->app_config) { /* * Make sure to set both the master_mode and slave_disable_bit * to both 0 or both 1 */ SYS_LOG_DBG("I2C: host configured as Master Device"); ic_con.bits.master_mode = 1; ic_con.bits.slave_disable = 1; } else { return -EINVAL; } ic_con.bits.restart_en = 1; /* Set addressing mode - (initialization = 7 bit) */ if (I2C_ADDR_10_BITS & dw->app_config) { SYS_LOG_DBG("I2C: using 10-bit address"); ic_con.bits.addr_master_10bit = 1; ic_con.bits.addr_slave_10bit = 1; } /* Setup the clock frequency and speed mode */ switch (I2C_SPEED_GET(dw->app_config)) { case I2C_SPEED_STANDARD: SYS_LOG_DBG("I2C: speed set to STANDARD"); regs->ic_ss_scl_lcnt = dw->lcnt; regs->ic_ss_scl_hcnt = dw->hcnt; ic_con.bits.speed = I2C_DW_SPEED_STANDARD; break; case I2C_SPEED_FAST: /* fall through */ case I2C_SPEED_FAST_PLUS: SYS_LOG_DBG("I2C: speed set to FAST or FAST_PLUS"); regs->ic_fs_scl_lcnt = dw->lcnt; regs->ic_fs_scl_hcnt = dw->hcnt; ic_con.bits.speed = I2C_DW_SPEED_FAST; break; case I2C_SPEED_HIGH: if (!dw->support_hs_mode) { return -EINVAL; } SYS_LOG_DBG("I2C: speed set to HIGH"); regs->ic_hs_scl_lcnt = dw->lcnt; regs->ic_hs_scl_hcnt = dw->hcnt; ic_con.bits.speed = I2C_DW_SPEED_HIGH; break; default: SYS_LOG_DBG("I2C: invalid speed requested"); return -EINVAL; } SYS_LOG_DBG("I2C: lcnt = %d", dw->lcnt); SYS_LOG_DBG("I2C: hcnt = %d", dw->hcnt); /* Set the IC_CON register */ regs->ic_con = ic_con; /* Set RX fifo threshold level. * Setting it to zero automatically triggers interrupt * RX_FULL whenever there is data received. * * TODO: extend the threshold for multi-byte RX. */ regs->ic_rx_tl = 0; /* Set TX fifo threshold level. * TX_EMPTY interrupt is triggered only when the * TX FIFO is truly empty. So that we can let * the controller do the transfers for longer period * before we need to fill the FIFO again. This may * cause some pauses during transfers, but this keeps * the device from interrupting often. */ regs->ic_tx_tl = 0; if (regs->ic_con.bits.master_mode) { /* Set address of target slave */ regs->ic_tar.bits.ic_tar = slave_address; } else { /* Set slave address for device */ regs->ic_sar.bits.ic_sar = slave_address; } /* If I2C is being operated in master mode and I2C_DYNAMIC_TAR_UPDATE * configuration parameter is set to Yes (1), the ic_10bitaddr_master * bit in ic_tar register would control whether the DW_apb_i2c starts * its transfers in 7-bit or 10-bit addressing mode. */ if (I2C_MODE_MASTER & dw->app_config) { if (I2C_ADDR_10_BITS & dw->app_config) { regs->ic_tar.bits.ic_10bitaddr_master = 1; } else { regs->ic_tar.bits.ic_10bitaddr_master = 0; } } return 0; }