• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/arch/sh/drivers/pci/
1#include <linux/pci.h>
2#include <linux/interrupt.h>
3#include <linux/timer.h>
4#include <linux/kernel.h>
5
6/*
7 * These functions are used early on before PCI scanning is done
8 * and all of the pci_dev and pci_bus structures have been created.
9 */
10static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
11	int top_bus, int busnr, int devfn)
12{
13	static struct pci_dev dev;
14	static struct pci_bus bus;
15
16	dev.bus = &bus;
17	dev.sysdata = hose;
18	dev.devfn = devfn;
19	bus.number = busnr;
20	bus.sysdata = hose;
21	bus.ops = hose->pci_ops;
22
23	if(busnr != top_bus)
24		/* Fake a parent bus structure. */
25		bus.parent = &bus;
26	else
27		bus.parent = NULL;
28
29	return &dev;
30}
31
32#define EARLY_PCI_OP(rw, size, type)					\
33int __init early_##rw##_config_##size(struct pci_channel *hose,		\
34	int top_bus, int bus, int devfn, int offset, type value)	\
35{									\
36	return pci_##rw##_config_##size(				\
37		fake_pci_dev(hose, top_bus, bus, devfn),		\
38		offset, value);						\
39}
40
41EARLY_PCI_OP(read, byte, u8 *)
42EARLY_PCI_OP(read, word, u16 *)
43EARLY_PCI_OP(read, dword, u32 *)
44EARLY_PCI_OP(write, byte, u8)
45EARLY_PCI_OP(write, word, u16)
46EARLY_PCI_OP(write, dword, u32)
47
48int __init pci_is_66mhz_capable(struct pci_channel *hose,
49				int top_bus, int current_bus)
50{
51	u32 pci_devfn;
52	unsigned short vid;
53	int cap66 = -1;
54	u16 stat;
55
56	printk(KERN_INFO "PCI: Checking 66MHz capabilities...\n");
57
58	for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
59		if (PCI_FUNC(pci_devfn))
60			continue;
61		if (early_read_config_word(hose, top_bus, current_bus,
62					   pci_devfn, PCI_VENDOR_ID, &vid) !=
63		    PCIBIOS_SUCCESSFUL)
64			continue;
65		if (vid == 0xffff)
66			continue;
67
68		/* check 66MHz capability */
69		if (cap66 < 0)
70			cap66 = 1;
71		if (cap66) {
72			early_read_config_word(hose, top_bus, current_bus,
73					       pci_devfn, PCI_STATUS, &stat);
74			if (!(stat & PCI_STATUS_66MHZ)) {
75				printk(KERN_DEBUG
76				       "PCI: %02x:%02x not 66MHz capable.\n",
77				       current_bus, pci_devfn);
78				cap66 = 0;
79				break;
80			}
81		}
82	}
83
84	return cap66 > 0;
85}
86
87static void pcibios_enable_err(unsigned long __data)
88{
89	struct pci_channel *hose = (struct pci_channel *)__data;
90
91	del_timer(&hose->err_timer);
92	printk(KERN_DEBUG "PCI: re-enabling error IRQ.\n");
93	enable_irq(hose->err_irq);
94}
95
96static void pcibios_enable_serr(unsigned long __data)
97{
98	struct pci_channel *hose = (struct pci_channel *)__data;
99
100	del_timer(&hose->serr_timer);
101	printk(KERN_DEBUG "PCI: re-enabling system error IRQ.\n");
102	enable_irq(hose->serr_irq);
103}
104
105void pcibios_enable_timers(struct pci_channel *hose)
106{
107	if (hose->err_irq) {
108		init_timer(&hose->err_timer);
109		hose->err_timer.data = (unsigned long)hose;
110		hose->err_timer.function = pcibios_enable_err;
111	}
112
113	if (hose->serr_irq) {
114		init_timer(&hose->serr_timer);
115		hose->serr_timer.data = (unsigned long)hose;
116		hose->serr_timer.function = pcibios_enable_serr;
117	}
118}
119
120/*
121 * A simple handler for the regular PCI status errors, called from IRQ
122 * context.
123 */
124unsigned int pcibios_handle_status_errors(unsigned long addr,
125					  unsigned int status,
126					  struct pci_channel *hose)
127{
128	unsigned int cmd = 0;
129
130	if (status & PCI_STATUS_REC_MASTER_ABORT) {
131		printk(KERN_DEBUG "PCI: master abort, pc=0x%08lx\n", addr);
132		cmd |= PCI_STATUS_REC_MASTER_ABORT;
133	}
134
135	if (status & PCI_STATUS_REC_TARGET_ABORT) {
136		printk(KERN_DEBUG "PCI: target abort: ");
137		pcibios_report_status(PCI_STATUS_REC_TARGET_ABORT |
138				      PCI_STATUS_SIG_TARGET_ABORT |
139				      PCI_STATUS_REC_MASTER_ABORT, 1);
140		printk("\n");
141
142		cmd |= PCI_STATUS_REC_TARGET_ABORT;
143	}
144
145	if (status & (PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY)) {
146		printk(KERN_DEBUG "PCI: parity error detected: ");
147		pcibios_report_status(PCI_STATUS_PARITY |
148				      PCI_STATUS_DETECTED_PARITY, 1);
149		printk("\n");
150
151		cmd |= PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY;
152
153		/* Now back off of the IRQ for awhile */
154		if (hose->err_irq) {
155			disable_irq_nosync(hose->err_irq);
156			hose->err_timer.expires = jiffies + HZ;
157			add_timer(&hose->err_timer);
158		}
159	}
160
161	return cmd;
162}
163