Date: Wed, 4 Apr 2018 11:30:20 +0000 (UTC) From: Michal Meloun <mmel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: 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-... Message-ID: <201804041130.w34BUKGk038103@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201804041130.w34BUKGk038103>