[PATCH v2 4/8] PCI: designware: add msi controller functions for v3.65 hw
Mohit KUMAR DCG
Mohit.KUMAR at st.com
Wed Jun 18 00:16:35 PDT 2014
Hello Murali,
> -----Original Message-----
> From: Murali Karicheri [mailto:m-karicheri2 at ti.com]
> Sent: Wednesday, June 11, 2014 12:21 AM
> To: linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> linux-pci at vger.kernel.org; devicetree at vger.kernel.org; linux-
> doc at vger.kernel.org
> 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 at ti.com>
>
> CC: Santosh Shilimkar <santosh.shilimkar at ti.com>
> CC: Russell King <linux at arm.linux.org.uk>
> CC: Grant Likely <grant.likely at linaro.org>
> CC: Rob Herring <robh+dt at kernel.org>
> CC: Mohit Kumar <mohit.kumar at st.com>
> CC: Jingoo Han <jg1.han at samsung.com>
> CC: Bjorn Helgaas <bhelgaas at google.com>
> CC: Pratyush Anand <pratyush.anand at st.com>
> CC: Richard Zhu <r65037 at freescale.com>
> CC: Kishon Vijay Abraham I <kishon at ti.com>
> CC: Marek Vasut <marex at denx.de>
> CC: Arnd Bergmann <arnd at arndb.de>
> CC: Pawel Moll <pawel.moll at arm.com>
> CC: Mark Rutland <mark.rutland at arm.com>
> CC: Ian Campbell <ijc+devicetree at hellion.org.uk>
> CC: Kumar Gala <galak at codeaurora.org>
> CC: Randy Dunlap <rdunlap at infradead.org>
> CC: Grant Likely <grant.likely at linaro.org>
>
> ---
> 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 at ti.com>
> + *
> + *
> + * 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 at ti.com>
> + *
> + *
> + * 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
More information about the linux-arm-kernel
mailing list