14374Slars/*- 24374Slars * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org> 34374Slars * All rights reserved. 44374Slars * 511990Speter * Redistribution and use in source and binary forms, with or without 611990Speter * modification, are permitted provided that the following conditions 711990Speter * are met: 834766Speter * 1. Redistributions of source code must retain the above copyright 911990Speter * notice, this list of conditions and the following disclaimer. 1011990Speter * 2. Redistributions in binary form must reproduce the above copyright 1111990Speter * notice, this list of conditions and the following disclaimer in the 1211990Speter * documentation and/or other materials provided with the distribution. 1311990Speter * 144374Slars * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 154374Slars * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1628597Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1734766Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1834766Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1934766Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2034766Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 214374Slars * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2228597Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2328597Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2428597Speter * SUCH DAMAGE. 2528597Speter */ 264374Slars 2728597Speter#include <sys/cdefs.h> 2828597Speter/* 2928597Speter * XHCI driver for Tegra SoCs. 3028597Speter */ 3128597Speter#include "opt_bus.h" 3228597Speter#include "opt_platform.h" 3328597Speter 3428597Speter#include <sys/param.h> 3528597Speter#include <sys/bus.h> 3628597Speter#include <sys/clock.h> 3728597Speter#include <sys/condvar.h> 3828597Speter#include <sys/firmware.h> 3928597Speter#include <sys/kernel.h> 4028597Speter#include <sys/lock.h> 4128597Speter#include <sys/malloc.h> 4228597Speter#include <sys/module.h> 4328597Speter#include <sys/mutex.h> 4428597Speter#include <sys/rman.h> 4528597Speter#include <sys/systm.h> 4628597Speter 4728597Speter#include <vm/vm.h> 4828597Speter#include <vm/vm_extern.h> 4928597Speter#include <vm/vm_kern.h> 5028597Speter#include <vm/pmap.h> 5128597Speter 5211990Speter#include <machine/bus.h> 5311990Speter#include <machine/resource.h> 5411990Speter 5534766Speter#include <dev/clk/clk.h> 5634766Speter#include <dev/hwreset/hwreset.h> 5734766Speter#include <dev/phy/phy.h> 5828597Speter#include <dev/regulator/regulator.h> 5934766Speter#include <dev/ofw/ofw_bus.h> 6028597Speter#include <dev/ofw/ofw_bus_subr.h> 6128597Speter#include <dev/usb/usb.h> 6228597Speter#include <dev/usb/usbdi.h> 6328597Speter#include <dev/usb/usb_busdma.h> 6428597Speter#include <dev/usb/usb_process.h> 6528597Speter#include <dev/usb/usb_controller.h> 6628597Speter#include <dev/usb/usb_bus.h> 6728597Speter#include <dev/usb/controller/xhci.h> 6828597Speter#include <dev/usb/controller/xhcireg.h> 694374Slars 704374Slars#include <arm/nvidia/tegra_pmc.h> 714374Slars 724374Slars#include "usbdevs.h" 734374Slars 744374Slars/* FPCI address space */ 754374Slars#define T_XUSB_CFG_0 0x000 7611990Speter#define T_XUSB_CFG_1 0x004 7728597Speter#define CFG_1_BUS_MASTER (1 << 2) 784374Slars#define CFG_1_MEMORY_SPACE (1 << 1) 794374Slars#define CFG_1_IO_SPACE (1 << 0) 8028597Speter 8141568Sarchie#define T_XUSB_CFG_2 0x008 8250477Speter#define T_XUSB_CFG_3 0x00C 8328597Speter#define T_XUSB_CFG_4 0x010 844374Slars#define CFG_4_BASE_ADDRESS(x) (((x) & 0x1FFFF) << 15) 854374Slars 8628597Speter#define T_XUSB_CFG_5 0x014 8711990Speter#define T_XUSB_CFG_ARU_MAILBOX_CMD 0x0E4 884374Slars#define ARU_MAILBOX_CMD_INT_EN (1U << 31) 894374Slars#define ARU_MAILBOX_CMD_DEST_XHCI (1 << 30) 904374Slars#define ARU_MAILBOX_CMD_DEST_SMI (1 << 29) 914374Slars#define ARU_MAILBOX_CMD_DEST_PME (1 << 28) 924374Slars#define ARU_MAILBOX_CMD_DEST_FALC (1 << 27) 9328597Speter 944374Slars#define T_XUSB_CFG_ARU_MAILBOX_DATA_IN 0x0E8 954374Slars#define ARU_MAILBOX_DATA_IN_DATA(x) (((x) & 0xFFFFFF) << 0) 964374Slars#define ARU_MAILBOX_DATA_IN_TYPE(x) (((x) & 0x0000FF) << 24) 974374Slars 984374Slars#define T_XUSB_CFG_ARU_MAILBOX_DATA_OUT 0x0EC 994374Slars#define ARU_MAILBOX_DATA_OUT_DATA(x) (((x) >> 0) & 0xFFFFFF) 1004374Slars#define ARU_MAILBOX_DATA_OUT_TYPE(x) (((x) >> 24) & 0x0000FF) 1014374Slars 1024374Slars#define T_XUSB_CFG_ARU_MAILBOX_OWNER 0x0F0 1034374Slars#define ARU_MAILBOX_OWNER_SW 2 1044374Slars#define ARU_MAILBOX_OWNER_FW 1 1054374Slars#define ARU_MAILBOX_OWNER_NONE 0 1064374Slars 1074374Slars#define XUSB_CFG_ARU_C11_CSBRANGE 0x41C /* ! UNDOCUMENTED ! */ 1084374Slars#define ARU_C11_CSBRANGE_PAGE(x) ((x) >> 9) 1094374Slars#define ARU_C11_CSBRANGE_ADDR(x) (0x800 + ((x) & 0x1FF)) 1104374Slars#define XUSB_CFG_ARU_SMI_INTR 0x428 /* ! UNDOCUMENTED ! */ 1114374Slars#define ARU_SMI_INTR_EN (1 << 3) 1124374Slars#define ARU_SMI_INTR_FW_HANG (1 << 1) 1134374Slars#define XUSB_CFG_ARU_RST 0x42C /* ! UNDOCUMENTED ! */ 1144374Slars#define ARU_RST_RESET (1 << 0) 1154374Slars 11634766Speter#define XUSB_HOST_CONFIGURATION 0x180 1174374Slars#define CONFIGURATION_CLKEN_OVERRIDE (1U<< 31) 11811990Speter#define CONFIGURATION_PW_NO_DEVSEL_ERR_CYA (1 << 19) 11911990Speter#define CONFIGURATION_INITIATOR_READ_IDLE (1 << 18) 12011990Speter#define CONFIGURATION_INITIATOR_WRITE_IDLE (1 << 17) 12111990Speter#define CONFIGURATION_WDATA_LEAD_CYA (1 << 15) 12234766Speter#define CONFIGURATION_WR_INTRLV_CYA (1 << 14) 12334766Speter#define CONFIGURATION_TARGET_READ_IDLE (1 << 11) 12434766Speter#define CONFIGURATION_TARGET_WRITE_IDLE (1 << 10) 12534766Speter#define CONFIGURATION_MSI_VEC_EMPTY (1 << 9) 12634766Speter#define CONFIGURATION_UFPCI_MSIAW (1 << 7) 12734766Speter#define CONFIGURATION_UFPCI_PWPASSPW (1 << 6) 12834766Speter#define CONFIGURATION_UFPCI_PASSPW (1 << 5) 12934766Speter#define CONFIGURATION_UFPCI_PWPASSNPW (1 << 4) 1304374Slars#define CONFIGURATION_DFPCI_PWPASSNPW (1 << 3) 1314374Slars#define CONFIGURATION_DFPCI_RSPPASSPW (1 << 2) 1324374Slars#define CONFIGURATION_DFPCI_PASSPW (1 << 1) 1334374Slars#define CONFIGURATION_EN_FPCI (1 << 0) 1344374Slars 1354374Slars/* IPFS address space */ 1364374Slars#define XUSB_HOST_FPCI_ERROR_MASKS 0x184 1374374Slars#define FPCI_ERROR_MASTER_ABORT (1 << 2) 1384374Slars#define FPCI_ERRORI_DATA_ERROR (1 << 1) 1394374Slars#define FPCI_ERROR_TARGET_ABORT (1 << 0) 1404374Slars 1414374Slars#define XUSB_HOST_INTR_MASK 0x188 1424374Slars#define INTR_IP_INT_MASK (1 << 16) 14311990Speter#define INTR_MSI_MASK (1 << 8) 1444374Slars#define INTR_INT_MASK (1 << 0) 1454374Slars 14628597Speter#define XUSB_HOST_CLKGATE_HYSTERESIS 0x1BC 14711990Speter 14834766Speter /* CSB Falcon CPU */ 14934766Speter#define XUSB_FALCON_CPUCTL 0x100 15028597Speter#define CPUCTL_STOPPED (1 << 5) 15111990Speter#define CPUCTL_HALTED (1 << 4) 15211990Speter#define CPUCTL_HRESET (1 << 3) 15311990Speter#define CPUCTL_SRESET (1 << 2) 15411990Speter#define CPUCTL_STARTCPU (1 << 1) 15511990Speter#define CPUCTL_IINVAL (1 << 0) 15611990Speter 15734766Speter#define XUSB_FALCON_BOOTVEC 0x104 15834766Speter#define XUSB_FALCON_DMACTL 0x10C 15911990Speter#define XUSB_FALCON_IMFILLRNG1 0x154 1604374Slars#define IMFILLRNG1_TAG_HI(x) (((x) & 0xFFF) << 16) 1614374Slars#define IMFILLRNG1_TAG_LO(x) (((x) & 0xFFF) << 0) 16211990Speter#define XUSB_FALCON_IMFILLCTL 0x158 1634374Slars 16411990Speter/* CSB mempool */ 16511990Speter#define XUSB_CSB_MEMPOOL_APMAP 0x10181C 16611990Speter#define APMAP_BOOTPATH (1U << 31) 1674374Slars 1684374Slars#define XUSB_CSB_MEMPOOL_ILOAD_ATTR 0x101A00 16911990Speter#define XUSB_CSB_MEMPOOL_ILOAD_BASE_LO 0x101A04 1704374Slars#define XUSB_CSB_MEMPOOL_ILOAD_BASE_HI 0x101A08 17111990Speter#define XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE 0x101A10 17211990Speter#define L2IMEMOP_SIZE_OFFSET(x) (((x) & 0x3FF) << 8) 17311990Speter#define L2IMEMOP_SIZE_SIZE(x) (((x) & 0x0FF) << 24) 1744374Slars 1754374Slars#define XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG 0x101A14 1764374Slars#define L2IMEMOP_INVALIDATE_ALL (0x40 << 24) 1774374Slars#define L2IMEMOP_LOAD_LOCKED_RESULT (0x11 << 24) 1784374Slars 17928597Speter#define XUSB_CSB_MEMPOOL_L2IMEMOP_RESULT 0x101A18 18028597Speter#define L2IMEMOP_RESULT_VLD (1U << 31) 1814374Slars 18211990Speter#define XUSB_CSB_IMEM_BLOCK_SIZE 256 18311990Speter 18411990Speter#define TEGRA_XHCI_SS_HIGH_SPEED 120000000 18528597Speter#define TEGRA_XHCI_SS_LOW_SPEED 12000000 18611990Speter 18728597Speter/* MBOX commands. */ 18828597Speter#define MBOX_CMD_MSG_ENABLED 1 18992920Simp#define MBOX_CMD_INC_FALC_CLOCK 2 19092920Simp#define MBOX_CMD_DEC_FALC_CLOCK 3 19192920Simp#define MBOX_CMD_INC_SSPI_CLOCK 4 19292920Simp#define MBOX_CMD_DEC_SSPI_CLOCK 5 19392920Simp#define MBOX_CMD_SET_BW 6 19492920Simp#define MBOX_CMD_SET_SS_PWR_GATING 7 19592920Simp#define MBOX_CMD_SET_SS_PWR_UNGATING 8 19692920Simp#define MBOX_CMD_SAVE_DFE_CTLE_CTX 9 19792920Simp#define MBOX_CMD_AIRPLANE_MODE_ENABLED 10 19892920Simp#define MBOX_CMD_AIRPLANE_MODE_DISABLED 11 19992920Simp#define MBOX_CMD_START_HSIC_IDLE 12 20092920Simp#define MBOX_CMD_STOP_HSIC_IDLE 13 20192920Simp#define MBOX_CMD_DBC_WAKE_STACK 14 20292920Simp#define MBOX_CMD_HSIC_PRETEND_CONNECT 15 20392920Simp#define MBOX_CMD_RESET_SSPI 16 20492920Simp#define MBOX_CMD_DISABLE_SS_LFPS_DETECTION 17 20592920Simp#define MBOX_CMD_ENABLE_SS_LFPS_DETECTION 18 20692920Simp 20792920Simp/* MBOX responses. */ 20892920Simp#define MBOX_CMD_ACK (0x80 + 0) 20992920Simp#define MBOX_CMD_NAK (0x80 + 1) 21092920Simp 21192920Simp#define IPFS_WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res_ipfs, (_r), (_v)) 21292920Simp#define IPFS_RD4(_sc, _r) bus_read_4((_sc)->mem_res_ipfs, (_r)) 21392920Simp#define FPCI_WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res_fpci, (_r), (_v)) 21492920Simp#define FPCI_RD4(_sc, _r) bus_read_4((_sc)->mem_res_fpci, (_r)) 21592920Simp 21692920Simp#define LOCK(_sc) mtx_lock(&(_sc)->mtx) 21792920Simp#define UNLOCK(_sc) mtx_unlock(&(_sc)->mtx) 21892920Simp#define SLEEP(_sc, timeout) \ 2194374Slars mtx_sleep(sc, &sc->mtx, 0, "tegra_xhci", timeout); 2204374Slars#define LOCK_INIT(_sc) \ 2214374Slars mtx_init(&_sc->mtx, device_get_nameunit(_sc->dev), "tegra_xhci", MTX_DEF) 2224374Slars#define LOCK_DESTROY(_sc) mtx_destroy(&_sc->mtx) 22334766Speter#define ASSERT_LOCKED(_sc) mtx_assert(&_sc->mtx, MA_OWNED) 2244374Slars#define ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->mtx, MA_NOTOWNED) 2254374Slars 22634766Speterstruct tegra_xusb_fw_hdr { 22734766Speter uint32_t boot_loadaddr_in_imem; 2284374Slars uint32_t boot_codedfi_offset; 2294374Slars uint32_t boot_codetag; 23034766Speter uint32_t boot_codesize; 2314374Slars 2324374Slars uint32_t phys_memaddr; 2334374Slars uint16_t reqphys_memsize; 23434766Speter uint16_t alloc_phys_memsize; 2354374Slars 23634766Speter uint32_t rodata_img_offset; 2374374Slars uint32_t rodata_section_start; 2384374Slars uint32_t rodata_section_end; 23934766Speter uint32_t main_fnaddr; 24034766Speter 2414374Slars uint32_t fwimg_cksum; 2424374Slars uint32_t fwimg_created_time; 2434374Slars 2444374Slars uint32_t imem_resident_start; 2454374Slars uint32_t imem_resident_end; 2464374Slars uint32_t idirect_start; 24734766Speter uint32_t idirect_end; 24834766Speter uint32_t l2_imem_start; 24934766Speter uint32_t l2_imem_end; 2504374Slars uint32_t version_id; 2514374Slars uint8_t init_ddirect; 2524374Slars uint8_t reserved[3]; 25311990Speter uint32_t phys_addr_log_buffer; 2544374Slars uint32_t total_log_entries; 25534766Speter uint32_t dequeue_ptr; 25634766Speter uint32_t dummy[2]; 25734766Speter uint32_t fwimg_len; 25834766Speter uint8_t magic[8]; 25934766Speter uint32_t ss_low_power_entry_timeout; 26028597Speter uint8_t num_hsic_port; 26134766Speter uint8_t ss_portmap; 26234766Speter uint8_t build; 26334766Speter uint8_t padding[137]; /* Pad to 256 bytes */ 2644374Slars}; 26534766Speter 26634766Speterstruct xhci_soc; 26734766Speterstruct tegra_xhci_softc { 26828597Speter struct xhci_softc xhci_softc; 26934766Speter device_t dev; 27034766Speter struct xhci_soc *soc; 27134766Speter struct mtx mtx; 27234766Speter struct resource *mem_res_fpci; 27334766Speter struct resource *mem_res_ipfs; 27434766Speter struct resource *irq_res_mbox; 27534766Speter void *irq_hdl_mbox; 27634766Speter 27734766Speter clk_t clk_xusb_host; 27834766Speter clk_t clk_xusb_gate; 2794374Slars clk_t clk_xusb_falcon_src; 28034766Speter clk_t clk_xusb_ss; 28134766Speter clk_t clk_xusb_hs_src; 28234766Speter clk_t clk_xusb_fs_src; 2834374Slars hwreset_t hwreset_xusb_host; 28434766Speter hwreset_t hwreset_xusb_ss; 28534766Speter regulator_t regulators[16]; /* Safe maximum */ 28634766Speter phy_t phys[8]; /* Safe maximum */ 28734766Speter 28834766Speter struct intr_config_hook irq_hook; 28934766Speter bool xhci_inited; 2904374Slars void *fw_vaddr; 29134766Speter vm_size_t fw_size; 29234766Speter}; 29334766Speter 29434766Speterstruct xhci_soc { 29534766Speter char *fw_name; 29634766Speter char **regulator_names; 29734766Speter char **phy_names; 29834766Speter}; 29934766Speter 30034766Speter/* Tegra 124 config */ 30134766Speterstatic char *tegra124_reg_names[] = { 30234766Speter "avddio-pex-supply", 30334766Speter "dvddio-pex-supply", 30434766Speter "avdd-usb-supply", 30534766Speter "avdd-pll-utmip-supply", 3064374Slars "avdd-pll-erefe-supply", 30734766Speter "avdd-usb-ss-pll-supply", 30834766Speter "hvdd-usb-ss-supply", 30934766Speter "hvdd-usb-ss-pll-e-supply", 31034766Speter NULL 3114374Slars}; 31234766Speter 31334766Speterstatic char *tegra124_phy_names[] = { 31434766Speter "usb2-0", 31534766Speter "usb2-1", 31634766Speter "usb2-2", 31734766Speter "usb3-0", 31834766Speter NULL 31934766Speter}; 32034766Speter 32134766Speterstatic struct xhci_soc tegra124_soc = 32234766Speter{ 32334766Speter .fw_name = "tegra124_xusb_fw", 32434766Speter .regulator_names = tegra124_reg_names, 32534766Speter .phy_names = tegra124_phy_names, 32611990Speter}; 32711990Speter 32811990Speter/* Tegra 210 config */ 32911990Speterstatic char *tegra210_reg_names[] = { 33011990Speter "dvddio-pex-supply", 3314374Slars "hvddio-pex-supply", 33234766Speter "avdd-usb-supply", 3334374Slars "avdd-pll-utmip-supply", 33434766Speter "avdd-pll-uerefe-supply", 3354374Slars "dvdd-usb-ss-pll-supply", 33634766Speter "hvdd-usb-ss-pll-e-supply", 3374374Slars NULL 33834766Speter}; 33934766Speter 34034766Speterstatic char *tegra210_phy_names[] = { 34134766Speter "usb2-0", 3424374Slars "usb2-1", 34334766Speter "usb2-2", 3444374Slars "usb2-3", 3454374Slars "usb3-0", 34611990Speter "usb3-1", 34734766Speter NULL 3484374Slars}; 3494374Slars 3504374Slarsstatic struct xhci_soc tegra210_soc = 3514374Slars{ 3524374Slars .fw_name = "tegra210_xusb_fw", 35334766Speter .regulator_names = tegra210_reg_names, 35434766Speter .phy_names = tegra210_phy_names, 3554374Slars}; 3564374Slars 35728597Speter/* Compatible devices. */ 3584374Slarsstatic struct ofw_compat_data compat_data[] = { 3594374Slars {"nvidia,tegra124-xusb", (uintptr_t)&tegra124_soc}, 36034766Speter {"nvidia,tegra210-xusb", (uintptr_t)&tegra210_soc}, 3614374Slars {NULL, 0} 3624374Slars}; 36328597Speter 36434766Speter 3654374Slarsstatic uint32_t 3664374SlarsCSB_RD4(struct tegra_xhci_softc *sc, uint32_t addr) 3674374Slars{ 3684374Slars 3694374Slars FPCI_WR4(sc, XUSB_CFG_ARU_C11_CSBRANGE, ARU_C11_CSBRANGE_PAGE(addr)); 3704374Slars return (FPCI_RD4(sc, ARU_C11_CSBRANGE_ADDR(addr))); 3714374Slars} 37234766Speter 37332069Salexstatic void 3744374SlarsCSB_WR4(struct tegra_xhci_softc *sc, uint32_t addr, uint32_t val) 3754374Slars{ 3764374Slars 3774374Slars FPCI_WR4(sc, XUSB_CFG_ARU_C11_CSBRANGE, ARU_C11_CSBRANGE_PAGE(addr)); 37811990Speter FPCI_WR4(sc, ARU_C11_CSBRANGE_ADDR(addr), val); 37911990Speter} 38034766Speter 3814374Slarsstatic int 3824374Slarsget_fdt_resources(struct tegra_xhci_softc *sc, phandle_t node) 3834374Slars{ 3844374Slars int i, rv; 38534766Speter 3864374Slars /* Regulators. */ 3874374Slars for (i = 0; sc->soc->regulator_names[i] != NULL; i++) { 3884374Slars if (i >= nitems(sc->regulators)) { 3894374Slars device_printf(sc->dev, 3904374Slars "Too many regulators present in DT.\n"); 3914374Slars return (EOVERFLOW); 39228597Speter } 39328597Speter rv = regulator_get_by_ofw_property(sc->dev, 0, 39428597Speter sc->soc->regulator_names[i], sc->regulators + i); 39534766Speter if (rv != 0) { 39634766Speter device_printf(sc->dev, 39728597Speter "Cannot get '%s' regulator\n", 39834766Speter sc->soc->regulator_names[i]); 39934766Speter return (ENXIO); 4004374Slars } 4014374Slars } 40234766Speter 4034374Slars rv = hwreset_get_by_ofw_name(sc->dev, 0, "xusb_host", 40434766Speter &sc->hwreset_xusb_host); 4054374Slars if (rv != 0) { 4064374Slars device_printf(sc->dev, "Cannot get 'xusb_host' reset\n"); 40734766Speter return (ENXIO); 4084374Slars } 40934766Speter rv = hwreset_get_by_ofw_name(sc->dev, 0, "xusb_ss", 41034766Speter &sc->hwreset_xusb_ss); 41134766Speter if (rv != 0) { 4124374Slars device_printf(sc->dev, "Cannot get 'xusb_ss' reset\n"); 4134374Slars return (ENXIO); 4144374Slars } 4154374Slars 41634766Speter /* Phys. */ 41734766Speter for (i = 0; sc->soc->phy_names[i] != NULL; i++) { 4184374Slars if (i >= nitems(sc->phys)) { 4194374Slars device_printf(sc->dev, 4204374Slars "Too many phys present in DT.\n"); 42134766Speter return (EOVERFLOW); 4224374Slars } 4234374Slars rv = phy_get_by_ofw_name(sc->dev, 0, sc->soc->phy_names[i], 4244374Slars sc->phys + i); 4254374Slars if (rv != 0 && rv != ENOENT) { 4264374Slars device_printf(sc->dev, "Cannot get '%s' phy.\n", 4274374Slars sc->soc->phy_names[i]); 4284374Slars return (ENXIO); 4294374Slars } 4304374Slars } 4314374Slars 43234766Speter rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_host", 4334374Slars &sc->clk_xusb_host); 43434766Speter if (rv != 0) { 4354374Slars device_printf(sc->dev, "Cannot get 'xusb_host' clock\n"); 4364374Slars return (ENXIO); 4374374Slars } 4384374Slars rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_falcon_src", 43926880Scharnier &sc->clk_xusb_falcon_src); 44026880Scharnier if (rv != 0) { 44134766Speter device_printf(sc->dev, "Cannot get 'xusb_falcon_src' clock\n"); 44234766Speter return (ENXIO); 44334766Speter } 44434766Speter rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_ss", 4454374Slars &sc->clk_xusb_ss); 44634766Speter if (rv != 0) { 4474374Slars device_printf(sc->dev, "Cannot get 'xusb_ss' clock\n"); 44834766Speter return (ENXIO); 4494374Slars } 45034766Speter rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_hs_src", 45134766Speter &sc->clk_xusb_hs_src); 45234766Speter if (rv != 0) { 45392920Simp device_printf(sc->dev, "Cannot get 'xusb_hs_src' clock\n"); 45428597Speter return (ENXIO); 45534766Speter } 4564374Slars rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_fs_src", 45734766Speter &sc->clk_xusb_fs_src); 45834766Speter if (rv != 0) { 45934766Speter device_printf(sc->dev, "Cannot get 'xusb_fs_src' clock\n"); 46028597Speter return (ENXIO); 46134766Speter } 46234766Speter /* Clock xusb_gate is missing in mainstream DT */ 46328597Speter rv = clk_get_by_name(sc->dev, "xusb_gate", &sc->clk_xusb_gate); 4644374Slars if (rv != 0) { 4654374Slars device_printf(sc->dev, "Cannot get 'xusb_gate' clock\n"); 4664374Slars return (ENXIO); 4674374Slars } 4684374Slars return (0); 46992920Simp} 47034766Speter 47134766Speterstatic int 4724374Slarsenable_fdt_resources(struct tegra_xhci_softc *sc) 47334766Speter{ 47434766Speter int i, rv; 47534766Speter 47634766Speter rv = hwreset_assert(sc->hwreset_xusb_host); 47734766Speter if (rv != 0) { 47834766Speter device_printf(sc->dev, "Cannot reset 'xusb_host' reset\n"); 47934766Speter return (rv); 48034766Speter } 4814374Slars rv = hwreset_assert(sc->hwreset_xusb_ss); 4824374Slars if (rv != 0) { 4834374Slars device_printf(sc->dev, "Cannot reset 'xusb_ss' reset\n"); 4844374Slars return (rv); 4854374Slars } 48634766Speter 4874374Slars /* Regulators. */ 4884374Slars for (i = 0; i < nitems(sc->regulators); i++) { 4894374Slars if (sc->regulators[i] == NULL) 4904374Slars continue; 4914374Slars rv = regulator_enable(sc->regulators[i]); 4924374Slars if (rv != 0) { 4934374Slars device_printf(sc->dev, 49434766Speter "Cannot enable '%s' regulator\n", 4954374Slars sc->soc->regulator_names[i]); 49634766Speter return (rv); 49734766Speter } 49834766Speter } 4994374Slars 50034766Speter /* Power off XUSB host and XUSB SS domains. */ 50134766Speter rv = tegra_powergate_power_off(TEGRA_POWERGATE_XUSBA); 5024374Slars if (rv != 0) { 5034374Slars device_printf(sc->dev, "Cannot powerdown 'xusba' domain\n"); 50434766Speter return (rv); 5054374Slars } 5064374Slars rv = tegra_powergate_power_off(TEGRA_POWERGATE_XUSBC); 5074374Slars if (rv != 0) { 50834766Speter device_printf(sc->dev, "Cannot powerdown 'xusbc' domain\n"); 5094374Slars return (rv); 51034766Speter } 51134766Speter 51234766Speter /* Setup XUSB ss_src clock first */ 51334766Speter clk_set_freq(sc->clk_xusb_ss, TEGRA_XHCI_SS_HIGH_SPEED, 0); 5144374Slars if (rv != 0) 5154374Slars return (rv); 51634766Speter 51734766Speter /* The XUSB gate clock must be enabled before XUSBA can be powered. */ 51834766Speter rv = clk_enable(sc->clk_xusb_gate); 5194374Slars if (rv != 0) { 5204374Slars device_printf(sc->dev, 5214374Slars "Cannot enable 'xusb_gate' clock\n"); 52234766Speter return (rv); 52334766Speter } 52434766Speter 5254374Slars /* Power on XUSB host and XUSB SS domains. */ 5264374Slars rv = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_XUSBC, 5274374Slars sc->clk_xusb_host, sc->hwreset_xusb_host); 52834766Speter if (rv != 0) { 52934766Speter device_printf(sc->dev, "Cannot powerup 'xusbc' domain\n"); 53034766Speter return (rv); 5314374Slars } 5324374Slars rv = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_XUSBA, 53334766Speter sc->clk_xusb_ss, sc->hwreset_xusb_ss); 5344374Slars if (rv != 0) { 5354374Slars device_printf(sc->dev, "Cannot powerup 'xusba' domain\n"); 5364374Slars return (rv); 5374374Slars } 5384374Slars 5394374Slars /* Enable rest of clocks */ 5404374Slars rv = clk_enable(sc->clk_xusb_falcon_src); 5414374Slars if (rv != 0) { 54234766Speter device_printf(sc->dev, 5434374Slars "Cannot enable 'xusb_falcon_src' clock\n"); 5444374Slars return (rv); 54534766Speter } 54611990Speter rv = clk_enable(sc->clk_xusb_fs_src); 54711990Speter if (rv != 0) { 5484374Slars device_printf(sc->dev, 54911990Speter "Cannot enable 'xusb_fs_src' clock\n"); 55034766Speter return (rv); 5514374Slars } 5524374Slars rv = clk_enable(sc->clk_xusb_hs_src); 55311990Speter if (rv != 0) { 5544374Slars device_printf(sc->dev, 55511990Speter "Cannot enable 'xusb_hs_src' clock\n"); 55611990Speter return (rv); 55711990Speter } 55811990Speter 55911990Speter /* Phys. */ 56011990Speter for (i = 0; i < nitems(sc->phys); i++) { 56111990Speter if (sc->phys[i] == NULL) 5624374Slars continue; 56311990Speter rv = phy_enable(sc->phys[i]); 56434766Speter if (rv != 0) { 5654374Slars device_printf(sc->dev, "Cannot enable '%s' phy\n", 56634766Speter sc->soc->phy_names[i]); 5674374Slars return (rv); 5684374Slars } 56934766Speter } 5704374Slars 5714374Slars return (0); 5724374Slars} 57334766Speter 5744374Slars/* Respond by ACK/NAK back to FW */ 5754374Slarsstatic void 5764374Slarsmbox_send_ack(struct tegra_xhci_softc *sc, uint32_t cmd, uint32_t data) 57734766Speter{ 57828597Speter uint32_t reg; 57934766Speter 58028597Speter reg = ARU_MAILBOX_DATA_IN_TYPE(cmd) | ARU_MAILBOX_DATA_IN_DATA(data); 58128597Speter FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_DATA_IN, reg); 58228597Speter 58328597Speter reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD); 58428597Speter reg |= ARU_MAILBOX_CMD_DEST_FALC | ARU_MAILBOX_CMD_INT_EN; 58528597Speter FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD, reg); 58628597Speter} 58728597Speter 58828597Speter/* Sent command to FW */ 58928597Speterstatic int 59028597Spetermbox_send_cmd(struct tegra_xhci_softc *sc, uint32_t cmd, uint32_t data) 59128597Speter{ 59228597Speter uint32_t reg; 59328597Speter int i; 59428597Speter 59528597Speter reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_OWNER); 59628597Speter if (reg != ARU_MAILBOX_OWNER_NONE) { 59728597Speter device_printf(sc->dev, 59828597Speter "CPU mailbox is busy: 0x%08X\n", reg); 59911990Speter return (EBUSY); 60011990Speter } 60111990Speter /* XXX Is this right? Retry loop? Wait before send? */ 60228597Speter FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_OWNER, ARU_MAILBOX_OWNER_SW); 60334766Speter reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_OWNER); 6044374Slars if (reg != ARU_MAILBOX_OWNER_SW) { 60511990Speter device_printf(sc->dev, 60634766Speter "Cannot acquire CPU mailbox: 0x%08X\n", reg); 60711990Speter return (EBUSY); 60834766Speter } 60934766Speter reg = ARU_MAILBOX_DATA_IN_TYPE(cmd) | ARU_MAILBOX_DATA_IN_DATA(data); 61011990Speter FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_DATA_IN, reg); 6114374Slars 61211990Speter reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD); 61334766Speter reg |= ARU_MAILBOX_CMD_DEST_FALC | ARU_MAILBOX_CMD_INT_EN; 6144374Slars FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD, reg); 6154374Slars 6164374Slars for (i = 250; i > 0; i--) { 6174374Slars reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_OWNER); 6184374Slars if (reg == ARU_MAILBOX_OWNER_NONE) 6194374Slars break; 62034766Speter DELAY(100); 62134766Speter } 6224374Slars if (i <= 0) { 62334766Speter device_printf(sc->dev, 6244374Slars "Command response timeout: 0x%08X\n", reg); 6254374Slars return (ETIMEDOUT); 6264374Slars } 6274374Slars 62853686Skris return(0); 62953686Skris} 6304374Slars 63134766Speterstatic void 6324374Slarsprocess_msg(struct tegra_xhci_softc *sc, uint32_t req_cmd, uint32_t req_data, 63334766Speter uint32_t *resp_cmd, uint32_t *resp_data) 6344374Slars{ 6354374Slars uint64_t freq; 63634766Speter int rv; 6374374Slars 63834766Speter /* In most cases, data are echoed back. */ 6394374Slars *resp_data = req_data; 64034766Speter switch (req_cmd) { 6414374Slars case MBOX_CMD_INC_FALC_CLOCK: 64234766Speter case MBOX_CMD_DEC_FALC_CLOCK: 6434374Slars rv = clk_set_freq(sc->clk_xusb_falcon_src, req_data * 1000ULL, 64434766Speter 0); 6454374Slars if (rv == 0) { 6464374Slars rv = clk_get_freq(sc->clk_xusb_falcon_src, &freq); 64734766Speter *resp_data = (uint32_t)(freq / 1000); 6484374Slars } 6494374Slars *resp_cmd = rv == 0 ? MBOX_CMD_ACK: MBOX_CMD_NAK; 65034766Speter break; 65134766Speter 6524374Slars case MBOX_CMD_INC_SSPI_CLOCK: 6534374Slars case MBOX_CMD_DEC_SSPI_CLOCK: 65434766Speter rv = clk_set_freq(sc->clk_xusb_ss, req_data * 1000ULL, 6554374Slars 0); 65634766Speter if (rv == 0) { 6574374Slars rv = clk_get_freq(sc->clk_xusb_ss, &freq); 65834766Speter *resp_data = (uint32_t)(freq / 1000); 6594374Slars } 6604374Slars *resp_cmd = rv == 0 ? MBOX_CMD_ACK: MBOX_CMD_NAK; 6614374Slars break; 6624374Slars 6634374Slars case MBOX_CMD_SET_BW: 6644374Slars /* No respense is expected. */ 6654374Slars *resp_cmd = 0; 6664374Slars break; 6674374Slars 6684374Slars case MBOX_CMD_SET_SS_PWR_GATING: 6694374Slars case MBOX_CMD_SET_SS_PWR_UNGATING: 6704374Slars *resp_cmd = MBOX_CMD_NAK; 6714374Slars break; 6724374Slars 6734374Slars case MBOX_CMD_SAVE_DFE_CTLE_CTX: 6744374Slars /* Not implemented yet. */ 6754374Slars *resp_cmd = MBOX_CMD_ACK; 6764374Slars break; 6774374Slars 6784374Slars case MBOX_CMD_START_HSIC_IDLE: 6794374Slars case MBOX_CMD_STOP_HSIC_IDLE: 68034766Speter /* Not implemented yet. */ 68134766Speter *resp_cmd = MBOX_CMD_NAK; 68234766Speter break; 68334766Speter 68434766Speter case MBOX_CMD_DISABLE_SS_LFPS_DETECTION: 68534766Speter case MBOX_CMD_ENABLE_SS_LFPS_DETECTION: 68634766Speter /* Not implemented yet. */ 68734766Speter *resp_cmd = MBOX_CMD_NAK; 68834766Speter break; 68934766Speter 69034766Speter case MBOX_CMD_AIRPLANE_MODE_ENABLED: 69134766Speter case MBOX_CMD_AIRPLANE_MODE_DISABLED: 69234766Speter case MBOX_CMD_DBC_WAKE_STACK: 69334766Speter case MBOX_CMD_HSIC_PRETEND_CONNECT: 69434766Speter case MBOX_CMD_RESET_SSPI: 69534766Speter device_printf(sc->dev, 69634766Speter "Received unused/unexpected command: %u\n", req_cmd); 69734766Speter *resp_cmd = 0; 69834766Speter break; 69934766Speter 70034766Speter default: 70134766Speter device_printf(sc->dev, 7024374Slars "Received unknown command: %u\n", req_cmd); 70328597Speter } 7044374Slars} 7054374Slars 7064374Slarsstatic void 7074374Slarsintr_mbox(void *arg) 7084374Slars{ 7094374Slars struct tegra_xhci_softc *sc; 7104374Slars uint32_t reg, msg, resp_cmd, resp_data; 7114374Slars 7124374Slars sc = (struct tegra_xhci_softc *)arg; 7134374Slars 7144374Slars /* Clear interrupt first */ 7154374Slars reg = FPCI_RD4(sc, XUSB_CFG_ARU_SMI_INTR); 7164374Slars FPCI_WR4(sc, XUSB_CFG_ARU_SMI_INTR, reg); 7174374Slars if (reg & ARU_SMI_INTR_FW_HANG) { 7184374Slars device_printf(sc->dev, 7194374Slars "XUSB CPU firmware hang!!! CPUCTL: 0x%08X\n", 7204374Slars CSB_RD4(sc, XUSB_FALCON_CPUCTL)); 7214374Slars } 7224374Slars 72334766Speter msg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_DATA_OUT); 7244374Slars resp_cmd = 0; 7254374Slars process_msg(sc, ARU_MAILBOX_DATA_OUT_TYPE(msg), 72634766Speter ARU_MAILBOX_DATA_OUT_DATA(msg), &resp_cmd, &resp_data); 7274374Slars if (resp_cmd != 0) 7284374Slars mbox_send_ack(sc, resp_cmd, resp_data); 7294374Slars else 73011990Speter FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_OWNER, 7314374Slars ARU_MAILBOX_OWNER_NONE); 73234766Speter 7334374Slars reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD); 73434766Speter reg &= ~ARU_MAILBOX_CMD_DEST_SMI; 7354374Slars FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD, reg); 7364374Slars 73734766Speter} 7384374Slars 7394374Slarsstatic int 7404374Slarsload_fw(struct tegra_xhci_softc *sc) 74134766Speter{ 7424374Slars const struct firmware *fw; 74334766Speter const struct tegra_xusb_fw_hdr *fw_hdr; 7444374Slars vm_paddr_t fw_paddr, fw_base; 7454374Slars void *fw_vaddr; 7464374Slars vm_size_t fw_size; 74734766Speter uint32_t code_tags, code_size; 7484374Slars struct clocktime fw_clock; 74934766Speter struct timespec fw_timespec; 7504374Slars int i; 7514374Slars 7524374Slars /* Reset ARU */ 7534374Slars FPCI_WR4(sc, XUSB_CFG_ARU_RST, ARU_RST_RESET); 7544374Slars DELAY(3000); 7554374Slars 75634766Speter /* Check if FALCON already runs */ 7574374Slars if (CSB_RD4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO) != 0) { 7584374Slars device_printf(sc->dev, 7594374Slars "XUSB CPU is already loaded, CPUCTL: 0x%08X\n", 7604374Slars CSB_RD4(sc, XUSB_FALCON_CPUCTL)); 7614374Slars return (0); 7624374Slars } 7634374Slars 76434766Speter fw = firmware_get(sc->soc->fw_name); 7654374Slars if (fw == NULL) { 7664374Slars device_printf(sc->dev, "Cannot read xusb firmware\n"); 76728597Speter return (ENOENT); 76828597Speter } 76928597Speter 77028597Speter /* Allocate uncached memory and copy firmware into. */ 77134766Speter fw_hdr = (const struct tegra_xusb_fw_hdr *)fw->data; 77234766Speter fw_size = fw_hdr->fwimg_len; 77328597Speter 77428597Speter fw_vaddr = kmem_alloc_contig(fw_size, M_WAITOK, 0, -1UL, PAGE_SIZE, 0, 77528597Speter VM_MEMATTR_UNCACHEABLE); 77634766Speter fw_paddr = vtophys((uintptr_t)fw_vaddr); 77728597Speter fw_hdr = (const struct tegra_xusb_fw_hdr *)fw_vaddr; 77828597Speter memcpy(fw_vaddr, fw->data, fw_size); 77928597Speter 78028597Speter firmware_put(fw, FIRMWARE_UNLOAD); 78128597Speter sc->fw_vaddr = fw_vaddr; 78234766Speter sc->fw_size = fw_size; 78328597Speter 78428597Speter /* Setup firmware physical address and size. */ 78528597Speter fw_base = fw_paddr + sizeof(*fw_hdr); 78628597Speter CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_ATTR, fw_size); 78728597Speter CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO, fw_base & 0xFFFFFFFF); 78828597Speter CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_HI, (uint64_t)fw_base >> 32); 78928597Speter CSB_WR4(sc, XUSB_CSB_MEMPOOL_APMAP, APMAP_BOOTPATH); 79028597Speter 79134766Speter /* Invalidate full L2IMEM context. */ 79234766Speter CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG, 79328597Speter L2IMEMOP_INVALIDATE_ALL); 79428597Speter 79528597Speter /* Program load of L2IMEM by boot code. */ 79634766Speter code_tags = howmany(fw_hdr->boot_codetag, XUSB_CSB_IMEM_BLOCK_SIZE); 79728597Speter code_size = howmany(fw_hdr->boot_codesize, XUSB_CSB_IMEM_BLOCK_SIZE); 79834766Speter CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE, 79928597Speter L2IMEMOP_SIZE_OFFSET(code_tags) | 80028597Speter L2IMEMOP_SIZE_SIZE(code_size)); 80128597Speter 80234766Speter /* Execute L2IMEM boot code fetch. */ 80334766Speter CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG, 80428597Speter L2IMEMOP_LOAD_LOCKED_RESULT); 80528597Speter 80628597Speter /* Program FALCON auto-fill range and block count */ 80734766Speter CSB_WR4(sc, XUSB_FALCON_IMFILLCTL, code_size); 80828597Speter CSB_WR4(sc, XUSB_FALCON_IMFILLRNG1, 80928597Speter IMFILLRNG1_TAG_LO(code_tags) | 81034766Speter IMFILLRNG1_TAG_HI(code_tags + code_size)); 81134766Speter 81228597Speter CSB_WR4(sc, XUSB_FALCON_DMACTL, 0); 81328597Speter /* Wait for CPU */ 81428597Speter for (i = 500; i > 0; i--) { 81528597Speter if (CSB_RD4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_RESULT) & 81628597Speter L2IMEMOP_RESULT_VLD) 81734766Speter break; 81828597Speter DELAY(100); 81934766Speter } 82028597Speter if (i <= 0) { 82128597Speter device_printf(sc->dev, "Timedout while wating for DMA, " 8224374Slars "state: 0x%08X\n", 8234374Slars CSB_RD4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_RESULT)); 82428597Speter return (ETIMEDOUT); 82528597Speter } 82628597Speter 82734766Speter /* Boot FALCON cpu */ 82828597Speter CSB_WR4(sc, XUSB_FALCON_BOOTVEC, fw_hdr->boot_codetag); 82928597Speter CSB_WR4(sc, XUSB_FALCON_CPUCTL, CPUCTL_STARTCPU); 83028597Speter 83134766Speter /* Wait for CPU */ 83228597Speter for (i = 50; i > 0; i--) { 83328597Speter if (CSB_RD4(sc, XUSB_FALCON_CPUCTL) == CPUCTL_STOPPED) 83434766Speter break; 83528597Speter DELAY(100); 83634766Speter } 8374374Slars if (i <= 0) { 8384374Slars device_printf(sc->dev, "Timedout while wating for FALCON cpu, " 83934766Speter "state: 0x%08X\n", CSB_RD4(sc, XUSB_FALCON_CPUCTL)); 8404374Slars return (ETIMEDOUT); 84134766Speter } 84228597Speter 84328597Speter fw_timespec.tv_sec = fw_hdr->fwimg_created_time; 84434766Speter fw_timespec.tv_nsec = 0; 84528597Speter clock_ts_to_ct(&fw_timespec, &fw_clock); 84634766Speter device_printf(sc->dev, 84711990Speter " Falcon firmware version: %02X.%02X.%04X," 84811990Speter " (%d/%d/%d %d:%02d:%02d UTC)\n", 84934766Speter (fw_hdr->version_id >> 24) & 0xFF,(fw_hdr->version_id >> 15) & 0xFF, 85011990Speter fw_hdr->version_id & 0xFFFF, 85134766Speter fw_clock.day, fw_clock.mon, fw_clock.year, 85228597Speter fw_clock.hour, fw_clock.min, fw_clock.sec); 85328597Speter 85434766Speter return (0); 85528597Speter} 85634766Speter 8574374Slarsstatic int 8584374Slarsinit_hw(struct tegra_xhci_softc *sc) 85934766Speter{ 8604374Slars int rv; 86134766Speter uint32_t reg; 86228597Speter rman_res_t base_addr; 86328597Speter 86434766Speter base_addr = rman_get_start(sc->xhci_softc.sc_io_res); 86534766Speter 86634766Speter /* Enable FPCI access */ 86728597Speter reg = IPFS_RD4(sc, XUSB_HOST_CONFIGURATION); 86828597Speter reg |= CONFIGURATION_EN_FPCI; 86934766Speter IPFS_WR4(sc, XUSB_HOST_CONFIGURATION, reg); 87034766Speter IPFS_RD4(sc, XUSB_HOST_CONFIGURATION); 87128597Speter 87228597Speter /* Program bar for XHCI base address */ 87328597Speter reg = FPCI_RD4(sc, T_XUSB_CFG_4); 87434766Speter reg &= ~CFG_4_BASE_ADDRESS(~0); 87528597Speter reg |= CFG_4_BASE_ADDRESS((uint32_t)base_addr >> 15); 87628597Speter FPCI_WR4(sc, T_XUSB_CFG_4, reg); 8774374Slars FPCI_WR4(sc, T_XUSB_CFG_5, (uint32_t)((uint64_t)(base_addr) >> 32)); 87828597Speter 87928597Speter /* Enable bus master */ 88028597Speter reg = FPCI_RD4(sc, T_XUSB_CFG_1); 88128597Speter reg |= CFG_1_IO_SPACE; 88234766Speter reg |= CFG_1_MEMORY_SPACE; 88328597Speter reg |= CFG_1_BUS_MASTER; 88428597Speter FPCI_WR4(sc, T_XUSB_CFG_1, reg); 88528597Speter 88628597Speter /* Enable Interrupts */ 88728597Speter reg = IPFS_RD4(sc, XUSB_HOST_INTR_MASK); 88834766Speter reg |= INTR_IP_INT_MASK; 88928597Speter IPFS_WR4(sc, XUSB_HOST_INTR_MASK, reg); 89028597Speter 89128597Speter /* Set hysteresis */ 89228597Speter IPFS_WR4(sc, XUSB_HOST_CLKGATE_HYSTERESIS, 128); 89328597Speter 89428597Speter rv = load_fw(sc); 8954374Slars if (rv != 0) 89628597Speter return rv; 89734766Speter return (0); 89834766Speter} 89928597Speter 90028597Speterstatic int 90128597Spetertegra_xhci_probe(device_t dev) 90228597Speter{ 90334766Speter 90428597Speter if (!ofw_bus_status_okay(dev)) 90534766Speter return (ENXIO); 90628597Speter 90734766Speter if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) { 9084374Slars device_set_desc(dev, "Nvidia Tegra XHCI controller"); 90928597Speter return (BUS_PROBE_DEFAULT); 91028597Speter } 91128597Speter return (ENXIO); 91228597Speter} 91328597Speter 9144374Slarsstatic int 91511990Spetertegra_xhci_detach(device_t dev) 91634766Speter{ 9174374Slars struct tegra_xhci_softc *sc; 9184374Slars struct xhci_softc *xsc; 9194374Slars 9204374Slars sc = device_get_softc(dev); 9214374Slars xsc = &sc->xhci_softc; 9224374Slars 9234374Slars /* during module unload there are lots of children leftover */ 9244374Slars device_delete_children(dev); 92534766Speter if (sc->xhci_inited) { 92634766Speter usb_callout_drain(&xsc->sc_callout); 9274374Slars xhci_halt_controller(xsc); 92834766Speter } 9294374Slars 9304374Slars if (xsc->sc_irq_res && xsc->sc_intr_hdl) { 93134766Speter bus_teardown_intr(dev, xsc->sc_irq_res, xsc->sc_intr_hdl); 9324374Slars xsc->sc_intr_hdl = NULL; 9334374Slars } 9344374Slars if (xsc->sc_irq_res) { 9354374Slars bus_release_resource(dev, SYS_RES_IRQ, 9364374Slars rman_get_rid(xsc->sc_irq_res), xsc->sc_irq_res); 9374374Slars xsc->sc_irq_res = NULL; 93834766Speter } 93934766Speter if (xsc->sc_io_res != NULL) { 94028597Speter bus_release_resource(dev, SYS_RES_MEMORY, 94128597Speter rman_get_rid(xsc->sc_io_res), xsc->sc_io_res); 94280381Ssheldonh xsc->sc_io_res = NULL; 94328597Speter } 94428597Speter if (sc->xhci_inited) 94534766Speter xhci_uninit(xsc); 94634766Speter if (sc->irq_hdl_mbox != NULL) 94734766Speter bus_teardown_intr(dev, sc->irq_res_mbox, sc->irq_hdl_mbox); 94828597Speter if (sc->fw_vaddr != NULL) 94928597Speter kmem_free(sc->fw_vaddr, sc->fw_size); 95028597Speter LOCK_DESTROY(sc); 95128597Speter return (0); 95228597Speter} 95328597Speter 95434766Speterstatic int 95534766Spetertegra_xhci_attach(device_t dev) 95634766Speter{ 95728597Speter struct tegra_xhci_softc *sc; 95828597Speter struct xhci_softc *xsc; 95928597Speter int rv, rid; 96034766Speter phandle_t node; 96134766Speter 96234766Speter sc = device_get_softc(dev); 9634374Slars sc->dev = dev; 96411990Speter sc->soc = (struct xhci_soc *)ofw_bus_search_compatible(dev, 9654374Slars compat_data)->ocd_data; 96611990Speter node = ofw_bus_get_node(dev); 9674374Slars xsc = &sc->xhci_softc; 96834766Speter LOCK_INIT(sc); 96911990Speter 9704374Slars rv = get_fdt_resources(sc, node); 97111990Speter if (rv != 0) { 97211990Speter rv = ENXIO; 97311990Speter goto error; 97434766Speter } 9754374Slars rv = enable_fdt_resources(sc); 9764374Slars if (rv != 0) { 9774374Slars rv = ENXIO; 9784374Slars goto error; 97934766Speter } 98011990Speter 98134766Speter /* Allocate resources. */ 98211990Speter rid = 0; 98334766Speter xsc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 98428597Speter RF_ACTIVE); 98528597Speter if (xsc->sc_io_res == NULL) { 98628597Speter device_printf(dev, 98728597Speter "Could not allocate HCD memory resources\n"); 98828597Speter rv = ENXIO; 98928597Speter goto error; 99028597Speter } 99128597Speter rid = 1; 99228597Speter sc->mem_res_fpci = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 99328597Speter RF_ACTIVE); 99428597Speter if (sc->mem_res_fpci == NULL) { 99534766Speter device_printf(dev, 99628597Speter "Could not allocate FPCI memory resources\n"); 99728597Speter rv = ENXIO; 99834766Speter goto error; 99934766Speter } 100034766Speter rid = 2; 100134766Speter sc->mem_res_ipfs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 100234766Speter RF_ACTIVE); 100334766Speter if (sc->mem_res_ipfs == NULL) { 100434766Speter device_printf(dev, 100534766Speter "Could not allocate IPFS memory resources\n"); 100628597Speter rv = ENXIO; 100734766Speter goto error; 100828597Speter } 100934766Speter 101034766Speter rid = 0; 101128597Speter xsc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 101234766Speter RF_ACTIVE); 101328597Speter if (xsc->sc_irq_res == NULL) { 101434766Speter device_printf(dev, "Could not allocate HCD IRQ resources\n"); 101511990Speter rv = ENXIO; 101611990Speter goto error; 101711990Speter } 101811990Speter rid = 1; 101934766Speter sc->irq_res_mbox = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 102011990Speter RF_ACTIVE); 102111990Speter if (sc->irq_res_mbox == NULL) { 102211990Speter device_printf(dev, "Could not allocate MBOX IRQ resources\n"); 102311990Speter rv = ENXIO; 102434766Speter goto error; 102511990Speter } 102611990Speter 102711990Speter rv = init_hw(sc); 102811990Speter if (rv != 0) { 102934766Speter device_printf(dev, "Could not initialize XUSB hardware\n"); 103011990Speter goto error; 103134766Speter } 10324374Slars 103334766Speter /* Wakeup and enable firmaware */ 103428597Speter rv = mbox_send_cmd(sc, MBOX_CMD_MSG_ENABLED, 0); 103528597Speter if (rv != 0) { 103628597Speter device_printf(sc->dev, "Could not enable XUSB firmware\n"); 103728597Speter goto error; 103828597Speter } 103928597Speter 104028597Speter /* Fill data for XHCI driver. */ 104128597Speter xsc->sc_bus.parent = dev; 104228597Speter xsc->sc_bus.devices = xsc->sc_devices; 104328597Speter xsc->sc_bus.devices_max = XHCI_MAX_DEVICES; 104434766Speter 104528597Speter xsc->sc_io_tag = rman_get_bustag(xsc->sc_io_res); 104628597Speter xsc->sc_io_hdl = rman_get_bushandle(xsc->sc_io_res); 104734766Speter xsc->sc_io_size = rman_get_size(xsc->sc_io_res); 104834766Speter strlcpy(xsc->sc_vendor, "Nvidia", sizeof(xsc->sc_vendor)); 104934766Speter 105034766Speter /* Add USB bus device. */ 105134766Speter xsc->sc_bus.bdev = device_add_child(sc->dev, "usbus", -1); 105234766Speter if (xsc->sc_bus.bdev == NULL) { 105334766Speter device_printf(sc->dev, "Could not add USB device\n"); 105434766Speter rv = ENXIO; 105528597Speter goto error; 105634766Speter } 105728597Speter device_set_ivars(xsc->sc_bus.bdev, &xsc->sc_bus); 105834766Speter device_set_desc(xsc->sc_bus.bdev, "Nvidia USB 3.0 controller"); 105934766Speter 106028597Speter rv = xhci_init(xsc, sc->dev, 1); 106128597Speter if (rv != 0) { 106234766Speter device_printf(sc->dev, "USB init failed: %d\n", rv); 106328597Speter goto error; 106434766Speter } 106511990Speter sc->xhci_inited = true; 106611990Speter rv = xhci_start_controller(xsc); 106711990Speter if (rv != 0) { 106811990Speter device_printf(sc->dev, 106911990Speter "Could not start XHCI controller: %d\n", rv); 10704374Slars goto error; 107111990Speter } 107234766Speter 107334766Speter rv = bus_setup_intr(dev, sc->irq_res_mbox, INTR_TYPE_MISC | INTR_MPSAFE, 107411990Speter NULL, intr_mbox, sc, &sc->irq_hdl_mbox); 107534766Speter if (rv != 0) { 107611990Speter device_printf(dev, "Could not setup error IRQ: %d\n",rv); 107711990Speter xsc->sc_intr_hdl = NULL; 107811990Speter goto error; 107934766Speter } 108034766Speter 108111990Speter rv = bus_setup_intr(dev, xsc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 108211990Speter NULL, (driver_intr_t *)xhci_interrupt, xsc, &xsc->sc_intr_hdl); 108334766Speter if (rv != 0) { 108434766Speter device_printf(dev, "Could not setup error IRQ: %d\n",rv); 10854374Slars xsc->sc_intr_hdl = NULL; 10864374Slars goto error; 108734766Speter } 10884374Slars 10894374Slars /* Probe the bus. */ 10904374Slars rv = device_probe_and_attach(xsc->sc_bus.bdev); 109180381Ssheldonh if (rv != 0) { 10924374Slars device_printf(sc->dev, "Could not initialize USB: %d\n", rv); 109334766Speter goto error; 109411990Speter } 109511990Speter 10964374Slars return (0); 109711990Speter 109834766Spetererror: 10994374Slarspanic("XXXXX"); 110011990Speter tegra_xhci_detach(dev); 110111990Speter return (rv); 110234766Speter} 110334766Speter 110434766Speterstatic device_method_t xhci_methods[] = { 110534766Speter /* Device interface */ 110611990Speter DEVMETHOD(device_probe, tegra_xhci_probe), 110711990Speter DEVMETHOD(device_attach, tegra_xhci_attach), 11084374Slars DEVMETHOD(device_detach, tegra_xhci_detach), 110934766Speter DEVMETHOD(device_suspend, bus_generic_suspend), 11104374Slars DEVMETHOD(device_resume, bus_generic_resume), 11114374Slars DEVMETHOD(device_shutdown, bus_generic_shutdown), 111211990Speter 111334766Speter /* Bus interface */ 11144374Slars DEVMETHOD(bus_print_child, bus_generic_print_child), 111511990Speter 11164374Slars DEVMETHOD_END 111711990Speter}; 11184374Slars 111980381Ssheldonhstatic DEFINE_CLASS_0(xhci, xhci_driver, xhci_methods, 11204374Slars sizeof(struct tegra_xhci_softc)); 112134766SpeterDRIVER_MODULE(tegra_xhci, simplebus, xhci_driver, NULL, NULL); 112211990SpeterMODULE_DEPEND(tegra_xhci, usb, 1, 1, 1); 112311990Speter