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