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/] [x86/] [pci/] [acpi.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
#include <linux/pci.h>
2
#include <linux/acpi.h>
3
#include <linux/init.h>
4
#include <linux/irq.h>
5
#include <linux/dmi.h>
6
#include <asm/numa.h>
7
#include "pci.h"
8
 
9
static int __devinit can_skip_ioresource_align(const struct dmi_system_id *d)
10
{
11
        pci_probe |= PCI_CAN_SKIP_ISA_ALIGN;
12
        printk(KERN_INFO "PCI: %s detected, can skip ISA alignment\n", d->ident);
13
        return 0;
14
}
15
 
16
static struct dmi_system_id acpi_pciprobe_dmi_table[] __devinitdata = {
17
/*
18
 * Systems where PCI IO resource ISA alignment can be skipped
19
 * when the ISA enable bit in the bridge control is not set
20
 */
21
        {
22
                .callback = can_skip_ioresource_align,
23
                .ident = "IBM System x3800",
24
                .matches = {
25
                        DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
26
                        DMI_MATCH(DMI_PRODUCT_NAME, "x3800"),
27
                },
28
        },
29
        {
30
                .callback = can_skip_ioresource_align,
31
                .ident = "IBM System x3850",
32
                .matches = {
33
                        DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
34
                        DMI_MATCH(DMI_PRODUCT_NAME, "x3850"),
35
                },
36
        },
37
        {
38
                .callback = can_skip_ioresource_align,
39
                .ident = "IBM System x3950",
40
                .matches = {
41
                        DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
42
                        DMI_MATCH(DMI_PRODUCT_NAME, "x3950"),
43
                },
44
        },
45
        {}
46
};
47
 
48
struct pci_root_info {
49
        char *name;
50
        unsigned int res_num;
51
        struct resource *res;
52
        struct pci_bus *bus;
53
        int busnum;
54
};
55
 
56
static acpi_status
57
resource_to_addr(struct acpi_resource *resource,
58
                        struct acpi_resource_address64 *addr)
59
{
60
        acpi_status status;
61
 
62
        status = acpi_resource_to_address64(resource, addr);
63
        if (ACPI_SUCCESS(status) &&
64
            (addr->resource_type == ACPI_MEMORY_RANGE ||
65
            addr->resource_type == ACPI_IO_RANGE) &&
66
            addr->address_length > 0 &&
67
            addr->producer_consumer == ACPI_PRODUCER) {
68
                return AE_OK;
69
        }
70
        return AE_ERROR;
71
}
72
 
73
static acpi_status
74
count_resource(struct acpi_resource *acpi_res, void *data)
75
{
76
        struct pci_root_info *info = data;
77
        struct acpi_resource_address64 addr;
78
        acpi_status status;
79
 
80
        if (info->res_num >= PCI_BUS_NUM_RESOURCES)
81
                return AE_OK;
82
 
83
        status = resource_to_addr(acpi_res, &addr);
84
        if (ACPI_SUCCESS(status))
85
                info->res_num++;
86
        return AE_OK;
87
}
88
 
89
static acpi_status
90
setup_resource(struct acpi_resource *acpi_res, void *data)
91
{
92
        struct pci_root_info *info = data;
93
        struct resource *res;
94
        struct acpi_resource_address64 addr;
95
        acpi_status status;
96
        unsigned long flags;
97
        struct resource *root;
98
 
99
        if (info->res_num >= PCI_BUS_NUM_RESOURCES)
100
                return AE_OK;
101
 
102
        status = resource_to_addr(acpi_res, &addr);
103
        if (!ACPI_SUCCESS(status))
104
                return AE_OK;
105
 
106
        if (addr.resource_type == ACPI_MEMORY_RANGE) {
107
                root = &iomem_resource;
108
                flags = IORESOURCE_MEM;
109
                if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
110
                        flags |= IORESOURCE_PREFETCH;
111
        } else if (addr.resource_type == ACPI_IO_RANGE) {
112
                root = &ioport_resource;
113
                flags = IORESOURCE_IO;
114
        } else
115
                return AE_OK;
116
 
117
        res = &info->res[info->res_num];
118
        res->name = info->name;
119
        res->flags = flags;
120
        res->start = addr.minimum + addr.translation_offset;
121
        res->end = res->start + addr.address_length - 1;
122
        res->child = NULL;
123
 
124
        if (insert_resource(root, res)) {
125
                printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx "
126
                        "from %s for %s\n", (unsigned long) res->start,
127
                        (unsigned long) res->end, root->name, info->name);
128
        } else {
129
                info->bus->resource[info->res_num] = res;
130
                info->res_num++;
131
        }
132
        return AE_OK;
133
}
134
 
