Blame view

arch/arm/mach-orion5x/pci.c 14.8 KB
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
1
  /*
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
2
   * arch/arm/mach-orion5x/pci.c
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
3
   *
159ffb3a0   Lennert Buytenhek   Orion: general cl...
4
   * PCI and PCIe functions for Marvell Orion System On Chip
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
5
6
7
   *
   * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
   *
159ffb3a0   Lennert Buytenhek   Orion: general cl...
8
9
   * This file is licensed under the terms of the GNU General Public
   * License version 2.  This program is licensed "as is" without any
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
10
11
12
13
14
   * warranty of any kind, whether express or implied.
   */
  
  #include <linux/kernel.h>
  #include <linux/pci.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
15
  #include <linux/slab.h>
1f2223b12   Lennert Buytenhek   Orion: make PCIe/...
16
  #include <linux/mbus.h>
158c0c623   Bryan Wu   ARM: mach-orion5x...
17
  #include <video/vga.h>
ff89c462d   Nicolas Pitre   [ARM] 5360/1: Ori...
18
  #include <asm/irq.h>
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
19
  #include <asm/mach/pci.h>
6f088f1d2   Lennert Buytenhek   [ARM] Move includ...
20
  #include <plat/pcie.h>
45173d5ed   Andrew Lunn   ARM: Orion: mbus_...
21
  #include <plat/addr-map.h>
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
22
23
24
  #include "common.h"
  
  /*****************************************************************************
159ffb3a0   Lennert Buytenhek   Orion: general cl...
25
   * Orion has one PCIe controller and one PCI controller.
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
26
   *
159ffb3a0   Lennert Buytenhek   Orion: general cl...
27
28
   * Note1: The local PCIe bus number is '0'. The local PCI bus number
   * follows the scanned PCIe bridged busses, if any.
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
29
   *
159ffb3a0   Lennert Buytenhek   Orion: general cl...
30
   * Note2: It is possible for PCI/PCIe agents to access many subsystem's
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
31
32
33
34
35
36
37
   * space, by configuring BARs and Address Decode Windows, e.g. flashes on
   * device bus, Orion registers, etc. However this code only enable the
   * access to DDR banks.
   ****************************************************************************/
  
  
  /*****************************************************************************
159ffb3a0   Lennert Buytenhek   Orion: general cl...
38
   * PCIe controller
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
39
   ****************************************************************************/
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
40
  #define PCIE_BASE	((void __iomem *)ORION5X_PCIE_VIRT_BASE)
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
41

9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
42
  void __init orion5x_pcie_id(u32 *dev, u32 *rev)
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
43
  {
abc0197d7   Lennert Buytenhek   plat-orion: share...
44
45
  	*dev = orion_pcie_dev_id(PCIE_BASE);
  	*rev = orion_pcie_rev(PCIE_BASE);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
46
  }
abc0197d7   Lennert Buytenhek   plat-orion: share...
47
  static int pcie_valid_config(int bus, int dev)
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
48
49
50
  {
  	/*
  	 * Don't go out when trying to access --
d50c60a87   Lennert Buytenhek   Orion: enable acc...
51
  	 * 1. nonexisting device on local bus
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
52
  	 * 2. where there's no device connected (no link)
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
53
  	 */
d50c60a87   Lennert Buytenhek   Orion: enable acc...
54
55
  	if (bus == 0 && dev == 0)
  		return 1;
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
56

abc0197d7   Lennert Buytenhek   plat-orion: share...
57
  	if (!orion_pcie_link_up(PCIE_BASE))
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
58
  		return 0;
d50c60a87   Lennert Buytenhek   Orion: enable acc...
59
60
  	if (bus == 0 && dev != 1)
  		return 0;
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
61
62
  	return 1;
  }
abc0197d7   Lennert Buytenhek   plat-orion: share...
63
64
  
  /*
159ffb3a0   Lennert Buytenhek   Orion: general cl...
65
   * PCIe config cycles are done by programming the PCIE_CONF_ADDR register
abc0197d7   Lennert Buytenhek   plat-orion: share...
66
67
68
   * and then reading the PCIE_CONF_DATA register. Need to make sure these
   * transactions are atomic.
   */
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
69
  static DEFINE_SPINLOCK(orion5x_pcie_lock);
