diff options
Diffstat (limited to 'arch/mips/ath79/pci.c')
-rw-r--r-- | arch/mips/ath79/pci.c | 165 |
1 files changed, 154 insertions, 11 deletions
diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c index ca83abd9d31e..730c0b03060d 100644 --- a/arch/mips/ath79/pci.c +++ b/arch/mips/ath79/pci.c | |||
@@ -14,10 +14,11 @@ | |||
14 | 14 | ||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/pci.h> | 16 | #include <linux/pci.h> |
17 | #include <linux/resource.h> | ||
18 | #include <linux/platform_device.h> | ||
17 | #include <asm/mach-ath79/ar71xx_regs.h> | 19 | #include <asm/mach-ath79/ar71xx_regs.h> |
18 | #include <asm/mach-ath79/ath79.h> | 20 | #include <asm/mach-ath79/ath79.h> |
19 | #include <asm/mach-ath79/irq.h> | 21 | #include <asm/mach-ath79/irq.h> |
20 | #include <asm/mach-ath79/pci.h> | ||
21 | #include "pci.h" | 22 | #include "pci.h" |
22 | 23 | ||
23 | static int (*ath79_pci_plat_dev_init)(struct pci_dev *dev); | 24 | static int (*ath79_pci_plat_dev_init)(struct pci_dev *dev); |
@@ -48,6 +49,21 @@ static const struct ath79_pci_irq ar724x_pci_irq_map[] __initconst = { | |||
48 | } | 49 | } |
49 | }; | 50 | }; |
50 | 51 | ||
52 | static const struct ath79_pci_irq qca955x_pci_irq_map[] __initconst = { | ||
53 | { | ||
54 | .bus = 0, | ||
55 | .slot = 0, | ||
56 | .pin = 1, | ||
57 | .irq = ATH79_PCI_IRQ(0), | ||
58 | }, | ||
59 | { | ||
60 | .bus = 1, | ||
61 | .slot = 0, | ||
62 | .pin = 1, | ||
63 | .irq = ATH79_PCI_IRQ(1), | ||
64 | }, | ||
65 | }; | ||
66 | |||
51 | int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) | 67 | int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) |
52 | { | 68 | { |
53 | int irq = -1; | 69 | int irq = -1; |
@@ -63,6 +79,9 @@ int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) | |||
63 | soc_is_ar9344()) { | 79 | soc_is_ar9344()) { |
64 | ath79_pci_irq_map = ar724x_pci_irq_map; | 80 | ath79_pci_irq_map = ar724x_pci_irq_map; |
65 | ath79_pci_nr_irqs = ARRAY_SIZE(ar724x_pci_irq_map); | 81 | ath79_pci_nr_irqs = ARRAY_SIZE(ar724x_pci_irq_map); |
82 | } else if (soc_is_qca955x()) { | ||
83 | ath79_pci_irq_map = qca955x_pci_irq_map; | ||
84 | ath79_pci_nr_irqs = ARRAY_SIZE(qca955x_pci_irq_map); | ||
66 | } else { | 85 | } else { |
67 | pr_crit("pci %s: invalid irq map\n", | 86 | pr_crit("pci %s: invalid irq map\n", |
68 | pci_name((struct pci_dev *) dev)); | 87 | pci_name((struct pci_dev *) dev)); |
@@ -74,7 +93,9 @@ int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) | |||
74 | const struct ath79_pci_irq *entry; | 93 | const struct ath79_pci_irq *entry; |
75 | 94 | ||
76 | entry = &ath79_pci_irq_map[i]; | 95 | entry = &ath79_pci_irq_map[i]; |
77 | if (entry->slot == slot && entry->pin == pin) { | 96 | if (entry->bus == dev->bus->number && |
97 | entry->slot == slot && | ||
98 | entry->pin == pin) { | ||
78 | irq = entry->irq; | 99 | irq = entry->irq; |
79 | break; | 100 | break; |
80 | } | 101 | } |
@@ -110,21 +131,143 @@ void __init ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev)) | |||
110 | ath79_pci_plat_dev_init = func; | 131 | ath79_pci_plat_dev_init = func; |
111 | } | 132 | } |
112 | 133 | ||
113 | int __init ath79_register_pci(void) | 134 | static struct platform_device * |
135 | ath79_register_pci_ar71xx(void) | ||
136 | { | ||
137 | struct platform_device *pdev; | ||
138 | struct resource res[4]; | ||
139 | |||
140 | memset(res, 0, sizeof(res)); | ||
141 | |||
142 | res[0].name = "cfg_base"; | ||
143 | res[0].flags = IORESOURCE_MEM; | ||
144 | res[0].start = AR71XX_PCI_CFG_BASE; | ||
145 | res[0].end = AR71XX_PCI_CFG_BASE + AR71XX_PCI_CFG_SIZE - 1; | ||
146 | |||
147 | res[1].flags = IORESOURCE_IRQ; | ||
148 | res[1].start = ATH79_CPU_IRQ(2); | ||
149 | res[1].end = ATH79_CPU_IRQ(2); | ||
150 | |||
151 | res[2].name = "io_base"; | ||
152 | res[2].flags = IORESOURCE_IO; | ||
153 | res[2].start = 0; | ||
154 | res[2].end = 0; | ||
155 | |||
156 | res[3].name = "mem_base"; | ||
157 | res[3].flags = IORESOURCE_MEM; | ||
158 | res[3].start = AR71XX_PCI_MEM_BASE; | ||
159 | res[3].end = AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1; | ||
160 | |||
161 | pdev = platform_device_register_simple("ar71xx-pci", -1, | ||
162 | res, ARRAY_SIZE(res)); | ||
163 | return pdev; | ||
164 | } | ||
165 | |||
166 | static struct platform_device * | ||
167 | ath79_register_pci_ar724x(int id, | ||
168 | unsigned long cfg_base, | ||
169 | unsigned long ctrl_base, | ||
170 | unsigned long crp_base, | ||
171 | unsigned long mem_base, | ||
172 | unsigned long mem_size, | ||
173 | unsigned long io_base, | ||
174 | int irq) | ||
114 | { | 175 | { |
115 | if (soc_is_ar71xx()) | 176 | struct platform_device *pdev; |
116 | return ar71xx_pcibios_init(); | 177 | struct resource res[6]; |
178 | |||
179 | memset(res, 0, sizeof(res)); | ||
180 | |||
181 | res[0].name = "cfg_base"; | ||
182 | res[0].flags = IORESOURCE_MEM; | ||
183 | res[0].start = cfg_base; | ||
184 | res[0].end = cfg_base + AR724X_PCI_CFG_SIZE - 1; | ||
185 | |||
186 | res[1].name = "ctrl_base"; | ||
187 | res[1].flags = IORESOURCE_MEM; | ||
188 | res[1].start = ctrl_base; | ||
189 | res[1].end = ctrl_base + AR724X_PCI_CTRL_SIZE - 1; | ||
190 | |||
191 | res[2].flags = IORESOURCE_IRQ; | ||
192 | res[2].start = irq; | ||
193 | res[2].end = irq; | ||
194 | |||
195 | res[3].name = "mem_base"; | ||
196 | res[3].flags = IORESOURCE_MEM; | ||
197 | res[3].start = mem_base; | ||
198 | res[3].end = mem_base + mem_size - 1; | ||
199 | |||
200 | res[4].name = "io_base"; | ||
201 | res[4].flags = IORESOURCE_IO; | ||
202 | res[4].start = io_base; | ||
203 | res[4].end = io_base; | ||
117 | 204 | ||
118 | if (soc_is_ar724x()) | 205 | res[5].name = "crp_base"; |
119 | return ar724x_pcibios_init(ATH79_CPU_IRQ_IP2); | 206 | res[5].flags = IORESOURCE_MEM; |
207 | res[5].start = crp_base; | ||
208 | res[5].end = crp_base + AR724X_PCI_CRP_SIZE - 1; | ||
120 | 209 | ||
121 | if (soc_is_ar9342() || soc_is_ar9344()) { | 210 | pdev = platform_device_register_simple("ar724x-pci", id, |
211 | res, ARRAY_SIZE(res)); | ||
212 | return pdev; | ||
213 | } | ||
214 | |||
215 | int __init ath79_register_pci(void) | ||
216 | { | ||
217 | struct platform_device *pdev = NULL; | ||
218 | |||
219 | if (soc_is_ar71xx()) { | ||
220 | pdev = ath79_register_pci_ar71xx(); | ||
221 | } else if (soc_is_ar724x()) { | ||
222 | pdev = ath79_register_pci_ar724x(-1, | ||
223 | AR724X_PCI_CFG_BASE, | ||
224 | AR724X_PCI_CTRL_BASE, | ||
225 | AR724X_PCI_CRP_BASE, | ||
226 | AR724X_PCI_MEM_BASE, | ||
227 | AR724X_PCI_MEM_SIZE, | ||
228 | 0, | ||
229 | ATH79_CPU_IRQ(2)); | ||
230 | } else if (soc_is_ar9342() || | ||
231 | soc_is_ar9344()) { | ||
122 | u32 bootstrap; | 232 | u32 bootstrap; |
123 | 233 | ||
124 | bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); | 234 | bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); |
125 | if (bootstrap & AR934X_BOOTSTRAP_PCIE_RC) | 235 | if ((bootstrap & AR934X_BOOTSTRAP_PCIE_RC) == 0) |
126 | return ar724x_pcibios_init(ATH79_IP2_IRQ(0)); | 236 | return -ENODEV; |
237 | |||
238 | pdev = ath79_register_pci_ar724x(-1, | ||
239 | AR724X_PCI_CFG_BASE, | ||
240 | AR724X_PCI_CTRL_BASE, | ||
241 | AR724X_PCI_CRP_BASE, | ||
242 | AR724X_PCI_MEM_BASE, | ||
243 | AR724X_PCI_MEM_SIZE, | ||
244 | 0, | ||
245 | ATH79_IP2_IRQ(0)); | ||
246 | } else if (soc_is_qca9558()) { | ||
247 | pdev = ath79_register_pci_ar724x(0, | ||
248 | QCA955X_PCI_CFG_BASE0, | ||
249 | QCA955X_PCI_CTRL_BASE0, | ||
250 | QCA955X_PCI_CRP_BASE0, | ||
251 | QCA955X_PCI_MEM_BASE0, | ||
252 | QCA955X_PCI_MEM_SIZE, | ||
253 | 0, | ||
254 | ATH79_IP2_IRQ(0)); | ||
255 | |||
256 | pdev = ath79_register_pci_ar724x(1, | ||
257 | QCA955X_PCI_CFG_BASE1, | ||
258 | QCA955X_PCI_CTRL_BASE1, | ||
259 | QCA955X_PCI_CRP_BASE1, | ||
260 | QCA955X_PCI_MEM_BASE1, | ||
261 | QCA955X_PCI_MEM_SIZE, | ||
262 | 1, | ||
263 | ATH79_IP3_IRQ(2)); | ||
264 | } else { | ||
265 | /* No PCI support */ | ||
266 | return -ENODEV; | ||
127 | } | 267 | } |
128 | 268 | ||
129 | return -ENODEV; | 269 | if (!pdev) |
270 | pr_err("unable to register PCI controller device\n"); | ||
271 | |||
272 | return pdev ? 0 : -ENODEV; | ||
130 | } | 273 | } |