Как использовать интерфейс дескриптора ядра GPIO - PullRequest
0 голосов
/ 05 сентября 2018

Я пытаюсь разработать простой модуль ядра Linux, который управляет группой датчиков / исполнительных механизмов, закрепленных на GPIO Raspberry Pi.
Функции GPIO, которые мне нужны, довольно просты: получить / установить значения выводов, получить IRQ, ...

В моем коде у меня есть misc_device , который реализует обычное открытие , чтение , запись и открытие операций. Например, в моей операции чтения я хотел бы получить значение (высокое / низкое) определенного вывода GPIO.

К счастью, ядро ​​предоставляет интерфейс для таких операций GPIO. На самом деле, согласно официальному документу GPIO , существует два интерфейса: устаревший, чрезвычайно простой, но устаревший, и новый, основанный на дескрипторах.
Я хотел бы использовать последний для своего проекта, и я понимаю, как реализовать все, что мне нужно, за исключением одной вещи: дерева устройств.
Со ссылкой на board.txt , прежде чем я смогу вызвать gpiod_get_index () и позже gpiod_get_value () , сначала мне нужно настроить дерево устройств примерно так:

foo_device {
    compatible = "acme,foo";
    ...
    led-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>, /* red */
            <&gpio 16 GPIO_ACTIVE_HIGH>, /* green */
            <&gpio 17 GPIO_ACTIVE_HIGH>; /* blue */

    power-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
};

Однако я абсолютно не знаю, куда поместить этот кусок кода, и действительно ли он мне нужен. Имейте в виду, что у меня есть разное устройство, которое выглядит так, где aaa_fops содержит операцию чтения:

static struct miscdevice aaa = {
    MISC_DYNAMIC_MINOR, "aaa", &aaa_fops
};

Используя старый устаревший интерфейс, моя проблема была бы решена, потому что не нужно связываться с деревом устройств, но я все равно хотел бы использовать новый, если не слишком сложный.

Я прочитал кучу документации, официальной и неофициальной, но не смог найти прямой и простой ответ на мою проблему. Я пытался найти ответ в исходном коде ядра, особенно в разделе драйверов, но затерялся только в долине сложных и запутанных вещей. Отсутствие рабочих минимальных примеров (WME) по ядру значительно замедляет мой учебный процесс, только мое мнение об этом.
Не могли бы вы дать мне WME простого устройства (предпочтительно misc), чья операция read () получает значение контакта, используя новый интерфейс GPIO?

Если вам нужна более подробная информация о моем коде, просто спросите. Заранее спасибо!

Примечание 1: я знаю, что большая часть моей работы может выполняться в пространстве пользователя, а не в пространстве ядра; Мой проект только для образовательных целей, чтобы изучить ядро.

Примечание 2: Я выбираю разное устройство, потому что оно простое, но при необходимости я могу переключиться на символьное устройство.

1 Ответ

0 голосов
/ 06 сентября 2018

... сначала мне нужно настроить дерево устройств примерно так:
...
Тем не менее, я абсолютно не знаю, куда поместить этот кусок кода

Узлы и свойства дерева устройств не следует называть «кодом» .
Большинство устройств подключены к периферийной шине, поэтому узлы устройств обычно являются дочерними узлами периферийного шинного узла.


Не могли бы вы дать мне WME простого устройства

Вы можете найти множество примеров использования GPIO на основе дескриптора в исходном коде ядра.
Поскольку в документации указан дескриптор GPIO как свойство с именем <function>-gpios, grep каталога arch / arm / boot / dts для строки "\ -gpios" сообщает о многих возможных примерах.
В частности, есть

./bcm2835-rpi-b.dts:    hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;

Это свойство hpd-gpios принадлежит базовому узлу hdmi, определенному в bcm283x.dtsi , и используется драйвером gpu / drm / vc4 / vc4_hdmi.c .

/* General HDMI hardware state. */
struct vc4_hdmi {
        ... 
        int hpd_gpio;
        ...
};


static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
{
    ...
        /* Only use the GPIO HPD pin if present in the DT, otherwise
         * we'll use the HDMI core's register.
         */
        if (of_find_property(dev->of_node, "hpd-gpios", &value)) {
                ...

                hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node,
                                                         "hpd-gpios", 0,
                                                         &hpd_gpio_flags);
                if (hdmi->hpd_gpio < 0) {
                        ret = hdmi->hpd_gpio;
                        goto err_unprepare_hsm;
                }
                ...
        }

Если свойство hpd-gpios определено / найдено и успешно извлечено из DeviceTree платы, то элемент структуры драйвера hpd_gpio содержит номер контакта GPIO.
Поскольку этот драйвер не вызывает devm_gpio_request () , платформа, очевидно, выделяет вывод GPIO для драйвера.


Драйвер может получить доступ к выводу GPIO.

static enum drm_connector_status
vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
{
    ...
        if (vc4->hdmi->hpd_gpio) {
                if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^
                    vc4->hdmi->hpd_active_low)
                        return connector_status_connected;
                else
                        return connector_status_disconnected;
        }
...