aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/drivers
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-02-10 02:00:58 -0500
committerPaul Mundt <lethal@linux-sh.org>2010-02-10 02:00:58 -0500
commit7578a4c625a5cc32812946338a4549f3090be113 (patch)
treedbd53333f97fc2af6818e8bfac50d02917cf1583 /arch/sh/drivers
parent801cd56e3e2c2b727399d2c50c50139b2d7c98e8 (diff)
sh: Fix up multi-resource mapping for SH7786 PCIe.
This reworks some of the SH7786 PCIe initialization code to dynamically setup and size the various resource windows, as opposed to the original code that simply wired in a couple of them statically. At the same time, we tidy up the initialization code a bit, kill off some read-only register twiddling that was gleaned from the bus analyzer, and also propagate the physical slot/channel mapping. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/drivers')
-rw-r--r--arch/sh/drivers/pci/pcie-sh7786.c89
-rw-r--r--arch/sh/drivers/pci/pcie-sh7786.h36
2 files changed, 82 insertions, 43 deletions
diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c
index 95d095f26d6..ae91a2dd918 100644
--- a/arch/sh/drivers/pci/pcie-sh7786.c
+++ b/arch/sh/drivers/pci/pcie-sh7786.c
@@ -204,7 +204,9 @@ static int pcie_init(struct sh7786_pcie_port *port)
204{ 204{
205 struct pci_channel *chan = port->hose; 205 struct pci_channel *chan = port->hose;
206 unsigned int data; 206 unsigned int data;
207 int ret; 207 phys_addr_t memphys;
208 size_t memsize;
209 int ret, i;
208 210
209 /* Begin initialization */ 211 /* Begin initialization */
210 pci_write_reg(chan, 0, SH4A_PCIETCTLR); 212 pci_write_reg(chan, 0, SH4A_PCIETCTLR);
@@ -227,15 +229,24 @@ static int pcie_init(struct sh7786_pcie_port *port)
227 data |= PCI_CAP_ID_EXP; 229 data |= PCI_CAP_ID_EXP;
228 pci_write_reg(chan, data, SH4A_PCIEEXPCAP0); 230 pci_write_reg(chan, data, SH4A_PCIEEXPCAP0);
229 231
230 /* Enable x4 link width and extended sync. */ 232 /* Enable data link layer active state reporting */
233 pci_write_reg(chan, PCI_EXP_LNKCAP_DLLLARC, SH4A_PCIEEXPCAP3);
234
235 /* Enable extended sync and ASPM L0s support */
231 data = pci_read_reg(chan, SH4A_PCIEEXPCAP4); 236 data = pci_read_reg(chan, SH4A_PCIEEXPCAP4);
232 data &= ~(PCI_EXP_LNKSTA_NLW << 16); 237 data &= ~PCI_EXP_LNKCTL_ASPMC;
233 data |= (1 << 22) | PCI_EXP_LNKCTL_ES; 238 data |= PCI_EXP_LNKCTL_ES | 1;
234 pci_write_reg(chan, data, SH4A_PCIEEXPCAP4); 239 pci_write_reg(chan, data, SH4A_PCIEEXPCAP4);
235 240
241 /* Write out the physical slot number */
242 data = pci_read_reg(chan, SH4A_PCIEEXPCAP5);
243 data &= ~PCI_EXP_SLTCAP_PSN;
244 data |= (port->index + 1) << 19;
245 pci_write_reg(chan, data, SH4A_PCIEEXPCAP5);
246
236 /* Set the completion timer timeout to the maximum 32ms. */ 247 /* Set the completion timer timeout to the maximum 32ms. */
237 data = pci_read_reg(chan, SH4A_PCIETLCTLR); 248 data = pci_read_reg(chan, SH4A_PCIETLCTLR);
238 data &= ~0xffff; 249 data &= ~0x3f00;
239 data |= 0x32 << 8; 250 data |= 0x32 << 8;
240 pci_write_reg(chan, data, SH4A_PCIETLCTLR); 251 pci_write_reg(chan, data, SH4A_PCIETLCTLR);
241 252
@@ -248,6 +259,33 @@ static int pcie_init(struct sh7786_pcie_port *port)
248 data |= (0xff << 16); 259 data |= (0xff << 16);
249 pci_write_reg(chan, data, SH4A_PCIEMACCTLR); 260 pci_write_reg(chan, data, SH4A_PCIEMACCTLR);
250 261
262 memphys = __pa(memory_start);
263 memsize = roundup_pow_of_two(memory_end - memory_start);
264
265 /*
266 * If there's more than 512MB of memory, we need to roll over to
267 * LAR1/LAMR1.
268 */
269 if (memsize > SZ_512M) {
270 __raw_writel(memphys + SZ_512M, chan->reg_base + SH4A_PCIELAR1);
271 __raw_writel(((memsize - SZ_512M) - SZ_256) | 1,
272 chan->reg_base + SH4A_PCIELAMR1);
273 memsize = SZ_512M;
274 } else {
275 /*
276 * Otherwise just zero it out and disable it.
277 */
278 __raw_writel(0, chan->reg_base + SH4A_PCIELAR1);
279 __raw_writel(0, chan->reg_base + SH4A_PCIELAMR1);
280 }
281
282 /*
283 * LAR0/LAMR0 covers up to the first 512MB, which is enough to
284 * cover all of lowmem on most platforms.
285 */
286 __raw_writel(memphys, chan->reg_base + SH4A_PCIELAR0);
287 __raw_writel((memsize - SZ_256) | 1, chan->reg_base + SH4A_PCIELAMR0);
288
251 /* Finish initialization */ 289 /* Finish initialization */
252 data = pci_read_reg(chan, SH4A_PCIETCTLR); 290 data = pci_read_reg(chan, SH4A_PCIETCTLR);
253 data |= 0x1; 291 data |= 0x1;
@@ -267,10 +305,14 @@ static int pcie_init(struct sh7786_pcie_port *port)
267 if (unlikely(ret != 0)) 305 if (unlikely(ret != 0))
268 return -ENODEV; 306 return -ENODEV;
269 307
270 pci_write_reg(chan, 0x00100007, SH4A_PCIEPCICONF1); 308 data = pci_read_reg(chan, SH4A_PCIEPCICONF1);
309 data &= ~(PCI_STATUS_DEVSEL_MASK << 16);
310 data |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
311 (PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_FAST) << 16;
312 pci_write_reg(chan, data, SH4A_PCIEPCICONF1);
313
271 pci_write_reg(chan, 0x80888000, SH4A_PCIETXVC0DCTLR); 314 pci_write_reg(chan, 0x80888000, SH4A_PCIETXVC0DCTLR);
272 pci_write_reg(chan, 0x00222000, SH4A_PCIERXVC0DCTLR); 315 pci_write_reg(chan, 0x00222000, SH4A_PCIERXVC0DCTLR);
273 pci_write_reg(chan, 0x000050A0, SH4A_PCIEEXPCAP2);
274 316
275 wmb(); 317 wmb();
276 318
@@ -278,15 +320,32 @@ static int pcie_init(struct sh7786_pcie_port *port)
278 printk(KERN_NOTICE "PCI: PCIe#%d link width %d\n", 320 printk(KERN_NOTICE "PCI: PCIe#%d link width %d\n",
279 port->index, (data >> 20) & 0x3f); 321 port->index, (data >> 20) & 0x3f);
280 322
281 pci_write_reg(chan, 0x007c0000, SH4A_PCIEPAMR0);
282 pci_write_reg(chan, 0x00000000, SH4A_PCIEPARH0);
283 pci_write_reg(chan, 0x00000000, SH4A_PCIEPARL0);
284 pci_write_reg(chan, 0x80000100, SH4A_PCIEPTCTLR0);
285 323
286 pci_write_reg(chan, 0x03fc0000, SH4A_PCIEPAMR2); 324 for (i = 0; i < chan->nr_resources; i++) {
287 pci_write_reg(chan, 0x00000000, SH4A_PCIEPARH2); 325 struct resource *res = chan->resources + i;
288 pci_write_reg(chan, 0x00000000, SH4A_PCIEPARL2); 326 resource_size_t size;
289 pci_write_reg(chan, 0x80000000, SH4A_PCIEPTCTLR2); 327 u32 enable_mask;
328
329 pci_write_reg(chan, 0x00000000, SH4A_PCIEPTCTLR(i));
330
331 size = resource_size(res);
332
333 /*
334 * The PAMR mask is calculated in units of 256kB, which
335 * keeps things pretty simple.
336 */
337 __raw_writel(((roundup_pow_of_two(size) / SZ_256K) - 1) << 18,
338 chan->reg_base + SH4A_PCIEPAMR(i));
339
340 pci_write_reg(chan, 0x00000000, SH4A_PCIEPARH(i));
341 pci_write_reg(chan, 0x00000000, SH4A_PCIEPARL(i));
342
343 enable_mask = MASK_PARE;
344 if (res->flags & IORESOURCE_IO)
345 enable_mask |= MASK_SPC;
346
347 pci_write_reg(chan, enable_mask, SH4A_PCIEPTCTLR(i));
348 }
290 349
291 return 0; 350 return 0;
292} 351}
diff --git a/arch/sh/drivers/pci/pcie-sh7786.h b/arch/sh/drivers/pci/pcie-sh7786.h
index 6666ea29cba..90a6992576b 100644
--- a/arch/sh/drivers/pci/pcie-sh7786.h
+++ b/arch/sh/drivers/pci/pcie-sh7786.h
@@ -312,23 +312,23 @@
312#define SH4A_PCIECSAR5 (0x0202B4) /* R/W R/W 0x0000 0000 32 */ 312#define SH4A_PCIECSAR5 (0x0202B4) /* R/W R/W 0x0000 0000 32 */
313#define SH4A_PCIESTCTLR5 (0x0202B8) /* R/W R/W 0x0000 0000 32 */ 313#define SH4A_PCIESTCTLR5 (0x0202B8) /* R/W R/W 0x0000 0000 32 */
314 314
315/* PCIEPARL0 */ 315/* PCIEPARL */
316#define SH4A_PCIEPARL0 (0x020400) /* R/W R/W 0x0000 0000 32 */ 316#define SH4A_PCIEPARL(x) (0x020400 + ((x) * 0x20)) /* R/W R/W 0x0000 0000 32 */
317#define BITS_PAL (18) 317#define BITS_PAL (18)
318#define MASK_PAL (0x3fff<<BITS_PAL) 318#define MASK_PAL (0x3fff<<BITS_PAL)
319 319
320/* PCIEPARH0 */ 320/* PCIEPARH */
321#define SH4A_PCIEPARH0 (0x020404) /* R/W R/W 0x0000 0000 32 */ 321#define SH4A_PCIEPARH(x) (0x020404 + ((x) * 0x20)) /* R/W R/W 0x0000 0000 32 */
322#define BITS_PAH (0) 322#define BITS_PAH (0)
323#define MASK_PAH (0xffffffff<<BITS_PAH) 323#define MASK_PAH (0xffffffff<<BITS_PAH)
324 324
325/* PCIEPAMR0 */ 325/* PCIEPAMR */
326#define SH4A_PCIEPAMR0 (0x020408) /* R/W R/W 0x0000 0000 32 */ 326#define SH4A_PCIEPAMR(x) (0x020408 + ((x) * 0x20)) /* R/W R/W 0x0000 0000 32 */
327#define BITS_PAM (18) 327#define BITS_PAM (18)
328#define MASK_PAM (0x3fff<<BITS_PAM) 328#define MASK_PAM (0x3fff<<BITS_PAM)
329 329
330/* PCIEPTCTLR0 */ 330/* PCIEPTCTLR */
331#define SH4A_PCIEPTCTLR0 (0x02040C) /* R/W R/W 0x0000 0000 32 */ 331#define SH4A_PCIEPTCTLR(x) (0x02040C + ((x) * 0x20))
332#define BITS_PARE (31) 332#define BITS_PARE (31)
333#define MASK_PARE (0x1<<BITS_PARE) 333#define MASK_PARE (0x1<<BITS_PARE)
334#define BITS_TC (20) 334#define BITS_TC (20)
@@ -340,26 +340,6 @@
340#define BITS_SPC (8) 340#define BITS_SPC (8)
341#define MASK_SPC (0x1<<BITS_SPC) 341#define MASK_SPC (0x1<<BITS_SPC)
342 342
343#define SH4A_PCIEPARL1 (0x020420) /* R/W R/W 0x0000 0000 32 */
344#define SH4A_PCIEPARH1 (0x020424) /* R/W R/W 0x0000 0000 32 */
345#define SH4A_PCIEPAMR1 (0x020428) /* R/W R/W 0x0000 0000 32 */
346#define SH4A_PCIEPTCTLR1 (0x02042C) /* R/W R/W 0x0000 0000 32 */
347#define SH4A_PCIEPARL2 (0x020440) /* R/W R/W 0x0000 0000 32 */
348#define SH4A_PCIEPARH2 (0x020444) /* R/W R/W 0x0000 0000 32 */
349#define SH4A_PCIEPAMR2 (0x020448) /* R/W R/W 0x0000 0000 32 */
350#define SH4A_PCIEPTCTLR2 (0x02044C) /* R/W R/W 0x0000 0000 32 */
351#define SH4A_PCIEPARL3 (0x020460) /* R/W R/W 0x0000 0000 32 */
352#define SH4A_PCIEPARH3 (0x020464) /* R/W R/W 0x0000 0000 32 */
353#define SH4A_PCIEPAMR3 (0x020468) /* R/W R/W 0x0000 0000 32 */
354#define SH4A_PCIEPTCTLR3 (0x02046C) /* R/W R/W 0x0000 0000 32 */
355#define SH4A_PCIEPARL4 (0x020480) /* R/W R/W 0x0000 0000 32 */
356#define SH4A_PCIEPARH4 (0x020484) /* R/W R/W 0x0000 0000 32 */
357#define SH4A_PCIEPAMR4 (0x020488) /* R/W R/W 0x0000 0000 32 */
358#define SH4A_PCIEPTCTLR4 (0x02048C) /* R/W R/W 0x0000 0000 32 */
359#define SH4A_PCIEPARL5 (0x0204A0) /* R/W R/W 0x0000 0000 32 */
360#define SH4A_PCIEPARH5 (0x0204A4) /* R/W R/W 0x0000 0000 32 */
361#define SH4A_PCIEPAMR5 (0x0204A8) /* R/W R/W 0x0000 0000 32 */
362#define SH4A_PCIEPTCTLR5 (0x0204AC) /* R/W R/W 0x0000 0000 32 */
363#define SH4A_PCIEDMAOR (0x021000) /* R/W R/W 0x0000 0000 32 */ 343#define SH4A_PCIEDMAOR (0x021000) /* R/W R/W 0x0000 0000 32 */
364#define SH4A_PCIEDMSAR0 (0x021100) /* R/W R/W 0x0000 0000 32 */ 344#define SH4A_PCIEDMSAR0 (0x021100) /* R/W R/W 0x0000 0000 32 */
365#define SH4A_PCIEDMSAHR0 (0x021104) /* R/W R/W 0x0000 0000 32 */ 345#define SH4A_PCIEDMSAHR0 (0x021104) /* R/W R/W 0x0000 0000 32 */