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