Как использовать дерево устройств


1. Базовый формат данных

2. Основные понятия

3.   Как работает адресация  

4. Как работают прерывания

5. Специфические данные устройства

6. Специальные узлы

7. Машина с мостом Host/PCI



3. Как работает адресация

Адресуемые устройства используют следующие свойства для кодирования адресной информации в дереве устройств:

  • reg
  • #address-cells
  • #size-cells

    Каждое адресуемое устройство получает список reg кортежей в формате: reg = < address1 length1 [address2 length2] [address3 length3] ... >.

    Примечание ред.. По определению, кортеж ( tuple )- это упорядоченный набор даных фиксированной длины. Кортеж отличается от списка или массива тем, что элементы кортежа могут принадлежать разным типам и набор таких типов заранее определён типом кортежа, а значит, и размер кортежа также определён.

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

    Каждое значение адреса представляет собой список из одного или нескольких 32-битных целых чисел, называемых ячейками (cells). Точно так же значение длины (length) может быть списком ячеек или пустым.

    Поскольку поля адреса и длины являются переменными и имеют переменный размер, свойства #address-cells и #size-cells родительского узла используются для определения количества ячеек в каждом поле. Или, другими словами, для правильной интерпретации свойства reg требуются значения #address-cells и #size-cells родительского узла.

    Чтобы увидеть, как все это работает, давайте добавим свойства адресации в образец дерева устройств, начиная с процессоров.


    3.1. Адресация ЦП

    Узлы ЦП представляют собой простейший случай, когда речь идет об адресации. Каждому ЦП назначается один уникальный идентификатор, и с идентификаторами ЦП не связан размер.

    В узле cpus значение свойства #address-cells=1 и #size-cells=0. Это означает, что дочерние значения reg - это один uint32, представляющий адрес без поля размера.

    В этом случае двум процессорам назначаются адреса 0 и 1. Значение свойства #size-cells равно 0 для узлов процессора, потому что каждому процессору назначается только один адрес. Обратите внимание, что значение reg соответствует значению в имени узла. По соглашению, если узел имеет свойство reg, тогда имя узла должно включать адрес устройства, который является первым значением адреса в свойстве reg.


    3.2. Устройства с отображением в памяти

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

    Свойство #size-cells используется для указания размера поля длины в каждом дочернем кортеже reg. В следующем примере каждое значение адреса составляет 1 ячейку (32 бита), и каждое значение длины также равно 1 ячейке, что типично для 32-битных систем.

    64-битные машины могут использовать значение #address-cells=2 и #size-cells=2 чтобы получить 64-битную адресацию в дереве устройств.

    Каждому устройству назначается базовый адрес и диапазон адресов. Для портов GPIO в этом примере назначены два диапазона адресов:

  • 0x101f3000 - 0x101f3fff
  • 0x101f4000 - 0x101f400f

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

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

    external-bus использует 2 ячейки для значения адреса: один для номера выбора чипа (CS) и один для смещения от базового адреса выбора чипа (CS). Поле длины остается одной ячейкой, поскольку только часть смещения адреса должна иметь диапазон. Итак, в этом примере каждая запись reg содержит 3 ячейки; номер выбора чипа, смещение и длина.

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


    3.3. Устройства без отображения в памяти

    Другие устройства не отображаются в память на шину процессора. У них могут быть диапазоны адресов, но они не доступны напрямую ЦП. Вместо этого драйвер родительского устройства будет выполнять косвенный доступ от имени ЦП.

    В качестве примера с устройствами i2c каждому устройству назначается адрес, но с ним не связана длина или диапазон. Это похоже на назначение адресов ЦП.


    3.4. Трансляция адресов (Ranges)

    Мы говорили о том, как назначать адреса устройствам, но на данный момент эти адреса являются локальными только для узла устройства. Он еще не описывает, как сопоставить этот адрес с адресом, который может использовать ЦП. Корневой узел всегда описывает точку зрения ЦП на адресное пространство.

    Дочерние узлы корня уже используют адресный домен ЦП и поэтому не нуждаются в явном отображении. Например, устройству serial @ 101f0000 напрямую назначается адрес 0x101f0000.

    Узлы, которые не являются прямыми потомками корня, не используют адресный домен ЦП. Чтобы получить адрес, отображаемый в памяти, в дереве устройств должно быть указано, как транслировать адреса из одного домена в другой. Для этого используется свойство ranges.

    Вот пример дерева устройств с добавленным свойством ranges.

    Свойство ranges - это список трансляции адресов. Каждая запись в таблице диапазонов представляет собой тройной кортеж, содержащий :

  • дочерний адрес
  • родительский адрес
  • размер области в дочернем адресном пространстве.

    Размер каждого поля определяется путем взятия значения дочернего #address-cells, значения родительского #address-cells и значения дочернего #size-cells. Для внешней шины в нашем примере дочерний адрес составляет 2 ячейки, родительский адрес - 1 ячейка, а размер также равен 1 ячейке.

    Транслируются три диапазона:

  • Смещение 0 для chip select 0 отображается в диапазон адресов 0x10100000 - 0x1010ffff
  • Смещение 0 для chip select 1 отображается в диапазон адресов 0x10160000 - 0x1016ffff
  • Смещение 0 для chip select 2 отображается в диапазон адресов 0x30000000 - 0x30ffffff

    В качестве альтернативы, если родительское и дочернее адресные пространства идентичны, то может вместо этого добавить в узел пустое свойство ranges. Наличие пустых диапазонов свойства означает, что адреса в дочернем адресном пространстве отображаются 1:1 в родительское адресное пространство.

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

    Некоторые шины (например, PCI) имеют совершенно разные адресные пространства, детали которых должны быть доступны операционной системе. У других есть механизмы DMA, которым необходимо знать реальный адрес на шине. Иногда устройства необходимо сгруппировать вместе, потому что все они используют одно и то же программируемое физическое отображение адресов.

    Использование отображения 1:1 во многом зависит от информации, необходимой операционной системе, и от конструкции оборудования.

    Обратите внимание, что в узле i2c@1,0 нет свойства ranges Причина этого в том, что, в отличие от внешней шины, устройства на шине i2c не отображают в память в адресном пространстве ЦП. Вместо этого ЦП косвенно обращается к устройству rtc@58 через устройство i2c@1,0.

    Отсутствие свойства ranges означает, что к устройству не может получить прямой доступ ни одно устройство, кроме его родительского.



  •   1    2    3    4    5    6    7