i2 c загрузка драйвера - raspbian - PullRequest
8 голосов
/ 14 февраля 2020

Я относительно новичок в драйверах устройств на linux. Чего я пытаюсь добиться, так это того, что при загрузке моего Raspberry внешний RGB-драйвер получит команду i2 c, чтобы вы могли видеть светодиод при загрузке.

Мой подход заключается в достижении sh это через модуль ядра, который будет загружен при загрузке. Я много чего пытался достичь, но сейчас чувствую, что у меня есть пробел в знаниях. Может быть, кто-то может мне помочь? (обратите внимание, что это не аппаратная проблема, из пользовательского пространства я могу отправлять команды устройству.)

Мой код модуля ядра выглядит следующим образом:

    #include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/regmap.h>


MODULE_AUTHOR ("Niels");
MODULE_DESCRIPTION("driver rgb led");
MODULE_LICENSE("GPL");

/*CAT3626 control registers*/
#define CAT3626_ADDRESS     0x66
#define CAT3626_ENA         0x03
#define CAT3626_REGA        0x00
#define CAT3626_REGB        0x01
#define CAT3626_REGC        0x02

struct cat3626 {
    struct device *dev;
    struct regmap * regmap;
};


enum {
    cat3626, 
};

static const struct of_device_id cat3626_dt_ids[] = {
    { .compatible = "onsemi,cat3626", .data = (void *)cat3626},
    { }
};

MODULE_DEVICE_TABLE(of, cat3626_dt_ids);


static const struct i2c_device_id cat3626_id[] = {
    {"cat3626",cat3626},
    { }
};

MODULE_DEVICE_TABLE(i2c, cat3626_id);

static const struct regmap_config regmap_config = {
    .reg_bits = 8,
    .val_bits = 8,
};

static int cat3626_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    struct cat3626 *cat3626;
    const struct of_device_id *match;
    int ret;

    cat3626 = devm_kzalloc(&client->dev, sizeof(struct cat3626), GFP_KERNEL);
    if (!cat3626){
        return -ENOMEM;
    }

    dev_set_drvdata(&client->dev, cat3626);
    cat3626->dev = &client->dev;

    cat3626->regmap = devm_regmap_init_i2c(client, &regmap_config);
    if (IS_ERR(cat3626->regmap)) {
        dev_err(cat3626->dev, "regmap allocation failed\n");
        return PTR_ERR(cat3626->regmap);
    }

    i2c_set_clientdata(client, cat3626);

    match = of_match_device(cat3626_dt_ids, &client->dev);
        if (!match) {
        dev_err(&client->dev, "unknown device model\n");
        return -ENODEV;
    }

    ret = i2c_smbus_write_byte_data(client, CAT3626_ENA, 0x30);   /* write LED C on*/
    ret = i2c_smbus_write_byte_data(client, CAT3626_REGC, 19);    /* write mA*/

    return ret;
}

static struct i2c_driver cat3626_driver = {
    .driver = {
        .name = "cat3626",
        .owner = THIS_MODULE,
        .of_match_table = of_match_ptr(cat3626_dt_ids),
    },
    .probe = cat3626_probe,
    .remove = cat3626_remove,
    .id_table = cat3626_id,
};

module_i2c_driver(cat3626_driver);

Вот файл makefile:

ifneq ($(KERNELRELEASE),)
    obj-m := hiber_rgb_driver.o

else
    KERNELDIR ?= \
    /lib/modules/`uname -r`/build/
    PWD := `pwd`

default:
    $(MAKE) -C $(KERNELDIR) \
    M=$(PWD) modules

endif

clean:
    rm -f *.ko *.o Module* *mod*

В файле /boot/config.txt я добавил это:

dtoverlay = i2c-gpio, bus = 80, i2c_gpio_delay_us = 2, i2c_gpio_sda = 44, i2c_gpio_scl = 45.

Кроме того, я сделал пользовательский dtoverlay:

/dts-v1/;
/plugin/;

/ {
    fragment@0 {
        target = <&i2c80>;
        __overlay__ {
            status = "okay";
            #address-cells = <1>;
            #size-cells = <0>;

            cat3626: cat3626@66 {
                compatible = "onsemi,cat3626";
                reg = <0x66>;
                clock-frequency = <400000>;
            };
        };
    };
};

Неудачно на при загрузке ничего не происходит. Все, что я получаю от загрузочного dmesg, это следующее:

rgb_driver: loading out-of-tree module taints kernel

Кто-нибудь может мне помочь, или, может быть, другой подход для достижения моей цели?

Заранее спасибо!

1 Ответ

4 голосов
/ 21 февраля 2020

Несколько вещей, на которые стоит обратить внимание - испорченное ядро ​​часто сокращает функциональность, и вы, вероятно, не захотите туда go, если вам не нужно. Я бы попытался решить проблему с заражением. Я построил модули ядра как автономные и не затронул проблему порчи. Вы можете sh пересмотреть свой make-файл, это более стандартный make-файл для сборки модулей с парой морщин, так как, конечно, вы пересекаете компиляцию -

PWD = $(shell pwd)
obj-m += hiber_rgb_driver.o

all:
    make ARCH=arm CROSS_COMPILE=$(CROSS) -C $(KERNEL) SUBDIRS=$(PWD) modules

clean:
    make -C $(KERNEL) SUBDIRS=$(PWD) clean

и собираете ее как-то так: -

make KERNEL=<LINUX_SOURCE_DIR> CROSS=<TOOLCHAIN_DIR>/bin/arm-linux-gnueabihf-

Итак, вот что.

Далее, зонд вашего устройства выглядит интересно. У меня нет времени отлаживать его для вас, но я бы предложил добавить туда несколько printk, чтобы убедиться, что зонд попал в цель. Если это так, то отлично, это просто вопрос выяснения, почему вы не «совпадаете». Если он не получил удара, тогда читайте дальше ..

Как вы, наверное, знаете, шины i2 c немного особенные, когда дело доходит до проверки устройства. Нет реального автоматизированного или магического зондирования, которое обычно происходило бы, скажем, на шине PCI. Вместо этого вам нужно создать дерево устройств, которое ядро ​​может просмотреть во время загрузки, чтобы завершить все тесты.

Я вижу, что вы создали фрагмент наложения. Вам нужно убедиться, что эта вещь скомпилирована в двоичный байт-код '.dtb', который ядро ​​может проанализировать, а затем поместить в правильное место на вашем загрузочном носителе, где grub сможет его найти.

Вам также может понадобиться обновить основную базу данных вашего устройства, чтобы она ссылалась на это наложение, чтобы ядро ​​знало, где оно может go. Представьте, что dtb устройства - это искусственная рождественская елка, а оверлей - как ветвь, которая может быть прикреплена в какой-то момент в будущем - вам нужно указать точки крепления в dtb устройства. Я sh, что я мог бы быть более точным здесь, но надежда, по крайней мере, направляет вас в правильном направлении.

...