usb: host: xhci-tegra: Add Tegra234 XHCI support
This change adds Tegra234 XUSB host mode controller support. In Tegra234, some of the registers have moved to bar2 space. The new soc variable has_bar2 indicates the chip with bar2 area. This patch adds new reg helper to let the driver reuse the same code for those chips with bar2 support. Signed-off-by: Sing-Han Chen <singhanc@nvidia.com> Co-developed-by: Wayne Chang <waynec@nvidia.com> Signed-off-by: Wayne Chang <waynec@nvidia.com> Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Link: https://lore.kernel.org/r/20230111110450.24617-7-jonathanh@nvidia.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d8163a32ca
commit
ee0e40efc4
|
@ -44,6 +44,9 @@
|
|||
#define XUSB_CFG_4 0x010
|
||||
#define XUSB_BASE_ADDR_SHIFT 15
|
||||
#define XUSB_BASE_ADDR_MASK 0x1ffff
|
||||
#define XUSB_CFG_7 0x01c
|
||||
#define XUSB_BASE2_ADDR_SHIFT 16
|
||||
#define XUSB_BASE2_ADDR_MASK 0xffff
|
||||
#define XUSB_CFG_16 0x040
|
||||
#define XUSB_CFG_24 0x060
|
||||
#define XUSB_CFG_AXI_CFG 0x0f8
|
||||
|
@ -75,6 +78,20 @@
|
|||
#define MBOX_SMI_INTR_FW_HANG BIT(1)
|
||||
#define MBOX_SMI_INTR_EN BIT(3)
|
||||
|
||||
/* BAR2 registers */
|
||||
#define XUSB_BAR2_ARU_MBOX_CMD 0x004
|
||||
#define XUSB_BAR2_ARU_MBOX_DATA_IN 0x008
|
||||
#define XUSB_BAR2_ARU_MBOX_DATA_OUT 0x00c
|
||||
#define XUSB_BAR2_ARU_MBOX_OWNER 0x010
|
||||
#define XUSB_BAR2_ARU_SMI_INTR 0x014
|
||||
#define XUSB_BAR2_ARU_SMI_ARU_FW_SCRATCH_DATA0 0x01c
|
||||
#define XUSB_BAR2_ARU_IFRDMA_CFG0 0x0e0
|
||||
#define XUSB_BAR2_ARU_IFRDMA_CFG1 0x0e4
|
||||
#define XUSB_BAR2_ARU_IFRDMA_STREAMID_FIELD 0x0e8
|
||||
#define XUSB_BAR2_ARU_C11_CSBRANGE 0x9c
|
||||
#define XUSB_BAR2_ARU_FW_SCRATCH 0x1000
|
||||
#define XUSB_BAR2_CSB_BASE_ADDR 0x2000
|
||||
|
||||
/* IPFS registers */
|
||||
#define IPFS_XUSB_HOST_MSI_BAR_SZ_0 0x0c0
|
||||
#define IPFS_XUSB_HOST_MSI_AXI_BAR_ST_0 0x0c4
|
||||
|
@ -111,6 +128,9 @@
|
|||
#define IMFILLRNG1_TAG_HI_SHIFT 16
|
||||
#define XUSB_FALC_IMFILLCTL 0x158
|
||||
|
||||
/* CSB ARU registers */
|
||||
#define XUSB_CSB_ARU_SCRATCH0 0x100100
|
||||
|
||||
/* MP CSB registers */
|
||||
#define XUSB_CSB_MP_ILOAD_ATTR 0x101a00
|
||||
#define XUSB_CSB_MP_ILOAD_BASE_LO 0x101a04
|
||||
|
@ -131,6 +151,9 @@
|
|||
|
||||
#define IMEM_BLOCK_SIZE 256
|
||||
|
||||
#define FW_IOCTL_TYPE_SHIFT 24
|
||||
#define FW_IOCTL_CFGTBL_READ 17
|
||||
|
||||
struct tegra_xusb_fw_header {
|
||||
__le32 boot_loadaddr_in_imem;
|
||||
__le32 boot_codedfi_offset;
|
||||
|
@ -175,6 +198,7 @@ struct tegra_xusb_mbox_regs {
|
|||
u16 data_in;
|
||||
u16 data_out;
|
||||
u16 owner;
|
||||
u16 smi_intr;
|
||||
};
|
||||
|
||||
struct tegra_xusb_context_soc {
|
||||
|
@ -189,6 +213,14 @@ struct tegra_xusb_context_soc {
|
|||
} fpci;
|
||||
};
|
||||
|
||||
struct tegra_xusb;
|
||||
struct tegra_xusb_soc_ops {
|
||||
u32 (*mbox_reg_readl)(struct tegra_xusb *tegra, unsigned int offset);
|
||||
void (*mbox_reg_writel)(struct tegra_xusb *tegra, u32 value, unsigned int offset);
|
||||
u32 (*csb_reg_readl)(struct tegra_xusb *tegra, unsigned int offset);
|
||||
void (*csb_reg_writel)(struct tegra_xusb *tegra, u32 value, unsigned int offset);
|
||||
};
|
||||
|
||||
struct tegra_xusb_soc {
|
||||
const char *firmware;
|
||||
const char * const *supply_names;
|
||||
|
@ -205,11 +237,14 @@ struct tegra_xusb_soc {
|
|||
} ports;
|
||||
|
||||
struct tegra_xusb_mbox_regs mbox;
|
||||
const struct tegra_xusb_soc_ops *ops;
|
||||
|
||||
bool scale_ss_clock;
|
||||
bool has_ipfs;
|
||||
bool lpm_support;
|
||||
bool otg_reset_sspi;
|
||||
|
||||
bool has_bar2;
|
||||
};
|
||||
|
||||
struct tegra_xusb_context {
|
||||
|
@ -230,6 +265,8 @@ struct tegra_xusb {
|
|||
|
||||
void __iomem *ipfs_base;
|
||||
void __iomem *fpci_base;
|
||||
void __iomem *bar2_base;
|
||||
struct resource *bar2;
|
||||
|
||||
const struct tegra_xusb_soc *soc;
|
||||
|
||||
|
@ -300,7 +337,33 @@ static inline void ipfs_writel(struct tegra_xusb *tegra, u32 value,
|
|||
writel(value, tegra->ipfs_base + offset);
|
||||
}
|
||||
|
||||
static inline u32 bar2_readl(struct tegra_xusb *tegra, unsigned int offset)
|
||||
{
|
||||
return readl(tegra->bar2_base + offset);
|
||||
}
|
||||
|
||||
static inline void bar2_writel(struct tegra_xusb *tegra, u32 value,
|
||||
unsigned int offset)
|
||||
{
|
||||
writel(value, tegra->bar2_base + offset);
|
||||
}
|
||||
|
||||
static u32 csb_readl(struct tegra_xusb *tegra, unsigned int offset)
|
||||
{
|
||||
const struct tegra_xusb_soc_ops *ops = tegra->soc->ops;
|
||||
|
||||
return ops->csb_reg_readl(tegra, offset);
|
||||
}
|
||||
|
||||
static void csb_writel(struct tegra_xusb *tegra, u32 value,
|
||||
unsigned int offset)
|
||||
{
|
||||
const struct tegra_xusb_soc_ops *ops = tegra->soc->ops;
|
||||
|
||||
ops->csb_reg_writel(tegra, value, offset);
|
||||
}
|
||||
|
||||
static u32 fpci_csb_readl(struct tegra_xusb *tegra, unsigned int offset)
|
||||
{
|
||||
u32 page = CSB_PAGE_SELECT(offset);
|
||||
u32 ofs = CSB_PAGE_OFFSET(offset);
|
||||
|
@ -310,8 +373,8 @@ static u32 csb_readl(struct tegra_xusb *tegra, unsigned int offset)
|
|||
return fpci_readl(tegra, XUSB_CFG_CSB_BASE_ADDR + ofs);
|
||||
}
|
||||
|
||||
static void csb_writel(struct tegra_xusb *tegra, u32 value,
|
||||
unsigned int offset)
|
||||
static void fpci_csb_writel(struct tegra_xusb *tegra, u32 value,
|
||||
unsigned int offset)
|
||||
{
|
||||
u32 page = CSB_PAGE_SELECT(offset);
|
||||
u32 ofs = CSB_PAGE_OFFSET(offset);
|
||||
|
@ -320,6 +383,26 @@ static void csb_writel(struct tegra_xusb *tegra, u32 value,
|
|||
fpci_writel(tegra, value, XUSB_CFG_CSB_BASE_ADDR + ofs);
|
||||
}
|
||||
|
||||
static u32 bar2_csb_readl(struct tegra_xusb *tegra, unsigned int offset)
|
||||
{
|
||||
u32 page = CSB_PAGE_SELECT(offset);
|
||||
u32 ofs = CSB_PAGE_OFFSET(offset);
|
||||
|
||||
bar2_writel(tegra, page, XUSB_BAR2_ARU_C11_CSBRANGE);
|
||||
|
||||
return bar2_readl(tegra, XUSB_BAR2_CSB_BASE_ADDR + ofs);
|
||||
}
|
||||
|
||||
static void bar2_csb_writel(struct tegra_xusb *tegra, u32 value,
|
||||
unsigned int offset)
|
||||
{
|
||||
u32 page = CSB_PAGE_SELECT(offset);
|
||||
u32 ofs = CSB_PAGE_OFFSET(offset);
|
||||
|
||||
bar2_writel(tegra, page, XUSB_BAR2_ARU_C11_CSBRANGE);
|
||||
bar2_writel(tegra, value, XUSB_BAR2_CSB_BASE_ADDR + ofs);
|
||||
}
|
||||
|
||||
static int tegra_xusb_set_ss_clk(struct tegra_xusb *tegra,
|
||||
unsigned long rate)
|
||||
{
|
||||
|
@ -451,6 +534,7 @@ static bool tegra_xusb_mbox_cmd_requires_ack(enum tegra_xusb_mbox_cmd cmd)
|
|||
static int tegra_xusb_mbox_send(struct tegra_xusb *tegra,
|
||||
const struct tegra_xusb_mbox_msg *msg)
|
||||
{
|
||||
const struct tegra_xusb_soc_ops *ops = tegra->soc->ops;
|
||||
bool wait_for_idle = false;
|
||||
u32 value;
|
||||
|
||||
|
@ -459,15 +543,15 @@ static int tegra_xusb_mbox_send(struct tegra_xusb *tegra,
|
|||
* ACK/NAK messages.
|
||||
*/
|
||||
if (!(msg->cmd == MBOX_CMD_ACK || msg->cmd == MBOX_CMD_NAK)) {
|
||||
value = fpci_readl(tegra, tegra->soc->mbox.owner);
|
||||
value = ops->mbox_reg_readl(tegra, tegra->soc->mbox.owner);
|
||||
if (value != MBOX_OWNER_NONE) {
|
||||
dev_err(tegra->dev, "mailbox is busy\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
fpci_writel(tegra, MBOX_OWNER_SW, tegra->soc->mbox.owner);
|
||||
ops->mbox_reg_writel(tegra, MBOX_OWNER_SW, tegra->soc->mbox.owner);
|
||||
|
||||
value = fpci_readl(tegra, tegra->soc->mbox.owner);
|
||||
value = ops->mbox_reg_readl(tegra, tegra->soc->mbox.owner);
|
||||
if (value != MBOX_OWNER_SW) {
|
||||
dev_err(tegra->dev, "failed to acquire mailbox\n");
|
||||
return -EBUSY;
|
||||
|
@ -477,17 +561,17 @@ static int tegra_xusb_mbox_send(struct tegra_xusb *tegra,
|
|||
}
|
||||
|
||||
value = tegra_xusb_mbox_pack(msg);
|
||||
fpci_writel(tegra, value, tegra->soc->mbox.data_in);
|
||||
ops->mbox_reg_writel(tegra, value, tegra->soc->mbox.data_in);
|
||||
|
||||
value = fpci_readl(tegra, tegra->soc->mbox.cmd);
|
||||
value = ops->mbox_reg_readl(tegra, tegra->soc->mbox.cmd);
|
||||
value |= MBOX_INT_EN | MBOX_DEST_FALC;
|
||||
fpci_writel(tegra, value, tegra->soc->mbox.cmd);
|
||||
ops->mbox_reg_writel(tegra, value, tegra->soc->mbox.cmd);
|
||||
|
||||
if (wait_for_idle) {
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(250);
|
||||
|
||||
while (time_before(jiffies, timeout)) {
|
||||
value = fpci_readl(tegra, tegra->soc->mbox.owner);
|
||||
value = ops->mbox_reg_readl(tegra, tegra->soc->mbox.owner);
|
||||
if (value == MBOX_OWNER_NONE)
|
||||
break;
|
||||
|
||||
|
@ -495,7 +579,7 @@ static int tegra_xusb_mbox_send(struct tegra_xusb *tegra,
|
|||
}
|
||||
|
||||
if (time_after(jiffies, timeout))
|
||||
value = fpci_readl(tegra, tegra->soc->mbox.owner);
|
||||
value = ops->mbox_reg_readl(tegra, tegra->soc->mbox.owner);
|
||||
|
||||
if (value != MBOX_OWNER_NONE)
|
||||
return -ETIMEDOUT;
|
||||
|
@ -507,11 +591,12 @@ static int tegra_xusb_mbox_send(struct tegra_xusb *tegra,
|
|||
static irqreturn_t tegra_xusb_mbox_irq(int irq, void *data)
|
||||
{
|
||||
struct tegra_xusb *tegra = data;
|
||||
const struct tegra_xusb_soc_ops *ops = tegra->soc->ops;
|
||||
u32 value;
|
||||
|
||||
/* clear mailbox interrupts */
|
||||
value = fpci_readl(tegra, XUSB_CFG_ARU_SMI_INTR);
|
||||
fpci_writel(tegra, value, XUSB_CFG_ARU_SMI_INTR);
|
||||
value = ops->mbox_reg_readl(tegra, tegra->soc->mbox.smi_intr);
|
||||
ops->mbox_reg_writel(tegra, value, tegra->soc->mbox.smi_intr);
|
||||
|
||||
if (value & MBOX_SMI_INTR_FW_HANG)
|
||||
dev_err(tegra->dev, "controller firmware hang\n");
|
||||
|
@ -664,6 +749,7 @@ static void tegra_xusb_mbox_handle(struct tegra_xusb *tegra,
|
|||
static irqreturn_t tegra_xusb_mbox_thread(int irq, void *data)
|
||||
{
|
||||
struct tegra_xusb *tegra = data;
|
||||
const struct tegra_xusb_soc_ops *ops = tegra->soc->ops;
|
||||
struct tegra_xusb_mbox_msg msg;
|
||||
u32 value;
|
||||
|
||||
|
@ -672,16 +758,16 @@ static irqreturn_t tegra_xusb_mbox_thread(int irq, void *data)
|
|||
if (pm_runtime_suspended(tegra->dev) || tegra->suspended)
|
||||
goto out;
|
||||
|
||||
value = fpci_readl(tegra, tegra->soc->mbox.data_out);
|
||||
value = ops->mbox_reg_readl(tegra, tegra->soc->mbox.data_out);
|
||||
tegra_xusb_mbox_unpack(&msg, value);
|
||||
|
||||
value = fpci_readl(tegra, tegra->soc->mbox.cmd);
|
||||
value = ops->mbox_reg_readl(tegra, tegra->soc->mbox.cmd);
|
||||
value &= ~MBOX_DEST_SMI;
|
||||
fpci_writel(tegra, value, tegra->soc->mbox.cmd);
|
||||
ops->mbox_reg_writel(tegra, value, tegra->soc->mbox.cmd);
|
||||
|
||||
/* clear mailbox owner if no ACK/NAK is required */
|
||||
if (!tegra_xusb_mbox_cmd_requires_ack(msg.cmd))
|
||||
fpci_writel(tegra, MBOX_OWNER_NONE, tegra->soc->mbox.owner);
|
||||
ops->mbox_reg_writel(tegra, MBOX_OWNER_NONE, tegra->soc->mbox.owner);
|
||||
|
||||
tegra_xusb_mbox_handle(tegra, &msg);
|
||||
|
||||
|
@ -709,6 +795,15 @@ static void tegra_xusb_config(struct tegra_xusb *tegra)
|
|||
value |= regs & (XUSB_BASE_ADDR_MASK << XUSB_BASE_ADDR_SHIFT);
|
||||
fpci_writel(tegra, value, XUSB_CFG_4);
|
||||
|
||||
/* Program BAR2 space */
|
||||
if (tegra->bar2) {
|
||||
value = fpci_readl(tegra, XUSB_CFG_7);
|
||||
value &= ~(XUSB_BASE2_ADDR_MASK << XUSB_BASE2_ADDR_SHIFT);
|
||||
value |= tegra->bar2->start &
|
||||
(XUSB_BASE2_ADDR_MASK << XUSB_BASE2_ADDR_SHIFT);
|
||||
fpci_writel(tegra, value, XUSB_CFG_7);
|
||||
}
|
||||
|
||||
usleep_range(100, 200);
|
||||
|
||||
/* Enable bus master */
|
||||
|
@ -881,21 +976,36 @@ static int tegra_xusb_request_firmware(struct tegra_xusb *tegra)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_xusb_load_firmware(struct tegra_xusb *tegra)
|
||||
static int tegra_xusb_wait_for_falcon(struct tegra_xusb *tegra)
|
||||
{
|
||||
struct xhci_cap_regs __iomem *cap_regs;
|
||||
struct xhci_op_regs __iomem *op_regs;
|
||||
int ret;
|
||||
u32 value;
|
||||
|
||||
cap_regs = tegra->regs;
|
||||
op_regs = tegra->regs + HC_LENGTH(readl(&cap_regs->hc_capbase));
|
||||
|
||||
ret = readl_poll_timeout(&op_regs->status, value, !(value & STS_CNR), 1000, 200000);
|
||||
|
||||
if (ret)
|
||||
dev_err(tegra->dev, "XHCI Controller not ready. Falcon state: 0x%x\n",
|
||||
csb_readl(tegra, XUSB_FALC_CPUCTL));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tegra_xusb_load_firmware_rom(struct tegra_xusb *tegra)
|
||||
{
|
||||
unsigned int code_tag_blocks, code_size_blocks, code_blocks;
|
||||
struct xhci_cap_regs __iomem *cap = tegra->regs;
|
||||
struct tegra_xusb_fw_header *header;
|
||||
struct device *dev = tegra->dev;
|
||||
struct xhci_op_regs __iomem *op;
|
||||
unsigned long timeout;
|
||||
time64_t timestamp;
|
||||
u64 address;
|
||||
u32 value;
|
||||
int err;
|
||||
|
||||
header = (struct tegra_xusb_fw_header *)tegra->fw.virt;
|
||||
op = tegra->regs + HC_LENGTH(readl(&cap->hc_capbase));
|
||||
|
||||
if (csb_readl(tegra, XUSB_CSB_MP_ILOAD_BASE_LO) != 0) {
|
||||
dev_info(dev, "Firmware already loaded, Falcon state %#x\n",
|
||||
|
@ -968,22 +1078,8 @@ static int tegra_xusb_load_firmware(struct tegra_xusb *tegra)
|
|||
/* Boot Falcon CPU and wait for USBSTS_CNR to get cleared. */
|
||||
csb_writel(tegra, CPUCTL_STARTCPU, XUSB_FALC_CPUCTL);
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(200);
|
||||
|
||||
do {
|
||||
value = readl(&op->status);
|
||||
if ((value & STS_CNR) == 0)
|
||||
break;
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
} while (time_is_after_jiffies(timeout));
|
||||
|
||||
value = readl(&op->status);
|
||||
if (value & STS_CNR) {
|
||||
value = csb_readl(tegra, XUSB_FALC_CPUCTL);
|
||||
dev_err(dev, "XHCI controller not read: %#010x\n", value);
|
||||
if (tegra_xusb_wait_for_falcon(tegra))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
timestamp = le32_to_cpu(header->fwimg_created_time);
|
||||
|
||||
|
@ -992,6 +1088,44 @@ static int tegra_xusb_load_firmware(struct tegra_xusb *tegra)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u32 tegra_xusb_read_firmware_header(struct tegra_xusb *tegra, u32 offset)
|
||||
{
|
||||
/*
|
||||
* We only accept reading the firmware config table
|
||||
* The offset should not exceed the fw header structure
|
||||
*/
|
||||
if (offset >= sizeof(struct tegra_xusb_fw_header))
|
||||
return 0;
|
||||
|
||||
bar2_writel(tegra, (FW_IOCTL_CFGTBL_READ << FW_IOCTL_TYPE_SHIFT) | offset,
|
||||
XUSB_BAR2_ARU_FW_SCRATCH);
|
||||
return bar2_readl(tegra, XUSB_BAR2_ARU_SMI_ARU_FW_SCRATCH_DATA0);
|
||||
}
|
||||
|
||||
static int tegra_xusb_init_ifr_firmware(struct tegra_xusb *tegra)
|
||||
{
|
||||
time64_t timestamp;
|
||||
|
||||
if (tegra_xusb_wait_for_falcon(tegra))
|
||||
return -EIO;
|
||||
|
||||
#define offsetof_32(X, Y) ((u8)(offsetof(X, Y) / sizeof(__le32)))
|
||||
timestamp = tegra_xusb_read_firmware_header(tegra, offsetof_32(struct tegra_xusb_fw_header,
|
||||
fwimg_created_time) << 2);
|
||||
|
||||
dev_info(tegra->dev, "Firmware timestamp: %ptTs UTC\n", ×tamp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_xusb_load_firmware(struct tegra_xusb *tegra)
|
||||
{
|
||||
if (!tegra->soc->firmware)
|
||||
return tegra_xusb_init_ifr_firmware(tegra);
|
||||
else
|
||||
return tegra_xusb_load_firmware_rom(tegra);
|
||||
}
|
||||
|
||||
static void tegra_xusb_powerdomain_remove(struct device *dev,
|
||||
struct tegra_xusb *tegra)
|
||||
{
|
||||
|
@ -1435,6 +1569,10 @@ static int tegra_xusb_probe(struct platform_device *pdev)
|
|||
tegra->ipfs_base = devm_platform_ioremap_resource(pdev, 2);
|
||||
if (IS_ERR(tegra->ipfs_base))
|
||||
return PTR_ERR(tegra->ipfs_base);
|
||||
} else if (tegra->soc->has_bar2) {
|
||||
tegra->bar2_base = devm_platform_get_and_ioremap_resource(pdev, 2, &tegra->bar2);
|
||||
if (IS_ERR(tegra->bar2_base))
|
||||
return PTR_ERR(tegra->bar2_base);
|
||||
}
|
||||
|
||||
tegra->xhci_irq = platform_get_irq(pdev, 0);
|
||||
|
@ -1651,10 +1789,13 @@ static int tegra_xusb_probe(struct platform_device *pdev)
|
|||
goto disable_phy;
|
||||
}
|
||||
|
||||
err = tegra_xusb_request_firmware(tegra);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to request firmware: %d\n", err);
|
||||
goto disable_phy;
|
||||
if (tegra->soc->firmware) {
|
||||
err = tegra_xusb_request_firmware(tegra);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed to request firmware: %d\n", err);
|
||||
goto disable_phy;
|
||||
}
|
||||
}
|
||||
|
||||
err = tegra_xusb_unpowergate_partitions(tegra);
|
||||
|
@ -2271,6 +2412,13 @@ static const struct tegra_xusb_context_soc tegra124_xusb_context = {
|
|||
},
|
||||
};
|
||||
|
||||
static const struct tegra_xusb_soc_ops tegra124_ops = {
|
||||
.mbox_reg_readl = &fpci_readl,
|
||||
.mbox_reg_writel = &fpci_writel,
|
||||
.csb_reg_readl = &fpci_csb_readl,
|
||||
.csb_reg_writel = &fpci_csb_writel,
|
||||
};
|
||||
|
||||
static const struct tegra_xusb_soc tegra124_soc = {
|
||||
.firmware = "nvidia/tegra124/xusb.bin",
|
||||
.supply_names = tegra124_supply_names,
|
||||
|
@ -2286,11 +2434,13 @@ static const struct tegra_xusb_soc tegra124_soc = {
|
|||
.scale_ss_clock = true,
|
||||
.has_ipfs = true,
|
||||
.otg_reset_sspi = false,
|
||||
.ops = &tegra124_ops,
|
||||
.mbox = {
|
||||
.cmd = 0xe4,
|
||||
.data_in = 0xe8,
|
||||
.data_out = 0xec,
|
||||
.owner = 0xf0,
|
||||
.smi_intr = XUSB_CFG_ARU_SMI_INTR,
|
||||
},
|
||||
};
|
||||
MODULE_FIRMWARE("nvidia/tegra124/xusb.bin");
|
||||
|
@ -2322,11 +2472,13 @@ static const struct tegra_xusb_soc tegra210_soc = {
|
|||
.scale_ss_clock = false,
|
||||
.has_ipfs = true,
|
||||
.otg_reset_sspi = true,
|
||||
.ops = &tegra124_ops,
|
||||
.mbox = {
|
||||
.cmd = 0xe4,
|
||||
.data_in = 0xe8,
|
||||
.data_out = 0xec,
|
||||
.owner = 0xf0,
|
||||
.smi_intr = XUSB_CFG_ARU_SMI_INTR,
|
||||
},
|
||||
};
|
||||
MODULE_FIRMWARE("nvidia/tegra210/xusb.bin");
|
||||
|
@ -2363,11 +2515,13 @@ static const struct tegra_xusb_soc tegra186_soc = {
|
|||
.scale_ss_clock = false,
|
||||
.has_ipfs = false,
|
||||
.otg_reset_sspi = false,
|
||||
.ops = &tegra124_ops,
|
||||
.mbox = {
|
||||
.cmd = 0xe4,
|
||||
.data_in = 0xe8,
|
||||
.data_out = 0xec,
|
||||
.owner = 0xf0,
|
||||
.smi_intr = XUSB_CFG_ARU_SMI_INTR,
|
||||
},
|
||||
.lpm_support = true,
|
||||
};
|
||||
|
@ -2394,21 +2548,56 @@ static const struct tegra_xusb_soc tegra194_soc = {
|
|||
.scale_ss_clock = false,
|
||||
.has_ipfs = false,
|
||||
.otg_reset_sspi = false,
|
||||
.ops = &tegra124_ops,
|
||||
.mbox = {
|
||||
.cmd = 0x68,
|
||||
.data_in = 0x6c,
|
||||
.data_out = 0x70,
|
||||
.owner = 0x74,
|
||||
.smi_intr = XUSB_CFG_ARU_SMI_INTR,
|
||||
},
|
||||
.lpm_support = true,
|
||||
};
|
||||
MODULE_FIRMWARE("nvidia/tegra194/xusb.bin");
|
||||
|
||||
static const struct tegra_xusb_soc_ops tegra234_ops = {
|
||||
.mbox_reg_readl = &bar2_readl,
|
||||
.mbox_reg_writel = &bar2_writel,
|
||||
.csb_reg_readl = &bar2_csb_readl,
|
||||
.csb_reg_writel = &bar2_csb_writel,
|
||||
};
|
||||
|
||||
static const struct tegra_xusb_soc tegra234_soc = {
|
||||
.supply_names = tegra194_supply_names,
|
||||
.num_supplies = ARRAY_SIZE(tegra194_supply_names),
|
||||
.phy_types = tegra194_phy_types,
|
||||
.num_types = ARRAY_SIZE(tegra194_phy_types),
|
||||
.context = &tegra186_xusb_context,
|
||||
.ports = {
|
||||
.usb3 = { .offset = 0, .count = 4, },
|
||||
.usb2 = { .offset = 4, .count = 4, },
|
||||
},
|
||||
.scale_ss_clock = false,
|
||||
.has_ipfs = false,
|
||||
.otg_reset_sspi = false,
|
||||
.ops = &tegra234_ops,
|
||||
.mbox = {
|
||||
.cmd = XUSB_BAR2_ARU_MBOX_CMD,
|
||||
.data_in = XUSB_BAR2_ARU_MBOX_DATA_IN,
|
||||
.data_out = XUSB_BAR2_ARU_MBOX_DATA_OUT,
|
||||
.owner = XUSB_BAR2_ARU_MBOX_OWNER,
|
||||
.smi_intr = XUSB_BAR2_ARU_SMI_INTR,
|
||||
},
|
||||
.lpm_support = true,
|
||||
.has_bar2 = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_xusb_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra124-xusb", .data = &tegra124_soc },
|
||||
{ .compatible = "nvidia,tegra210-xusb", .data = &tegra210_soc },
|
||||
{ .compatible = "nvidia,tegra186-xusb", .data = &tegra186_soc },
|
||||
{ .compatible = "nvidia,tegra194-xusb", .data = &tegra194_soc },
|
||||
{ .compatible = "nvidia,tegra234-xusb", .data = &tegra234_soc },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_xusb_of_match);
|
||||
|
|
Loading…
Reference in New Issue