diff options
Diffstat (limited to 'arch/mips/ath79/pci.c')
-rw-r--r-- | arch/mips/ath79/pci.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c new file mode 100644 index 000000000000..ca83abd9d31e --- /dev/null +++ b/arch/mips/ath79/pci.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * Atheros AR71XX/AR724X specific PCI setup code | ||
3 | * | ||
4 | * Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com> | ||
5 | * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> | ||
6 | * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> | ||
7 | * | ||
8 | * Parts of this file are based on Atheros' 2.6.15 BSP | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License version 2 as published | ||
12 | * by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include <asm/mach-ath79/ar71xx_regs.h> | ||
18 | #include <asm/mach-ath79/ath79.h> | ||
19 | #include <asm/mach-ath79/irq.h> | ||
20 | #include <asm/mach-ath79/pci.h> | ||
21 | #include "pci.h" | ||
22 | |||
23 | static int (*ath79_pci_plat_dev_init)(struct pci_dev *dev); | ||
24 | static const struct ath79_pci_irq *ath79_pci_irq_map __initdata; | ||
25 | static unsigned ath79_pci_nr_irqs __initdata; | ||
26 | |||
27 | static const struct ath79_pci_irq ar71xx_pci_irq_map[] __initconst = { | ||
28 | { | ||
29 | .slot = 17, | ||
30 | .pin = 1, | ||
31 | .irq = ATH79_PCI_IRQ(0), | ||
32 | }, { | ||
33 | .slot = 18, | ||
34 | .pin = 1, | ||
35 | .irq = ATH79_PCI_IRQ(1), | ||
36 | }, { | ||
37 | .slot = 19, | ||
38 | .pin = 1, | ||
39 | .irq = ATH79_PCI_IRQ(2), | ||
40 | } | ||
41 | }; | ||
42 | |||
43 | static const struct ath79_pci_irq ar724x_pci_irq_map[] __initconst = { | ||
44 | { | ||
45 | .slot = 0, | ||
46 | .pin = 1, | ||
47 | .irq = ATH79_PCI_IRQ(0), | ||
48 | } | ||
49 | }; | ||
50 | |||
51 | int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) | ||
52 | { | ||
53 | int irq = -1; | ||
54 | int i; | ||
55 | |||
56 | if (ath79_pci_nr_irqs == 0 || | ||
57 | ath79_pci_irq_map == NULL) { | ||
58 | if (soc_is_ar71xx()) { | ||
59 | ath79_pci_irq_map = ar71xx_pci_irq_map; | ||
60 | ath79_pci_nr_irqs = ARRAY_SIZE(ar71xx_pci_irq_map); | ||
61 | } else if (soc_is_ar724x() || | ||
62 | soc_is_ar9342() || | ||
63 | soc_is_ar9344()) { | ||
64 | ath79_pci_irq_map = ar724x_pci_irq_map; | ||
65 | ath79_pci_nr_irqs = ARRAY_SIZE(ar724x_pci_irq_map); | ||
66 | } else { | ||
67 | pr_crit("pci %s: invalid irq map\n", | ||
68 | pci_name((struct pci_dev *) dev)); | ||
69 | return irq; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | for (i = 0; i < ath79_pci_nr_irqs; i++) { | ||
74 | const struct ath79_pci_irq *entry; | ||
75 | |||
76 | entry = &ath79_pci_irq_map[i]; | ||
77 | if (entry->slot == slot && entry->pin == pin) { | ||
78 | irq = entry->irq; | ||
79 | break; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | if (irq < 0) | ||
84 | pr_crit("pci %s: no irq found for pin %u\n", | ||
85 | pci_name((struct pci_dev *) dev), pin); | ||
86 | else | ||
87 | pr_info("pci %s: using irq %d for pin %u\n", | ||
88 | pci_name((struct pci_dev *) dev), irq, pin); | ||
89 | |||
90 | return irq; | ||
91 | } | ||
92 | |||
93 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
94 | { | ||
95 | if (ath79_pci_plat_dev_init) | ||
96 | return ath79_pci_plat_dev_init(dev); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | void __init ath79_pci_set_irq_map(unsigned nr_irqs, | ||
102 | const struct ath79_pci_irq *map) | ||
103 | { | ||
104 | ath79_pci_nr_irqs = nr_irqs; | ||
105 | ath79_pci_irq_map = map; | ||
106 | } | ||
107 | |||
108 | void __init ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev)) | ||
109 | { | ||
110 | ath79_pci_plat_dev_init = func; | ||
111 | } | ||
112 | |||
113 | int __init ath79_register_pci(void) | ||
114 | { | ||
115 | if (soc_is_ar71xx()) | ||
116 | return ar71xx_pcibios_init(); | ||
117 | |||
118 | if (soc_is_ar724x()) | ||
119 | return ar724x_pcibios_init(ATH79_CPU_IRQ_IP2); | ||
120 | |||
121 | if (soc_is_ar9342() || soc_is_ar9344()) { | ||
122 | u32 bootstrap; | ||
123 | |||
124 | bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); | ||
125 | if (bootstrap & AR934X_BOOTSTRAP_PCIE_RC) | ||
126 | return ar724x_pcibios_init(ATH79_IP2_IRQ(0)); | ||
127 | } | ||
128 | |||
129 | return -ENODEV; | ||
130 | } | ||