From owner-svn-src-head@freebsd.org Mon Nov 7 05:34:45 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 68208C34AA4; Mon, 7 Nov 2016 05:34:45 +0000 (UTC) (envelope-from mmel@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 03812DC3; Mon, 7 Nov 2016 05:34:44 +0000 (UTC) (envelope-from mmel@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id uA75Yi2d061349; Mon, 7 Nov 2016 05:34:44 GMT (envelope-from mmel@FreeBSD.org) Received: (from mmel@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uA75Yil1061348; Mon, 7 Nov 2016 05:34:44 GMT (envelope-from mmel@FreeBSD.org) Message-Id: <201611070534.uA75Yil1061348@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mmel set sender to mmel@FreeBSD.org using -f From: Michal Meloun Date: Mon, 7 Nov 2016 05:34:44 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r308390 - head/sys/arm/nvidia/tegra124 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 07 Nov 2016 05:34:45 -0000 Author: mmel Date: Mon Nov 7 05:34:44 2016 New Revision: 308390 URL: https://svnweb.freebsd.org/changeset/base/308390 Log: Rework NVIDIA Tegra124 XUSBPAD driver. - Adapt it for new, incompatible, DT bindings introduced by r306197. - Add support for USB super speed pads/ports. MFC after: 3 weeks Modified: head/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c Modified: head/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c ============================================================================== --- head/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c Sun Nov 6 23:13:13 2016 (r308389) +++ head/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c Mon Nov 7 05:34:44 2016 (r308390) @@ -39,26 +39,57 @@ #include #include +#include #include #include #include #include #include +#include + #include #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,8 +97,59 @@ #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) @@ -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_dat {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"}; - -#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), +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); + + /* 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; - - for (i = 0; i < lane->nmux; i++) { - if (strcmp(fnc_name, lane->mux[i]) == 0) - return (i); - } +static int usb3_port_init(struct padctl_softc *sc, struct padctl_port *port); - 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) -{ - - int tmp; - uint32_t reg; +/* Pads - a group of lannes. */ +enum padctl_pad_type { + PADCTL_PAD_USB2, + PADCTL_PAD_ULPI, + PADCTL_PAD_HSIC, + PADCTL_PAD_PCIE, + PADCTL_PAD_SATA, +}; - 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; - } +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; +}; - bus_write_4(sc->mem_res, lane->reg, reg); - return (0); +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); + +#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; - - for (i = 0; i < nitems(lanes_tbl); i++) { - if (strcmp(lane_name, lanes_tbl[i].name) == 0) - return (&lanes_tbl[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"}; - return (NULL); -} +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; -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; - - *llanes = OF_getprop_alloc(node, "nvidia,lanes", 1, (void **)lanes); - if (*llanes <= 0) - return (ENOENT); +/* Define all possible mappings for USB3 port lanes */ +struct padctl_lane_map { + int port_idx; + enum padctl_pad_type pad_type; + int lane_idx; +}; - /* 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; - - rv = xusbpadctl_read_node(sc, node, &cfg, &lanes, &llanes); - if (rv != 0) - return (rv); - - 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); - - len += i; - lname += i; - } while (len < llanes); - - if (lanes != NULL) - OF_prop_free(lanes); - if (cfg.function != NULL) - OF_prop_free(cfg.function); - return (rv); -} - + uint32_t reg; -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_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); + + 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); + + WR4(sc, XUSB_PADCTL_IOPHY_USB3_PAD_CTL4(port->idx), + 0x002008EE); + + 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); - sc = device_get_softc(dev); - cfgnode = OF_node_from_xref(cfgxref); + 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); - 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); - } + 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); - 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,81 +495,188 @@ xusbpadctl_phy_sata_powerup(struct xusbp 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); - reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; - bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg); + 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 = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM); - reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; - bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg); + reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM); + reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; + 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); + reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM); + reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; + WR4(sc, 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); @@ -467,45 +685,43 @@ xusbpadctl_phy_powerdown(struct xusbpadc 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); - else - rv = xusbpadctl_phy_sata_powerdown(sc); - if (rv != 0) - return (rv); - } + if (enable) + rv = pad->powerup(sc, lane); + else + rv = pad->powerdown(sc, lane); + if (rv != 0) + return (rv); + if (!enable) { if (sc->phy_ena_cnt == 1) { - rv = xusbpadctl_phy_powerdown(sc); + rv = phy_powerdown(sc); if (rv != 0) return (rv); } @@ -516,6 +732,387 @@ xusbpadctl_phy_enable(device_t dev, intp } static int +xusbpadctl_phy_map(device_t provider, phandle_t xref, int ncells, + pcell_t *cells, intptr_t *id) +{ + int i; + + if (ncells != 0) + return (ERANGE); + + for (i = 0; i < nitems(lanes_tbl); i++) { + if (lanes_tbl[i].xref == xref) { + *id = i; + return (0); + } + } + return (ENXIO); +} + +/* ------------------------------------------------------------------------- + * + * FDT processing + */ +static struct padctl_port * +search_port(struct padctl_softc *sc, char *port_name) +{ + int i; + + for (i = 0; i < nitems(ports_tbl); i++) { + if (strcmp(port_name, ports_tbl[i].name) == 0) + return (&ports_tbl[i]); + } + return (NULL); +} + +static struct padctl_port * +search_lane_port(struct padctl_softc *sc, struct padctl_lane *lane) +{ + int i; + + for (i = 0; i < nitems(ports_tbl); i++) { + if (!ports_tbl[i].enabled) + continue; + if (ports_tbl[i].lane == lane) + return (ports_tbl + i); + } + return (NULL); +} + +static struct padctl_lane * +search_lane(struct padctl_softc *sc, char *lane_name) +{ + int i; + + for (i = 0; i < nitems(lanes_tbl); i++) { + if (strcmp(lane_name, lanes_tbl[i].name) == 0) + return (lanes_tbl + i); + } + return (NULL); +} + +static struct padctl_lane * +search_pad_lane(struct padctl_softc *sc, enum padctl_pad_type type, int idx) +{ + int i; + + for (i = 0; i < nitems(lanes_tbl); i++) { + if (!lanes_tbl[i].enabled) + continue; + if (type == lanes_tbl[i].pad->type && idx == lanes_tbl[i].idx) *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***