LAN969x USB
1. LAN969x USB
1.1. SoC Resources
LAN969x SoC supports one instance of the Dual Role SuperSpeed DesignWare USB3 controller.
The current implementation supports only the host mode part of dual role |
1.2. Kernel configurations
Following kernel config options should be enabled to use LAN969x USB in host mode:
-
CONFIG_USB_DWC3
- DesignWare USB Controller support -
CONFIG_USB_DWC3_ULPI
- Using an ULPI type PHY on the USB controller -
Atmel High-Speed USB device controller DT Documentation dwc3-of-simple
1.3. Devicetree Configuration
To enable LAN969x USB, following configurations are required in device tree:
-
compatible
string must be set to"microchip,lan966x-dwc3"
-
clocks
property must be set to<&clks GCK_GATE_USB_DRD>
-
#address-cells
must be set to 1. -
#size-cells
must be set to 1. -
ranges
property must be present (this is an empty address translation) -
This node must have a child node that specifies the glue for the DWC3 controller:
-
compatible
string must be set to ="snps,dwc3"
. -
reg
property must be set to<0x300000 0x80000>
. -
interrupts
must be set to<GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>
Peripheral Shared Peripheral Interrupt CPU INTR USB Host
112
80
-
dr_mode
property must be set to"host"
. -
clocks
property must be set to<&clks GCK_ID_USB_REFCLK>
. -
clock-names
property must be set to"ref"
. -
assigned-clocks
property must be set to<&clks GCK_ID_USB_REFCLK>
. -
assigned-clock-rates
property must be set to 60Mhz. -
maximum-speed
property must be set to"full-speed"
. -
phy-names
property must be set to"usb2-phy"
and"usb3-phy"
-
1.3.2. Example
Following example shows how the LAN969x USB controller should be defined in DT:
dtsi file:
usb0: usb@300000 { compatible = "microchip,lan966x-dwc3"; clocks = <&clks GCK_GATE_USB_DRD>; #address-cells = <1>; #size-cells = <1>; ranges; status = "disabled"; usb0_dwc3: usb_dwc3@300000 { compatible = "snps,dwc3"; reg = <0x300000 0x80000>; interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>; dr_mode = "host"; clocks = <&clks GCK_ID_USB_REFCLK>; clock-names = "ref"; assigned-clocks = <&clks GCK_ID_USB_REFCLK>; assigned-clock-rates = <60000000>; maximum-speed = "full-speed"; phy-names = "usb2-phy", "usb3-phy"; status = "okay"; }; };
dts file changes:
&gpio { usb_ulpi_pins: usb-ulpi-pins { pins = "GPIO_30", "GPIO_31", "GPIO_32", "GPIO_33", "GPIO_34", "GPIO_35", "GPIO_36", "GPIO_37", "GPIO_38", "GPIO_39", "GPIO_40", "GPIO_41"; function = "usb_ulpi"; }; usb_rst_pins: usb-rst-pins { pins = "GPIO_12"; function = "usb2phy_rst"; }; usb_over_pins: usb-over-pins { pins = "GPIO_13"; function = "usb_over_detect"; }; usb_power_pins: usb-power-pins { pins = "GPIO_1"; function = "usb_power"; }; }; &usb0 { status = "okay"; pinctrl-0 = <&usb_ulpi_pins>, <&usb_rst_pins>, <&usb_over_pins>, <&usb_power_pins>; pinctrl-names = "default"; };
1.4. UserSpace
You can verify that the driver is available by checking its mode
setting is
host
, like this:
# cat /sys/kernel/debug/usb/300000.usb_dwc3/mode host
1.4.1. Mounting a USB Memory Stick
Prepare a USB Memory Stick with the following properties on a Linux Desktop:
-
Make a GTP partition table
-
Add one primary partition using the EXT4 filesystem that uses the total USB Memory Stick space.
-
Format the partition with the ext4 formatter
-
Mount the partition on an empty folder
-
Copy a wellknown file to the mounted folder
-
Sync and unmount the folder
Now insert the memory stick in the USB vertical USB port on the EVB-LAN9696-24port and check the logs:
# [ 382.641801] usb 1-1: new high-speed USB device number 2 using xhci-hcd [ 382.790319] usb 1-1: New USB device found, idVendor=0781, idProduct=5406, bcdDevice= 2.00 [ 382.795753] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [ 382.803050] usb 1-1: Product: U3 Cruzer Micro [ 382.807278] usb 1-1: Manufacturer: SanDisk [ 382.811348] usb 1-1: SerialNumber: 194253029D50FD3B [ 382.817444] usb-storage 1-1:1.0: USB Mass Storage device detected [ 382.822855] scsi host0: usb-storage 1-1:1.0 [ 383.842201] scsi 0:0:0:0: Direct-Access SanDisk Cruzer 8.02 PQ: 0 ANSI: 0 CCS [ 383.848550] sd 0:0:0:0: [sda] Media removed, stopped polling [ 383.854874] sd 0:0:0:0: [sda] Attached SCSI removable disk # ls /dev/sda* /dev/sda
The log announces a new sda
block device which is visible in the /dev
folder, but what about the partition that we created?
Here you need to probe the new device for partition information:
# partprobe /dev/sda [ 405.656881] sd 0:0:0:0: [sda] 15704063 512-byte logical blocks: (8.04 gb/7.49 gib) [ 405.662434] sda: detected capacity change from 0 to 15704063 [ 405.693476] sda: sda1 [ 405.720651] sda: sda1
Partprobe informs the kernel about the partitions on device sda
which in turn
causes the kernel to create a new sda1
block device that represents the first
(and only) partition on sda
.
On Desktop Linux systems it is common to run the udev daemon that takes
care of retrieving partition information and spawn process that will mount these
partitions with specific user rights, but udev and its helpers are not always
available on embedded systems.
|
Now you can mount the sda1
partition to access the file that was stored
there:
# mount /dev/sda1 /mnt/ [ 421.617746] EXT4-fs (sda1): mounted filesystem with ordered data mode. Quota mode: disabled. # ls -l /mnt/ total 28K drwxr-xr-x 3 root root 4.0K Dec 12 2023 . drwxr-xr-x 19 1001 1001 4.0K Sep 28 2023 .. drwx------ 2 root root 16.0K Dec 12 2023 lost+found -rw-r--r-- 1 root root 1.4K Dec 12 2023 main.rs # cat /mnt/main.rs use std::fs::File; use std::io::Read; ... file listing continues... #
You can now read and write to the folder as you please, and the changes will be stored in the first partition of the USB Memory Stick.
Remember to sync and unmount the device before unplugging it.
# sync # umount /mnt/ [ 897.689004] EXT4-fs (sda1): unmounting filesystem. #