aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/drivers/pci/pci-st40.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/sh/drivers/pci/pci-st40.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/sh/drivers/pci/pci-st40.c')
-rw-r--r--arch/sh/drivers/pci/pci-st40.c509
1 files changed, 509 insertions, 0 deletions
diff --git a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c
new file mode 100644
index 000000000000..cb6752131156
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-st40.c
@@ -0,0 +1,509 @@
1/*
2 * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
3 *
4 * May be copied or modified under the terms of the GNU General Public
5 * License. See linux/COPYING for more information.
6 *
7 * Support functions for the ST40 PCI hardware.
8 */
9
10#include <linux/config.h>
11#include <linux/kernel.h>
12#include <linux/smp.h>
13#include <linux/smp_lock.h>
14#include <linux/init.h>
15#include <linux/errno.h>
16#include <linux/pci.h>
17#include <linux/delay.h>
18#include <linux/types.h>
19#include <asm/pci.h>
20#include <linux/irq.h>
21#include <linux/interrupt.h> /* irqreturn_t */
22
23#include "pci-st40.h"
24
25/* This is in P2 of course */
26#define ST40PCI_BASE_ADDRESS (0xb0000000)
27#define ST40PCI_MEM_ADDRESS (ST40PCI_BASE_ADDRESS+0x0)
28#define ST40PCI_IO_ADDRESS (ST40PCI_BASE_ADDRESS+0x06000000)
29#define ST40PCI_REG_ADDRESS (ST40PCI_BASE_ADDRESS+0x07000000)
30
31#define ST40PCI_REG(x) (ST40PCI_REG_ADDRESS+(ST40PCI_##x))
32#define ST40PCI_REG_INDEXED(reg, index) \
33 (ST40PCI_REG(reg##0) + \
34 ((ST40PCI_REG(reg##1) - ST40PCI_REG(reg##0))*index))
35
36#define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg))
37#define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg))
38#define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg))
39#define ST40PCI_WRITE_INDEXED(reg, index, val) \
40 writel((val), ST40PCI_REG_INDEXED(reg, index));
41
42#define ST40PCI_READ(reg) readl(ST40PCI_REG(reg))
43#define ST40PCI_READ_SHORT(reg) readw(ST40PCI_REG(reg))
44#define ST40PCI_READ_BYTE(reg) readb(ST40PCI_REG(reg))
45
46#define ST40PCI_SERR_IRQ 64
47#define ST40PCI_ERR_IRQ 65
48
49
50/* Macros to extract PLL params */
51#define PLL_MDIV(reg) ( ((unsigned)reg) & 0xff )
52#define PLL_NDIV(reg) ( (((unsigned)reg)>>8) & 0xff )
53#define PLL_PDIV(reg) ( (((unsigned)reg)>>16) & 0x3 )
54#define PLL_SETUP(reg) ( (((unsigned)reg)>>19) & 0x1ff )
55
56/* Build up the appropriate settings */
57#define PLL_SET(mdiv,ndiv,pdiv,setup) \
58( ((mdiv)&0xff) | (((ndiv)&0xff)<<8) | (((pdiv)&3)<<16)| (((setup)&0x1ff)<<19))
59
60#define PLLPCICR (0xbb040000+0x10)
61
62#define PLLPCICR_POWERON (1<<28)
63#define PLLPCICR_OUT_EN (1<<29)
64#define PLLPCICR_LOCKSELECT (1<<30)
65#define PLLPCICR_LOCK (1<<31)
66
67
68#define PLL_25MHZ 0x793c8512
69#define PLL_33MHZ PLL_SET(18,88,3,295)
70
71static void pci_set_rbar_region(unsigned int region, unsigned long localAddr,
72 unsigned long pciOffset, unsigned long regionSize);
73
74/*
75 * The pcibios_map_platform_irq function is defined in the appropriate
76 * board specific code and referenced here
77 */
78extern int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin);
79
80static __init void SetPCIPLL(void)
81{
82 {
83 /* Lets play with the PLL values */
84 unsigned long pll1cr1;
85 unsigned long mdiv, ndiv, pdiv;
86 unsigned long muxcr;
87 unsigned int muxcr_ratios[4] = { 8, 16, 21, 1 };
88 unsigned int freq;
89
90#define CLKGENA 0xbb040000
91#define CLKGENA_PLL2_MUXCR CLKGENA + 0x48
92 pll1cr1 = ctrl_inl(PLLPCICR);
93 printk("PLL1CR1 %08lx\n", pll1cr1);
94 mdiv = PLL_MDIV(pll1cr1);
95 ndiv = PLL_NDIV(pll1cr1);
96 pdiv = PLL_PDIV(pll1cr1);
97 printk("mdiv %02lx ndiv %02lx pdiv %02lx\n", mdiv, ndiv, pdiv);
98 freq = ((2*27*ndiv)/mdiv) / (1 << pdiv);
99 printk("PLL freq %dMHz\n", freq);
100 muxcr = ctrl_inl(CLKGENA_PLL2_MUXCR);
101 printk("PCI freq %dMhz\n", freq / muxcr_ratios[muxcr & 3]);
102 }
103}
104
105
106struct pci_err {
107 unsigned mask;
108 const char *error_string;
109};
110
111static struct pci_err int_error[]={
112 { INT_MNLTDIM,"MNLTDIM: Master non-lock transfer"},
113 { INT_TTADI, "TTADI: Illegal byte enable in I/O transfer"},
114 { INT_TMTO, "TMTO: Target memory read/write timeout"},
115 { INT_MDEI, "MDEI: Master function disable error"},
116 { INT_APEDI, "APEDI: Address parity error"},
117 { INT_SDI, "SDI: SERR detected"},
118 { INT_DPEITW, "DPEITW: Data parity error target write"},
119 { INT_PEDITR, "PEDITR: PERR detected"},
120 { INT_TADIM, "TADIM: Target abort detected"},
121 { INT_MADIM, "MADIM: Master abort detected"},
122 { INT_MWPDI, "MWPDI: PERR from target at data write"},
123 { INT_MRDPEI, "MRDPEI: Master read data parity error"}
124};
125#define NUM_PCI_INT_ERRS (sizeof(int_error)/sizeof(struct pci_err))
126
127static struct pci_err aint_error[]={
128 { AINT_MBI, "MBI: Master broken"},
129 { AINT_TBTOI, "TBTOI: Target bus timeout"},
130 { AINT_MBTOI, "MBTOI: Master bus timeout"},
131 { AINT_TAI, "TAI: Target abort"},
132 { AINT_MAI, "MAI: Master abort"},
133 { AINT_RDPEI, "RDPEI: Read data parity"},
134 { AINT_WDPE, "WDPE: Write data parity"}
135};
136
137#define NUM_PCI_AINT_ERRS (sizeof(aint_error)/sizeof(struct pci_err))
138
139static void print_pci_errors(unsigned reg,struct pci_err *error,int num_errors)
140{
141 int i;
142
143 for(i=0;i<num_errors;i++) {
144 if(reg & error[i].mask) {
145 printk("%s\n",error[i].error_string);
146 }
147 }
148
149}
150
151
152static char * pci_commands[16]={
153 "Int Ack",
154 "Special Cycle",
155 "I/O Read",
156 "I/O Write",
157 "Reserved",
158 "Reserved",
159 "Memory Read",
160 "Memory Write",
161 "Reserved",
162 "Reserved",
163 "Configuration Read",
164 "Configuration Write",
165 "Memory Read Multiple",
166 "Dual Address Cycle",
167 "Memory Read Line",
168 "Memory Write-and-Invalidate"
169};
170
171static irqreturn_t st40_pci_irq(int irq, void *dev_instance, struct pt_regs *regs)
172{
173 unsigned pci_int, pci_air, pci_cir, pci_aint;
174 static int count=0;
175
176
177 pci_int = ST40PCI_READ(INT);pci_aint = ST40PCI_READ(AINT);
178 pci_cir = ST40PCI_READ(CIR);pci_air = ST40PCI_READ(AIR);
179
180 /* Reset state to stop multiple interrupts */
181 ST40PCI_WRITE(INT, ~0); ST40PCI_WRITE(AINT, ~0);
182
183
184 if(++count>1) return IRQ_HANDLED;
185
186 printk("** PCI ERROR **\n");
187
188 if(pci_int) {
189 printk("** INT register status\n");
190 print_pci_errors(pci_int,int_error,NUM_PCI_INT_ERRS);
191 }
192
193 if(pci_aint) {
194 printk("** AINT register status\n");
195 print_pci_errors(pci_aint,aint_error,NUM_PCI_AINT_ERRS);
196 }
197
198 printk("** Address and command info\n");
199
200 printk("** Command %s : Address 0x%x\n",
201 pci_commands[pci_cir&0xf],pci_air);
202
203 if(pci_cir&CIR_PIOTEM) {
204 printk("CIR_PIOTEM:PIO transfer error for master\n");
205 }
206 if(pci_cir&CIR_RWTET) {
207 printk("CIR_RWTET:Read/Write transfer error for target\n");
208 }
209
210 return IRQ_HANDLED;
211}
212
213
214/* Rounds a number UP to the nearest power of two. Used for
215 * sizing the PCI window.
216 */
217static u32 r2p2(u32 num)
218{
219 int i = 31;
220 u32 tmp = num;
221
222 if (num == 0)
223 return 0;
224
225 do {
226 if (tmp & (1 << 31))
227 break;
228 i--;
229 tmp <<= 1;
230 } while (i >= 0);
231
232 tmp = 1 << i;
233 /* If the original number isn't a power of 2, round it up */
234 if (tmp != num)
235 tmp <<= 1;
236
237 return tmp;
238}
239
240static void __init pci_fixup_ide_bases(struct pci_dev *d)
241{
242 int i;
243
244 /*
245 * PCI IDE controllers use non-standard I/O port decoding, respect it.
246 */
247 if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
248 return;
249 printk("PCI: IDE base address fixup for %s\n", pci_name(d));
250 for(i=0; i<4; i++) {
251 struct resource *r = &d->resource[i];
252 if ((r->start & ~0x80) == 0x374) {
253 r->start |= 2;
254 r->end = r->start;
255 }
256 }
257}
258DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
259
260int __init st40pci_init(unsigned memStart, unsigned memSize)
261{
262 u32 lsr0;
263
264 SetPCIPLL();
265
266 /* Initialises the ST40 pci subsystem, performing a reset, then programming
267 * up the address space decoders appropriately
268 */
269
270 /* Should reset core here as well methink */
271
272 ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_SOFT_RESET);
273
274 /* Loop while core resets */
275 while (ST40PCI_READ(CR) & CR_SOFT_RESET);
276
277 /* Switch off interrupts */
278 ST40PCI_WRITE(INTM, 0);
279 ST40PCI_WRITE(AINT, 0);
280
281 /* Now, lets reset all the cards on the bus with extreme prejudice */
282 ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_RSTCTL);
283 udelay(250);
284
285 /* Set bus active, take it out of reset */
286 ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_BMAM | CR_CFINT | CR_PFCS | CR_PFE);
287
288 /* The PCI spec says that no access must be made to the bus until 1 second
289 * after reset. This seem ludicrously long, but some delay is needed here
290 */
291 mdelay(1000);
292
293 /* Switch off interrupts */
294 ST40PCI_WRITE(INTM, 0);
295 ST40PCI_WRITE(AINT, 0);
296
297 /* Allow it to be a master */
298
299 ST40PCI_WRITE_SHORT(CSR_CMD,
300 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
301 PCI_COMMAND_IO);
302
303 /* Accesse to the 0xb0000000 -> 0xb6000000 area will go through to 0x10000000 -> 0x16000000
304 * on the PCI bus. This allows a nice 1-1 bus to phys mapping.
305 */
306
307
308 ST40PCI_WRITE(MBR, 0x10000000);
309 /* Always set the max size 128M (actually, it is only 96MB wide) */
310 ST40PCI_WRITE(MBMR, 0x07ff0000);
311
312 /* I/O addresses are mapped at 0xb6000000 -> 0xb7000000. These are changed to 0, to
313 * allow cards that have legacy io such as vga to function correctly. This gives a
314 * maximum of 64K of io/space as only the bottom 16 bits of the address are copied
315 * over to the bus when the transaction is made. 64K of io space is more than enough
316 */
317 ST40PCI_WRITE(IOBR, 0x0);
318 /* Set up the 64K window */
319 ST40PCI_WRITE(IOBMR, 0x0);
320
321 /* Now we set up the mbars so the PCI bus can see the local memory */
322 /* Expose a 256M window starting at PCI address 0... */
323 ST40PCI_WRITE(CSR_MBAR0, 0);
324 ST40PCI_WRITE(LSR0, 0x0fff0001);
325
326 /* ... and set up the initial incomming window to expose all of RAM */
327 pci_set_rbar_region(7, memStart, memStart, memSize);
328
329 /* Maximise timeout values */
330 ST40PCI_WRITE_BYTE(CSR_TRDY, 0xff);
331 ST40PCI_WRITE_BYTE(CSR_RETRY, 0xff);
332 ST40PCI_WRITE_BYTE(CSR_MIT, 0xff);
333
334 ST40PCI_WRITE_BYTE(PERF,PERF_MASTER_WRITE_POSTING);
335
336 return 1;
337}
338
339char * __init pcibios_setup(char *str)
340{
341 return str;
342}
343
344
345#define SET_CONFIG_BITS(bus,devfn,where)\
346 (((bus) << 16) | ((devfn) << 8) | ((where) & ~3) | (bus!=0))
347
348#define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where)
349
350
351static int CheckForMasterAbort(void)
352{
353 if (ST40PCI_READ(INT) & INT_MADIM) {
354 /* Should we clear config space version as well ??? */
355 ST40PCI_WRITE(INT, INT_MADIM);
356 ST40PCI_WRITE_SHORT(CSR_STATUS, 0);
357 return 1;
358 }
359
360 return 0;
361}
362
363/* Write to config register */
364static int st40pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val)
365{
366 ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
367 switch (size) {
368 case 1:
369 *val = (u8)ST40PCI_READ_BYTE(PDR + (where & 3));
370 break;
371 case 2:
372 *val = (u16)ST40PCI_READ_SHORT(PDR + (where & 2));
373 break;
374 case 4:
375 *val = ST40PCI_READ(PDR);
376 break;
377 }
378
379 if (CheckForMasterAbort()){
380 switch (size) {
381 case 1:
382 *val = (u8)0xff;
383 break;
384 case 2:
385 *val = (u16)0xffff;
386 break;
387 case 4:
388 *val = 0xffffffff;
389 break;
390 }
391 }
392
393 return PCIBIOS_SUCCESSFUL;
394}
395
396static int st40pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
397{
398 ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
399
400 switch (size) {
401 case 1:
402 ST40PCI_WRITE_BYTE(PDR + (where & 3), (u8)val);
403 break;
404 case 2:
405 ST40PCI_WRITE_SHORT(PDR + (where & 2), (u16)val);
406 break;
407 case 4:
408 ST40PCI_WRITE(PDR, val);
409 break;
410 }
411
412 CheckForMasterAbort();
413
414 return PCIBIOS_SUCCESSFUL;
415}
416
417struct pci_ops st40pci_config_ops = {
418 .read = st40pci_read,
419 .write = st40pci_write,
420};
421
422
423/* Everything hangs off this */
424static struct pci_bus *pci_root_bus;
425
426
427static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
428{
429 return PCI_SLOT(dev->devfn);
430}
431
432
433static int __init pcibios_init(void)
434{
435 extern unsigned long memory_start, memory_end;
436
437 printk(KERN_ALERT "pci-st40.c: pcibios_init\n");
438
439 if (sh_mv.mv_init_pci != NULL) {
440 sh_mv.mv_init_pci();
441 }
442
443 /* The pci subsytem needs to know where memory is and how much
444 * of it there is. I've simply made these globals. A better mechanism
445 * is probably needed.
446 */
447 st40pci_init(PHYSADDR(memory_start),
448 PHYSADDR(memory_end) - PHYSADDR(memory_start));
449
450 if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq,
451 SA_INTERRUPT, "st40pci", NULL)) {
452 printk(KERN_ERR "st40pci: Cannot hook interrupt\n");
453 return -EIO;
454 }
455
456 /* Enable the PCI interrupts on the device */
457 ST40PCI_WRITE(INTM, ~0);
458 ST40PCI_WRITE(AINT, ~0);
459
460 /* Map the io address apprioately */
461#ifdef CONFIG_HD64465
462 hd64465_port_map(PCIBIOS_MIN_IO, (64 * 1024) - PCIBIOS_MIN_IO + 1,
463 ST40_IO_ADDR + PCIBIOS_MIN_IO, 0);
464#endif
465
466 /* ok, do the scan man */
467 pci_root_bus = pci_scan_bus(0, &st40pci_config_ops, NULL);
468 pci_assign_unassigned_resources();
469 pci_fixup_irqs(no_swizzle, pcibios_map_platform_irq);
470
471 return 0;
472}
473
474subsys_initcall(pcibios_init);
475
476void __init pcibios_fixup_bus(struct pci_bus *bus)
477{
478}
479
480/*
481 * Publish a region of local address space over the PCI bus
482 * to other devices.
483 */
484static void pci_set_rbar_region(unsigned int region, unsigned long localAddr,
485 unsigned long pciOffset, unsigned long regionSize)
486{
487 unsigned long mask;
488
489 if (region > 7)
490 return;
491
492 if (regionSize > (512 * 1024 * 1024))
493 return;
494
495 mask = r2p2(regionSize) - 0x10000;
496
497 /* Diable the region (in case currently in use, should never happen) */
498 ST40PCI_WRITE_INDEXED(RSR, region, 0);
499
500 /* Start of local address space to publish */
501 ST40PCI_WRITE_INDEXED(RLAR, region, PHYSADDR(localAddr) );
502
503 /* Start of region in PCI address space as an offset from MBAR0 */
504 ST40PCI_WRITE_INDEXED(RBAR, region, pciOffset);
505
506 /* Size of region */
507 ST40PCI_WRITE_INDEXED(RSR, region, mask | 1);
508}
509