135
static void
136
adjust_transparent_bridge_resources(struct pci_bus *bus)
137
{
138
        struct pci_dev *dev;
139
 
140
        list_for_each_entry(dev, &bus->devices, bus_list) {
141
                int i;
142
                u16 class = dev->class >> 8;
143
 
144
                if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent) {
145
                        for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++)
146
                                dev->subordinate->resource[i] =
147
                                                dev->bus->resource[i - 3];
148
                }
149
        }
150
}
151
 
152
static void
153
get_current_resources(struct acpi_device *device, int busnum,
154
                        struct pci_bus *bus)
155
{
156
        struct pci_root_info info;
157
        size_t size;
158
 
159
        info.bus = bus;
160
        info.res_num = 0;
161
        acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
162
                                &info);
163
        if (!info.res_num)
164
                return;
165
 
166
        size = sizeof(*info.res) * info.res_num;
167
        info.res = kmalloc(size, GFP_KERNEL);
168
        if (!info.res)
169
                goto res_alloc_fail;
170
 
171
        info.name = kmalloc(12, GFP_KERNEL);
172
        if (!info.name)
173
                goto name_alloc_fail;
174
        sprintf(info.name, "PCI Bus #%02x", busnum);
175
 
176
        info.res_num = 0;
177
        acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
178
                                &info);
179
        if (info.res_num)
180
                adjust_transparent_bridge_resources(bus);
181
 
182
        return;
183
 
184
name_alloc_fail:
185
        kfree(info.res);
186
res_alloc_fail:
187
        return;
188
}
189
 
190
struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
191
{
192
        struct pci_bus *bus;
193
        struct pci_sysdata *sd;
194
        int pxm;
195
 
196
        dmi_check_system(acpi_pciprobe_dmi_table);
197
 
198
        if (domain && !pci_domains_supported) {
199
                printk(KERN_WARNING "PCI: Multiple domains not supported "
200
                       "(dom %d, bus %d)\n", domain, busnum);
201
                return NULL;
202
        }
203
 
204
        /* Allocate per-root-bus (not per bus) arch-specific data.
205
         * TODO: leak; this memory is never freed.
206
         * It's arguable whether it's worth the trouble to care.
207
         */
208
        sd = kzalloc(sizeof(*sd), GFP_KERNEL);
209
        if (!sd) {
210
                printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum);
211
                return NULL;
212
        }
213
 
214
        sd->domain = domain;
215
        sd->node = -1;
216
 
217
        pxm = acpi_get_pxm(device->handle);
218
#ifdef CONFIG_ACPI_NUMA
219
        if (pxm >= 0)
220
                sd->node = pxm_to_node(pxm);
221
#endif
222
 
223
        bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd);
224
        if (!bus)
225
                kfree(sd);
226
 
227
#ifdef CONFIG_ACPI_NUMA
228
        if (bus != NULL) {
229
                if (pxm >= 0) {
230
                        printk("bus %d -> pxm %d -> node %d\n",
231
                                busnum, pxm, sd->node);
232
                }
233
        }
234
#endif
235
 
236
        if (bus && (pci_probe & PCI_USE__CRS))
237
                get_current_resources(device, busnum, bus);
238
 
239
        return bus;
240
}
241
 
242
extern int pci_routeirq;
243
static int __init pci_acpi_init(void)
244
{
245
        struct pci_dev *dev = NULL;
246
 
247
        if (pcibios_scanned)
248
                return 0;
249
 
250
        if (acpi_noirq)
251
                return 0;
252
 
253
        printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
254
        acpi_irq_penalty_init();
255
        pcibios_scanned++;
256
        pcibios_enable_irq = acpi_pci_irq_enable;
257
        pcibios_disable_irq = acpi_pci_irq_disable;
258
 
259
        if (pci_routeirq) {
260
                /*
261
                 * PCI IRQ routing is set up by pci_enable_device(), but we
262
                 * also do it here in case there are still broken drivers that
263
                 * don't use pci_enable_device().
264
                 */
265
                printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
266
                for_each_pci_dev(dev)
267
                        acpi_pci_irq_enable(dev);
268
        } else
269
                printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\".  If it helps, post a report\n");
270
 
271
#ifdef CONFIG_X86_IO_APIC
272
        if (acpi_ioapic)
273
                print_IO_APIC();
274
#endif
275
 
276
        return 0;
277
}
278
subsys_initcall(pci_acpi_init);

powered by: WebSVN 2.1.0

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