Hello Murali, > -----Original Message----- > From: Murali Karicheri [mailto:m-karicheri2@xxxxxx] > Sent: Wednesday, June 11, 2014 12:21 AM > To: linux-arm-kernel@xxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; > linux-pci@xxxxxxxxxxxxxxx; devicetree@xxxxxxxxxxxxxxx; linux- > doc@xxxxxxxxxxxxxxx > Cc: Murali Karicheri; Santosh Shilimkar; Russell King; Grant Likely; Rob Herring; > Mohit KUMAR DCG; Jingoo Han; Bjorn Helgaas; Pratyush ANAND; Richard > Zhu; Kishon Vijay Abraham I; Marek Vasut; Arnd Bergmann; Pawel Moll; > Mark Rutland; Ian Campbell; Kumar Gala; Randy Dunlap > Subject: [PATCH v2 4/8] PCI: designware: add msi controller functions for > v3.65 hw > > Add dw msi controller functions for v3.65 hw. This adds dw_v3_65_msi_chip > and dw_v3_65_msi_domain_ops so that can be used on this version of the > hw. > This required since MSI irq registers reside in the application space for v3.65 > hw. The functions are used by v3.65 dw pci core functions to support > implementation of PCI controllers based on this hw version. > > While at it, move the ATU hw specific variable and msi irq to a separate struct > inside a union and add another struct inside the union to hold dw v3.65 > specific variables. > - Here also, pls look into Lucas work for MSI cleanup and then apply your changes: [PATCH 0/4] proper multi MSI handling for designware host Thanks Mohit > Signed-off-by: Murali Karicheri <m-karicheri2@xxxxxx> > > CC: Santosh Shilimkar <santosh.shilimkar@xxxxxx> > CC: Russell King <linux@xxxxxxxxxxxxxxxx> > CC: Grant Likely <grant.likely@xxxxxxxxxx> > CC: Rob Herring <robh+dt@xxxxxxxxxx> > CC: Mohit Kumar <mohit.kumar@xxxxxx> > CC: Jingoo Han <jg1.han@xxxxxxxxxxx> > CC: Bjorn Helgaas <bhelgaas@xxxxxxxxxx> > CC: Pratyush Anand <pratyush.anand@xxxxxx> > CC: Richard Zhu <r65037@xxxxxxxxxxxxx> > CC: Kishon Vijay Abraham I <kishon@xxxxxx> > CC: Marek Vasut <marex@xxxxxxx> > CC: Arnd Bergmann <arnd@xxxxxxxx> > CC: Pawel Moll <pawel.moll@xxxxxxx> > CC: Mark Rutland <mark.rutland@xxxxxxx> > CC: Ian Campbell <ijc+devicetree@xxxxxxxxxxxxxx> > CC: Kumar Gala <galak@xxxxxxxxxxxxxx> > CC: Randy Dunlap <rdunlap@xxxxxxxxxxxxx> > CC: Grant Likely <grant.likely@xxxxxxxxxx> > > --- > drivers/pci/host/Kconfig | 5 ++ > drivers/pci/host/Makefile | 1 + > drivers/pci/host/pci-dw-v3_65-msi.c | 149 > +++++++++++++++++++++++++++++++++++ > drivers/pci/host/pci-dw-v3_65.h | 20 +++++ > drivers/pci/host/pcie-designware.h | 21 +++-- > 5 files changed, 191 insertions(+), 5 deletions(-) create mode 100644 > drivers/pci/host/pci-dw-v3_65-msi.c > create mode 100644 drivers/pci/host/pci-dw-v3_65.h > > diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index > a6f67ec..2fcd9f9 100644 > --- a/drivers/pci/host/Kconfig > +++ b/drivers/pci/host/Kconfig > @@ -9,6 +9,11 @@ config PCI_MVEBU > config PCIE_DW > bool > > +config PCI_DW_V3_65 > + bool "Designware PCIe h/w v3.65" > + help > + Say Y here if the DW h/w version is 3.65 > + > config PCI_EXYNOS > bool "Samsung Exynos PCIe controller" > depends on SOC_EXYNOS5440 > diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index > 13fb333..28af710 100644 > --- a/drivers/pci/host/Makefile > +++ b/drivers/pci/host/Makefile > @@ -4,3 +4,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o > obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o > obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o > obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o > +obj-$(CONFIG_PCI_DW_V3_65) += pci-dw-v3_65-msi.o > diff --git a/drivers/pci/host/pci-dw-v3_65-msi.c b/drivers/pci/host/pci-dw- > v3_65-msi.c > new file mode 100644 > index 0000000..a26ffdd > --- /dev/null > +++ b/drivers/pci/host/pci-dw-v3_65-msi.c > @@ -0,0 +1,149 @@ > +/* > + * Designware(dw) MSI controller version 3.65 > + * > + * Copyright (C) 2013-2014 Texas Instruments., Ltd. > + * http://www.ti.com > + * > + * Author: Murali Karicheri <m-karicheri2@xxxxxx> > + * > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > + > +#include <linux/of_irq.h> > +#include <linux/kernel.h> > +#include <linux/msi.h> > +#include <linux/pci.h> > + > +#include "pcie-designware.h" > + > +#define MSI_IRQ 0x054 > +#define MSI0_IRQ_STATUS 0x104 > +#define MSI0_IRQ_ENABLE_SET 0x108 > +#define MSI0_IRQ_ENABLE_CLR 0x10c > +#define IRQ_STATUS 0x184 > +#define IRQ_EOI 0x050 > +#define MSI_IRQ_OFFSET 4 > + > +static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys) { > + return sys->private_data; > +} > + > +static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset, > + u32 *bit_pos) > +{ > + *reg_offset = offset % 8; > + *bit_pos = offset >> 3; > +} > + > +inline u32 dw_v3_65_get_msi_data(struct pcie_port *pp) { > + return pp->app.start + MSI_IRQ; > +} > + > +void dw_v3_65_handle_msi_irq(struct pcie_port *pp, int offset) { > + u32 pending, vector; > + int src, virq; > + > + pending = readl(pp->va_app_base + MSI0_IRQ_STATUS + (offset << > 4)); > + /* > + * MSI0, Status bit 0-3 shows vectors 0, 8, 16, 24, MSI1 status bit > + * shows 1, 9, 17, 25 and so forth > + */ > + for (src = 0; src < 4; src++) { > + if (BIT(src) & pending) { > + vector = offset + (src << 3); > + virq = irq_linear_revmap(pp->irq_domain, vector); > + dev_dbg(pp->dev, > + "irq: bit %d, vector %d, virq %d\n", > + src, vector, virq); > + generic_handle_irq(virq); > + } > + } > +} > + > +static void dw_v3_65_msi_irq_ack(struct irq_data *d) { > + u32 offset, reg_offset, bit_pos; > + unsigned int irq = d->irq; > + struct msi_desc *msi; > + struct pcie_port *pp; > + > + msi = irq_get_msi_desc(irq); > + pp = sys_to_pcie(msi->dev->bus->sysdata); > + offset = irq - irq_linear_revmap(pp->irq_domain, 0); > + update_reg_offset_bit_pos(offset, ®_offset, &bit_pos); > + > + writel(BIT(bit_pos), > + pp->va_app_base + MSI0_IRQ_STATUS + (reg_offset << 4)); > + writel(reg_offset + MSI_IRQ_OFFSET, pp->va_app_base + IRQ_EOI); > } > + > +static void dw_v3_65_msi_irq_mask(struct irq_data *d) { > + u32 offset, reg_offset, bit_pos; > + unsigned int irq = d->irq; > + struct msi_desc *msi; > + struct pcie_port *pp; > + > + msi = irq_get_msi_desc(irq); > + pp = sys_to_pcie(msi->dev->bus->sysdata); > + offset = irq - irq_linear_revmap(pp->irq_domain, 0); > + update_reg_offset_bit_pos(offset, ®_offset, &bit_pos); > + > + /* mask the end point if PVM implemented */ > + if (IS_ENABLED(CONFIG_PCI_MSI)) { > + if (msi->msi_attrib.maskbit) > + mask_msi_irq(d); > + } > + > + writel(BIT(bit_pos), > + pp->va_app_base + MSI0_IRQ_ENABLE_CLR + (reg_offset << > 4)); } > + > +static void dw_v3_65_msi_irq_unmask(struct irq_data *d) { > + u32 offset, reg_offset, bit_pos; > + unsigned int irq = d->irq; > + struct msi_desc *msi; > + struct pcie_port *pp; > + > + msi = irq_get_msi_desc(irq); > + pp = sys_to_pcie(msi->dev->bus->sysdata); > + offset = irq - irq_linear_revmap(pp->irq_domain, 0); > + update_reg_offset_bit_pos(offset, ®_offset, &bit_pos); > + > + /* mask the end point if PVM implemented */ > + if (IS_ENABLED(CONFIG_PCI_MSI)) { > + if (msi->msi_attrib.maskbit) > + unmask_msi_irq(d); > + } > + > + writel(BIT(bit_pos), > + pp->va_app_base + MSI0_IRQ_ENABLE_SET + (reg_offset << > 4)); } > + > +static struct irq_chip dw_v3_65_msi_chip = { > + .name = "PCI-DW-MSI-OLD", > + .irq_ack = dw_v3_65_msi_irq_ack, > + .irq_mask = dw_v3_65_msi_irq_mask, > + .irq_unmask = dw_v3_65_msi_irq_unmask, }; > + > +static int dw_v3_65_msi_map(struct irq_domain *domain, unsigned int irq, > + irq_hw_number_t hwirq) > +{ > + irq_set_chip_and_handler(irq, &dw_v3_65_msi_chip, > handle_level_irq); > + irq_set_chip_data(irq, domain->host_data); > + set_irq_flags(irq, IRQF_VALID); > + > + return 0; > +} > + > +const struct irq_domain_ops dw_v3_65_msi_domain_ops = { > + .map = dw_v3_65_msi_map, > +}; > diff --git a/drivers/pci/host/pci-dw-v3_65.h b/drivers/pci/host/pci-dw- > v3_65.h new file mode 100644 index 0000000..689256a > --- /dev/null > +++ b/drivers/pci/host/pci-dw-v3_65.h > @@ -0,0 +1,20 @@ > +/* > + * Designware(dw) v3.65 controller common includes > + * > + * Copyright (C) 2013-2014 Texas Instruments., Ltd. > + * http://www.ti.com > + * > + * Author: Murali Karicheri <m-karicheri2@xxxxxx> > + * > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > + > +#define MAX_LEGACY_IRQS 4 > + > +/* v3.65 specific MSI controller APIs/definitions */ extern const > +struct irq_domain_ops dw_v3_65_msi_domain_ops; void > +dw_v3_65_handle_msi_irq(struct pcie_port *pp, int offset); > +u32 dw_v3_65_get_msi_data(struct pcie_port *pp); > diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie- > designware.h > index 3a6a6eb..05bb590 100644 > --- a/drivers/pci/host/pcie-designware.h > +++ b/drivers/pci/host/pcie-designware.h > @@ -35,16 +35,27 @@ struct pcie_port { > struct device *dev; > u8 root_bus_nr; > void __iomem *dbi_base; > - u64 cfg0_base; > - void __iomem *va_cfg0_base; > - u64 cfg1_base; > - void __iomem *va_cfg1_base; > /* > * v3.65 DW hw implements application register space for > * MSI and has no ATU view port > */ > #define DW_V3_65 BIT(0) > u32 version; > + union { > + /* New DW hw specific */ > + struct { > + u64 cfg0_base; > + void __iomem *va_cfg0_base; > + u64 cfg1_base; > + void __iomem *va_cfg1_base; > + int msi_irq; > + }; > + /* v3.65 DW hw specific */ > + struct { > + void __iomem *va_app_base; > + struct resource app; > + }; > + }; > u64 io_base; > u64 mem_base; > spinlock_t conf_lock; > @@ -55,7 +66,7 @@ struct pcie_port { > int irq; > u32 lanes; > struct pcie_host_ops *ops; > - int msi_irq; > + /* msi irq domain */ > struct irq_domain *irq_domain; > unsigned long msi_data; > DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS); > -- > 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html