Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / arch / mips / pmc-sierra / yosemite / ht.c
1 /*
2  * Copyright 2003 PMC-Sierra
3  * Author: Manish Lachwani (lachwani@pmc-sierra.com)
4  *
5  *  This program is free software; you can redistribute  it and/or modify it
6  *  under  the terms of  the GNU General  Public License as published by the
7  *  Free Software Foundation;  either version 2 of the  License, or (at your
8  *  option) any later version.
9  *
10  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
11  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
12  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
13  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
14  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
15  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
16  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
17  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
18  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
19  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20  *
21  *  You should have received a copy of the  GNU General Public License along
22  *  with this program; if not, write  to the Free Software Foundation, Inc.,
23  *  675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 #include <linux/config.h>
27 #include <linux/types.h>
28 #include <linux/pci.h>
29 #include <linux/kernel.h>
30 #include <linux/slab.h>
31 #include <asm/pci.h>
32 #include <asm/io.h>
33
34 #include <linux/init.h>
35 #include <asm/titan_dep.h>
36
37 #ifdef CONFIG_HYPERTRANSPORT
38
39
40 /*
41  * This function check if the Hypertransport Link Initialization completed. If
42  * it did, then proceed further with scanning bus #2
43  */
44 static __inline__ int check_titan_htlink(void)
45 {
46         u32 val;
47
48         val = *(volatile uint32_t *)(RM9000x2_HTLINK_REG);
49         if (val & 0x00000020)
50                 /* HT Link Initialization completed */
51                 return 1;
52         else
53                 return 0;
54 }
55
56 static int titan_ht_config_read_dword(struct pci_dev *device,
57                                              int offset, u32* val)
58 {
59         int dev, bus, func;
60         uint32_t address_reg, data_reg;
61         uint32_t address;
62
63         bus = device->bus->number;
64         dev = PCI_SLOT(device->devfn);
65         func = PCI_FUNC(device->devfn);
66
67         /* XXX Need to change the Bus # */
68         if (bus > 2)
69                 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
70                                                         0x80000000 | 0x1;
71         else
72                 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
73
74         address_reg = RM9000x2_OCD_HTCFGA;
75         data_reg =  RM9000x2_OCD_HTCFGD;
76
77         RM9K_WRITE(address_reg, address);
78         RM9K_READ(data_reg, val);
79
80         return PCIBIOS_SUCCESSFUL;
81 }
82
83
84 static int titan_ht_config_read_word(struct pci_dev *device,
85                                              int offset, u16* val)
86 {
87         int dev, bus, func;
88         uint32_t address_reg, data_reg;
89         uint32_t address;
90
91         bus = device->bus->number;
92         dev = PCI_SLOT(device->devfn);
93         func = PCI_FUNC(device->devfn);
94
95         /* XXX Need to change the Bus # */
96         if (bus > 2)
97                 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
98                                                 0x80000000 | 0x1;
99         else
100                 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
101
102         address_reg = RM9000x2_OCD_HTCFGA;
103         data_reg =  RM9000x2_OCD_HTCFGD;
104
105         if ((offset & 0x3) == 0)
106                 offset = 0x2;
107         else
108                 offset = 0x0;
109
110         RM9K_WRITE(address_reg, address);
111         RM9K_READ_16(data_reg + offset, val);
112
113         return PCIBIOS_SUCCESSFUL;
114 }
115
116
117 u32 longswap(unsigned long l)
118 {
119         unsigned char b1,b2,b3,b4;
120
121         b1 = l&255;
122         b2 = (l>>8)&255;
123         b3 = (l>>16)&255;
124         b4 = (l>>24)&255;
125
126         return ((b1<<24) + (b2<<16) + (b3<<8) + b4);
127 }
128
129
130 static int titan_ht_config_read_byte(struct pci_dev *device,
131                                              int offset, u8* val)
132 {
133         int dev, bus, func;
134         uint32_t address_reg, data_reg;
135         uint32_t address;
136         int offset1;
137
138         bus = device->bus->number;
139         dev = PCI_SLOT(device->devfn);
140         func = PCI_FUNC(device->devfn);
141
142         /* XXX Need to change the Bus # */
143         if (bus > 2)
144                 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
145                                                         0x80000000 | 0x1;
146         else
147                 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
148
149         address_reg = RM9000x2_OCD_HTCFGA;
150         data_reg =  RM9000x2_OCD_HTCFGD;
151
152         RM9K_WRITE(address_reg, address);
153
154         if ((offset & 0x3) == 0) {
155                 offset1 = 0x3;
156         }
157         if ((offset & 0x3) == 1) {
158                 offset1 = 0x2;
159         }
160         if ((offset & 0x3) == 2) {
161                 offset1 = 0x1;
162         }
163         if ((offset & 0x3) == 3) {
164                 offset1 = 0x0;
165         }
166         RM9K_READ_8(data_reg + offset1, val);
167
168         return PCIBIOS_SUCCESSFUL;
169 }
170
171
172 static int titan_ht_config_write_dword(struct pci_dev *device,
173                                              int offset, u8 val)
174 {
175         int dev, bus, func;
176         uint32_t address_reg, data_reg;
177         uint32_t address;
178
179         bus = device->bus->number;
180         dev = PCI_SLOT(device->devfn);
181         func = PCI_FUNC(device->devfn);
182
183         /* XXX Need to change the Bus # */
184         if (bus > 2)
185                 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
186                                                         0x80000000 | 0x1;
187         else
188               address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
189
190         address_reg = RM9000x2_OCD_HTCFGA;
191         data_reg =  RM9000x2_OCD_HTCFGD;
192
193         RM9K_WRITE(address_reg, address);
194         RM9K_WRITE(data_reg, val);
195
196         return PCIBIOS_SUCCESSFUL;
197 }
198
199 static int titan_ht_config_write_word(struct pci_dev *device,
200                                              int offset, u8 val)
201 {
202         int dev, bus, func;
203         uint32_t address_reg, data_reg;
204         uint32_t address;
205
206         bus = device->bus->number;
207         dev = PCI_SLOT(device->devfn);
208         func = PCI_FUNC(device->devfn);
209
210         /* XXX Need to change the Bus # */
211         if (bus > 2)
212                 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
213                                 0x80000000 | 0x1;
214         else
215                 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
216
217         address_reg = RM9000x2_OCD_HTCFGA;
218         data_reg =  RM9000x2_OCD_HTCFGD;
219
220         if ((offset & 0x3) == 0)
221                 offset = 0x2;
222         else
223                 offset = 0x0;
224
225         RM9K_WRITE(address_reg, address);
226         RM9K_WRITE_16(data_reg + offset, val);
227
228         return PCIBIOS_SUCCESSFUL;
229 }
230
231 static int titan_ht_config_write_byte(struct pci_dev *device,
232                                              int offset, u8 val)
233 {
234         int dev, bus, func;
235         uint32_t address_reg, data_reg;
236         uint32_t address;
237         int offset1;
238
239         bus = device->bus->number;
240         dev = PCI_SLOT(device->devfn);
241         func = PCI_FUNC(device->devfn);
242
243         /* XXX Need to change the Bus # */
244         if (bus > 2)
245                 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
246                                 0x80000000 | 0x1;
247         else
248                 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
249
250         address_reg = RM9000x2_OCD_HTCFGA;
251         data_reg =  RM9000x2_OCD_HTCFGD;
252
253         RM9K_WRITE(address_reg, address);
254
255         if ((offset & 0x3) == 0) {
256              offset1 = 0x3;
257         }
258         if ((offset & 0x3) == 1) {
259              offset1 = 0x2;
260         }
261         if ((offset & 0x3) == 2) {
262              offset1 = 0x1;
263         }
264         if ((offset & 0x3) == 3) {
265             offset1 = 0x0;
266         }
267
268         RM9K_WRITE_8(data_reg + offset1, val);
269         return PCIBIOS_SUCCESSFUL;
270 }
271
272
273 static void titan_pcibios_set_master(struct pci_dev *dev)
274 {
275         u16 cmd;
276         int bus = dev->bus->number;
277
278         if (check_titan_htlink())
279             titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
280
281         cmd |= PCI_COMMAND_MASTER;
282
283         if (check_titan_htlink())
284             titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
285 }
286
287
288 int pcibios_enable_resources(struct pci_dev *dev)
289 {
290         u16 cmd, old_cmd;
291         u8 tmp1;
292         int idx;
293         struct resource *r;
294         int bus = dev->bus->number;
295
296         if (check_titan_htlink())
297             titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
298
299         old_cmd = cmd;
300         for (idx = 0; idx < 6; idx++) {
301                 r = &dev->resource[idx];
302                 if (!r->start && r->end) {
303                         printk(KERN_ERR
304                                "PCI: Device %s not available because of "
305                                "resource collisions\n", pci_name(dev));
306                         return -EINVAL;
307                 }
308                 if (r->flags & IORESOURCE_IO)
309                         cmd |= PCI_COMMAND_IO;
310                 if (r->flags & IORESOURCE_MEM)
311                         cmd |= PCI_COMMAND_MEMORY;
312         }
313         if (cmd != old_cmd) {
314                 if (check_titan_htlink())
315                    titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
316         }
317
318         if (check_titan_htlink())
319                 titan_ht_config_read_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1);
320
321         if (tmp1 != 8) {
322                 printk(KERN_WARNING "PCI setting cache line size to 8 from "
323                        "%d\n", tmp1);
324         }
325
326         if (check_titan_htlink())
327                 titan_ht_config_write_byte(dev, PCI_CACHE_LINE_SIZE, 8);
328
329         if (check_titan_htlink())
330                 titan_ht_config_read_byte(dev, PCI_LATENCY_TIMER, &tmp1);
331
332         if (tmp1 < 32 || tmp1 == 0xff) {
333                 printk(KERN_WARNING "PCI setting latency timer to 32 from %d\n",
334                        tmp1);
335         }
336
337         if (check_titan_htlink())
338                 titan_ht_config_write_byte(dev, PCI_LATENCY_TIMER, 32);
339
340         return 0;
341 }
342
343
344 int pcibios_enable_device(struct pci_dev *dev, int mask)
345 {
346         return pcibios_enable_resources(dev);
347 }
348
349
350
351 void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
352                              struct resource *res, int resource)
353 {
354         u32 new, check;
355         int reg;
356
357         return;
358
359         new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
360         if (resource < 6) {
361                 reg = PCI_BASE_ADDRESS_0 + 4 * resource;
362         } else if (resource == PCI_ROM_RESOURCE) {
363                 res->flags |= IORESOURCE_ROM_ENABLE;
364                 reg = dev->rom_base_reg;
365         } else {
366                 /*
367                  * Somebody might have asked allocation of a non-standard
368                  * resource
369                  */
370                 return;
371         }
372
373         pci_write_config_dword(dev, reg, new);
374         pci_read_config_dword(dev, reg, &check);
375         if ((new ^ check) &
376             ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
377              PCI_BASE_ADDRESS_MEM_MASK)) {
378                 printk(KERN_ERR "PCI: Error while updating region "
379                        "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
380                        new, check);
381         }
382 }
383
384
385 void pcibios_align_resource(void *data, struct resource *res,
386                             unsigned long size, unsigned long align)
387 {
388         struct pci_dev *dev = data;
389
390         if (res->flags & IORESOURCE_IO) {
391                 unsigned long start = res->start;
392
393                 /* We need to avoid collisions with `mirrored' VGA ports
394                    and other strange ISA hardware, so we always want the
395                    addresses kilobyte aligned.  */
396                 if (size > 0x100) {
397                         printk(KERN_ERR "PCI: I/O Region %s/%d too large"
398                                " (%ld bytes)\n", pci_name(dev),
399                                 dev->resource - res, size);
400                 }
401
402                 start = (start + 1024 - 1) & ~(1024 - 1);
403                 res->start = start;
404         }
405 }
406
407 struct pci_ops titan_pci_ops = {
408         titan_ht_config_read_byte,
409         titan_ht_config_read_word,
410         titan_ht_config_read_dword,
411         titan_ht_config_write_byte,
412         titan_ht_config_write_word,
413         titan_ht_config_write_dword
414 };
415
416 void __init pcibios_fixup_bus(struct pci_bus *c)
417 {
418         titan_ht_pcibios_fixup_bus(c);
419 }
420
421 void __init pcibios_init(void)
422 {
423
424         /* Reset PCI I/O and PCI MEM values */
425         /* XXX Need to add the proper values here */
426         ioport_resource.start = 0xe0000000;
427         ioport_resource.end   = 0xe0000000 + 0x20000000 - 1;
428         iomem_resource.start  = 0xc0000000;
429         iomem_resource.end    = 0xc0000000 + 0x20000000 - 1;
430
431         /* XXX Need to add bus values */
432         pci_scan_bus(2, &titan_pci_ops, NULL);
433         pci_scan_bus(3, &titan_pci_ops, NULL);
434 }
435
436 /*
437  * for parsing "pci=" kernel boot arguments.
438  */
439 char *pcibios_setup(char *str)
440 {
441         printk(KERN_INFO "rr: pcibios_setup\n");
442         /* Nothing to do for now.  */
443
444         return str;
445 }
446
447 unsigned __init int pcibios_assign_all_busses(void)
448 {
449         /* We want to use the PCI bus detection done by PMON */
450         return 0;
451 }
452
453 #endif /* CONFIG_HYPERTRANSPORT */