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