diff options
author | Jia Hongtao <hongtao.jia@freescale.com> | 2013-03-26 02:32:38 (GMT) |
---|---|---|
committer | Fleming Andrew-AFLEMING <AFLEMING@freescale.com> | 2013-04-18 15:36:37 (GMT) |
commit | 0974fadbb0e39609ab08ee5bfaa9f5de3e589f28 (patch) | |
tree | f47ac40f2930b108bb7bc7193c2ca77b04794f50 | |
parent | 6bfe40fc421a1bdae7d1f84ddc259ddef642c047 (diff) | |
download | linux-fsl-qoriq-0974fadbb0e39609ab08ee5bfaa9f5de3e589f28.tar.xz |
powerpc/85xx: workaround for chips with MSI hardware errata
The MPIC version 2.0 has a MSI errata (errata PIC1 of mpc8544), It causes
that neither MSI nor MSI-X can work fine. This is a workaround to allow
MSI-X to function properly.
Signed-off-by: Liu Shuo <soniccat.liu@gmail.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Jia Hongtao <hongtao.jia@freescale.com>
Change-Id: Iaeaddc226c395beef4007b705869e2694760dc0f
Reviewed-on: http://git.am.freescale.net:8181/1330
Reviewed-by: Wood Scott-B07421 <scottwood@freescale.com>
Reviewed-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Tested-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.c | 40 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.h | 2 |
2 files changed, 39 insertions, 3 deletions
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index ab02db3..1b77e55 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -98,8 +98,18 @@ static int fsl_msi_init_allocator(struct fsl_msi *msi_data) static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type) { - if (type == PCI_CAP_ID_MSIX) - pr_debug("fslmsi: MSI-X untested, trying anyway.\n"); + struct fsl_msi *msi; + + if (type == PCI_CAP_ID_MSI) { + /* + * MPIC version 2.0 has erratum PIC1. For now MSI + * could not work. So check to prevent MSI from + * being used on the board with this erratum. + */ + list_for_each_entry(msi, &msi_head, list) + if (msi->feature & MSI_HW_ERRATA_ENDIAN) + return -EINVAL; + } return 0; } @@ -142,7 +152,17 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, msg->address_lo = lower_32_bits(address); msg->address_hi = upper_32_bits(address); - msg->data = hwirq; + /* + * MPIC version 2.0 has erratum PIC1. It causes + * that neither MSI nor MSI-X can work fine. + * This is a workaround to allow MSI-X to function + * properly. It only works for MSI-X, we prevent + * MSI on buggy chips in fsl_msi_check_device(). + */ + if (msi_data->feature & MSI_HW_ERRATA_ENDIAN) + msg->data = __swab32(hwirq); + else + msg->data = hwirq; pr_debug("%s: allocated srs: %d, ibs: %d\n", __func__, hwirq / IRQS_PER_MSI_REG, hwirq % IRQS_PER_MSI_REG); @@ -363,6 +383,15 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev, return 0; } +/* MPIC version 2.0 has erratum PIC1 */ +static int mpic_has_erratum_pic1(void) +{ + if (fsl_mpic_primary_get_version() == 0x0200) + return 1; + + return 0; +} + static const struct of_device_id fsl_of_msi_ids[]; static int fsl_of_msi_probe(struct platform_device *dev) { @@ -425,6 +454,11 @@ static int fsl_of_msi_probe(struct platform_device *dev) msi->feature = features->fsl_pic_ip; + if ((features->fsl_pic_ip & FSL_PIC_IP_MASK) == FSL_PIC_IP_MPIC) { + if (mpic_has_erratum_pic1()) + msi->feature |= MSI_HW_ERRATA_ENDIAN; + } + /* * Remember the phandle, so that we can match with any PCI nodes * that have an "fsl,msi" property. diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h index 8225f86..7389e8e 100644 --- a/arch/powerpc/sysdev/fsl_msi.h +++ b/arch/powerpc/sysdev/fsl_msi.h @@ -25,6 +25,8 @@ #define FSL_PIC_IP_IPIC 0x00000002 #define FSL_PIC_IP_VMPIC 0x00000003 +#define MSI_HW_ERRATA_ENDIAN 0x00000010 + struct fsl_msi { struct irq_domain *irqhost; |