How to access an i2c device in device driver

Hello,

I’d like to access an i2c device in device driver so I’ve tried to do it but it doesn’t work.

below is source code.

static int imx000_dac_device_init(struct imx000 *priv)
{
	char *dev_name = "dac_imx000";
	static struct regmap_config dac_regmap_config = {
		.reg_bits = 8,
		.val_bits = 16,
	};
	int err = 0;

	priv->dac.adap = i2c_get_adapter(priv->i2c_client->adapter->nr);
	memset(&priv->dac.brd, 0, sizeof(priv->dac.brd));
	strncpy(priv->dac.brd.type, dev_name, sizeof(priv->dac.brd.type));
	priv->dac.brd.addr = IMX000_DAC_ADDRESS;
	priv->dac.i2c_client = i2c_new_device( priv->dac.adap, &priv->dac.brd);

	priv->dac.regmap = devm_regmap_init_i2c(priv->dac.i2c_client, &dac_regmap_config);
	if (IS_ERR(priv->dac.regmap)) {
		err = PTR_ERR(priv->dac.regmap);
		imx556_dac_device_release(priv);
		return err;
	}

	return 0;
}

static int imx000_read_dac(struct camera_common_data *s_data)
{
	struct device *dev = s_data->dev;
	u32 val = 0;
	int err = 0, i = 0;
	char msg[256] = {0, };

	for(i = 0; i < IMX000_DAC_REG_SIZE; ++i) {
		err |= regmap_read(s_data->regmap, dac_reg[i].addr, &val);

		if (err)
			dev_err(dev, "%s: i2c read failed, 0x%04x\n", __func__, dac_reg[i].addr);

		sprintf(msg, "addr: 0x%x ==> val: 0x%04x", dac_reg[i].addr, val);
		PRINT_FUNC_NAME_2_KERN_LOG(__func__, msg);
	}

	return 0;
}

static int imx000_write_dac(struct camera_common_data *s_data)
{
	struct device *dev = s_data->dev;
	int err = 0, i = 0;
	char msg[256] = {0, };
	
	for(i = 0; i < IMX000_DAC_REG_SIZE; ++i) {
		err |= regmap_write(s_data->regmap, dac_reg[i].addr, dac_reg[i].val);

		if (err)
			dev_err(dev, "%s: i2c write failed, 0x%04x\n", __func__, dac_reg[i].addr);

		sprintf(msg, "addr: 0x%x ==> val: 0x%04x", dac_reg[i].addr, dac_reg[i].val);
		PRINT_FUNC_NAME_2_KERN_LOG(__func__, msg);
	}

	if (err)
		return err;

	return 0;
}

static int imx000_dac_device_release(struct imx000 *priv)
{
	if (priv->dac.i2c_client != NULL) {
		i2c_unregister_device(priv->dac.i2c_client);
		priv->dac.i2c_client = NULL;
	}

	return 0;
}

Above source code is based on handling eeprom in ov5693.

And, I modified slave address and some source code to access i2c communication.

below log is test log.

[    7.476309] IMX000 : imx000_write_dac() => addr: 0x27 ==> val: 0xf00
[    7.476477] IMX000 : imx000_write_dac() => addr: 0x5f ==> val: 0xa0b9
[    7.477155] IMX000 : imx000_write_dac() => addr: 0x6f ==> val: 0x100

[    7.477415] IMX000 : imx000_read_dac() => addr: 0x27 ==> val: 0x0
[    7.478853] IMX000 : imx000_read_dac() => addr: 0x5f ==> val: 0x0
[    7.479047] IMX000 : imx000_read_dac() => addr: 0x6f ==> val: 0x0

I wrote values then read them again but all of values were 0.

Please give me any example source code or comments.

Thanks.

Any error message while access the device?

Hello ShaneCCC,
In dmesg log, nothing appears.
Are there any methods to check error messages?
Thanks.

Could you try more REG to check.

Hello ShaneCCC,

Thanks for your support.

I found something wrong in my code.

My EEPROM has 16bit-address, 8bit-data but I set to 8bit-address, 16bit-data.

After fixing this, reading operation seems like working but writing operation is not.

Both read and write operations are the same slave address which is 0x50.

The test sequence is as follows.

  1. Read EEPROM from 0x00 to 0x0F.
  2. Write the values from 0x00 to 0x0F to the EEPROM from 0x00 to 0x0F.
  3. Read the EEPROM from 0x00 to 0x0F again.

