Фиктивное устройство I2 C вызывает срабатывание датчика - PullRequest
0 голосов
/ 06 мая 2020

Пишу драйвер для 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

...