ACPI: Remove CBMEM TOC from GNVS
[coreboot.git] / src / vendorcode / amd / cimx / sb800 / vendorcode / amd / cimx / sb800 / SATA.c
1
2 /**
3  * @file
4  *
5  * Config Southbridge SATA controller
6  *
7  * Init SATA features.
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:      CIMx-SB
11  * @e sub-project:
12  * @e \$Revision:$   @e \$Date:$
13  *
14  */
15 /*
16  *****************************************************************************
17  *
18  * Copyright (c) 2011, Advanced Micro Devices, Inc.
19  * All rights reserved.
20  * 
21  * Redistribution and use in source and binary forms, with or without
22  * modification, are permitted provided that the following conditions are met:
23  *     * Redistributions of source code must retain the above copyright
24  *       notice, this list of conditions and the following disclaimer.
25  *     * Redistributions in binary form must reproduce the above copyright
26  *       notice, this list of conditions and the following disclaimer in the
27  *       documentation and/or other materials provided with the distribution.
28  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of 
29  *       its contributors may be used to endorse or promote products derived 
30  *       from this software without specific prior written permission.
31  * 
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42  * 
43  * ***************************************************************************
44  *
45  */
46
47 #include "SBPLATFORM.h"
48 #include "cbtypes.h"
49
50 //
51 // Declaration of local functions
52 //
53 VOID  sataSetIrqIntResource (IN AMDSBCFG* pConfig);
54 VOID  sataBar5setting (IN AMDSBCFG* pConfig, IN UINT32 *pBar5);
55 VOID  shutdownUnconnectedSataPortClock (IN AMDSBCFG* pConfig, IN UINT32 ddBar5);
56 VOID  sataDriveDetection (IN AMDSBCFG* pConfig, IN UINT32 *pBar5);
57
58 /**
59  * sataSetIrqIntResource - Config SATA IRQ/INT# resource
60  *
61  *
62  *   - Private function
63  *
64  * @param[in] pConfig Southbridge configuration structure pointer.
65  *
66  */
67 VOID
68 sataSetIrqIntResource (
69   IN       AMDSBCFG*   pConfig
70   )
71 {
72   UINT8   dbValue;
73   // IRQ14/IRQ15 come from IDE or SATA
74   dbValue = 0x08;
75   WriteIO (SB_IOMAP_REGC00, AccWidthUint8, &dbValue);
76   ReadIO (SB_IOMAP_REGC01, AccWidthUint8, &dbValue);
77   dbValue = dbValue & 0x0F;
78   if (pConfig->SataClass == 3) {
79     dbValue = dbValue | 0x50;
80   } else {
81     if (pConfig->SataIdeMode == 1) {
82       // Both IDE & SATA set to Native mode
83       dbValue = dbValue | 0xF0;
84     }
85   }
86   WriteIO (SB_IOMAP_REGC01, AccWidthUint8, &dbValue);
87 }
88
89 /**
90  * sataBar5setting - Config SATA BAR5
91  *
92  *   - Private function
93  *
94  * @param[in] pConfig - Southbridge configuration structure pointer.
95  * @param[in] *pBar5   - SATA BAR5 buffer.
96  *
97  */
98 VOID
99 sataBar5setting (
100   IN       AMDSBCFG*   pConfig,
101   IN       UINT32      *pBar5
102   )
103 {
104   //Get BAR5 value
105   ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG24), AccWidthUint32, pBar5);
106   //Assign temporary BAR if is not already assigned
107   if ( (*pBar5 == 0) || (*pBar5 == - 1) ) {
108     //assign temporary BAR5
109     if ( (pConfig->TempMMIO == 0) || (pConfig->TempMMIO == - 1) ) {
110       *pBar5 = 0xFEC01000;
111     } else {
112       *pBar5 = pConfig->TempMMIO;
113     }
114     WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG24), AccWidthUint32, pBar5);
115   }
116   //Clear Bits 9:0
117   *pBar5 = *pBar5 & 0xFFFFFC00;
118 }
119 /**
120  * shutdownUnconnectedSataPortClock - Shutdown unconnected Sata port clock
121  *
122  *   - Private function
123  *
124  * @param[in] pConfig Southbridge configuration structure pointer.
125  * @param[in] ddBar5 Sata BAR5 base address.
126  *
127  */
128 VOID
129 shutdownUnconnectedSataPortClock (
130   IN       AMDSBCFG* pConfig,
131   IN       UINT32 ddBar5
132   )
133 {
134   UINT8  dbPortNum;
135   UINT8  dbPortSataStatus;
136   UINT8  NumOfPorts;
137   UINT8  cimSataClkAutoOff;
138
139   cimSataClkAutoOff = (UINT8) pConfig->SataClkAutoOff;
140 #if  SB_CIMx_PARAMETER == 0
141   cimSataClkAutoOff = cimSataClkAutoOffDefault;
142 #endif
143   NumOfPorts = 0;
144   if ( cimSataClkAutoOff == TRUE ) {
145     for ( dbPortNum = 0; dbPortNum < 6; dbPortNum++ ) {
146       ReadMEM (ddBar5 + SB_SATA_BAR5_REG128 + (dbPortNum * 0x80), AccWidthUint8, &dbPortSataStatus);
147       // Shutdown the clock for the port and do the necessary port reporting changes.
148       // ?? Error port status should be 1 not 3
149       if ( ((dbPortSataStatus & 0x0F) != 0x03) && (! ((pConfig->SataEspPort) & (1 << dbPortNum))) ) {
150         RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 2), AccWidthUint8, 0xFF, (1 << dbPortNum));
151         RWMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, ~(1 << dbPortNum), 00);
152       }
153     }     //end of for (dbPortNum=0;dbPortNum<6;dbPortNum++)
154     ReadMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, &dbPortSataStatus);
155     //if all ports are in disabled state, report atleast one port
156     if ( (dbPortSataStatus & 0x3F) == 0) {
157       RWMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, (UINT32) ~(0x3F), 01);
158     }
159     ReadMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, &dbPortSataStatus);
160     for (dbPortNum = 0; dbPortNum < 6; dbPortNum ++) {
161       if (dbPortSataStatus & (1 << dbPortNum)) {
162         NumOfPorts++;
163       }
164     }
165     if ( NumOfPorts == 0) {
166       NumOfPorts = 0x01;
167     }
168     RWMEM (ddBar5 + SB_SATA_BAR5_REG00, AccWidthUint8, 0xE0, NumOfPorts - 1);
169   }  //end of SataClkAuto Off option
170 }
171
172 /**
173  * Table for class code of SATA Controller in different modes
174  *
175  *
176  *
177  *
178  */
179 const static UINT32 sataIfCodeTable[] =
180 {
181   0x01018F40, //sata class ID of IDE
182   0x01040040, //sata class ID of RAID
183   0x01060140, //sata class ID of AHCI
184   0x01018A40, //sata class ID of Legacy IDE
185   0x01018F40, //sata class ID of IDE to AHCI mode
186 };
187
188 /**
189  * Table for device id of SATA Controller in different modes
190  *
191  *
192  *
193  *
194  */
195 const static UINT16 sataDeviceIDTable[] =
196 {
197   0x4390,  //sata device ID of IDE
198   0x4392,  //sata device ID of RAID
199   0x4391,  //sata class ID of AHCI
200   0x4390,  //sata device ID of Legacy IDE
201   0x4390,  //sata device ID of IDE->AHCI mode
202 };
203
204 /**
205  * Table for Sata Phy Fine Setting
206  *
207  *
208  *
209  *
210  */
211 const static SATAPHYSETTING sataPhyTable[] =
212 {
213   {0x3006, 0x0056A607},
214   {0x2006, 0x00061400},
215   {0x1006, 0x00061302},
216
217   {0x3206, 0x0056A607},
218   {0x2206, 0x00061400},
219   {0x1206, 0x00061302},
220
221   {0x3406, 0x0056A607},
222   {0x2406, 0x00061402},
223   {0x1406, 0x00064300},
224
225   {0x3606, 0x0056A607},
226   {0x2606, 0x00061402},
227   {0x1606, 0x00064300},
228
229   {0x3806, 0x0056A700},
230   {0x2806, 0x00061502},
231   {0x1806, 0x00064302},
232
233   {0x3A06, 0x0056A700},
234   {0x2A06, 0x00061502},
235   {0x1A06, 0x00064302}
236 };
237
238 /**
239  * sataInitBeforePciEnum - Config SATA controller before PCI emulation
240  *
241  *
242  *
243  * @param[in] pConfig Southbridge configuration structure pointer.
244  *
245  */
246 VOID
247 sataInitBeforePciEnum (
248   IN       AMDSBCFG*   pConfig
249   )
250 {
251   UINT32  ddTempVar;
252   UINT32  ddValue;
253   UINT32  *tempptr;
254   UINT16  *pDeviceIdptr;
255   UINT32  dwDeviceId;
256   UINT8   dbValue;
257   UINT8   pValue;
258   UINT16    i;
259   SATAPHYSETTING  *pPhyTable;
260
261   ddTempVar = NULL;
262   // BIT0 Enable write access to PCI header (reg 08h-0Bh) by setting SATA PCI register 40h
263   // BIT4: Disable fast boot
264   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, 0xff, BIT0 + BIT2 + BIT4);
265   // BIT0 Enable write access to PCI header (reg 08h-0Bh) by setting IDE PCI register 40h
266   RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG40), AccWidthUint8 | S3_SAVE, 0xff, BIT0);
267   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 2), AccWidthUint8 | S3_SAVE, 0, pConfig->SataPortPower);
268   dbValue = (UINT8)pConfig->SataClass;
269   if (dbValue == AHCI_MODE_4394) {
270     dbValue = AHCI_MODE;
271   }
272   if (dbValue == IDE_TO_AHCI_MODE_4394) {
273     dbValue = IDE_TO_AHCI_MODE;
274   }
275   // Disable PATA MSI
276   RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG34), AccWidthUint8 | S3_SAVE, 0x00, 0x00);
277   RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG06), AccWidthUint8 | S3_SAVE, 0xEF, 0x00);
278
279   // Get the appropriate class code from the table and write it to PCI register 08h-0Bh
280   // Set the appropriate SATA class based on the input parameters
281   // SATA IDE Controller Class ID & SSID
282   tempptr = (UINT32 *) FIXUP_PTR (&sataIfCodeTable[0]);
283   if ( (pConfig->SataIdeMode == 1) && (pConfig->SataClass != 3) ) {
284     ddValue = tempptr[0];
285     // Write the class code to IDE PCI register 08h-0Bh
286     RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG08), AccWidthUint32 | S3_SAVE, 0, ddValue);
287   }
288   ddValue = tempptr[dbValue];
289   // Write the class code to SATA PCI register 08h-0Bh
290   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG08), AccWidthUint32 | S3_SAVE, 0, ddValue);
291   if ( pConfig->SataClass == LEGACY_IDE_MODE ) {
292     //Set PATA controller to native mode
293     RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG09), AccWidthUint8 | S3_SAVE, 0x00, 0x08F);
294   }
295   if (pConfig->BuildParameters.IdeSsid != NULL ) {
296     RWPCI ((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG2C, AccWidthUint32 | S3_SAVE, 0x00, pConfig->BuildParameters.IdeSsid);
297   }
298   // SATA Controller Class ID & SSID
299   pDeviceIdptr = (UINT16 *) FIXUP_PTR (&sataDeviceIDTable[0]);
300   if ( pConfig->BuildParameters.SataIDESsid != NULL ) {
301     ddTempVar = pConfig->BuildParameters.SataIDESsid;
302   }
303   dwDeviceId = pDeviceIdptr[dbValue];
304   if ( pConfig->SataClass == RAID_MODE) {
305     if ( pConfig->BuildParameters.SataRAID5Ssid != NULL ) {
306       ddTempVar = pConfig->BuildParameters.SataRAID5Ssid;
307     }
308     dwDeviceId = V_SB_SATA_RAID5_DID;
309     pValue = SATA_EFUSE_LOCATION;
310     getEfuseStatus (&pValue);
311     if (( pValue & SATA_EFUSE_BIT ) || ( pConfig->SataForceRaid == 1 )) {
312       dwDeviceId = V_SB_SATA_RAID_DID;
313       if ( pConfig->BuildParameters.SataRAIDSsid != NULL ) {
314         ddTempVar = pConfig->BuildParameters.SataRAIDSsid;
315       }
316     }
317   }
318   if ( ((pConfig->SataClass) == AHCI_MODE) || ((pConfig->SataClass) == IDE_TO_AHCI_MODE) ||
319     ((pConfig->SataClass) == AHCI_MODE_4394) || ((pConfig->SataClass) == IDE_TO_AHCI_MODE_4394) ) {
320     if ( pConfig->BuildParameters.SataAHCISsid != NULL ) {
321       ddTempVar = pConfig->BuildParameters.SataAHCISsid;
322     }
323   }
324   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, 0, dwDeviceId);
325   if ( ddTempVar != NULL ) {
326     RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG2C, AccWidthUint32 | S3_SAVE, 0x00, ddTempVar);
327   }
328   // SATA IRQ Resource
329   sataSetIrqIntResource (pConfig);
330
331   // 8.4 SATA PHY Programming Sequence
332   pPhyTable = (SATAPHYSETTING*)FIXUP_PTR (&sataPhyTable[0]);
333   for (i = 0; i < (sizeof (sataPhyTable) / sizeof (SATAPHYSETTING)); i++) {
334     RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG84, AccWidthUint16 | S3_SAVE, ~(BIT1 + BIT2 + BIT9 + BIT10 + BIT11 + BIT12 + BIT13 + BIT14), pPhyTable->wPhyCoreControl);
335     RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG94, AccWidthUint32 | S3_SAVE, 0x00, pPhyTable->dwPhyFineTune);
336     ++pPhyTable;
337   }
338
339 //   CallBackToOEM (SATA_PHY_PROGRAMMING, NULL, pConfig);
340
341   RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0);
342   // Disable write access to PCI header
343   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0);
344 }
345
346 /**
347  * sataInitAfterPciEnum - Config SATA controller after PCI emulation
348  *
349  *
350  *
351  * @param[in] pConfig Southbridge configuration structure pointer.
352  *
353  */
354 VOID
355 sataInitAfterPciEnum (
356   IN       AMDSBCFG* pConfig
357   )
358 {
359   UINT32  ddAndMask;
360   UINT32  ddOrMask;
361   UINT32  ddBar5;
362   UINT8  dbVar;
363   UINT8  dbPortNum;
364   UINT8  dbEfuse;
365   UINT8  dbPortMode;
366   UINT16  SataPortMode;
367   UINT8  cimSataAggrLinkPmCap;
368   UINT8  cimSataPortMultCap;
369   UINT8  cimSataPscCap;
370   UINT8  cimSataSscCap;
371   UINT8  cimSataFisBasedSwitching;
372   UINT8  cimSataCccSupport;
373
374   cimSataAggrLinkPmCap = (UINT8) pConfig->SataAggrLinkPmCap;
375   cimSataPortMultCap = (UINT8) pConfig->SataPortMultCap;
376   cimSataPscCap = (UINT8) pConfig->SataPscCap;
377   cimSataSscCap = (UINT8) pConfig->SataSscCap;
378   cimSataFisBasedSwitching = (UINT8) pConfig->SataFisBasedSwitching;
379   cimSataCccSupport = (UINT8) pConfig->SataCccSupport;
380
381 #if  SB_CIMx_PARAMETER == 0
382   cimSataAggrLinkPmCap = cimSataAggrLinkPmCapDefault;
383   cimSataPortMultCap = cimSataPortMultCapDefault;
384   cimSataPscCap = cimSataPscCapDefault;
385   cimSataSscCap = cimSataSscCapDefault;
386   cimSataFisBasedSwitching = cimSataFisBasedSwitchingDefault;
387   cimSataCccSupport = cimSataCccSupportDefault;
388 #endif
389
390   ddAndMask = 0;
391   ddOrMask = 0;
392   ddBar5 = 0;
393   if ( pConfig->SATAMODE.SataMode.SataController == 0 ) {
394     return;   //return if SATA controller is disabled.
395   }
396
397   //Enable write access to pci header, pm capabilities
398   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, 0xFF, BIT0);
399   //Disable AHCI Prefetch function
400   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 2), AccWidthUint8 | S3_SAVE, 0x7F, BIT7);
401
402   sataBar5setting (pConfig, &ddBar5);
403
404   ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar);
405   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8,0xFF, 0x03);   //memory and io access enable
406   dbEfuse = SATA_FIS_BASE_EFUSE_LOC;
407   getEfuseStatus (&dbEfuse);
408
409   if ( !cimSataPortMultCap ) {
410     ddAndMask |= BIT12;
411   }
412   if ( cimSataAggrLinkPmCap ) {
413     ddOrMask |= BIT11;
414   } else {
415     ddAndMask |= BIT11;
416   }
417   if ( cimSataPscCap ) {
418     ddOrMask |= BIT1;
419   }
420   if ( cimSataSscCap ) {
421     ddOrMask |= BIT26;
422   }
423   if ( cimSataFisBasedSwitching ) {
424     if (dbEfuse & BIT1) {
425       ddAndMask |= BIT10;
426     } else {
427       ddOrMask |= BIT10;
428     }
429   } else {
430     ddAndMask |= BIT10;
431   }
432   // RPR 8.10 Disabling CCC (Command Completion Coalescing) support.
433   if ( cimSataCccSupport ) {
434     ddOrMask |= BIT19;
435   } else {
436     ddAndMask |= BIT19;
437   }
438   RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint32 | S3_SAVE, ~ddAndMask, ddOrMask);
439
440
441   // SATA ESP port setting
442   // These config bits are set for SATA driver to identify which ports are external SATA ports and need to
443   // support hotplug. If a port is set as an external SATA port and need to support hotplug, then driver will
444   // not enable power management (HIPM & DIPM) for these ports.
445   if ( pConfig->SataEspPort != 0 ) {
446     RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, ~(pConfig->SataEspPort), 0);
447     RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, ~(BIT12 + BIT13 + BIT14 + BIT15 + BIT16 + BIT17 + BIT5 + BIT4 + BIT3 + BIT2 + BIT1 + BIT0), (pConfig->SataEspPort << 12));
448     // RPR 8.7 External SATA Port Indication Registers
449     // If any of the ports was programmed as an external port, HCAP.SXS should also be set
450     RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint32 | S3_SAVE, ~(BIT20), BIT20);
451   } else {
452     // RPR 8.7 External SATA Port Indication Registers
453     // If any of the ports was programmed as an external port, HCAP.SXS should also be set (Clear for no ESP port)
454     RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, ~(BIT5 + BIT4 + BIT3 + BIT2 + BIT1 + BIT0), 0x00);
455     RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint32 | S3_SAVE, ~(BIT20), 0x00);
456   }
457   if ( cimSataFisBasedSwitching ) {
458     if (dbEfuse & BIT1) {
459       RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, ~(BIT22 + BIT23 + BIT24 + BIT25 + BIT26 + BIT27), 0x00);
460     } else {
461       RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, ~(BIT22 + BIT23 + BIT24 + BIT25 + BIT26 + BIT27), (BIT22 + BIT23 + BIT24 + BIT25 + BIT26 + BIT27));
462     }
463   } else {
464     RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, ~(BIT22 + BIT23 + BIT24 + BIT25 + BIT26 + BIT27), 0x00);
465   }
466
467   // Disabled SATA MSI and D3 Power State capability
468   // RPR 8.13 SATA MSI and D3 Power State Capability
469   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG34), AccWidthUint8 | S3_SAVE, 0, 0x70);
470
471   if (((pConfig->SataClass) != NATIVE_IDE_MODE) && ((pConfig->SataClass) != LEGACY_IDE_MODE)) {
472     // RIAD or AHCI
473     if ((pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == SATA_IDE_COMBINE_DISABLE) {
474       RWMEM ((ddBar5 + SB_SATA_BAR5_REG00), AccWidthUint8 | S3_SAVE, ~(BIT2 + BIT1 + BIT0), BIT2 + BIT0);
475       RWMEM ((ddBar5 + SB_SATA_BAR5_REG0C), AccWidthUint8 | S3_SAVE, 0xC0, 0x3F);
476       // RPR 8.10 Disabling CCC (Command Completion Coalescing) support.
477       // 8 messages
478       RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2 + BIT1);
479     } else {
480       // RPR 8.10 Disabling CCC (Command Completion Coalescing) support.
481       if ( pConfig->SataCccSupport ) {
482           // 8 messages
483         RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2 + BIT1);
484       } else {
485           // 4 messages
486         RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2);
487       }
488     }
489   }
490
491   if ( pConfig->BIOSOSHandoff == 1 ) {
492     RWMEM ((ddBar5 + SB_SATA_BAR5_REG24), AccWidthUint8 | S3_SAVE, ~BIT0, BIT0);
493   } else {
494     RWMEM ((ddBar5 + SB_SATA_BAR5_REG24), AccWidthUint8 | S3_SAVE, ~BIT0, 0x00);
495   }
496
497   SataPortMode = (UINT16)pConfig->SataPortMode;
498   dbPortNum = 0;
499   while ( dbPortNum < 6 ) {
500     dbPortMode = (UINT8) (SataPortMode & 3);
501     if ( (dbPortMode == BIT0) || (dbPortMode == BIT1) ) {
502       if ( dbPortMode == BIT0 ) {
503         // set GEN 1
504         RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0x0F, 0x10);
505       }
506       if ( dbPortMode == BIT1 ) {
507         // set GEN2 (default is GEN3)
508         RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0x0F, 0x20);
509       }
510       RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFF, 0x01);
511     }
512     SataPortMode >>= 2;
513     dbPortNum ++;
514   }
515   SbStall (1000);
516   SataPortMode = (UINT16)pConfig->SataPortMode;
517   dbPortNum = 0;
518   while ( dbPortNum < 6 ) {
519     dbPortMode = (UINT8) (SataPortMode & 3);
520     if ( (dbPortMode == BIT0) || (dbPortMode == BIT1) ) {
521       RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFE, 0x00);
522     }
523     dbPortNum ++;
524     SataPortMode >>= 2;
525   }
526   WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar);
527   //Disable write access to pci header, pm capabilities
528   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0);
529 }
530
531
532 /**
533  * sataInitMidPost - Config SATA controller in Middle POST.
534  *
535  *
536  *
537  * @param[in] pConfig Southbridge configuration structure pointer.
538  *
539  */
540 VOID
541 sataInitMidPost (
542   IN       AMDSBCFG* pConfig
543   )
544 {
545   UINT32   ddBar5;
546   sataBar5setting (pConfig, &ddBar5);
547   //If this is not S3 resume and also if SATA set to one of IDE mode, them implement drive detection workaround.
548   if ( ! (pConfig->S3Resume) && ( ((pConfig->SataClass) != AHCI_MODE)  && ((pConfig->SataClass) != RAID_MODE) ) ) {
549     sataDriveDetection (pConfig, &ddBar5);
550   }
551 }
552
553 /**
554  * sataDriveDetection - Sata drive detection
555  *
556  *
557  * @param[in] pConfig Southbridge configuration structure pointer.
558  * @param[in] *pBar5 Sata BAR5 base address.
559  *
560  */
561 VOID
562 sataDriveDetection (
563   IN       AMDSBCFG* pConfig,
564   IN       UINT32 *pBar5
565   )
566 {
567   UINT32   ddVar0;
568   UINT8   dbPortNum;
569   UINT8   dbVar0;
570   UINT16   dwIoBase;
571   UINT16   dwVar0;
572   if ( (pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE) || (pConfig->SataClass == IDE_TO_AHCI_MODE) ) {
573     for ( dbPortNum = 0; dbPortNum < 4; dbPortNum++ ) {
574       ReadMEM (*pBar5 + SB_SATA_BAR5_REG128 + dbPortNum * 0x80, AccWidthUint32, &ddVar0);
575       if ( ( ddVar0 & 0x0F ) == 0x03 ) {
576         if ( dbPortNum & BIT0 ) {
577           //this port belongs to secondary channel
578           ReadPCI (((UINT32) (SATA_BUS_DEV_FUN << 16) + SB_SATA_REG18), AccWidthUint16, &dwIoBase);
579         } else {
580           //this port belongs to primary channel
581           ReadPCI (((UINT32) (SATA_BUS_DEV_FUN << 16) + SB_SATA_REG10), AccWidthUint16, &dwIoBase);
582         }
583         //if legacy ide mode, then the bar registers don't contain the correct values. So we need to hardcode them
584         if ( pConfig->SataClass == LEGACY_IDE_MODE ) {
585           dwIoBase = ( (0x170) | ((UINT16) ( (~((UINT8) (dbPortNum & BIT0) << 7)) & 0x80 )) );
586         }
587         if ( dbPortNum & BIT1 ) {
588           //this port is slave
589           dbVar0 = 0xB0;
590         } else {
591           //this port is master
592           dbVar0 = 0xA0;
593         }
594         dwIoBase &= 0xFFF8;
595         WriteIO (dwIoBase + 6, AccWidthUint8, &dbVar0);
596         //Wait in loop for 30s for the drive to become ready
597         for ( dwVar0 = 0; dwVar0 < 300000; dwVar0++ ) {
598           ReadIO (dwIoBase + 7, AccWidthUint8, &dbVar0);
599           if ( (dbVar0 & 0x88) == 0 ) {
600             break;
601           }
602           SbStall (100);
603         }
604       } //end of if ( ( ddVar0 & 0x0F ) == 0x03)
605     } //for (dbPortNum = 0; dbPortNum < 4; dbPortNum++)
606   } //if ( (pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE) || (pConfig->SataClass == IDE_TO_AHCI_MODE))
607 }
608
609 /**
610  * sataInitLatePost - Prepare SATA controller to boot to OS.
611  *
612  *              - Set class ID to AHCI (if set to AHCI * Mode)
613  *              - Enable AHCI interrupt
614  *
615  * @param[in] pConfig Southbridge configuration structure pointer.
616  *
617  */
618 VOID
619 sataInitLatePost (
620   IN       AMDSBCFG* pConfig
621   )
622 {
623   UINT32  ddBar5;
624   UINT8  dbVar;
625   UINT8  dbPortNum;
626
627   //Return immediately is sata controller is not enabled
628   if ( pConfig->SATAMODE.SataMode.SataController == 0 ) {
629     return;
630   }
631   //Enable write access to pci header, pm capabilities
632   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, 0xff, BIT0);
633
634 //  if ((pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == SATA_IDE_COMBINE_DISABLE) {
635   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 1), AccWidthUint8 | S3_SAVE, ~BIT7, BIT7);
636 //  }
637   sataBar5setting (pConfig, &ddBar5);
638
639   ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar);
640   //Enable memory and io access
641   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, 0xFF, 0x03);
642
643   shutdownUnconnectedSataPortClock (pConfig, ddBar5);
644
645   if (( pConfig->SataClass == IDE_TO_AHCI_MODE) || ( pConfig->SataClass == IDE_TO_AHCI_MODE_4394 )) {
646     //program the AHCI class code
647     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG08), AccWidthUint32 | S3_SAVE, 0, 0x01060100);
648     //Set interrupt enable bit
649     RWMEM ((ddBar5 + 0x04), AccWidthUint8, (UINT32)~0, BIT1);
650     //program the correct device id for AHCI mode
651     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, 0, 0x4391);
652   }
653
654   if (( pConfig->SataClass == AHCI_MODE_4394 ) || ( pConfig->SataClass == IDE_TO_AHCI_MODE_4394 )) {
655     //program the correct device id for AHCI 4394 mode
656     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, 0, 0x4394);
657   }
658
659   //Clear error status ?? only 4 port
660   RWMEM ((ddBar5 + SB_SATA_BAR5_REG130), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
661   RWMEM ((ddBar5 + SB_SATA_BAR5_REG1B0), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
662   RWMEM ((ddBar5 + SB_SATA_BAR5_REG230), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
663   RWMEM ((ddBar5 + SB_SATA_BAR5_REG2B0), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
664   RWMEM ((ddBar5 + SB_SATA_BAR5_REG330), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
665   RWMEM ((ddBar5 + SB_SATA_BAR5_REG3B0), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
666   //Restore memory and io access bits
667   WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar );
668   //Disable write access to pci header and pm capabilities
669   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0);
670   for ( dbPortNum = 0; dbPortNum < 6; dbPortNum++ ) {
671     RWMEM ((ddBar5 + 0x110 + (dbPortNum * 0x80)), AccWidthUint32, 0xFFFFFFFF, 0x00);
672   }
673 }
674
675