Анализ кода инициализации контроллера USB3.0 ядра Linux-шины USB (3)
Анализ кода инициализации контроллера USB3.0 ядра Linux-шины USB (3)

1. Обзор

RK33999 использует IP-адрес контроллера USB3.0 Synopsys dwc3. Раннюю инициализацию необходимо выполнить в двух модулях. Один из них инициализируется в официально предоставленном Rockchip драйвере, расположенном в файле driver/usb/dwc3/dwc3-rockchip.c. Он в основном инициализирует контент, тесно связанный с ЦП, например. часы, сброс, питание, extcon( Используется для переключения режима USB), другой инициализируется в драйвере, предоставленном Synopsys и расположенном в файле driver/usb/dwc3/core.c. Эта часть тесно связана с контроллером USB3.0, например USB3.0. Адрес внутреннего регистра контроллера, USB3.0 PHY, прерывания и т. д. Только когда оба модуля инициализированы, контроллер USB3.0 может работать нормально. В этом разделе анализируется только часть ранней инициализации драйвера USB.

2.Дерево устройств

Ниже представлен узел дерева устройств контроллера USB3.0. Самый внешний совместимый атрибут — «rockchip,rk3399-dwc3», который является атрибутом, определенным Rockchip, включая часы, питание, сброс, extcon и т. д. Extcon (внешние разъемы) — это драйвер USB, используемый для уведомления о состоянии. Он в основном используется для переключения режима USB. Когда PHY получает прерывание и обрабатывает статус USB, он передает его всем драйверам, отслеживающим событие через драйвер extcon. Используйте devm_extcon_register_notifier для регистрации функции обратного вызова, которая отслеживает изменения состояния USB. Атрибутами совместимости внутреннего уровня являются «snps, dwc3», которые определяются синопсисом и в основном связаны с контроллерами USB и PHY. Конкретную информацию об атрибутах узла устройства dwc3 см. в документе Documentation/devicetree/bindings/usb/dwc3.txt.

Поскольку узел дерева устройств usbdrd3_0 является дочерним узлом корневого узла и имеет атрибут совместимости, ядро ​​автоматически преобразует его в Platform_device и затем сопоставляет его с соответствующим драйвером. Однако его дочерний узел usbdrd_dwc3_0 не будет обрабатываться ядром. и будет обработан его родительским узлом, обрабатывающим драйвер usbdrd3_0.

Язык кода:javascript
копировать
usbdrd3_0: usb0 {

    compatible = "rockchip,rk3399-dwc3";

    clocks = <&cru SCLK_USB3OTG0_REF>, <&cru SCLK_USB3OTG0_SUSPEND>,

            <&cru ACLK_USB3OTG0>, <&cru ACLK_USB3_GRF>;

    clock-names = "ref_clk", "suspend_clk", "bus_clk", "grf_clk";

    power-domains = <&power RK3399_PD_USB3>;  // источник питания

    resets = <&cru SRST_A_USB3_OTG0>;  // для сброса

    reset-names = "usb3-otg";

    #address-cells = <2>;

    #size-cells = <2>;

    ranges;

    status = "disabled";



    usbdrd_dwc3_0: dwc3@fe800000 {

        compatible = "snps,dwc3";

        reg = <0x0 0xfe800000 0x0 0x100000>;

        interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH 0>;  // Атрибут прерывания

        dr_mode = "otg";  // режим, режим по умолчанию — OTG

        phys = <&u2phy0_otg>, <&tcphy0_usb3>;

        phy-names = "usb2-phy", "usb3-phy";  // USB PHY

        phy_type = "utmi_wide";

        /* when set clears the enblslpm in GUSB2PHYCFG,

            disabling the suspend signal to the PHY */

        snps,dis_enblslpm_quirk;

        /* when set, clear the u2_freeclk_exists in GUSB2PHYCFG, 

           specify that USB2 PHY doesn't provide a free-running PHY clock */

        snps,dis-u2-freeclk-exists-quirk;

        /* when set core will disable USB2 suspend phy */

        snps,dis_u2_susphy_quirk;

        /* when set core will change PHY power from P0 to P1/P2/P3 without delay */

        snps,dis-del-phy-power-chg-quirk;

        /* when set, disable u2mac linestate check during HS transmit */

        snps,tx-ipgap-linecheck-dis-quirk;

        /* when set, need an extraordinary delay to wait for xHC enter the 

           Halted state (i.e. HCH in the USBSTS register is '1') */

        snps,xhci-slow-suspend-quirk;

        /* when set, the xHC use the Evaluate Next TRB(ENT) flag to force

           the xHC to pre-fetch the next TRB of a TD */

        snps,xhci-trb-ent-quirk;

        /* when set, need warm reset on resume */

        snps,usb3-warm-reset-on-resume-quirk;

        status = "disabled";

    };

};

