Commit graph

13 commits

Author SHA1 Message Date
Tomasz Moń 2368623f32 drivers: udc_dwc2: Avoid IN endpoint dequeue race
Flushing TxFIFO is racing with actual use of the TxFIFO. The software
controls only one side of the race (flush trigger) while the host
controls the other side. Therefore, locking interrupts before flushing
TxFIFO is not protecting against the race condition.

Disable the endpoint on dequeue to make sure that TxFIFO flushing won't
conflict with host actions (because the endpoint would be forced to NAK
the IN tokens before the TxFIFO is flushed).

Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
2024-05-29 12:00:08 +02:00
Tomasz Moń 4db14f83e5 drivers: udc_dwc2: Fix timeouts when disabling endpoints
Do not set NAK bit again for endpoints that already have NAK bit set.
Do not wait for OUT endpoint 0 disable because it cannot be disabled by
application (DOEPCTL0 EPDis bit is Read-Only).

Disable endpoints before disabling interrupts because it is necessary to
handle RXFLVL interrupt (in Slave mode) for GOUTNAKEFF to become active.

Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
2024-05-29 12:00:08 +02:00
Tomasz Moń f4e95ccd48 drivers: udc_dwc2: Properly revive STALLed endpoints
DWC2 documentation unfortunately assigns somewhat confusing semantics to
endpoint "enable"/"disable" and "activate"/"deactivate". The Zephyr USB
device stack endpoint enable/disable refers to DWC2 activate/deactivate.
The DWC2 endpoint enable/disable actions can be loosely referred to
Zephyr USB stack enqueue/dequeue.

Rename the functions and rework internal working to match DWC2
Programming Guide. This makes endpoint halt work as expected by the
stack and therefore fixes all classes that rely on correct STALL
handling. Most notable STALL user is the Mass Storage class.

Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
2024-05-18 13:24:26 +02:00
Tomasz Moń 00e2b86708 drivers: udc_dwc2: Process SETUP stage when allowed
DWC2 programming guide mentions that SETUP can only be processed by
application after DOEPINTn.SETUP interrupt. Not respecting this
requirement makes setting Global OUT NAK hang while waiting for
GOUTNAKEFF interrupt until the host starts next control transfer.
Global OUT NAK is necessary if the application ever wants to properly
cancel any ongoing transfer.

Change the processing to comply with the programming guide.

Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
2024-05-18 13:24:26 +02:00
Johann Fischer acd2fa7972 drivers: udc_dwc2: fix interpretation of NUMDEVEPS and INEPS fields
The NUMDEVEPS field provides the number of endpoints in addition to the
control endpoint. It is used to iterate over GHWCFG1 register value to
get correct number of configured IN/OUT endpoints. To get it correctly,
we need to use it internally as number including control endpoint.

Interpretation of INEPS misses +1 because value 0 means 1 IN endpoint
and so on.

Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
2024-05-17 14:05:08 +01:00
Johann Fischer 6d06a8cea9 drivers: udc_dwc2: use devicetree to configure endpoint capabilities
Although we can get the number of configured OUT and IN endpoints and
endpoint capabilities from the DWC GHWCFGn registers, we need to
configure the number of endpoint configuration structs at build time. On
some platforms, we cannot access the hardware register at pre-init, so
we use the GHWCFGn values from the devicetree to provide endpoint
capabilities. This can be considered a workaround, and we may change the
upper layer internals to avoid it in the future.

Also, add a new vendor quirk to fill in platform-specific controller
capabilities.

Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
2024-05-17 14:05:08 +01:00
Johann Fischer efb286dfdf drivers: udc_dwc2: rework vendor quirks
Rework and rename vendor quirks to better reflect where they intended to
be called. Number of quirks probably not final and will be trimmed
later.

Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
2024-05-17 14:05:08 +01:00
Johann Fischer 67cdccc1c2 drivers: udc_dwc2: rework controller initialization
Move most of the controller initialization to a separate function called
during udc_enable(). This allows us to add support for the platform
where the device controller is only available when VBUS is present and
the PHY is powered.

Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
2024-05-17 14:05:08 +01:00
Tomasz Moń 3a8c9b8ac3 drivers: udc_dwc2: Fix debug logging bus fault
Pass DIEPTXF address instead of value to sys_read32() to prevent bus
fault when debug logging is enabled.

Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
2024-05-15 12:28:08 +02:00
Tomasz Moń 25229b2fce drivers: udc_dwc2: Submit reset after chirp sequence
DWC USB 2.0 HS OTG Controller sets USB Reset interrupt after Reset
signalling starts, but before the High-Speed Detection Handshake. This
allows software to perform most of the reset handling even before the
connection speed is known. The device controller indicates High-Speed
Detection Handshake result is available in DSTS register by setting
Enumeration Done interrupt.

USB stack expects that the connection speed is known immediately after
UDC_EVT_RESET is submitted. Due to this expectation, it is important to
submit UDC_EVT_RESET only after Enumeration Done interrupt to prevent
the USB stack from reading (and storing) actual device speed before
it is known.

Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
2024-05-14 12:16:06 +01:00
Johann Fischer b501278237 drivers: udc_dwc2: handle interrupt IEPINT before the RXFLVL
During a control read transfer host is able to start status stage as
soon as it receives last data packet. The time between last data packet
and status stage can be approximately 1 us at High-Speed and 8 us at
Full-Speed (exact timing depends on host but it is mostly constrained by
bus turnaround time).

With sufficient interrupt latency it is therefore possible that both
IEPINT (raised at end of Data Stage) and RXFLVL (raised at Status Stage)
would be set when dwc2 interrupt handler reads GINTSTS register. When
device is operating at High-Speed, the latency introduced by UART logger
backend is enough to trigger this condition. If the RXFLVL is handled
before IEPINT the stack will trigger "Cannot determine the next stage"
error.

Handle IEPINT before RXFLVL to make the handler immune to increased
interrupt latencies.

Co-authored-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
2024-05-13 11:46:39 +01:00
Johann Fischer 13022ceab7 drivers: udc_dwc2: enable SOF interrupts and SOF events
Enable SOF interrupts and SOF events.

Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
2024-03-22 10:10:26 +01:00
Johann Fischer cc2fdf2053 drivers: udc: add initial support for DWC2 controller
The driver currently supports only dedicated FIFO mode (with
dynfifosizing if enabled). Control, bulk and interrupt transfers are
supported, isochronous transfers are not yet supported. The driver
accesses controller registers using sys_io.h, but for debugging purposes
one can get a register map from the driver's config, similar to the
usb_dc_dw.c driver.

Initial support also has vendor quirks for the STM32F4 SoC family.
Tested on NUCLEO-F413HG.

Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
2023-12-18 09:48:58 +01:00