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