&usbdrd3_0 {

    status = "okay";

    extcon = <&fusb0>;

};

&i2c4 {

    status = "okay";

    i2c-scl-rising-time-ns = <160>;

    i2c-scl-falling-time-ns = <30>;

    clock-frequency = <400000>;



    fusb0: fusb30x@22 {

        compatible = "fairchild,fusb302";

        reg = <0x22>;

        pinctrl-names = "default";

        pinctrl-0 = <&fusb0_int>;

        int-n-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;

        vbus-5v-gpios = <&gpio4 26 GPIO_ACTIVE_HIGH>;

        status = "okay";

    };

    ......

};

3. Инициализируйте анализ драйверов.

Драйвер инициализации разделен на две части: одна часть — это инициализация, связанная с процессором, например тактовой частотой, питанием и т. д., которая выполняется драйвером, предоставляемым Rockchip. Другая часть — это инициализация, связанная с контроллером USB, например. Адрес регистрации контроллера USB, прерывание, PHY и т. д. Дополняется официальным драйвером Synopsys. Эти две части анализируются отдельно: сначала анализируется драйвер, предоставленный Rockchip, и, наконец, анализируется официальный драйвер из Synopsys.

3.1.rockchip Анализ драйвера инициализации USB

Драйвер инициализации USB, предоставляемый Rockchip, — это Platform_driver, атрибут соответствия дерева устройств — «rockchip,rk3399-dwc3», а функция входа — dwc3_rockchip_probe. Разберем процесс выполнения функции входа.

Язык кода:javascript
копировать
[drivers/usb/dwc3/dwc3-rockchip.c]

static const struct of_device_id rockchip_dwc3_match[] = {

    { .compatible = "rockchip,rk3399-dwc3" },

    { /* Sentinel */ }

};

MODULE_DEVICE_TABLE(of, rockchip_dwc3_match);

static struct platform_driver dwc3_rockchip_driver = {

    .probe		= dwc3_rockchip_probe,

    .remove		= dwc3_rockchip_remove,

    .driver		= {

        .name	= "rockchip-dwc3",

        .of_match_table = rockchip_dwc3_match,

        .pm	= DEV_PM_OPS,

    },

};

module_platform_driver(dwc3_rockchip_driver);

Основная работа функции dwc3_rockchip_probe заключается в следующем:

(1) Получите часы и включите часы.

(2) Преобразуйте дочерний узел usbdrd_dwc3_0 в Platform_device и сохраните указатель структуры частных данных dwc3 драйвера устройства, соответствующего дочернему узлу. Если указатель структуры dwc3 не может быть получен, будет возвращен EPROBE_DEFER, и ядро ​​выполнит команду. dwc3_rockchip_probe позже.

(3) Обработайте атрибут extcon и установите функцию обратного вызова для устройства — dwc3_rockchip_device_notifier. Функция обратного вызова хоста — dwc3_rockchip_host_notifier. Функция обратного вызова выполняется через рабочую очередь otg_work.

(4) Асинхронно выполнить функцию dwc3_rockchip_async_probe, в основном регистрируя обратные вызовы уведомлений, устанавливая мощность и т. д.

