[PATCH V222/7] PCI: dwc: Add msi_ops to allow DBI based MSI register access
Mayank Rana
quic_mrana at quicinc.com
Mon Jul 15 11:13:30 PDT 2024
PCIe ECAM driver do not have dw_pcie data structure populated and DBI
access related APIs. Hence add msi_ops as part of dw_msi structure to
allow populating DBI based MSI register access.
Signed-off-by: Mayank Rana <quic_mrana at quicinc.com>
---
drivers/pci/controller/dwc/pcie-designware-host.c | 20 ++++++++++++-
drivers/pci/controller/dwc/pcie-designware-msi.c | 36 +++++++++++++----------
drivers/pci/controller/dwc/pcie-designware-msi.h | 10 +++++--
3 files changed, 47 insertions(+), 19 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 3dcf88a..7a1eb1f 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -47,6 +47,16 @@ static void dw_pcie_host_request_msg_tlp_res(struct dw_pcie_rp *pp)
}
}
+static u32 dw_pcie_readl_msi_dbi(void *pci, u32 reg)
+{
+ return dw_pcie_readl_dbi((struct dw_pcie *)pci, reg);
+}
+
+static void dw_pcie_writel_msi_dbi(void *pci, u32 reg, u32 val)
+{
+ dw_pcie_writel_dbi((struct dw_pcie *)pci, reg, val);
+}
+
int dw_pcie_host_init(struct dw_pcie_rp *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -55,6 +65,7 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
struct platform_device *pdev = to_platform_device(dev);
struct resource_entry *win;
struct pci_host_bridge *bridge;
+ struct dw_msi_ops *msi_ops;
struct resource *res;
bool has_msi_ctrl;
int ret;
@@ -124,7 +135,14 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
if (ret < 0)
goto err_deinit_host;
} else if (has_msi_ctrl) {
- pp->msi = dw_pcie_msi_host_init(pdev, pp, pp->num_vectors);
+ msi_ops = devm_kzalloc(dev, sizeof(*msi_ops), GFP_KERNEL);
+ if (msi_ops == NULL)
+ goto err_deinit_host;
+
+ msi_ops->pp = pci;
+ msi_ops->readl_msi = dw_pcie_readl_msi_dbi,
+ msi_ops->writel_msi = dw_pcie_writel_msi_dbi,
+ pp->msi = dw_pcie_msi_host_init(pdev, msi_ops, pp->num_vectors);
if (IS_ERR(pp->msi)) {
ret = PTR_ERR(pp->msi);
goto err_deinit_host;
diff --git a/drivers/pci/controller/dwc/pcie-designware-msi.c b/drivers/pci/controller/dwc/pcie-designware-msi.c
index 39fe5be..dbfffce 100644
--- a/drivers/pci/controller/dwc/pcie-designware-msi.c
+++ b/drivers/pci/controller/dwc/pcie-designware-msi.c
@@ -44,6 +44,16 @@ static struct msi_domain_info dw_pcie_msi_domain_info = {
.chip = &dw_pcie_msi_irq_chip,
};
+static u32 dw_msi_readl(struct dw_msi *msi, u32 reg)
+{
+ return msi->msi_ops->readl_msi(msi->msi_ops->pp, reg);
+}
+
+static void dw_msi_writel(struct dw_msi *msi, u32 reg, u32 val)
+{
+ msi->msi_ops->writel_msi(msi->msi_ops->pp, reg, val);
+}
+
/* MSI int handler */
irqreturn_t dw_handle_msi_irq(struct dw_msi *msi)
{
@@ -51,13 +61,11 @@ irqreturn_t dw_handle_msi_irq(struct dw_msi *msi)
unsigned long val;
u32 status, num_ctrls;
irqreturn_t ret = IRQ_NONE;
- struct dw_pcie *pci = to_dw_pcie_from_pp(msi->pp);
num_ctrls = msi->num_vectors / MAX_MSI_IRQS_PER_CTRL;
for (i = 0; i < num_ctrls; i++) {
- status = dw_pcie_readl_dbi(pci, PCIE_MSI_INTR0_STATUS +
- (i * MSI_REG_CTRL_BLOCK_SIZE));
+ status = dw_msi_readl(msi, PCIE_MSI_INTR0_STATUS + (i * MSI_REG_CTRL_BLOCK_SIZE));
if (!status)
continue;
@@ -115,7 +123,6 @@ static int dw_pci_msi_set_affinity(struct irq_data *d,
static void dw_pci_bottom_mask(struct irq_data *d)
{
struct dw_msi *msi = irq_data_get_irq_chip_data(d);
- struct dw_pcie *pci = to_dw_pcie_from_pp(msi->pp);
unsigned int res, bit, ctrl;
unsigned long flags;
@@ -126,7 +133,7 @@ static void dw_pci_bottom_mask(struct irq_data *d)
bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
msi->irq_mask[ctrl] |= BIT(bit);
- dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, msi->irq_mask[ctrl]);
+ dw_msi_writel(msi, PCIE_MSI_INTR0_MASK + res, msi->irq_mask[ctrl]);
raw_spin_unlock_irqrestore(&msi->lock, flags);
}
@@ -134,7 +141,6 @@ static void dw_pci_bottom_mask(struct irq_data *d)
static void dw_pci_bottom_unmask(struct irq_data *d)
{
struct dw_msi *msi = irq_data_get_irq_chip_data(d);
- struct dw_pcie *pci = to_dw_pcie_from_pp(msi->pp);
unsigned int res, bit, ctrl;
unsigned long flags;
@@ -145,7 +151,7 @@ static void dw_pci_bottom_unmask(struct irq_data *d)
bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
msi->irq_mask[ctrl] &= ~BIT(bit);
- dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, msi->irq_mask[ctrl]);
+ dw_msi_writel(msi, PCIE_MSI_INTR0_MASK + res, msi->irq_mask[ctrl]);
raw_spin_unlock_irqrestore(&msi->lock, flags);
}
@@ -153,14 +159,13 @@ static void dw_pci_bottom_unmask(struct irq_data *d)
static void dw_pci_bottom_ack(struct irq_data *d)
{
struct dw_msi *msi = irq_data_get_irq_chip_data(d);
- struct dw_pcie *pci = to_dw_pcie_from_pp(msi->pp);
unsigned int res, bit, ctrl;
ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
- dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_STATUS + res, BIT(bit));
+ dw_msi_writel(msi, PCIE_MSI_INTR0_STATUS + res, BIT(bit));
}
static struct irq_chip dw_pci_msi_bottom_irq_chip = {
@@ -262,7 +267,6 @@ void dw_pcie_free_msi(struct dw_msi *msi)
void dw_pcie_msi_init(struct dw_msi *msi)
{
- struct dw_pcie *pci = to_dw_pcie_from_pp(msi->pp);
u32 ctrl, num_ctrls;
u64 msi_target;
@@ -273,16 +277,16 @@ void dw_pcie_msi_init(struct dw_msi *msi)
num_ctrls = msi->num_vectors / MAX_MSI_IRQS_PER_CTRL;
/* Initialize IRQ Status array */
for (ctrl = 0; ctrl < num_ctrls; ctrl++) {
- dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK +
+ dw_msi_writel(msi, PCIE_MSI_INTR0_MASK +
(ctrl * MSI_REG_CTRL_BLOCK_SIZE),
msi->irq_mask[ctrl]);
- dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_ENABLE +
+ dw_msi_writel(msi, PCIE_MSI_INTR0_ENABLE +
(ctrl * MSI_REG_CTRL_BLOCK_SIZE), ~0);
}
/* Program the msi_data */
- dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_LO, lower_32_bits(msi_target));
- dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_HI, upper_32_bits(msi_target));
+ dw_msi_writel(msi, PCIE_MSI_ADDR_LO, lower_32_bits(msi_target));
+ dw_msi_writel(msi, PCIE_MSI_ADDR_HI, upper_32_bits(msi_target));
}
static int dw_pcie_parse_split_msi_irq(struct dw_msi *msi, struct platform_device *pdev)
@@ -324,7 +328,7 @@ static int dw_pcie_parse_split_msi_irq(struct dw_msi *msi, struct platform_devic
}
struct dw_msi *dw_pcie_msi_host_init(struct platform_device *pdev,
- void *pp, u32 num_vectors)
+ struct dw_msi_ops *ops, u32 num_vectors)
{
struct device *dev = &pdev->dev;
u64 *msi_vaddr = NULL;
@@ -341,7 +345,7 @@ struct dw_msi *dw_pcie_msi_host_init(struct platform_device *pdev,
raw_spin_lock_init(&msi->lock);
msi->dev = dev;
- msi->pp = pp;
+ msi->msi_ops = ops;
msi->has_msi_ctrl = true;
msi->num_vectors = num_vectors;
diff --git a/drivers/pci/controller/dwc/pcie-designware-msi.h b/drivers/pci/controller/dwc/pcie-designware-msi.h
index 633156e..cf5c612 100644
--- a/drivers/pci/controller/dwc/pcie-designware-msi.h
+++ b/drivers/pci/controller/dwc/pcie-designware-msi.h
@@ -18,8 +18,15 @@
#define MSI_REG_CTRL_BLOCK_SIZE 12
#define MSI_DEF_NUM_VECTORS 32
+struct dw_msi_ops {
+ void *pp;
+ u32 (*readl_msi)(void *pp, u32 reg);
+ void (*writel_msi)(void *pp, u32 reg, u32 val);
+};
+
struct dw_msi {
struct device *dev;
+ struct dw_msi_ops *msi_ops;
struct irq_domain *irq_domain;
struct irq_domain *msi_domain;
struct irq_chip *msi_irq_chip;
@@ -31,11 +38,10 @@ struct dw_msi {
DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
bool has_msi_ctrl;
void *private_data;
- void *pp;
};
struct dw_msi *dw_pcie_msi_host_init(struct platform_device *pdev,
- void *pp, u32 num_vectors);
+ struct dw_msi_ops *ops, u32 num_vectors);
int dw_pcie_allocate_domains(struct dw_msi *msi);
void dw_pcie_msi_init(struct dw_msi *msi);
void dw_pcie_free_msi(struct dw_msi *msi);
--
2.7.4
More information about the linux-arm-kernel
mailing list