abc0197d7   Lennert Buytenhek   plat-orion: share...
70
71
72
  
  static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
  			int size, u32 *val)
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
73
74
  {
  	unsigned long flags;
abc0197d7   Lennert Buytenhek   plat-orion: share...
75
  	int ret;
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
76

abc0197d7   Lennert Buytenhek   plat-orion: share...
77
  	if (pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) {
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
78
79
80
  		*val = 0xffffffff;
  		return PCIBIOS_DEVICE_NOT_FOUND;
  	}
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
81
  	spin_lock_irqsave(&orion5x_pcie_lock, flags);
abc0197d7   Lennert Buytenhek   plat-orion: share...
82
  	ret = orion_pcie_rd_conf(PCIE_BASE, bus, devfn, where, size, val);
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
83
  	spin_unlock_irqrestore(&orion5x_pcie_lock, flags);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
84

abc0197d7   Lennert Buytenhek   plat-orion: share...
85
86
  	return ret;
  }
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
87

abc0197d7   Lennert Buytenhek   plat-orion: share...
88
89
90
91
  static int pcie_rd_conf_wa(struct pci_bus *bus, u32 devfn,
  			   int where, int size, u32 *val)
  {
  	int ret;
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
92

abc0197d7   Lennert Buytenhek   plat-orion: share...
93
94
95
96
  	if (pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) {
  		*val = 0xffffffff;
  		return PCIBIOS_DEVICE_NOT_FOUND;
  	}
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
97

abc0197d7   Lennert Buytenhek   plat-orion: share...
98
99
100
101
102
103
104
105
106
  	/*
  	 * We only support access to the non-extended configuration
  	 * space when using the WA access method (or we would have to
  	 * sacrifice 256M of CPU virtual address space.)
  	 */
  	if (where >= 0x100) {
  		*val = 0xffffffff;
  		return PCIBIOS_DEVICE_NOT_FOUND;
  	}
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
107

9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
108
  	ret = orion_pcie_rd_conf_wa((void __iomem *)ORION5X_PCIE_WA_VIRT_BASE,
abc0197d7   Lennert Buytenhek   plat-orion: share...
109
  				    bus, devfn, where, size, val);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
110

abc0197d7   Lennert Buytenhek   plat-orion: share...
111
112
  	return ret;
  }
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
113

abc0197d7   Lennert Buytenhek   plat-orion: share...
114
115
  static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
  			int where, int size, u32 val)
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
116
117
118
  {
  	unsigned long flags;
  	int ret;
abc0197d7   Lennert Buytenhek   plat-orion: share...
119
  	if (pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0)
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
120
  		return PCIBIOS_DEVICE_NOT_FOUND;
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
121
  	spin_lock_irqsave(&orion5x_pcie_lock, flags);
abc0197d7   Lennert Buytenhek   plat-orion: share...
122
  	ret = orion_pcie_wr_conf(PCIE_BASE, bus, devfn, where, size, val);
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
123
  	spin_unlock_irqrestore(&orion5x_pcie_lock, flags);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
124
125
126
  
  	return ret;
  }
159ffb3a0   Lennert Buytenhek   Orion: general cl...
127
  static struct pci_ops pcie_ops = {
abc0197d7   Lennert Buytenhek   plat-orion: share...
128
129
  	.read = pcie_rd_conf,
  	.write = pcie_wr_conf,
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
130
  };