Язык кода:javascript
копировать
    dwc3_rockchip_probe

        devm_kzalloc  // выделить структуру Структурная память dwc3_rockchip

        of_clk_get_parent_count       // Получите количество источников синхронизации, на которые ссылается дерево устройств.

        rockchip->num_clocks = count  // Количество сохраненных источников синхронизации

        devm_kcalloc             // Выделить структуры num_clocks клк*указатель

        platform_set_drvdata     // Сохранить указатель dwc3_rockchip

        clk = of_clk_get(np, i)  // Получить часы

        clk_prepare_enable       // включить часы

        rockchip->clks[i] = clk  // Сохранить указатель структуры часов

        pm_runtime_set_active    // источник связанные с управлением питанием

        pm_runtime_enable

        pm_runtime_get_sync 

        devm_reset_control_get(dev, "usb3-otg")  // Получить для сбросаизreset_control

        of_get_child_by_name(np, "dwc3")         // Получить device_node дочернего узла dwc3.

        /* Пройдите все дочерние узлы указанного узла и преобразуйте составные требования в Platform_device, то есть дочерние узлы usbdrd3_0.

           usbdrd_dwc3_0 преобразован в Platform_device */

        of_platform_populate  

        // Инициализируйте рабочую очередь. Функция входа в рабочую очередь — dwc3_rockchip_otg_extcon_evt_work, которая используется для переключения режима USB.

        INIT_WORK(&rockchip->otg_work, dwc3_rockchip_otg_extcon_evt_work)

        of_find_device_by_node  // Получите указатель Platform_device дочернего узла, которым является узел usbdrd_dwc3_0.

        /* Получите указатель личных данных драйвера дочернего узла, то есть указатель структуры dwc3. Если получение не удалось, возвращается EPROBE_DEFER.

           Ядро позже снова выполнит dwc3_rockchip_probe. */

        rockchip->dwc = platform_get_drvdata  

        // Если это режим хоста и OTG, получите структуру хост-контроллера. указатель usb_hcd

        rockchip->hcd = dev_get_drvdata(&rockchip->dwc->xhci->dev)

        // Обработка атрибутов extcon

        dwc3_rockchip_get_extcon_dev

            // Определите, есть ли атрибут extcon в узле usbdrd3_0.

            device_property_read_bool(dev, "extcon")

            extcon_get_edev_by_phandle  // Получить структуру по указанному узлу дерева устройств extcon_dev

            // Установить функцию обратного вызова уведомлений

            rockchip->device_nb.notifier_call = dwc3_rockchip_device_notifier;

            rockchip->host_nb.notifier_call = dwc3_rockchip_host_notifier;

            rockchip->edev = edev;

        // Асинхронное выполнение функции dwc3_rockchip_async_probe по существу выполняется через рабочую очередь system_unbound_wq.

        async_schedule(dwc3_rockchip_async_probe, rockchip)

Функция обратного вызова extcon следующая. За исключением различных параметров, функции обратного вызова устройства и хоста одинаковы. Все они планируют рабочую очередь otg_work для обработки рабочей задачи через Schedule_work. Функция рабочей задачи — dwc3_rockchip_otg_extcon_evt_work. что в основном связано с переключением режима USB. Подробный анализ драйвера extcon будет сделан позже.

Язык кода:javascript
копировать
    dwc3_rockchip_device_notifier

        // Получите структуру dwc3_rockchip

        rockchip = container_of(nb, struct dwc3_rockchip, device_nb)

        // Когда USB не находится в приостановленном состоянии, запланируйте рабочую очередь otg_work

        schedule_work(&rockchip->otg_work)  



    dwc3_rockchip_host_notifier

        // Получите структуру dwc3_rockchip

        rockchip = container_of(nb, struct dwc3_rockchip, host_nb)

        // Когда USB не находится в приостановленном состоянии, запланируйте рабочую очередь otg_work

        schedule_work(&rockchip->otg_work)

