ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / arm / common / plx90x0.c
1 /* 
2  * Driver for PLX Technology PCI9000-series host bridge.
3  *
4  * Copyright (C) 1997, 1998, 1999, 2000 FutureTV Labs Ltd
5  */
6
7 /*
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version
11  * 2 of the License, or (at your option) any later version.
12  */
13
14 #include <linux/kernel.h>
15 #include <linux/pci.h>
16 #include <linux/init.h>
17
18 #include <asm/hardware.h>
19 #include <asm/io.h>
20 #include <asm/ptrace.h>
21 #include <asm/irq.h>
22 #include <asm/mach/pci.h>
23
24 /*
25  * Since the following functions are all very similar, the common parts
26  * are pulled out into these macros.
27  */
28
29 #define PLX_CLEAR_CONFIG                                                \
30         __raw_writel(0, PLX_BASE + 0xac);                               \
31         local_irq_restore(flags); }
32
33 #define PLX_SET_CONFIG                                                  \
34         { unsigned long flags;                                          \
35         local_irq_save(flags);                                          \
36         __raw_writel((1<<31 | (bus->number << 16)                       \
37                 | (devfn << 8) | (where & ~3)                           \
38                 | ((bus->number == 0)?0:1)), PLX_BASE + 0xac);          \
39
40 #define PLX_CONFIG_WRITE(size)                                          \
41         PLX_SET_CONFIG                                                  \
42         __raw_write##size(value, PCIO_BASE + (where & 3));              \
43         if (__raw_readw(PLX_BASE + 0x6) & 0x2000)                       \
44                 __raw_writew(0x2000, PLX_BASE + 0x6);                   \
45         PLX_CLEAR_CONFIG                                                \
46         return PCIBIOS_SUCCESSFUL;
47
48 #define PLX_CONFIG_READ(size)                                           \
49         PLX_SET_CONFIG                                                  \
50         *value = __raw_read##size(PCIO_BASE + (where & 3));             \
51         if (__raw_readw(PLX_BASE + 0x6) & 0x2000) {                     \
52                 __raw_writew(0x2000, PLX_BASE + 0x6);                   \
53                 *value = 0xffffffffUL;                                  \
54         }                                                               \
55         PLX_CLEAR_CONFIG                                                \
56         return PCIBIOS_SUCCESSFUL;
57
58 /* Configuration space access routines */
59
60 static int 
61 plx90x0_read_config (struct pci_bus *bus, unsigned int devfn, int where,
62                      int where, int size, u32 *value)
63 {
64         switch (size) {
65         case 1:
66                 PLX_CONFIG_READ(b)
67                 break;
68         case 2:
69                 PLX_CONFIG_READ(w)
70                 break;
71         case 4:
72                 PLX_CONFIG_READ(l)
73                 break;
74         }
75         return PCIBIOS_SUCCESSFUL;
76 }
77
78 static int 
79 plx90x0_write_config (struct pci_bus *bus, unsigned int devfn, int where,
80                       int where, int size, u32 value)
81 {
82         switch (size) {
83         case 1:
84                 PLX_CONFIG_WRITE(b)
85                 break;
86         case 2:
87                 PLX_CONFIG_WRITE(w)
88                 break;
89         case 4:
90                 PLX_CONFIG_WRITE(l)
91                 break;
92         }
93         return PCIBIOS_SUCCESSFUL;
94 }
95
96 static struct pci_ops plx90x0_ops = 
97 {
98         .read   = plx90x0_read_config,
99         .write  = plx90x0_write_config,
100 };
101
102 static void 
103 plx_syserr_handler(int irq, void *handle, struct pt_regs *regs)
104 {
105         printk("PLX90x0: machine check %04x (pc=%08lx)\n", 
106                readw(PLX_BASE + 6), regs->ARM_pc);
107         __raw_writew(0xf000, PLX_BASE + 6);
108 }
109
110 /*
111  * Initialise the PCI system.
112  */
113
114 void __init
115 plx90x0_init(struct arm_sysdata *sysdata)
116 {
117         static const unsigned long int base = PLX_BASE;
118         char *what;
119         unsigned long bar = (unsigned long)virt_to_bus((void *)PAGE_OFFSET);
120
121         /* Have a sniff around and see which PLX device is present. */
122         unsigned long id = __raw_readl(base + 0xf0);
123         
124 #if 0
125         /* This check was a good idea, but can fail.  The PLX9060 puts no
126            default value in these registers unless NB# is asserted (which it
127            isn't on these cards).  */
128         if ((id & 0xffff) != PCI_VENDOR_ID_PLX)
129                 return;         /* Nothing found */
130 #endif
131
132         /* Found one - now work out what it is. */
133         switch (id >> 16) {
134         case 0:         /* PCI_DEVICE_ID_PLX_9060 */
135                 what = "PCI9060";
136                 break;
137         case PCI_DEVICE_ID_PLX_9060ES:
138                 what = "PCI9060ES";
139                 break;
140         case PCI_DEVICE_ID_PLX_9060SD:
141                 what = "PCI9060SD";             /* uhuhh.. */
142                 break;
143         case PCI_DEVICE_ID_PLX_9080:
144                 what = "PCI9080";
145                 break;
146         default:
147                 printk("PCI: Unknown PLX device %04lx found -- ignored.\n",
148                        id >> 16);
149                 return;
150         }
151         
152         printk("PCI: PLX Technology %s host bridge found.\n", what);
153         
154         /* Now set it up for both master and slave accesses. */
155         __raw_writel(0xffff0147,        base + 0x4);
156         __raw_writeb(32,                base + 0xd);
157         __raw_writel(0x8 | bar,         base + 0x18);
158         __raw_writel(0xf8000008,        base + 0x80);
159         __raw_writel(0x40000001,        base + 0x84);
160         __raw_writel(0,                 base + 0x88);
161         __raw_writel(0,                 base + 0x8c);
162         __raw_writel(0x11,              base + 0x94);
163         __raw_writel(0xC3 + (4 << 28)
164                 + (8 << 11) + (1 << 10)
165                      + (1 << 24),       base + 0x98);
166         __raw_writel(0xC0000000,        base + 0x9c);
167         __raw_writel(PLX_MEM_START,     base + 0xa0);
168         __raw_writel(PLX_IO_START,      base + 0xa4);
169         __raw_writel(0x3,               base + 0xa8);
170         __raw_writel(0,                 base + 0xac);
171         __raw_writel(0x10001,           base + 0xe8);
172         __raw_writel(0x8000767e,        base + 0xec);
173         
174         request_irq(IRQ_SYSERR, plx_syserr_handler, 0, 
175                     "system error", NULL);
176
177         pci_scan_bus(0, &plx90x0_ops, sysdata);
178 }