PCI: brcmstb: Accommodate MSI for older chips
Older BrcmSTB chips do not have a separate register for MSI interrupts; the MSIs are in a register that also contains unrelated interrupts. In addition, the interrupts lie in bits [31..24] for these legacy chips. This commit provides common code for both legacy and non-legacy MSI interrupt registers. Link: https://lore.kernel.org/r/20200911175232.19016-9-james.quinlan@broadcom.com Signed-off-by: Jim Quinlan <jquinlan@broadcom.com> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Reviewed-by: Rob Herring <robh@kernel.org> Acked-by: Florian Fainelli <f.fainelli@gmail.com>
This commit is contained in:
parent
52ded9e4f0
commit
3baec684a5
@ -83,7 +83,8 @@
|
|||||||
#define PCIE_MISC_MSI_BAR_CONFIG_HI 0x4048
|
#define PCIE_MISC_MSI_BAR_CONFIG_HI 0x4048
|
||||||
|
|
||||||
#define PCIE_MISC_MSI_DATA_CONFIG 0x404c
|
#define PCIE_MISC_MSI_DATA_CONFIG 0x404c
|
||||||
#define PCIE_MISC_MSI_DATA_CONFIG_VAL 0xffe06540
|
#define PCIE_MISC_MSI_DATA_CONFIG_VAL_32 0xffe06540
|
||||||
|
#define PCIE_MISC_MSI_DATA_CONFIG_VAL_8 0xfff86540
|
||||||
|
|
||||||
#define PCIE_MISC_PCIE_CTRL 0x4064
|
#define PCIE_MISC_PCIE_CTRL 0x4064
|
||||||
#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK 0x1
|
#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK 0x1
|
||||||
@ -95,6 +96,9 @@
|
|||||||
#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK 0x10
|
#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK 0x10
|
||||||
#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK 0x40
|
#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK 0x40
|
||||||
|
|
||||||
|
#define PCIE_MISC_REVISION 0x406c
|
||||||
|
#define BRCM_PCIE_HW_REV_33 0x0303
|
||||||
|
|
||||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT 0x4070
|
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT 0x4070
|
||||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK 0xfff00000
|
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK 0xfff00000
|
||||||
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK 0xfff0
|
#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK 0xfff0
|
||||||
@ -115,10 +119,14 @@
|
|||||||
#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2
|
#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2
|
||||||
#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
|
#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
|
||||||
|
|
||||||
#define PCIE_MSI_INTR2_STATUS 0x4500
|
|
||||||
#define PCIE_MSI_INTR2_CLR 0x4508
|
#define PCIE_INTR2_CPU_BASE 0x4300
|
||||||
#define PCIE_MSI_INTR2_MASK_SET 0x4510
|
#define PCIE_MSI_INTR2_BASE 0x4500
|
||||||
#define PCIE_MSI_INTR2_MASK_CLR 0x4514
|
/* Offsets from PCIE_INTR2_CPU_BASE and PCIE_MSI_INTR2_BASE */
|
||||||
|
#define MSI_INT_STATUS 0x0
|
||||||
|
#define MSI_INT_CLR 0x8
|
||||||
|
#define MSI_INT_MASK_SET 0x10
|
||||||
|
#define MSI_INT_MASK_CLR 0x14
|
||||||
|
|
||||||
#define PCIE_EXT_CFG_DATA 0x8000
|
#define PCIE_EXT_CFG_DATA 0x8000
|
||||||
|
|
||||||
@ -138,6 +146,8 @@
|
|||||||
/* PCIe parameters */
|
/* PCIe parameters */
|
||||||
#define BRCM_NUM_PCIE_OUT_WINS 0x4
|
#define BRCM_NUM_PCIE_OUT_WINS 0x4
|
||||||
#define BRCM_INT_PCI_MSI_NR 32
|
#define BRCM_INT_PCI_MSI_NR 32
|
||||||
|
#define BRCM_INT_PCI_MSI_LEGACY_NR 8
|
||||||
|
#define BRCM_INT_PCI_MSI_SHIFT 0
|
||||||
|
|
||||||
/* MSI target adresses */
|
/* MSI target adresses */
|
||||||
#define BRCM_MSI_TARGET_ADDR_LT_4GB 0x0fffffffcULL
|
#define BRCM_MSI_TARGET_ADDR_LT_4GB 0x0fffffffcULL
|
||||||
@ -253,6 +263,12 @@ struct brcm_msi {
|
|||||||
int irq;
|
int irq;
|
||||||
/* used indicates which MSI interrupts have been alloc'd */
|
/* used indicates which MSI interrupts have been alloc'd */
|
||||||
unsigned long used;
|
unsigned long used;
|
||||||
|
bool legacy;
|
||||||
|
/* Some chips have MSIs in bits [31..24] of a shared register. */
|
||||||
|
int legacy_shift;
|
||||||
|
int nr; /* No. of MSI available, depends on chip */
|
||||||
|
/* This is the base pointer for interrupt status/set/clr regs */
|
||||||
|
void __iomem *intr_base;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Internal PCIe Host Controller Information.*/
|
/* Internal PCIe Host Controller Information.*/
|
||||||
@ -463,8 +479,10 @@ static void brcm_pcie_msi_isr(struct irq_desc *desc)
|
|||||||
msi = irq_desc_get_handler_data(desc);
|
msi = irq_desc_get_handler_data(desc);
|
||||||
dev = msi->dev;
|
dev = msi->dev;
|
||||||
|
|
||||||
status = readl(msi->base + PCIE_MSI_INTR2_STATUS);
|
status = readl(msi->intr_base + MSI_INT_STATUS);
|
||||||
for_each_set_bit(bit, &status, BRCM_INT_PCI_MSI_NR) {
|
status >>= msi->legacy_shift;
|
||||||
|
|
||||||
|
for_each_set_bit(bit, &status, msi->nr) {
|
||||||
virq = irq_find_mapping(msi->inner_domain, bit);
|
virq = irq_find_mapping(msi->inner_domain, bit);
|
||||||
if (virq)
|
if (virq)
|
||||||
generic_handle_irq(virq);
|
generic_handle_irq(virq);
|
||||||
@ -481,7 +499,7 @@ static void brcm_msi_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
|
|||||||
|
|
||||||
msg->address_lo = lower_32_bits(msi->target_addr);
|
msg->address_lo = lower_32_bits(msi->target_addr);
|
||||||
msg->address_hi = upper_32_bits(msi->target_addr);
|
msg->address_hi = upper_32_bits(msi->target_addr);
|
||||||
msg->data = (0xffff & PCIE_MISC_MSI_DATA_CONFIG_VAL) | data->hwirq;
|
msg->data = (0xffff & PCIE_MISC_MSI_DATA_CONFIG_VAL_32) | data->hwirq;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int brcm_msi_set_affinity(struct irq_data *irq_data,
|
static int brcm_msi_set_affinity(struct irq_data *irq_data,
|
||||||
@ -493,8 +511,9 @@ static int brcm_msi_set_affinity(struct irq_data *irq_data,
|
|||||||
static void brcm_msi_ack_irq(struct irq_data *data)
|
static void brcm_msi_ack_irq(struct irq_data *data)
|
||||||
{
|
{
|
||||||
struct brcm_msi *msi = irq_data_get_irq_chip_data(data);
|
struct brcm_msi *msi = irq_data_get_irq_chip_data(data);
|
||||||
|
const int shift_amt = data->hwirq + msi->legacy_shift;
|
||||||
|
|
||||||
writel(1 << data->hwirq, msi->base + PCIE_MSI_INTR2_CLR);
|
writel(1 << shift_amt, msi->intr_base + MSI_INT_CLR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -510,7 +529,7 @@ static int brcm_msi_alloc(struct brcm_msi *msi)
|
|||||||
int hwirq;
|
int hwirq;
|
||||||
|
|
||||||
mutex_lock(&msi->lock);
|
mutex_lock(&msi->lock);
|
||||||
hwirq = bitmap_find_free_region(&msi->used, BRCM_INT_PCI_MSI_NR, 0);
|
hwirq = bitmap_find_free_region(&msi->used, msi->nr, 0);
|
||||||
mutex_unlock(&msi->lock);
|
mutex_unlock(&msi->lock);
|
||||||
|
|
||||||
return hwirq;
|
return hwirq;
|
||||||
@ -559,8 +578,7 @@ static int brcm_allocate_domains(struct brcm_msi *msi)
|
|||||||
struct fwnode_handle *fwnode = of_node_to_fwnode(msi->np);
|
struct fwnode_handle *fwnode = of_node_to_fwnode(msi->np);
|
||||||
struct device *dev = msi->dev;
|
struct device *dev = msi->dev;
|
||||||
|
|
||||||
msi->inner_domain = irq_domain_add_linear(NULL, BRCM_INT_PCI_MSI_NR,
|
msi->inner_domain = irq_domain_add_linear(NULL, msi->nr, &msi_domain_ops, msi);
|
||||||
&msi_domain_ops, msi);
|
|
||||||
if (!msi->inner_domain) {
|
if (!msi->inner_domain) {
|
||||||
dev_err(dev, "failed to create IRQ domain\n");
|
dev_err(dev, "failed to create IRQ domain\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -597,7 +615,10 @@ static void brcm_msi_remove(struct brcm_pcie *pcie)
|
|||||||
|
|
||||||
static void brcm_msi_set_regs(struct brcm_msi *msi)
|
static void brcm_msi_set_regs(struct brcm_msi *msi)
|
||||||
{
|
{
|
||||||
writel(0xffffffff, msi->base + PCIE_MSI_INTR2_MASK_CLR);
|
u32 val = __GENMASK(31, msi->legacy_shift);
|
||||||
|
|
||||||
|
writel(val, msi->intr_base + MSI_INT_MASK_CLR);
|
||||||
|
writel(val, msi->intr_base + MSI_INT_CLR);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The 0 bit of PCIE_MISC_MSI_BAR_CONFIG_LO is repurposed to MSI
|
* The 0 bit of PCIE_MISC_MSI_BAR_CONFIG_LO is repurposed to MSI
|
||||||
@ -608,8 +629,8 @@ static void brcm_msi_set_regs(struct brcm_msi *msi)
|
|||||||
writel(upper_32_bits(msi->target_addr),
|
writel(upper_32_bits(msi->target_addr),
|
||||||
msi->base + PCIE_MISC_MSI_BAR_CONFIG_HI);
|
msi->base + PCIE_MISC_MSI_BAR_CONFIG_HI);
|
||||||
|
|
||||||
writel(PCIE_MISC_MSI_DATA_CONFIG_VAL,
|
val = msi->legacy ? PCIE_MISC_MSI_DATA_CONFIG_VAL_8 : PCIE_MISC_MSI_DATA_CONFIG_VAL_32;
|
||||||
msi->base + PCIE_MISC_MSI_DATA_CONFIG);
|
writel(val, msi->base + PCIE_MISC_MSI_DATA_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int brcm_pcie_enable_msi(struct brcm_pcie *pcie)
|
static int brcm_pcie_enable_msi(struct brcm_pcie *pcie)
|
||||||
@ -634,6 +655,17 @@ static int brcm_pcie_enable_msi(struct brcm_pcie *pcie)
|
|||||||
msi->np = pcie->np;
|
msi->np = pcie->np;
|
||||||
msi->target_addr = pcie->msi_target_addr;
|
msi->target_addr = pcie->msi_target_addr;
|
||||||
msi->irq = irq;
|
msi->irq = irq;
|
||||||
|
msi->legacy = pcie->hw_rev < BRCM_PCIE_HW_REV_33;
|
||||||
|
|
||||||
|
if (msi->legacy) {
|
||||||
|
msi->intr_base = msi->base + PCIE_INTR2_CPU_BASE;
|
||||||
|
msi->nr = BRCM_INT_PCI_MSI_LEGACY_NR;
|
||||||
|
msi->legacy_shift = 24;
|
||||||
|
} else {
|
||||||
|
msi->intr_base = msi->base + PCIE_MSI_INTR2_BASE;
|
||||||
|
msi->nr = BRCM_INT_PCI_MSI_NR;
|
||||||
|
msi->legacy_shift = 0;
|
||||||
|
}
|
||||||
|
|
||||||
ret = brcm_allocate_domains(msi);
|
ret = brcm_allocate_domains(msi);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -904,12 +936,6 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
|
|||||||
tmp &= ~PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK;
|
tmp &= ~PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK;
|
||||||
writel(tmp, base + PCIE_MISC_RC_BAR3_CONFIG_LO);
|
writel(tmp, base + PCIE_MISC_RC_BAR3_CONFIG_LO);
|
||||||
|
|
||||||
/* Mask all interrupts since we are not handling any yet */
|
|
||||||
writel(0xffffffff, pcie->base + PCIE_MSI_INTR2_MASK_SET);
|
|
||||||
|
|
||||||
/* clear any interrupts we find on boot */
|
|
||||||
writel(0xffffffff, pcie->base + PCIE_MSI_INTR2_CLR);
|
|
||||||
|
|
||||||
if (pcie->gen)
|
if (pcie->gen)
|
||||||
brcm_pcie_set_gen(pcie, pcie->gen);
|
brcm_pcie_set_gen(pcie, pcie->gen);
|
||||||
|
|
||||||
@ -1253,6 +1279,8 @@ static int brcm_pcie_probe(struct platform_device *pdev)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
pcie->hw_rev = readl(pcie->base + PCIE_MISC_REVISION);
|
||||||
|
|
||||||
msi_np = of_parse_phandle(pcie->np, "msi-parent", 0);
|
msi_np = of_parse_phandle(pcie->np, "msi-parent", 0);
|
||||||
if (pci_msi_enabled() && msi_np == pcie->np) {
|
if (pci_msi_enabled() && msi_np == pcie->np) {
|
||||||
ret = brcm_pcie_enable_msi(pcie);
|
ret = brcm_pcie_enable_msi(pcie);
|
||||||
|
Loading…
Reference in New Issue
Block a user