dwc3_rockchip_async_probe — это асинхронно выполняемая функция, которая по существу выполняется через рабочую очередь system_unbound_wq. Основная работа — зарегистрировать функцию обратного вызова уведомлений extcon, включить USB PHY и создать группу файлов атрибутов отладки.

Язык кода:javascript
копировать
    dwc3_rockchip_async_probe

        // Узнайте, имеет ли устройство атрибут «needs-reset-on-resume», и верните true, если да.

        device_property_read_bool(dev, "needs-reset-on-resume")

        devm_extcon_register_notifier(..., &rockchip->device_nb)  // Зарегистрируйте функцию обратного вызова уведомлений extcon устройства.

        devm_extcon_register_notifier(..., &rockchip->host_nb)    // Зарегистрируйте функцию обратного вызова уведомления extcon хоста



        // Если extcon существует или dr_mode равен USB_DR_MODE_OTG,Затем приступайте к поиску настройки, связанные с питанием

        pm_runtime_set_autosuspend_delay  // Установите время задержки автоприостановки на 500 миллисекунд.

        pm_runtime_allow  // Открыть ленту источников питанияуправлять

        pm_runtime_suspend  // Войти в состояние ожидания

        // Планирование рабочей очереди otg_work, функция выполнения — dwc3_rockchip_otg_extcon_evt_work

        schedule_work(&rockchip->otg_work)  



        // Если extcon не существует и dr_mode не USB_DR_MODE_OTG, это означает, что USB-контроллер не выполняет переключение режимов.

        // Это может быть только режим хоста или режим устройства.

        // Установите для подключения значение true, чтобы предотвратить USB от PM. Выполните сброс контроллера DWC3, когда состояние приостановки переходит в возобновление.

        // Сброс режима хоста приводит к повторному перечислению устройства

        rockchip->connected = true

        // Если на устройстве не установлен атрибут «needs-reset-on-resume», а процессор — «rockchip,rk3399» и

        // dr_modeдляUSB_DR_MODE_HOST        // USB3.0 PHY RK3399 имеет тип C. PHY, помимо включения в dwc3_core_init(), также должен

        // Включите здесь,предотвратитьUSBустройство, подключенное кDWC3Переключатель состояния пост-контроллера хостадляsuspendзакрыто, когдаPHYизисточник питания

        phy_power_on(dwc->usb2_generic_phy)

        phy_power_on(dwc->usb3_generic_phy)

        rockchip->is_phy_on = true



        // Создайте группу файлов свойств отладки.

        sysfs_create_group(&dev->kobj, &dwc3_rockchip_attr_group)

3.2.synopsys Анализ драйвера инициализации USB

3.2.1.Анализ структуры данных

Struct dwc3 — это базовая структура данных контроллера USB3.0 OTG, и вся работа вращается вокруг этой структуры данных. Значение этой структуры данных показано в коде ниже, за исключением некоторых менее важных элементов.

