diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/pci-dma_32.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/pci-dma_64.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/reboot_fixups_32.c | 6 | ||||
-rw-r--r-- | arch/x86/pci/acpi.c | 194 | ||||
-rw-r--r-- | arch/x86/pci/common.c | 19 | ||||
-rw-r--r-- | arch/x86/pci/fixup.c | 47 | ||||
-rw-r--r-- | arch/x86/pci/i386.c | 13 | ||||
-rw-r--r-- | arch/x86/pci/irq.c | 39 | ||||
-rw-r--r-- | arch/x86/pci/pci.h | 2 |
9 files changed, 315 insertions, 9 deletions
diff --git a/arch/x86/kernel/pci-dma_32.c b/arch/x86/kernel/pci-dma_32.c index 048f09b62553..0aae2f3847a5 100644 --- a/arch/x86/kernel/pci-dma_32.c +++ b/arch/x86/kernel/pci-dma_32.c | |||
@@ -63,7 +63,8 @@ void dma_free_coherent(struct device *dev, size_t size, | |||
63 | { | 63 | { |
64 | struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; | 64 | struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; |
65 | int order = get_order(size); | 65 | int order = get_order(size); |
66 | 66 | ||
67 | WARN_ON(irqs_disabled()); /* for portability */ | ||
67 | if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { | 68 | if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { |
68 | int page = (vaddr - mem->virt_base) >> PAGE_SHIFT; | 69 | int page = (vaddr - mem->virt_base) >> PAGE_SHIFT; |
69 | 70 | ||
diff --git a/arch/x86/kernel/pci-dma_64.c b/arch/x86/kernel/pci-dma_64.c index 29711445c818..9576a2eb375e 100644 --- a/arch/x86/kernel/pci-dma_64.c +++ b/arch/x86/kernel/pci-dma_64.c | |||
@@ -167,6 +167,7 @@ EXPORT_SYMBOL(dma_alloc_coherent); | |||
167 | void dma_free_coherent(struct device *dev, size_t size, | 167 | void dma_free_coherent(struct device *dev, size_t size, |
168 | void *vaddr, dma_addr_t bus) | 168 | void *vaddr, dma_addr_t bus) |
169 | { | 169 | { |
170 | WARN_ON(irqs_disabled()); /* for portability */ | ||
170 | if (dma_ops->unmap_single) | 171 | if (dma_ops->unmap_single) |
171 | dma_ops->unmap_single(dev, bus, size, 0); | 172 | dma_ops->unmap_single(dev, bus, size, 0); |
172 | free_pages((unsigned long)vaddr, get_order(size)); | 173 | free_pages((unsigned long)vaddr, get_order(size)); |
diff --git a/arch/x86/kernel/reboot_fixups_32.c b/arch/x86/kernel/reboot_fixups_32.c index 03e1cce58f49..139eb03490f5 100644 --- a/arch/x86/kernel/reboot_fixups_32.c +++ b/arch/x86/kernel/reboot_fixups_32.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <asm/delay.h> | 12 | #include <asm/delay.h> |
13 | #include <linux/pci.h> | 13 | #include <linux/pci.h> |
14 | #include <linux/interrupt.h> | ||
14 | #include <asm/reboot_fixups.h> | 15 | #include <asm/reboot_fixups.h> |
15 | #include <asm/msr.h> | 16 | #include <asm/msr.h> |
16 | 17 | ||
@@ -56,6 +57,11 @@ void mach_reboot_fixups(void) | |||
56 | struct pci_dev *dev; | 57 | struct pci_dev *dev; |
57 | int i; | 58 | int i; |
58 | 59 | ||
60 | /* we can be called from sysrq-B code. In such a case it is | ||
61 | * prohibited to dig PCI */ | ||
62 | if (in_interrupt()) | ||
63 | return; | ||
64 | |||
59 | for (i=0; i < ARRAY_SIZE(fixups_table); i++) { | 65 | for (i=0; i < ARRAY_SIZE(fixups_table); i++) { |
60 | cur = &(fixups_table[i]); | 66 | cur = &(fixups_table[i]); |
61 | dev = pci_get_device(cur->vendor, cur->device, NULL); | 67 | dev = pci_get_device(cur->vendor, cur->device, NULL); |
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index bc8a44bddaa7..27a391da9a98 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c | |||
@@ -2,15 +2,199 @@ | |||
2 | #include <linux/acpi.h> | 2 | #include <linux/acpi.h> |
3 | #include <linux/init.h> | 3 | #include <linux/init.h> |
4 | #include <linux/irq.h> | 4 | #include <linux/irq.h> |
5 | #include <linux/dmi.h> | ||
5 | #include <asm/numa.h> | 6 | #include <asm/numa.h> |
6 | #include "pci.h" | 7 | #include "pci.h" |
7 | 8 | ||
9 | static int __devinit can_skip_ioresource_align(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[] = { | ||
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 | status = resource_to_addr(acpi_res, &addr); | ||
81 | if (ACPI_SUCCESS(status)) | ||
82 | info->res_num++; | ||
83 | return AE_OK; | ||
84 | } | ||
85 | |||
86 | static acpi_status | ||
87 | setup_resource(struct acpi_resource *acpi_res, void *data) | ||
88 | { | ||
89 | struct pci_root_info *info = data; | ||
90 | struct resource *res; | ||
91 | struct acpi_resource_address64 addr; | ||
92 | acpi_status status; | ||
93 | unsigned long flags; | ||
94 | struct resource *root; | ||
95 | |||
96 | status = resource_to_addr(acpi_res, &addr); | ||
97 | if (!ACPI_SUCCESS(status)) | ||
98 | return AE_OK; | ||
99 | |||
100 | if (addr.resource_type == ACPI_MEMORY_RANGE) { | ||
101 | root = &iomem_resource; | ||
102 | flags = IORESOURCE_MEM; | ||
103 | if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY) | ||
104 | flags |= IORESOURCE_PREFETCH; | ||
105 | } else if (addr.resource_type == ACPI_IO_RANGE) { | ||
106 | root = &ioport_resource; | ||
107 | flags = IORESOURCE_IO; | ||
108 | } else | ||
109 | return AE_OK; | ||
110 | |||
111 | res = &info->res[info->res_num]; | ||
112 | res->name = info->name; | ||
113 | res->flags = flags; | ||
114 | res->start = addr.minimum + addr.translation_offset; | ||
115 | res->end = res->start + addr.address_length - 1; | ||
116 | res->child = NULL; | ||
117 | |||
118 | if (insert_resource(root, res)) { | ||
119 | printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx " | ||
120 | "from %s for %s\n", (unsigned long) res->start, | ||
121 | (unsigned long) res->end, root->name, info->name); | ||
122 | } else { | ||
123 | info->bus->resource[info->res_num] = res; | ||
124 | info->res_num++; | ||
125 | } | ||
126 | return AE_OK; | ||
127 | } | ||
128 | |||
129 | static void | ||
130 | adjust_transparent_bridge_resources(struct pci_bus *bus) | ||
131 | { | ||
132 | struct pci_dev *dev; | ||
133 | |||
134 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
135 | int i; | ||
136 | u16 class = dev->class >> 8; | ||
137 | |||
138 | if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent) { | ||
139 | for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++) | ||
140 | dev->subordinate->resource[i] = | ||
141 | dev->bus->resource[i - 3]; | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | |||
146 | static void | ||
147 | get_current_resources(struct acpi_device *device, int busnum, | ||
148 | struct pci_bus *bus) | ||
149 | { | ||
150 | struct pci_root_info info; | ||
151 | size_t size; | ||
152 | |||
153 | info.bus = bus; | ||
154 | info.res_num = 0; | ||
155 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource, | ||
156 | &info); | ||
157 | if (!info.res_num) | ||
158 | return; | ||
159 | |||
160 | size = sizeof(*info.res) * info.res_num; | ||
161 | info.res = kmalloc(size, GFP_KERNEL); | ||
162 | if (!info.res) | ||
163 | goto res_alloc_fail; | ||
164 | |||
165 | info.name = kmalloc(12, GFP_KERNEL); | ||
166 | if (!info.name) | ||
167 | goto name_alloc_fail; | ||
168 | sprintf(info.name, "PCI Bus #%02x", busnum); | ||
169 | |||
170 | info.res_num = 0; | ||
171 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource, | ||
172 | &info); | ||
173 | if (info.res_num) | ||
174 | adjust_transparent_bridge_resources(bus); | ||
175 | |||
176 | return; | ||
177 | |||
178 | name_alloc_fail: | ||
179 | kfree(info.res); | ||
180 | res_alloc_fail: | ||
181 | return; | ||
182 | } | ||
183 | |||
8 | struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) | 184 | struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) |
9 | { | 185 | { |
10 | struct pci_bus *bus; | 186 | struct pci_bus *bus; |
11 | struct pci_sysdata *sd; | 187 | struct pci_sysdata *sd; |
12 | int pxm; | 188 | int pxm; |
13 | 189 | ||
190 | dmi_check_system(acpi_pciprobe_dmi_table); | ||
191 | |||
192 | if (domain && !pci_domains_supported) { | ||
193 | printk(KERN_WARNING "PCI: Multiple domains not supported " | ||
194 | "(dom %d, bus %d)\n", domain, busnum); | ||
195 | return NULL; | ||
196 | } | ||
197 | |||
14 | /* Allocate per-root-bus (not per bus) arch-specific data. | 198 | /* Allocate per-root-bus (not per bus) arch-specific data. |
15 | * TODO: leak; this memory is never freed. | 199 | * TODO: leak; this memory is never freed. |
16 | * It's arguable whether it's worth the trouble to care. | 200 | * It's arguable whether it's worth the trouble to care. |
@@ -21,12 +205,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do | |||
21 | return NULL; | 205 | return NULL; |
22 | } | 206 | } |
23 | 207 | ||
24 | if (domain != 0) { | 208 | sd->domain = domain; |
25 | printk(KERN_WARNING "PCI: Multiple domains not supported\n"); | ||
26 | kfree(sd); | ||
27 | return NULL; | ||
28 | } | ||
29 | |||
30 | sd->node = -1; | 209 | sd->node = -1; |
31 | 210 | ||
32 | pxm = acpi_get_pxm(device->handle); | 211 | pxm = acpi_get_pxm(device->handle); |
@@ -47,6 +226,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do | |||
47 | } | 226 | } |
48 | } | 227 | } |
49 | #endif | 228 | #endif |
229 | |||
230 | if (bus && (pci_probe & PCI_USE__CRS)) | ||
231 | get_current_resources(device, busnum, bus); | ||
50 | 232 | ||
51 | return bus; | 233 | return bus; |
52 | } | 234 | } |
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 07d5223442bf..2d71bbc411d2 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c | |||
@@ -29,12 +29,14 @@ struct pci_raw_ops *raw_pci_ops; | |||
29 | 29 | ||
30 | static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) | 30 | static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) |
31 | { | 31 | { |
32 | return raw_pci_ops->read(0, bus->number, devfn, where, size, value); | 32 | return raw_pci_ops->read(pci_domain_nr(bus), bus->number, |
33 | devfn, where, size, value); | ||
33 | } | 34 | } |
34 | 35 | ||
35 | static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) | 36 | static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) |
36 | { | 37 | { |
37 | return raw_pci_ops->write(0, bus->number, devfn, where, size, value); | 38 | return raw_pci_ops->write(pci_domain_nr(bus), bus->number, |
39 | devfn, where, size, value); | ||
38 | } | 40 | } |
39 | 41 | ||
40 | struct pci_ops pci_root_ops = { | 42 | struct pci_ops pci_root_ops = { |
@@ -287,6 +289,16 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { | |||
287 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"), | 289 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"), |
288 | }, | 290 | }, |
289 | }, | 291 | }, |
292 | #ifdef __i386__ | ||
293 | { | ||
294 | .callback = assign_all_busses, | ||
295 | .ident = "Compaq EVO N800c", | ||
296 | .matches = { | ||
297 | DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), | ||
298 | DMI_MATCH(DMI_PRODUCT_NAME, "EVO N800c"), | ||
299 | }, | ||
300 | }, | ||
301 | #endif | ||
290 | {} | 302 | {} |
291 | }; | 303 | }; |
292 | 304 | ||
@@ -426,6 +438,9 @@ char * __devinit pcibios_setup(char *str) | |||
426 | } else if (!strcmp(str, "assign-busses")) { | 438 | } else if (!strcmp(str, "assign-busses")) { |
427 | pci_probe |= PCI_ASSIGN_ALL_BUSSES; | 439 | pci_probe |= PCI_ASSIGN_ALL_BUSSES; |
428 | return NULL; | 440 | return NULL; |
441 | } else if (!strcmp(str, "use_crs")) { | ||
442 | pci_probe |= PCI_USE__CRS; | ||
443 | return NULL; | ||
429 | } else if (!strcmp(str, "routeirq")) { | 444 | } else if (!strcmp(str, "routeirq")) { |
430 | pci_routeirq = 1; | 445 | pci_routeirq = 1; |
431 | return NULL; | 446 | return NULL; |
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index c82cbf4c7226..6cff66dd0c91 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c | |||
@@ -353,6 +353,53 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev) | |||
353 | } | 353 | } |
354 | DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); | 354 | DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); |
355 | 355 | ||
356 | |||
357 | static struct dmi_system_id __devinitdata msi_k8t_dmi_table[] = { | ||
358 | { | ||
359 | .ident = "MSI-K8T-Neo2Fir", | ||
360 | .matches = { | ||
361 | DMI_MATCH(DMI_SYS_VENDOR, "MSI"), | ||
362 | DMI_MATCH(DMI_PRODUCT_NAME, "MS-6702E"), | ||
363 | }, | ||
364 | }, | ||
365 | {} | ||
366 | }; | ||
367 | |||
368 | /* | ||
369 | * The AMD-Athlon64 board MSI "K8T Neo2-FIR" disables the onboard sound | ||
370 | * card if a PCI-soundcard is added. | ||
371 | * | ||
372 | * The BIOS only gives options "DISABLED" and "AUTO". This code sets | ||
373 | * the corresponding register-value to enable the soundcard. | ||
374 | * | ||
375 | * The soundcard is only enabled, if the mainborad is identified | ||
376 | * via DMI-tables and the soundcard is detected to be off. | ||
377 | */ | ||
378 | static void __devinit pci_fixup_msi_k8t_onboard_sound(struct pci_dev *dev) | ||
379 | { | ||
380 | unsigned char val; | ||
381 | if (!dmi_check_system(msi_k8t_dmi_table)) | ||
382 | return; /* only applies to MSI K8T Neo2-FIR */ | ||
383 | |||
384 | pci_read_config_byte(dev, 0x50, &val); | ||
385 | if (val & 0x40) { | ||
386 | pci_write_config_byte(dev, 0x50, val & (~0x40)); | ||
387 | |||
388 | /* verify the change for status output */ | ||
389 | pci_read_config_byte(dev, 0x50, &val); | ||
390 | if (val & 0x40) | ||
391 | printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, " | ||
392 | "can't enable onboard soundcard!\n"); | ||
393 | else | ||
394 | printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, " | ||
395 | "enabled onboard soundcard.\n"); | ||
396 | } | ||
397 | } | ||
398 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, | ||
399 | pci_fixup_msi_k8t_onboard_sound); | ||
400 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, | ||
401 | pci_fixup_msi_k8t_onboard_sound); | ||
402 | |||
356 | /* | 403 | /* |
357 | * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A. | 404 | * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A. |
358 | * | 405 | * |
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index bcd2f94b732c..42ba0e2da1a0 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c | |||
@@ -33,6 +33,15 @@ | |||
33 | 33 | ||
34 | #include "pci.h" | 34 | #include "pci.h" |
35 | 35 | ||
36 | static int | ||
37 | skip_isa_ioresource_align(struct pci_dev *dev) { | ||
38 | |||
39 | if ((pci_probe & PCI_CAN_SKIP_ISA_ALIGN) && | ||
40 | !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA)) | ||
41 | return 1; | ||
42 | return 0; | ||
43 | } | ||
44 | |||
36 | /* | 45 | /* |
37 | * We need to avoid collisions with `mirrored' VGA ports | 46 | * We need to avoid collisions with `mirrored' VGA ports |
38 | * and other strange ISA hardware, so we always want the | 47 | * and other strange ISA hardware, so we always want the |
@@ -50,9 +59,13 @@ void | |||
50 | pcibios_align_resource(void *data, struct resource *res, | 59 | pcibios_align_resource(void *data, struct resource *res, |
51 | resource_size_t size, resource_size_t align) | 60 | resource_size_t size, resource_size_t align) |
52 | { | 61 | { |
62 | struct pci_dev *dev = data; | ||
63 | |||
53 | if (res->flags & IORESOURCE_IO) { | 64 | if (res->flags & IORESOURCE_IO) { |
54 | resource_size_t start = res->start; | 65 | resource_size_t start = res->start; |
55 | 66 | ||
67 | if (skip_isa_ioresource_align(dev)) | ||
68 | return; | ||
56 | if (start & 0x300) { | 69 | if (start & 0x300) { |
57 | start = (start + 0x3ff) & ~0x3ff; | 70 | start = (start + 0x3ff) & ~0x3ff; |
58 | res->start = start; | 71 | res->start = start; |
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index d98c6b096f8e..c52150fdf82b 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c | |||
@@ -492,6 +492,26 @@ static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq | |||
492 | return 1; | 492 | return 1; |
493 | } | 493 | } |
494 | 494 | ||
495 | /* | ||
496 | * PicoPower PT86C523 | ||
497 | */ | ||
498 | static int pirq_pico_get(struct pci_dev *router, struct pci_dev *dev, int pirq) | ||
499 | { | ||
500 | outb(0x10 + ((pirq - 1) >> 1), 0x24); | ||
501 | return ((pirq - 1) & 1) ? (inb(0x26) >> 4) : (inb(0x26) & 0xf); | ||
502 | } | ||
503 | |||
504 | static int pirq_pico_set(struct pci_dev *router, struct pci_dev *dev, int pirq, | ||
505 | int irq) | ||
506 | { | ||
507 | unsigned int x; | ||
508 | outb(0x10 + ((pirq - 1) >> 1), 0x24); | ||
509 | x = inb(0x26); | ||
510 | x = ((pirq - 1) & 1) ? ((x & 0x0f) | (irq << 4)) : ((x & 0xf0) | (irq)); | ||
511 | outb(x, 0x26); | ||
512 | return 1; | ||
513 | } | ||
514 | |||
495 | #ifdef CONFIG_PCI_BIOS | 515 | #ifdef CONFIG_PCI_BIOS |
496 | 516 | ||
497 | static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) | 517 | static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) |
@@ -721,6 +741,24 @@ static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router, | |||
721 | return 1; | 741 | return 1; |
722 | } | 742 | } |
723 | 743 | ||
744 | static __init int pico_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) | ||
745 | { | ||
746 | switch (device) { | ||
747 | case PCI_DEVICE_ID_PICOPOWER_PT86C523: | ||
748 | r->name = "PicoPower PT86C523"; | ||
749 | r->get = pirq_pico_get; | ||
750 | r->set = pirq_pico_set; | ||
751 | return 1; | ||
752 | |||
753 | case PCI_DEVICE_ID_PICOPOWER_PT86C523BBP: | ||
754 | r->name = "PicoPower PT86C523 rev. BB+"; | ||
755 | r->get = pirq_pico_get; | ||
756 | r->set = pirq_pico_set; | ||
757 | return 1; | ||
758 | } | ||
759 | return 0; | ||
760 | } | ||
761 | |||
724 | static __initdata struct irq_router_handler pirq_routers[] = { | 762 | static __initdata struct irq_router_handler pirq_routers[] = { |
725 | { PCI_VENDOR_ID_INTEL, intel_router_probe }, | 763 | { PCI_VENDOR_ID_INTEL, intel_router_probe }, |
726 | { PCI_VENDOR_ID_AL, ali_router_probe }, | 764 | { PCI_VENDOR_ID_AL, ali_router_probe }, |
@@ -732,6 +770,7 @@ static __initdata struct irq_router_handler pirq_routers[] = { | |||
732 | { PCI_VENDOR_ID_VLSI, vlsi_router_probe }, | 770 | { PCI_VENDOR_ID_VLSI, vlsi_router_probe }, |
733 | { PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe }, | 771 | { PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe }, |
734 | { PCI_VENDOR_ID_AMD, amd_router_probe }, | 772 | { PCI_VENDOR_ID_AMD, amd_router_probe }, |
773 | { PCI_VENDOR_ID_PICOPOWER, pico_router_probe }, | ||
735 | /* Someone with docs needs to add the ATI Radeon IGP */ | 774 | /* Someone with docs needs to add the ATI Radeon IGP */ |
736 | { 0, NULL } | 775 | { 0, NULL } |
737 | }; | 776 | }; |
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h index 8c66f275756f..ac56d3916c50 100644 --- a/arch/x86/pci/pci.h +++ b/arch/x86/pci/pci.h | |||
@@ -26,6 +26,8 @@ | |||
26 | #define PCI_ASSIGN_ROMS 0x1000 | 26 | #define PCI_ASSIGN_ROMS 0x1000 |
27 | #define PCI_BIOS_IRQ_SCAN 0x2000 | 27 | #define PCI_BIOS_IRQ_SCAN 0x2000 |
28 | #define PCI_ASSIGN_ALL_BUSSES 0x4000 | 28 | #define PCI_ASSIGN_ALL_BUSSES 0x4000 |
29 | #define PCI_CAN_SKIP_ISA_ALIGN 0x8000 | ||
30 | #define PCI_USE__CRS 0x10000 | ||
29 | 31 | ||
30 | extern unsigned int pci_probe; | 32 | extern unsigned int pci_probe; |
31 | extern unsigned long pirq_table_addr; | 33 | extern unsigned long pirq_table_addr; |