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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to