Язык кода:javascript
копировать
    [drivers/usb/dwc3/core.h]

    struct dwc3 {

    	// Запрос управления USB для конечной точки 0, То есть запрос на установку, полученный ep0out, например Get Descriptor, Set Интерфейс и другие команды

        struct usb_ctrlrequest	*ctrl_req;

        struct dwc3_trb		*ep0_trb;       // Конечная точка 0 контролирует передаваемый trb

        // Выделяется с помощью функции kzalloc, Не функция dma_alloc_coherent

        // Get Статус и набор Стандартные запросы, такие как Sel, должны использовать предварительно выделенный буфер в качестве полезной нагрузки передачи USB.

        void			*ep0_bounce;        // отскок конечной точки 0 buffer

        void			*zlp_buf;           // request->zeroиспользуется при настройке

        // В основном используется для функции пробуждения во время сна (гибернации), То есть сохранение информации о регистрах контроллера в памяти во время сна.

        void			*scratchbuf;        // RK3399 контроллер dwc3 не используется

        u8			*setup_buf;             // Используется при обработке стандартных запросов USB.

        dma_addr_t		ctrl_req_addr;      // dma-адрес ctrl_req

        dma_addr_t		ep0_trb_addr;       // dma-адрес ep0_trb

        dma_addr_t		ep0_bounce_addr;    // Адрес dma ep0_bounce

        dma_addr_t		scratch_addr;       // dma-адрес Scratchbuf

        struct dwc3_request	ep0_usb_req;    // dummy req used while handling STD USB requests

        struct device		*dev;

        struct platform_device	*xhci;      // Структура хост-контроллера USB данных

        struct resource xhci_resources[DWC3_XHCI_RESOURCES_NUM];  // Ресурсы хост-контроллера USB

        // Буфер событий, контроллер сохранит переданную информацию о событии в этот буфер, и она будет равномерно обработана программным обеспечением.

        struct dwc3_event_buffer *ev_buf;              

        struct dwc3_ep		*eps[DWC3_ENDPOINTS_NUM];  // конечная точкаструктура Массив указателей на данные длиной 32

        struct usb_gadget	gadget;  // структура, используемая, когда USB-контроллер находится в режиме устройства данных

        struct usb_gadget_driver *gadget_driver;  // Драйвер, используемый в режиме устройства, определяется конкретным подходящим устройством.

        void __iomem		*regs;    // Зарегистрировать базовый адрес

        size_t			regs_size;    // Длина адреса регистрации

        enum usb_dr_mode	dr_mode;  // Тип перечисления режима USB-контроллера

        u32			fladj;  // frame length adjustment

        u32			irq_gadget;  // Номер прерывания, когда USB находится в режиме устройства

        u32			nr_scratch;  // scratch Количество буферов, не используется

        u32			u1u2;        // only used on revisions <1.83a for workaround

        u32			maximum_speed;  // максимальная скорость

        u32			revision;       // Номер версии в реестре USB-контроллера

        enum dwc3_ep0_next	ep0_next_event;  // hold the next expected event

        enum dwc3_ep0_state	ep0state;        // Статус конечной точки 0

        enum dwc3_link_state	link_state;  // статус ссылки

        u16			isoch_delay;  // wValue from Set Isochronous Delay request

        u16			u2sel;  // parameter from Set SEL request

        u16			u2pel;  // parameter from Set SEL request

        u8			u1sel;  // parameter from Set SEL request

        u8			u1pel;  // parameter from Set SEL request

        u8			speed;  // device speed (super, high, full, low)

        u8			num_out_eps;  // Количество конечных точек вывода

        u8			num_in_eps;   // Введите количество конечных точек

        void			*mem;  // Указывает на начальный адрес памяти структуры. DWC3 имеет требования к выравниванию. Первые байты памяти не могут использоваться.

        struct dwc3_hwparams	hwparams;  // Кэш регистров

        struct dentry		*root;

        struct debugfs_regset32	*regset;

        u8			test_mode;

        u8			test_mode_nr;

        u8			lpm_nyet_threshold;

        u8			hird_threshold;

        u32			grxthrcfg[2];

        u32			gtxthrcfg[2];

    };

Структура struct dwc3 очень сложна, внутри нее встроено множество важных структур данных. Взаимосвязь между ними можно кратко проиллюстрировать на следующем рисунке. xhci указывает на структуру данных, когда USB находится в режиме хоста. Он представлен драйвером в режиме хоста — Platform_driver. Эти два значения совпадают по имени устройства xhci-hcd. Это будет подробно объяснено при анализе драйвера хоста. .