Below is test code and trace log.

Source code below :

static int imx000_eeprom_device_release(struct imx000 *priv)
{
	int i = 0;

	PRINT_FUNC_NAME_2_KERN_LOG(__func__, "START");
	for (i = 0; i < 1; i++) {
		if (priv->eeprom[i].i2c_client != NULL) {
			i2c_unregister_device(priv->eeprom[i].i2c_client);
			priv->eeprom[i].i2c_client = NULL;
		}
	}
	PRINT_FUNC_NAME_2_KERN_LOG(__func__, "END");

	return 0;
}

static int imx000_eeprom_device_init(struct imx000 *priv)
{
	struct camera_common_pdata *pdata =  priv->s_data->pdata;
	char *dev_name = "eeprom_imx000";
	static struct regmap_config eeprom_regmap_config = {
		.reg_bits = 16,
		.val_bits = 8,
	};
	int err = 0, i = 0;

	PRINT_FUNC_NAME_2_KERN_LOG(__func__, "START");
	if (!pdata->has_eeprom)
		return -EINVAL;

	for (i = 0; i < 1; i++) {
		priv->eeprom[i].adap = i2c_get_adapter(priv->i2c_client->adapter->nr);
		memset(&priv->eeprom[i].brd, 0, sizeof(priv->eeprom[i].brd));
		strncpy(priv->eeprom[i].brd.type, dev_name, sizeof(priv->eeprom[i].brd.type));
		priv->eeprom[i].brd.addr = IMX000_EEPROM_ADDRESS + i;
		priv->eeprom[i].i2c_client = i2c_new_device(priv->eeprom[i].adap, &priv->eeprom[i].brd);

		priv->eeprom[i].regmap = devm_regmap_init_i2c(priv->eeprom[i].i2c_client, &eeprom_regmap_config);
		if (IS_ERR(priv->eeprom[i].regmap)) {
			err = PTR_ERR(priv->eeprom[i].regmap);
			imx000_eeprom_device_release(priv);
			return err;
		}
	}
	PRINT_FUNC_NAME_2_KERN_LOG(__func__, "END");

	return 0;
}

static int imx000_write_eeprom(struct imx000 *priv)
{
	int err = 0, i = 0;
	char str_msg[256] = {0, };

	PRINT_FUNC_NAME_2_KERN_LOG(__func__, "START");
//	for (i = 0; i < IMX000_EEPROM_NUM_BLOCKS; i++) {
//		if(regmap_bulk_write(priv->eeprom[i].regmap, i, &val, IMX000_EEPROM_BLOCK_SIZE))
//			return err;		
//	}
	for (i = 0; i <= 0x0F; i++) {
		if ((err = regmap_write(priv->eeprom[0].regmap, i, i))) {
			dev_err(priv->s_data->dev, "%s: i2c write failed, 0x%04X = 0x%02X\n", __func__, i, i);
			return err;
		}
		sprintf(str_msg, "addr: 0x%04X ==> val: 0x%02X", i, i);
		PRINT_FUNC_NAME_2_KERN_LOG(__func__, str_msg);
	}
	PRINT_FUNC_NAME_2_KERN_LOG(__func__, "END");

	return 0;
}

static int imx000_read_eeprom(struct imx000 *priv)
{
	int err = 0, i = 0, val = 0;
	char str_msg[256] = {0, };

	PRINT_FUNC_NAME_2_KERN_LOG(__func__, "START");
	/*for (i = 0; i < IMX000_EEPROM_NUM_BLOCKS; i++) {
		if(regmap_bulk_read(priv->eeprom[i].regmap, 0, &priv->eeprom_buf[i * IMX000_EEPROM_BLOCK_SIZE], IMX000_EEPROM_BLOCK_SIZE))
			return err;
	}*/
	for (i = 0; i <= 0x0F; i++) {		
		if ((regmap_read(priv->eeprom[0].regmap, i, &val))) {
			dev_err(priv->s_data->dev, "%s: i2c write failed, 0x%04X = 0x%02X\n", __func__, i, val);
			return err;
		}

		sprintf(str_msg, "addr: 0x%04X ==> val: 0x%02X", i, val);
		PRINT_FUNC_NAME_2_KERN_LOG(__func__, str_msg);
	}
	PRINT_FUNC_NAME_2_KERN_LOG(__func__, "END");

	return 0;
}