a99842704   Lennert Buytenhek   Orion: add __init...
131
  static int __init pcie_setup(struct pci_sys_data *sys)
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
132
133
  {
  	struct resource *res;
abc0197d7   Lennert Buytenhek   plat-orion: share...
134
  	int dev;
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
135
136
  
  	/*
abc0197d7   Lennert Buytenhek   plat-orion: share...
137
  	 * Generic PCIe unit setup.
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
138
  	 */
63a9332b2   Andrew Lunn   ARM: Orion: Get a...
139
  	orion_pcie_setup(PCIE_BASE);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
140
141
  
  	/*
abc0197d7   Lennert Buytenhek   plat-orion: share...
142
143
  	 * Check whether to apply Orion-1/Orion-NAS PCIe config
  	 * read transaction workaround.
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
144
  	 */
abc0197d7   Lennert Buytenhek   plat-orion: share...
145
146
147
148
149
  	dev = orion_pcie_dev_id(PCIE_BASE);
  	if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) {
  		printk(KERN_NOTICE "Applying Orion-1/Orion-NAS PCIe config "
  				   "read transaction workaround
  ");
386a048a1   Lennert Buytenhek   [ARM] Orion: move...
150
151
  		orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
  					  ORION5X_PCIE_WA_SIZE);
abc0197d7   Lennert Buytenhek   plat-orion: share...
152
153
  		pcie_ops.read = pcie_rd_conf_wa;
  	}
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
154
155
  
  	/*
abc0197d7   Lennert Buytenhek   plat-orion: share...
156
  	 * Request resources.
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
157
158
159
  	 */
  	res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
  	if (!res)
abc0197d7   Lennert Buytenhek   plat-orion: share...
160
  		panic("pcie_setup unable to alloc resources");
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
161
162
163
164
  
  	/*
  	 * IORESOURCE_IO
  	 */
159ffb3a0   Lennert Buytenhek   Orion: general cl...
165
  	res[0].name = "PCIe I/O Space";
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
166
  	res[0].flags = IORESOURCE_IO;
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
167
168
  	res[0].start = ORION5X_PCIE_IO_BUS_BASE;
  	res[0].end = res[0].start + ORION5X_PCIE_IO_SIZE - 1;
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
169
  	if (request_resource(&ioport_resource, &res[0]))