Структуры данных, когда USB находится в режиме устройства, — это usb_gadget и gadget_driver; usb_gadget внутренне содержит структуры данных usb_udc и usb_gadget_ops. usb_gadget_ops — это набор функций работы оборудования контроллера USB, указывающий на dwc3_gadget_ops, который является драйвером конкретного устройства и должен быть указан; Сопоставляется в соответствии с типом устройства. Определяется, устанавливается при успешном сопоставлении устройств. eps[32] — это массив указателей, в котором сохраняются указатели всех структур конечных точек dwc3_ep в режиме устройства. Каждая конечная точка соответствует структуре данных dwc3_ep. Набор рабочих функций конечной точки 0 указывает на dwc3_gadget_ep0_ops, а набор рабочих функций других. конечные точки указывают на dwc3_gadget_ep_ops.

3.2.2. Анализ драйверов

dwc3_rockchip_probe преобразует узел дерева устройств usbdrd_dwc3_0 в Platform_device, а затем сопоставляет его с dwc3_driver. После успешного сопоставления будет выполнена функция dwc3_probe.

Язык кода:javascript
копировать
[drivers/usb/dwc3/core.c]

static const struct of_device_id of_dwc3_match[] = {

    {

        .compatible = "snps,dwc3"

    },

    {

        .compatible = "synopsys,dwc3"

    },

    { },

};

static struct platform_driver dwc3_driver = {

    .probe		= dwc3_probe,

    .remove		= dwc3_remove,

    .driver		= {

        .name	= "dwc3",

        .of_match_table	= of_match_ptr(of_dwc3_match),

        .acpi_match_table = ACPI_PTR(dwc3_acpi_match),

        .pm	= &dwc3_dev_pm_ops,

    },

};

module_platform_driver(dwc3_driver);

dwc3_probe завершает инициализацию контроллера dwc3 USB3.0. Основное содержание следующее:

(1) Выделите структуру данных драйвера dwc3 и выровняйте ее по 16 байтам.

(2) Получение и обработка ресурсов, таких как ресурсы регистра, параметры, максимальная скорость, dr_mode и другие атрибуты.

(3) Выделите согласованный буфер DMA dwc3_event_buffer, DMA передает события контроллера USB в dwc3_event_buffer, а затем обрабатывает ЦП.

(4) Инициализация ядра и инициализация режима USB, подробный анализ позже.

(5) Инициализируйте файл отладки, как показано на рисунке ниже. Пользователи могут получать информацию о USB-контроллере и управлять USB-контроллером в пользовательском пространстве.

