From: Preetesh  Parekh <[EMAIL PROTECTED]>

Signed-off-by: Preetesh Parekh <[EMAIL PROTECTED]>
---
 arch/powerpc/platforms/40x/kilauea.c     |   13 ++++
 arch/powerpc/platforms/44x/canyonlands.c |   14 ++++
 arch/powerpc/sysdev/ppc4xx_pci.c         |  115 ++++++++++++++++++++++++++++++
 arch/powerpc/sysdev/ppc4xx_pci.h         |   45 ++++++++++++
 include/asm-powerpc/dcr-native.h         |   12 +++
 5 files changed, 199 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/platforms/40x/kilauea.c 
b/arch/powerpc/platforms/40x/kilauea.c
index 1dd24ff..3610be2 100644
--- a/arch/powerpc/platforms/40x/kilauea.c
+++ b/arch/powerpc/platforms/40x/kilauea.c
@@ -22,6 +22,11 @@
 #include <asm/pci-bridge.h>
 #include <asm/ppc4xx.h>
 
+#ifdef CONFIG_PCI_MSI
+extern int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
+extern void ppc4xx_teardown_msi_irqs(struct pci_dev *dev);
+#endif
+
 static __initdata struct of_device_id kilauea_of_bus[] = {
        { .compatible = "ibm,plb4", },
        { .compatible = "ibm,opb", },
@@ -46,6 +51,14 @@ static int __init kilauea_probe(void)
 
        ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
 
+#ifdef CONFIG_PCI_MSI
+       /*
+        * Setting callback functions for MSI support
+        */
+       ppc_md.setup_msi_irqs = ppc4xx_setup_msi_irqs;
+       ppc_md.teardown_msi_irqs = ppc4xx_teardown_msi_irqs;
+#endif
+
        return 1;
 }
 
diff --git a/arch/powerpc/platforms/44x/canyonlands.c 
b/arch/powerpc/platforms/44x/canyonlands.c
index 3949289..ee38fb7 100644
--- a/arch/powerpc/platforms/44x/canyonlands.c
+++ b/arch/powerpc/platforms/44x/canyonlands.c
@@ -25,6 +25,12 @@
 #include <asm/pci-bridge.h>
 #include <asm/ppc4xx.h>
 
+
+#ifdef CONFIG_PCI_MSI
+extern int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
+extern void ppc4xx_teardown_msi_irqs(struct pci_dev *dev);
+#endif
+
 static __initdata struct of_device_id canyonlands_of_bus[] = {
        { .compatible = "ibm,plb4", },
        { .compatible = "ibm,opb", },
@@ -49,6 +55,14 @@ static int __init canyonlands_probe(void)
 
        ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
 
+#ifdef CONFIG_PCI_MSI
+       /*
+        * Setting callback functions for MSI support
+        */
+       ppc_md.setup_msi_irqs = ppc4xx_setup_msi_irqs;
+       ppc_md.teardown_msi_irqs = ppc4xx_teardown_msi_irqs;
+#endif
+
        return 1;
 }
 
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index fb368df..bdb3663 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -35,6 +35,11 @@
 
 static int dma_offset_set;
 
+#ifdef CONFIG_PCI_MSI
+#include <linux/msi.h>
+#include "../../../drivers/pci/msi.h"
+#endif
+
 /* Move that to a useable header */
 extern unsigned long total_memory;
 
@@ -1587,12 +1592,26 @@ static void __init ppc4xx_pciex_port_setup_hose(struct 
ppc4xx_pciex_port *port)
        out_le16(mbase + 0x202, val);
 
        if (!port->endpoint) {
+#ifdef CONFIG_PCI_MSI
+               /* Set MSI enable, multiple msg cap = 4 */
+               /* 4 messages allocated, 64 bit capability */
+               out_le32(mbase + 0x048, in_le32(mbase + 0x048) | 0x00a50000);
+
+               /* Enable interrupts in BCR */
+               out_le32(mbase + 0x03C, in_le32(mbase + 0x03C) | 0xFF000000);
+#endif
+
                /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */
                out_le32(mbase + 0x208, 0x06040001);
 
                printk(KERN_INFO "PCIE%d: successfully set as root-complex\n",
                       port->index);
        } else {
+#ifdef CONFIG_PCI_MSI
+               /* Enable MSI for End-Point */
+               out_le32(mbase + 0x048, (in_le32(mbase + 0x048) | 0x00a50000));
+#endif
+
                /* Set Class Code to Processor/PPC */
                out_le32(mbase + 0x208, 0x0b200001);
 
@@ -1704,6 +1723,97 @@ static void __init ppc4xx_probe_pciex_bridge(struct 
device_node *np)
        ppc4xx_pciex_port_setup_hose(port);
 }
 
