aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
authorLan Chunhe-B25806 <B25806@freescale.com>2010-03-15 02:38:33 -0400
committerKumar Gala <galak@kernel.crashing.org>2010-05-24 22:26:21 -0400
commit8081881327d4791f26ebf56cf304992673503ad4 (patch)
tree8bed0fd8f0fb0e0637ab0775728caeeff58d30ed /arch/powerpc/sysdev
parentb3df895aebe091b1657a42a8c859bd49fc96646b (diff)
powerpc/fsl_msi: Add multiple MSI bank support
Freescale QorIQ P4080 has three MSI banks and the original code can not work well. This patch adds multiple MSI banks support for Freescale processor. Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com> Signed-off-by: Roy Zang <tie-fei.zang@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 3482e3fd89c0..c84fbb1c1b42 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2007-2008 Freescale Semiconductor, Inc. All rights reserved. 2 * Copyright (C) 2007-2010 Freescale Semiconductor, Inc.
3 * 3 *
4 * Author: Tony Li <tony.li@freescale.com> 4 * Author: Tony Li <tony.li@freescale.com>
5 * Jason Jin <Jason.jin@freescale.com> 5 * Jason Jin <Jason.jin@freescale.com>
@@ -29,7 +29,6 @@ struct fsl_msi_feature {
29 u32 msiir_offset; 29 u32 msiir_offset;
30}; 30};
31 31
32static struct fsl_msi *fsl_msi;
33 32
34static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg) 33static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg)
35{ 34{
@@ -54,10 +53,12 @@ static struct irq_chip fsl_msi_chip = {
54static int fsl_msi_host_map(struct irq_host *h, unsigned int virq, 53static int fsl_msi_host_map(struct irq_host *h, unsigned int virq,
55 irq_hw_number_t hw) 54 irq_hw_number_t hw)
56{ 55{
56 struct fsl_msi *msi_data = h->host_data;
57 struct irq_chip *chip = &fsl_msi_chip; 57 struct irq_chip *chip = &fsl_msi_chip;
58 58
59 irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING; 59 irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING;
60 60
61 set_irq_chip_data(virq, msi_data);
61 set_irq_chip_and_handler(virq, chip, handle_edge_irq); 62 set_irq_chip_and_handler(virq, chip, handle_edge_irq);
62 63
63 return 0; 64 return 0;
@@ -96,11 +97,12 @@ static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type)
96static void fsl_teardown_msi_irqs(struct pci_dev *pdev) 97static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
97{ 98{
98 struct msi_desc *entry; 99 struct msi_desc *entry;
99 struct fsl_msi *msi_data = fsl_msi; 100 struct fsl_msi *msi_data;
100 101
101 list_for_each_entry(entry, &pdev->msi_list, list) { 102 list_for_each_entry(entry, &pdev->msi_list, list) {
102 if (entry->irq == NO_IRQ) 103 if (entry->irq == NO_IRQ)
103 continue; 104 continue;
105 msi_data = get_irq_chip_data(entry->irq);
104 set_irq_msi(entry->irq, NULL); 106 set_irq_msi(entry->irq, NULL);
105 msi_bitmap_free_hwirqs(&msi_data->bitmap, 107 msi_bitmap_free_hwirqs(&msi_data->bitmap,
106 virq_to_hw(entry->irq), 1); 108 virq_to_hw(entry->irq), 1);
@@ -111,9 +113,10 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
111} 113}
112 114
113static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, 115static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
114 struct msi_msg *msg) 116 struct msi_msg *msg,
117 struct fsl_msi *fsl_msi_data)
115{ 118{
116 struct fsl_msi *msi_data = fsl_msi; 119 struct fsl_msi *msi_data = fsl_msi_data;
117 struct pci_controller *hose = pci_bus_to_host(pdev->bus); 120 struct pci_controller *hose = pci_bus_to_host(pdev->bus);
118 u32 base = 0; 121 u32 base = 0;
119 122
@@ -134,9 +137,11 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
134 unsigned int virq; 137 unsigned int virq;
135 struct msi_desc *entry; 138 struct msi_desc *entry;
136 struct msi_msg msg; 139 struct msi_msg msg;
137 struct fsl_msi *msi_data = fsl_msi; 140 struct fsl_msi *msi_data;
138 141
139 list_for_each_entry(entry, &pdev->msi_list, list) { 142 list_for_each_entry(entry, &pdev->msi_list, list) {
143 msi_data = get_irq_chip_data(entry->irq);
144
140 hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); 145 hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
141 if (hwirq < 0) { 146 if (hwirq < 0) {
142 rc = hwirq; 147 rc = hwirq;
@@ -156,7 +161,7 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
156 } 161 }
157 set_irq_msi(virq, entry); 162 set_irq_msi(virq, entry);
158 163
159 fsl_compose_msi_msg(pdev, hwirq, &msg); 164 fsl_compose_msi_msg(pdev, hwirq, &msg, msi_data);
160 write_msi_msg(virq, &msg); 165 write_msi_msg(virq, &msg);
161 } 166 }
162 return 0; 167 return 0;
@@ -168,7 +173,7 @@ out_free:
168static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) 173static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
169{ 174{
170 unsigned int cascade_irq; 175 unsigned int cascade_irq;
171 struct fsl_msi *msi_data = fsl_msi; 176 struct fsl_msi *msi_data = get_irq_chip_data(irq);
172 int msir_index = -1; 177 int msir_index = -1;
173 u32 msir_value = 0; 178 u32 msir_value = 0;
174 u32 intr_index; 179 u32 intr_index;
@@ -193,7 +198,7 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
193 cascade_irq = NO_IRQ; 198 cascade_irq = NO_IRQ;
194 199
195 desc->status |= IRQ_INPROGRESS; 200 desc->status |= IRQ_INPROGRESS;
196 switch (fsl_msi->feature & FSL_PIC_IP_MASK) { 201 switch (msi_data->feature & FSL_PIC_IP_MASK) {
197 case FSL_PIC_IP_MPIC: 202 case FSL_PIC_IP_MPIC:
198 msir_value = fsl_msi_read(msi_data->msi_regs, 203 msir_value = fsl_msi_read(msi_data->msi_regs,
199 msir_index * 0x10); 204 msir_index * 0x10);
@@ -307,15 +312,20 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
307 if (virt_msir != NO_IRQ) { 312 if (virt_msir != NO_IRQ) {
308 set_irq_data(virt_msir, (void *)i); 313 set_irq_data(virt_msir, (void *)i);
309 set_irq_chained_handler(virt_msir, fsl_msi_cascade); 314 set_irq_chained_handler(virt_msir, fsl_msi_cascade);
315 set_irq_chip_data(virt_msir, msi);
310 } 316 }
311 } 317 }
312 318
313 fsl_msi = msi; 319 /* The multiple setting ppc_md.setup_msi_irqs will not harm things */
314 320 if (!ppc_md.setup_msi_irqs) {
315 WARN_ON(ppc_md.setup_msi_irqs); 321 ppc_md.setup_msi_irqs = fsl_setup_msi_irqs;
316 ppc_md.setup_msi_irqs = fsl_setup_msi_irqs; 322 ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs;
317 ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs; 323 ppc_md.msi_check_device = fsl_msi_check_device;
318 ppc_md.msi_check_device = fsl_msi_check_device; 324 } else if (ppc_md.setup_msi_irqs != fsl_setup_msi_irqs) {
325 dev_err(&dev->dev, "Different MSI driver already installed!\n");
326 err = -ENODEV;
327 goto error_out;
328 }
319 return 0; 329 return 0;
320error_out: 330error_out:
321 kfree(msi); 331 kfree(msi);