[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v1 2/3] pci/rcar: implement OSID configuration for Renesas RCar Gen4 PCIe host
On Mon, 7 Jul 2025, Mykyta Poturai wrote: > For IPMMU to be able to associate a specific PCI device with it's TLB > the BDF to OSID mapping needs to be set up in the host bridge. The > configured OSID is then emmited as a sideband data on the AXI bus during > PCI DMA transactions. OSID configuration registers are located in the > "app" region of the host bridge. > > Map the "app" region on init and implement methods for setting up > BDF->OSID mappings > > Signed-off-by: Mykyta Poturai <mykyta_poturai@xxxxxxxx> Acked-by: Stefano Stabellini <sstabellini@xxxxxxxxxx> > --- > xen/arch/arm/pci/pci-host-rcar4.c | 148 ++++++++++++++++++++++++++++++ > xen/arch/arm/pci/pci-host-rcar4.h | 18 ++++ > 2 files changed, 166 insertions(+) > create mode 100644 xen/arch/arm/pci/pci-host-rcar4.h > > diff --git a/xen/arch/arm/pci/pci-host-rcar4.c > b/xen/arch/arm/pci/pci-host-rcar4.c > index 62d2130a63..9290c6cac5 100644 > --- a/xen/arch/arm/pci/pci-host-rcar4.c > +++ b/xen/arch/arm/pci/pci-host-rcar4.c > @@ -16,6 +16,32 @@ > > #define RCAR4_DWC_VERSION 0x520A > > +/* PCIE BDF-OSID assignment */ > +#define CNVID(n) (0x700 + ((n) * 4)) > +#define CNVID_CNV_EN (1U << 31) > +#define CNVID_OSID_MASK (0x0F << 16) > +#define CNVID_OSID_SHIFT 16 > +#define CNVID_BDF_MASK (0xFFFF << 0) > +#define CNVID_BDF_SHIFT 0 > + > +#define CNVIDMSK(n) (0x780 + ((n) * 4)) > +#define CNVIDMSK_BDF_MSK_MASK (0xFFFF << 0) > +#define CNVIDMSK_BDF_MSK_SHIFT 0 > + > +#define CNVOSIDCTRL 0x800 > +#define CNVOSIDCTRL_OSID_MASK (0x0F << 16) > +#define CNVOSIDCTRL_OSID_SHIFT 16 > + > +#define DEFAULT_OSID 0 > + > +#define NUM_OSID_REGS 16 > + > +struct rcar4_pcie_priv { > + bool init_done; > + void __iomem *app_base; > + DECLARE_BITMAP(osid_regs, NUM_OSID_REGS); > +}; > + > /* > * PCI host bridges often have different ways to access the root and child > * bus config spaces: > @@ -65,17 +91,139 @@ static const struct dt_device_match __initconstrel > rcar4_pcie_dt_match[] = { > {}, > }; > > +static void rcar4_pcie_writel_app(struct rcar4_pcie_priv *pci, uint32_t reg, > + uint32_t val) > +{ > + writel(val, pci->app_base + reg); > +} > + > +static uint32_t rcar4_pcie_readl_app(struct rcar4_pcie_priv *pci, uint32_t > reg) > +{ > + return readl(pci->app_base + reg); > +} > + > +int rcar4_pcie_osid_regs_init(struct pci_host_bridge *bridge) > +{ > + struct rcar4_pcie_priv *priv = dw_pcie_get_priv(bridge); > + uint32_t val = rcar4_pcie_readl_app(priv, CNVOSIDCTRL); > + > + if ( priv->init_done ) > + return 0; > + priv->init_done = true; > + > + val = (val & ~CNVOSIDCTRL_OSID_MASK) | > + (DEFAULT_OSID << CNVOSIDCTRL_OSID_SHIFT); > + rcar4_pcie_writel_app(priv, CNVOSIDCTRL, val); > + bitmap_zero(priv->osid_regs, NUM_OSID_REGS); > + > + printk("%s: Initialized OSID regs (default OSID %u)\n", > + bridge->dt_node->full_name, DEFAULT_OSID); > + > + return 0; > +} > + > +int rcar4_pcie_osid_reg_alloc(struct pci_host_bridge *bridge) > +{ > + struct rcar4_pcie_priv *priv = dw_pcie_get_priv(bridge); > + int ret; > + > + ret = find_first_zero_bit(priv->osid_regs, NUM_OSID_REGS); > + if ( ret != NUM_OSID_REGS ) > + set_bit(ret, priv->osid_regs); > + else > + ret = -EBUSY; > + > + return ret; > +} > + > +void rcar4_pcie_osid_reg_free(struct pci_host_bridge *bridge, > + unsigned int reg_id) > +{ > + struct rcar4_pcie_priv *priv = dw_pcie_get_priv(bridge); > + > + clear_bit(reg_id, priv->osid_regs); > +} > + > +void rcar4_pcie_osid_bdf_set(struct pci_host_bridge *bridge, > + unsigned int reg_id, uint32_t osid, uint32_t > bdf) > +{ > + struct rcar4_pcie_priv *priv = dw_pcie_get_priv(bridge); > + uint32_t data = rcar4_pcie_readl_app(priv, CNVID(reg_id)); > + > + data &= ~(CNVID_OSID_MASK | CNVID_BDF_MASK); > + data |= CNVID_CNV_EN | (osid << CNVID_OSID_SHIFT) | > + (bdf << CNVID_BDF_SHIFT); > + rcar4_pcie_writel_app(priv, CNVID(reg_id), data); > +} > + > +void rcar4_pcie_osid_bdf_clear(struct pci_host_bridge *bridge, > + unsigned int reg_id) > +{ > + struct rcar4_pcie_priv *priv = dw_pcie_get_priv(bridge); > + uint32_t data = rcar4_pcie_readl_app(priv, CNVID(reg_id)); > + > + data &= ~CNVID_CNV_EN; > + rcar4_pcie_writel_app(priv, CNVID(reg_id), data); > +} > + > +void rcar4_pcie_bdf_msk_set(struct pci_host_bridge *bridge, unsigned int > reg_id, > + uint32_t data) > +{ > + struct rcar4_pcie_priv *priv = dw_pcie_get_priv(bridge); > + > + uint32_t val = rcar4_pcie_readl_app(priv, CNVIDMSK(reg_id)); > + > + val = (val & ~CNVIDMSK_BDF_MSK_MASK) | (data << CNVIDMSK_BDF_MSK_SHIFT); > + > + rcar4_pcie_writel_app(priv, CNVIDMSK(reg_id), val); > +} > + > static int __init pci_host_rcar4_probe(struct dt_device_node *dev, > const void *data) > { > struct pci_host_bridge *bridge; > + paddr_t app_phys_addr; > + paddr_t app_size; > + int app_idx, ret; > + > + struct rcar4_pcie_priv *priv = xzalloc(struct rcar4_pcie_priv); > + if ( !priv ) > + return -ENOMEM; > > bridge = dw_pcie_host_probe(dev, data, &rcar4_pcie_ops, > &rcar4_pcie_child_ops); > > + app_idx = dt_property_match_string(dev, "reg-names", "app"); > + if ( app_idx < 0 ) > + { > + printk(XENLOG_ERR "Cannot find \"app\" range index in device > tree\n"); > + ret = app_idx; > + goto err; > + } > + ret = dt_device_get_address(dev, app_idx, &app_phys_addr, &app_size); > + if ( ret ) > + { > + printk(XENLOG_ERR "Cannot find \"app\" range in device tree\n"); > + goto err; > + } > + > + priv->app_base = ioremap_nocache(app_phys_addr, app_size); > + if ( !priv->app_base ) > + { > + printk(XENLOG_ERR "APP ioremap failed\n"); > + ret = -ENXIO; > + goto err; > + } > + printk("APP at [mem 0x%" PRIpaddr "-0x%" PRIpaddr "]\n", app_phys_addr, > + app_phys_addr + app_size - 1); > + > + dw_pcie_set_priv(bridge, priv); > dw_pcie_set_version(bridge, RCAR4_DWC_VERSION); > > return 0; > +err: > + xfree(priv); > + return ret; > } > > DT_DEVICE_START(pci_gen, "PCI HOST R-CAR GEN4", DEVICE_PCI_HOSTBRIDGE) > diff --git a/xen/arch/arm/pci/pci-host-rcar4.h > b/xen/arch/arm/pci/pci-host-rcar4.h > new file mode 100644 > index 0000000000..8ac6626a22 > --- /dev/null > +++ b/xen/arch/arm/pci/pci-host-rcar4.h > @@ -0,0 +1,18 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +#include <asm/pci.h> > + > +#ifndef __PCI_HOST_RCAR4_H__ > +#define __PCI_HOST_RCAR4_H__ > + > +void rcar4_pcie_osid_bdf_set(struct pci_host_bridge *bridge, > + unsigned int reg_id, uint32_t osid, uint32_t > bdf); > +void rcar4_pcie_osid_bdf_clear(struct pci_host_bridge *bridge, > + unsigned int reg_id); > +void rcar4_pcie_bdf_msk_set(struct pci_host_bridge *bridge, unsigned int > reg_id, > + uint32_t data); > +int rcar4_pcie_osid_reg_alloc(struct pci_host_bridge *bridge); > +void rcar4_pcie_osid_reg_free(struct pci_host_bridge *bridge, > + unsigned int reg_id); > +int rcar4_pcie_osid_regs_init(struct pci_host_bridge *bridge); > + > +#endif /* __PCI_HOST_RCAR4_H__ */ > -- > 2.34.1 >
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |