Дерево устройств Linux: как разобрать свойство, содержащее список ячеек - PullRequest
1 голос
/ 23 мая 2019

Я разрабатываю драйвер устройства Linux для сбора данных во встроенном Linux (PetaLinux).

Чтобы избежать аппаратного аппаратного кодирования в модуле ядра, одна из записей в дереве устройств имеет список ячеек, описывающих сопоставления реле, к которым осуществляется доступ через SPI для разных чипов АЦП, например:

ll-adc@a1000000 {
  compatible = "ll,llmk1-adc-1.0";
  reg =   <0x0 0xa1000000 0x1000>;

  // related SPI devices to control attenutor relays
  relay-devs = <&usmk1_max4820_0 &usmk1_max4820_1>;

  // Which relays control which ADC channel attenuator
  relays =
        <0 0 0 2>, // Channel 0, att 0 --> relay dev 0, ch 2 
        <0 1 0 3>, // Channel 0, att 1 --> relay dev 0, ch 3 
        <1 0 1 3>, // Channel 1, att 0 --> relay dev 1, ch 3 
        <1 1 0 0>; // Channel 1, att 1 --> relay dev 0, ch 0 
};

При создании экземпляра устройства я хотел бы прочитать значения из свойства "relay" и сохранить их в таблице в модуле ядра.

Однако я не смог найти подходящих функций для этого.

Насколько я вижу, of_property_read_*_array может прочитать массив для свойства, которое содержит одну ячейку. of_for_each* макросы могут повторять несколько значений свойства, если они являются phandles, u32 или строками.

Может кто-нибудь предложить, как правильно читать список ячеек, как показано выше, если это вообще возможно?

Спасибо за вашу помощь.

1 Ответ

1 голос
/ 24 мая 2019

Пример в исходном коде ядра указывает на возможное решение.

Если свойство вашего узла состоит из списка n-кортежей, то of_property_read_u32_index () может использоваться для извлечения отдельного аргумента u32 из i-го кортежа:

num_args = 4;

if (!of_get_property(np, "relays", &tmp))
    return NULL;
num_relays = tmp / (sizeof(u32) * num_args);

for (i = 0; i < num_relays; i++) {
    offset = i * num_args;
    if (of_property_read_u32_index(np, "relays", offset, &arg0))
        goto err;

    if (of_property_read_u32_index(np, "relays", offset + 1, &arg1))
        goto err;

    if (of_property_read_u32_index(np, "relays", offset + 2, &arg2))
        goto err;

    if (of_property_read_u32_index(np, "relays", offset + 3, &arg3))
        goto err;
}

Драйвер drivers / clk / at91 / clk-pll.c использует аналогичный код для извлечения значений из свойства atmel,pll-clk-output-ranges:

        pmc: pmc@fffffc00 {
            plla: pllack {
                atmel,clk-input-range = <2000000 32000000>;
                atmel,pll-clk-output-ranges = <745000000 800000000 0 0>,
                            <695000000 750000000 1 0>,
                            <645000000 700000000 2 0>,
                            <595000000 650000000 3 0>,
                            <545000000 600000000 0 1>,
                            <495000000 550000000 1 1>,
                            <445000000 500000000 2 1>,
                            <400000000 450000000 3 1>;
            };  
            ...
        };            

ADDENDUM

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

    node1 {
        xxx = <745000000 800000000 0 0>,
            <695000000 750000000 1 0>,
            <645000000 700000000 2 0>,
            <595000000 650000000 3 0>,
            <545000000 600000000 0 1>,
            <495000000 550000000 1 1>,
            <445000000 500000000 2 1>,
            <400000000 450000000 3 1>;
    };

    node2 {
        xxx = < 745000000 800000000 0 0
            695000000 750000000 1 0
            645000000 700000000 2 0
            595000000 650000000 3 0
            545000000 600000000 0 1
            495000000 550000000 1 1
            445000000 500000000 2 1
            400000000 450000000 3 1 >;
    };

имеют то же значение при выгрузке из / proc / device-tree / :

# hexdump -C node1/xxx
00000000  2c 67 cc 40 2f af 08 00  00 00 00 00 00 00 00 00  |,g.@/...........|
00000010  29 6c db c0 2c b4 17 80  00 00 00 01 00 00 00 00  |)l..,...........|
00000020  26 71 eb 40 29 b9 27 00  00 00 00 02 00 00 00 00  |&q.@).'.........|
00000030  23 76 fa c0 26 be 36 80  00 00 00 03 00 00 00 00  |#v..&.6.........|
00000040  20 7c 0a 40 23 c3 46 00  00 00 00 00 00 00 00 01  | |.@#.F.........|
00000050  1d 81 19 c0 20 c8 55 80  00 00 00 01 00 00 00 01  |.... .U.........|
00000060  1a 86 29 40 1d cd 65 00  00 00 00 02 00 00 00 01  |..)@..e.........|
00000070  17 d7 84 00 1a d2 74 80  00 00 00 03 00 00 00 01  |......t.........|
00000080
# hexdump -C node2/xxx
00000000  2c 67 cc 40 2f af 08 00  00 00 00 00 00 00 00 00  |,g.@/...........|
00000010  29 6c db c0 2c b4 17 80  00 00 00 01 00 00 00 00  |)l..,...........|
00000020  26 71 eb 40 29 b9 27 00  00 00 00 02 00 00 00 00  |&q.@).'.........|
00000030  23 76 fa c0 26 be 36 80  00 00 00 03 00 00 00 00  |#v..&.6.........|
00000040  20 7c 0a 40 23 c3 46 00  00 00 00 00 00 00 00 01  | |.@#.F.........|
00000050  1d 81 19 c0 20 c8 55 80  00 00 00 01 00 00 00 01  |.... .U.........|
00000060  1a 86 29 40 1d cd 65 00  00 00 00 02 00 00 00 01  |..)@..e.........|
00000070  17 d7 84 00 1a d2 74 80  00 00 00 03 00 00 00 01  |......t.........|
00000080
# cmp node1/xxx node2/xxx
# 

В любой версии свойства угловые скобки (также известные как шевроны) и запятые, похоже, игнорируются, а значения просто сохраняются как одномерный массив целых чисел (с порядком байтов в старшем порядке).


ADDENDUM 2

Приведенные выше результаты подтверждаются двумя утверждениями в Спецификации DeviceTree (выпуск v0.2-18-g8466c3b-dirty), раздел 6.3:

Массивы ячеек (то есть единицы информации, состоящие из 32 битов) представлены угловыми скобками, окружающими разделенный пробелами список целых чисел в стиле C

и

(Свойство) Значения могут иметь несколько компонентов, разделенных запятыми, которые объединяются вместе.

Следовательно, значение свойства, представляющее собой отдельный массив, неотличимо от нескольких объединенных массивов.
Использование списка n-кортежей было бы чисто для эстетики и читабельности.

«Организацию» данных (в виде n-кортежей) невозможно определить на уровне dtb.
Таким образом, размер или n n-кортежа (или « список ячеек ») должен быть передан драйверу в другом свойстве или указан в документе привязок (если он жестко задан в драйвере).

...