Язык кода:javascript
копировать
    dwc3_probe

        mem = devm_kzalloc  // Выделить структуру dwc3 

        dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1)  // Выровнено по 16 байтам

        dwc->mem = mem  // Сохранить выделенный адрес памяти

        // Установите 64-битную маску DMA. Устройство не обязательно сможет выполнять операции DMA для всех адресов памяти. В этом случае ее следует установить.

        // Маска адреса DMA, dma_mask — это диапазон, к которому может обращаться DMA устройства, а coherent_dma_mask используется для маски DMA сопоставления согласованности.

        dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))

        platform_get_resource  // Получить ресурсы с адресом регистрации

        devm_ioremap_resource  // Сопоставить адреса регистров, но не включать регистры xHCI, регистры xHCI обрабатываются его драйвером.

        lpm_nyet_threshold = 0xff /* default to highest possible threshold */

        tx_de_emphasis = 1  /* default to -3.5dB de-emphasis */

        /* default to assert utmi_sleep_n and use maximum allowed HIRD

	       threshold value of 0b1100 */

        hird_threshold = 12

        usb_get_maximum_speed  // Получите максимальную скорость

        usb_get_dr_mode        // Получить dr_mode

        ......                 // Чтобы получить некоторые свойства dwc3, обратитесь к узлу дерева устройств и документу dwc3.txt.

        // Если максимальная_скорость равна USB_SPEED_UNKNOWN, установите значение USB_SPEED_SUPER.

        dwc->maximum_speed = USB_SPEED_SUPER;

        platform_set_drvdata  // Установите личные данные Platform_device

        dwc3_cache_hwparams   // Прочитайте параметры, сохраненные во внутреннем регистре контроллера dwc3, и сохраните их в hwparams dwc3.

        dwc3_core_get_phy     // Получить dwc3 USB-контроллер фи

        dwc3_alloc_event_buffers  // Выделить буфер событий длиной DWC3_EVENT_BUFFERS_SIZE=4096.

            dwc3_alloc_one_event_buffer

                devm_kzalloc  // Сначала выделите структуру dwc3_event_buffer, которая управляет буфером событий.

                evt->dwc = dwc        // Сохранить указатель структуры dwc3

                evt->length	= length  // Сохранить длину буфера

                // Выделить согласованный буфер DMA,buf сохраняет виртуальный адрес,&evt->dmaСохранить физический адрес

                evt->buf = dma_alloc_coherent(dwc->dev, length, &evt->dma, GFP_KERNEL)

        dwc3_alloc_scratch_buffers  // Выделить рабочий буфер, не используемый

            dwc->scratchbuf = kmalloc_array  // Назначить номер nr_scratch * Память DWC3_SCRATCHBUF_SIZE

        dwc3_core_init  // Инициализация ядра

        dwc3_core_init_mode  // В соответствии с режимом, соответствующим инициализации dr_mode, существуют режимы устройства, хоста и otg.

        dwc3_debugfs_init    // Инициализация, связанная с атрибутом отладки dwc3

            debugfs_create_dir  // Создайте каталог отладки/sys/kernel/debug/fe800000.dwc3(fe900000.dwc3)

            kzalloc  // Выделить структуру debugfs_regset32

            dwc->regset->regs = dwc3_regs  // Сохраните регистры, которые необходимо сбросить.

            debugfs_create_regset32("regdump", ...)  // Создайте файл отладки, который может выгружать значения регистров.

            // Чтобы создать файл отладки, способный переключать режимы, необходимо включить опцию CONFIG_USB_DWC3_DUAL_ROLE.

            debugfs_create_file("mode", ...., &dwc3_mode_fops)



            // Чтобы создать файл отладки в режиме отладки, необходимо включить опцию CONFIG_USB_DWC3_DUAL_ROLE или CONFIG_USB_DWC3_GADGET.

            debugfs_create_file("testmode", ..., &dwc3_testmode_fops)

            // Чтобы создать файл отладки link_state, вам необходимо включить опцию CONFIG_USB_DWC3_DUAL_ROLE или CONFIG_USB_DWC3_GADGET.

            debugfs_create_file("link_state", ..., &dwc3_link_state_fops)

            // Чтобы создать файл отладки конечной точки, вам необходимо включить опцию CONFIG_USB_DWC3_DUAL_ROLE или CONFIG_USB_DWC3_GADGET.

            dwc3_debugfs_create_endpoint_dirs(dwc, root)

                dwc3_debugfs_create_endpoint_dir  // Цикл для создания файлов отладки входной конечной точки

                    debugfs_create_dir  // Создать каталог

                    dwc3_debugfs_create_endpoint_files  // Создать файл

                dwc3_debugfs_create_endpoint_dir  // Цикл для создания файлов отладки конечной точки вывода.

                    debugfs_create_dir  // Создать каталог

                    dwc3_debugfs_create_endpoint_files  // Создать файл

Основная задача dwc3_core_init — инициализация оборудования USB-контроллера. Основной процесс выглядит следующим образом:

(1) Получите версию IP-адреса USB-контроллера для облегчения последующей настройки. Между различными IP-версиями USB-контроллера существуют различия. Запишите номер версии ядра Linux в реестр USB-контроллера, чтобы обнаружить ошибки в определенных версиях.

(2) В соответствии с dr_mode выберите, нужно ли сбрасывать USB-контроллер.

(3) Получите количество конечных точек USB-контроллера из кэша регистров USB-контроллера. Конечные точки здесь представляют собой набор ресурсов.

(4) Создайте Scratch_buffers и используйте потоковое сопоставление DMA. USB-контроллер RK3399 не использует эту функцию.

