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