• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/src/linux/linux-2.6/arch/mips/pmc-sierra/yosemite/
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/types.h>
27#include <linux/pci.h>
28#include <linux/kernel.h>
29#include <linux/slab.h>
30#include <asm/pci.h>
31#include <asm/io.h>
32
33#include <linux/init.h>
34#include <asm/titan_dep.h>
35
36#ifdef CONFIG_HYPERTRANSPORT
37
38
39/*
40 * This function check if the Hypertransport Link Initialization completed. If
41 * it did, then proceed further with scanning bus #2
42 */
43static __inline__ int check_titan_htlink(void)
44{
45        u32 val;
46
47        val = *(volatile uint32_t *)(RM9000x2_HTLINK_REG);
48        if (val & 0x00000020)
49                /* HT Link Initialization completed */
50                return 1;
51        else
52                return 0;
53}
54
55static int titan_ht_config_read_dword(struct pci_dev *device,
56                                             int offset, u32* val)
57{
58        int dev, bus, func;
59        uint32_t address_reg, data_reg;
60        uint32_t address;
61
62        bus = device->bus->number;
63        dev = PCI_SLOT(device->devfn);
64        func = PCI_FUNC(device->devfn);
65
66        if (bus > 2)
67                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
68                                                        0x80000000 | 0x1;
69        else
70                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
71
72        address_reg = RM9000x2_OCD_HTCFGA;
73        data_reg =  RM9000x2_OCD_HTCFGD;
74
75        RM9K_WRITE(address_reg, address);
76        RM9K_READ(data_reg, val);
77
78        return PCIBIOS_SUCCESSFUL;
79}
80
81
82static int titan_ht_config_read_word(struct pci_dev *device,
83                                             int offset, u16* val)
84{
85        int dev, bus, func;
86        uint32_t address_reg, data_reg;
87        uint32_t address;
88
89        bus = device->bus->number;
90        dev = PCI_SLOT(device->devfn);
91        func = PCI_FUNC(device->devfn);
92
93        if (bus > 2)
94                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
95                                                0x80000000 | 0x1;
96        else
97                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
98
99        address_reg = RM9000x2_OCD_HTCFGA;
100        data_reg =  RM9000x2_OCD_HTCFGD;
101
102        if ((offset & 0x3) == 0)
103                offset = 0x2;
104        else
105                offset = 0x0;
106
107        RM9K_WRITE(address_reg, address);
108        RM9K_READ_16(data_reg + offset, val);
109
110        return PCIBIOS_SUCCESSFUL;
111}
112
113
114u32 longswap(unsigned long l)
115{
116        unsigned char b1,b2,b3,b4;
117
118        b1 = l&255;
119        b2 = (l>>8)&255;
120        b3 = (l>>16)&255;
121        b4 = (l>>24)&255;
122
123        return ((b1<<24) + (b2<<16) + (b3<<8) + b4);
124}
125
126
127static int titan_ht_config_read_byte(struct pci_dev *device,
128                                             int offset, u8* val)
129{
130        int dev, bus, func;
131        uint32_t address_reg, data_reg;
132        uint32_t address;
133        int offset1;
134
135        bus = device->bus->number;
136        dev = PCI_SLOT(device->devfn);
137        func = PCI_FUNC(device->devfn);
138
139        if (bus > 2)
140                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
141                                                        0x80000000 | 0x1;
142        else
143                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
144
145        address_reg = RM9000x2_OCD_HTCFGA;
146        data_reg =  RM9000x2_OCD_HTCFGD;
147
148        RM9K_WRITE(address_reg, address);
149
150        if ((offset & 0x3) == 0) {
151                offset1 = 0x3;
152        }
153        if ((offset & 0x3) == 1) {
154                offset1 = 0x2;
155        }
156        if ((offset & 0x3) == 2) {
157                offset1 = 0x1;
158        }
159        if ((offset & 0x3) == 3) {
160                offset1 = 0x0;
161        }
162        RM9K_READ_8(data_reg + offset1, val);
163
164        return PCIBIOS_SUCCESSFUL;
165}
166
167
168static int titan_ht_config_write_dword(struct pci_dev *device,
169                                             int offset, u8 val)
170{
171        int dev, bus, func;
172        uint32_t address_reg, data_reg;
173        uint32_t address;
174
175        bus = device->bus->number;
176        dev = PCI_SLOT(device->devfn);
177        func = PCI_FUNC(device->devfn);
178
179        if (bus > 2)
180                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
181                                                        0x80000000 | 0x1;
182        else
183              address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
184
185        address_reg = RM9000x2_OCD_HTCFGA;
186        data_reg =  RM9000x2_OCD_HTCFGD;
187
188        RM9K_WRITE(address_reg, address);
189        RM9K_WRITE(data_reg, val);
190
191        return PCIBIOS_SUCCESSFUL;
192}
193
194static int titan_ht_config_write_word(struct pci_dev *device,
195                                             int offset, u8 val)
196{
197        int dev, bus, func;
198        uint32_t address_reg, data_reg;
199        uint32_t address;
200
201        bus = device->bus->number;
202        dev = PCI_SLOT(device->devfn);
203        func = PCI_FUNC(device->devfn);
204
205        if (bus > 2)
206                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
207                                0x80000000 | 0x1;
208        else
209                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
210
211        address_reg = RM9000x2_OCD_HTCFGA;
212        data_reg =  RM9000x2_OCD_HTCFGD;
213
214        if ((offset & 0x3) == 0)
215                offset = 0x2;
216        else
217                offset = 0x0;
218
219        RM9K_WRITE(address_reg, address);
220        RM9K_WRITE_16(data_reg + offset, val);
221
222        return PCIBIOS_SUCCESSFUL;
223}
224
225static int titan_ht_config_write_byte(struct pci_dev *device,
226                                             int offset, u8 val)
227{
228        int dev, bus, func;
229        uint32_t address_reg, data_reg;
230        uint32_t address;
231        int offset1;
232
233        bus = device->bus->number;
234        dev = PCI_SLOT(device->devfn);
235        func = PCI_FUNC(device->devfn);
236
237        if (bus > 2)
238                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
239                                0x80000000 | 0x1;
240        else
241                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
242
243        address_reg = RM9000x2_OCD_HTCFGA;
244        data_reg =  RM9000x2_OCD_HTCFGD;
245
246        RM9K_WRITE(address_reg, address);
247
248        if ((offset & 0x3) == 0) {
249             offset1 = 0x3;
250        }
251        if ((offset & 0x3) == 1) {
252             offset1 = 0x2;
253        }
254        if ((offset & 0x3) == 2) {
255             offset1 = 0x1;
256        }
257        if ((offset & 0x3) == 3) {
258            offset1 = 0x0;
259        }
260
261        RM9K_WRITE_8(data_reg + offset1, val);
262        return PCIBIOS_SUCCESSFUL;
263}
264
265
266static void titan_pcibios_set_master(struct pci_dev *dev)
267{
268        u16 cmd;
269        int bus = dev->bus->number;
270
271	if (check_titan_htlink())
272            titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
273
274	cmd |= PCI_COMMAND_MASTER;
275
276	if (check_titan_htlink())
277            titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
278}
279
280
281int pcibios_enable_resources(struct pci_dev *dev)
282{
283        u16 cmd, old_cmd;
284        u8 tmp1;
285        int idx;
286        struct resource *r;
287        int bus = dev->bus->number;
288
289	if (check_titan_htlink())
290            titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
291
292	old_cmd = cmd;
293        for (idx = 0; idx < 6; idx++) {
294                r = &dev->resource[idx];
295                if (!r->start && r->end) {
296                        printk(KERN_ERR
297                               "PCI: Device %s not available because of "
298                               "resource collisions\n", pci_name(dev));
299                        return -EINVAL;
300                }
301                if (r->flags & IORESOURCE_IO)
302                        cmd |= PCI_COMMAND_IO;
303                if (r->flags & IORESOURCE_MEM)
304                        cmd |= PCI_COMMAND_MEMORY;
305        }
306        if (cmd != old_cmd) {
307		if (check_titan_htlink())
308                   titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
309	}
310
311	if (check_titan_htlink())
312		titan_ht_config_read_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1);
313
314	if (tmp1 != 8) {
315                printk(KERN_WARNING "PCI setting cache line size to 8 from "
316                       "%d\n", tmp1);
317	}
318
319	if (check_titan_htlink())
320		titan_ht_config_write_byte(dev, PCI_CACHE_LINE_SIZE, 8);
321
322	if (check_titan_htlink())
323		titan_ht_config_read_byte(dev, PCI_LATENCY_TIMER, &tmp1);
324
325	if (tmp1 < 32 || tmp1 == 0xff) {
326                printk(KERN_WARNING "PCI setting latency timer to 32 from %d\n",
327                       tmp1);
328	}
329
330	if (check_titan_htlink())
331		titan_ht_config_write_byte(dev, PCI_LATENCY_TIMER, 32);
332
333	return 0;
334}
335
336
337int pcibios_enable_device(struct pci_dev *dev, int mask)
338{
339        return pcibios_enable_resources(dev);
340}
341
342
343
344void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
345                             struct resource *res, int resource)
346{
347        u32 new, check;
348        int reg;
349
350        return;
351
352        new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
353        if (resource < 6) {
354                reg = PCI_BASE_ADDRESS_0 + 4 * resource;
355        } else if (resource == PCI_ROM_RESOURCE) {
356		res->flags |= IORESOURCE_ROM_ENABLE;
357                reg = dev->rom_base_reg;
358        } else {
359                /*
360                 * Somebody might have asked allocation of a non-standard
361                 * resource
362                 */
363                return;
364        }
365
366        pci_write_config_dword(dev, reg, new);
367        pci_read_config_dword(dev, reg, &check);
368        if ((new ^ check) &
369            ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
370             PCI_BASE_ADDRESS_MEM_MASK)) {
371                printk(KERN_ERR "PCI: Error while updating region "
372                       "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
373                       new, check);
374        }
375}
376
377
378void pcibios_align_resource(void *data, struct resource *res,
379                            resource_size_t size, resource_size_t align)
380{
381        struct pci_dev *dev = data;
382
383        if (res->flags & IORESOURCE_IO) {
384                resource_size_t start = res->start;
385
386                /* We need to avoid collisions with `mirrored' VGA ports
387                   and other strange ISA hardware, so we always want the
388                   addresses kilobyte aligned.  */
389                if (size > 0x100) {
390                        printk(KERN_ERR "PCI: I/O Region %s/%d too large"
391                               " (%ld bytes)\n", pci_name(dev),
392                                dev->resource - res, size);
393                }
394
395                start = (start + 1024 - 1) & ~(1024 - 1);
396                res->start = start;
397        }
398}
399
400struct pci_ops titan_pci_ops = {
401        titan_ht_config_read_byte,
402        titan_ht_config_read_word,
403        titan_ht_config_read_dword,
404        titan_ht_config_write_byte,
405        titan_ht_config_write_word,
406        titan_ht_config_write_dword
407};
408
409void __init pcibios_fixup_bus(struct pci_bus *c)
410{
411        titan_ht_pcibios_fixup_bus(c);
412}
413
414void __init pcibios_init(void)
415{
416
417        /* Reset PCI I/O and PCI MEM values */
418        ioport_resource.start = 0xe0000000;
419        ioport_resource.end   = 0xe0000000 + 0x20000000 - 1;
420        iomem_resource.start  = 0xc0000000;
421        iomem_resource.end    = 0xc0000000 + 0x20000000 - 1;
422
423        pci_scan_bus(2, &titan_pci_ops, NULL);
424        pci_scan_bus(3, &titan_pci_ops, NULL);
425}
426
427/*
428 * for parsing "pci=" kernel boot arguments.
429 */
430char *pcibios_setup(char *str)
431{
432        printk(KERN_INFO "rr: pcibios_setup\n");
433        /* Nothing to do for now.  */
434
435        return str;
436}
437
438unsigned __init int pcibios_assign_all_busses(void)
439{
440        /* We want to use the PCI bus detection done by PMON */
441        return 0;
442}
443
444#endif /* CONFIG_HYPERTRANSPORT */
445