159ffb3a0   Lennert Buytenhek   Orion: general cl...
170
171
  		panic("Request PCIe IO resource failed
  ");
37d15909f   Bjorn Helgaas   arm/PCI: convert ...
172
  	pci_add_resource(&sys->resources, &res[0]);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
173
174
175
176
  
  	/*
  	 * IORESOURCE_MEM
  	 */
159ffb3a0   Lennert Buytenhek   Orion: general cl...
177
  	res[1].name = "PCIe Memory Space";
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
178
  	res[1].flags = IORESOURCE_MEM;
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
179
180
  	res[1].start = ORION5X_PCIE_MEM_PHYS_BASE;
  	res[1].end = res[1].start + ORION5X_PCIE_MEM_SIZE - 1;
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
181
  	if (request_resource(&iomem_resource, &res[1]))
159ffb3a0   Lennert Buytenhek   Orion: general cl...
182
183
  		panic("Request PCIe Memory resource failed
  ");
37d15909f   Bjorn Helgaas   arm/PCI: convert ...
184
  	pci_add_resource(&sys->resources, &res[1]);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
185

038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
186
187
188
189
190
191
192
193
  	sys->io_offset = 0;
  
  	return 1;
  }
  
  /*****************************************************************************
   * PCI controller
   ****************************************************************************/
fdd8b079e   Nicolas Pitre   [ARM] 5460/1: Ori...
194
  #define ORION5X_PCI_REG(x)	(ORION5X_PCI_VIRT_BASE | (x))
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
195
196
197
198
199
  #define PCI_MODE		ORION5X_PCI_REG(0xd00)
  #define PCI_CMD			ORION5X_PCI_REG(0xc00)
  #define PCI_P2P_CONF		ORION5X_PCI_REG(0x1d14)
  #define PCI_CONF_ADDR		ORION5X_PCI_REG(0xc78)
  #define PCI_CONF_DATA		ORION5X_PCI_REG(0xc7c)
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
  
  /*
   * PCI_MODE bits
   */
  #define PCI_MODE_64BIT			(1 << 2)
  #define PCI_MODE_PCIX			((1 << 4) | (1 << 5))
  
  /*
   * PCI_CMD bits
   */
  #define PCI_CMD_HOST_REORDER		(1 << 29)
  
  /*
   * PCI_P2P_CONF bits
   */
  #define PCI_P2P_BUS_OFFS		16
  #define PCI_P2P_BUS_MASK		(0xff << PCI_P2P_BUS_OFFS)
  #define PCI_P2P_DEV_OFFS		24
  #define PCI_P2P_DEV_MASK		(0x1f << PCI_P2P_DEV_OFFS)
  
  /*
   * PCI_CONF_ADDR bits
   */
  #define PCI_CONF_REG(reg)		((reg) & 0xfc)
  #define PCI_CONF_FUNC(func)		(((func) & 0x3) << 8)
  #define PCI_CONF_DEV(dev)		(((dev) & 0x1f) << 11)
  #define PCI_CONF_BUS(bus)		(((bus) & 0xff) << 16)
  #define PCI_CONF_ADDR_EN		(1 << 31)
  
  /*
   * Internal configuration space
   */
  #define PCI_CONF_FUNC_STAT_CMD		0
  #define PCI_CONF_REG_STAT_CMD		4
  #define PCIX_STAT			0x64
  #define PCIX_STAT_BUS_OFFS		8
  #define PCIX_STAT_BUS_MASK		(0xff << PCIX_STAT_BUS_OFFS)
  
  /*
1f2223b12   Lennert Buytenhek   Orion: make PCIe/...
239
240
   * PCI Address Decode Windows registers
   */
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
241
  #define PCI_BAR_SIZE_DDR_CS(n)	(((n) == 0) ? ORION5X_PCI_REG(0xc08) : \
e7068ad33   Lennert Buytenhek   [ARM] Orion: fix ...
242
243
244
245
246
247
248
  				 ((n) == 1) ? ORION5X_PCI_REG(0xd08) : \
  				 ((n) == 2) ? ORION5X_PCI_REG(0xc0c) : \
  				 ((n) == 3) ? ORION5X_PCI_REG(0xd0c) : 0)
  #define PCI_BAR_REMAP_DDR_CS(n)	(((n) == 0) ? ORION5X_PCI_REG(0xc48) : \
  				 ((n) == 1) ? ORION5X_PCI_REG(0xd48) : \
  				 ((n) == 2) ? ORION5X_PCI_REG(0xc4c) : \
  				 ((n) == 3) ? ORION5X_PCI_REG(0xd4c) : 0)
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
249
250
  #define PCI_BAR_ENABLE		ORION5X_PCI_REG(0xc3c)
  #define PCI_ADDR_DECODE_CTRL	ORION5X_PCI_REG(0xd3c)
1f2223b12   Lennert Buytenhek   Orion: make PCIe/...
251
252
253
254
255
256
257
258
259
  
  /*
   * PCI configuration helpers for BAR settings
   */
  #define PCI_CONF_FUNC_BAR_CS(n)		((n) >> 1)
  #define PCI_CONF_REG_BAR_LO_CS(n)	(((n) & 1) ? 0x18 : 0x10)
  #define PCI_CONF_REG_BAR_HI_CS(n)	(((n) & 1) ? 0x1c : 0x14)
  
  /*
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
260
261
262
263
   * PCI config cycles are done by programming the PCI_CONF_ADDR register
   * and then reading the PCI_CONF_DATA register. Need to make sure these
   * transactions are atomic.
   */
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
264
  static DEFINE_SPINLOCK(orion5x_pci_lock);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
265

da01bba3c   Lennert Buytenhek   [ARM] Orion: make...
266
  static int orion5x_pci_cardbus_mode;
