Commit graph

71 commits

Author SHA1 Message Date
Johann Fischer
76fadf90f7 drivers: udc_dwc2: enable Internal DMA support by default
Remove BUILD_ASSERT for Internal DMA and DCACHE if both are enabled, and
enable Internal DMA support by default.

Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
2024-07-30 18:26:04 +01:00
Tomasz Moń
f0677e5a3b drivers: udc_dwc2: Respect maximum fifo depth
When dynamic fifo sizing is enabled the driver can assign fifo size
lower or equal to the reset value. Software must respect the maximum
sizes because fifo width registers are optimized during synthesis and
the larger values simply get discarded.

Use 16-bit values for FIFO depths because maximum FIFO depth the vendor
can configure the DWC2 otg is 32768.

Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
2024-07-29 14:12:02 +02:00
Johann Fischer
06086ce771 drivers: udc_dwc: remove rwup flag
The driver does not implement host_wakeup, remove rwup capability flag.

Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
2024-06-28 07:21:29 -04:00
Tomasz Moń
e1b95eb6df drivers: udc_dwc2: Initial Buffer DMA support
Implement absolute minimum necessary to get Buffer DMA working. Require
Data Cache to be disabled if DWC2 OTG has DMA enabled because the stack
does not currently guarantee cache line alignment for allocated buffers.

Set EPENA bit before disabling IN endpoints because it seems to be
necessary in Buffer DMA mode (without EPENA the wait for INEPNAKEFF does
time out). Setting EPENA should have no impact on Completer mode
operation (where EPENA is not necessary for INEPNAKEFF to trigger).

Programming Guide recommends programming SUPCnt to 3, but the only
advantage would be to be able to tell how many back-to-back SETUP packets
were received if there was no more than 3 back-to-back SETUPs. This
information doesn't seem to be useful. The disadvantage is that the
buffer needed for receiving SETUP packet must be able to hold SUPCnt
multiple of 8 bytes. Use SUPCnt 1 so the 8 bytes buffer is enough.

Make sure to clear StsPhseRcvd interrupt bit in Buffer DMA mode because
the DMA seems to prevent the SETUP Phase Done interrupt from triggering
if StsPhseRcvd is set. Clearing this bit doesn't seem to be necessary in
Completer mode. This bit is set on control transfers with data stage
from host to device.

Both Buffer DMA and Completer mode operation on nRF54H20DK was verified
using USB2CV Chapter 9 Tests and MSC Tests with Mass Storage sample.

Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
2024-06-15 07:43:45 -04:00
Tomasz Moń
59702c7633 drivers: udc_dwc2: Avoid unnecessary register accesses
Do not use sys_clear_bits() followed by sys_set_bits() on DCTL register
to avoid writing to DCTL register twice - first with zeroed out address,
and then with the new address. Change the code to write the address in
one DCTL register write.

Do not use sys_set_bits() to set test mode, but rather prepare the
correct value first.

Set DCFG and GUSBCFG registers in one go. There is no point in reading
back the value or doing multiple subsequent writes to these registers.

Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
2024-06-15 07:43:45 -04:00
Tomasz Moń
fb27c36ad5 drivers: udc_dwc2: Fix control OUT buffer leak
Release buffer allocated in dwc2_ctrl_feed_dout() on endpoint deactivate
to prevent the buffer from leaking on USB stack disable.

Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
2024-06-12 12:48:45 -04:00
Tomasz Moń
fa0a6e2274 drivers: udc_dwc2: Allocate at least 8 bytes for control OUT
Make sure to feed control OUT endpoint with at least 8 bytes buffer to
make it possible to always receive SETUP data. This solves the assertion
failure in net_buf_add() called inside dwc2_handle_evt_setup() when a
host decides to start new control transfer immediately after it has
issued control transfer with Data Stage from host to device with wLength
less than 8.

Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
2024-06-12 14:21:37 +03:00
Tomasz Moń
e2afcafca5 drivers: udc_dwc2: Abort wait when PHY is not clocked
On nRF54H20DK the USB PHY is powered from VBUS. When the USB cable is
not connected, the PHY is not powered and the PHY clock disappears.

Because the GOUTNAKEFF and INEPNAKEFF can only ever be set when PHY
clock is active, the waits for these bits do timeout if cable is
disconnected. Workaround the issue by aborting the wait if vendor quirk
indicates that PHY clock has abruptly vanished.

Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
2024-06-06 07:53:17 -04:00
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