Rev 1600 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1029 | serge | 1 | |
2 | |||
1600 | serge | 3 | bool retval = false; |
1029 | serge | 4 | u32_t bus, last_bus; |
1600 | serge | 5 | PCITAG tag; |
1029 | serge | 6 | |
7 | if( (last_bus = PciApi(1))==-1) |
||
8 | |||
9 | |||
10 | for(bus=0;bus<=last_bus;bus++) |
||
11 | |||
12 | u32_t devfn; |
||
13 | |||
14 | for(devfn=0;devfn<256;devfn++) |
||
15 | |||
16 | hc_t *hc; |
||
17 | |||
18 | u32_t id; |
||
19 | |||
20 | u16_t devclass; |
||
21 | u8_t interface; |
||
22 | int i; |
||
1430 | serge | 23 | |
1029 | serge | 24 | interface = PciRead8(bus,devfn, 0x09); |
25 | |||
1430 | serge | 26 | if( devclass != 0x0C03) |
1029 | serge | 27 | continue; |
28 | |||
29 | if( interface != 0) |
||
30 | |||
1430 | serge | 31 | |
32 | pcicmd = PciRead16(bus,devfn, PCI_COMMAND); |
||
33 | |||
1029 | serge | 34 | continue; |
35 | |||
36 | hc = (hc_t*)kmalloc(sizeof(hc_t), 0); |
||
37 | |||
1600 | serge | 38 | |
39 | hc->pciId = PciRead32(bus,devfn, 0); |
||
1029 | serge | 40 | |
41 | |||
42 | hc->irq_line = PciRead32(bus,devfn, 0x3C) & 0xFF; |
||
43 | |||
1605 | serge | 44 | |
45 | for (i = 0; i < 6; i++) |
||
46 | |||
1029 | serge | 47 | u32_t base; |
48 | bool validSize; |
||
49 | |||
1600 | serge | 50 | base = PciRead32(bus,devfn, PCI_MAP_REG_START + (i << 2)); |
1029 | serge | 51 | |
52 | { |
||
53 | if (base & PCI_MAP_IO) { |
||
54 | hc->ioBase[i] = (addr_t)PCIGETIO(base); |
||
55 | hc->memType[i] = base & PCI_MAP_IO_ATTR_MASK; |
||
56 | } else { |
||
57 | hc->memBase[i] = (u32_t)PCIGETMEMORY(base); |
||
58 | hc->memType[i] = base & PCI_MAP_MEMORY_ATTR_MASK; |
||
59 | } |
||
60 | } |
||
61 | }; |
||
62 | list_add_tail(&hc->list, &hc_list); |
||
63 | retval = true; |
||
1600 | serge | 64 | }; |
65 | }; |
||
1029 | serge | 66 | return retval; |
67 | }; |
||
68 | |||
69 | |||
1600 | serge | 70 | |
71 | |||
72 | /* these helpers provide future and backwards compatibility |
||
73 | |||
74 | #define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start) |
||
75 | #define pci_resource_end(dev, bar) ((dev)->resource[(bar)].end) |
||
76 | #define pci_resource_flags(dev, bar) ((dev)->resource[(bar)].flags) |
||
77 | #define pci_resource_len(dev,bar) \ |
||
78 | ((pci_resource_start((dev), (bar)) == 0 && \ |
||
79 | pci_resource_end((dev), (bar)) == \ |
||
80 | pci_resource_start((dev), (bar))) ? 0 : \ |
||
81 | \ |
||
82 | (pci_resource_end((dev), (bar)) - \ |
||
83 | pci_resource_start((dev), (bar)) + 1)) |
||
84 | |||
85 | static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx) |
||
86 | |||
87 | return pci_resource_start(pdev, idx) && mmio_enabled(pdev); |
||
88 | } |
||
89 | |||
90 | static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) |
||
91 | |||
92 | int wait_time, delta; |
||
93 | void __iomem *base, *op_reg_base; |
||
94 | u32 hcc_params, val; |
||
95 | u8 offset, cap_length; |
||
96 | int count = 256/4; |
||
97 | int tried_handoff = 0; |
||
98 | |||
99 | if (!mmio_resource_enabled(pdev, 0)) |
||
100 | |||
101 | |||
102 | base = pci_ioremap_bar(pdev, 0); |
||
103 | |||
104 | return; |
||
105 | |||
106 | cap_length = readb(base); |
||
107 | |||
108 | |||
109 | /* EHCI 0.96 and later may have "extended capabilities" |
||
110 | |||
111 | * booting from USB disk or using a usb keyboard |
||
112 | */ |
||
113 | hcc_params = readl(base + EHCI_HCC_PARAMS); |
||
114 | offset = (hcc_params >> 8) & 0xff; |
||
115 | while (offset && --count) { |
||
116 | u32 cap; |
||
117 | int msec; |
||
118 | |||
119 | pci_read_config_dword(pdev, offset, &cap); |
||
120 | |||
121 | case 1: /* BIOS/SMM/... handoff support */ |
||
122 | if ((cap & EHCI_USBLEGSUP_BIOS)) { |
||
123 | dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n"); |
||
124 | |||
125 | #if 0 |
||
126 | |||
127 | * but that seems dubious in general (the BIOS left it off intentionally) |
||
128 | * and is known to prevent some systems from booting. so we won't do this |
||
129 | * unless maybe we can determine when we're on a system that needs SMI forced. |
||
130 | */ |
||
131 | /* BIOS workaround (?): be sure the |
||
132 | * pre-Linux code receives the SMI |
||
133 | */ |
||
134 | pci_read_config_dword(pdev, |
||
135 | offset + EHCI_USBLEGCTLSTS, |
||
136 | &val); |
||
137 | pci_write_config_dword(pdev, |
||
138 | offset + EHCI_USBLEGCTLSTS, |
||
139 | val | EHCI_USBLEGCTLSTS_SOOE); |
||
140 | #endif |
||
141 | |||
142 | /* some systems get upset if this semaphore is |
||
143 | |||
144 | * handoff.. |
||
145 | */ |
||
146 | pci_write_config_byte(pdev, offset + 3, 1); |
||
147 | } |
||
148 | |||
149 | /* if boot firmware now owns EHCI, spin till |
||
150 | |||
151 | */ |
||
152 | msec = 1000; |
||
153 | while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { |
||
154 | tried_handoff = 1; |
||
155 | msleep(10); |
||
156 | msec -= 10; |
||
157 | pci_read_config_dword(pdev, offset, &cap); |
||
158 | } |
||
159 | |||
160 | if (cap & EHCI_USBLEGSUP_BIOS) { |
||
161 | |||
162 | * it down, and hope nothing goes too wrong |
||
163 | */ |
||
164 | dev_warn(&pdev->dev, "EHCI: BIOS handoff failed" |
||
165 | " (BIOS bug?) %08x\n", cap); |
||
166 | pci_write_config_byte(pdev, offset + 2, 0); |
||
167 | } |
||
168 | |||
169 | /* just in case, always disable EHCI SMIs */ |
||
170 | |||
171 | offset + EHCI_USBLEGCTLSTS, |
||
172 | 0); |
||
173 | |||
174 | /* If the BIOS ever owned the controller then we |
||
175 | |||
176 | */ |
||
177 | if (tried_handoff) |
||
178 | writel(0, op_reg_base + EHCI_CONFIGFLAG); |
||
179 | break; |
||
180 | case 0: /* illegal reserved capability */ |
||
181 | cap = 0; |
||
182 | /* FALLTHROUGH */ |
||
183 | default: |
||
184 | dev_warn(&pdev->dev, "EHCI: unrecognized capability " |
||
185 | "%02x\n", cap & 0xff); |
||
186 | break; |
||
187 | } |
||
188 | offset = (cap >> 8) & 0xff; |
||
189 | } |
||
190 | if (!count) |
||
191 | dev_printk(KERN_DEBUG, &pdev->dev, "EHCI: capability loop?\n"); |
||
192 | |||
193 | /* |
||
194 | |||
195 | */ |
||
196 | val = readl(op_reg_base + EHCI_USBSTS); |
||
197 | if ((val & EHCI_USBSTS_HALTED) == 0) { |
||
198 | val = readl(op_reg_base + EHCI_USBCMD); |
||
199 | val &= ~EHCI_USBCMD_RUN; |
||
200 | writel(val, op_reg_base + EHCI_USBCMD); |
||
201 | |||
202 | wait_time = 2000; |
||
203 | |||
204 | do { |
||
205 | writel(0x3f, op_reg_base + EHCI_USBSTS); |
||
206 | udelay(delta); |
||
207 | wait_time -= delta; |
||
208 | val = readl(op_reg_base + EHCI_USBSTS); |
||
209 | if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) { |
||
210 | break; |
||
211 | } |
||
212 | } while (wait_time > 0); |
||
213 | } |
||
214 | writel(0, op_reg_base + EHCI_USBINTR); |
||
215 | writel(0x3f, op_reg_base + EHCI_USBSTS); |
||
216 | |||
217 | iounmap(base); |
||
218 | |||
219 | return; |
||
220 | |||
221 | |||
222 | #endif><>>256;devfn++) |
||
223 | |||
224 | > |