92b913b08   Lennert Buytenhek   [ARM] Orion: fix ...
267
  static int orion5x_pci_local_bus_nr(void)
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
268
  {
79e90dd5a   Lennert Buytenhek   [ARM] Orion: nuke...
269
  	u32 conf = readl(PCI_P2P_CONF);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
270
271
  	return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS);
  }
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
272
  static int orion5x_pci_hw_rd_conf(int bus, int dev, u32 func,
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
273
274
275
  					u32 where, u32 size, u32 *val)
  {
  	unsigned long flags;
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
276
  	spin_lock_irqsave(&orion5x_pci_lock, flags);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
277

79e90dd5a   Lennert Buytenhek   [ARM] Orion: nuke...
278
279
280
  	writel(PCI_CONF_BUS(bus) |
  		PCI_CONF_DEV(dev) | PCI_CONF_REG(where) |
  		PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN, PCI_CONF_ADDR);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
281

79e90dd5a   Lennert Buytenhek   [ARM] Orion: nuke...
282
  	*val = readl(PCI_CONF_DATA);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
283
284
285
286
287
  
  	if (size == 1)
  		*val = (*val >> (8*(where & 0x3))) & 0xff;
  	else if (size == 2)
  		*val = (*val >> (8*(where & 0x3))) & 0xffff;
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
288
  	spin_unlock_irqrestore(&orion5x_pci_lock, flags);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
289
290
291
  
  	return PCIBIOS_SUCCESSFUL;
  }
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
292
  static int orion5x_pci_hw_wr_conf(int bus, int dev, u32 func,
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
293
294
295
296
  					u32 where, u32 size, u32 val)
  {
  	unsigned long flags;
  	int ret = PCIBIOS_SUCCESSFUL;
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
297
  	spin_lock_irqsave(&orion5x_pci_lock, flags);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
298

79e90dd5a   Lennert Buytenhek   [ARM] Orion: nuke...
299
300
301
  	writel(PCI_CONF_BUS(bus) |
  		PCI_CONF_DEV(dev) | PCI_CONF_REG(where) |
  		PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN, PCI_CONF_ADDR);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
302
303
304
305
306
307
308
309
310
311
  
  	if (size == 4) {
  		__raw_writel(val, PCI_CONF_DATA);
  	} else if (size == 2) {
  		__raw_writew(val, PCI_CONF_DATA + (where & 0x3));
  	} else if (size == 1) {
  		__raw_writeb(val, PCI_CONF_DATA + (where & 0x3));
  	} else {
  		ret = PCIBIOS_BAD_REGISTER_NUMBER;
  	}
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
312
  	spin_unlock_irqrestore(&orion5x_pci_lock, flags);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
313
314
315
  
  	return ret;
  }
da01bba3c   Lennert Buytenhek   [ARM] Orion: make...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
  static int orion5x_pci_valid_config(int bus, u32 devfn)
  {
  	if (bus == orion5x_pci_local_bus_nr()) {
  		/*
  		 * Don't go out for local device
  		 */
  		if (PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0)
  			return 0;
  
  		/*
  		 * When the PCI signals are directly connected to a
  		 * Cardbus slot, ignore all but device IDs 0 and 1.
  		 */
  		if (orion5x_pci_cardbus_mode && PCI_SLOT(devfn) > 1)
  			return 0;
  	}
  
  	return 1;
  }
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
335
  static int orion5x_pci_rd_conf(struct pci_bus *bus, u32 devfn,
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
336
337
  				int where, int size, u32 *val)
  {
da01bba3c   Lennert Buytenhek   [ARM] Orion: make...
338
  	if (!orion5x_pci_valid_config(bus->number, devfn)) {
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
339
340
341
  		*val = 0xffffffff;
  		return PCIBIOS_DEVICE_NOT_FOUND;
  	}
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
342
  	return orion5x_pci_hw_rd_conf(bus->number, PCI_SLOT(devfn),
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
343
344
  					PCI_FUNC(devfn), where, size, val);
  }
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
345
  static int orion5x_pci_wr_conf(struct pci_bus *bus, u32 devfn,
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
346
347
  				int where, int size, u32 val)
  {
da01bba3c   Lennert Buytenhek   [ARM] Orion: make...
348
  	if (!orion5x_pci_valid_config(bus->number, devfn))
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
349
  		return PCIBIOS_DEVICE_NOT_FOUND;
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
350
  	return orion5x_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn),
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
351
352
  					PCI_FUNC(devfn), where, size, val);
  }