+#ifdef CONFIG_PCI_MSI
+int ppc4xx_setup_peih(void)
+{
+       void __iomem *peih_base;
+
+       printk(KERN_INFO " %s \n",__FUNCTION__);        
+       /* Set base address for PEIH and enable PEIH */
+       SDR_WRITE(PESDR0_4XX_IHS1, PPC4XX_PEIH_REGBASE_HADDR);  
+       SDR_WRITE(PESDR0_4XX_IHS2, PPC4XX_PEIH_REGBASE_LADDR);  
+
+       /* Map in PCI-E Interrupt Handler Registers */
+       peih_base = ioremap(PPC4XX_PEIH_REGBASE, PPC4XX_PEIH_REGSIZE);
+       if(!peih_base) {
+               printk(KERN_ERR "%s: ioremap64 failed for addr 0x%08x\n",
+                       __FUNCTION__, PPC4XX_PEIH_REGBASE);
+               return -ENODEV;
+       }
+
+       /* Progam the Interrupt handler Termination addr registers */
+       out_be32(peih_base + PEIH_TERMADH, PPC4XX_PCIE_MSI_HADDR);
+       out_be32(peih_base + PEIH_TERMADL, PPC4XX_PCIE_MSI_LADDR);
+
+       /* Program MSI Expected data and Mask bits */
+       out_be32(peih_base + PEIH_MSIED, PPC4XX_MSI_DATA_PTRN);
+       out_be32(peih_base + PEIH_MSIMK, PPC4XX_MSI_DATA_VALD);
+
+       iounmap(peih_base);
+
+       return 0;       /* success */
+}
+
+
+int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+{
+       /* Setup MSI Capabilities structure for dev func */
+       int pos;
+       u16 control, ctrl;
+
+       printk(KERN_INFO " %s \n",__FUNCTION__);        
+       pos = desc->msi_attrib.pos;
+       pci_read_config_word(dev, msi_control_reg(pos), &control);
+
+       /* Multiple msg enable */
+       ctrl = multi_msi_enable(control, 4);
+       pci_write_config_dword(dev, msi_control_reg(pos), ctrl);
+
+       /* setup MSI address registers */
+       if(is_64bit_address(control))
+               pci_write_config_dword(dev, msi_upper_address_reg(pos), 
PPC4XX_PCIE_MSI_HADDR);
+
+       pci_write_config_dword(dev, msi_lower_address_reg(pos),
+                                       PPC4XX_PCIE_MSI_LADDR);
+
+       if(is_64bit_address(control)) {
+               /* setup MSI data register */
+               pci_write_config_dword(dev, msi_data_reg(pos, 1),
+                                               PPC4XX_MSI_DATA_PTRN_EP);
+               /* setup MSI mask bits reg */
+               pci_write_config_dword(dev, msi_mask_bits_reg(pos, 1), 
0x00000000);
+       }
+       else {
+               pci_write_config_dword(dev, msi_data_reg(pos, 0),
+                                                       
PPC4XX_MSI_DATA_PTRN_EP);
+               pci_write_config_dword(dev, msi_mask_bits_reg(pos, 0), 
0x00000000);
+       }
+               
+       return 0;
+}
+
+int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+       struct msi_desc *entry;
+       int ret;
+
+       list_for_each_entry(entry, &dev->msi_list, list) {
+               ret = arch_setup_msi_irq(dev, entry);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+void ppc4xx_teardown_msi_irqs(struct pci_dev *dev)
+{
+       return;
+}
+
+
+#endif /* CONFIG_PCI_MSI  */
+
 #endif /* CONFIG_PPC4xx_PCI_EXPRESS */
 
 static int __init ppc4xx_pci_find_bridges(void)
@@ -1713,6 +1823,11 @@ static int __init ppc4xx_pci_find_bridges(void)
 #ifdef CONFIG_PPC4xx_PCI_EXPRESS
        for_each_compatible_node(np, NULL, "ibm,plb-pciex")
                ppc4xx_probe_pciex_bridge(np);
+
+#ifdef CONFIG_PCI_MSI
+       ppc4xx_setup_peih();
+#endif
+
 #endif
        for_each_compatible_node(np, NULL, "ibm,plb-pcix")
                ppc4xx_probe_pcix_bridge(np);
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.h b/arch/powerpc/sysdev/ppc4xx_pci.h
index d04e40b..d5fcaa9 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.h
+++ b/arch/powerpc/sysdev/ppc4xx_pci.h
@@ -158,6 +158,51 @@
 #define GPL_DMER_MASK_DISA     0x02000000
 
 /*
+ * 4xx PCIe IRQ Handler register definitions
+ */
+#ifdef CONFIG_PCI_MSI
+
+#if defined(CONFIG_405EX)
+#define PESDR0_4XX_IHS1                                0x04B0
+#define PESDR0_4XX_IHS2                                0x04B1
+#define PPC4XX_PEIH_REGBASE                    0x0EF620000
+#define PPC4XX_PEIH_REGBASE_HADDR      0x0
+#define PPC4XX_PEIH_REGBASE_LADDR      0xEF620000
+#define PPC4XX_PCIE_MSI_ADDR                   0x080000000
+#define PPC4XX_PCIE_MSI_HADDR                  0x0
+#define PPC4XX_PCIE_MSI_LADDR                  0x80000000
+
+#elif defined(CONFIG_460EX)
+#define PESDR0_4XX_IHS1                                0x036C
+#define PESDR0_4XX_IHS2                                0x036D
+#define PPC4XX_PEIH_REGBASE                    0xC10000000
+#define PPC4XX_PEIH_REGBASE_HADDR      0xC
+#define PPC4XX_PEIH_REGBASE_LADDR      0x10000000
+#define PPC4XX_PCIE_MSI_ADDR                   0xe80000000
+#define PPC4XX_PCIE_MSI_HADDR                  0xe
+#define PPC4XX_PCIE_MSI_LADDR                  0x80000000
+#endif
+
+#define PPC4XX_PEIH_REGSIZE       0x100
+#define PPC4XX_MSI_DATA_PTRN      0x44440000
+#define PPC4XX_MSI_DATA_VALD      0xFFFF0000
+#define PPC4XX_MSI_DATA_PTRN_EP   0x00004444
+
+#define PEIH_TERMADH    0x00
+#define PEIH_TERMADL    0x08
+#define PEIH_MSIED      0x10
+#define PEIH_MSIMK      0x18
+#define PEIH_MSIASS     0x20
+#define PEIH_FLUSH0     0x30
+#define PEIH_FLUSH1     0x38
+#define PEIH_CNTRST     0x48
+
+
+#endif         /* CONFIG_PCI_MSI  */
+
+
+
+/*
  * System DCRs (SDRs)
  */
 #define PESDR0_PLLLCT1                 0x03a0
diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h
index 72d2b72..357ba36 100644
--- a/include/asm-powerpc/dcr-native.h
+++ b/include/asm-powerpc/dcr-native.h
@@ -111,6 +111,18 @@ static inline void __dcri_clrset(int base_addr, int 
base_data, int reg,
                                                              DCRN_ ## base ## 
_CONFIG_DATA,    \
                                                              reg, clr, set)
 
+/* SDR read/write helper macros */
+
+#define DCRN_SDR_CONFIG_ADDR    0x00E
+#define DCRN_SDR_CONFIG_DATA    0x00F
+
+#define SDR_READ(offset) ({                    \
+       mtdcr(DCRN_SDR_CONFIG_ADDR, offset);    \
+       mfdcr(DCRN_SDR_CONFIG_DATA);})
+#define SDR_WRITE(offset, data) ({             \
+       mtdcr(DCRN_SDR_CONFIG_ADDR, offset);    \
+       mtdcr(DCRN_SDR_CONFIG_DATA, data);})
+
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_DCR_NATIVE_H */
-- 
1.5.5

_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded

Reply via email to