diff options
-rw-r--r-- | Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt | 3 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt | 14 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/pci/mvebu-pci.txt | 10 | ||||
-rw-r--r-- | arch/arm/mach-dove/board-dt.c | 39 | ||||
-rw-r--r-- | drivers/irqchip/irq-armada-370-xp.c | 202 | ||||
-rw-r--r-- | drivers/pci/host/Kconfig | 2 | ||||
-rw-r--r-- | drivers/pci/host/pci-mvebu.c | 121 |
7 files changed, 307 insertions, 84 deletions
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt index 61df564c0d23..d74091a8a3bf 100644 --- a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt +++ b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt | |||
@@ -4,6 +4,8 @@ Marvell Armada 370 and Armada XP Interrupt Controller | |||
4 | Required properties: | 4 | Required properties: |
5 | - compatible: Should be "marvell,mpic" | 5 | - compatible: Should be "marvell,mpic" |
6 | - interrupt-controller: Identifies the node as an interrupt controller. | 6 | - interrupt-controller: Identifies the node as an interrupt controller. |
7 | - msi-controller: Identifies the node as an PCI Message Signaled | ||
8 | Interrupt controller. | ||
7 | - #interrupt-cells: The number of cells to define the interrupts. Should be 1. | 9 | - #interrupt-cells: The number of cells to define the interrupts. Should be 1. |
8 | The cell is the IRQ number | 10 | The cell is the IRQ number |
9 | 11 | ||
@@ -24,6 +26,7 @@ Example: | |||
24 | #address-cells = <1>; | 26 | #address-cells = <1>; |
25 | #size-cells = <1>; | 27 | #size-cells = <1>; |
26 | interrupt-controller; | 28 | interrupt-controller; |
29 | msi-controller; | ||
27 | reg = <0xd0020a00 0x1d0>, | 30 | reg = <0xd0020a00 0x1d0>, |
28 | <0xd0021070 0x58>; | 31 | <0xd0021070 0x58>; |
29 | }; | 32 | }; |
diff --git a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt index cffc93d97f54..fc2910fa7e45 100644 --- a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt +++ b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt | |||
@@ -1,10 +1,10 @@ | |||
1 | * Gated Clock bindings for Marvell Orion SoCs | 1 | * Gated Clock bindings for Marvell EBU SoCs |
2 | 2 | ||
3 | Marvell Dove and Kirkwood allow some peripheral clocks to be gated to save | 3 | Marvell Armada 370/XP, Dove and Kirkwood allow some peripheral clocks to be |
4 | some power. The clock consumer should specify the desired clock by having | 4 | gated to save some power. The clock consumer should specify the desired clock |
5 | the clock ID in its "clocks" phandle cell. The clock ID is directly mapped to | 5 | by having the clock ID in its "clocks" phandle cell. The clock ID is directly |
6 | the corresponding clock gating control bit in HW to ease manual clock lookup | 6 | mapped to the corresponding clock gating control bit in HW to ease manual clock |
7 | in datasheet. | 7 | lookup in datasheet. |
8 | 8 | ||
9 | The following is a list of provided IDs for Armada 370: | 9 | The following is a list of provided IDs for Armada 370: |
10 | ID Clock Peripheral | 10 | ID Clock Peripheral |
@@ -94,6 +94,8 @@ ID Clock Peripheral | |||
94 | 94 | ||
95 | Required properties: | 95 | Required properties: |
96 | - compatible : shall be one of the following: | 96 | - compatible : shall be one of the following: |
97 | "marvell,armada-370-gating-clock" - for Armada 370 SoC clock gating | ||
98 | "marvell,armada-xp-gating-clock" - for Armada XP SoC clock gating | ||
97 | "marvell,dove-gating-clock" - for Dove SoC clock gating | 99 | "marvell,dove-gating-clock" - for Dove SoC clock gating |
98 | "marvell,kirkwood-gating-clock" - for Kirkwood SoC clock gating | 100 | "marvell,kirkwood-gating-clock" - for Kirkwood SoC clock gating |
99 | - reg : shall be the register address of the Clock Gating Control register | 101 | - reg : shall be the register address of the Clock Gating Control register |
diff --git a/Documentation/devicetree/bindings/pci/mvebu-pci.txt b/Documentation/devicetree/bindings/pci/mvebu-pci.txt index 9556e2fedf6d..08c716b2c6b6 100644 --- a/Documentation/devicetree/bindings/pci/mvebu-pci.txt +++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt | |||
@@ -5,6 +5,7 @@ Mandatory properties: | |||
5 | - compatible: one of the following values: | 5 | - compatible: one of the following values: |
6 | marvell,armada-370-pcie | 6 | marvell,armada-370-pcie |
7 | marvell,armada-xp-pcie | 7 | marvell,armada-xp-pcie |
8 | marvell,dove-pcie | ||
8 | marvell,kirkwood-pcie | 9 | marvell,kirkwood-pcie |
9 | - #address-cells, set to <3> | 10 | - #address-cells, set to <3> |
10 | - #size-cells, set to <2> | 11 | - #size-cells, set to <2> |
@@ -14,6 +15,8 @@ Mandatory properties: | |||
14 | - ranges: ranges describing the MMIO registers to control the PCIe | 15 | - ranges: ranges describing the MMIO registers to control the PCIe |
15 | interfaces, and ranges describing the MBus windows needed to access | 16 | interfaces, and ranges describing the MBus windows needed to access |
16 | the memory and I/O regions of each PCIe interface. | 17 | the memory and I/O regions of each PCIe interface. |
18 | - msi-parent: Link to the hardware entity that serves as the Message | ||
19 | Signaled Interrupt controller for this PCI controller. | ||
17 | 20 | ||
18 | The ranges describing the MMIO registers have the following layout: | 21 | The ranges describing the MMIO registers have the following layout: |
19 | 22 | ||
@@ -74,6 +77,8 @@ and the following optional properties: | |||
74 | - marvell,pcie-lane: the physical PCIe lane number, for ports having | 77 | - marvell,pcie-lane: the physical PCIe lane number, for ports having |
75 | multiple lanes. If this property is not found, we assume that the | 78 | multiple lanes. If this property is not found, we assume that the |
76 | value is 0. | 79 | value is 0. |
80 | - reset-gpios: optional gpio to PERST# | ||
81 | - reset-delay-us: delay in us to wait after reset de-assertion | ||
77 | 82 | ||
78 | Example: | 83 | Example: |
79 | 84 | ||
@@ -86,6 +91,7 @@ pcie-controller { | |||
86 | #size-cells = <2>; | 91 | #size-cells = <2>; |
87 | 92 | ||
88 | bus-range = <0x00 0xff>; | 93 | bus-range = <0x00 0xff>; |
94 | msi-parent = <&mpic>; | ||
89 | 95 | ||
90 | ranges = | 96 | ranges = |
91 | <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000 /* Port 0.0 registers */ | 97 | <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000 /* Port 0.0 registers */ |
@@ -135,6 +141,10 @@ pcie-controller { | |||
135 | interrupt-map = <0 0 0 0 &mpic 58>; | 141 | interrupt-map = <0 0 0 0 &mpic 58>; |
136 | marvell,pcie-port = <0>; | 142 | marvell,pcie-port = <0>; |
137 | marvell,pcie-lane = <0>; | 143 | marvell,pcie-lane = <0>; |
144 | /* low-active PERST# reset on GPIO 25 */ | ||
145 | reset-gpios = <&gpio0 25 1>; | ||
146 | /* wait 20ms for device settle after reset deassertion */ | ||
147 | reset-delay-us = <20000>; | ||
138 | clocks = <&gateclk 5>; | 148 | clocks = <&gateclk 5>; |
139 | status = "disabled"; | 149 | status = "disabled"; |
140 | }; | 150 | }; |
diff --git a/arch/arm/mach-dove/board-dt.c b/arch/arm/mach-dove/board-dt.c index 49f72a848423..9a116d796323 100644 --- a/arch/arm/mach-dove/board-dt.c +++ b/arch/arm/mach-dove/board-dt.c | |||
@@ -23,41 +23,12 @@ | |||
23 | #include <plat/irq.h> | 23 | #include <plat/irq.h> |
24 | #include "common.h" | 24 | #include "common.h" |
25 | 25 | ||
26 | /* | ||
27 | * There are still devices that doesn't even know about DT, | ||
28 | * get clock gates here and add a clock lookup. | ||
29 | */ | ||
30 | static void __init dove_legacy_clk_init(void) | ||
31 | { | ||
32 | struct device_node *np = of_find_compatible_node(NULL, NULL, | ||
33 | "marvell,dove-gating-clock"); | ||
34 | struct of_phandle_args clkspec; | ||
35 | |||
36 | clkspec.np = np; | ||
37 | clkspec.args_count = 1; | ||
38 | |||
39 | clkspec.args[0] = CLOCK_GATING_BIT_PCIE0; | ||
40 | orion_clkdev_add("0", "pcie", | ||
41 | of_clk_get_from_provider(&clkspec)); | ||
42 | |||
43 | clkspec.args[0] = CLOCK_GATING_BIT_PCIE1; | ||
44 | orion_clkdev_add("1", "pcie", | ||
45 | of_clk_get_from_provider(&clkspec)); | ||
46 | } | ||
47 | |||
48 | static void __init dove_dt_time_init(void) | 26 | static void __init dove_dt_time_init(void) |
49 | { | 27 | { |
50 | of_clk_init(NULL); | 28 | of_clk_init(NULL); |
51 | clocksource_of_init(); | 29 | clocksource_of_init(); |
52 | } | 30 | } |
53 | 31 | ||
54 | static void __init dove_dt_init_early(void) | ||
55 | { | ||
56 | mvebu_mbus_init("marvell,dove-mbus", | ||
57 | BRIDGE_WINS_BASE, BRIDGE_WINS_SZ, | ||
58 | DOVE_MC_WINS_BASE, DOVE_MC_WINS_SZ); | ||
59 | } | ||
60 | |||
61 | static void __init dove_dt_init(void) | 32 | static void __init dove_dt_init(void) |
62 | { | 33 | { |
63 | pr_info("Dove 88AP510 SoC\n"); | 34 | pr_info("Dove 88AP510 SoC\n"); |
@@ -65,14 +36,7 @@ static void __init dove_dt_init(void) | |||
65 | #ifdef CONFIG_CACHE_TAUROS2 | 36 | #ifdef CONFIG_CACHE_TAUROS2 |
66 | tauros2_init(0); | 37 | tauros2_init(0); |
67 | #endif | 38 | #endif |
68 | dove_setup_cpu_wins(); | 39 | BUG_ON(mvebu_mbus_dt_init()); |
69 | |||
70 | /* Setup clocks for legacy devices */ | ||
71 | dove_legacy_clk_init(); | ||
72 | |||
73 | /* Internal devices not ported to DT yet */ | ||
74 | dove_pcie_init(1, 1); | ||
75 | |||
76 | of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); | 40 | of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); |
77 | } | 41 | } |
78 | 42 | ||
@@ -83,7 +47,6 @@ static const char * const dove_dt_board_compat[] = { | |||
83 | 47 | ||
84 | DT_MACHINE_START(DOVE_DT, "Marvell Dove (Flattened Device Tree)") | 48 | DT_MACHINE_START(DOVE_DT, "Marvell Dove (Flattened Device Tree)") |
85 | .map_io = dove_map_io, | 49 | .map_io = dove_map_io, |
86 | .init_early = dove_dt_init_early, | ||
87 | .init_time = dove_dt_time_init, | 50 | .init_time = dove_dt_time_init, |
88 | .init_machine = dove_dt_init, | 51 | .init_machine = dove_dt_init, |
89 | .restart = dove_restart, | 52 | .restart = dove_restart, |
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index bb328a366122..433cc8568dec 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c | |||
@@ -21,7 +21,10 @@ | |||
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <linux/of_address.h> | 22 | #include <linux/of_address.h> |
23 | #include <linux/of_irq.h> | 23 | #include <linux/of_irq.h> |
24 | #include <linux/of_pci.h> | ||
24 | #include <linux/irqdomain.h> | 25 | #include <linux/irqdomain.h> |
26 | #include <linux/slab.h> | ||
27 | #include <linux/msi.h> | ||
25 | #include <asm/mach/arch.h> | 28 | #include <asm/mach/arch.h> |
26 | #include <asm/exception.h> | 29 | #include <asm/exception.h> |
27 | #include <asm/smp_plat.h> | 30 | #include <asm/smp_plat.h> |
@@ -51,12 +54,22 @@ | |||
51 | #define IPI_DOORBELL_START (0) | 54 | #define IPI_DOORBELL_START (0) |
52 | #define IPI_DOORBELL_END (8) | 55 | #define IPI_DOORBELL_END (8) |
53 | #define IPI_DOORBELL_MASK 0xFF | 56 | #define IPI_DOORBELL_MASK 0xFF |
57 | #define PCI_MSI_DOORBELL_START (16) | ||
58 | #define PCI_MSI_DOORBELL_NR (16) | ||
59 | #define PCI_MSI_DOORBELL_END (32) | ||
60 | #define PCI_MSI_DOORBELL_MASK 0xFFFF0000 | ||
54 | 61 | ||
55 | static DEFINE_RAW_SPINLOCK(irq_controller_lock); | 62 | static DEFINE_RAW_SPINLOCK(irq_controller_lock); |
56 | 63 | ||
57 | static void __iomem *per_cpu_int_base; | 64 | static void __iomem *per_cpu_int_base; |
58 | static void __iomem *main_int_base; | 65 | static void __iomem *main_int_base; |
59 | static struct irq_domain *armada_370_xp_mpic_domain; | 66 | static struct irq_domain *armada_370_xp_mpic_domain; |
67 | #ifdef CONFIG_PCI_MSI | ||
68 | static struct irq_domain *armada_370_xp_msi_domain; | ||
69 | static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR); | ||
70 | static DEFINE_MUTEX(msi_used_lock); | ||
71 | static phys_addr_t msi_doorbell_addr; | ||
72 | #endif | ||
60 | 73 | ||
61 | /* | 74 | /* |
62 | * In SMP mode: | 75 | * In SMP mode: |
@@ -87,6 +100,144 @@ static void armada_370_xp_irq_unmask(struct irq_data *d) | |||
87 | ARMADA_370_XP_INT_CLEAR_MASK_OFFS); | 100 | ARMADA_370_XP_INT_CLEAR_MASK_OFFS); |
88 | } | 101 | } |
89 | 102 | ||
103 | #ifdef CONFIG_PCI_MSI | ||
104 | |||
105 | static int armada_370_xp_alloc_msi(void) | ||
106 | { | ||
107 | int hwirq; | ||
108 | |||
109 | mutex_lock(&msi_used_lock); | ||
110 | hwirq = find_first_zero_bit(&msi_used, PCI_MSI_DOORBELL_NR); | ||
111 | if (hwirq >= PCI_MSI_DOORBELL_NR) | ||
112 | hwirq = -ENOSPC; | ||
113 | else | ||
114 | set_bit(hwirq, msi_used); | ||
115 | mutex_unlock(&msi_used_lock); | ||
116 | |||
117 | return hwirq; | ||
118 | } | ||
119 | |||
120 | static void armada_370_xp_free_msi(int hwirq) | ||
121 | { | ||
122 | mutex_lock(&msi_used_lock); | ||
123 | if (!test_bit(hwirq, msi_used)) | ||
124 | pr_err("trying to free unused MSI#%d\n", hwirq); | ||
125 | else | ||
126 | clear_bit(hwirq, msi_used); | ||
127 | mutex_unlock(&msi_used_lock); | ||
128 | } | ||
129 | |||
130 | static int armada_370_xp_setup_msi_irq(struct msi_chip *chip, | ||
131 | struct pci_dev *pdev, | ||
132 | struct msi_desc *desc) | ||
133 | { | ||
134 | struct msi_msg msg; | ||
135 | irq_hw_number_t hwirq; | ||
136 | int virq; | ||
137 | |||
138 | hwirq = armada_370_xp_alloc_msi(); | ||
139 | if (hwirq < 0) | ||
140 | return hwirq; | ||
141 | |||
142 | virq = irq_create_mapping(armada_370_xp_msi_domain, hwirq); | ||
143 | if (!virq) { | ||
144 | armada_370_xp_free_msi(hwirq); | ||
145 | return -EINVAL; | ||
146 | } | ||
147 | |||
148 | irq_set_msi_desc(virq, desc); | ||
149 | |||
150 | msg.address_lo = msi_doorbell_addr; | ||
151 | msg.address_hi = 0; | ||
152 | msg.data = 0xf00 | (hwirq + 16); | ||
153 | |||
154 | write_msi_msg(virq, &msg); | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip, | ||
159 | unsigned int irq) | ||
160 | { | ||
161 | struct irq_data *d = irq_get_irq_data(irq); | ||
162 | irq_dispose_mapping(irq); | ||
163 | armada_370_xp_free_msi(d->hwirq); | ||
164 | } | ||
165 | |||
166 | static struct irq_chip armada_370_xp_msi_irq_chip = { | ||
167 | .name = "armada_370_xp_msi_irq", | ||
168 | .irq_enable = unmask_msi_irq, | ||
169 | .irq_disable = mask_msi_irq, | ||
170 | .irq_mask = mask_msi_irq, | ||
171 | .irq_unmask = unmask_msi_irq, | ||
172 | }; | ||
173 | |||
174 | static int armada_370_xp_msi_map(struct irq_domain *domain, unsigned int virq, | ||
175 | irq_hw_number_t hw) | ||
176 | { | ||
177 | irq_set_chip_and_handler(virq, &armada_370_xp_msi_irq_chip, | ||
178 | handle_simple_irq); | ||
179 | set_irq_flags(virq, IRQF_VALID); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static const struct irq_domain_ops armada_370_xp_msi_irq_ops = { | ||
185 | .map = armada_370_xp_msi_map, | ||
186 | }; | ||
187 | |||
188 | static int armada_370_xp_msi_init(struct device_node *node, | ||
189 | phys_addr_t main_int_phys_base) | ||
190 | { | ||
191 | struct msi_chip *msi_chip; | ||
192 | u32 reg; | ||
193 | int ret; | ||
194 | |||
195 | msi_doorbell_addr = main_int_phys_base + | ||
196 | ARMADA_370_XP_SW_TRIG_INT_OFFS; | ||
197 | |||
198 | msi_chip = kzalloc(sizeof(*msi_chip), GFP_KERNEL); | ||
199 | if (!msi_chip) | ||
200 | return -ENOMEM; | ||
201 | |||
202 | msi_chip->setup_irq = armada_370_xp_setup_msi_irq; | ||
203 | msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq; | ||
204 | msi_chip->of_node = node; | ||
205 | |||
206 | armada_370_xp_msi_domain = | ||
207 | irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR, | ||
208 | &armada_370_xp_msi_irq_ops, | ||
209 | NULL); | ||
210 | if (!armada_370_xp_msi_domain) { | ||
211 | kfree(msi_chip); | ||
212 | return -ENOMEM; | ||
213 | } | ||
214 | |||
215 | ret = of_pci_msi_chip_add(msi_chip); | ||
216 | if (ret < 0) { | ||
217 | irq_domain_remove(armada_370_xp_msi_domain); | ||
218 | kfree(msi_chip); | ||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS) | ||
223 | | PCI_MSI_DOORBELL_MASK; | ||
224 | |||
225 | writel(reg, per_cpu_int_base + | ||
226 | ARMADA_370_XP_IN_DRBEL_MSK_OFFS); | ||
227 | |||
228 | /* Unmask IPI interrupt */ | ||
229 | writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | #else | ||
234 | static inline int armada_370_xp_msi_init(struct device_node *node, | ||
235 | phys_addr_t main_int_phys_base) | ||
236 | { | ||
237 | return 0; | ||
238 | } | ||
239 | #endif | ||
240 | |||
90 | #ifdef CONFIG_SMP | 241 | #ifdef CONFIG_SMP |
91 | static int armada_xp_set_affinity(struct irq_data *d, | 242 | static int armada_xp_set_affinity(struct irq_data *d, |
92 | const struct cpumask *mask_val, bool force) | 243 | const struct cpumask *mask_val, bool force) |
@@ -214,12 +365,39 @@ armada_370_xp_handle_irq(struct pt_regs *regs) | |||
214 | if (irqnr > 1022) | 365 | if (irqnr > 1022) |
215 | break; | 366 | break; |
216 | 367 | ||
217 | if (irqnr > 0) { | 368 | if (irqnr > 1) { |
218 | irqnr = irq_find_mapping(armada_370_xp_mpic_domain, | 369 | irqnr = irq_find_mapping(armada_370_xp_mpic_domain, |
219 | irqnr); | 370 | irqnr); |
220 | handle_IRQ(irqnr, regs); | 371 | handle_IRQ(irqnr, regs); |
221 | continue; | 372 | continue; |
222 | } | 373 | } |
374 | |||
375 | #ifdef CONFIG_PCI_MSI | ||
376 | /* MSI handling */ | ||
377 | if (irqnr == 1) { | ||
378 | u32 msimask, msinr; | ||
379 | |||
380 | msimask = readl_relaxed(per_cpu_int_base + | ||
381 | ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS) | ||
382 | & PCI_MSI_DOORBELL_MASK; | ||
383 | |||
384 | writel(~PCI_MSI_DOORBELL_MASK, per_cpu_int_base + | ||
385 | ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); | ||
386 | |||
387 | for (msinr = PCI_MSI_DOORBELL_START; | ||
388 | msinr < PCI_MSI_DOORBELL_END; msinr++) { | ||
389 | int irq; | ||
390 | |||
391 | if (!(msimask & BIT(msinr))) | ||
392 | continue; | ||
393 | |||
394 | irq = irq_find_mapping(armada_370_xp_msi_domain, | ||
395 | msinr - 16); | ||
396 | handle_IRQ(irq, regs); | ||
397 | } | ||
398 | } | ||
399 | #endif | ||
400 | |||
223 | #ifdef CONFIG_SMP | 401 | #ifdef CONFIG_SMP |
224 | /* IPI Handling */ | 402 | /* IPI Handling */ |
225 | if (irqnr == 0) { | 403 | if (irqnr == 0) { |
@@ -248,12 +426,25 @@ armada_370_xp_handle_irq(struct pt_regs *regs) | |||
248 | static int __init armada_370_xp_mpic_of_init(struct device_node *node, | 426 | static int __init armada_370_xp_mpic_of_init(struct device_node *node, |
249 | struct device_node *parent) | 427 | struct device_node *parent) |
250 | { | 428 | { |
429 | struct resource main_int_res, per_cpu_int_res; | ||
251 | u32 control; | 430 | u32 control; |
252 | 431 | ||
253 | main_int_base = of_iomap(node, 0); | 432 | BUG_ON(of_address_to_resource(node, 0, &main_int_res)); |
254 | per_cpu_int_base = of_iomap(node, 1); | 433 | BUG_ON(of_address_to_resource(node, 1, &per_cpu_int_res)); |
434 | |||
435 | BUG_ON(!request_mem_region(main_int_res.start, | ||
436 | resource_size(&main_int_res), | ||
437 | node->full_name)); | ||
438 | BUG_ON(!request_mem_region(per_cpu_int_res.start, | ||
439 | resource_size(&per_cpu_int_res), | ||
440 | node->full_name)); | ||
255 | 441 | ||
442 | main_int_base = ioremap(main_int_res.start, | ||
443 | resource_size(&main_int_res)); | ||
256 | BUG_ON(!main_int_base); | 444 | BUG_ON(!main_int_base); |
445 | |||
446 | per_cpu_int_base = ioremap(per_cpu_int_res.start, | ||
447 | resource_size(&per_cpu_int_res)); | ||
257 | BUG_ON(!per_cpu_int_base); | 448 | BUG_ON(!per_cpu_int_base); |
258 | 449 | ||
259 | control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL); | 450 | control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL); |
@@ -262,8 +453,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, | |||
262 | irq_domain_add_linear(node, (control >> 2) & 0x3ff, | 453 | irq_domain_add_linear(node, (control >> 2) & 0x3ff, |
263 | &armada_370_xp_mpic_irq_ops, NULL); | 454 | &armada_370_xp_mpic_irq_ops, NULL); |
264 | 455 | ||
265 | if (!armada_370_xp_mpic_domain) | 456 | BUG_ON(!armada_370_xp_mpic_domain); |
266 | panic("Unable to add Armada_370_Xp MPIC irq domain (DT)\n"); | ||
267 | 457 | ||
268 | irq_set_default_host(armada_370_xp_mpic_domain); | 458 | irq_set_default_host(armada_370_xp_mpic_domain); |
269 | 459 | ||
@@ -280,6 +470,8 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, | |||
280 | 470 | ||
281 | #endif | 471 | #endif |
282 | 472 | ||
473 | armada_370_xp_msi_init(node, main_int_res.start); | ||
474 | |||
283 | set_handle_irq(armada_370_xp_handle_irq); | 475 | set_handle_irq(armada_370_xp_handle_irq); |
284 | 476 | ||
285 | return 0; | 477 | return 0; |
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 3d9504811126..43186feb4294 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig | |||
@@ -3,7 +3,7 @@ menu "PCI host controller drivers" | |||
3 | 3 | ||
4 | config PCI_MVEBU | 4 | config PCI_MVEBU |
5 | bool "Marvell EBU PCIe controller" | 5 | bool "Marvell EBU PCIe controller" |
6 | depends on ARCH_MVEBU || ARCH_KIRKWOOD | 6 | depends on ARCH_MVEBU || ARCH_DOVE || ARCH_KIRKWOOD |
7 | depends on OF | 7 | depends on OF |
8 | 8 | ||
9 | config PCIE_DW | 9 | config PCIE_DW |
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 729d5a101d62..77f8a7c58597 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c | |||
@@ -9,13 +9,17 @@ | |||
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/pci.h> | 10 | #include <linux/pci.h> |
11 | #include <linux/clk.h> | 11 | #include <linux/clk.h> |
12 | #include <linux/delay.h> | ||
13 | #include <linux/gpio.h> | ||
12 | #include <linux/module.h> | 14 | #include <linux/module.h> |
13 | #include <linux/mbus.h> | 15 | #include <linux/mbus.h> |
16 | #include <linux/msi.h> | ||
14 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
15 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
16 | #include <linux/of_address.h> | 19 | #include <linux/of_address.h> |
17 | #include <linux/of_pci.h> | ||
18 | #include <linux/of_irq.h> | 20 | #include <linux/of_irq.h> |
21 | #include <linux/of_gpio.h> | ||
22 | #include <linux/of_pci.h> | ||
19 | #include <linux/of_platform.h> | 23 | #include <linux/of_platform.h> |
20 | 24 | ||
21 | /* | 25 | /* |
@@ -103,6 +107,7 @@ struct mvebu_pcie_port; | |||
103 | struct mvebu_pcie { | 107 | struct mvebu_pcie { |
104 | struct platform_device *pdev; | 108 | struct platform_device *pdev; |
105 | struct mvebu_pcie_port *ports; | 109 | struct mvebu_pcie_port *ports; |
110 | struct msi_chip *msi; | ||
106 | struct resource io; | 111 | struct resource io; |
107 | struct resource realio; | 112 | struct resource realio; |
108 | struct resource mem; | 113 | struct resource mem; |
@@ -124,6 +129,9 @@ struct mvebu_pcie_port { | |||
124 | unsigned int io_target; | 129 | unsigned int io_target; |
125 | unsigned int io_attr; | 130 | unsigned int io_attr; |
126 | struct clk *clk; | 131 | struct clk *clk; |
132 | int reset_gpio; | ||
133 | int reset_active_low; | ||
134 | char *reset_name; | ||
127 | struct mvebu_sw_pci_bridge bridge; | 135 | struct mvebu_sw_pci_bridge bridge; |
128 | struct device_node *dn; | 136 | struct device_node *dn; |
129 | struct mvebu_pcie *pcie; | 137 | struct mvebu_pcie *pcie; |
@@ -163,7 +171,7 @@ static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr) | |||
163 | * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks | 171 | * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks |
164 | * WIN[0-3] -> DRAM bank[0-3] | 172 | * WIN[0-3] -> DRAM bank[0-3] |
165 | */ | 173 | */ |
166 | static void __init mvebu_pcie_setup_wins(struct mvebu_pcie_port *port) | 174 | static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port) |
167 | { | 175 | { |
168 | const struct mbus_dram_target_info *dram; | 176 | const struct mbus_dram_target_info *dram; |
169 | u32 size; | 177 | u32 size; |
@@ -215,7 +223,7 @@ static void __init mvebu_pcie_setup_wins(struct mvebu_pcie_port *port) | |||
215 | port->base + PCIE_BAR_CTRL_OFF(1)); | 223 | port->base + PCIE_BAR_CTRL_OFF(1)); |
216 | } | 224 | } |
217 | 225 | ||
218 | static void __init mvebu_pcie_setup_hw(struct mvebu_pcie_port *port) | 226 | static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port) |
219 | { | 227 | { |
220 | u16 cmd; | 228 | u16 cmd; |
221 | u32 mask; | 229 | u32 mask; |
@@ -626,7 +634,7 @@ static struct pci_ops mvebu_pcie_ops = { | |||
626 | .write = mvebu_pcie_wr_conf, | 634 | .write = mvebu_pcie_wr_conf, |
627 | }; | 635 | }; |
628 | 636 | ||
629 | static int __init mvebu_pcie_setup(int nr, struct pci_sys_data *sys) | 637 | static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys) |
630 | { | 638 | { |
631 | struct mvebu_pcie *pcie = sys_to_pcie(sys); | 639 | struct mvebu_pcie *pcie = sys_to_pcie(sys); |
632 | int i; | 640 | int i; |
@@ -645,7 +653,7 @@ static int __init mvebu_pcie_setup(int nr, struct pci_sys_data *sys) | |||
645 | return 1; | 653 | return 1; |
646 | } | 654 | } |
647 | 655 | ||
648 | static int __init mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | 656 | static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
649 | { | 657 | { |
650 | struct of_irq oirq; | 658 | struct of_irq oirq; |
651 | int ret; | 659 | int ret; |
@@ -673,6 +681,12 @@ static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys) | |||
673 | return bus; | 681 | return bus; |
674 | } | 682 | } |
675 | 683 | ||
684 | void mvebu_pcie_add_bus(struct pci_bus *bus) | ||
685 | { | ||
686 | struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata); | ||
687 | bus->msi = pcie->msi; | ||
688 | } | ||
689 | |||
676 | resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, | 690 | resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, |
677 | const struct resource *res, | 691 | const struct resource *res, |
678 | resource_size_t start, | 692 | resource_size_t start, |
@@ -696,7 +710,7 @@ resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, | |||
696 | return start; | 710 | return start; |
697 | } | 711 | } |
698 | 712 | ||
699 | static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie) | 713 | static void mvebu_pcie_enable(struct mvebu_pcie *pcie) |
700 | { | 714 | { |
701 | struct hw_pci hw; | 715 | struct hw_pci hw; |
702 | 716 | ||
@@ -709,6 +723,7 @@ static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie) | |||
709 | hw.map_irq = mvebu_pcie_map_irq; | 723 | hw.map_irq = mvebu_pcie_map_irq; |
710 | hw.ops = &mvebu_pcie_ops; | 724 | hw.ops = &mvebu_pcie_ops; |
711 | hw.align_resource = mvebu_pcie_align_resource; | 725 | hw.align_resource = mvebu_pcie_align_resource; |
726 | hw.add_bus = mvebu_pcie_add_bus; | ||
712 | 727 | ||
713 | pci_common_init(&hw); | 728 | pci_common_init(&hw); |
714 | } | 729 | } |
@@ -718,10 +733,8 @@ static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie) | |||
718 | * <...> property for one that matches the given port/lane. Once | 733 | * <...> property for one that matches the given port/lane. Once |
719 | * found, maps it. | 734 | * found, maps it. |
720 | */ | 735 | */ |
721 | static void __iomem * __init | 736 | static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev, |
722 | mvebu_pcie_map_registers(struct platform_device *pdev, | 737 | struct device_node *np, struct mvebu_pcie_port *port) |
723 | struct device_node *np, | ||
724 | struct mvebu_pcie_port *port) | ||
725 | { | 738 | { |
726 | struct resource regs; | 739 | struct resource regs; |
727 | int ret = 0; | 740 | int ret = 0; |
@@ -777,7 +790,22 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn, | |||
777 | return -ENOENT; | 790 | return -ENOENT; |
778 | } | 791 | } |
779 | 792 | ||
780 | static int __init mvebu_pcie_probe(struct platform_device *pdev) | 793 | static void mvebu_pcie_msi_enable(struct mvebu_pcie *pcie) |
794 | { | ||
795 | struct device_node *msi_node; | ||
796 | |||
797 | msi_node = of_parse_phandle(pcie->pdev->dev.of_node, | ||
798 | "msi-parent", 0); | ||
799 | if (!msi_node) | ||
800 | return; | ||
801 | |||
802 | pcie->msi = of_pci_find_msi_chip_by_node(msi_node); | ||
803 | |||
804 | if (pcie->msi) | ||
805 | pcie->msi->dev = &pcie->pdev->dev; | ||
806 | } | ||
807 | |||
808 | static int mvebu_pcie_probe(struct platform_device *pdev) | ||
781 | { | 809 | { |
782 | struct mvebu_pcie *pcie; | 810 | struct mvebu_pcie *pcie; |
783 | struct device_node *np = pdev->dev.of_node; | 811 | struct device_node *np = pdev->dev.of_node; |
@@ -790,6 +818,7 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) | |||
790 | return -ENOMEM; | 818 | return -ENOMEM; |
791 | 819 | ||
792 | pcie->pdev = pdev; | 820 | pcie->pdev = pdev; |
821 | platform_set_drvdata(pdev, pcie); | ||
793 | 822 | ||
794 | /* Get the PCIe memory and I/O aperture */ | 823 | /* Get the PCIe memory and I/O aperture */ |
795 | mvebu_mbus_get_pcie_mem_aperture(&pcie->mem); | 824 | mvebu_mbus_get_pcie_mem_aperture(&pcie->mem); |
@@ -818,13 +847,14 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) | |||
818 | return ret; | 847 | return ret; |
819 | } | 848 | } |
820 | 849 | ||
850 | i = 0; | ||
821 | for_each_child_of_node(pdev->dev.of_node, child) { | 851 | for_each_child_of_node(pdev->dev.of_node, child) { |
822 | if (!of_device_is_available(child)) | 852 | if (!of_device_is_available(child)) |
823 | continue; | 853 | continue; |
824 | pcie->nports++; | 854 | i++; |
825 | } | 855 | } |
826 | 856 | ||
827 | pcie->ports = devm_kzalloc(&pdev->dev, pcie->nports * | 857 | pcie->ports = devm_kzalloc(&pdev->dev, i * |
828 | sizeof(struct mvebu_pcie_port), | 858 | sizeof(struct mvebu_pcie_port), |
829 | GFP_KERNEL); | 859 | GFP_KERNEL); |
830 | if (!pcie->ports) | 860 | if (!pcie->ports) |
@@ -833,6 +863,7 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) | |||
833 | i = 0; | 863 | i = 0; |
834 | for_each_child_of_node(pdev->dev.of_node, child) { | 864 | for_each_child_of_node(pdev->dev.of_node, child) { |
835 | struct mvebu_pcie_port *port = &pcie->ports[i]; | 865 | struct mvebu_pcie_port *port = &pcie->ports[i]; |
866 | enum of_gpio_flags flags; | ||
836 | 867 | ||
837 | if (!of_device_is_available(child)) | 868 | if (!of_device_is_available(child)) |
838 | continue; | 869 | continue; |
@@ -873,11 +904,47 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) | |||
873 | continue; | 904 | continue; |
874 | } | 905 | } |
875 | 906 | ||
907 | port->reset_gpio = of_get_named_gpio_flags(child, | ||
908 | "reset-gpios", 0, &flags); | ||
909 | if (gpio_is_valid(port->reset_gpio)) { | ||
910 | u32 reset_udelay = 20000; | ||
911 | |||
912 | port->reset_active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
913 | port->reset_name = kasprintf(GFP_KERNEL, | ||
914 | "pcie%d.%d-reset", port->port, port->lane); | ||
915 | of_property_read_u32(child, "reset-delay-us", | ||
916 | &reset_udelay); | ||
917 | |||
918 | ret = devm_gpio_request_one(&pdev->dev, | ||
919 | port->reset_gpio, GPIOF_DIR_OUT, port->reset_name); | ||
920 | if (ret) { | ||
921 | if (ret == -EPROBE_DEFER) | ||
922 | return ret; | ||
923 | continue; | ||
924 | } | ||
925 | |||
926 | gpio_set_value(port->reset_gpio, | ||
927 | (port->reset_active_low) ? 1 : 0); | ||
928 | msleep(reset_udelay/1000); | ||
929 | } | ||
930 | |||
931 | port->clk = of_clk_get_by_name(child, NULL); | ||
932 | if (IS_ERR(port->clk)) { | ||
933 | dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n", | ||
934 | port->port, port->lane); | ||
935 | continue; | ||
936 | } | ||
937 | |||
938 | ret = clk_prepare_enable(port->clk); | ||
939 | if (ret) | ||
940 | continue; | ||
941 | |||
876 | port->base = mvebu_pcie_map_registers(pdev, child, port); | 942 | port->base = mvebu_pcie_map_registers(pdev, child, port); |
877 | if (IS_ERR(port->base)) { | 943 | if (IS_ERR(port->base)) { |
878 | dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n", | 944 | dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n", |
879 | port->port, port->lane); | 945 | port->port, port->lane); |
880 | port->base = NULL; | 946 | port->base = NULL; |
947 | clk_disable_unprepare(port->clk); | ||
881 | continue; | 948 | continue; |
882 | } | 949 | } |
883 | 950 | ||
@@ -893,25 +960,14 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) | |||
893 | port->port, port->lane); | 960 | port->port, port->lane); |
894 | } | 961 | } |
895 | 962 | ||
896 | port->clk = of_clk_get_by_name(child, NULL); | ||
897 | if (IS_ERR(port->clk)) { | ||
898 | dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n", | ||
899 | port->port, port->lane); | ||
900 | iounmap(port->base); | ||
901 | port->haslink = 0; | ||
902 | continue; | ||
903 | } | ||
904 | |||
905 | port->dn = child; | 963 | port->dn = child; |
906 | |||
907 | clk_prepare_enable(port->clk); | ||
908 | spin_lock_init(&port->conf_lock); | 964 | spin_lock_init(&port->conf_lock); |
909 | |||
910 | mvebu_sw_pci_bridge_init(port); | 965 | mvebu_sw_pci_bridge_init(port); |
911 | |||
912 | i++; | 966 | i++; |
913 | } | 967 | } |
914 | 968 | ||
969 | pcie->nports = i; | ||
970 | mvebu_pcie_msi_enable(pcie); | ||
915 | mvebu_pcie_enable(pcie); | 971 | mvebu_pcie_enable(pcie); |
916 | 972 | ||
917 | return 0; | 973 | return 0; |
@@ -920,6 +976,7 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) | |||
920 | static const struct of_device_id mvebu_pcie_of_match_table[] = { | 976 | static const struct of_device_id mvebu_pcie_of_match_table[] = { |
921 | { .compatible = "marvell,armada-xp-pcie", }, | 977 | { .compatible = "marvell,armada-xp-pcie", }, |
922 | { .compatible = "marvell,armada-370-pcie", }, | 978 | { .compatible = "marvell,armada-370-pcie", }, |
979 | { .compatible = "marvell,dove-pcie", }, | ||
923 | { .compatible = "marvell,kirkwood-pcie", }, | 980 | { .compatible = "marvell,kirkwood-pcie", }, |
924 | {}, | 981 | {}, |
925 | }; | 982 | }; |
@@ -931,16 +988,12 @@ static struct platform_driver mvebu_pcie_driver = { | |||
931 | .name = "mvebu-pcie", | 988 | .name = "mvebu-pcie", |
932 | .of_match_table = | 989 | .of_match_table = |
933 | of_match_ptr(mvebu_pcie_of_match_table), | 990 | of_match_ptr(mvebu_pcie_of_match_table), |
991 | /* driver unloading/unbinding currently not supported */ | ||
992 | .suppress_bind_attrs = true, | ||
934 | }, | 993 | }, |
994 | .probe = mvebu_pcie_probe, | ||
935 | }; | 995 | }; |
936 | 996 | module_platform_driver(mvebu_pcie_driver); | |
937 | static int __init mvebu_pcie_init(void) | ||
938 | { | ||
939 | return platform_driver_probe(&mvebu_pcie_driver, | ||
940 | mvebu_pcie_probe); | ||
941 | } | ||
942 | |||
943 | subsys_initcall(mvebu_pcie_init); | ||
944 | 997 | ||
945 | MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); | 998 | MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); |
946 | MODULE_DESCRIPTION("Marvell EBU PCIe driver"); | 999 | MODULE_DESCRIPTION("Marvell EBU PCIe driver"); |