Path: blob/main/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c
39507 views
/*-1* Copyright (c) 2016 Michal Meloun <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526#include <sys/param.h>27#include <sys/systm.h>28#include <sys/bus.h>29#include <sys/kernel.h>30#include <sys/module.h>31#include <sys/malloc.h>32#include <sys/rman.h>3334#include <machine/bus.h>35#include <machine/fdt.h>3637#include <dev/hwreset/hwreset.h>38#include <dev/phy/phy.h>39#include <dev/regulator/regulator.h>40#include <dev/fdt/fdt_common.h>41#include <dev/fdt/fdt_pinctrl.h>42#include <dev/ofw/openfirm.h>43#include <dev/ofw/ofw_bus.h>44#include <dev/ofw/ofw_bus_subr.h>4546#include <arm/nvidia/tegra_efuse.h>4748#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>4950#include "phydev_if.h"5152/* FUSE calibration data. */53#define FUSE_XUSB_CALIB 0x0F054#define FUSE_XUSB_CALIB_HS_CURR_LEVEL_123(x) (((x) >> 15) & 0x3F);55#define FUSE_XUSB_CALIB_HS_IREF_CAP(x) (((x) >> 13) & 0x03);56#define FUSE_XUSB_CALIB_HS_SQUELCH_LEVEL(x) (((x) >> 11) & 0x03);57#define FUSE_XUSB_CALIB_HS_TERM_RANGE_ADJ(x) (((x) >> 7) & 0x0F);58#define FUSE_XUSB_CALIB_HS_CURR_LEVEL_0(x) (((x) >> 0) & 0x3F);5960/* Registers. */61#define XUSB_PADCTL_USB2_PAD_MUX 0x0046263#define XUSB_PADCTL_USB2_PORT_CAP 0x00864#define USB2_PORT_CAP_ULPI_PORT_INTERNAL (1 << 25)65#define USB2_PORT_CAP_ULPI_PORT_CAP (1 << 24)66#define USB2_PORT_CAP_PORT_REVERSE_ID(p) (1 << (3 + (p) * 4))67#define USB2_PORT_CAP_PORT_INTERNAL(p) (1 << (2 + (p) * 4))68#define USB2_PORT_CAP_PORT_CAP(p, x) (((x) & 3) << ((p) * 4))69#define USB2_PORT_CAP_PORT_CAP_OTG 0x370#define USB2_PORT_CAP_PORT_CAP_DEVICE 0x271#define USB2_PORT_CAP_PORT_CAP_HOST 0x172#define USB2_PORT_CAP_PORT_CAP_DISABLED 0x07374#define XUSB_PADCTL_SS_PORT_MAP 0x01475#define SS_PORT_MAP_PORT_INTERNAL(p) (1 << (3 + (p) * 4))76#define SS_PORT_MAP_PORT_MAP(p, x) (((x) & 7) << ((p) * 4))7778#define XUSB_PADCTL_ELPG_PROGRAM 0x01C79#define ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)80#define ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)81#define ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)82#define ELPG_PROGRAM_SSP_ELPG_VCORE_DOWN(x) (1 << (18 + (x) * 4))83#define ELPG_PROGRAM_SSP_ELPG_CLAMP_EN_EARLY(x) (1 << (17 + (x) * 4))84#define ELPG_PROGRAM_SSP_ELPG_CLAMP_EN(x) (1 << (16 + (x) * 4))8586#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x04087#define IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)88#define IOPHY_PLL_P0_CTL1_REFCLK_SEL(x) (((x) & 0xF) << 12)89#define IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)9091#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x04492#define IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)93#define IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)94#define IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)9596#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2(x) (0x058 + (x) * 4)97#define IOPHY_USB3_PAD_CTL2_CDR_CNTL(x) (((x) & 0x00FF) << 4)98#define IOPHY_USB3_PAD_CTL2_RX_EQ(x) (((x) & 0xFFFF) << 8)99#define IOPHY_USB3_PAD_CTL2_RX_WANDER(x) (((x) & 0x000F) << 4)100#define IOPHY_USB3_PAD_CTL2_RX_TERM_CNTL(x) (((x) & 0x0003) << 2)101#define IOPHY_USB3_PAD_CTL2_TX_TERM_CNTL(x) (((x) & 0x0003) << 0)102103#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4(x) (0x068 + (x) * 4)104105#define XUSB_PADCTL_USB2_OTG_PAD_CTL0(x) (0x0A0 + (x) * 4)106#define USB2_OTG_PAD_CTL0_LSBIAS_SEL (1 << 23)107#define USB2_OTG_PAD_CTL0_DISCON_DETECT_METHOD (1 << 22)108#define USB2_OTG_PAD_CTL0_PD_ZI (1 << 21)109#define USB2_OTG_PAD_CTL0_PD2 (1 << 20)110#define USB2_OTG_PAD_CTL0_PD (1 << 19)111#define USB2_OTG_PAD_CTL0_TERM_EN (1 << 18)112#define USB2_OTG_PAD_CTL0_LS_LS_FSLEW(x) (((x) & 0x03) << 16)113#define USB2_OTG_PAD_CTL0_LS_RSLEW(x) (((x) & 0x03) << 14)114#define USB2_OTG_PAD_CTL0_FS_SLEW(x) (((x) & 0x03) << 12)115#define USB2_OTG_PAD_CTL0_HS_SLEW(x) (((x) & 0x3F) << 6)116#define USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(x) (((x) & 0x3F) << 0)117118#define XUSB_PADCTL_USB2_OTG_PAD_CTL1(x) (0x0AC + (x) * 4)119#define USB2_OTG_PAD_CTL1_RPU_RANGE_ADJ(x) (((x) & 0x3) << 11)120#define USB2_OTG_PAD_CTL1_HS_IREF_CAP(x) (((x) & 0x3) << 9)121#define USB2_OTG_PAD_CTL1_SPARE(x) (((x) & 0x3) << 7)122#define USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ(x) (((x) & 0xF) << 3)123#define USB2_OTG_PAD_CTL1_PD_DR (1 << 2)124#define USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP (1 << 1)125#define USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP (1 << 0)126127#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x0B8128#define USB2_BIAS_PAD_CTL0_ADJRPU(x) (((x) & 0x7) << 14)129#define USB2_BIAS_PAD_CTL0_PD_TRK (1 << 13)130#define USB2_BIAS_PAD_CTL0_PD (1 << 12)131#define USB2_BIAS_PAD_CTL0_TERM_OFFSETL(x) (((x) & 0x3) << 9)132#define USB2_BIAS_PAD_CTL0_VBUS_LEVEL(x) (((x) & 0x3) << 7)133#define USB2_BIAS_PAD_CTL0_HS_CHIRP_LEVEL(x) (((x) & 0x3) << 5)134#define USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL(x) (((x) & 0x7) << 2)135#define USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL(x) (((x) & 0x3) << 0)136137#define XUSB_PADCTL_HSIC_PAD0_CTL0 0x0C8138#define HSIC_PAD0_CTL0_HSIC_OPT(x) (((x) & 0xF) << 16)139#define HSIC_PAD0_CTL0_TX_SLEWN(x) (((x) & 0xF) << 12)140#define HSIC_PAD0_CTL0_TX_SLEWP(x) (((x) & 0xF) << 8)141#define HSIC_PAD0_CTL0_TX_RTUNEN(x) (((x) & 0xF) << 4)142#define HSIC_PAD0_CTL0_TX_RTUNEP(x) (((x) & 0xF) << 0)143144#define XUSB_PADCTL_USB3_PAD_MUX 0x134145#define USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) (1 << (1 + (x)))146#define USB3_PAD_MUX_SATA_IDDQ_DISABLE (1 << 6)147148#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138149#define IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)150#define IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)151#define IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)152#define IOPHY_PLL_S0_CTL1_PLL_RST_L (1 << 1)153#define IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)154155#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2 0x13C156#define XUSB_PADCTL_IOPHY_PLL_S0_CTL3 0x140157#define XUSB_PADCTL_IOPHY_PLL_S0_CTL4 0x144158159#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148160#define IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)161#define IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)162163#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2 0x14C164#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL3 0x150165#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL4 0x154166#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5 0x158167#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6 0x15C168169#define WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res, (_r), (_v))170#define RD4(_sc, _r) bus_read_4((_sc)->mem_res, (_r))171172struct padctl_softc {173device_t dev;174struct resource *mem_res;175hwreset_t rst;176int phy_ena_cnt;177178/* Fuses calibration data */179uint32_t hs_curr_level_0;180uint32_t hs_curr_level_123;181uint32_t hs_iref_cap;182uint32_t hs_term_range_adj;183uint32_t hs_squelch_level;184185uint32_t hs_curr_level_offset;186};187188static struct ofw_compat_data compat_data[] = {189{"nvidia,tegra124-xusb-padctl", 1},190{NULL, 0},191};192193/* Ports. */194enum padctl_port_type {195PADCTL_PORT_USB2,196PADCTL_PORT_ULPI,197PADCTL_PORT_HSIC,198PADCTL_PORT_USB3,199};200201struct padctl_lane;202struct padctl_port {203enum padctl_port_type type;204const char *name;205const char *base_name;206int idx;207int (*init)(struct padctl_softc *sc,208struct padctl_port *port);209210/* Runtime data. */211bool enabled;212regulator_t supply_vbus; /* USB2, USB3 */213bool internal; /* ULPI, USB2, USB3 */214uint32_t companion; /* USB3 */215struct padctl_lane *lane;216};217218static int usb3_port_init(struct padctl_softc *sc, struct padctl_port *port);219220#define PORT(t, n, p, i) { \221.type = t, \222.name = n "-" #p, \223.base_name = n, \224.idx = p, \225.init = i, \226}227static struct padctl_port ports_tbl[] = {228PORT(PADCTL_PORT_USB2, "usb2", 0, NULL),229PORT(PADCTL_PORT_USB2, "usb2", 1, NULL),230PORT(PADCTL_PORT_USB2, "usb2", 2, NULL),231PORT(PADCTL_PORT_ULPI, "ulpi", 0, NULL),232PORT(PADCTL_PORT_HSIC, "hsic", 0, NULL),233PORT(PADCTL_PORT_HSIC, "hsic", 1, NULL),234PORT(PADCTL_PORT_USB3, "usb3", 0, usb3_port_init),235PORT(PADCTL_PORT_USB3, "usb3", 1, usb3_port_init),236};237238/* Pads - a group of lannes. */239enum padctl_pad_type {240PADCTL_PAD_USB2,241PADCTL_PAD_ULPI,242PADCTL_PAD_HSIC,243PADCTL_PAD_PCIE,244PADCTL_PAD_SATA,245};246247struct padctl_lane;248struct padctl_pad {249const char *name;250enum padctl_pad_type type;251int (*powerup)(struct padctl_softc *sc,252struct padctl_lane *lane);253int (*powerdown)(struct padctl_softc *sc,254struct padctl_lane *lane);255/* Runtime data. */256bool enabled;257struct padctl_lane *lanes[8]; /* Safe maximum value. */258int nlanes;259};260261static int usb2_powerup(struct padctl_softc *sc, struct padctl_lane *lane);262static int usb2_powerdown(struct padctl_softc *sc, struct padctl_lane *lane);263static int pcie_powerup(struct padctl_softc *sc, struct padctl_lane *lane);264static int pcie_powerdown(struct padctl_softc *sc, struct padctl_lane *lane);265static int sata_powerup(struct padctl_softc *sc, struct padctl_lane *lane);266static int sata_powerdown(struct padctl_softc *sc, struct padctl_lane *lane);267268#define PAD(n, t, u, d) { \269.name = n, \270.type = t, \271.powerup = u, \272.powerdown = d, \273}274static struct padctl_pad pads_tbl[] = {275PAD("usb2", PADCTL_PAD_USB2, usb2_powerup, usb2_powerdown),276PAD("ulpi", PADCTL_PAD_ULPI, NULL, NULL),277PAD("hsic", PADCTL_PAD_HSIC, NULL, NULL),278PAD("pcie", PADCTL_PAD_PCIE, pcie_powerup, pcie_powerdown),279PAD("sata", PADCTL_PAD_SATA, sata_powerup, sata_powerdown),280};281282/* Lanes. */283static char *otg_mux[] = {"snps", "xusb", "uart", "rsvd"};284static char *usb_mux[] = {"snps", "xusb"};285static char *pci_mux[] = {"pcie", "usb3-ss", "sata", "rsvd"};286287struct padctl_lane {288const char *name;289int idx;290bus_size_t reg;291uint32_t shift;292uint32_t mask;293char **mux;294int nmux;295/* Runtime data. */296bool enabled;297struct padctl_pad *pad;298struct padctl_port *port;299int mux_idx;300301};302303#define LANE(n, p, r, s, m, mx) { \304.name = n "-" #p, \305.idx = p, \306.reg = r, \307.shift = s, \308.mask = m, \309.mux = mx, \310.nmux = nitems(mx), \311}312static struct padctl_lane lanes_tbl[] = {313LANE("usb2", 0, XUSB_PADCTL_USB2_PAD_MUX, 0, 0x3, otg_mux),314LANE("usb2", 1, XUSB_PADCTL_USB2_PAD_MUX, 2, 0x3, otg_mux),315LANE("usb2", 2, XUSB_PADCTL_USB2_PAD_MUX, 4, 0x3, otg_mux),316LANE("ulpi", 0, XUSB_PADCTL_USB2_PAD_MUX, 12, 0x1, usb_mux),317LANE("hsic", 0, XUSB_PADCTL_USB2_PAD_MUX, 14, 0x1, usb_mux),318LANE("hsic", 1, XUSB_PADCTL_USB2_PAD_MUX, 15, 0x1, usb_mux),319LANE("pcie", 0, XUSB_PADCTL_USB3_PAD_MUX, 16, 0x3, pci_mux),320LANE("pcie", 1, XUSB_PADCTL_USB3_PAD_MUX, 18, 0x3, pci_mux),321LANE("pcie", 2, XUSB_PADCTL_USB3_PAD_MUX, 20, 0x3, pci_mux),322LANE("pcie", 3, XUSB_PADCTL_USB3_PAD_MUX, 22, 0x3, pci_mux),323LANE("pcie", 4, XUSB_PADCTL_USB3_PAD_MUX, 24, 0x3, pci_mux),324LANE("sata", 0, XUSB_PADCTL_USB3_PAD_MUX, 26, 0x3, pci_mux),325};326327/* Define all possible mappings for USB3 port lanes */328struct padctl_lane_map {329int port_idx;330enum padctl_pad_type pad_type;331int lane_idx;332};333334#define LANE_MAP(pi, pt, li) { \335.port_idx = pi, \336.pad_type = pt, \337.lane_idx = li, \338}339static struct padctl_lane_map lane_map_tbl[] = {340LANE_MAP(0, PADCTL_PAD_PCIE, 0), /* port USB3-0 -> lane PCIE-0 */341LANE_MAP(1, PADCTL_PAD_PCIE, 1), /* port USB3-1 -> lane PCIE-1 */342/* -- or -- */343LANE_MAP(1, PADCTL_PAD_SATA, 0), /* port USB3-1 -> lane SATA-0 */344};345346/* Phy class and methods. */347static int xusbpadctl_phy_enable(struct phynode *phy, bool enable);348static phynode_method_t xusbpadctl_phynode_methods[] = {349PHYNODEMETHOD(phynode_enable, xusbpadctl_phy_enable),350PHYNODEMETHOD_END351352};353DEFINE_CLASS_1(xusbpadctl_phynode, xusbpadctl_phynode_class,354xusbpadctl_phynode_methods, 0, phynode_class);355356static struct padctl_port *search_lane_port(struct padctl_softc *sc,357struct padctl_lane *lane);358/* -------------------------------------------------------------------------359*360* PHY functions361*/362static int363usb3_port_init(struct padctl_softc *sc, struct padctl_port *port)364{365uint32_t reg;366367reg = RD4(sc, XUSB_PADCTL_SS_PORT_MAP);368if (port->internal)369reg &= ~SS_PORT_MAP_PORT_INTERNAL(port->idx);370else371reg |= SS_PORT_MAP_PORT_INTERNAL(port->idx);372reg &= ~SS_PORT_MAP_PORT_MAP(port->idx, ~0);373reg |= SS_PORT_MAP_PORT_MAP(port->idx, port->companion);374WR4(sc, XUSB_PADCTL_SS_PORT_MAP, reg);375376reg = RD4(sc, XUSB_PADCTL_IOPHY_USB3_PAD_CTL2(port->idx));377reg &= ~IOPHY_USB3_PAD_CTL2_CDR_CNTL(~0);378reg &= ~IOPHY_USB3_PAD_CTL2_RX_EQ(~0);379reg &= ~IOPHY_USB3_PAD_CTL2_RX_WANDER(~0);380reg |= IOPHY_USB3_PAD_CTL2_CDR_CNTL(0x24);381reg |= IOPHY_USB3_PAD_CTL2_RX_EQ(0xF070);382reg |= IOPHY_USB3_PAD_CTL2_RX_WANDER(0xF);383WR4(sc, XUSB_PADCTL_IOPHY_USB3_PAD_CTL2(port->idx), reg);384385WR4(sc, XUSB_PADCTL_IOPHY_USB3_PAD_CTL4(port->idx),3860x002008EE);387388reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);389reg &= ~ELPG_PROGRAM_SSP_ELPG_VCORE_DOWN(port->idx);390WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);391DELAY(100);392393reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);394reg &= ~ELPG_PROGRAM_SSP_ELPG_CLAMP_EN_EARLY(port->idx);395WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);396DELAY(100);397398reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);399reg &= ~ELPG_PROGRAM_SSP_ELPG_CLAMP_EN(port->idx);400WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);401DELAY(100);402403return (0);404}405406static int407pcie_powerup(struct padctl_softc *sc, struct padctl_lane *lane)408{409uint32_t reg;410int i;411412reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);413reg &= ~IOPHY_PLL_P0_CTL1_REFCLK_SEL(~0);414WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);415DELAY(100);416417reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);418reg |= IOPHY_PLL_P0_CTL2_REFCLKBUF_EN;419reg |= IOPHY_PLL_P0_CTL2_TXCLKREF_EN;420reg |= IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;421WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL2, reg);422DELAY(100);423424reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);425reg |= IOPHY_PLL_P0_CTL1_PLL_RST;426WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);427DELAY(100);428429for (i = 100; i > 0; i--) {430reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);431if (reg & IOPHY_PLL_P0_CTL1_PLL0_LOCKDET)432break;433DELAY(10);434}435if (i <= 0) {436device_printf(sc->dev, "Failed to power up PCIe phy\n");437return (ETIMEDOUT);438}439reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);440reg |= USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->idx);441WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);442443return (0);444}445446static int447pcie_powerdown(struct padctl_softc *sc, struct padctl_lane *lane)448{449uint32_t reg;450451reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);452reg &= ~USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->idx);453WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);454455reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);456reg &= ~IOPHY_PLL_P0_CTL1_PLL_RST;457WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);458DELAY(100);459460return (0);461462}463464static int465sata_powerup(struct padctl_softc *sc, struct padctl_lane *lane)466{467uint32_t reg;468int i;469470reg = RD4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);471reg &= ~IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;472reg &= ~IOPHY_MISC_PAD_S0_CTL1_IDDQ;473WR4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg);474475reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);476reg &= ~IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;477reg &= ~IOPHY_PLL_S0_CTL1_PLL_IDDQ;478WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);479480reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);481reg |= IOPHY_PLL_S0_CTL1_PLL1_MODE;482WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);483484reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);485reg |= IOPHY_PLL_S0_CTL1_PLL_RST_L;486WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);487488for (i = 100; i >= 0; i--) {489reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);490if (reg & IOPHY_PLL_S0_CTL1_PLL1_LOCKDET)491break;492DELAY(100);493}494if (i <= 0) {495device_printf(sc->dev, "Failed to power up SATA phy\n");496return (ETIMEDOUT);497}498reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);499reg |= IOPHY_PLL_S0_CTL1_PLL_RST_L;500WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);501502reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);503reg |= USB3_PAD_MUX_SATA_IDDQ_DISABLE;504WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);505506return (0);507}508509static int510sata_powerdown(struct padctl_softc *sc, struct padctl_lane *lane)511{512uint32_t reg;513514reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX);515reg &= ~USB3_PAD_MUX_SATA_IDDQ_DISABLE;516WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg);517518reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);519reg &= ~IOPHY_PLL_S0_CTL1_PLL_RST_L;520WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);521DELAY(100);522523reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);524reg &= ~IOPHY_PLL_S0_CTL1_PLL1_MODE;525WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);526DELAY(100);527528reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);529reg |= IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;530reg |= IOPHY_PLL_S0_CTL1_PLL_IDDQ;531WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);532DELAY(100);533534reg = RD4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);535reg |= IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;536reg |= IOPHY_MISC_PAD_S0_CTL1_IDDQ;537WR4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg);538DELAY(100);539540return (0);541}542543static int544usb2_powerup(struct padctl_softc *sc, struct padctl_lane *lane)545{546uint32_t reg;547struct padctl_port *port;548int rv;549550port = search_lane_port(sc, lane);551if (port == NULL) {552device_printf(sc->dev, "Cannot find port for lane: %s\n",553lane->name);554}555reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);556reg &= ~USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL(~0);557reg &= ~USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL(~0);558reg |= USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL(sc->hs_squelch_level);559reg |= USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL(5);560WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0, reg);561562reg = RD4(sc, XUSB_PADCTL_USB2_PORT_CAP);563reg &= ~USB2_PORT_CAP_PORT_CAP(lane->idx, ~0);564reg |= USB2_PORT_CAP_PORT_CAP(lane->idx, USB2_PORT_CAP_PORT_CAP_HOST);565WR4(sc, XUSB_PADCTL_USB2_PORT_CAP, reg);566567reg = RD4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL0(lane->idx));568reg &= ~USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(~0);569reg &= ~USB2_OTG_PAD_CTL0_HS_SLEW(~0);570reg &= ~USB2_OTG_PAD_CTL0_LS_RSLEW(~0);571reg &= ~USB2_OTG_PAD_CTL0_PD;572reg &= ~USB2_OTG_PAD_CTL0_PD2;573reg &= ~USB2_OTG_PAD_CTL0_PD_ZI;574575reg |= USB2_OTG_PAD_CTL0_HS_SLEW(14);576if (lane->idx == 0) {577reg |= USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(sc->hs_curr_level_0);578reg |= USB2_OTG_PAD_CTL0_LS_RSLEW(3);579} else {580reg |= USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(sc->hs_curr_level_123);581reg |= USB2_OTG_PAD_CTL0_LS_RSLEW(0);582}583WR4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL0(lane->idx), reg);584585reg = RD4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL1(lane->idx));586reg &= ~USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ(~0);587reg &= ~USB2_OTG_PAD_CTL1_HS_IREF_CAP(~0);588reg &= ~USB2_OTG_PAD_CTL1_PD_DR;589reg &= ~USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP;590reg &= ~USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP;591592reg |= USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ(sc->hs_term_range_adj);593reg |= USB2_OTG_PAD_CTL1_HS_IREF_CAP(sc->hs_iref_cap);594WR4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL1(lane->idx), reg);595596if (port != NULL && port->supply_vbus != NULL) {597rv = regulator_enable(port->supply_vbus);598if (rv != 0) {599device_printf(sc->dev,600"Cannot enable vbus regulator\n");601return (rv);602}603}604reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);605reg &= ~USB2_BIAS_PAD_CTL0_PD;606WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0, reg);607608return (0);609}610611static int612usb2_powerdown(struct padctl_softc *sc, struct padctl_lane *lane)613{614uint32_t reg;615struct padctl_port *port;616int rv;617618port = search_lane_port(sc, lane);619if (port == NULL) {620device_printf(sc->dev, "Cannot find port for lane: %s\n",621lane->name);622}623reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);624reg |= USB2_BIAS_PAD_CTL0_PD;625WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0, reg);626627if (port != NULL && port->supply_vbus != NULL) {628rv = regulator_enable(port->supply_vbus);629if (rv != 0) {630device_printf(sc->dev,631"Cannot disable vbus regulator\n");632return (rv);633}634}635return (0);636}637638static int639phy_powerup(struct padctl_softc *sc)640{641uint32_t reg;642643reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);644reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;645WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);646DELAY(100);647648reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);649reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;650WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);651DELAY(100);652653reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);654reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;655WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);656DELAY(100);657658return (0);659}660661static int662phy_powerdown(struct padctl_softc *sc)663{664uint32_t reg;665666reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);667reg |= ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;668WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);669DELAY(100);670671reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);672reg |= ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;673WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);674DELAY(100);675676reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM);677reg |= ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;678WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg);679DELAY(100);680681return (0);682}683684static int685xusbpadctl_phy_enable(struct phynode *phy, bool enable)686{687device_t dev;688intptr_t id;689struct padctl_softc *sc;690struct padctl_lane *lane;691struct padctl_pad *pad;692int rv;693694dev = phynode_get_device(phy);695id = phynode_get_id(phy);696sc = device_get_softc(dev);697698if (id < 0 || id >= nitems(lanes_tbl)) {699device_printf(dev, "Unknown phy: %d\n", id);700return (ENXIO);701}702lane = lanes_tbl + id;703if (!lane->enabled) {704device_printf(dev, "Lane is not enabled/configured: %s\n",705lane->name);706return (ENXIO);707}708pad = lane->pad;709if (enable) {710if (sc->phy_ena_cnt == 0) {711rv = phy_powerup(sc);712if (rv != 0)713return (rv);714}715sc->phy_ena_cnt++;716}717718if (enable)719rv = pad->powerup(sc, lane);720else721rv = pad->powerdown(sc, lane);722if (rv != 0)723return (rv);724725if (!enable) {726if (sc->phy_ena_cnt == 1) {727rv = phy_powerdown(sc);728if (rv != 0)729return (rv);730}731sc->phy_ena_cnt--;732}733734return (0);735}736737/* -------------------------------------------------------------------------738*739* FDT processing740*/741static struct padctl_port *742search_port(struct padctl_softc *sc, char *port_name)743{744int i;745746for (i = 0; i < nitems(ports_tbl); i++) {747if (strcmp(port_name, ports_tbl[i].name) == 0)748return (&ports_tbl[i]);749}750return (NULL);751}752753static struct padctl_port *754search_lane_port(struct padctl_softc *sc, struct padctl_lane *lane)755{756int i;757758for (i = 0; i < nitems(ports_tbl); i++) {759if (!ports_tbl[i].enabled)760continue;761if (ports_tbl[i].lane == lane)762return (ports_tbl + i);763}764return (NULL);765}766767static struct padctl_lane *768search_lane(struct padctl_softc *sc, char *lane_name)769{770int i;771772for (i = 0; i < nitems(lanes_tbl); i++) {773if (strcmp(lane_name, lanes_tbl[i].name) == 0)774return (lanes_tbl + i);775}776return (NULL);777}778779static struct padctl_lane *780search_pad_lane(struct padctl_softc *sc, enum padctl_pad_type type, int idx)781{782int i;783784for (i = 0; i < nitems(lanes_tbl); i++) {785if (!lanes_tbl[i].enabled)786continue;787if (type == lanes_tbl[i].pad->type && idx == lanes_tbl[i].idx)788return (lanes_tbl + i);789}790return (NULL);791}792793static struct padctl_lane *794search_usb3_pad_lane(struct padctl_softc *sc, int idx)795{796int i;797struct padctl_lane *lane, *tmp;798799lane = NULL;800for (i = 0; i < nitems(lane_map_tbl); i++) {801if (idx != lane_map_tbl[i].port_idx)802continue;803tmp = search_pad_lane(sc, lane_map_tbl[i].pad_type,804lane_map_tbl[i].lane_idx);805if (tmp == NULL)806continue;807if (strcmp(tmp->mux[tmp->mux_idx], "usb3-ss") != 0)808continue;809if (lane != NULL) {810device_printf(sc->dev, "Duplicated mappings found for"811" lanes: %s and %s\n", lane->name, tmp->name);812return (NULL);813}814lane = tmp;815}816return (lane);817}818819static struct padctl_pad *820search_pad(struct padctl_softc *sc, char *pad_name)821{822int i;823824for (i = 0; i < nitems(pads_tbl); i++) {825if (strcmp(pad_name, pads_tbl[i].name) == 0)826return (pads_tbl + i);827}828return (NULL);829}830831static int832search_mux(struct padctl_softc *sc, struct padctl_lane *lane, char *fnc_name)833{834int i;835836for (i = 0; i < lane->nmux; i++) {837if (strcmp(fnc_name, lane->mux[i]) == 0)838return (i);839}840return (-1);841}842843static int844config_lane(struct padctl_softc *sc, struct padctl_lane *lane)845{846uint32_t reg;847848reg = RD4(sc, lane->reg);849reg &= ~(lane->mask << lane->shift);850reg |= (lane->mux_idx & lane->mask) << lane->shift;851WR4(sc, lane->reg, reg);852return (0);853}854855static int856process_lane(struct padctl_softc *sc, phandle_t node, struct padctl_pad *pad)857{858struct padctl_lane *lane;859struct phynode *phynode;860struct phynode_init_def phy_init;861char *name;862char *function;863int rv;864865name = NULL;866function = NULL;867rv = OF_getprop_alloc(node, "name", (void **)&name);868if (rv <= 0) {869device_printf(sc->dev, "Cannot read lane name.\n");870return (ENXIO);871}872873lane = search_lane(sc, name);874if (lane == NULL) {875device_printf(sc->dev, "Unknown lane: %s\n", name);876rv = ENXIO;877goto end;878}879880/* Read function (mux) settings. */881rv = OF_getprop_alloc(node, "nvidia,function", (void **)&function);882if (rv <= 0) {883device_printf(sc->dev, "Cannot read lane function.\n");884rv = ENXIO;885goto end;886}887888lane->mux_idx = search_mux(sc, lane, function);889if (lane->mux_idx == ~0) {890device_printf(sc->dev, "Unknown function %s for lane %s\n",891function, name);892rv = ENXIO;893goto end;894}895896rv = config_lane(sc, lane);897if (rv != 0) {898device_printf(sc->dev, "Cannot configure lane: %s: %d\n",899name, rv);900rv = ENXIO;901goto end;902}903lane->pad = pad;904lane->enabled = true;905pad->lanes[pad->nlanes++] = lane;906907/* Create and register phy. */908bzero(&phy_init, sizeof(phy_init));909phy_init.id = lane - lanes_tbl;910phy_init.ofw_node = node;911phynode = phynode_create(sc->dev, &xusbpadctl_phynode_class, &phy_init);912if (phynode == NULL) {913device_printf(sc->dev, "Cannot create phy\n");914rv = ENXIO;915goto end;916}917if (phynode_register(phynode) == NULL) {918device_printf(sc->dev, "Cannot create phy\n");919return (ENXIO);920}921922rv = 0;923924end:925if (name != NULL)926OF_prop_free(name);927if (function != NULL)928OF_prop_free(function);929return (rv);930}931932static int933process_pad(struct padctl_softc *sc, phandle_t node)934{935struct padctl_pad *pad;936char *name;937int rv;938939name = NULL;940rv = OF_getprop_alloc(node, "name", (void **)&name);941if (rv <= 0) {942device_printf(sc->dev, "Cannot read pad name.\n");943return (ENXIO);944}945pad = search_pad(sc, name);946if (pad == NULL) {947device_printf(sc->dev, "Unknown pad: %s\n", name);948rv = ENXIO;949goto end;950}951952/* Read and process associated lanes. */953node = ofw_bus_find_child(node, "lanes");954if (node <= 0) {955device_printf(sc->dev, "Cannot find regulators subnode\n");956rv = ENXIO;957goto end;958}959960for (node = OF_child(node); node != 0; node = OF_peer(node)) {961if (!ofw_bus_node_status_okay(node))962continue;963964rv = process_lane(sc, node, pad);965if (rv != 0)966goto end;967}968pad->enabled = true;969rv = 0;970end:971if (name != NULL)972OF_prop_free(name);973return (rv);974}975976static int977process_port(struct padctl_softc *sc, phandle_t node)978{979980struct padctl_port *port;981char *name;982int rv;983984name = NULL;985rv = OF_getprop_alloc(node, "name", (void **)&name);986if (rv <= 0) {987device_printf(sc->dev, "Cannot read port name.\n");988return (ENXIO);989}990991port = search_port(sc, name);992if (port == NULL) {993device_printf(sc->dev, "Unknown port: %s\n", name);994rv = ENXIO;995goto end;996}997998if (port->type == PADCTL_PORT_USB3) {999rv = OF_getencprop(node, "nvidia,usb2-companion",1000&(port->companion), sizeof(port->companion));1001if (rv <= 0) {1002device_printf(sc->dev,1003"Missing 'nvidia,usb2-companion' property "1004"for port: %s\n", name);1005rv = ENXIO;1006goto end;1007}1008}10091010if (OF_hasprop(node, "vbus-supply")) {1011rv = regulator_get_by_ofw_property(sc->dev, 0,1012"vbus-supply", &port->supply_vbus);1013if (rv <= 0) {1014device_printf(sc->dev,1015"Cannot get 'vbus-supply' regulator "1016"for port: %s\n", name);1017rv = ENXIO;1018goto end;1019}1020}10211022if (OF_hasprop(node, "nvidia,internal"))1023port->internal = true;1024/* Find assigned lane */1025if (port->lane == NULL) {1026switch(port->type) {1027/* Routing is fixed for USB2, ULPI AND HSIC. */1028case PADCTL_PORT_USB2:1029port->lane = search_pad_lane(sc, PADCTL_PAD_USB2,1030port->idx);1031break;1032case PADCTL_PORT_ULPI:1033port->lane = search_pad_lane(sc, PADCTL_PAD_ULPI,1034port->idx);1035break;1036case PADCTL_PORT_HSIC:1037port->lane = search_pad_lane(sc, PADCTL_PAD_HSIC,1038port->idx);1039break;1040case PADCTL_PORT_USB3:1041port->lane = search_usb3_pad_lane(sc, port->idx);1042break;1043}1044}1045if (port->lane == NULL) {1046device_printf(sc->dev, "Cannot find lane for port: %s\n", name);1047rv = ENXIO;1048goto end;1049}1050port->enabled = true;1051rv = 0;1052end:1053if (name != NULL)1054OF_prop_free(name);1055return (rv);1056}10571058static int1059parse_fdt(struct padctl_softc *sc, phandle_t base_node)1060{1061phandle_t node;1062int rv;10631064rv = 0;1065node = ofw_bus_find_child(base_node, "pads");10661067if (node <= 0) {1068device_printf(sc->dev, "Cannot find pads subnode.\n");1069return (ENXIO);1070}1071for (node = OF_child(node); node != 0; node = OF_peer(node)) {1072if (!ofw_bus_node_status_okay(node))1073continue;1074rv = process_pad(sc, node);1075if (rv != 0)1076return (rv);1077}10781079node = ofw_bus_find_child(base_node, "ports");1080if (node <= 0) {1081device_printf(sc->dev, "Cannot find ports subnode.\n");1082return (ENXIO);1083}1084for (node = OF_child(node); node != 0; node = OF_peer(node)) {1085if (!ofw_bus_node_status_okay(node))1086continue;1087rv = process_port(sc, node);1088if (rv != 0)1089return (rv);1090}10911092return (0);1093}10941095static void1096load_calibration(struct padctl_softc *sc)1097{1098uint32_t reg;10991100/* All XUSB pad calibrations are packed into single dword.*/1101reg = tegra_fuse_read_4(FUSE_XUSB_CALIB);1102sc->hs_curr_level_0 = FUSE_XUSB_CALIB_HS_CURR_LEVEL_0(reg);1103sc->hs_curr_level_123 = FUSE_XUSB_CALIB_HS_CURR_LEVEL_123(reg);1104sc->hs_iref_cap = FUSE_XUSB_CALIB_HS_IREF_CAP(reg);1105sc->hs_squelch_level = FUSE_XUSB_CALIB_HS_SQUELCH_LEVEL(reg);1106sc->hs_term_range_adj = FUSE_XUSB_CALIB_HS_TERM_RANGE_ADJ(reg);1107}11081109/* -------------------------------------------------------------------------1110*1111* BUS functions1112*/1113static int1114xusbpadctl_probe(device_t dev)1115{11161117if (!ofw_bus_status_okay(dev))1118return (ENXIO);11191120if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)1121return (ENXIO);11221123device_set_desc(dev, "Tegra XUSB phy");1124return (BUS_PROBE_DEFAULT);1125}11261127static int1128xusbpadctl_detach(device_t dev)1129{11301131/* This device is always present. */1132return (EBUSY);1133}11341135static int1136xusbpadctl_attach(device_t dev)1137{1138struct padctl_softc * sc;1139int i, rid, rv;1140struct padctl_port *port;1141phandle_t node;11421143sc = device_get_softc(dev);1144sc->dev = dev;1145node = ofw_bus_get_node(dev);11461147rid = 0;1148sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,1149RF_ACTIVE);1150if (sc->mem_res == NULL) {1151device_printf(dev, "Cannot allocate memory resources\n");1152return (ENXIO);1153}11541155rv = hwreset_get_by_ofw_name(dev, 0, "padctl", &sc->rst);1156if (rv != 0) {1157device_printf(dev, "Cannot get 'padctl' reset: %d\n", rv);1158return (rv);1159}1160rv = hwreset_deassert(sc->rst);1161if (rv != 0) {1162device_printf(dev, "Cannot unreset 'padctl' reset: %d\n", rv);1163return (rv);1164}11651166load_calibration(sc);11671168rv = parse_fdt(sc, node);1169if (rv != 0) {1170device_printf(dev, "Cannot parse fdt configuration: %d\n", rv);1171return (rv);1172}1173for (i = 0; i < nitems(ports_tbl); i++) {1174port = ports_tbl + i;1175if (!port->enabled)1176continue;1177if (port->init == NULL)1178continue;1179rv = port->init(sc, port);1180if (rv != 0) {1181device_printf(dev, "Cannot init port '%s'\n",1182port->name);1183return (rv);1184}1185}1186return (0);1187}11881189static device_method_t tegra_xusbpadctl_methods[] = {1190/* Device interface */1191DEVMETHOD(device_probe, xusbpadctl_probe),1192DEVMETHOD(device_attach, xusbpadctl_attach),1193DEVMETHOD(device_detach, xusbpadctl_detach),11941195DEVMETHOD_END1196};11971198static DEFINE_CLASS_0(xusbpadctl, tegra_xusbpadctl_driver,1199tegra_xusbpadctl_methods, sizeof(struct padctl_softc));1200EARLY_DRIVER_MODULE(tegra_xusbpadctl, simplebus, tegra_xusbpadctl_driver,1201NULL, NULL, 73);120212031204