AMD Chipset Drivers
| Разработчик: | Advanced Micro Devices (США) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Лицензия: | Бесплатно | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Версия: | 3.10.08.506 (Windows 10/11, 64-bit) / 2.17.25.506 (Windows 7, 64-bit) / 18.10.0830 (32-bit) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Обновлено: | 2021-10-21 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Системы: | Windows 11 / 10 / 8.1 / 8 / 7 / Vista / XP (32/64-bit) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Интерфейс: | русский / английский | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Рейтинг: | ![]() | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ваша оценка: |
| Имя регистра | Смещение | Имя в драйвере | Комментарий |
|---|---|---|---|
| GPIO_IRQSTATUS_0 | 0x02С | OMAP4_GPIO_IRQSTATUS_0 | Состояние прерывания для заданного входа |
| GPIO_IRQSTATUS_1 | 0x030 | OMAP4_GPIO_IRQSTATUS_1 | Состояние прерывания для заданного входа |
| GPIO_IRQSTATUS_SET_0 | 0x034 | OMAP4_GPIO_IRQSTATUS_SET_0 | Включает прерывания по заданному входу |
| GPIO_IRQSTATUS_SET_1 | 0x038 | OMAP4_GPIO_IRQSTATUS_SET_1 | Включает прерывания по заданному входу |
| GPIO_IRQSTATUS_CLR_0 | 0x03С | OMAP4_GPIO_IRQSTATUS_CLR_0 | Выключает прерывания по заданному входу |
| GPIO_IRQSTATUS_CLR_1 | 0x040 | OMAP4_GPIO_IRQSTATUS_CLR_1 | Выключает прерывания по заданному входу |
| GPIO_OE | 0x134 | OMAP4_GPIO_OE | Контролирует состояние вход/выход (in/out) |
| GPIO_DATAIN | 0x138 | OMAP4_GPIO_DATAIN | Состояние входа/выхода |
| GPIO_DATAOUT | 0x13C | OMAP4_GPIO_DATAOUT | Задание состояния для выходов (low/high) |
| GPIO_LEVELDETECT0 | 0x140 | OMAP4_GPIO_LEVELDETECT0 | Включение/выключения прерывания для входа по низкому уровню сигнала |
| GPIO_LEVELDETECT1 | 0x144 | OMAP4_GPIO_LEVELDETECT1 | Включение/выключения прерывания для входа по высокому уровню сигнала |
| GPIO_RISINGDETECT | 0x148 | OMAP4_GPIO_RISINGDETECT | Включение/выключения прерывания для входа по переднему фронту |
| GPIO_FALLINGDETECT | 0x14С | OMAP4_GPIO_FALLINGDETECT | Включение/выключения прерывания для входа по заднему фронту |
| GPIO_CLEARDATAOUT | 0x190 | OMAP4_GPIO_CLEARDATAOUT | Переключает соответствующий вход в состояние low |
| GPIO_SETDATAOUT | 0x194 | OMAP4_GPIO_SETDATAOUT | Переключает соответствующий вход в состояние high |
Примечание: GPIO_IRQSTATUS_N также используется для IRQ ACK. Управление дребезгом, а так же питанием выходит за рамки данной статьи.
ep9301
Разработчик: Cirrus Logic
Документация: EP9301 User’s Guide (page 523)
Соответствующий ему драйвер gpio: linux/drivers/gpio/gpio-ep93xx.c
Соответствующий заголовок: linux/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h
Количество входов/выходов: 56 (7 портов gpio — по 8 контактов каждый)
| Имя регистра | Смещение | Имя в драйвере | Описание |
|---|---|---|---|
| PADR | 0x00 | EP93XX_GPIO_REG(0x0) | Регистр состояние входов/выходов доступен для чтения записи |
| PADDR | 0x10 | EP93XX_GPIO_REG(0x10) | Контролирует состояние вход/выход (in/out) |
| GPIOAIntEn | 0x9C | int_en_register_offset[0] | Включает прерывания по заданному входу |
| GPIOAIntType1 | 0x90 | int_type1_register_offset[0] | Задает тип прерывания level/edge |
| GPIOAIntType2 | 0x94 | int_type2_register_offset[0] | Задает high/rising или low/fallingв зависимости от выбранного типа прерываний |
| GPIOAEOI | 0x98 | eoi_register_offset[0] | Регистр для оповещения об обработанном прерывании |
| IntStsA | 0xA0 | EP93XX_GPIO_A_INT_STATUS | Регистр состояние прерывания |
Примечание:
Из них для доступны 7 портов по 8, 8, 1, 2, 3, 2, 4 входов/выходов причем регистрами прерываний обладают только первый, второй и пятый порты.
В таблице рассмотрен только порт A.
Одной из особенностей ep9301, является то что тип прерываний both на аппаратном уровне не поддерживается, в драйвере происходит переключение в момент срабатывания прерывания. Другая интересная особенность — на порту F каждый контакт имеет свое собственное прерывание.
Bt848
Последний пример: pci плата Bt848, с gpio.
Разработчик: Intel
Документация: Bt848/848A/849A (page 68)
Соответствующий драйвер gpio: linux/drivers/gpio/gpio-bt8xx.c
Соответствующий заголовок: linux/drivers/media/pci/bt8xx/bt848.h
Количество входов/выходов: 24
Bt848 является платой видеозахвата.
| Имя регистра | Смещение | Имя в драйвере | Описание |
|---|---|---|---|
| BT848_GPIO_OUT_EN | 0x118 | BT848_GPIO_OUT_EN | Регистр состояние входов/выходов доступен для чтения и записи |
| BT848_GPIO_DATA | 0x200 | BT848_GPIO_DATA | Контролирует состояние вход/выход (in/out) |
Поддержки прерываний нет. Всего два регистра — состояние и настройка in/out.
Размечаем в памяти наше устройство
Для начала выделим место под данные и управление состоянием.
Пусть устройство обладает 8 входами/выходами общего назначения, тогда:
| Имя регистра | Смещение | Имя в драйвере | Описание |
|---|---|---|---|
| DATA | 0x00 | VIRTUAL_GPIO_DATA | Регистр состояние входов/выходов доступен для чтения и записи |
| OUTPUTEN | 0x01 | VIRTUAL_GPIO_OUT_EN | Контролирует состояние вход/выход (in/out) |
Краткая справка по интерфейсу gpio
Состояние выхода при переключении
Необходимо отметить параметр int value в функции direction_output, которая обслуживает файл /sys/class/gpio/gpioN/direction, принимающий значение не только “in”/”out”, но так же и “high”/“low”, значения которых передаются как параметр value (этот простой факт, по какой-то причине, редко упоминается в руководствах для начинающих).
Динамическое присвоение int base и наследие ARCH_NR_GPIOS
Исторически, количество GPIO в ядре было ограничено параметром ARCH_NR_GPIOS, по умолчанию равном 256 и, впоследствии увеличенном до 512 (версия 3.18).
Его смысл достаточно прост, в ядре не может быть больше GPIO чем значение параметра, если планируемое количество было больше чем значение по умолчанию, он переопределялся в соответствующем заголовочном файле платформы.
Причиной такого поведения было определение таблицы описаний GPIO как статической и максимальная величина смещения для каждого порта была ограничена:
Порты GPIO и их смещения были жестко определены в файлах описывающих аппаратную часть конкретного SOC, например:
Начиная с версии 3.19 статический массив был заменен на динамические для каждого порта GPIO, выделяемого в фукнции gpiochip_add().
Тем не менее ARCH_NR_GPIOS все еще здесь (на момент версии 4.7) и используется для поиска смещения при динамическом присваивании base.
Определим следующие функции нашего драйвера
Задать соответствующий контакт как вход:
Чтение текущего состояния контакта:
Задать соответствующий контакт как выход:
Задать состояние выхода:
Функция регистрации нашего драйвера как устройства gpio_chip:
vgread и vgwrite это просто обертки для функций iowrite8 и ioread8:
Передача значения gpiobase в качестве параметра при динамической загрузки модуля
Загрузка и тестирования модуля
DATA выставлен, OUTPUTEN выставлен.
Добавляем прерывания
Разметка регистров прерываний и базовая обработка прерывания
Примечание: В виртуальном драйвере рассматриваются только EDGEDETECT_RISE и EDGEDETECT_FALL.
Добавляем следующие регистры:
| Имя регистра | Смещение | Имя в драйвере | Описание |
|---|---|---|---|
| INTERRUPT_EN | 0x01 | VIRTUAL_GPIO_INT_EN | Включает прерывания по заданному входу |
| INTERRUPT_ST | 0x02 | VIRTUAL_GPIO_INT_ST | Регистр состояния прерывания |
| INTERRUPT_EOI | 0x03 | VIRTUAL_GPIO_INT_EOI | Регистр для оповещения об обработанном прерывании |
| EDGEDETECT_RISE | 0x04 | VIRTUAL_GPIO_RISING | Включение/выключения прерывания для входа по переднему фронту |
| EDGEDETECT_FALL | 0x05 | VIRTUAL_GPIO_FALLING | Включение/выключения прерывания для входа по заднему фронту |
| LEVELDETECT_HIGH | NC | NOT CONNECTED | |
| LEVELDETECT_LOW | NC | NOT CONNECTED |
За обработку прерывания от pci шины отвечает следующая функция, на данный момент её роль заключается всего лишь в уведомлении об обработанном прерывании:
irq_chip и концепция chained_interrupt
На данный момент для нас является главным тот факт, что порты GPIO предоставляющие прерывания каскадируемые от родительского контроллера прерываний обычная практика в дни современного линукса.
Вот почему часть драйвера GPIO отвечающего за прерывания использует irq_chip. Другими словами такой драйвер использует две подсистемы одновременно: gpio_chip и irq_chip.
Беглый взгляд на подсистему irq дает нам следующую картину:
High-Level Interrupt Service Routines (ISRs) — Выполняет всю необходимую работу по обслуживанию прерывания на драйвере устройства. Например, если прерывание используется для индикации доступных для чтения новых данных, работа ISR будет заключаться в копировании данных в соответствующее место.
Interrupt Flow Handling — Данная подсистема отвечает за особенности в реализации обработок прерываний, таких как срабатывание по уровню сигнала (level) или по фронту (edge).
Срабатывание по фронту (Edge-triggering) происходит при определении, что на линии произошло изменение потенциала. Срабатывание по уровню (Level-triggering), определяется как определенное значение потенциала, при этом изменение потенциала не играет роли.
С точки зрения ядра, срабатывание по уровню более сложный случай, так как, после в начале каждого прерывания его необходимо маскировать.
Chip-Level Hardware Encapsulation — Используется для инкапсуляции особенностей реализации работы с аппаратной частью. Данную подсистему можно рассматривать как разновидность “драйвера устройства” для контроллеров прерываний.
Как мы видим ядро берет на себя управление обработкой цепочки прерывания и разницу в реализации типов (по фронту и по уровню), если предоставить соответствующую инфраструктуру.
IRQ Domains
Подсистема IRQ Domain появившееся в патче irq: add irq_domain translation infrastructure позволила отделить локальные для контроллера номера прерываний от номеров прерываний в ядре, предоставив общий массив номеров прерываний. Цитируя официальную документацию: «Сегодня номер IRQ, это просто номер».
До данного обновления аппаратные номера отображались на номерами ядра как 1:1, а каскадирование не поддерживалось. Под аппаратными номерами, понимается локальные для контроллера номера прерывания, которые в нашем случае совпадают с локальными номерами GPIO.
Поскольку наш вектор прерываний достаточно мал, и у нас точно нет интереса в «No map» отображении, наше отображение линейно, фактически номера сопоставляются 1:1 со смещением, разница со старым подходом состоит в том что за присвоение номеров irq и за вычисление смещения отвечает ядро, при этом гарантируется непрерывность выделяемого диапазона.
В каждую функцию интерфейса irq_chip передается указатель на структуру struct irq_data, где irq_data->irq это номер прерывания в ядре linux, a irq_data->hwirq это наш локальный номер прерывания в рамках драйвера. Так же в struct irq_data передается указатель на нашу структуру struct virtual_gpio, что неудивительно.
Связывание irq_chip и gpio_chip
Если бы мы ориентировались на более младшие версии ядра, нам пришлось бы воспользоваться функцией irq_domain_add_simple для отображения наших номер, но с версии 3.15 в патче gpio: add IRQ chip helpers in gpiolib patch нет необходимости напрямую использовать интерфейс IRQ Domain.
Поэтому вместо прямого использования интерфейса IRQ Domain и предоставления инфраструктуры для отображения локальных номеров на глобальные (.map() ops), мы воспользуемся функциями gpiochip_irqchip_add и gpiochip_set_chained_irqchip (зависят от параметра GPIOLIB_IRQCHIP Kconfig).
Прекрасным примером использования и простоты в применении, является драйвер gpio-pl061.
Привязываем наш irq_chip к уже существующему gpio_chip:
handle_edge_irq — это один из встроенных обработчиков потока, который берет на себя управление цепочкой прерывания по фронтам.
Примечание: прерывания по фронтам является наиболее распространенным. Главное отличие от прерываний по уровню заключается как раз в управлении цепочкой, прерывание по уровню маскируется в ядре сразу после получения.
Вызовом функции gpiochip_set_chained_irqchip мы сообщаем ядру, что наш irq_chip использует прерывание от PCI шины и наши прерывания каскадируются от pdev->irq.
Доработаем наш обработчик, чтобы он генерировал прерывания в зависимости от состояния VIRTUAL_GPIO_INT_ST:
irq_find_mapping — вспомогательная функция для трансляции локального номера входа в глобальный номер прерывания.
Собираем все вместе
Прежде всего, отметим, что интерфейс irq_chip нашего драйвера, выглядит следующим образом:
Функция ack() всегда тесна связана с аппаратной спецификой контроллера. Некоторым устройствам, например требуется подтверждение обработки запроса прерывания, прежде чем могут быть обслужены последующие запросы.
В нашем случае в программе vg_get_set – используется достаточно грубая эмуляция регистра eoi. После выставления флага статуса прерывания, в цикле постоянно опрашивается eoi регистр. Когда бит входа уведомления о прерывании выставляется драйвером, происходит обнуление регистра eoi и снятие бита статуса прерывания на входе.
Маскирование и демаскирование производится записью соответствующего значения в регистр INTERRUPT_EN.
irq_type позволяет задать тип триггера — на текущий момент в ядре определены следующие типы:
IRQ_TYPE_NONE — тип не задан
IRQ_TYPE_EDGE_RISING — по переднему фронту
IRQ_TYPE_EDGE_FALLING — по заднему фронту
IRQ_TYPE_EDGE_BOTH — по переднему и заднему фронту
IRQ_TYPE_LEVEL_HIGH — по высокому уровню
IRQ_TYPE_LEVEL_LOW — по низкому уровню
Тестирование и результаты
Для тестирования передачи информации о прерываниях в user space, воспользуемся специально написанной утилитой vg_guest_client. Согласно документации по gpio_sysfs, “Если вы используете select для отслеживания событий, задайте файловый дескриптор (входа) в exceptfds”.
Подготавливаем входы к работе при помощи sysfs:
Примечание: gpio на подавляющем большинстве устройств по умолчанию инициализируются как входы.
Цепочка вызовов от нашего обработчика прерывания к уведомлению pselect:
Заключение
Данная статья подразумевалась мной, как базовая для материала, который сложно, или даже невозможно, представить без какого-либо общего вступления. Qemu в паре с ivshmem послужили отличным и понятным базисом для этой цели. Причиной выбора этой конкретной связки является наличие вменяемой документации и прозрачности использования.
Сама работа с gpio sysfs ничем не отличается для любых устройств с реализованной поддержкой sysfs, любая инструкция по использованию GPIO может быть успешно применена к другому подобному устройству, как и задумывалось при разработке данного интерфейса. Все различия заканчиваются на уровне конкретного драйвера устройства.
Сам драйвер, несмотря на безусловную образовательную ценность, далек от идеала в контексте современного ядра. Для подобного простого драйвера стоит использовать generic-gpio драйвер, созданный, чтобы избежать похожего, повторяющегося кода для mmio gpio драйверов, использование которого, правда, не так очевидно. Обработку прерываний можно было бы сделать более элегантной, а значения смещений регистров лучше хранить в структуре драйвера.
Так же нельзя упускать из виду последние изменения в gpiolib — sysfs gpio теперь является устаревшей. Новый основанный на ioctl интерфейс для gpiolib на пути становления как новый стандарт для общения с GPIO. Но младшие версии еще долго будут использоваться, к тому же никто не собирается на данный момент убирать из ядра старый интерфейс. У меня например до сих пор есть устройства успешно работающие на версии ядра 2.6.34.
990x.top
Простой компьютерный блог для души)
AMD PCI Device Driver — что это за драйвер?

