diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-11 03:05:37 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-11 03:05:37 -0500 |
commit | 53575aa99dc1584484b99c8173042d8370f6ed88 (patch) | |
tree | 06fd13c8847c1e97cd5080ea31cec47c4ad54963 /drivers/pci | |
parent | d5aabbcaee6bb5fb57ea8c67714516af4d8238ce (diff) | |
parent | 3316dee245ef297155fa45b8d14263dfd6a9164b (diff) |
Merge tag 'drivers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM driver updates from Olof Johansson:
"Updates of SoC-near drivers and other driver updates that makes more
sense to take through our tree. In this case it's involved:
- Some Davinci driver updates that has required corresponding
platform code changes (gpio mostly)
- CCI bindings and a few driver updates
- Marvell mvebu patches for PCI MSI support (could have gone through
the PCI tree for this release, but they were acked by Bjorn for
3.12 so we kept them through arm-soc).
- Marvell dove switch-over to DT-based PCIe configuration
- Misc updates for Samsung platform dmaengine drivers"
* tag 'drivers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (32 commits)
ARM: S3C24XX: add dma pdata for s3c2410, s3c2440 and s3c2442
dmaengine: s3c24xx-dma: add support for the s3c2410 type of controller
ARM: S3C24XX: Fix possible dma selection warning
PCI: mvebu: make local functions static
PCI: mvebu: add I/O access wrappers
PCI: mvebu: Dynamically detect if the PEX link is up to enable hot plug
ARM: mvebu: fix gated clock documentation
ARM: dove: remove legacy pcie and clock init
ARM: dove: switch to DT probed mbus address windows
ARM: SAMSUNG: set s3c24xx_dma_filter for s3c64xx-spi0 device
ARM: S3C24XX: add platform-devices for new dma driver for s3c2412 and s3c2443
dmaengine: add driver for Samsung s3c24xx SoCs
ARM: S3C24XX: number the dma clocks
PCI: mvebu: add support for Marvell Dove SoCs
PCI: mvebu: add support for reset on GPIO
PCI: mvebu: remove subsys_initcall
PCI: mvebu: increment nports only for registered ports
PCI: mvebu: move clock enable before register access
PCI: mvebu: add support for MSI
irqchip: armada-370-xp: implement MSI support
...
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/host/Kconfig | 2 | ||||
-rw-r--r-- | drivers/pci/host/pci-mvebu.c | 235 |
2 files changed, 150 insertions, 87 deletions
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..80b2250ea19a 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; |
@@ -115,7 +120,6 @@ struct mvebu_pcie_port { | |||
115 | char *name; | 120 | char *name; |
116 | void __iomem *base; | 121 | void __iomem *base; |
117 | spinlock_t conf_lock; | 122 | spinlock_t conf_lock; |
118 | int haslink; | ||
119 | u32 port; | 123 | u32 port; |
120 | u32 lane; | 124 | u32 lane; |
121 | int devfn; | 125 | int devfn; |
@@ -124,6 +128,9 @@ struct mvebu_pcie_port { | |||
124 | unsigned int io_target; | 128 | unsigned int io_target; |
125 | unsigned int io_attr; | 129 | unsigned int io_attr; |
126 | struct clk *clk; | 130 | struct clk *clk; |
131 | int reset_gpio; | ||
132 | int reset_active_low; | ||
133 | char *reset_name; | ||
127 | struct mvebu_sw_pci_bridge bridge; | 134 | struct mvebu_sw_pci_bridge bridge; |
128 | struct device_node *dn; | 135 | struct device_node *dn; |
129 | struct mvebu_pcie *pcie; | 136 | struct mvebu_pcie *pcie; |
@@ -133,29 +140,39 @@ struct mvebu_pcie_port { | |||
133 | size_t iowin_size; | 140 | size_t iowin_size; |
134 | }; | 141 | }; |
135 | 142 | ||
143 | static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg) | ||
144 | { | ||
145 | writel(val, port->base + reg); | ||
146 | } | ||
147 | |||
148 | static inline u32 mvebu_readl(struct mvebu_pcie_port *port, u32 reg) | ||
149 | { | ||
150 | return readl(port->base + reg); | ||
151 | } | ||
152 | |||
136 | static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port) | 153 | static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port) |
137 | { | 154 | { |
138 | return !(readl(port->base + PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN); | 155 | return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN); |
139 | } | 156 | } |
140 | 157 | ||
141 | static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie_port *port, int nr) | 158 | static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie_port *port, int nr) |
142 | { | 159 | { |
143 | u32 stat; | 160 | u32 stat; |
144 | 161 | ||
145 | stat = readl(port->base + PCIE_STAT_OFF); | 162 | stat = mvebu_readl(port, PCIE_STAT_OFF); |
146 | stat &= ~PCIE_STAT_BUS; | 163 | stat &= ~PCIE_STAT_BUS; |
147 | stat |= nr << 8; | 164 | stat |= nr << 8; |
148 | writel(stat, port->base + PCIE_STAT_OFF); | 165 | mvebu_writel(port, stat, PCIE_STAT_OFF); |
149 | } | 166 | } |
150 | 167 | ||
151 | static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr) | 168 | static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr) |
152 | { | 169 | { |
153 | u32 stat; | 170 | u32 stat; |
154 | 171 | ||
155 | stat = readl(port->base + PCIE_STAT_OFF); | 172 | stat = mvebu_readl(port, PCIE_STAT_OFF); |
156 | stat &= ~PCIE_STAT_DEV; | 173 | stat &= ~PCIE_STAT_DEV; |
157 | stat |= nr << 16; | 174 | stat |= nr << 16; |
158 | writel(stat, port->base + PCIE_STAT_OFF); | 175 | mvebu_writel(port, stat, PCIE_STAT_OFF); |
159 | } | 176 | } |
160 | 177 | ||
161 | /* | 178 | /* |
@@ -163,7 +180,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 | 180 | * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks |
164 | * WIN[0-3] -> DRAM bank[0-3] | 181 | * WIN[0-3] -> DRAM bank[0-3] |
165 | */ | 182 | */ |
166 | static void __init mvebu_pcie_setup_wins(struct mvebu_pcie_port *port) | 183 | static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port) |
167 | { | 184 | { |
168 | const struct mbus_dram_target_info *dram; | 185 | const struct mbus_dram_target_info *dram; |
169 | u32 size; | 186 | u32 size; |
@@ -173,33 +190,34 @@ static void __init mvebu_pcie_setup_wins(struct mvebu_pcie_port *port) | |||
173 | 190 | ||
174 | /* First, disable and clear BARs and windows. */ | 191 | /* First, disable and clear BARs and windows. */ |
175 | for (i = 1; i < 3; i++) { | 192 | for (i = 1; i < 3; i++) { |
176 | writel(0, port->base + PCIE_BAR_CTRL_OFF(i)); | 193 | mvebu_writel(port, 0, PCIE_BAR_CTRL_OFF(i)); |
177 | writel(0, port->base + PCIE_BAR_LO_OFF(i)); | 194 | mvebu_writel(port, 0, PCIE_BAR_LO_OFF(i)); |
178 | writel(0, port->base + PCIE_BAR_HI_OFF(i)); | 195 | mvebu_writel(port, 0, PCIE_BAR_HI_OFF(i)); |
179 | } | 196 | } |
180 | 197 | ||
181 | for (i = 0; i < 5; i++) { | 198 | for (i = 0; i < 5; i++) { |
182 | writel(0, port->base + PCIE_WIN04_CTRL_OFF(i)); | 199 | mvebu_writel(port, 0, PCIE_WIN04_CTRL_OFF(i)); |
183 | writel(0, port->base + PCIE_WIN04_BASE_OFF(i)); | 200 | mvebu_writel(port, 0, PCIE_WIN04_BASE_OFF(i)); |
184 | writel(0, port->base + PCIE_WIN04_REMAP_OFF(i)); | 201 | mvebu_writel(port, 0, PCIE_WIN04_REMAP_OFF(i)); |
185 | } | 202 | } |
186 | 203 | ||
187 | writel(0, port->base + PCIE_WIN5_CTRL_OFF); | 204 | mvebu_writel(port, 0, PCIE_WIN5_CTRL_OFF); |
188 | writel(0, port->base + PCIE_WIN5_BASE_OFF); | 205 | mvebu_writel(port, 0, PCIE_WIN5_BASE_OFF); |
189 | writel(0, port->base + PCIE_WIN5_REMAP_OFF); | 206 | mvebu_writel(port, 0, PCIE_WIN5_REMAP_OFF); |
190 | 207 | ||
191 | /* Setup windows for DDR banks. Count total DDR size on the fly. */ | 208 | /* Setup windows for DDR banks. Count total DDR size on the fly. */ |
192 | size = 0; | 209 | size = 0; |
193 | for (i = 0; i < dram->num_cs; i++) { | 210 | for (i = 0; i < dram->num_cs; i++) { |
194 | const struct mbus_dram_window *cs = dram->cs + i; | 211 | const struct mbus_dram_window *cs = dram->cs + i; |
195 | 212 | ||
196 | writel(cs->base & 0xffff0000, | 213 | mvebu_writel(port, cs->base & 0xffff0000, |
197 | port->base + PCIE_WIN04_BASE_OFF(i)); | 214 | PCIE_WIN04_BASE_OFF(i)); |
198 | writel(0, port->base + PCIE_WIN04_REMAP_OFF(i)); | 215 | mvebu_writel(port, 0, PCIE_WIN04_REMAP_OFF(i)); |
199 | writel(((cs->size - 1) & 0xffff0000) | | 216 | mvebu_writel(port, |
200 | (cs->mbus_attr << 8) | | 217 | ((cs->size - 1) & 0xffff0000) | |
201 | (dram->mbus_dram_target_id << 4) | 1, | 218 | (cs->mbus_attr << 8) | |
202 | port->base + PCIE_WIN04_CTRL_OFF(i)); | 219 | (dram->mbus_dram_target_id << 4) | 1, |
220 | PCIE_WIN04_CTRL_OFF(i)); | ||
203 | 221 | ||
204 | size += cs->size; | 222 | size += cs->size; |
205 | } | 223 | } |
@@ -209,41 +227,40 @@ static void __init mvebu_pcie_setup_wins(struct mvebu_pcie_port *port) | |||
209 | size = 1 << fls(size); | 227 | size = 1 << fls(size); |
210 | 228 | ||
211 | /* Setup BAR[1] to all DRAM banks. */ | 229 | /* Setup BAR[1] to all DRAM banks. */ |
212 | writel(dram->cs[0].base, port->base + PCIE_BAR_LO_OFF(1)); | 230 | mvebu_writel(port, dram->cs[0].base, PCIE_BAR_LO_OFF(1)); |
213 | writel(0, port->base + PCIE_BAR_HI_OFF(1)); | 231 | mvebu_writel(port, 0, PCIE_BAR_HI_OFF(1)); |
214 | writel(((size - 1) & 0xffff0000) | 1, | 232 | mvebu_writel(port, ((size - 1) & 0xffff0000) | 1, |
215 | port->base + PCIE_BAR_CTRL_OFF(1)); | 233 | PCIE_BAR_CTRL_OFF(1)); |
216 | } | 234 | } |
217 | 235 | ||
218 | static void __init mvebu_pcie_setup_hw(struct mvebu_pcie_port *port) | 236 | static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port) |
219 | { | 237 | { |
220 | u16 cmd; | 238 | u32 cmd, mask; |
221 | u32 mask; | ||
222 | 239 | ||
223 | /* Point PCIe unit MBUS decode windows to DRAM space. */ | 240 | /* Point PCIe unit MBUS decode windows to DRAM space. */ |
224 | mvebu_pcie_setup_wins(port); | 241 | mvebu_pcie_setup_wins(port); |
225 | 242 | ||
226 | /* Master + slave enable. */ | 243 | /* Master + slave enable. */ |
227 | cmd = readw(port->base + PCIE_CMD_OFF); | 244 | cmd = mvebu_readl(port, PCIE_CMD_OFF); |
228 | cmd |= PCI_COMMAND_IO; | 245 | cmd |= PCI_COMMAND_IO; |
229 | cmd |= PCI_COMMAND_MEMORY; | 246 | cmd |= PCI_COMMAND_MEMORY; |
230 | cmd |= PCI_COMMAND_MASTER; | 247 | cmd |= PCI_COMMAND_MASTER; |
231 | writew(cmd, port->base + PCIE_CMD_OFF); | 248 | mvebu_writel(port, cmd, PCIE_CMD_OFF); |
232 | 249 | ||
233 | /* Enable interrupt lines A-D. */ | 250 | /* Enable interrupt lines A-D. */ |
234 | mask = readl(port->base + PCIE_MASK_OFF); | 251 | mask = mvebu_readl(port, PCIE_MASK_OFF); |
235 | mask |= PCIE_MASK_ENABLE_INTS; | 252 | mask |= PCIE_MASK_ENABLE_INTS; |
236 | writel(mask, port->base + PCIE_MASK_OFF); | 253 | mvebu_writel(port, mask, PCIE_MASK_OFF); |
237 | } | 254 | } |
238 | 255 | ||
239 | static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port, | 256 | static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port, |
240 | struct pci_bus *bus, | 257 | struct pci_bus *bus, |
241 | u32 devfn, int where, int size, u32 *val) | 258 | u32 devfn, int where, int size, u32 *val) |
242 | { | 259 | { |
243 | writel(PCIE_CONF_ADDR(bus->number, devfn, where), | 260 | mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where), |
244 | port->base + PCIE_CONF_ADDR_OFF); | 261 | PCIE_CONF_ADDR_OFF); |
245 | 262 | ||
246 | *val = readl(port->base + PCIE_CONF_DATA_OFF); | 263 | *val = mvebu_readl(port, PCIE_CONF_DATA_OFF); |
247 | 264 | ||
248 | if (size == 1) | 265 | if (size == 1) |
249 | *val = (*val >> (8 * (where & 3))) & 0xff; | 266 | *val = (*val >> (8 * (where & 3))) & 0xff; |
@@ -257,21 +274,24 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port, | |||
257 | struct pci_bus *bus, | 274 | struct pci_bus *bus, |
258 | u32 devfn, int where, int size, u32 val) | 275 | u32 devfn, int where, int size, u32 val) |
259 | { | 276 | { |
260 | int ret = PCIBIOS_SUCCESSFUL; | 277 | u32 _val, shift = 8 * (where & 3); |
261 | 278 | ||
262 | writel(PCIE_CONF_ADDR(bus->number, devfn, where), | 279 | mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where), |
263 | port->base + PCIE_CONF_ADDR_OFF); | 280 | PCIE_CONF_ADDR_OFF); |
281 | _val = mvebu_readl(port, PCIE_CONF_DATA_OFF); | ||
264 | 282 | ||
265 | if (size == 4) | 283 | if (size == 4) |
266 | writel(val, port->base + PCIE_CONF_DATA_OFF); | 284 | _val = val; |
267 | else if (size == 2) | 285 | else if (size == 2) |
268 | writew(val, port->base + PCIE_CONF_DATA_OFF + (where & 3)); | 286 | _val = (_val & ~(0xffff << shift)) | ((val & 0xffff) << shift); |
269 | else if (size == 1) | 287 | else if (size == 1) |
270 | writeb(val, port->base + PCIE_CONF_DATA_OFF + (where & 3)); | 288 | _val = (_val & ~(0xff << shift)) | ((val & 0xff) << shift); |
271 | else | 289 | else |
272 | ret = PCIBIOS_BAD_REGISTER_NUMBER; | 290 | return PCIBIOS_BAD_REGISTER_NUMBER; |
273 | 291 | ||
274 | return ret; | 292 | mvebu_writel(port, _val, PCIE_CONF_DATA_OFF); |
293 | |||
294 | return PCIBIOS_SUCCESSFUL; | ||
275 | } | 295 | } |
276 | 296 | ||
277 | static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) | 297 | static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) |
@@ -552,7 +572,7 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn, | |||
552 | if (bus->number == 0) | 572 | if (bus->number == 0) |
553 | return mvebu_sw_pci_bridge_write(port, where, size, val); | 573 | return mvebu_sw_pci_bridge_write(port, where, size, val); |
554 | 574 | ||
555 | if (!port->haslink) | 575 | if (!mvebu_pcie_link_up(port)) |
556 | return PCIBIOS_DEVICE_NOT_FOUND; | 576 | return PCIBIOS_DEVICE_NOT_FOUND; |
557 | 577 | ||
558 | /* | 578 | /* |
@@ -594,7 +614,7 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, | |||
594 | if (bus->number == 0) | 614 | if (bus->number == 0) |
595 | return mvebu_sw_pci_bridge_read(port, where, size, val); | 615 | return mvebu_sw_pci_bridge_read(port, where, size, val); |
596 | 616 | ||
597 | if (!port->haslink) { | 617 | if (!mvebu_pcie_link_up(port)) { |
598 | *val = 0xffffffff; | 618 | *val = 0xffffffff; |
599 | return PCIBIOS_DEVICE_NOT_FOUND; | 619 | return PCIBIOS_DEVICE_NOT_FOUND; |
600 | } | 620 | } |
@@ -626,7 +646,7 @@ static struct pci_ops mvebu_pcie_ops = { | |||
626 | .write = mvebu_pcie_wr_conf, | 646 | .write = mvebu_pcie_wr_conf, |
627 | }; | 647 | }; |
628 | 648 | ||
629 | static int __init mvebu_pcie_setup(int nr, struct pci_sys_data *sys) | 649 | static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys) |
630 | { | 650 | { |
631 | struct mvebu_pcie *pcie = sys_to_pcie(sys); | 651 | struct mvebu_pcie *pcie = sys_to_pcie(sys); |
632 | int i; | 652 | int i; |
@@ -645,7 +665,7 @@ static int __init mvebu_pcie_setup(int nr, struct pci_sys_data *sys) | |||
645 | return 1; | 665 | return 1; |
646 | } | 666 | } |
647 | 667 | ||
648 | static int __init mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | 668 | static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
649 | { | 669 | { |
650 | struct of_irq oirq; | 670 | struct of_irq oirq; |
651 | int ret; | 671 | int ret; |
@@ -673,11 +693,17 @@ static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys) | |||
673 | return bus; | 693 | return bus; |
674 | } | 694 | } |
675 | 695 | ||
676 | resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, | 696 | static void mvebu_pcie_add_bus(struct pci_bus *bus) |
677 | const struct resource *res, | 697 | { |
678 | resource_size_t start, | 698 | struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata); |
679 | resource_size_t size, | 699 | bus->msi = pcie->msi; |
680 | resource_size_t align) | 700 | } |
701 | |||
702 | static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, | ||
703 | const struct resource *res, | ||
704 | resource_size_t start, | ||
705 | resource_size_t size, | ||
706 | resource_size_t align) | ||
681 | { | 707 | { |
682 | if (dev->bus->number != 0) | 708 | if (dev->bus->number != 0) |
683 | return start; | 709 | return start; |
@@ -696,7 +722,7 @@ resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, | |||
696 | return start; | 722 | return start; |
697 | } | 723 | } |
698 | 724 | ||
699 | static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie) | 725 | static void mvebu_pcie_enable(struct mvebu_pcie *pcie) |
700 | { | 726 | { |
701 | struct hw_pci hw; | 727 | struct hw_pci hw; |
702 | 728 | ||
@@ -709,6 +735,7 @@ static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie) | |||
709 | hw.map_irq = mvebu_pcie_map_irq; | 735 | hw.map_irq = mvebu_pcie_map_irq; |
710 | hw.ops = &mvebu_pcie_ops; | 736 | hw.ops = &mvebu_pcie_ops; |
711 | hw.align_resource = mvebu_pcie_align_resource; | 737 | hw.align_resource = mvebu_pcie_align_resource; |
738 | hw.add_bus = mvebu_pcie_add_bus; | ||
712 | 739 | ||
713 | pci_common_init(&hw); | 740 | pci_common_init(&hw); |
714 | } | 741 | } |
@@ -718,10 +745,8 @@ static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie) | |||
718 | * <...> property for one that matches the given port/lane. Once | 745 | * <...> property for one that matches the given port/lane. Once |
719 | * found, maps it. | 746 | * found, maps it. |
720 | */ | 747 | */ |
721 | static void __iomem * __init | 748 | static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev, |
722 | mvebu_pcie_map_registers(struct platform_device *pdev, | 749 | struct device_node *np, struct mvebu_pcie_port *port) |
723 | struct device_node *np, | ||
724 | struct mvebu_pcie_port *port) | ||
725 | { | 750 | { |
726 | struct resource regs; | 751 | struct resource regs; |
727 | int ret = 0; | 752 | int ret = 0; |
@@ -777,7 +802,22 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn, | |||
777 | return -ENOENT; | 802 | return -ENOENT; |
778 | } | 803 | } |
779 | 804 | ||
780 | static int __init mvebu_pcie_probe(struct platform_device *pdev) | 805 | static void mvebu_pcie_msi_enable(struct mvebu_pcie *pcie) |
806 | { | ||
807 | struct device_node *msi_node; | ||
808 | |||
809 | msi_node = of_parse_phandle(pcie->pdev->dev.of_node, | ||
810 | "msi-parent", 0); | ||
811 | if (!msi_node) | ||
812 | return; | ||
813 | |||
814 | pcie->msi = of_pci_find_msi_chip_by_node(msi_node); | ||
815 | |||
816 | if (pcie->msi) | ||
817 | pcie->msi->dev = &pcie->pdev->dev; | ||
818 | } | ||
819 | |||
820 | static int mvebu_pcie_probe(struct platform_device *pdev) | ||
781 | { | 821 | { |
782 | struct mvebu_pcie *pcie; | 822 | struct mvebu_pcie *pcie; |
783 | struct device_node *np = pdev->dev.of_node; | 823 | struct device_node *np = pdev->dev.of_node; |
@@ -790,6 +830,7 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) | |||
790 | return -ENOMEM; | 830 | return -ENOMEM; |
791 | 831 | ||
792 | pcie->pdev = pdev; | 832 | pcie->pdev = pdev; |
833 | platform_set_drvdata(pdev, pcie); | ||
793 | 834 | ||
794 | /* Get the PCIe memory and I/O aperture */ | 835 | /* Get the PCIe memory and I/O aperture */ |
795 | mvebu_mbus_get_pcie_mem_aperture(&pcie->mem); | 836 | mvebu_mbus_get_pcie_mem_aperture(&pcie->mem); |
@@ -818,13 +859,14 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) | |||
818 | return ret; | 859 | return ret; |
819 | } | 860 | } |
820 | 861 | ||
862 | i = 0; | ||
821 | for_each_child_of_node(pdev->dev.of_node, child) { | 863 | for_each_child_of_node(pdev->dev.of_node, child) { |
822 | if (!of_device_is_available(child)) | 864 | if (!of_device_is_available(child)) |
823 | continue; | 865 | continue; |
824 | pcie->nports++; | 866 | i++; |
825 | } | 867 | } |
826 | 868 | ||
827 | pcie->ports = devm_kzalloc(&pdev->dev, pcie->nports * | 869 | pcie->ports = devm_kzalloc(&pdev->dev, i * |
828 | sizeof(struct mvebu_pcie_port), | 870 | sizeof(struct mvebu_pcie_port), |
829 | GFP_KERNEL); | 871 | GFP_KERNEL); |
830 | if (!pcie->ports) | 872 | if (!pcie->ports) |
@@ -833,6 +875,7 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) | |||
833 | i = 0; | 875 | i = 0; |
834 | for_each_child_of_node(pdev->dev.of_node, child) { | 876 | for_each_child_of_node(pdev->dev.of_node, child) { |
835 | struct mvebu_pcie_port *port = &pcie->ports[i]; | 877 | struct mvebu_pcie_port *port = &pcie->ports[i]; |
878 | enum of_gpio_flags flags; | ||
836 | 879 | ||
837 | if (!of_device_is_available(child)) | 880 | if (!of_device_is_available(child)) |
838 | continue; | 881 | continue; |
@@ -873,45 +916,68 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) | |||
873 | continue; | 916 | continue; |
874 | } | 917 | } |
875 | 918 | ||
919 | port->reset_gpio = of_get_named_gpio_flags(child, | ||
920 | "reset-gpios", 0, &flags); | ||
921 | if (gpio_is_valid(port->reset_gpio)) { | ||
922 | u32 reset_udelay = 20000; | ||
923 | |||
924 | port->reset_active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
925 | port->reset_name = kasprintf(GFP_KERNEL, | ||
926 | "pcie%d.%d-reset", port->port, port->lane); | ||
927 | of_property_read_u32(child, "reset-delay-us", | ||
928 | &reset_udelay); | ||
929 | |||
930 | ret = devm_gpio_request_one(&pdev->dev, | ||
931 | port->reset_gpio, GPIOF_DIR_OUT, port->reset_name); | ||
932 | if (ret) { | ||
933 | if (ret == -EPROBE_DEFER) | ||
934 | return ret; | ||
935 | continue; | ||
936 | } | ||
937 | |||
938 | gpio_set_value(port->reset_gpio, | ||
939 | (port->reset_active_low) ? 1 : 0); | ||
940 | msleep(reset_udelay/1000); | ||
941 | } | ||
942 | |||
943 | port->clk = of_clk_get_by_name(child, NULL); | ||
944 | if (IS_ERR(port->clk)) { | ||
945 | dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n", | ||
946 | port->port, port->lane); | ||
947 | continue; | ||
948 | } | ||
949 | |||
950 | ret = clk_prepare_enable(port->clk); | ||
951 | if (ret) | ||
952 | continue; | ||
953 | |||
876 | port->base = mvebu_pcie_map_registers(pdev, child, port); | 954 | port->base = mvebu_pcie_map_registers(pdev, child, port); |
877 | if (IS_ERR(port->base)) { | 955 | if (IS_ERR(port->base)) { |
878 | dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n", | 956 | dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n", |
879 | port->port, port->lane); | 957 | port->port, port->lane); |
880 | port->base = NULL; | 958 | port->base = NULL; |
959 | clk_disable_unprepare(port->clk); | ||
881 | continue; | 960 | continue; |
882 | } | 961 | } |
883 | 962 | ||
884 | mvebu_pcie_set_local_dev_nr(port, 1); | 963 | mvebu_pcie_set_local_dev_nr(port, 1); |
885 | 964 | ||
886 | if (mvebu_pcie_link_up(port)) { | ||
887 | port->haslink = 1; | ||
888 | dev_info(&pdev->dev, "PCIe%d.%d: link up\n", | ||
889 | port->port, port->lane); | ||
890 | } else { | ||
891 | port->haslink = 0; | ||
892 | dev_info(&pdev->dev, "PCIe%d.%d: link down\n", | ||
893 | port->port, port->lane); | ||
894 | } | ||
895 | |||
896 | port->clk = of_clk_get_by_name(child, NULL); | 965 | port->clk = of_clk_get_by_name(child, NULL); |
897 | if (IS_ERR(port->clk)) { | 966 | if (IS_ERR(port->clk)) { |
898 | dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n", | 967 | dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n", |
899 | port->port, port->lane); | 968 | port->port, port->lane); |
900 | iounmap(port->base); | 969 | iounmap(port->base); |
901 | port->haslink = 0; | ||
902 | continue; | 970 | continue; |
903 | } | 971 | } |
904 | 972 | ||
905 | port->dn = child; | 973 | port->dn = child; |
906 | |||
907 | clk_prepare_enable(port->clk); | ||
908 | spin_lock_init(&port->conf_lock); | 974 | spin_lock_init(&port->conf_lock); |
909 | |||
910 | mvebu_sw_pci_bridge_init(port); | 975 | mvebu_sw_pci_bridge_init(port); |
911 | |||
912 | i++; | 976 | i++; |
913 | } | 977 | } |
914 | 978 | ||
979 | pcie->nports = i; | ||
980 | mvebu_pcie_msi_enable(pcie); | ||
915 | mvebu_pcie_enable(pcie); | 981 | mvebu_pcie_enable(pcie); |
916 | 982 | ||
917 | return 0; | 983 | return 0; |
@@ -920,6 +986,7 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) | |||
920 | static const struct of_device_id mvebu_pcie_of_match_table[] = { | 986 | static const struct of_device_id mvebu_pcie_of_match_table[] = { |
921 | { .compatible = "marvell,armada-xp-pcie", }, | 987 | { .compatible = "marvell,armada-xp-pcie", }, |
922 | { .compatible = "marvell,armada-370-pcie", }, | 988 | { .compatible = "marvell,armada-370-pcie", }, |
989 | { .compatible = "marvell,dove-pcie", }, | ||
923 | { .compatible = "marvell,kirkwood-pcie", }, | 990 | { .compatible = "marvell,kirkwood-pcie", }, |
924 | {}, | 991 | {}, |
925 | }; | 992 | }; |
@@ -931,16 +998,12 @@ static struct platform_driver mvebu_pcie_driver = { | |||
931 | .name = "mvebu-pcie", | 998 | .name = "mvebu-pcie", |
932 | .of_match_table = | 999 | .of_match_table = |
933 | of_match_ptr(mvebu_pcie_of_match_table), | 1000 | of_match_ptr(mvebu_pcie_of_match_table), |
1001 | /* driver unloading/unbinding currently not supported */ | ||
1002 | .suppress_bind_attrs = true, | ||
934 | }, | 1003 | }, |
1004 | .probe = mvebu_pcie_probe, | ||
935 | }; | 1005 | }; |
936 | 1006 | 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 | 1007 | ||
945 | MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); | 1008 | MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); |
946 | MODULE_DESCRIPTION("Marvell EBU PCIe driver"); | 1009 | MODULE_DESCRIPTION("Marvell EBU PCIe driver"); |