Пишу драйвер для CMOS сенсора. Это устройство требует нескольких настроек I2 C, но я также контролирую для него IO через FPGA с I2 C. В частности, эта FPGA содержит IO, требующий управления при запуске потока. Поскольку это настраиваемое устройство, я пытаюсь создать фиктивную структуру i2c_client. У меня есть следующая (измененная) функция в драйвере для запуска потока.
static int imx267_start_streaming(struct tegracam_device *tc_dev)
{
struct imx267 *priv = (struct imx267 *)tegracam_get_privdata(tc_dev);
int err;
struct i2c_client *fpgai2c;
struct i2c_adapter *adapterused;
s32 val;
u8 bytetowrite;
u8 regaddr_toread = 0xFF;
printk(KERN_INFO "%s\n", __FUNCTION__);
printk("[IMX267]: We can get the following information from the tc_dev struct, nr = %d, name = %s\n",tc_dev->client->adapter->nr,tc_dev->client->adapter->name);
adapterused = i2c_get_adapter(tc_dev->client->adapter->nr); //First we need to get a handle on the adapter beeing used by the currently starting sensor
fpgai2c = i2c_new_dummy(adapterused,0x48); //Create dummy I2C client to access FPGA I2C on same adapter as currently starting sensor
printk("[IMX267]: We can get the following information from the adapterused struct, nr = %d, name = %s\n",tc_dev->client->adapter->nr,tc_dev->client->adapter->name);
val = i2c_smbus_read_byte_data(fpgai2c,regaddr_toread); //Read register for read modify write
bytetowrite = (u8)val;
printk("[IMX267]: register 0x%x from FPGA reads 0x%x(%d). Casting it (s32) to u8 gives a value 0x%x(%d)\n",regaddr_toread,val,val,bytetowrite,bytetowrite);
bytetowrite |= 0x40;
printk("[IMX267]: after OR with 0x40 value is 0x%x(%d), name of client is now %s",bytetowrite,bytetowrite,fpgai2c->name);
val = i2c_smbus_write_byte_data(fpgai2c,regaddr_toread,bytetowrite);
printk("[IMX267]: FPGA I2C write gave following results 0x%x(%d)\n",val,val);
usleep_range(1000, 2000); // Falco: delay before stream start
if (test_mode) {
err = imx267_write_table(priv,
mode_table[IMX267_MODE_TEST_PATTERN]);
} else {
err = imx267_write_table(priv, mode_table[IMX267_MODE_START_STREAM]);
}
if (err) {
printk(KERN_ERR "%s in write table\n", __FUNCTION__);
return err;
}
i2c_unregister_device(fpgai2c); //Unregister temporary client to release FPGA control for now
return 0;
}
Часть использования FPGA через I2 C для управления вводом-выводом работает, я вижу запуск потока. Однако, глядя в dmesg, я также вижу, что он запустил функцию проверки драйвера датчика:
[ 62.884372] imx267_start_streaming
[ 62.884377] [IMX267]: We can get the following information from the tc_dev struct, nr = 30, name = i2c-2-mux (chan_id 0)
[ 62.885442] [IMX267]: We can get the following information from the adapterused struct, nr = 30, name = i2c-2-mux (chan_id 0)
[ 62.885788] [IMX267]: register 0xFF from FPGA reads 0x00(0). Casting it (s32) to u8 gives a value 0x00(0)
[ 62.885791] [IMX267]: after OR with 0xF0 value is 0xF0(240), name of client is now dummy
[ 62.886077] [IMX267]: FPGA I2C write gave following results 0x0(0)
[ 62.886605] imx267_probe: called
[ 62.886608] imx267_probe: module version: 0.04
[ 62.886614] imx267 32-001a: [IMX267]: probing v4l2 sensor at addr 0x1a with name 'imx267'.
[ 62.886655] imx267_parse_dt: called
[ 62.886657] imx267_parse_dt: OK of_match_device
[ 62.886660] imx267_parse_dt of_property_read_string (mclk) found: extperiph1
[ 62.886686] imx267 32-001a: reset-gpios not found 0
[ 62.888100] IMX267: Now writing table. Number of modes: 3, mode_prop_idx = 0, active_w/width = 4096, table = 12288
[ 62.891612] imx267 32-001a: tegra camera driver registration failed
Всего imx267_probe и _parse не должно быть, это уже было сделано при инициализации водитель. Странно то, что имя i2c_client отличается, имя созданного мной клиента - фиктивное, но имя, используемое функцией imx267_probe, называется imx267 (отсюда и почему сработала функция проверки драйвера изображения?) Функция проверки - это определяется как:
static int imx267_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct tegracam_device *tc_dev;
struct imx267 *priv;
int err;
printk("%s: called\n", __FUNCTION__);
printk("%s: module version: %s", __FUNCTION__, IMX267_MODULE_VERSION);
dev_info(&client->dev, "[IMX267]: probing v4l2 sensor at addr 0x%0x with name '%s'.\n",
client->addr,client->name);
...
Я также пробовал создать фиктивный i2c_board_info и использовать i2c_new_device, но это приводит к тому же эффекту, что и функция проверки драйвера датчика ..
Я думаю, что мне не хватает информации, которая требует изменения в структурах i2 c, но я просто не знаю, где искать.
Используемая версия ядра - 4.9.140
Изменить: Я также нашел функцию i2c_new_probed_device, для которой вы можете передать свою собственную функцию исследования. Это привело к срабатыванию фиктивной функции, но по-прежнему работает функция датчика датчика.
int dummy_probe(struct i2c_adapter *useless, unsigned short addr) //Needs to follow naming conventions
{
printk("IMX[267]: dummy_probe function triggered!\n");
return 1;
}
static int imx267_start_streaming(struct tegracam_device *tc_dev)
{
struct imx267 *priv = (struct imx267 *)tegracam_get_privdata(tc_dev);
int err;
static struct i2c_board_info dummy_board_info = {
I2C_BOARD_INFO("dummy", 0x48),
};
unsigned short addr_list[1] = { 0x48 };
struct i2c_client *fpgai2c;
struct i2c_adapter *adapterused;
s32 val;
u8 bytetowrite;
u8 regaddr_toread = 0xFF;
printk(KERN_INFO "%s\n", __FUNCTION__);
printk("[IMX267]: We can get the following information from the tc_dev struct, nr = %d, name = %s\n",tc_dev->client->adapter->nr,tc_dev->client->adapter->name);
adapterused = i2c_get_adapter(tc_dev->client->adapter->nr); //First we need to get a handle on the adapter beeing used by the currently starting sensor
//fpgai2c = i2c_new_dummy_device(adapterused,0x48); //Create dummy I2C client to access FPGA I2C on same adapter as currently starting sensor
fpgai2c = i2c_new_probed_device(adapterused,&dummy_board_info,addr_list,(*dummy_probe));
printk("[IMX267]: We can get the following information from the adapterused struct, nr = %d, name = %s\n",tc_dev->client->adapter->nr,tc_dev->client->adapter->name);
...
Результат:
3
[ 76.276400] imx267_start_streaming
[ 76.276404] [IMX267]: We can get the following information from the tc_dev struct, nr = 30, name = i2c-2-mux (chan_id 0)
[ 76.276417] IMX[267]: dummy_probe function triggered!
[ 76.277201] [IMX267]: We can get the following information from the adapterused struct, nr = 30, name = i2c-2-mux (chan_id 0)
[ 76.277540] [IMX267]: register from FPGA reads . Casting it (s32) to u8 gives a value
[ 76.277543] [IMX267]: after OR with value is , name of client is now dummy
[ 76.277826] [IMX267]: FPGA I2C write gave following results 0x0(0)
[ 76.278820] imx267_probe: called
[ 76.278824] imx267_probe: module version: 0.04
[ 76.278829] imx267 32-001a: [IMX267]: probing v4l2 sensor at addr 0x1a with name 'imx267'.
[ 76.278868] imx267_parse_dt: called
[ 76.278870] imx267_parse_dt: OK of_match_device
[ 76.278873] imx267_parse_dt of_property_read_string (mclk) found: extperiph1
[ 76.278898] imx267 32-001a: reset-gpios not found 0
[ 76.279890] IMX267: Now writing table. Number of modes: 3, mode_prop_idx = 0, active_w/width = 4096, table = 12288
[ 76.283825] imx267 32-001a: tegra camera driver registration failed