OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [mips/] [pmc-sierra/] [yosemite/] [ht.c] - Blame information for rev 3

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.