Example #1
0
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;
}
Example #2
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;
}
Example #3
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);
}
Example #4
0
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;
}
Example #5
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;
}
Example #6
0
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;
}
Example #7
0
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;
}