cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pcie-mobiveil-host.c (16709B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * PCIe host controller driver for Mobiveil PCIe Host controller
      4 *
      5 * Copyright (c) 2018 Mobiveil Inc.
      6 * Copyright 2019-2020 NXP
      7 *
      8 * Author: Subrahmanya Lingappa <l.subrahmanya@mobiveil.co.in>
      9 *	   Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
     10 */
     11
     12#include <linux/init.h>
     13#include <linux/interrupt.h>
     14#include <linux/irq.h>
     15#include <linux/irqchip/chained_irq.h>
     16#include <linux/irqdomain.h>
     17#include <linux/kernel.h>
     18#include <linux/module.h>
     19#include <linux/msi.h>
     20#include <linux/of_address.h>
     21#include <linux/of_irq.h>
     22#include <linux/of_platform.h>
     23#include <linux/of_pci.h>
     24#include <linux/pci.h>
     25#include <linux/platform_device.h>
     26#include <linux/slab.h>
     27
     28#include "pcie-mobiveil.h"
     29
     30static bool mobiveil_pcie_valid_device(struct pci_bus *bus, unsigned int devfn)
     31{
     32	/* Only one device down on each root port */
     33	if (pci_is_root_bus(bus) && (devfn > 0))
     34		return false;
     35
     36	/*
     37	 * Do not read more than one device on the bus directly
     38	 * attached to RC
     39	 */
     40	if ((bus->primary == to_pci_host_bridge(bus->bridge)->busnr) && (PCI_SLOT(devfn) > 0))
     41		return false;
     42
     43	return true;
     44}
     45
     46/*
     47 * mobiveil_pcie_map_bus - routine to get the configuration base of either
     48 * root port or endpoint
     49 */
     50static void __iomem *mobiveil_pcie_map_bus(struct pci_bus *bus,
     51					   unsigned int devfn, int where)
     52{
     53	struct mobiveil_pcie *pcie = bus->sysdata;
     54	struct mobiveil_root_port *rp = &pcie->rp;
     55	u32 value;
     56
     57	if (!mobiveil_pcie_valid_device(bus, devfn))
     58		return NULL;
     59
     60	/* RC config access */
     61	if (pci_is_root_bus(bus))
     62		return pcie->csr_axi_slave_base + where;
     63
     64	/*
     65	 * EP config access (in Config/APIO space)
     66	 * Program PEX Address base (31..16 bits) with appropriate value
     67	 * (BDF) in PAB_AXI_AMAP_PEX_WIN_L0 Register.
     68	 * Relies on pci_lock serialization
     69	 */
     70	value = bus->number << PAB_BUS_SHIFT |
     71		PCI_SLOT(devfn) << PAB_DEVICE_SHIFT |
     72		PCI_FUNC(devfn) << PAB_FUNCTION_SHIFT;
     73
     74	mobiveil_csr_writel(pcie, value, PAB_AXI_AMAP_PEX_WIN_L(WIN_NUM_0));
     75
     76	return rp->config_axi_slave_base + where;
     77}
     78
     79static struct pci_ops mobiveil_pcie_ops = {
     80	.map_bus = mobiveil_pcie_map_bus,
     81	.read = pci_generic_config_read,
     82	.write = pci_generic_config_write,
     83};
     84
     85static void mobiveil_pcie_isr(struct irq_desc *desc)
     86{
     87	struct irq_chip *chip = irq_desc_get_chip(desc);
     88	struct mobiveil_pcie *pcie = irq_desc_get_handler_data(desc);
     89	struct device *dev = &pcie->pdev->dev;
     90	struct mobiveil_root_port *rp = &pcie->rp;
     91	struct mobiveil_msi *msi = &rp->msi;
     92	u32 msi_data, msi_addr_lo, msi_addr_hi;
     93	u32 intr_status, msi_status;
     94	unsigned long shifted_status;
     95	u32 bit, val, mask;
     96
     97	/*
     98	 * The core provides a single interrupt for both INTx/MSI messages.
     99	 * So we'll read both INTx and MSI status
    100	 */
    101
    102	chained_irq_enter(chip, desc);
    103
    104	/* read INTx status */
    105	val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_STAT);
    106	mask = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
    107	intr_status = val & mask;
    108
    109	/* Handle INTx */
    110	if (intr_status & PAB_INTP_INTX_MASK) {
    111		shifted_status = mobiveil_csr_readl(pcie,
    112						    PAB_INTP_AMBA_MISC_STAT);
    113		shifted_status &= PAB_INTP_INTX_MASK;
    114		shifted_status >>= PAB_INTX_START;
    115		do {
    116			for_each_set_bit(bit, &shifted_status, PCI_NUM_INTX) {
    117				int ret;
    118				ret = generic_handle_domain_irq(rp->intx_domain,
    119								bit + 1);
    120				if (ret)
    121					dev_err_ratelimited(dev, "unexpected IRQ, INT%d\n",
    122							    bit);
    123
    124				/* clear interrupt handled */
    125				mobiveil_csr_writel(pcie,
    126						    1 << (PAB_INTX_START + bit),
    127						    PAB_INTP_AMBA_MISC_STAT);
    128			}
    129
    130			shifted_status = mobiveil_csr_readl(pcie,
    131							    PAB_INTP_AMBA_MISC_STAT);
    132			shifted_status &= PAB_INTP_INTX_MASK;
    133			shifted_status >>= PAB_INTX_START;
    134		} while (shifted_status != 0);
    135	}
    136
    137	/* read extra MSI status register */
    138	msi_status = readl_relaxed(pcie->apb_csr_base + MSI_STATUS_OFFSET);
    139
    140	/* handle MSI interrupts */
    141	while (msi_status & 1) {
    142		msi_data = readl_relaxed(pcie->apb_csr_base + MSI_DATA_OFFSET);
    143
    144		/*
    145		 * MSI_STATUS_OFFSET register gets updated to zero
    146		 * once we pop not only the MSI data but also address
    147		 * from MSI hardware FIFO. So keeping these following
    148		 * two dummy reads.
    149		 */
    150		msi_addr_lo = readl_relaxed(pcie->apb_csr_base +
    151					    MSI_ADDR_L_OFFSET);
    152		msi_addr_hi = readl_relaxed(pcie->apb_csr_base +
    153					    MSI_ADDR_H_OFFSET);
    154		dev_dbg(dev, "MSI registers, data: %08x, addr: %08x:%08x\n",
    155			msi_data, msi_addr_hi, msi_addr_lo);
    156
    157		generic_handle_domain_irq(msi->dev_domain, msi_data);
    158
    159		msi_status = readl_relaxed(pcie->apb_csr_base +
    160					   MSI_STATUS_OFFSET);
    161	}
    162
    163	/* Clear the interrupt status */
    164	mobiveil_csr_writel(pcie, intr_status, PAB_INTP_AMBA_MISC_STAT);
    165	chained_irq_exit(chip, desc);
    166}
    167
    168static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie)
    169{
    170	struct device *dev = &pcie->pdev->dev;
    171	struct platform_device *pdev = pcie->pdev;
    172	struct device_node *node = dev->of_node;
    173	struct mobiveil_root_port *rp = &pcie->rp;
    174	struct resource *res;
    175
    176	/* map config resource */
    177	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
    178					   "config_axi_slave");
    179	rp->config_axi_slave_base = devm_pci_remap_cfg_resource(dev, res);
    180	if (IS_ERR(rp->config_axi_slave_base))
    181		return PTR_ERR(rp->config_axi_slave_base);
    182	rp->ob_io_res = res;
    183
    184	/* map csr resource */
    185	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
    186					   "csr_axi_slave");
    187	pcie->csr_axi_slave_base = devm_pci_remap_cfg_resource(dev, res);
    188	if (IS_ERR(pcie->csr_axi_slave_base))
    189		return PTR_ERR(pcie->csr_axi_slave_base);
    190	pcie->pcie_reg_base = res->start;
    191
    192	/* read the number of windows requested */
    193	if (of_property_read_u32(node, "apio-wins", &pcie->apio_wins))
    194		pcie->apio_wins = MAX_PIO_WINDOWS;
    195
    196	if (of_property_read_u32(node, "ppio-wins", &pcie->ppio_wins))
    197		pcie->ppio_wins = MAX_PIO_WINDOWS;
    198
    199	return 0;
    200}
    201
    202static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie)
    203{
    204	phys_addr_t msg_addr = pcie->pcie_reg_base;
    205	struct mobiveil_msi *msi = &pcie->rp.msi;
    206
    207	msi->num_of_vectors = PCI_NUM_MSI;
    208	msi->msi_pages_phys = (phys_addr_t)msg_addr;
    209
    210	writel_relaxed(lower_32_bits(msg_addr),
    211		       pcie->apb_csr_base + MSI_BASE_LO_OFFSET);
    212	writel_relaxed(upper_32_bits(msg_addr),
    213		       pcie->apb_csr_base + MSI_BASE_HI_OFFSET);
    214	writel_relaxed(4096, pcie->apb_csr_base + MSI_SIZE_OFFSET);
    215	writel_relaxed(1, pcie->apb_csr_base + MSI_ENABLE_OFFSET);
    216}
    217
    218int mobiveil_host_init(struct mobiveil_pcie *pcie, bool reinit)
    219{
    220	struct mobiveil_root_port *rp = &pcie->rp;
    221	struct pci_host_bridge *bridge = rp->bridge;
    222	u32 value, pab_ctrl, type;
    223	struct resource_entry *win;
    224
    225	pcie->ib_wins_configured = 0;
    226	pcie->ob_wins_configured = 0;
    227
    228	if (!reinit) {
    229		/* setup bus numbers */
    230		value = mobiveil_csr_readl(pcie, PCI_PRIMARY_BUS);
    231		value &= 0xff000000;
    232		value |= 0x00ff0100;
    233		mobiveil_csr_writel(pcie, value, PCI_PRIMARY_BUS);
    234	}
    235
    236	/*
    237	 * program Bus Master Enable Bit in Command Register in PAB Config
    238	 * Space
    239	 */
    240	value = mobiveil_csr_readl(pcie, PCI_COMMAND);
    241	value |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
    242	mobiveil_csr_writel(pcie, value, PCI_COMMAND);
    243
    244	/*
    245	 * program PIO Enable Bit to 1 (and PEX PIO Enable to 1) in PAB_CTRL
    246	 * register
    247	 */
    248	pab_ctrl = mobiveil_csr_readl(pcie, PAB_CTRL);
    249	pab_ctrl |= (1 << AMBA_PIO_ENABLE_SHIFT) | (1 << PEX_PIO_ENABLE_SHIFT);
    250	mobiveil_csr_writel(pcie, pab_ctrl, PAB_CTRL);
    251
    252	/*
    253	 * program PIO Enable Bit to 1 and Config Window Enable Bit to 1 in
    254	 * PAB_AXI_PIO_CTRL Register
    255	 */
    256	value = mobiveil_csr_readl(pcie, PAB_AXI_PIO_CTRL);
    257	value |= APIO_EN_MASK;
    258	mobiveil_csr_writel(pcie, value, PAB_AXI_PIO_CTRL);
    259
    260	/* Enable PCIe PIO master */
    261	value = mobiveil_csr_readl(pcie, PAB_PEX_PIO_CTRL);
    262	value |= 1 << PIO_ENABLE_SHIFT;
    263	mobiveil_csr_writel(pcie, value, PAB_PEX_PIO_CTRL);
    264
    265	/*
    266	 * we'll program one outbound window for config reads and
    267	 * another default inbound window for all the upstream traffic
    268	 * rest of the outbound windows will be configured according to
    269	 * the "ranges" field defined in device tree
    270	 */
    271
    272	/* config outbound translation window */
    273	program_ob_windows(pcie, WIN_NUM_0, rp->ob_io_res->start, 0,
    274			   CFG_WINDOW_TYPE, resource_size(rp->ob_io_res));
    275
    276	/* memory inbound translation window */
    277	program_ib_windows(pcie, WIN_NUM_0, 0, 0, MEM_WINDOW_TYPE, IB_WIN_SIZE);
    278
    279	/* Get the I/O and memory ranges from DT */
    280	resource_list_for_each_entry(win, &bridge->windows) {
    281		if (resource_type(win->res) == IORESOURCE_MEM)
    282			type = MEM_WINDOW_TYPE;
    283		else if (resource_type(win->res) == IORESOURCE_IO)
    284			type = IO_WINDOW_TYPE;
    285		else
    286			continue;
    287
    288		/* configure outbound translation window */
    289		program_ob_windows(pcie, pcie->ob_wins_configured,
    290				   win->res->start,
    291				   win->res->start - win->offset,
    292				   type, resource_size(win->res));
    293	}
    294
    295	/* fixup for PCIe class register */
    296	value = mobiveil_csr_readl(pcie, PAB_INTP_AXI_PIO_CLASS);
    297	value &= 0xff;
    298	value |= PCI_CLASS_BRIDGE_PCI_NORMAL << 8;
    299	mobiveil_csr_writel(pcie, value, PAB_INTP_AXI_PIO_CLASS);
    300
    301	return 0;
    302}
    303
    304static void mobiveil_mask_intx_irq(struct irq_data *data)
    305{
    306	struct mobiveil_pcie *pcie = irq_data_get_irq_chip_data(data);
    307	struct mobiveil_root_port *rp;
    308	unsigned long flags;
    309	u32 mask, shifted_val;
    310
    311	rp = &pcie->rp;
    312	mask = 1 << ((data->hwirq + PAB_INTX_START) - 1);
    313	raw_spin_lock_irqsave(&rp->intx_mask_lock, flags);
    314	shifted_val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
    315	shifted_val &= ~mask;
    316	mobiveil_csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB);
    317	raw_spin_unlock_irqrestore(&rp->intx_mask_lock, flags);
    318}
    319
    320static void mobiveil_unmask_intx_irq(struct irq_data *data)
    321{
    322	struct mobiveil_pcie *pcie = irq_data_get_irq_chip_data(data);
    323	struct mobiveil_root_port *rp;
    324	unsigned long flags;
    325	u32 shifted_val, mask;
    326
    327	rp = &pcie->rp;
    328	mask = 1 << ((data->hwirq + PAB_INTX_START) - 1);
    329	raw_spin_lock_irqsave(&rp->intx_mask_lock, flags);
    330	shifted_val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
    331	shifted_val |= mask;
    332	mobiveil_csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB);
    333	raw_spin_unlock_irqrestore(&rp->intx_mask_lock, flags);
    334}
    335
    336static struct irq_chip intx_irq_chip = {
    337	.name = "mobiveil_pcie:intx",
    338	.irq_enable = mobiveil_unmask_intx_irq,
    339	.irq_disable = mobiveil_mask_intx_irq,
    340	.irq_mask = mobiveil_mask_intx_irq,
    341	.irq_unmask = mobiveil_unmask_intx_irq,
    342};
    343
    344/* routine to setup the INTx related data */
    345static int mobiveil_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
    346				  irq_hw_number_t hwirq)
    347{
    348	irq_set_chip_and_handler(irq, &intx_irq_chip, handle_level_irq);
    349	irq_set_chip_data(irq, domain->host_data);
    350
    351	return 0;
    352}
    353
    354/* INTx domain operations structure */
    355static const struct irq_domain_ops intx_domain_ops = {
    356	.map = mobiveil_pcie_intx_map,
    357};
    358
    359static struct irq_chip mobiveil_msi_irq_chip = {
    360	.name = "Mobiveil PCIe MSI",
    361	.irq_mask = pci_msi_mask_irq,
    362	.irq_unmask = pci_msi_unmask_irq,
    363};
    364
    365static struct msi_domain_info mobiveil_msi_domain_info = {
    366	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
    367		   MSI_FLAG_PCI_MSIX),
    368	.chip	= &mobiveil_msi_irq_chip,
    369};
    370
    371static void mobiveil_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
    372{
    373	struct mobiveil_pcie *pcie = irq_data_get_irq_chip_data(data);
    374	phys_addr_t addr = pcie->pcie_reg_base + (data->hwirq * sizeof(int));
    375
    376	msg->address_lo = lower_32_bits(addr);
    377	msg->address_hi = upper_32_bits(addr);
    378	msg->data = data->hwirq;
    379
    380	dev_dbg(&pcie->pdev->dev, "msi#%d address_hi %#x address_lo %#x\n",
    381		(int)data->hwirq, msg->address_hi, msg->address_lo);
    382}
    383
    384static int mobiveil_msi_set_affinity(struct irq_data *irq_data,
    385				     const struct cpumask *mask, bool force)
    386{
    387	return -EINVAL;
    388}
    389
    390static struct irq_chip mobiveil_msi_bottom_irq_chip = {
    391	.name			= "Mobiveil MSI",
    392	.irq_compose_msi_msg	= mobiveil_compose_msi_msg,
    393	.irq_set_affinity	= mobiveil_msi_set_affinity,
    394};
    395
    396static int mobiveil_irq_msi_domain_alloc(struct irq_domain *domain,
    397					 unsigned int virq,
    398					 unsigned int nr_irqs, void *args)
    399{
    400	struct mobiveil_pcie *pcie = domain->host_data;
    401	struct mobiveil_msi *msi = &pcie->rp.msi;
    402	unsigned long bit;
    403
    404	WARN_ON(nr_irqs != 1);
    405	mutex_lock(&msi->lock);
    406
    407	bit = find_first_zero_bit(msi->msi_irq_in_use, msi->num_of_vectors);
    408	if (bit >= msi->num_of_vectors) {
    409		mutex_unlock(&msi->lock);
    410		return -ENOSPC;
    411	}
    412
    413	set_bit(bit, msi->msi_irq_in_use);
    414
    415	mutex_unlock(&msi->lock);
    416
    417	irq_domain_set_info(domain, virq, bit, &mobiveil_msi_bottom_irq_chip,
    418			    domain->host_data, handle_level_irq, NULL, NULL);
    419	return 0;
    420}
    421
    422static void mobiveil_irq_msi_domain_free(struct irq_domain *domain,
    423					 unsigned int virq,
    424					 unsigned int nr_irqs)
    425{
    426	struct irq_data *d = irq_domain_get_irq_data(domain, virq);
    427	struct mobiveil_pcie *pcie = irq_data_get_irq_chip_data(d);
    428	struct mobiveil_msi *msi = &pcie->rp.msi;
    429
    430	mutex_lock(&msi->lock);
    431
    432	if (!test_bit(d->hwirq, msi->msi_irq_in_use))
    433		dev_err(&pcie->pdev->dev, "trying to free unused MSI#%lu\n",
    434			d->hwirq);
    435	else
    436		__clear_bit(d->hwirq, msi->msi_irq_in_use);
    437
    438	mutex_unlock(&msi->lock);
    439}
    440static const struct irq_domain_ops msi_domain_ops = {
    441	.alloc	= mobiveil_irq_msi_domain_alloc,
    442	.free	= mobiveil_irq_msi_domain_free,
    443};
    444
    445static int mobiveil_allocate_msi_domains(struct mobiveil_pcie *pcie)
    446{
    447	struct device *dev = &pcie->pdev->dev;
    448	struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
    449	struct mobiveil_msi *msi = &pcie->rp.msi;
    450
    451	mutex_init(&msi->lock);
    452	msi->dev_domain = irq_domain_add_linear(NULL, msi->num_of_vectors,
    453						&msi_domain_ops, pcie);
    454	if (!msi->dev_domain) {
    455		dev_err(dev, "failed to create IRQ domain\n");
    456		return -ENOMEM;
    457	}
    458
    459	msi->msi_domain = pci_msi_create_irq_domain(fwnode,
    460						    &mobiveil_msi_domain_info,
    461						    msi->dev_domain);
    462	if (!msi->msi_domain) {
    463		dev_err(dev, "failed to create MSI domain\n");
    464		irq_domain_remove(msi->dev_domain);
    465		return -ENOMEM;
    466	}
    467
    468	return 0;
    469}
    470
    471static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie)
    472{
    473	struct device *dev = &pcie->pdev->dev;
    474	struct device_node *node = dev->of_node;
    475	struct mobiveil_root_port *rp = &pcie->rp;
    476
    477	/* setup INTx */
    478	rp->intx_domain = irq_domain_add_linear(node, PCI_NUM_INTX,
    479						&intx_domain_ops, pcie);
    480
    481	if (!rp->intx_domain) {
    482		dev_err(dev, "Failed to get a INTx IRQ domain\n");
    483		return -ENOMEM;
    484	}
    485
    486	raw_spin_lock_init(&rp->intx_mask_lock);
    487
    488	/* setup MSI */
    489	return mobiveil_allocate_msi_domains(pcie);
    490}
    491
    492static int mobiveil_pcie_integrated_interrupt_init(struct mobiveil_pcie *pcie)
    493{
    494	struct platform_device *pdev = pcie->pdev;
    495	struct device *dev = &pdev->dev;
    496	struct mobiveil_root_port *rp = &pcie->rp;
    497	struct resource *res;
    498	int ret;
    499
    500	/* map MSI config resource */
    501	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apb_csr");
    502	pcie->apb_csr_base = devm_pci_remap_cfg_resource(dev, res);
    503	if (IS_ERR(pcie->apb_csr_base))
    504		return PTR_ERR(pcie->apb_csr_base);
    505
    506	/* setup MSI hardware registers */
    507	mobiveil_pcie_enable_msi(pcie);
    508
    509	rp->irq = platform_get_irq(pdev, 0);
    510	if (rp->irq < 0)
    511		return rp->irq;
    512
    513	/* initialize the IRQ domains */
    514	ret = mobiveil_pcie_init_irq_domain(pcie);
    515	if (ret) {
    516		dev_err(dev, "Failed creating IRQ Domain\n");
    517		return ret;
    518	}
    519
    520	irq_set_chained_handler_and_data(rp->irq, mobiveil_pcie_isr, pcie);
    521
    522	/* Enable interrupts */
    523	mobiveil_csr_writel(pcie, (PAB_INTP_INTX_MASK | PAB_INTP_MSI_MASK),
    524			    PAB_INTP_AMBA_MISC_ENB);
    525
    526
    527	return 0;
    528}
    529
    530static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie)
    531{
    532	struct mobiveil_root_port *rp = &pcie->rp;
    533
    534	if (rp->ops->interrupt_init)
    535		return rp->ops->interrupt_init(pcie);
    536
    537	return mobiveil_pcie_integrated_interrupt_init(pcie);
    538}
    539
    540static bool mobiveil_pcie_is_bridge(struct mobiveil_pcie *pcie)
    541{
    542	u32 header_type;
    543
    544	header_type = mobiveil_csr_readb(pcie, PCI_HEADER_TYPE);
    545	header_type &= 0x7f;
    546
    547	return header_type == PCI_HEADER_TYPE_BRIDGE;
    548}
    549
    550int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
    551{
    552	struct mobiveil_root_port *rp = &pcie->rp;
    553	struct pci_host_bridge *bridge = rp->bridge;
    554	struct device *dev = &pcie->pdev->dev;
    555	int ret;
    556
    557	ret = mobiveil_pcie_parse_dt(pcie);
    558	if (ret) {
    559		dev_err(dev, "Parsing DT failed, ret: %x\n", ret);
    560		return ret;
    561	}
    562
    563	if (!mobiveil_pcie_is_bridge(pcie))
    564		return -ENODEV;
    565
    566	/*
    567	 * configure all inbound and outbound windows and prepare the RC for
    568	 * config access
    569	 */
    570	ret = mobiveil_host_init(pcie, false);
    571	if (ret) {
    572		dev_err(dev, "Failed to initialize host\n");
    573		return ret;
    574	}
    575
    576	ret = mobiveil_pcie_interrupt_init(pcie);
    577	if (ret) {
    578		dev_err(dev, "Interrupt init failed\n");
    579		return ret;
    580	}
    581
    582	/* Initialize bridge */
    583	bridge->sysdata = pcie;
    584	bridge->ops = &mobiveil_pcie_ops;
    585
    586	ret = mobiveil_bringup_link(pcie);
    587	if (ret) {
    588		dev_info(dev, "link bring-up failed\n");
    589		return ret;
    590	}
    591
    592	return pci_host_probe(bridge);
    593}