-
Notifications
You must be signed in to change notification settings - Fork 154
Tegra manual contains all info on how usb works on TegraX1: https://developer.nvidia.com/embedded/downloads#?search=TRM (behind nvidia developer program wall) USB Chapter is Chapter 22 (starting page 1321)
There are two mutually exclusive controllers in the tegra.
One is usb2 only (ehci), supports otg on the main port. This is what is used by boot rom, coreboot and uboot to do the usb stuff.
The main one codenamed xusb supports the xhci protocol, but requires much more complicated sw stack. This is probably why they kept the ehci IP.
There are two options to supports usb device mode on switch:
- Enable otg mode on xhci.
- ENable ehci driver on linux (and disable xhci)
Linux supports only the xusb driver via xhci-tegra.c pinctrl-tegra-xusb.c pinctrl-tegra210.c xusb-tegra210.c and xusb.c
device tree for xusb is: usb@70090000
xhci-tegra is developed by chromos guys. It does not support device mode as per initial commit:
https://github.com/abrestic/linux/commit/a483045bec842de7a2e8fecf7c0474074447aa31
Add support for the on-chip xHCI host controller present on Tegra SoCs.
The controller requires external firmware which must be loaded before
using the controller. This driver loads the firmware, starts the
controller, and is able to service host-specific messages sent by
the controller's firmware.
The controller also supports USB device mode as well as powergating
of the SuperSpeed and host-controller logic when not in use, but
support for these is not yet implemented.
otg aka udc is supported by nvidia BSP aka L4T as xudc.c, but requires a lot of infrastructure from L4T, which is hard to port in an upstream like kernel.
ChromeOS guys did it for the Pixel C (aka smaug, aka ryu), but the last kernel supported by ChromeOS is 3.18.
So we have the choice of porting xudc.c either from L4T or from chromeOS.
device tree for ehci is: usb@7d000000
usb@7d000000 {
status = "okay";
};
phy1: usb-phy@7d000000 {
status = "okay";
vbus-supply = <&usb2_vbus>;
};
and add the usb regulator (as per uboot own device tree)
usb2_vbus: regulator@6 {
compatible = "regulator-fixed";
reg = <6>;
regulator-name = "USB2_VBUS";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio TEGRA_GPIO(CC, 4) GPIO_ACTIVE_HIGH>;
enable-active-high;
};
Then, you can configure the mux to use ehci instead of xhci:
lanes {
usb2-0 {
nvidia,function = "snps"; // for ehci
// nvidia,function = "xusb"; // for xhci
status = "okay";
};
};
tegra210.dsi says:
usb@7d000000 {
compatible = "nvidia,tegra210-ehci", "nvidia,tegra30-ehci", "usb-ehci";
}
which taken by:
usb/host/ehci-tegra.c: { .compatible = "nvidia,tegra30-ehci", .data = &tegra30_soc_config },
No driver upstream claims support of tegra210-usb variants.
The phy is claimed by
usb/phy/phy-tegra-usb.c: { .compatible = "nvidia,tegra30-usb-phy", .data = &tegra30_soc_config },
But this driver harcodes registers that are different from what is in the spec, and the tegra_freq_table do not contain the mapping for 38400000 main cristal (aka OSC or pll_ref).
uboot contains those mapping, which are coherent with what is described in the spec.
// <uboot>/drivers/usb/host/ehci-tegra.c
/* NOTE: 13/26MHz settings are N/A for T210, so dupe 12MHz settings for now */
static const unsigned T210_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = {
/* DivN, DivM, DivP, KCP, KVCO, Delays Debounce, Bias */
{ 0x028, 0x01, 0x01, 0x0, 0, 0x02, 0x2F, 0x08, 0x76, 32500, 5 },
{ 0x019, 0x01, 0x01, 0x0, 0, 0x03, 0x4B, 0x0C, 0xBB, 48000, 8 },
{ 0x028, 0x01, 0x01, 0x0, 0, 0x02, 0x2F, 0x08, 0x76, 30000, 5 },
{ 0x028, 0x01, 0x01, 0x0, 0, 0x02, 0x2F, 0x08, 0x76, 65000, 5 },
{ 0x019, 0x02, 0x01, 0x0, 0, 0x05, 0x96, 0x18, 0x177, 96000, 15 },
{ 0x028, 0x04, 0x01, 0x0, 0, 0x04, 0x66, 0x09, 0xFE, 120000, 20 }
};
which maps in linux to:
{
.freq = 38400000,
.enable_delay = 0x05,
.stable_count = 0x96,
.active_delay = 0x18,
.xtal_freq_count = 0x177,
.debounce = 0x17700,
},
the DivN, DivM, DivP table is in linux in clk-tegra210.c:
static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
{ 38400000, 480000000, 25, 2, 0, 0 },
}
note that the p values are different in uboot and in linux.
The previous modifications successfully enable ehci driver for linux, but ehci is host only, we still need the udc driver in order to enable otg. The udc driver was available in L4T, and also visible in early bring-up linux of smaug kernels, but it was later abandoned in favor of xudc.c. The udc driver has been removed from L4T in ebfc015edbe
attempt has been made to enable the tegra_udc driver from chromium in our tree. It is not yet fully working (the host recognise the configured gadget, but communications get stucked for some reason).
u-boot supports both host and device modes via ehci-tegra.c
As per teardown by techinsinde, the Type C connector is connected through a Pericom PI3USB30532. This passive mux chip handles the switch between full usb3 mode and display port (DP). Configuring this chip is one key to enabling docking station graphics.
This chip is supported by 4.17 driver which is in our the 4.17 rebase tree.
Power delivery is managed by chip BM92T36m which sits on i2c 0x18, and has the marking M92T36
This repo may have useful info.
The switch firmware (obviously) has code to interact with the chip, but so does the dock firmware (it has 2 other rohm chips). The overall design is actually quite similar to the rohm evaluation kit design.
dhewg has an usb dump of the comm to that chip:
~/ i2cdump -y 0 0x18
No size specified (using byte-data access)
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 00 00 00 80 00 00 e0 a2 00 00 00 00 00 00 00 00 ...?..??........
10: 00 00 00 00 00 00 00 00 00 00 72 00 00 00 00 00 ..........r.....
20: 04 90 12 04 00 00 49 44 04 90 00 04 00 00 ff 06 ????..ID??.?...?
30: 00 00 00 0c 90 36 b0 00 90 92 00 00 04 90 22 00 ...??6?.??..??".
40: 00 00 00 00 00 00 00 00 00 00 00 03 7c b5 b0 01 ...........?|???
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
70: 00 00 00 00 00 00 00 00 00 80 f4 01 40 00 8f 00 .........???@.?.
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
By default linux setup charge at 500mA. In order to let it charge faster, you can do
echo 1500000 > /sys/class/power_supply/bq24190-charger/input_current_limit
and make sure that works in
cat /sys/class/power_supply/max170xx_battery/current_now
to prevent battery consumption, you can also shutdown the screen
echo 1 >/sys/class/backlight/backlight/brightness
echo 1 >/sys/class/graphics/fb0/blank
how to setup gadget using sysfs: https://events.static.linuxfound.org/sites/events/files/slides/USB%20Gadget%20Configfs%20API_0.pdf