Trace log below :

[    5.290338] IMX000 : imx000_read_eeprom() => START
[    5.291279] IMX000 : imx000_read_eeprom() => addr: 0x0000 ==> val: 0x00
[    5.291450] IMX000 : imx000_read_eeprom() => addr: 0x0001 ==> val: 0x01
[    5.291618] IMX000 : imx000_read_eeprom() => addr: 0x0002 ==> val: 0x00
[    5.292047] IMX000 : imx000_read_eeprom() => addr: 0x0003 ==> val: 0x00
[    5.293202] IMX000 : imx000_read_eeprom() => addr: 0x0004 ==> val: 0x00
[    5.297055] IMX000 : imx000_read_eeprom() => addr: 0x0005 ==> val: 0x00
[    5.297498] IMX000 : imx000_read_eeprom() => addr: 0x0006 ==> val: 0x00
[    5.300278] IMX000 : imx000_read_eeprom() => addr: 0x0007 ==> val: 0x00
[    5.301762] IMX000 : imx000_read_eeprom() => addr: 0x0008 ==> val: 0x00
[    5.302106] IMX000 : imx000_read_eeprom() => addr: 0x0009 ==> val: 0x00
[    5.302292] IMX000 : imx000_read_eeprom() => addr: 0x000A ==> val: 0x00
[    5.303087] IMX000 : imx000_read_eeprom() => addr: 0x000B ==> val: 0x00
[    5.320290] IMX000 : imx000_read_eeprom() => addr: 0x000C ==> val: 0x00
[    5.321655] IMX000 : imx000_read_eeprom() => addr: 0x000D ==> val: 0x00
[    5.328368] IMX000 : imx000_read_eeprom() => addr: 0x000E ==> val: 0x00
[    5.331380] IMX000 : imx000_read_eeprom() => addr: 0x000F ==> val: 0x00
[    5.331384] IMX000 : imx000_read_eeprom() => END
[    5.332182] IMX000 : imx000_write_eeprom() => START
[    5.334343] IMX000 : imx000_write_eeprom() => addr: 0x0000 ==> val: 0x00
[    5.337725] tegra-i2c 3180000.i2c: no acknowledge from address 0x50
[    5.344543] imx000 2-0057: imx000_write_eeprom: i2c write failed, 0x0001 = 0x01
[    5.352221] imx000 2-0057: Error -121 writing eeprom
[    5.357937] IMX000 : imx000_read_eeprom() => START
[    5.359101] IMX000 : imx000_read_eeprom() => addr: 0x0000 ==> val: 0x00
[    5.360817] IMX000 : imx000_read_eeprom() => addr: 0x0001 ==> val: 0x01
[    5.363772] IMX000 : imx000_read_eeprom() => addr: 0x0002 ==> val: 0x00
[    5.364078] IMX000 : imx000_read_eeprom() => addr: 0x0003 ==> val: 0x00
[    5.364260] IMX000 : imx000_read_eeprom() => addr: 0x0004 ==> val: 0x00
[    5.364827] IMX000 : imx000_read_eeprom() => addr: 0x0005 ==> val: 0x00
[    5.365015] IMX000 : imx000_read_eeprom() => addr: 0x0006 ==> val: 0x00
[    5.365235] IMX000 : imx000_read_eeprom() => addr: 0x0007 ==> val: 0x00
[    5.365422] IMX000 : imx000_read_eeprom() => addr: 0x0008 ==> val: 0x00
[    5.365612] IMX000 : imx000_read_eeprom() => addr: 0x0009 ==> val: 0x00
[    5.365791] IMX000 : imx000_read_eeprom() => addr: 0x000A ==> val: 0x00
[    5.365968] IMX000 : imx000_read_eeprom() => addr: 0x000B ==> val: 0x00
[    5.366259] IMX000 : imx000_read_eeprom() => addr: 0x000C ==> val: 0x00
[    5.366431] IMX000 : imx000_read_eeprom() => addr: 0x000D ==> val: 0x00
[    5.366602] IMX000 : imx000_read_eeprom() => addr: 0x000E ==> val: 0x00
[    5.366770] IMX000 : imx000_read_eeprom() => addr: 0x000F ==> val: 0x00
[    5.366771] IMX000 : imx000_read_eeprom() => END

Any ideas are welcome.

Thanks.