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