Язык кода:javascript
копировать
    dwc3_core_init        dwc3_readl(dwc->regs, DWC3_GSNPSID)  // GetGlobal SNPS ID Содержание в реестре        /* Write Linux Version Code to our GUID register so it's easy to figure           out which kernel version a bug was found. */        dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE)        dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE)        dwc3_soft_reset  // Программный сброс USB-контроллера            // Контроллер USB будет сброшен только в том случае, если он находится в режиме устройства, режиме хоста или dr_mode — это режим OTG.            // И реестр не сбрасывается при настройке в режиме хоста и будет сброшен последующими драйверами.            dwc3_readl(dwc->regs, DWC3_GCTL)  // Чтение глобального управляющего регистра USB            timeout = jiffies + msecs_to_jiffies(500)  // Установите тайм-аут ожидания сброса на 500 миллисекунд.            dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST)  // Программный сброс, бит очищается аппаратно, если сброс успешен.            // Прочитайте в цикле регистр DWC3_DCTL, чтобы определить, успешен ли сброс.            dwc3_readl(dwc->regs, DWC3_DCTL)            time_after(jiffies, timeout)  // Определить, истек ли период тайм-аута            cpu_relax()  // барьер памяти asm volatile("yield" ::: "memory")                // yield:Указывает текущее выполнениеиз Темы не имеют значения,можно отключить,memory:барьер памяти                asm volatile("yield" ::: "memory")  // aarch64            dwc3_core_soft_reset  // ИнициализироватьPHY            dwc3_phy_setup  // Configure USB PHY Interface of DWC3 Core            dwc3_core_num_eps  // Получить количество конечных точек                dwc->num_in_eps = DWC3_NUM_IN_EPS(parms)  // Введите количество конечных точек                dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps  // Количество конечных точек вывода            dwc3_setup_scratch_buffers  // не используется                // При потоковом сопоставлении DMA данные могут перемещаться в обоих направлениях, то есть могут передаваться на устройство и обратно, при этом возвращается физический адрес.                scratch_addr = dma_map_single(..., DMA_BIDIRECTIONAL);                dwc->scratch_addr = scratch_addr  // Сохранить физический адрес                param = lower_32_bits(scratch_addr)  // Получите младшие 32 бита физического адреса.                dwc3_send_gadget_generic_command(..., DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, ...)                    // Запишите младший 32-битный адрес в регистр в качестве параметра команды, который будет использоваться при выполнении команды.                    dwc3_writel(dwc->regs, DWC3_DGCMDPAR, param)                      // Команда записи, DWC3_DGCMD_CMDACT: активировать команду, начать выполнение команды после установки                    // DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO:Set Scratchpad Buffer Array Address Lo                    dwc3_writel(dwc->regs, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT)

Драйвер режима хоста USB-контроллера и драйвер режима устройства представляют собой два набора платформ драйверов и не могут использоваться универсально. Таким образом, при инициализации драйвера dwc3 соответствующий драйвер режима USB будет инициализирован в соответствии с параметром dr_mode, который указан в дереве устройств. Функция dwc3_core_init_mode используется для установки драйвера режима контроллера USB. Основная работа этой функции заключается в следующем:

Язык кода:javascript
копировать
    dwc3_core_init_mode  // Инициализируйте соответствующий драйвер в соответствии с dr_mode.        // dwc->dr_mode == USB_DR_MODE_PERIPHERAL        dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE)  // Переведите USB-контроллер в режим устройства        dwc3_gadget_init  // Инициализировать драйвер устройства        // dwc->dr_mode == USB_DR_MODE_HOST        dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST)  // Установите USB-контроллер в режим хоста        dwc3_host_init  // Инициализировать драйвер хоста        // dwc->dr_mode == USB_DR_MODE_OTG        // Установите USB-контроллер в режим OTG. USB-контроллер в режиме OTG может быть хостом или устройством, а за переключение отвечает extcon.        dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG)        dwc3_host_init    // Инициализировать драйвер хоста        dwc3_gadget_init  // Инициализировать драйвер устройства

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

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose