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/] [powerpc/] [sysdev/] [indirect_pci.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * Support for indirect PCI bridges.
3
 *
4
 * Copyright (C) 1998 Gabriel Paubert.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version
9
 * 2 of the License, or (at your option) any later version.
10
 */
11
 
12
#include <linux/kernel.h>
13
#include <linux/pci.h>
14
#include <linux/delay.h>
15
#include <linux/string.h>
16
#include <linux/init.h>
17
 
18
#include <asm/io.h>
19
#include <asm/prom.h>
20
#include <asm/pci-bridge.h>
21
#include <asm/machdep.h>
22
 
23
static int
24
indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
25
                     int len, u32 *val)
26
{
27
        struct pci_controller *hose = bus->sysdata;
28
        volatile void __iomem *cfg_data;
29
        u8 cfg_type = 0;
30
        u32 bus_no, reg;
31
 
32
        if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK) {
33
                if (bus->number != hose->first_busno)
34
                        return PCIBIOS_DEVICE_NOT_FOUND;
35
                if (devfn != 0)
36
                        return PCIBIOS_DEVICE_NOT_FOUND;
37
        }
38
 
39
        if (ppc_md.pci_exclude_device)
40
                if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
41
                        return PCIBIOS_DEVICE_NOT_FOUND;
42
 
43
        if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE)
44
                if (bus->number != hose->first_busno)
45
                        cfg_type = 1;
46
 
47
        bus_no = (bus->number == hose->first_busno) ?
48
                        hose->self_busno : bus->number;
49
 
50
        if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG)
51
                reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
52
        else
53
                reg = offset & 0xfc;
54
 
55
        if (hose->indirect_type & PPC_INDIRECT_TYPE_BIG_ENDIAN)
56
                out_be32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
57
                         (devfn << 8) | reg | cfg_type));
58
        else
59
                out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
60
                         (devfn << 8) | reg | cfg_type));
61
 
62
        /*
63
         * Note: the caller has already checked that offset is
64
         * suitably aligned and that len is 1, 2 or 4.
65
         */
66
        cfg_data = hose->cfg_data + (offset & 3);
67
        switch (len) {
68
        case 1:
69
                *val = in_8(cfg_data);
70
                break;
71
        case 2:
72
                *val = in_le16(cfg_data);
73
                break;
74
        default:
75
                *val = in_le32(cfg_data);
76
                break;
77
        }
78
        return PCIBIOS_SUCCESSFUL;
79
}
80
 
81
static int
82
indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
83
                      int len, u32 val)
84
{
85
        struct pci_controller *hose = bus->sysdata;
86
        volatile void __iomem *cfg_data;
87
        u8 cfg_type = 0;
88
        u32 bus_no, reg;
89
 
90
        if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK) {
91
                if (bus->number != hose->first_busno)
92
                        return PCIBIOS_DEVICE_NOT_FOUND;
93
                if (devfn != 0)
94
                        return PCIBIOS_DEVICE_NOT_FOUND;
95
        }
96
 
97
        if (ppc_md.pci_exclude_device)
98
                if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
99
                        return PCIBIOS_DEVICE_NOT_FOUND;
100
 
101
        if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE)
102
                if (bus->number != hose->first_busno)
103
                        cfg_type = 1;
104
 
105
        bus_no = (bus->number == hose->first_busno) ?
106
                        hose->self_busno : bus->number;
107
 
108
        if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG)
109
                reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
110
        else
111
                reg = offset & 0xfc;
112
 
113
        if (hose->indirect_type & PPC_INDIRECT_TYPE_BIG_ENDIAN)
114
                out_be32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
115
                         (devfn << 8) | reg | cfg_type));
116
        else
117
                out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
118
                         (devfn << 8) | reg | cfg_type));
119
 
120
        /* surpress setting of PCI_PRIMARY_BUS */
121
        if (hose->indirect_type & PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS)
122
                if ((offset == PCI_PRIMARY_BUS) &&
123
                        (bus->number == hose->first_busno))
124
                val &= 0xffffff00;
125
 
126
        /*
127
         * Note: the caller has already checked that offset is
128
         * suitably aligned and that len is 1, 2 or 4.
129
         */
130
        cfg_data = hose->cfg_data + (offset & 3);
131
        switch (len) {
132
        case 1:
133
                out_8(cfg_data, val);
134
                break;
135
        case 2:
136
                out_le16(cfg_data, val);
137
                break;
138
        default:
139
                out_le32(cfg_data, val);
140
                break;
141
        }
142
        return PCIBIOS_SUCCESSFUL;
143
}
144
 
145
static struct pci_ops indirect_pci_ops =
146
{
147
        .read = indirect_read_config,
148
        .write = indirect_write_config,
149
};
150
 
151
void __init
152
setup_indirect_pci(struct pci_controller* hose,
153
                   resource_size_t cfg_addr,
154
                   resource_size_t cfg_data, u32 flags)
155
{
156
        resource_size_t base = cfg_addr & PAGE_MASK;
157
        void __iomem *mbase;
158
 
159
        mbase = ioremap(base, PAGE_SIZE);
160
        hose->cfg_addr = mbase + (cfg_addr & ~PAGE_MASK);
161
        if ((cfg_data & PAGE_MASK) != base)
162
                mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
163
        hose->cfg_data = mbase + (cfg_data & ~PAGE_MASK);
164
        hose->ops = &indirect_pci_ops;
165
        hose->indirect_type = flags;
166
}

powered by: WebSVN 2.1.0

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