Add AMD SB800 southbridge CIMx code.
[coreboot.git] / src / vendorcode / amd / cimx / sb800 / USB.c
1 /**\r
2  * @file\r
3  *\r
4  * Config Southbridge USB controller\r
5  *\r
6  * Init USB features.\r
7  *\r
8  * @xrefitem bom "File Content Label" "Release Content"\r
9  * @e project:      CIMx-SB\r
10  * @e sub-project:\r
11  * @e \$Revision:$   @e \$Date:$\r
12  *\r
13  */\r
14 /*\r
15  *****************************************************************************\r
16  *\r
17  * This file is part of the coreboot project.\r
18  *\r
19  * Copyright (C) 2010 Advanced Micro Devices, Inc.\r
20  *\r
21  * This program is free software; you can redistribute it and/or modify\r
22  * it under the terms of the GNU General Public License as published by\r
23  * the Free Software Foundation; version 2 of the License.\r
24  *\r
25  * This program is distributed in the hope that it will be useful,\r
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
28  * GNU General Public License for more details.\r
29  *\r
30  * You should have received a copy of the GNU General Public License\r
31  * along with this program; if not, write to the Free Software\r
32  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA\r
33  * ***************************************************************************\r
34  *\r
35  */\r
36 \r
37 \r
38 #include "SBPLATFORM.h"\r
39 \r
40 //\r
41 // Declaration of local functions\r
42 //\r
43 \r
44 /**\r
45  * EhciInitAfterPciInit - Config USB controller after PCI emulation\r
46  *\r
47  * @param[in] Value Controller PCI config address (bus# + device# + function#)\r
48  * @param[in] pConfig Southbridge configuration structure pointer.\r
49  */\r
50 VOID EhciInitAfterPciInit (IN UINT32 Value, IN AMDSBCFG* pConfig);\r
51 /**\r
52  * OhciInitAfterPciInit - Config USB OHCI controller after PCI emulation\r
53  *\r
54  * @param[in] Value  Controller PCI config address (bus# + device# + function#)\r
55  * @param[in] pConfig Southbridge configuration structure pointer.\r
56  */\r
57 VOID OhciInitAfterPciInit (IN UINT32 Value, IN AMDSBCFG* pConfig);\r
58 \r
59 /**\r
60  * SetEhciP11Wr - FIXME\r
61  *\r
62  * @param[in] Value  Controller PCI config address (bus# + device# + function#)\r
63  * @param[in] pConfig Southbridge configuration structure pointer.\r
64  */\r
65 UINT32 SetEhciPllWr (IN UINT32 Value, IN AMDSBCFG* pConfig);\r
66 \r
67 \r
68 /**\r
69  * usbInitBeforePciEnum - Config USB controller before PCI emulation\r
70  *\r
71  *\r
72  *\r
73  * @param[in] pConfig Southbridge configuration structure pointer.\r
74  *\r
75  */\r
76 VOID\r
77 usbInitBeforePciEnum (\r
78   IN       AMDSBCFG* pConfig\r
79   )\r
80 {\r
81   // Disabled All USB controller\r
82   RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGEF, AccWidthUint8, BIT7, 0);\r
83   // Clear PM_IO 0x65[4] UsbResetByPciRstEnable, Set this bit so that usb gets reset whenever there is PCIRST.\r
84   // Enable UsbResumeEnable (USB PME) * Default value\r
85   // In SB700 USB SleepCtrl set as BIT10+BIT9, but SB800 default is BIT9+BIT8 (6 uframes)\r
86   RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGF0, AccWidthUint16 | S3_SAVE, ~BIT2, BIT2 + BIT7 + BIT8 + BIT9);\r
87   RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGEF, AccWidthUint8, 0, pConfig->USBMODE.UsbModeReg);\r
88 }\r
89 \r
90 /**\r
91  * usbInitAfterPciInit - Config USB controller after PCI emulation\r
92  *\r
93  *\r
94  *\r
95  * @param[in] pConfig Southbridge configuration structure pointer.\r
96  *\r
97  */\r
98 VOID\r
99 usbInitAfterPciInit (\r
100   IN       AMDSBCFG* pConfig\r
101   )\r
102 {\r
103   RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGED, AccWidthUint8, ~BIT1, BIT1);\r
104 \r
105   usb1EhciInitAfterPciInit (pConfig);\r
106   usb2EhciInitAfterPciInit (pConfig);\r
107   usb3EhciInitAfterPciInit (pConfig);\r
108   usb1OhciInitAfterPciInit (pConfig);\r
109   usb2OhciInitAfterPciInit (pConfig);\r
110   usb3OhciInitAfterPciInit (pConfig);\r
111   usb4OhciInitAfterPciInit (pConfig);\r
112 \r
113   if ( pConfig->UsbPhyPowerDown ) {\r
114     RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGF0, AccWidthUint8, ~BIT0, BIT0);\r
115   } else\r
116   {\r
117     RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGF0, AccWidthUint8, ~BIT0, 0);\r
118   }\r
119 \r
120 }\r
121 \r
122 /**\r
123  * usb1EhciInitAfterPciInit - Config USB1 EHCI controller after PCI emulation\r
124  *\r
125  *\r
126  *\r
127  * @param[in] pConfig Southbridge configuration structure pointer.\r
128  *\r
129  */\r
130 VOID\r
131 usb1EhciInitAfterPciInit (\r
132   IN       AMDSBCFG* pConfig\r
133   )\r
134 {\r
135   UINT32  ddDeviceId;\r
136   ddDeviceId = (USB1_EHCI_BUS_DEV_FUN << 16);\r
137   EhciInitAfterPciInit (ddDeviceId, pConfig);\r
138 }\r
139 \r
140 /**\r
141  * usb2EhciInitAfterPciInit - Config USB2 EHCI controller after PCI emulation\r
142  *\r
143  *\r
144  *\r
145  * @param[in] pConfig Southbridge configuration structure pointer.\r
146  *\r
147  */\r
148 VOID\r
149 usb2EhciInitAfterPciInit (\r
150   IN       AMDSBCFG* pConfig\r
151   )\r
152 {\r
153   UINT32  ddDeviceId;\r
154   ddDeviceId = (USB2_EHCI_BUS_DEV_FUN << 16);\r
155   EhciInitAfterPciInit (ddDeviceId, pConfig);\r
156 }\r
157 \r
158 /**\r
159  * usb3EhciInitAfterPciInit - Config USB3 EHCI controller after PCI emulation\r
160  *\r
161  *\r
162  *\r
163  * @param[in] pConfig Southbridge configuration structure pointer.\r
164  *\r
165  */\r
166 VOID\r
167 usb3EhciInitAfterPciInit (\r
168   IN       AMDSBCFG* pConfig\r
169   )\r
170 {\r
171   UINT32  ddDeviceId;\r
172   ddDeviceId = (USB3_EHCI_BUS_DEV_FUN << 16);\r
173   EhciInitAfterPciInit (ddDeviceId, pConfig);\r
174 }\r
175 \r
176 VOID\r
177 EhciInitAfterPciInit (\r
178   IN       UINT32 Value,\r
179   IN       AMDSBCFG* pConfig\r
180   )\r
181 {\r
182   UINT32  ddBarAddress;\r
183   UINT32  ddVar;\r
184   //Get BAR address\r
185   ReadPCI ((UINT32) Value + SB_EHCI_REG10, AccWidthUint32, &ddBarAddress);\r
186   if ( (ddBarAddress != - 1) && (ddBarAddress != 0) ) {\r
187     //Enable Memory access\r
188     RWPCI ((UINT32) Value + SB_EHCI_REG04, AccWidthUint8, 0, BIT1);\r
189     if (pConfig->BuildParameters.EhciSsid != NULL ) {\r
190       RWPCI ((UINT32) Value + SB_EHCI_REG2C, AccWidthUint32 | S3_SAVE, 0x00, pConfig->BuildParameters.EhciSsid);\r
191     }\r
192     //USB Common PHY CAL & Control Register setting\r
193     ddVar = 0x00020F00;\r
194     WriteMEM (ddBarAddress + SB_EHCI_BAR_REGC0, AccWidthUint32, &ddVar);\r
195     // RPR IN AND OUT DATA PACKET FIFO THRESHOLD\r
196     // EHCI BAR 0xA4 //IN threshold bits[7:0]=0x40 //OUT threshold bits[23:16]=0x40\r
197     RWMEM (ddBarAddress + SB_EHCI_BAR_REGA4, AccWidthUint32, 0xFF00FF00, 0x00400040);\r
198     // RPR EHCI Dynamic Clock Gating Feature\r
199     RWMEM (ddBarAddress + SB_EHCI_BAR_REGBC, AccWidthUint32, ~BIT12, 0);\r
200     // RPR Enable adding extra flops to PHY rsync path\r
201     // Step 1:\r
202     //  EHCI_BAR 0xB4 [6] = 1\r
203     //  EHCI_BAR 0xB4 [7] = 0\r
204     //  EHCI_BAR 0xB4 [12] = 0 ("VLoad")\r
205     //  All other bit field untouched\r
206     // Step 2:\r
207     //  EHCI_BAR 0xB4[12] = 1\r
208     RWMEM (ddBarAddress + SB_EHCI_BAR_REGB4, AccWidthUint32, ~(BIT6 + BIT7 + BIT12), 0x00);\r
209     RWMEM (ddBarAddress + SB_EHCI_BAR_REGB4, AccWidthUint32, ~BIT12, BIT12);\r
210     //Set EHCI_pci_configx50[6]='1' to disable EHCI MSI support\r
211     //RPR recommended setting "EHCI Async Park Mode"\r
212     //Set EHCI_pci_configx50[23]='0' to enable "EHCI Async Park Mode support"\r
213     //RPR Enabling EHCI Async Stop Enhancement\r
214     //Set EHCI_pci_configx50[29]='1' to disableEnabling EHCI Async Stop Enhancement\r
215     RWPCI ((UINT32) Value + SB_EHCI_REG50, AccWidthUint32 | S3_SAVE, ~(BIT23), BIT29 + BIT23 + BIT8 + BIT6);\r
216     // RPR recommended setting "EHCI Advance PHY Power Savings"\r
217     // Set EHCI_pci_configx50[31]='1'\r
218     // Fix for EHCI controller driver  yellow sign issue under device manager\r
219     // when used in conjunction with HSET tool driver. EHCI PCI config 0x50[20]=1\r
220     RWPCI ((UINT32) Value + SB_EHCI_REG50 + 2, AccWidthUint16 | S3_SAVE, (UINT16)0xFFFF, BIT15);\r
221     // RPR USB Delay A-Link Express L1 State\r
222     // RPR PING Response Fix Enable EHCI_PCI_Config  x54[1] = 1\r
223     // RPR Empty-list Detection Fix Enable EHCI_PCI_Config  x54[3] = 1\r
224     RWPCI ((UINT32) Value + SB_EHCI_REG54, AccWidthUint32 | S3_SAVE, ~BIT0, BIT0);\r
225     if ( pConfig->BuildParameters.UsbMsi) {\r
226       RWPCI ((UINT32) Value + SB_EHCI_REG50, AccWidthUint32 | S3_SAVE, ~BIT6, 0x00);\r
227     }\r
228   }\r
229 }\r
230 \r
231 /**\r
232  * usb1OhciInitAfterPciInit - Config USB1 OHCI controller after PCI emulation\r
233  *\r
234  *\r
235  *\r
236  * @param[in] pConfig Southbridge configuration structure pointer.\r
237  *\r
238  */\r
239 VOID\r
240 usb1OhciInitAfterPciInit (\r
241   IN       AMDSBCFG* pConfig\r
242   )\r
243 {\r
244   UINT32  ddDeviceId;\r
245   ddDeviceId = (USB1_OHCI_BUS_DEV_FUN << 16);\r
246   OhciInitAfterPciInit (ddDeviceId, pConfig);\r
247 }\r
248 \r
249 /**\r
250  * usb2OhciInitAfterPciInit - Config USB2 OHCI controller after PCI emulation\r
251  *\r
252  *\r
253  *\r
254  * @param[in] pConfig Southbridge configuration structure pointer.\r
255  *\r
256  */\r
257 VOID\r
258 usb2OhciInitAfterPciInit (\r
259   IN       AMDSBCFG* pConfig\r
260   )\r
261 {\r
262   UINT32  ddDeviceId;\r
263   ddDeviceId = (USB2_OHCI_BUS_DEV_FUN << 16);\r
264   OhciInitAfterPciInit (ddDeviceId, pConfig);\r
265 }\r
266 \r
267 /**\r
268  * usb3OhciInitAfterPciInit - Config USB3 OHCI controller after PCI emulation\r
269  *\r
270  *\r
271  *\r
272  * @param[in] pConfig Southbridge configuration structure pointer.\r
273  *\r
274  */\r
275 VOID\r
276 usb3OhciInitAfterPciInit (\r
277   IN       AMDSBCFG* pConfig\r
278   )\r
279 {\r
280   UINT32  ddDeviceId;\r
281   ddDeviceId = (USB3_OHCI_BUS_DEV_FUN << 16);\r
282   OhciInitAfterPciInit (ddDeviceId, pConfig);\r
283 }\r
284 \r
285 /**\r
286  * usb4OhciInitAfterPciInit - Config USB4 OHCI controller after PCI emulation\r
287  *\r
288  *\r
289  *\r
290  * @param[in] pConfig Southbridge configuration structure pointer.\r
291  *\r
292  */\r
293 VOID\r
294 usb4OhciInitAfterPciInit (\r
295   IN       AMDSBCFG* pConfig\r
296   )\r
297 {\r
298   UINT32  ddDeviceId;\r
299   ddDeviceId = (USB4_OHCI_BUS_DEV_FUN << 16);\r
300   OhciInitAfterPciInit (ddDeviceId, pConfig);\r
301   if (pConfig->BuildParameters.Ohci4Ssid != NULL ) {\r
302     RWPCI ((USB4_OHCI_BUS_DEV_FUN << 16) + SB_OHCI_REG2C, AccWidthUint32 | S3_SAVE, 0x00, pConfig->BuildParameters.Ohci4Ssid);\r
303   }\r
304 }\r
305 \r
306 VOID\r
307 OhciInitAfterPciInit (\r
308   IN       UINT32 Value,\r
309   IN       AMDSBCFG* pConfig\r
310   )\r
311 {\r
312   // Disable the MSI capability of USB host controllers\r
313   RWPCI ((UINT32) Value + SB_OHCI_REG40 + 1, AccWidthUint8 | S3_SAVE, 0xFF, BIT0);\r
314   RWPCI ((UINT32) Value + SB_OHCI_REG50, AccWidthUint8 | S3_SAVE, ~(BIT5 + BIT12), 0x00);\r
315   // RPR USB SMI Handshake\r
316   RWPCI ((UINT32) Value + SB_OHCI_REG50 + 1, AccWidthUint8 | S3_SAVE, ~BIT4, 0x00);\r
317   // SB02186\r
318   RWPCI ((UINT32) Value + SB_OHCI_REG50 + 1, AccWidthUint8 | S3_SAVE, 0xFC, 0x00);\r
319   if (Value != (USB4_OHCI_BUS_DEV_FUN << 16)) {\r
320     if ( pConfig->BuildParameters.OhciSsid != NULL ) {\r
321       RWPCI ((UINT32) Value + SB_OHCI_REG2C, AccWidthUint32 | S3_SAVE, 0x00, pConfig->BuildParameters.OhciSsid);\r
322     }\r
323   }\r
324   //RPR recommended setting to, enable fix to cover the corner case S3 wake up issue from some USB 1.1 devices\r
325   //OHCI 0_PCI_Config 0x50[30] = 1\r
326   RWPCI ((UINT32) Value + SB_OHCI_REG50 + 3, AccWidthUint8 | S3_SAVE, ~BIT6, BIT6);\r
327   if ( pConfig->BuildParameters.UsbMsi) {\r
328     RWPCI ((UINT32) Value + SB_OHCI_REG40 + 1, AccWidthUint8 | S3_SAVE, ~BIT0, 0x00);\r
329     RWPCI ((UINT32) Value + SB_OHCI_REG50, AccWidthUint8 | S3_SAVE, ~BIT5, BIT5);\r
330   }\r
331 }\r
332 \r
333 \r
334 UINT32\r
335 SetEhciPllWr (\r
336   IN       UINT32 Value,\r
337   IN       AMDSBCFG* pConfig\r
338   )\r
339 {\r
340   UINT32  ddRetureValue;\r
341   UINT32  ddBarAddress;\r
342   UINT16  dwVar;\r
343   UINT16  dwData;\r
344   UINT8  portSC;\r
345   ddRetureValue = 0;\r
346   dwData = 0;\r
347   // Memory, and etc.\r
348   //_asm { jmp $};\r
349   RWPCI ((UINT32) Value + 0xC4, AccWidthUint8, 0xF0, 0x00);\r
350   RWPCI ((UINT32) Value + 0x04, AccWidthUint8, 0xFF, 0x02);\r
351   // Get Bar address\r
352   ReadPCI ((UINT32) Value + 0x10, AccWidthUint32, &ddBarAddress);\r
353   for (portSC = 0x64; portSC < 0x75; portSC += 0x04 ) {\r
354     // Get OHCI command registers\r
355     ReadMEM (ddBarAddress + portSC, AccWidthUint16, &dwVar);\r
356     if ( dwVar & BIT6 ) {\r
357       ddRetureValue = ddBarAddress + portSC;\r
358       RWMEM (ddBarAddress + portSC, AccWidthUint16, ~BIT6, 0);\r
359       for (;;) {\r
360         SbStall (5);\r
361         ReadMEM (ddBarAddress + portSC, AccWidthUint16, &dwData);\r
362         if (dwData == 0x1005) break;\r
363       }\r
364       dwData = 0;\r
365     }\r
366   }\r
367   return ddRetureValue;\r
368 }\r
369 \r
370 VOID\r
371 usbSetPllDuringS3 (\r
372   IN       AMDSBCFG* pConfig\r
373   )\r
374 {\r
375   UINT32  resumeEhciPortTmp;\r
376   UINT32  resumeEhciPort;\r
377   resumeEhciPortTmp = 0;\r
378   resumeEhciPort = 0;\r
379 //  UINT32  ddDeviceId;\r
380 //if Force Port Resume == 1\r
381 // {\r
382 //     clear Force Port Resume;\r
383 //     while (!(PORTSC == 0x1005)){wait 5 us; read PORTSC;}\r
384 // }\r
385   if (pConfig->USBMODE.UsbModeReg & BIT1) {\r
386     resumeEhciPortTmp = SetEhciPllWr (USB1_EHCI_BUS_DEV_FUN << 16, pConfig);\r
387     if (resumeEhciPortTmp > 0) resumeEhciPort = resumeEhciPortTmp;\r
388   }\r
389   if (pConfig->USBMODE.UsbModeReg & BIT3) {\r
390     resumeEhciPortTmp = SetEhciPllWr (USB2_EHCI_BUS_DEV_FUN << 16, pConfig);\r
391     if (resumeEhciPortTmp > 0) resumeEhciPort = resumeEhciPortTmp;\r
392   }\r
393   if (pConfig->USBMODE.UsbModeReg & BIT5) {\r
394     resumeEhciPortTmp = SetEhciPllWr (USB3_EHCI_BUS_DEV_FUN << 16, pConfig);\r
395     if (resumeEhciPortTmp > 0) resumeEhciPort = resumeEhciPortTmp;\r
396   }\r
397 \r
398   RWPCI ((UINT32) (USB1_OHCI_BUS_DEV_FUN << 16) + SB_OHCI_REG50, AccWidthUint32, ~BIT29, 0);\r
399   RWPCI ((UINT32) (USB2_OHCI_BUS_DEV_FUN << 16) + SB_OHCI_REG50, AccWidthUint32, ~BIT29, 0);\r
400   RWPCI ((UINT32) (USB3_OHCI_BUS_DEV_FUN << 16) + SB_OHCI_REG50, AccWidthUint32, ~BIT29, 0);\r
401   RWPCI ((UINT32) (USB4_OHCI_BUS_DEV_FUN << 16) + SB_OHCI_REG50, AccWidthUint32, ~BIT29, 0);\r
402   RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGF3, AccWidthUint8, 0, 0x20);\r
403   SbStall (10);\r
404   RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGF3, AccWidthUint8, 0, 0x00);\r
405   RWPCI ((UINT32) (USB1_OHCI_BUS_DEV_FUN << 16) + SB_OHCI_REG50, AccWidthUint32, ~BIT29, BIT29);\r
406   RWPCI ((UINT32) (USB2_OHCI_BUS_DEV_FUN << 16) + SB_OHCI_REG50, AccWidthUint32, ~BIT29, BIT29);\r
407   RWPCI ((UINT32) (USB3_OHCI_BUS_DEV_FUN << 16) + SB_OHCI_REG50, AccWidthUint32, ~BIT29, BIT29);\r
408   RWPCI ((UINT32) (USB4_OHCI_BUS_DEV_FUN << 16) + SB_OHCI_REG50, AccWidthUint32, ~BIT29, BIT29);\r
409 \r
410   if (resumeEhciPort > 0) {\r
411     RWMEM (resumeEhciPort, AccWidthUint8, ~BIT7, BIT7);\r
412     SbStall (4000);\r
413     RWMEM (resumeEhciPort, AccWidthUint8, ~BIT6, BIT6);\r
414   }\r
415 \r
416   RWPCI ((UINT32) (USB1_EHCI_BUS_DEV_FUN << 16) + 0xC4, AccWidthUint8, 0xF0, 0x03);\r
417   RWPCI ((UINT32) (USB2_EHCI_BUS_DEV_FUN << 16) + 0xC4, AccWidthUint8, 0xF0, 0x03);\r
418   RWPCI ((UINT32) (USB3_EHCI_BUS_DEV_FUN << 16) + 0xC4, AccWidthUint8, 0xF0, 0x03);\r
419 \r
420 }\r
421 \r