159ffb3a0   Lennert Buytenhek   Orion: general cl...
353
  static struct pci_ops pci_ops = {
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
354
355
  	.read = orion5x_pci_rd_conf,
  	.write = orion5x_pci_wr_conf,
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
356
  };
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
357
  static void __init orion5x_pci_set_bus_nr(int nr)
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
358
  {
79e90dd5a   Lennert Buytenhek   [ARM] Orion: nuke...
359
  	u32 p2p = readl(PCI_P2P_CONF);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
360

79e90dd5a   Lennert Buytenhek   [ARM] Orion: nuke...
361
  	if (readl(PCI_MODE) & PCI_MODE_PCIX) {
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
362
363
364
365
366
367
  		/*
  		 * PCI-X mode
  		 */
  		u32 pcix_status, bus, dev;
  		bus = (p2p & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS;
  		dev = (p2p & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS;
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
368
  		orion5x_pci_hw_rd_conf(bus, dev, 0, PCIX_STAT, 4, &pcix_status);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
369
370
  		pcix_status &= ~PCIX_STAT_BUS_MASK;
  		pcix_status |= (nr << PCIX_STAT_BUS_OFFS);
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
371
  		orion5x_pci_hw_wr_conf(bus, dev, 0, PCIX_STAT, 4, pcix_status);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
372
373
374
375
376
377
  	} else {
  		/*
  		 * PCI Conventional mode
  		 */
  		p2p &= ~PCI_P2P_BUS_MASK;
  		p2p |= (nr << PCI_P2P_BUS_OFFS);
79e90dd5a   Lennert Buytenhek   [ARM] Orion: nuke...
378
  		writel(p2p, PCI_P2P_CONF);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
379
380
  	}
  }
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
381
  static void __init orion5x_pci_master_slave_enable(void)
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
382
  {
d50c60a87   Lennert Buytenhek   Orion: enable acc...
383
  	int bus_nr, func, reg;
abc0197d7   Lennert Buytenhek   plat-orion: share...
384
  	u32 val;
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
385

9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
386
  	bus_nr = orion5x_pci_local_bus_nr();
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
387
388
  	func = PCI_CONF_FUNC_STAT_CMD;
  	reg = PCI_CONF_REG_STAT_CMD;
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
389
  	orion5x_pci_hw_rd_conf(bus_nr, 0, func, reg, 4, &val);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
390
  	val |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
391
  	orion5x_pci_hw_wr_conf(bus_nr, 0, func, reg, 4, val | 0x7);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
392
  }
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
393
  static void __init orion5x_setup_pci_wins(struct mbus_dram_target_info *dram)
1f2223b12   Lennert Buytenhek   Orion: make PCIe/...
394
395
  {
  	u32 win_enable;
abc0197d7   Lennert Buytenhek   plat-orion: share...
396
  	int bus;
1f2223b12   Lennert Buytenhek   Orion: make PCIe/...
397
398
399
400
401
402
  	int i;
  
  	/*
  	 * First, disable windows.
  	 */
  	win_enable = 0xffffffff;
79e90dd5a   Lennert Buytenhek   [ARM] Orion: nuke...
403
  	writel(win_enable, PCI_BAR_ENABLE);
1f2223b12   Lennert Buytenhek   Orion: make PCIe/...
404
405
406
407
  
  	/*
  	 * Setup windows for DDR banks.
  	 */
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
408
  	bus = orion5x_pci_local_bus_nr();
1f2223b12   Lennert Buytenhek   Orion: make PCIe/...
409
410
411
412
413
414
415
416
417
418
419
  
  	for (i = 0; i < dram->num_cs; i++) {
  		struct mbus_dram_window *cs = dram->cs + i;
  		u32 func = PCI_CONF_FUNC_BAR_CS(cs->cs_index);
  		u32 reg;
  		u32 val;
  
  		/*
  		 * Write DRAM bank base address register.
  		 */
  		reg = PCI_CONF_REG_BAR_LO_CS(cs->cs_index);
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
420
  		orion5x_pci_hw_rd_conf(bus, 0, func, reg, 4, &val);
1f2223b12   Lennert Buytenhek   Orion: make PCIe/...
421
  		val = (cs->base & 0xfffff000) | (val & 0xfff);
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
422
  		orion5x_pci_hw_wr_conf(bus, 0, func, reg, 4, val);
1f2223b12   Lennert Buytenhek   Orion: make PCIe/...
423
424
425
426
427
  
  		/*
  		 * Write DRAM bank size register.
  		 */
  		reg = PCI_CONF_REG_BAR_HI_CS(cs->cs_index);
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
428
  		orion5x_pci_hw_wr_conf(bus, 0, func, reg, 4, 0);
79e90dd5a   Lennert Buytenhek   [ARM] Orion: nuke...
429
430
431
432
  		writel((cs->size - 1) & 0xfffff000,
  			PCI_BAR_SIZE_DDR_CS(cs->cs_index));
  		writel(cs->base & 0xfffff000,
  			PCI_BAR_REMAP_DDR_CS(cs->cs_index));
1f2223b12   Lennert Buytenhek   Orion: make PCIe/...
433
434
435
436
437
438
439
440
441
442
  
  		/*
  		 * Enable decode window for this chip select.
  		 */
  		win_enable &= ~(1 << cs->cs_index);
  	}
  
  	/*
  	 * Re-enable decode windows.
  	 */
79e90dd5a   Lennert Buytenhek   [ARM] Orion: nuke...
443
  	writel(win_enable, PCI_BAR_ENABLE);
1f2223b12   Lennert Buytenhek   Orion: make PCIe/...
444
445
  
  	/*
af901ca18   AndrĂ© Goddard Rosa   tree-wide: fix as...
446
  	 * Disable automatic update of address remapping when writing to BARs.
1f2223b12   Lennert Buytenhek   Orion: make PCIe/...
447
  	 */
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
448
  	orion5x_setbits(PCI_ADDR_DECODE_CTRL, 1);
1f2223b12   Lennert Buytenhek   Orion: make PCIe/...
449
  }
a99842704   Lennert Buytenhek   Orion: add __init...
450
  static int __init pci_setup(struct pci_sys_data *sys)
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
451
452
453
454
  {
  	struct resource *res;
  
  	/*
1f2223b12   Lennert Buytenhek   Orion: make PCIe/...
455
456
  	 * Point PCI unit MBUS decode windows to DRAM space.
  	 */
45173d5ed   Andrew Lunn   ARM: Orion: mbus_...
457
  	orion5x_setup_pci_wins(&orion_mbus_dram_info);
1f2223b12   Lennert Buytenhek   Orion: make PCIe/...
458
459
  
  	/*
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
460
461
  	 * Master + Slave enable
  	 */
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
462
  	orion5x_pci_master_slave_enable();
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
463
464
465
466
  
  	/*
  	 * Force ordering
  	 */
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
467
  	orion5x_setbits(PCI_CMD, PCI_CMD_HOST_REORDER);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
468
469
470
471
472
473
  
  	/*
  	 * Request resources
  	 */
  	res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
  	if (!res)
abc0197d7   Lennert Buytenhek   plat-orion: share...
474
  		panic("pci_setup unable to alloc resources");
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
475
476
477
478
479
480
  
  	/*
  	 * IORESOURCE_IO
  	 */
  	res[0].name = "PCI I/O Space";
  	res[0].flags = IORESOURCE_IO;
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
481
482
  	res[0].start = ORION5X_PCI_IO_BUS_BASE;
  	res[0].end = res[0].start + ORION5X_PCI_IO_SIZE - 1;
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
483
484
485
  	if (request_resource(&ioport_resource, &res[0]))
  		panic("Request PCI IO resource failed
  ");
37d15909f   Bjorn Helgaas   arm/PCI: convert ...
486
  	pci_add_resource(&sys->resources, &res[0]);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
487
488
489
490
491
492
  
  	/*
  	 * IORESOURCE_MEM
  	 */
  	res[1].name = "PCI Memory Space";
  	res[1].flags = IORESOURCE_MEM;
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
493
494
  	res[1].start = ORION5X_PCI_MEM_PHYS_BASE;
  	res[1].end = res[1].start + ORION5X_PCI_MEM_SIZE - 1;
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
495
496
497
  	if (request_resource(&iomem_resource, &res[1]))
  		panic("Request PCI Memory resource failed
  ");
37d15909f   Bjorn Helgaas   arm/PCI: convert ...
498
  	pci_add_resource(&sys->resources, &res[1]);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
499

038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
500
501
502
503
504
505
506
  	sys->io_offset = 0;
  
  	return 1;
  }
  
  
  /*****************************************************************************
159ffb3a0   Lennert Buytenhek   Orion: general cl...
507
   * General PCIe + PCI
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
508
   ****************************************************************************/
d50c60a87   Lennert Buytenhek   Orion: enable acc...
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
  static void __devinit rc_pci_fixup(struct pci_dev *dev)
  {
  	/*
  	 * Prevent enumeration of root complex.
  	 */
  	if (dev->bus->parent == NULL && dev->devfn == 0) {
  		int i;
  
  		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
  			dev->resource[i].start = 0;
  			dev->resource[i].end   = 0;
  			dev->resource[i].flags = 0;
  		}
  	}
  }
  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
7a6bb2622   Per Andersson   [ARM] Orion: Fix ...
525
526
527
528
529
530
  static int orion5x_pci_disabled __initdata;
  
  void __init orion5x_pci_disable(void)
  {
  	orion5x_pci_disabled = 1;
  }
da01bba3c   Lennert Buytenhek   [ARM] Orion: make...
531
532
533
534
  void __init orion5x_pci_set_cardbus_mode(void)
  {
  	orion5x_pci_cardbus_mode = 1;
  }
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
535
  int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys)
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
536
537
  {
  	int ret = 0;
cc22b4c18   Rob Herring   ARM: set vga memo...
538
  	vga_base = ORION5X_PCIE_MEM_PHYS_BASE;
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
539
  	if (nr == 0) {
abc0197d7   Lennert Buytenhek   plat-orion: share...
540
541
  		orion_pcie_set_local_bus_nr(PCIE_BASE, sys->busnr);
  		ret = pcie_setup(sys);
7a6bb2622   Per Andersson   [ARM] Orion: Fix ...
542
  	} else if (nr == 1 && !orion5x_pci_disabled) {
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
543
  		orion5x_pci_set_bus_nr(sys->busnr);
abc0197d7   Lennert Buytenhek   plat-orion: share...
544
  		ret = pci_setup(sys);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
545
546
547
548
  	}
  
  	return ret;
  }
9dd0b194b   Lennert Buytenhek   Orion: orion -> o...
549
  struct pci_bus __init *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys)
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
550
  {
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
551
  	struct pci_bus *bus;
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
552
  	if (nr == 0) {
37d15909f   Bjorn Helgaas   arm/PCI: convert ...
553
554
  		bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
  					&sys->resources);
7a6bb2622   Per Andersson   [ARM] Orion: Fix ...
555
  	} else if (nr == 1 && !orion5x_pci_disabled) {
37d15909f   Bjorn Helgaas   arm/PCI: convert ...
556
557
  		bus = pci_scan_root_bus(NULL, sys->busnr, &pci_ops, sys,
  					&sys->resources);
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
558
  	} else {
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
559
  		bus = NULL;
abc0197d7   Lennert Buytenhek   plat-orion: share...
560
  		BUG();
038ee0832   Tzachi Perelstein   [ARM] Orion: PCI ...
561
562
563
564
  	}
  
  	return bus;
  }
92b913b08   Lennert Buytenhek   [ARM] Orion: fix ...
565

d5341942d   Ralf Baechle   PCI: Make the str...
566
  int __init orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
92b913b08   Lennert Buytenhek   [ARM] Orion: fix ...
567
568
569
570
571
572
  {
  	int bus = dev->bus->number;
  
  	/*
  	 * PCIe endpoint?
  	 */
7a6bb2622   Per Andersson   [ARM] Orion: Fix ...
573
  	if (orion5x_pci_disabled || bus < orion5x_pci_local_bus_nr())
92b913b08   Lennert Buytenhek   [ARM] Orion: fix ...
574
575
576
577
  		return IRQ_ORION5X_PCIE0_INT;
  
  	return -1;
  }