Драйвер входит в состав пакета AMD Chipset Drivers.
Скорее всего нужен для корректной работы шины PCI и для обеспечения максимальной скорости. Что такое шина PCI? Это разьем на материнской плате, часто не один, в который могут устанавливаться разные устройства — например сетевая плата, звуковая плата, внешний Wi-Fi модуль, дополнительные порты USB, и конечно же видеокарта. Последнее — пожалуй наиболее важное, поэтому ставить драйвер нужно. Тем более, что AMD добавила поддержку PCI Express 4.0, для корректной работы как раз возможно и нужен драйвер.
Windows 10 способна автоматически обновить данный драйвер. Это хорошо, но после установки, можно попробовать установить и драйвер с официального сайта AMD или с сайта вашей модели материнки. Редко, но иногда Windows ставит драйвер не очень старый, но стабильный, однако при этом не самой последней версии.
Вообще на самом деле шина называется не PCI, а PCI-E.
Вот как выглядит разьем PCI-E на материнке:

Чтобы посмотреть установлены дрова или нет, то стоит открыть диспетчер устройств (Win + R > devmgmt.msc) и посмотреть нет ли устройства с восклицательным знаком. Второе — это открыть окно Программы и компоненты (Win + R > appwiz.cpl) и посмотреть в списке нет ли там установленных драйверов AMD PCI Device Driver, кроме этого, в этом же окне можно нажать Просмотр установленных обновлений — там тоже может быть нужная информация.
Собственно если драйвер не установлен, то может быть такая картина в диспетчере:
Надеюсь информация оказалась полезной. Удачи и добра, до новых встреч друзья!





