svn commit: r332010 - in stable/11/sys: arm/conf arm/nvidia arm/nvidia/drm2 arm/nvidia/tegra124 boot/fdt/dts/arm contrib/dev/nvidia gnu/dts/arm gnu/dts/include/dt-bindings/clock gnu/dts/include/dt-...
Michal Meloun
mmel at FreeBSD.org
Wed Apr 4 11:30:21 UTC 2018
Author: mmel
Date: Wed Apr 4 11:30:20 2018
New Revision: 332010
URL: https://svnweb.freebsd.org/changeset/base/332010
Log:
MFC (cherry pick)r306197,r306327,r306328,r308390,r308391,r310600,r314703:
cherry pick from r306197:
Nvidia Tegra 124 and Jetson TK1 related DTS.
r306327:
Update AHCI driver to match new dts tree
r306328:
Update PCI driver to match new dts tree
r308390:
Rework NVIDIA Tegra124 XUSBPAD driver.
- Adapt it for new, incompatible, DT bindings introduced by r306197. -
Add support for USB super speed pads/ports.
r308391:
Add NVIDIA Tegra XHCI driver and coresponding firmware blob.
r310600:
Implement drivers for NVIDIA tegra124 display controller, HDMI source and
host1x module. Unfortunately, tegra124 SoC doesn't have 2D acceleration
engine and 3D requires not yet started nouveau driver.
r314703:
Add support for card detect and write protect gpio pins to Tegra SDHCI.
Added:
stable/11/sys/arm/nvidia/drm2/
- copied from r310600, head/sys/arm/nvidia/drm2/
stable/11/sys/arm/nvidia/tegra_xhci.c
- copied unchanged from r308391, head/sys/arm/nvidia/tegra_xhci.c
stable/11/sys/contrib/dev/nvidia/
- copied from r308391, head/sys/contrib/dev/nvidia/
Modified:
stable/11/sys/arm/conf/TEGRA124
stable/11/sys/arm/nvidia/tegra124/files.tegra124
stable/11/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c
stable/11/sys/arm/nvidia/tegra_ahci.c
stable/11/sys/arm/nvidia/tegra_pcie.c
stable/11/sys/arm/nvidia/tegra_sdhci.c
stable/11/sys/boot/fdt/dts/arm/tegra124-jetson-tk1-fbsd.dts
stable/11/sys/gnu/dts/arm/tegra124-jetson-tk1-emc.dtsi (contents, props changed)
stable/11/sys/gnu/dts/arm/tegra124-jetson-tk1.dts
stable/11/sys/gnu/dts/arm/tegra124.dtsi
stable/11/sys/gnu/dts/include/dt-bindings/clock/tegra124-car-common.h
stable/11/sys/gnu/dts/include/dt-bindings/clock/tegra124-car.h
stable/11/sys/gnu/dts/include/dt-bindings/gpio/tegra-gpio.h
stable/11/sys/gnu/dts/include/dt-bindings/memory/tegra124-mc.h
stable/11/sys/gnu/dts/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
stable/11/sys/gnu/dts/include/dt-bindings/reset/tegra124-car.h (contents, props changed)
stable/11/sys/gnu/dts/include/dt-bindings/thermal/tegra124-soctherm.h
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/arm/conf/TEGRA124
==============================================================================
--- stable/11/sys/arm/conf/TEGRA124 Wed Apr 4 11:14:27 2018 (r332009)
+++ stable/11/sys/arm/conf/TEGRA124 Wed Apr 4 11:30:20 2018 (r332010)
@@ -50,7 +50,7 @@ device vlan # 802.1Q VLAN support
#device tun # Packet tunnel.
device md # Memory "disks"
#device gif # IPv6 and IPv4 tunneling
-#device firmware # firmware assist module
+device firmware # firmware assist module
device ether # Ethernet support
device miibus # Required for ethernet
device bpf # Berkeley packet filter (required for DHCP)
@@ -86,6 +86,8 @@ device pass # Passthrough device (direct ATA/SCSI a
# USB support
options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
device ehci # EHCI USB interface
+device xhci # XHCI USB interface
+device tegra124_xusb_fw # Tegra XUSB firmware
device usb # USB Bus (required)
device umass # Disks/Mass storage - Requires scbus and da
device uhid # "Human Interface Devices"
@@ -121,11 +123,10 @@ device pci
device re # RealTek 8139C+/8169/8169S/8110S
# DRM2
-#device fbd
-#device vt
-#device splash
-#device kbdmux
-#device drm2
+device fbd
+device vt
+device kbdmux
+device drm2
# Sound
#device sound
Modified: stable/11/sys/arm/nvidia/tegra124/files.tegra124
==============================================================================
--- stable/11/sys/arm/nvidia/tegra124/files.tegra124 Wed Apr 4 11:14:27 2018 (r332009)
+++ stable/11/sys/arm/nvidia/tegra124/files.tegra124 Wed Apr 4 11:30:20 2018 (r332010)
@@ -24,6 +24,7 @@ arm/nvidia/tegra_uart.c optional uart
arm/nvidia/tegra_sdhci.c optional sdhci
arm/nvidia/tegra_gpio.c optional gpio
arm/nvidia/tegra_ehci.c optional ehci
+arm/nvidia/tegra_xhci.c optional xhci
arm/nvidia/tegra_ahci.c optional ahci
arm/nvidia/tegra_pcie.c optional pci
arm/nvidia/tegra_i2c.c optional iic
@@ -35,21 +36,35 @@ arm/nvidia/tegra_soctherm.c standard
arm/nvidia/tegra_lic.c standard
arm/nvidia/tegra_mc.c standard
#arm/nvidia/tegra_hda.c optional snd_hda
-#arm/nvidia/drm2/hdmi.c optional drm2
-#arm/nvidia/drm2/tegra_drm_if.m optional drm2
-#arm/nvidia/drm2/tegra_drm_subr.c optional drm2
-#arm/nvidia/drm2/tegra_host1x.c optional drm2
-#arm/nvidia/drm2/tegra_hdmi.c optional drm2
-#arm/nvidia/drm2/tegra_dc_if.m optional drm2
-#arm/nvidia/drm2/tegra_dc.c optional drm2
-#arm/nvidia/drm2/tegra_fb.c optional drm2
-#arm/nvidia/drm2/tegra_bo.c optional drm2
+arm/nvidia/drm2/hdmi.c optional drm2
+arm/nvidia/drm2/tegra_drm_if.m optional drm2
+arm/nvidia/drm2/tegra_drm_subr.c optional drm2
+arm/nvidia/drm2/tegra_host1x.c optional drm2
+arm/nvidia/drm2/tegra_hdmi.c optional drm2
+arm/nvidia/drm2/tegra_dc_if.m optional drm2
+arm/nvidia/drm2/tegra_dc.c optional drm2
+arm/nvidia/drm2/tegra_fb.c optional drm2
+arm/nvidia/drm2/tegra_bo.c optional drm2
#
-# Optional devices.
+# Firmware
#
-
+tegra124_xusb_fw.c optional tegra124_xusb_fw \
+ dependency "$S/arm/nvidia/tegra124/files.tegra124" \
+ compile-with "${AWK} -f $S/tools/fw_stub.awk tegra124_xusb.fw:tegra124_xusb_fw -mtegra124_xusb_fw -c${.TARGET}" \
+ no-implicit-rule before-depend local \
+ clean "tegra124_xusb_fw.c"
+tegra124_xusb.fwo optional tegra124_xusb_fw \
+ dependency "tegra124_xusb.fw" \
+ compile-with "${NORMAL_FWO}" \
+ no-implicit-rule \
+ clean "tegra124_xusb.fwo"
+tegra124_xusb.fw optional tegra124_xusb_fw \
+ dependency "$S/contrib/dev/nvidia/tegra124_xusb.bin.uu" \
+ compile-with "${NORMAL_FW}" \
+ no-obj no-implicit-rule \
+ clean "tegra124_xusb.fw"
#
-# Temporary/ to be moved stuff
+# Temporary/to be moved stuff
#
arm/nvidia/as3722.c optional iic
arm/nvidia/as3722_regulators.c optional iic
Modified: stable/11/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c
==============================================================================
--- stable/11/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c Wed Apr 4 11:14:27 2018 (r332009)
+++ stable/11/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c Wed Apr 4 11:30:20 2018 (r332010)
@@ -39,26 +39,57 @@
#include <dev/extres/hwreset/hwreset.h>
#include <dev/extres/phy/phy.h>
+#include <dev/extres/regulator/regulator.h>
#include <dev/fdt/fdt_common.h>
#include <dev/fdt/fdt_pinctrl.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <arm/nvidia/tegra_efuse.h>
+
#include <gnu/dts/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
#include "phy_if.h"
+/* FUSE calibration data. */
+#define FUSE_XUSB_CALIB 0x0F0
+#define FUSE_XUSB_CALIB_HS_CURR_LEVEL_123(x) (((x) >> 15) & 0x3F);
+#define FUSE_XUSB_CALIB_HS_IREF_CAP(x) (((x) >> 13) & 0x03);
+#define FUSE_XUSB_CALIB_HS_SQUELCH_LEVEL(x) (((x) >> 11) & 0x03);
+#define FUSE_XUSB_CALIB_HS_TERM_RANGE_ADJ(x) (((x) >> 7) & 0x0F);
+#define FUSE_XUSB_CALIB_HS_CURR_LEVEL_0(x) (((x) >> 0) & 0x3F);
+
+
+/* Registers. */
#define XUSB_PADCTL_USB2_PAD_MUX 0x004
+#define XUSB_PADCTL_USB2_PORT_CAP 0x008
+#define USB2_PORT_CAP_ULPI_PORT_INTERNAL (1 << 25)
+#define USB2_PORT_CAP_ULPI_PORT_CAP (1 << 24)
+#define USB2_PORT_CAP_PORT_REVERSE_ID(p) (1 << (3 + (p) * 4))
+#define USB2_PORT_CAP_PORT_INTERNAL(p) (1 << (2 + (p) * 4))
+#define USB2_PORT_CAP_PORT_CAP(p, x) (((x) & 3) << ((p) * 4))
+#define USB2_PORT_CAP_PORT_CAP_OTG 0x3
+#define USB2_PORT_CAP_PORT_CAP_DEVICE 0x2
+#define USB2_PORT_CAP_PORT_CAP_HOST 0x1
+#define USB2_PORT_CAP_PORT_CAP_DISABLED 0x0
+
+#define XUSB_PADCTL_SS_PORT_MAP 0x014
+#define SS_PORT_MAP_PORT_INTERNAL(p) (1 << (3 + (p) * 4))
+#define SS_PORT_MAP_PORT_MAP(p, x) (((x) & 7) << ((p) * 4))
+
#define XUSB_PADCTL_ELPG_PROGRAM 0x01C
#define ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
#define ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
#define ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
+#define ELPG_PROGRAM_SSP_ELPG_VCORE_DOWN(x) (1 << (18 + (x) * 4))
+#define ELPG_PROGRAM_SSP_ELPG_CLAMP_EN_EARLY(x) (1 << (17 + (x) * 4))
+#define ELPG_PROGRAM_SSP_ELPG_CLAMP_EN(x) (1 << (16 + (x) * 4))
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
#define IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
-#define IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf<< 12)
+#define IOPHY_PLL_P0_CTL1_REFCLK_SEL(x) (((x) & 0xF) << 12)
#define IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
@@ -66,9 +97,60 @@
#define IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
#define IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2(x) (0x058 + (x) * 4)
+#define IOPHY_USB3_PAD_CTL2_CDR_CNTL(x) (((x) & 0x00FF) << 4)
+#define IOPHY_USB3_PAD_CTL2_RX_EQ(x) (((x) & 0xFFFF) << 8)
+#define IOPHY_USB3_PAD_CTL2_RX_WANDER(x) (((x) & 0x000F) << 4)
+#define IOPHY_USB3_PAD_CTL2_RX_TERM_CNTL(x) (((x) & 0x0003) << 2)
+#define IOPHY_USB3_PAD_CTL2_TX_TERM_CNTL(x) (((x) & 0x0003) << 0)
+
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4(x) (0x068 + (x) * 4)
+
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0(x) (0x0A0 + (x) * 4)
+#define USB2_OTG_PAD_CTL0_LSBIAS_SEL (1 << 23)
+#define USB2_OTG_PAD_CTL0_DISCON_DETECT_METHOD (1 << 22)
+#define USB2_OTG_PAD_CTL0_PD_ZI (1 << 21)
+#define USB2_OTG_PAD_CTL0_PD2 (1 << 20)
+#define USB2_OTG_PAD_CTL0_PD (1 << 19)
+#define USB2_OTG_PAD_CTL0_TERM_EN (1 << 18)
+#define USB2_OTG_PAD_CTL0_LS_LS_FSLEW(x) (((x) & 0x03) << 16)
+#define USB2_OTG_PAD_CTL0_LS_RSLEW(x) (((x) & 0x03) << 14)
+#define USB2_OTG_PAD_CTL0_FS_SLEW(x) (((x) & 0x03) << 12)
+#define USB2_OTG_PAD_CTL0_HS_SLEW(x) (((x) & 0x3F) << 6)
+#define USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(x) (((x) & 0x3F) << 0)
+
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1(x) (0x0AC + (x) * 4)
+#define USB2_OTG_PAD_CTL1_RPU_RANGE_ADJ(x) (((x) & 0x3) << 11)
+#define USB2_OTG_PAD_CTL1_HS_IREF_CAP(x) (((x) & 0x3) << 9)
+#define USB2_OTG_PAD_CTL1_SPARE(x) (((x) & 0x3) << 7)
+#define USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ(x) (((x) & 0xF) << 3)
+#define USB2_OTG_PAD_CTL1_PD_DR (1 << 2)
+#define USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP (1 << 1)
+#define USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP (1 << 0)
+
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x0B8
+#define USB2_BIAS_PAD_CTL0_ADJRPU(x) (((x) & 0x7) << 14)
+#define USB2_BIAS_PAD_CTL0_PD_TRK (1 << 13)
+#define USB2_BIAS_PAD_CTL0_PD (1 << 12)
+#define USB2_BIAS_PAD_CTL0_TERM_OFFSETL(x) (((x) & 0x3) << 9)
+#define USB2_BIAS_PAD_CTL0_VBUS_LEVEL(x) (((x) & 0x3) << 7)
+#define USB2_BIAS_PAD_CTL0_HS_CHIRP_LEVEL(x) (((x) & 0x3) << 5)
+#define USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL(x) (((x) & 0x7) << 2)
+#define USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL(x) (((x) & 0x3) << 0)
+
+#define XUSB_PADCTL_HSIC_PAD0_CTL0 0x0C8
+#define HSIC_PAD0_CTL0_HSIC_OPT(x) (((x) & 0xF) << 16)
+#define HSIC_PAD0_CTL0_TX_SLEWN(x) (((x) & 0xF) << 12)
+#define HSIC_PAD0_CTL0_TX_SLEWP(x) (((x) & 0xF) << 8)
+#define HSIC_PAD0_CTL0_TX_RTUNEN(x) (((x) & 0xF) << 4)
+#define HSIC_PAD0_CTL0_TX_RTUNEP(x) (((x) & 0xF) << 0)
+
#define XUSB_PADCTL_USB3_PAD_MUX 0x134
+#define USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) (1 << (1 + (x)))
+#define USB3_PAD_MUX_SATA_IDDQ_DISABLE (1 << 6)
+
#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
#define IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
#define IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
@@ -90,17 +172,25 @@
#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5 0x158
#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6 0x15C
-struct lane_cfg {
- char *function;
- char **lanes;
- int iddq;
-};
-struct xusbpadctl_softc {
+#define WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res, (_r), (_v))
+#define RD4(_sc, _r) bus_read_4((_sc)->mem_res, (_r))
+
+
+struct padctl_softc {
device_t dev;
struct resource *mem_res;
- hwreset_t rst;
+ hwreset_t rst;
int phy_ena_cnt;
+
+ /* Fuses calibration data */
+ uint32_t hs_curr_level_0;
+ uint32_t hs_curr_level_123;
+ uint32_t hs_iref_cap;
+ uint32_t hs_term_range_adj;
+ uint32_t hs_squelch_level;
+
+ uint32_t hs_curr_level_offset;
};
static struct ofw_compat_data compat_data[] = {
@@ -108,274 +198,295 @@ static struct ofw_compat_data compat_data[] = {
{NULL, 0},
};
-struct padctl_lane {
- const char *name;
- bus_size_t reg;
- uint32_t shift;
- uint32_t mask;
- int iddq;
- char **mux;
- int nmux;
+/* Ports. */
+enum padctl_port_type {
+ PADCTL_PORT_USB2,
+ PADCTL_PORT_ULPI,
+ PADCTL_PORT_HSIC,
+ PADCTL_PORT_USB3,
};
-static char *otg_mux[] = {"snps", "xusb", "uart", "rsvd"};
-static char *usb_mux[] = {"snps", "xusb"};
-static char *pci_mux[] = {"pcie", "usb3", "sata", "rsvd"};
+struct padctl_lane;
+struct padctl_port {
+ enum padctl_port_type type;
+ const char *name;
+ const char *base_name;
+ int idx;
+ int (*init)(struct padctl_softc *sc,
+ struct padctl_port *port);
-#define LANE(n, r, s, m, i, mx) \
-{ \
- .name = n, \
- .reg = r, \
- .shift = s, \
- .mask = m, \
- .iddq = i, \
- .mux = mx, \
- .nmux = nitems(mx), \
-}
-
-static const struct padctl_lane lanes_tbl[] = {
- LANE("otg-0", XUSB_PADCTL_USB2_PAD_MUX, 0, 0x3, -1, otg_mux),
- LANE("otg-1", XUSB_PADCTL_USB2_PAD_MUX, 2, 0x3, -1, otg_mux),
- LANE("otg-2", XUSB_PADCTL_USB2_PAD_MUX, 4, 0x3, -1, otg_mux),
- LANE("ulpi-0", XUSB_PADCTL_USB2_PAD_MUX, 12, 0x1, -1, usb_mux),
- LANE("hsic-0", XUSB_PADCTL_USB2_PAD_MUX, 14, 0x1, -1, usb_mux),
- LANE("hsic-1", XUSB_PADCTL_USB2_PAD_MUX, 15, 0x1, -1, usb_mux),
- LANE("pcie-0", XUSB_PADCTL_USB3_PAD_MUX, 16, 0x3, 1, pci_mux),
- LANE("pcie-1", XUSB_PADCTL_USB3_PAD_MUX, 18, 0x3, 2, pci_mux),
- LANE("pcie-2", XUSB_PADCTL_USB3_PAD_MUX, 20, 0x3, 3, pci_mux),
- LANE("pcie-3", XUSB_PADCTL_USB3_PAD_MUX, 22, 0x3, 4, pci_mux),
- LANE("pcie-4", XUSB_PADCTL_USB3_PAD_MUX, 24, 0x3, 5, pci_mux),
- LANE("sata-0", XUSB_PADCTL_USB3_PAD_MUX, 26, 0x3, 6, pci_mux),
+ /* Runtime data. */
+ phandle_t xref;
+ bool enabled;
+ regulator_t supply_vbus; /* USB2, USB3 */
+ bool internal; /* ULPI, USB2, USB3 */
+ uint32_t companion; /* USB3 */
+ struct padctl_lane *lane;
};
-static int
-xusbpadctl_mux_function(const struct padctl_lane *lane, char *fnc_name)
-{
- int i;
+static int usb3_port_init(struct padctl_softc *sc, struct padctl_port *port);
- for (i = 0; i < lane->nmux; i++) {
- if (strcmp(fnc_name, lane->mux[i]) == 0)
- return (i);
- }
-
- return (-1);
+#define PORT(t, n, p, i) { \
+ .type = t, \
+ .name = n "-" #p, \
+ .base_name = n, \
+ .idx = p, \
+ .init = i, \
}
+static struct padctl_port ports_tbl[] = {
+ PORT(PADCTL_PORT_USB2, "usb2", 0, NULL),
+ PORT(PADCTL_PORT_USB2, "usb2", 1, NULL),
+ PORT(PADCTL_PORT_USB2, "usb2", 2, NULL),
+ PORT(PADCTL_PORT_ULPI, "ulpi", 0, NULL),
+ PORT(PADCTL_PORT_HSIC, "hsic", 0, NULL),
+ PORT(PADCTL_PORT_HSIC, "hsic", 1, NULL),
+ PORT(PADCTL_PORT_USB3, "usb3", 0, usb3_port_init),
+ PORT(PADCTL_PORT_USB3, "usb3", 1, usb3_port_init),
+};
-static int
-xusbpadctl_config_lane(struct xusbpadctl_softc *sc, char *lane_name,
- const struct padctl_lane *lane, struct lane_cfg *cfg)
-{
+/* Pads - a group of lannes. */
+enum padctl_pad_type {
+ PADCTL_PAD_USB2,
+ PADCTL_PAD_ULPI,
+ PADCTL_PAD_HSIC,
+ PADCTL_PAD_PCIE,
+ PADCTL_PAD_SATA,
+};
- int tmp;
- uint32_t reg;
+struct padctl_lane;
+struct padctl_pad {
+ const char *name;
+ enum padctl_pad_type type;
+ int (*powerup)(struct padctl_softc *sc,
+ struct padctl_lane *lane);
+ int (*powerdown)(struct padctl_softc *sc,
+ struct padctl_lane *lane);
+ /* Runtime data. */
+ bool enabled;
+ struct padctl_lane *lanes[8]; /* Safe maximum value. */
+ int nlanes;
+};
- reg = bus_read_4(sc->mem_res, lane->reg);
- if (cfg->function != NULL) {
- tmp = xusbpadctl_mux_function(lane, cfg->function);
- if (tmp == -1) {
- device_printf(sc->dev,
- "Unknown function %s for lane %s\n", cfg->function,
- lane_name);
- return (EINVAL);
- }
- reg &= ~(lane->mask << lane->shift);
- reg |= (tmp & lane->mask) << lane->shift;
- }
- if (cfg->iddq != -1) {
- if (lane->iddq == -1) {
- device_printf(sc->dev, "Invalid IDDQ for lane %s\n",
- lane_name);
- return (EINVAL);
- }
- if (cfg->iddq != 0)
- reg &= ~(1 << lane->iddq);
- else
- reg |= 1 << lane->iddq;
- }
+static int usb2_powerup(struct padctl_softc *sc, struct padctl_lane *lane);
+static int usb2_powerdown(struct padctl_softc *sc, struct padctl_lane *lane);
+static int pcie_powerup(struct padctl_softc *sc, struct padctl_lane *lane);
+static int pcie_powerdown(struct padctl_softc *sc, struct padctl_lane *lane);
+static int sata_powerup(struct padctl_softc *sc, struct padctl_lane *lane);
+static int sata_powerdown(struct padctl_softc *sc, struct padctl_lane *lane);
- bus_write_4(sc->mem_res, lane->reg, reg);
- return (0);
+#define PAD(n, t, u, d) { \
+ .name = n, \
+ .type = t, \
+ .powerup = u, \
+ .powerdown = d, \
}
+static struct padctl_pad pads_tbl[] = {
+ PAD("usb2", PADCTL_PAD_USB2, usb2_powerup, usb2_powerdown),
+ PAD("ulpi", PADCTL_PAD_ULPI, NULL, NULL),
+ PAD("hsic", PADCTL_PAD_HSIC, NULL, NULL),
+ PAD("pcie", PADCTL_PAD_PCIE, pcie_powerup, pcie_powerdown),
+ PAD("sata", PADCTL_PAD_SATA, sata_powerup, sata_powerdown),
+};
-static const struct padctl_lane *
-xusbpadctl_search_lane(char *lane_name)
-{
- int i;
+/* Lanes. */
+static char *otg_mux[] = {"snps", "xusb", "uart", "rsvd"};
+static char *usb_mux[] = {"snps", "xusb"};
+static char *pci_mux[] = {"pcie", "usb3-ss", "sata", "rsvd"};
- for (i = 0; i < nitems(lanes_tbl); i++) {
- if (strcmp(lane_name, lanes_tbl[i].name) == 0)
- return (&lanes_tbl[i]);
- }
+struct padctl_lane {
+ const char *name;
+ int idx;
+ bus_size_t reg;
+ uint32_t shift;
+ uint32_t mask;
+ char **mux;
+ int nmux;
+ /* Runtime data. */
+ bool enabled;
+ phandle_t xref;
+ struct padctl_pad *pad;
+ struct padctl_port *port;
+ int mux_idx;
- return (NULL);
-}
+};
-static int
-xusbpadctl_config_node(struct xusbpadctl_softc *sc, char *lane_name,
- struct lane_cfg *cfg)
-{
- const struct padctl_lane *lane;
- int rv;
-
- lane = xusbpadctl_search_lane(lane_name);
- if (lane == NULL) {
- device_printf(sc->dev, "Unknown lane: %s\n", lane_name);
- return (ENXIO);
- }
- rv = xusbpadctl_config_lane(sc, lane_name, lane, cfg);
- return (rv);
+#define LANE(n, p, r, s, m, mx) { \
+ .name = n "-" #p, \
+ .idx = p, \
+ .reg = r, \
+ .shift = s, \
+ .mask = m, \
+ .mux = mx, \
+ .nmux = nitems(mx), \
}
+static struct padctl_lane lanes_tbl[] = {
+ LANE("usb2", 0, XUSB_PADCTL_USB2_PAD_MUX, 0, 0x3, otg_mux),
+ LANE("usb2", 1, XUSB_PADCTL_USB2_PAD_MUX, 2, 0x3, otg_mux),
+ LANE("usb2", 2, XUSB_PADCTL_USB2_PAD_MUX, 4, 0x3, otg_mux),
+ LANE("ulpi", 0, XUSB_PADCTL_USB2_PAD_MUX, 12, 0x1, usb_mux),
+ LANE("hsic", 0, XUSB_PADCTL_USB2_PAD_MUX, 14, 0x1, usb_mux),
+ LANE("hsic", 1, XUSB_PADCTL_USB2_PAD_MUX, 15, 0x1, usb_mux),
+ LANE("pcie", 0, XUSB_PADCTL_USB3_PAD_MUX, 16, 0x3, pci_mux),
+ LANE("pcie", 1, XUSB_PADCTL_USB3_PAD_MUX, 18, 0x3, pci_mux),
+ LANE("pcie", 2, XUSB_PADCTL_USB3_PAD_MUX, 20, 0x3, pci_mux),
+ LANE("pcie", 3, XUSB_PADCTL_USB3_PAD_MUX, 22, 0x3, pci_mux),
+ LANE("pcie", 4, XUSB_PADCTL_USB3_PAD_MUX, 24, 0x3, pci_mux),
+ LANE("sata", 0, XUSB_PADCTL_USB3_PAD_MUX, 26, 0x3, pci_mux),
+};
-static int
-xusbpadctl_read_node(struct xusbpadctl_softc *sc, phandle_t node,
- struct lane_cfg *cfg, char **lanes, int *llanes)
-{
- int rv;
+/* Define all possible mappings for USB3 port lanes */
+struct padctl_lane_map {
+ int port_idx;
+ enum padctl_pad_type pad_type;
+ int lane_idx;
+};
- *llanes = OF_getprop_alloc(node, "nvidia,lanes", 1, (void **)lanes);
- if (*llanes <= 0)
- return (ENOENT);
-
- /* Read function (mux) settings. */
- rv = OF_getprop_alloc(node, "nvidia,function", 1,
- (void **)&cfg->function);
- if (rv <= 0)
- cfg->function = NULL;
- /* Read numeric properties. */
- rv = OF_getencprop(node, "nvidia,iddq", &cfg->iddq,
- sizeof(cfg->iddq));
- if (rv <= 0)
- cfg->iddq = -1;
- return (0);
+#define LANE_MAP(pi, pt, li) { \
+ .port_idx = pi, \
+ .pad_type = pt, \
+ .lane_idx = li, \
}
+static struct padctl_lane_map lane_map_tbl[] = {
+ LANE_MAP(0, PADCTL_PAD_PCIE, 0), /* port USB3-0 -> lane PCIE-0 */
+ LANE_MAP(1, PADCTL_PAD_PCIE, 1), /* port USB3-1 -> lane PCIE-1 */
+ /* -- or -- */
+ LANE_MAP(1, PADCTL_PAD_SATA, 0), /* port USB3-1 -> lane SATA-0 */
+};
+static struct padctl_port *search_lane_port(struct padctl_softc *sc,
+ struct padctl_lane *lane);
+/* -------------------------------------------------------------------------
+ *
+ * PHY functions
+ */
static int
-xusbpadctl_process_node(struct xusbpadctl_softc *sc, phandle_t node)
+usb3_port_init(struct padctl_softc *sc, struct padctl_port *port)
{
- struct lane_cfg cfg;
- char *lanes, *lname;
- int i, len, llanes, rv;
+ uint32_t reg;
- rv = xusbpadctl_read_node(sc, node, &cfg, &lanes, &llanes);
- if (rv != 0)
- return (rv);
+ reg = RD4(sc, XUSB_PADCTL_SS_PORT_MAP);
+ if (port->internal)
+ reg &= ~SS_PORT_MAP_PORT_INTERNAL(port->idx);
+ else
+ reg |= SS_PORT_MAP_PORT_INTERNAL(port->idx);
+ reg &= ~SS_PORT_MAP_PORT_MAP(port->idx, ~0);
+ reg |= SS_PORT_MAP_PORT_MAP(port->idx, port->companion);
+ WR4(sc, XUSB_PADCTL_SS_PORT_MAP, reg);
- len = 0;
- lname = lanes;
- do {
- i = strlen(lname) + 1;
- rv = xusbpadctl_config_node(sc, lname, &cfg);
- if (rv != 0)
- device_printf(sc->dev,
- "Cannot configure lane: %s: %d\n", lname, rv);
+ reg = RD4(sc, XUSB_PADCTL_IOPHY_USB3_PAD_CTL2(port->idx));
+ reg &= ~IOPHY_USB3_PAD_CTL2_CDR_CNTL(~0);
+ reg &= ~IOPHY_USB3_PAD_CTL2_RX_EQ(~0);
+ reg &= ~IOPHY_USB3_PAD_CTL2_RX_WANDER(~0);
+ reg |= IOPHY_USB3_PAD_CTL2_CDR_CNTL(0x24);
+ reg |= IOPHY_USB3_PAD_CTL2_RX_EQ(0xF070);
+ reg |= IOPHY_USB3_PAD_CTL2_RX_WANDER(0xF);
+ WR4(sc, XUSB_PADCTL_IOPHY_USB3_PAD_CTL2(port->idx), reg);
- len += i;
- lname += i;
- } while (len < llanes);
+ WR4(sc, XUSB_PADCTL_IOPHY_USB3_PAD_CTL4(port->idx),
+ 0x002008EE);
- if (lanes != NULL)
- OF_prop_free(lanes);
- if (cfg.function != NULL)
- OF_prop_free(cfg.function);
- return (rv);
-}
+ reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
+ reg &= ~ELPG_PROGRAM_SSP_ELPG_VCORE_DOWN(port->idx);
+ WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
+ DELAY(100);
+ reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
+ reg &= ~ELPG_PROGRAM_SSP_ELPG_CLAMP_EN_EARLY(port->idx);
+ WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
+ DELAY(100);
-static int
-xusbpadctl_pinctrl_cfg(device_t dev, phandle_t cfgxref)
-{
- struct xusbpadctl_softc *sc;
- phandle_t node, cfgnode;
- int rv;
+ reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
+ reg &= ~ELPG_PROGRAM_SSP_ELPG_CLAMP_EN(port->idx);
+ WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
+ DELAY(100);
- sc = device_get_softc(dev);
- cfgnode = OF_node_from_xref(cfgxref);
-
- rv = 0;
- for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) {
- if (!fdt_is_enabled(node))
- continue;
- rv = xusbpadctl_process_node(sc, node);
- if (rv != 0)
- return (rv);
- }
-
- return (rv);
+ return (0);
}
static int
-xusbpadctl_phy_pcie_powerup(struct xusbpadctl_softc *sc)
+pcie_powerup(struct padctl_softc *sc, struct padctl_lane *lane)
{
uint32_t reg;
int i;
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
- reg &= ~IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
- bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
+ reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+ reg &= ~IOPHY_PLL_P0_CTL1_REFCLK_SEL(~0);
+ WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
DELAY(100);
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
+ reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
reg |= IOPHY_PLL_P0_CTL2_REFCLKBUF_EN;
reg |= IOPHY_PLL_P0_CTL2_TXCLKREF_EN;
reg |= IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
- bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL2, reg);
+ WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL2, reg);
DELAY(100);
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+ reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
reg |= IOPHY_PLL_P0_CTL1_PLL_RST;
- bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
+ WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
DELAY(100);
- for (i = 0; i < 100; i++) {
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+ for (i = 100; i > 0; i--) {
+ reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
if (reg & IOPHY_PLL_P0_CTL1_PLL0_LOCKDET)
- return (0);
+ break;
DELAY(10);
}
+ if (i <= 0) {
+ device_printf(sc->dev, "Failed to power up PCIe phy\n");
+ return (ETIMEDOUT);
+ }
+ reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);
+ reg |= USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->idx);
+ WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);
- return (ETIMEDOUT);
+ return (0);
}
-
static int
-xusbpadctl_phy_pcie_powerdown(struct xusbpadctl_softc *sc)
+pcie_powerdown(struct padctl_softc *sc, struct padctl_lane *lane)
{
uint32_t reg;
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+ reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);
+ reg &= ~USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->idx);
+ WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);
+
+ reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
reg &= ~IOPHY_PLL_P0_CTL1_PLL_RST;
- bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
+ WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
DELAY(100);
+
return (0);
}
static int
-xusbpadctl_phy_sata_powerup(struct xusbpadctl_softc *sc)
+sata_powerup(struct padctl_softc *sc, struct padctl_lane *lane)
{
uint32_t reg;
int i;
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+ reg = RD4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
reg &= ~IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
reg &= ~IOPHY_MISC_PAD_S0_CTL1_IDDQ;
- bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg);
+ WR4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg);
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
reg &= ~IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
reg &= ~IOPHY_PLL_S0_CTL1_PLL_IDDQ;
- bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+ WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
reg |= IOPHY_PLL_S0_CTL1_PLL1_MODE;
- bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+ WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
reg |= IOPHY_PLL_S0_CTL1_PLL_RST_L;
- bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+ WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
for (i = 100; i >= 0; i--) {
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
if (reg & IOPHY_PLL_S0_CTL1_PLL1_LOCKDET)
break;
DELAY(100);
@@ -384,128 +495,233 @@ xusbpadctl_phy_sata_powerup(struct xusbpadctl_softc *s
device_printf(sc->dev, "Failed to power up SATA phy\n");
return (ETIMEDOUT);
}
+ reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);
+ reg |= IOPHY_PLL_S0_CTL1_PLL_RST_L;
+ WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);
+ reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);
+ reg |= USB3_PAD_MUX_SATA_IDDQ_DISABLE;
+ WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);
+
return (0);
}
static int
-xusbpadctl_phy_sata_powerdown(struct xusbpadctl_softc *sc)
+sata_powerdown(struct padctl_softc *sc, struct padctl_lane *lane)
{
uint32_t reg;
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);
+ reg &= ~USB3_PAD_MUX_SATA_IDDQ_DISABLE;
+ WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);
+
+ reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
reg &= ~IOPHY_PLL_S0_CTL1_PLL_RST_L;
- bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+ WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
DELAY(100);
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
reg &= ~IOPHY_PLL_S0_CTL1_PLL1_MODE;
- bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+ WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
DELAY(100);
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
reg |= IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
reg |= IOPHY_PLL_S0_CTL1_PLL_IDDQ;
- bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+ WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
DELAY(100);
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+ reg = RD4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
reg |= IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
reg |= IOPHY_MISC_PAD_S0_CTL1_IDDQ;
- bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg);
+ WR4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg);
DELAY(100);
return (0);
}
static int
-xusbpadctl_phy_powerup(struct xusbpadctl_softc *sc)
+usb2_powerup(struct padctl_softc *sc, struct padctl_lane *lane)
{
uint32_t reg;
+ struct padctl_port *port;
+ int rv;
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
+ port = search_lane_port(sc, lane);
+ if (port == NULL) {
+ device_printf(sc->dev, "Cannot find port for lane: %s\n",
+ lane->name);
+ }
+ reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+ reg &= ~USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL(~0);
+ reg &= ~USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL(~0);
+ reg |= USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL(sc->hs_squelch_level);
+ reg |= USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL(5);
+ WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0, reg);
+
+ reg = RD4(sc, XUSB_PADCTL_USB2_PORT_CAP);
+ reg &= ~USB2_PORT_CAP_PORT_CAP(lane->idx, ~0);
+ reg |= USB2_PORT_CAP_PORT_CAP(lane->idx, USB2_PORT_CAP_PORT_CAP_HOST);
+ WR4(sc, XUSB_PADCTL_USB2_PORT_CAP, reg);
+
+ reg = RD4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL0(lane->idx));
+ reg &= ~USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(~0);
+ reg &= ~USB2_OTG_PAD_CTL0_HS_SLEW(~0);
+ reg &= ~USB2_OTG_PAD_CTL0_LS_RSLEW(~0);
+ reg &= ~USB2_OTG_PAD_CTL0_PD;
+ reg &= ~USB2_OTG_PAD_CTL0_PD2;
+ reg &= ~USB2_OTG_PAD_CTL0_PD_ZI;
+
+ reg |= USB2_OTG_PAD_CTL0_HS_SLEW(14);
+ if (lane->idx == 0) {
+ reg |= USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(sc->hs_curr_level_0);
+ reg |= USB2_OTG_PAD_CTL0_LS_RSLEW(3);
+ } else {
+ reg |= USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(sc->hs_curr_level_123);
+ reg |= USB2_OTG_PAD_CTL0_LS_RSLEW(0);
+ }
+ WR4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL0(lane->idx), reg);
+
+ reg = RD4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL1(lane->idx));
+ reg &= ~USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ(~0);
+ reg &= ~USB2_OTG_PAD_CTL1_HS_IREF_CAP(~0);
+ reg &= ~USB2_OTG_PAD_CTL1_PD_DR;
+ reg &= ~USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP;
+ reg &= ~USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP;
+
+ reg |= USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ(sc->hs_term_range_adj);
+ reg |= USB2_OTG_PAD_CTL1_HS_IREF_CAP(sc->hs_iref_cap);
+ WR4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL1(lane->idx), reg);
+
+ if (port != NULL && port->supply_vbus != NULL) {
+ rv = regulator_enable(port->supply_vbus);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot enable vbus regulator\n");
+ return (rv);
+ }
+ }
+ reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+ reg &= ~USB2_BIAS_PAD_CTL0_PD;
+ WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0, reg);
+
+ return (0);
+}
+
+static int
+usb2_powerdown(struct padctl_softc *sc, struct padctl_lane *lane)
+{
+ uint32_t reg;
+ struct padctl_port *port;
+ int rv;
+
+ port = search_lane_port(sc, lane);
+ if (port == NULL) {
+ device_printf(sc->dev, "Cannot find port for lane: %s\n",
+ lane->name);
+ }
+ reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+ reg |= USB2_BIAS_PAD_CTL0_PD;
+ WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0, reg);
+
+ if (port != NULL && port->supply_vbus != NULL) {
+ rv = regulator_enable(port->supply_vbus);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot disable vbus regulator\n");
+ return (rv);
+ }
+ }
+ return (0);
+}
+
+
+static int
+phy_powerup(struct padctl_softc *sc)
+{
+ uint32_t reg;
+
+ reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
+ reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
+ WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
+ DELAY(100);
+
+ reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
- bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
+ WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
DELAY(100);
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
+ reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
- bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
+ WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
DELAY(100);
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
- reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
- bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
- DELAY(100);
-
return (0);
}
static int
-xusbpadctl_phy_powerdown(struct xusbpadctl_softc *sc)
+phy_powerdown(struct padctl_softc *sc)
{
uint32_t reg;
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
- reg |= ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
- bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
- DELAY(100);
-
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
+ reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
reg |= ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
- bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
+ WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
DELAY(100);
- reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
+ reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
reg |= ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
- bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
+ WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
DELAY(100);
+ reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);
+ reg |= ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
+ WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);
+ DELAY(100);
+
return (0);
}
static int
xusbpadctl_phy_enable(device_t dev, intptr_t id, bool enable)
{
- struct xusbpadctl_softc *sc;
+ struct padctl_softc *sc;
+ struct padctl_lane *lane;
+ struct padctl_pad *pad;
int rv;
sc = device_get_softc(dev);
- if ((id != TEGRA_XUSB_PADCTL_PCIE) &&
- (id != TEGRA_XUSB_PADCTL_SATA)) {
+ if (id < 0 || id >= nitems(lanes_tbl)) {
device_printf(dev, "Unknown phy: %d\n", id);
return (ENXIO);
}
-
- rv = 0;
+ lane = lanes_tbl + id;
+ if (!lane->enabled) {
+ device_printf(dev, "Lane is not enabled/configured: %s\n",
+ lane->name);
+ return (ENXIO);
+ }
+ pad = lane->pad;
if (enable) {
if (sc->phy_ena_cnt == 0) {
- rv = xusbpadctl_phy_powerup(sc);
+ rv = phy_powerup(sc);
if (rv != 0)
return (rv);
}
sc->phy_ena_cnt++;
}
- if (id == TEGRA_XUSB_PADCTL_PCIE) {
- if (enable)
- rv = xusbpadctl_phy_pcie_powerup(sc);
- else
- rv = xusbpadctl_phy_pcie_powerdown(sc);
- if (rv != 0)
- return (rv);
- } else if (id == TEGRA_XUSB_PADCTL_SATA) {
- if (enable)
- rv = xusbpadctl_phy_sata_powerup(sc);
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable
mailing list