sigh
[coreboot.git] / src / vendorcode / amd / cimx / sb900 / 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 #include "SbPlatform.h"
46 #include "cbtypes.h"
47 #include "AmdSbLib.h"
48
49 //
50 // Declaration of local functions
51 //
52 VOID  sataSetIrqIntResource (IN AMDSBCFG* pConfig);
53 VOID  sataBar5setting (IN AMDSBCFG* pConfig, IN UINT32 *pBar5);
54 #ifdef SATA_BUS_DEV_FUN_FPGA
55   VOID  sataBar5settingFpga (IN AMDSBCFG* pConfig, IN UINT32 *pBar5);
56 #endif
57 VOID  shutdownUnconnectedSataPortClock (IN AMDSBCFG* pConfig, IN UINT32 ddBar5);
58 VOID  CaculateAhciPortNumber (IN AMDSBCFG* pConfig, IN UINT32 ddBar5);
59 VOID  sataDriveDetection (IN AMDSBCFG* pConfig, IN UINT32 *pBar5);
60 #ifdef SATA_BUS_DEV_FUN_FPGA
61   VOID  sataDriveDetectionFpga (IN AMDSBCFG* pConfig, IN UINT32 *pBar5);
62 #endif
63 VOID  sataGpioPorcedure (IN AMDSBCFG* pConfig);
64
65 /**
66  * sataSetIrqIntResource - Config SATA IRQ/INT# resource
67  *
68  *
69  *   - Private function
70  *
71  * @param[in] pConfig Southbridge configuration structure pointer.
72  *
73  */
74 VOID
75 sataSetIrqIntResource (
76   IN       AMDSBCFG*   pConfig
77   )
78 {
79   UINT8   dbValue;
80   // IRQ14/IRQ15 come from IDE or SATA
81   dbValue = 0x08;
82   WriteIO (SB_IOMAP_REGC00, AccWidthUint8, &dbValue);
83   ReadIO (SB_IOMAP_REGC01, AccWidthUint8, &dbValue);
84   dbValue = dbValue & 0x0F;
85   if (pConfig->SataClass == 3) {
86     dbValue = dbValue | 0x50;
87   } else {
88     if (pConfig->SataIdeMode == 1) {
89       // Both IDE & SATA set to Native mode
90       dbValue = dbValue | 0xF0;
91     }
92   }
93   WriteIO (SB_IOMAP_REGC01, AccWidthUint8, &dbValue);
94 }
95
96 /**
97  * sataBar5setting - Config SATA BAR5
98  *
99  *   - Private function
100  *
101  * @param[in] pConfig - Southbridge configuration structure pointer.
102  * @param[in] *pBar5   - SATA BAR5 buffer.
103  *
104  */
105 VOID
106 sataBar5setting (
107   IN       AMDSBCFG*   pConfig,
108   IN       UINT32      *pBar5
109   )
110 {
111   //Get BAR5 value
112   ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG24), AccWidthUint32, pBar5);
113   //Assign temporary BAR if is not already assigned
114   if ( (*pBar5 == 0) || (*pBar5 == - 1) ) {
115     //assign temporary BAR5
116     if ( (pConfig->TempMMIO == 0) || (pConfig->TempMMIO == - 1) ) {
117       *pBar5 = 0xFEC01000;
118     } else {
119       *pBar5 = pConfig->TempMMIO;
120     }
121     WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG24), AccWidthUint32, pBar5);
122   }
123   //Clear Bits 9:0
124   *pBar5 = *pBar5 & 0xFFFFFC00;
125 }
126 #ifdef SATA_BUS_DEV_FUN_FPGA
127 VOID
128 sataBar5settingFpga (
129   IN       AMDSBCFG*   pConfig,
130   IN       UINT32      *pBar5
131   )
132 {
133   UINT8  dbValue;
134   //Get BAR5 value
135   ReadPCI (((SATA_BUS_DEV_FUN_FPGA << 16) + SB_SATA_REG24), AccWidthUint32, pBar5);
136   //Assign temporary BAR if is not already assigned
137   if ( (*pBar5 == 0) || (*pBar5 == - 1) ) {
138     //assign temporary BAR5
139     if ( (pConfig->TempMMIO == 0) || (pConfig->TempMMIO == - 1) ) {
140       *pBar5 = 0xFEC01000;
141     } else {
142       *pBar5 = pConfig->TempMMIO;
143     }
144     WritePCI (((SATA_BUS_DEV_FUN_FPGA << 16) + SB_SATA_REG24), AccWidthUint32, pBar5);
145   }
146   //Clear Bits 9:0
147   *pBar5 = *pBar5 & 0xFFFFFC00;
148   dbValue = 0x07;
149   WritePCI (((SATA_BUS_DEV_FUN_FPGA << 16) + 0x04), AccWidthUint8, &dbValue);
150   WritePCI (((PCIB_BUS_DEV_FUN << 16) + 0x04), AccWidthUint8, &dbValue);
151 }
152 #endif
153 /**
154  * shutdownUnconnectedSataPortClock - Shutdown unconnected Sata port clock
155  *
156  *   - Private function
157  *
158  * @param[in] pConfig Southbridge configuration structure pointer.
159  * @param[in] ddBar5 Sata BAR5 base address.
160  *
161  */
162 VOID
163 shutdownUnconnectedSataPortClock (
164   IN       AMDSBCFG* pConfig,
165   IN       UINT32 ddBar5
166   )
167 {
168   UINT8  dbPortNum;
169   UINT32  ddPortSataStatus;
170   UINT8  cimSataClkAutoOff;
171
172   cimSataClkAutoOff = (UINT8) pConfig->SataClkAutoOff;
173 #if  SB_CIMx_PARAMETER == 0
174   cimSataClkAutoOff = cimSataClkAutoOffDefault;
175 #endif
176   if ( cimSataClkAutoOff == TRUE ) {
177     //ENH225976 Enable SATA auto clock control by default ( (pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE) || (pConfig->SataClass == IDE_TO_AHCI_MODE) ) {
178     for ( dbPortNum = 0; dbPortNum < 8; dbPortNum++ ) {
179       ReadMEM (ddBar5 + SB_SATA_BAR5_REG128 + (dbPortNum * 0x80), AccWidthUint32, &ddPortSataStatus);
180       // Shutdown the clock for the port and do the necessary port reporting changes.
181       // ?? Error port status should be 1 not 3
182       ddPortSataStatus &= 0x00000F0F;
183       if ( (!((ddPortSataStatus == 0x601) || (ddPortSataStatus == 0x201) || (ddPortSataStatus == 0x103))) && (! ((pConfig->SATAESPPORT.SataPortReg) & (1 << dbPortNum))) ) {
184         TRACE ((DMSG_SB_TRACE, "Shutting down clock for SATA port %X \n", dbPortNum));
185         RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 2), AccWidthUint8, 0xFF, (1 << dbPortNum));
186       }
187     }     //end of for (dbPortNum=0;dbPortNum<6;dbPortNum++)
188   }  //end of SataClkAuto Off option
189 }
190
191 /**
192  * CaculateAhciPortNumber - Caculat AHCI Port Number
193  *
194  *   - Private function
195  *
196  * @param[in] pConfig Southbridge configuration structure pointer.
197  * @param[in] ddBar5 Sata BAR5 base address.
198  *
199  */
200 VOID
201 CaculateAhciPortNumber (
202   IN       AMDSBCFG* pConfig,
203   IN       UINT32 ddBar5
204   )
205 {
206   UINT8  dbPortNum;
207   UINT8  dbPortSataStatus;
208   UINT8  NumOfPorts;
209   UINT8  MaxPortNum;
210   NumOfPorts = 0;
211   MaxPortNum = 4;
212   if ( (pConfig->SATAMODE.SataMode.SataIdeCombMdPriSecOpt) == ENABLED ) {
213     MaxPortNum = 6;
214   } else if ( (pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == ENABLED ) {
215     MaxPortNum = 8;
216   }
217   ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 2), AccWidthUint8, &dbPortSataStatus);
218   for ( dbPortNum = 0; dbPortNum < MaxPortNum; dbPortNum++ ) {
219     if ( dbPortSataStatus & (1 << dbPortNum) ) {
220       RWMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, ~(1 << dbPortNum), 00);
221     }
222   }
223   ReadMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, &dbPortSataStatus);
224   //if all ports are in disabled state, report atleast one port
225   if ( (dbPortSataStatus & 0xFF) == 0) {
226     RWMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, (UINT32) ~(0xFF), 01);
227   }
228   ReadMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, &dbPortSataStatus);
229   for (dbPortNum = 0; dbPortNum < MaxPortNum; dbPortNum ++) {
230     if (dbPortSataStatus & (1 << dbPortNum)) {
231       NumOfPorts++;
232     }
233   }
234   if ( NumOfPorts == 0) {
235     NumOfPorts = 0x01;
236   }
237   RWMEM (ddBar5 + SB_SATA_BAR5_REG00, AccWidthUint8, 0xE0, NumOfPorts - 1);
238 }
239
240 /**
241  * sataGpioPorcedure - Sata GPIO function Procedure
242  *
243  *   - Private function
244  *
245  * @param[in] pConfig Southbridge configuration structure pointer.
246  *
247  */
248 VOID
249 sataGpioPorcedure (
250   IN  AMDSBCFG* pConfig
251   )
252 {
253   UINT32  ddBar5;
254   UINT32  ddData;
255   UINT32  eMb;
256   UINT32  ddTempVariable;
257   UINT8  cimSataSgpio0;
258
259   ddBar5 = 0;
260   eMb = 0;
261   cimSataSgpio0 = (UINT8) pConfig->SataSgpio0;
262
263 #if  SB_CIMx_PARAMETER == 0
264   cimSataSgpio0 = cimSataSgpio0Default;
265 #endif
266
267   sataBar5setting (pConfig, &ddBar5);
268   ReadMEM (ddBar5 + SB_SATA_BAR5_REG1C , AccWidthUint32 | S3_SAVE, &ddData);
269   eMb = (ddBar5 + (( ddData & 0xFFFF0000) >> 14));
270   if ( eMb ) {
271     ddTempVariable = 0x03040C00;
272     WriteMEM ( ddBar5 + eMb, AccWidthUint32 | S3_SAVE, &ddTempVariable);
273     ddTempVariable = 0x00C08240;
274     WriteMEM ( ddBar5 + eMb + 4, AccWidthUint32 | S3_SAVE, &ddTempVariable);
275     ddTempVariable = 0x00000001;
276     WriteMEM ( ddBar5 + eMb + 8, AccWidthUint32 | S3_SAVE, &ddTempVariable);
277     if ( cimSataSgpio0 ) {
278       ddTempVariable = 0x00000060;
279     } else {
280       ddTempVariable = 0x00000061;
281     }
282     WriteMEM ( ddBar5 + eMb + 0x0C, AccWidthUint32 | S3_SAVE, &ddTempVariable);
283
284     RWMEM ((ddBar5 + SB_SATA_BAR5_REG20), AccWidthUint16 | S3_SAVE, ~(BIT8), BIT8);
285     do {
286       ReadMEM (ddBar5 + SB_SATA_BAR5_REG20 , AccWidthUint32 | S3_SAVE, &ddData);
287       ddData = ddData & BIT8;
288     } while ( ddData != 0 );
289
290     ddTempVariable = 0x03040F00;
291     WriteMEM ( ddBar5 + eMb, AccWidthUint32 | S3_SAVE, &ddTempVariable);
292     ddTempVariable = 0x00008240;
293     WriteMEM ( ddBar5 + eMb + 4, AccWidthUint32 | S3_SAVE, &ddTempVariable);
294     ddTempVariable = 0x00000002;
295     WriteMEM ( ddBar5 + eMb + 8, AccWidthUint32 | S3_SAVE, &ddTempVariable);
296     ddTempVariable = 0x00800000;
297     WriteMEM ( ddBar5 + eMb + 0x0C, AccWidthUint32 | S3_SAVE, &ddTempVariable);
298     ddTempVariable = 0x0F003700;
299     WriteMEM ( ddBar5 + eMb + 0x0C, AccWidthUint32 | S3_SAVE, &ddTempVariable);
300     RWMEM ((ddBar5 + SB_SATA_BAR5_REG20), AccWidthUint16 | S3_SAVE, ~(BIT8), BIT8);
301     do {
302       ReadMEM (ddBar5 + SB_SATA_BAR5_REG20 , AccWidthUint32 | S3_SAVE, &ddData);
303       ddData = ddData & BIT8;
304     } while ( ddData != 0 );
305   }
306 }
307
308
309 /**
310  * Table for class code of SATA Controller in different modes
311  *
312  *
313  *
314  *
315  */
316 UINT32 sataIfCodeTable[] =
317 {
318   0x01018F40, //sata class ID of IDE
319   0x01040040, //sata class ID of RAID
320   0x01060140, //sata class ID of AHCI
321   0x01018A40, //sata class ID of Legacy IDE
322   0x01018F40, //sata class ID of IDE to AHCI mode
323 };
324
325 /**
326  * Table for device id of SATA Controller in different modes
327  *
328  *
329  *
330  *
331  */
332
333 UINT16 sataDeviceIDTable[] =
334 {
335   SB_SATA_DID,  //sata device ID of IDE
336   SB_SATA_RAID_DID,  //sata device ID of RAID
337   SB_SATA_AHCI_DID,  //sata class ID of AHCI
338   SB_SATA_DID,  //sata device ID of Legacy IDE
339   SB_SATA_DID,  //sata device ID of IDE->AHCI mode
340 };
341
342 /**
343  * Table for Sata Phy Fine Setting
344  *
345  *
346  *
347  *
348  */
349 SATAPHYSETTING sataPhyTable[] =
350 {
351   //Gen3
352   {0x0030, 0x0057A607},
353   {0x0031, 0x0057A607},
354   {0x0032, 0x0057A407},
355   {0x0033, 0x0057A407},
356   {0x0034, 0x0057A607},
357   {0x0035, 0x0057A607},
358   {0x0036, 0x0057A403},
359   {0x0037, 0x0057A403},
360
361   //Gen2
362   {0x0120, 0x00071302},
363
364   //Gen1
365   {0x0110, 0x00174101}
366 };
367
368 /**
369  * sataInitBeforePciEnum - Config SATA controller before PCI emulation
370  *
371  *
372  *
373  * @param[in] pConfig Southbridge configuration structure pointer.
374  *
375  */
376 VOID
377 sataInitBeforePciEnum (
378   IN       AMDSBCFG*   pConfig
379   )
380 {
381   UINT32  ddTempVar;
382   UINT32  ddValue;
383   UINT32  *tempptr;
384   UINT16  *pDeviceIdptr;
385   UINT32  dwDeviceId;
386   UINT8   dbValue;
387   UINT8   pValue;
388   UINT8   dbChannel;
389   UINT16    i;
390   SATAPHYSETTING  *pPhyTable;
391
392   pConfig->SATAPORTPOWER.SataPortPowerReg = \
393     + pConfig->SATAPORTPOWER.SataPortPower.PORT0 \
394     + (pConfig->SATAPORTPOWER.SataPortPower.PORT1 << 1) \
395     + (pConfig->SATAPORTPOWER.SataPortPower.PORT2 << 2) \
396     + (pConfig->SATAPORTPOWER.SataPortPower.PORT3 << 3) \
397     + (pConfig->SATAPORTPOWER.SataPortPower.PORT4 << 4) \
398     + (pConfig->SATAPORTPOWER.SataPortPower.PORT5 << 5) \
399     + (pConfig->SATAPORTPOWER.SataPortPower.PORT6 << 6) \
400     + (pConfig->SATAPORTPOWER.SataPortPower.PORT7 << 7);
401   // BIT0 Enable write access to PCI header (reg 08h-0Bh) by setting SATA PCI register 40h
402   // BIT4:disable fast boot //?
403   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, 0xff, BIT0 + BIT4);
404   // BIT0 Enable write access to PCI header (reg 08h-0Bh) by setting IDE PCI register 40h
405   RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG40), AccWidthUint8 | S3_SAVE, 0xff, BIT0);
406   // RPR Enable IDE DMA read enhancement
407   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48 + 3), AccWidthUint8 | S3_SAVE, 0xff, BIT7);
408   // RPR Unused SATA Ports Disabled
409   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 2), AccWidthUint8 | S3_SAVE, 0, pConfig->SATAPORTPOWER.SataPortPowerReg);
410   dbValue = (UINT8)pConfig->SataClass;
411   if (dbValue == AHCI_MODE_7804) {
412     dbValue = AHCI_MODE;
413   }
414   if (dbValue == IDE_TO_AHCI_MODE_7804) {
415     dbValue = IDE_TO_AHCI_MODE;
416   }
417   // Disable PATA MSI
418   RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG34), AccWidthUint8 | S3_SAVE, 0x00, 0x00);
419   RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG06), AccWidthUint8 | S3_SAVE, 0xEF, 0x00);
420
421   if ( (pConfig->SataClass == 3) | (pConfig->SataClass == 0)) {
422     dbChannel = 0x00;
423     ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48 + 3), AccWidthUint8, &dbChannel);
424     dbChannel &= 0xCF;
425     if ( pConfig->SataDisUnusedIdePChannel ) {
426       dbChannel |= 0x10;
427     }
428     if ( pConfig->SataDisUnusedIdeSChannel ) {
429       dbChannel |= 0x20;
430     }
431     WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48 + 3), AccWidthUint8, &dbChannel);
432   }
433
434   if ((pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == DISABLED ) {
435     ReadPCI (((IDE_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 11), AccWidthUint8, &dbChannel);
436     dbChannel &= 0xCF;
437     if ( pConfig->IdeDisUnusedIdePChannel ) {
438       dbChannel |= 0x10;
439     }
440     if ( pConfig->IdeDisUnusedIdeSChannel ) {
441       dbChannel |= 0x20;
442     }
443     WritePCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG40 + 11), AccWidthUint8, &dbChannel);
444   }
445   // Get the appropriate class code from the table and write it to PCI register 08h-0Bh
446   // Set the appropriate SATA class based on the input parameters
447   // SATA IDE Controller Class ID & SSID
448   tempptr = (UINT32 *) FIXUP_PTR (&sataIfCodeTable[0]);
449   if ( (pConfig->SataIdeMode == 1) && (pConfig->SataClass != 3) ) {
450     ddValue = tempptr[0];
451     // Write the class code to IDE PCI register 08h-0Bh
452     RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG08), AccWidthUint32 | S3_SAVE, 0, ddValue);
453   }
454   ddValue = tempptr[dbValue];
455   // Write the class code to SATA PCI register 08h-0Bh
456   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG08), AccWidthUint32 | S3_SAVE, 0, ddValue);
457   if ( pConfig->SataClass == LEGACY_IDE_MODE ) {
458     //Set PATA controller to native mode
459     RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG09), AccWidthUint8 | S3_SAVE, 0x00, 0x08F);
460   }
461   if (pConfig->BuildParameters.IdeSsid != NULL ) {
462     RWPCI ((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG2C, AccWidthUint32 | S3_SAVE, 0x00, pConfig->BuildParameters.IdeSsid);
463   }
464   // SATA Controller Class ID & SSID
465   pDeviceIdptr = (UINT16 *) FIXUP_PTR (&sataDeviceIDTable[0]);
466   ddTempVar = pConfig->BuildParameters.SataIDESsid;
467   dwDeviceId = pDeviceIdptr[dbValue];
468   if ( pConfig->SataClass == RAID_MODE) {
469     ddTempVar = pConfig->BuildParameters.SataRAID5Ssid;
470     dwDeviceId = SB_SATA_RAID5_DID;
471     pValue = SATA_EFUSE_LOCATION;
472     getEfuseStatus (&pValue);
473     if (( pValue & SATA_EFUSE_BIT ) || ( pConfig->SataForceRaid == 1 )) {
474       dwDeviceId = SB_SATA_RAID_DID;
475       ddTempVar = pConfig->BuildParameters.SataRAIDSsid;
476     }
477   }
478   if ( ((pConfig->SataClass) == AHCI_MODE) || ((pConfig->SataClass) == IDE_TO_AHCI_MODE) ||
479     ((pConfig->SataClass) == AHCI_MODE_7804) || ((pConfig->SataClass) == IDE_TO_AHCI_MODE_7804) ) {
480     ddTempVar = pConfig->BuildParameters.SataAHCISsid;
481   }
482   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, 0, dwDeviceId);
483   RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG2C, AccWidthUint32 | S3_SAVE, 0x00, ddTempVar);
484
485   // SATA IRQ Resource
486   sataSetIrqIntResource (pConfig);
487
488   // RPR 9.5 SATA PHY Programming Sequence
489   pPhyTable = (SATAPHYSETTING*)FIXUP_PTR (&sataPhyTable[0]);
490   for (i = 0; i < (sizeof (sataPhyTable) / sizeof (SATAPHYSETTING)); i++) {
491     RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG80, AccWidthUint16 | S3_SAVE, 0x00, pPhyTable->wPhyCoreControl);
492     RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG98, AccWidthUint32 | S3_SAVE, 0x00, pPhyTable->dwPhyFineTune);
493     ++pPhyTable;
494   }
495   RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG80, AccWidthUint16 | S3_SAVE, 0x00, 0x110);
496   RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG9C, AccWidthUint32 | S3_SAVE, (UINT32) (~(0x7 << 4)), (UINT32) (0x2 << 4));
497   RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG80, AccWidthUint16 | S3_SAVE, 0x00, 0x10);
498
499   RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0);
500   // Disable write access to PCI header
501   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0);
502   if ( IsSbA12Plus () ) {
503     //SATA PCI Config 0x4C[31:26] program 111111b (six 1's)
504     //SATA PCI Config 0x48[11] program 1
505     //SATA PCI Config 0x84[31] program 0
506     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG4C), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x3f << 26)), (UINT32) (0x3f << 26));
507     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x01 << 11)), (UINT32) (0x01 << 11));
508     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG84), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x01 << 31)), (UINT32) (0x00 << 31));
509   }
510
511   //SATA PCI config register 0x4C [20] =1
512   //SATA PCI config register 0x4C [21] =1
513   //SATA PCI config register 0x4C [18] =1
514   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG4C), AccWidthUint32 | S3_SAVE, ~ (BIT18 + BIT20 + BIT21), (BIT18 + BIT20 + BIT21));
515 }
516
517 /**
518  * sataInitAfterPciEnum - Config SATA controller after PCI emulation
519  *
520  *
521  *
522  * @param[in] pConfig Southbridge configuration structure pointer.
523  *
524  */
525 VOID
526 sataInitAfterPciEnum (
527   IN       AMDSBCFG* pConfig
528   )
529 {
530   UINT32  ddAndMask;
531   UINT32  ddOrMask;
532   UINT32  ddBar5;
533   UINT8  dbVar;
534   UINT8  dbPortNum;
535   UINT8  dbEfuse;
536   UINT8  dbPortMode;
537   UINT16  SataPortMode;
538   UINT8  cimSataAggrLinkPmCap;
539   UINT8  cimSataPortMultCap;
540   UINT8  cimSataPscCap;
541   UINT8  cimSataSscCap;
542   UINT8  cimSataFisBasedSwitching;
543   UINT8  cimSataCccSupport;
544   UINT8  cimSataMsiCapability;
545   UINT8  cimSataTargetSupport8Device;
546   UINT8  cimSataDisableGenericMode;
547   UINT8  cimSataAhciEnclosureManagement;
548   UINT8  cimSataSgpio0;
549   UINT8  cimSataSgpio1;
550   UINT8  cimSataHotRemovelEnh;
551   UINT8  cimSataPhyPllShutDown;
552   UINT8  dbCccInt;
553
554   cimSataAggrLinkPmCap = (UINT8) pConfig->SataAggrLinkPmCap;
555   cimSataPortMultCap = (UINT8) pConfig->SataPortMultCap;
556   cimSataPscCap = (UINT8) pConfig->SataPscCap;
557   cimSataSscCap = (UINT8) pConfig->SataSscCap;
558   cimSataFisBasedSwitching = (UINT8) pConfig->SataFisBasedSwitching;
559   cimSataCccSupport = (UINT8) pConfig->SataCccSupport;
560   cimSataMsiCapability = (UINT8) pConfig->SataMsiCapability;
561   cimSataTargetSupport8Device = (UINT8) pConfig->SataTargetSupport8Device;
562   cimSataDisableGenericMode = (UINT8) pConfig->SataDisableGenericMode;
563   cimSataAhciEnclosureManagement = (UINT8) pConfig->SataAhciEnclosureManagement;
564   cimSataSgpio0 = (UINT8) pConfig->SataSgpio0;
565   cimSataSgpio1 = (UINT8) pConfig->SataSgpio1;
566   cimSataHotRemovelEnh = (UINT8) pConfig->SataHotRemoveEnh;
567   cimSataPhyPllShutDown = (UINT8) pConfig->SataPhyPllShutDown;
568
569 #if  SB_CIMx_PARAMETER == 0
570   cimSataAggrLinkPmCap = cimSataAggrLinkPmCapDefault;
571   cimSataPortMultCap = cimSataPortMultCapDefault;
572   cimSataPscCap = cimSataPscCapDefault;
573   cimSataSscCap = cimSataSscCapDefault;
574   cimSataFisBasedSwitching = cimSataFisBasedSwitchingDefault;
575   cimSataCccSupport = cimSataCccSupportDefault;
576   cimSataMsiCapability = cimSataMsiCapabilityDefault;
577   cimSataTargetSupport8Device = cimSataTargetSupport8DeviceDefault;
578   cimSataDisableGenericMode = cimSataDisableGenericModeDefault;
579   cimSataAhciEnclosureManagement = cimSataAhciEnclosureManagementDefault;
580   cimSataSgpio0 = cimSataSgpio0Default;
581   cimSataSgpio1 = cimSataSgpio1Default;
582   cimSataHotRemovelEnh = cimSataHotRemoveEnhDefault;
583   cimSataPhyPllShutDown = cimSataPhyPllShutDownDefault;
584 #endif
585
586   ddAndMask = 0;
587   ddOrMask = 0;
588   ddBar5 = 0;
589   if ( pConfig->SATAMODE.SataMode.SataController == 0 ) {
590     return;   //return if SATA controller is disabled.
591   }
592
593   //Enable write access to pci header, pm capabilities
594   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, 0xFF, BIT0);
595
596   sataBar5setting (pConfig, &ddBar5);
597
598   ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar);
599   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, 0xFF, 0x03);   //memory and io access enable
600   dbEfuse = SATA_FIS_BASE_EFUSE_LOC;
601   getEfuseStatus (&dbEfuse);
602
603   if ( !cimSataPortMultCap ) {
604     ddAndMask |= BIT12;
605   }
606   if ( cimSataAggrLinkPmCap ) {
607     ddOrMask |= BIT11;
608   } else {
609     ddAndMask |= BIT11;
610   }
611   if ( cimSataPscCap ) {
612     ddOrMask |= BIT1;
613   } else {
614     ddAndMask |= BIT1;
615   }
616   if ( cimSataSscCap ) {
617     ddOrMask |= BIT26;
618   } else {
619     ddAndMask |= BIT26;
620   }
621   if ( cimSataFisBasedSwitching ) {
622     if (dbEfuse & BIT1) {
623       ddAndMask |= BIT10;
624     } else {
625       ddOrMask |= BIT10;
626     }
627   } else {
628     ddAndMask |= BIT10;
629   }
630   // RPR 8.10 Disabling CCC (Command Completion Coalescing) support.
631   if ( cimSataCccSupport ) {
632     ddOrMask |= BIT19;
633   } else {
634     ddAndMask |= BIT19;
635   }
636   if ( cimSataAhciEnclosureManagement ) {
637     ddOrMask |= BIT27;
638   } else {
639     ddAndMask |= BIT27;
640   }
641   RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint32 | S3_SAVE, ~ddAndMask, ddOrMask);
642
643
644   // SATA ESP port setting
645   // These config bits are set for SATA driver to identify which ports are external SATA ports and need to
646   // support hotplug. If a port is set as an external SATA port and need to support hotplug, then driver will
647   // not enable power management (HIPM & DIPM) for these ports.
648   pConfig->SATAESPPORT.SataPortReg = \
649     + pConfig->SATAESPPORT.SataEspPort.PORT0 \
650     + (pConfig->SATAESPPORT.SataEspPort.PORT1 << 1) \
651     + (pConfig->SATAESPPORT.SataEspPort.PORT2 << 2) \
652     + (pConfig->SATAESPPORT.SataEspPort.PORT3 << 3) \
653     + (pConfig->SATAESPPORT.SataEspPort.PORT4 << 4) \
654     + (pConfig->SATAESPPORT.SataEspPort.PORT5 << 5) \
655     + (pConfig->SATAESPPORT.SataEspPort.PORT6 << 6) \
656     + (pConfig->SATAESPPORT.SataEspPort.PORT7 << 7);
657   if ( pConfig->SATAESPPORT.SataPortReg != 0 ) {
658     RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, ~(pConfig->SATAESPPORT.SataPortReg), 0);
659     RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, 0xFF00FF00, (pConfig->SATAESPPORT.SataPortReg << 16));
660     // RPR 8.7 External SATA Port Indication Registers
661     // If any of the ports was programmed as an external port, HCAP.SXS should also be set
662     RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint32 | S3_SAVE, ~(BIT20), BIT20);
663   } else {
664     // RPR 8.7 External SATA Port Indication Registers
665     // If any of the ports was programmed as an external port, HCAP.SXS should also be set (Clear for no ESP port)
666     RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, 0xFF00FF00, 0x00);
667     RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint32 | S3_SAVE, ~(BIT20), 0x00);
668   }
669
670   if ( cimSataFisBasedSwitching ) {
671     if (dbEfuse & BIT1) {
672       RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, 0x00FFFFFF, 0x00);
673     } else {
674       RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, 0x00FFFFFF, 0xFF000000);
675     }
676   } else {
677     RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, 0x00FFFFFF, 0x00);
678   }
679
680   //SB02712 Turn off MSI for SATA IDE mode.
681   if ((pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE)) {
682     cimSataMsiCapability = 0;
683   }
684   //Enabled SATA MSI capability
685   // RPR 8.11 SATA MSI and D3 Power State Capability
686   if (IsSbA12Plus ()) {
687     if ( cimSataMsiCapability ) {
688       RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG34), AccWidthUint8 | S3_SAVE, 0, 0x50);
689     } else {
690       RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG34), AccWidthUint8 | S3_SAVE, 0, 0x70);
691     }
692   } else {
693     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG34), AccWidthUint8 | S3_SAVE, 0, 0x70);
694   }
695
696   if (((pConfig->SataClass) != NATIVE_IDE_MODE) && ((pConfig->SataClass) != LEGACY_IDE_MODE)) {
697     // RIAD or AHCI
698     if ((pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == DISABLED) {
699       // IDE2 Controller is enabled
700       if ((pConfig->SATAMODE.SataMode.SataIdeCombMdPriSecOpt) == ENABLED) {
701         // 6 AHCI mode
702         RWMEM ((ddBar5 + SB_SATA_BAR5_REG0C), AccWidthUint8 | S3_SAVE, 0x00, 0x3F);
703         RWMEM ((ddBar5 + SB_SATA_BAR5_REG00), AccWidthUint8 | S3_SAVE, ~(BIT2 + BIT1 + BIT0), BIT2 + BIT0);
704         RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2 + BIT1);
705         RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint8, 0x07, 0x30);
706       } else {
707         RWMEM ((ddBar5 + SB_SATA_BAR5_REG0C), AccWidthUint8 | S3_SAVE, 0x00, 0x0F);
708         if ( pConfig->SataCccSupport ) {
709           RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2 + BIT1);
710         } else {
711           RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2);
712         }
713       }
714     } else {
715       // IDE2 Controller is disabled
716       RWMEM ((ddBar5 + SB_SATA_BAR5_REG00), AccWidthUint8 | S3_SAVE, ~(BIT2 + BIT1 + BIT0), BIT2 + BIT1 + BIT0);
717       RWMEM ((ddBar5 + SB_SATA_BAR5_REG0C), AccWidthUint8 | S3_SAVE, 0x00, 0xFF);
718       if ( pConfig->SataCccSupport ) {
719         RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT3);
720       } else {
721         RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2 + BIT1);
722       }
723     }
724   }
725   if ( pConfig->BIOSOSHandoff == 1 ) {
726     RWMEM ((ddBar5 + SB_SATA_BAR5_REG24), AccWidthUint8 | S3_SAVE, ~BIT0, BIT0);
727   } else {
728     RWMEM ((ddBar5 + SB_SATA_BAR5_REG24), AccWidthUint8 | S3_SAVE, ~BIT0, 0x00);
729   }
730   pConfig->SATAPORTMODE.SataPortMode = \
731     pConfig->SATAPORTMODE.SataPortMd.PORT0 \
732     + (pConfig->SATAPORTMODE.SataPortMd.PORT1 << 2) \
733     + (pConfig->SATAPORTMODE.SataPortMd.PORT2 << 4) \
734     + (pConfig->SATAPORTMODE.SataPortMd.PORT3 << 6) \
735     + (pConfig->SATAPORTMODE.SataPortMd.PORT4 << 8) \
736     + (pConfig->SATAPORTMODE.SataPortMd.PORT5 << 10) \
737     + (pConfig->SATAPORTMODE.SataPortMd.PORT6 << 12) \
738     + (pConfig->SATAPORTMODE.SataPortMd.PORT7 << 14);
739   SataPortMode = (UINT16)pConfig->SATAPORTMODE.SataPortMode;
740   dbPortNum = 0;
741
742   while ( dbPortNum < 8 ) {
743     dbPortMode = (UINT8) (SataPortMode & 3);
744     if ( (dbPortMode == BIT0) || (dbPortMode == BIT1) ) {
745       if ( dbPortMode == BIT0 ) {
746         // set GEN 1
747         RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0x0F, 0x10);
748       }
749       if ( dbPortMode == BIT1 ) {
750         // set GEN2 (default is GEN3)
751         RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0x0F, 0x20);
752       }
753       RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFF, 0x01);
754       cimSbStall (1000);
755       RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFE, 0x00);
756     }
757     SataPortMode >>= 2;
758     dbPortNum ++;
759   }
760   SbStall (1000);
761   SataPortMode = (UINT16)pConfig->SATAPORTMODE.SataPortMode;
762   dbPortNum = 0;
763
764   while ( dbPortNum < 8 ) {
765     dbPortMode = (UINT8) (SataPortMode & 3);
766     if ( (dbPortMode == BIT0) || (dbPortMode == BIT1) ) {
767       RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFE, 0x00);
768     }
769     dbPortNum ++;
770     SataPortMode >>= 2;
771   }
772
773   if ( cimSataTargetSupport8Device ) {
774     RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint16, ~BIT12, BIT12);
775   } else {
776     RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint16, ~BIT12, 0x00);
777   }
778
779   if ( cimSataDisableGenericMode ) {
780     RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint16, ~BIT13, BIT13);
781   } else {
782     RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint16, ~BIT13, 0x00);
783   }
784   // 9.19 Optionally Disable Hot-removal Detection Enhancement
785   if ( cimSataHotRemovelEnh ) {
786     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG80), AccWidthUint16 | S3_SAVE, ~BIT8, BIT8 );
787     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REGA8), AccWidthUint16 | S3_SAVE, ~BIT0, BIT0);
788     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG80), AccWidthUint16 | S3_SAVE, ~BIT8, 0 );
789   }
790   if ( cimSataSgpio0 ) {
791     sataGpioPorcedure (pConfig);
792   }
793   if ( cimSataSgpio1 ) {
794     sataGpioPorcedure (pConfig);
795   }
796   if ( IsSbA11 () ) {
797     if ( cimSataPhyPllShutDown ) {
798       RWPCI (((SATA_BUS_DEV_FUN << 16) + 0x87), AccWidthUint8 | S3_SAVE, ~(BIT6 + BIT7), BIT6 + BIT7);
799     } else {
800       RWPCI (((SATA_BUS_DEV_FUN << 16) + 0x87), AccWidthUint8 | S3_SAVE, ~(BIT6 + BIT7), 0x00);
801     }
802   } else {
803     if ( cimSataPhyPllShutDown ) {
804       RWPCI (((SATA_BUS_DEV_FUN << 16) + 0x87), AccWidthUint8 | S3_SAVE, ~(BIT6), BIT6);
805     } else {
806       RWPCI (((SATA_BUS_DEV_FUN << 16) + 0x87), AccWidthUint8 | S3_SAVE, ~(BIT6), 0x00);
807     }
808   }
809   if ( IsSbA12Plus () ) {
810     //SATA PCI Config 0x4C[31:26] program 111111b (six 1's)
811     //SATA PCI Config 0x48[11] program 1
812     //SATA PCI Config 0x84[31] program 0
813     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG4C), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x3f << 26)), (UINT32) (0x3f << 26));
814     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x01 << 11)), (UINT32) (0x01 << 11));
815     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG84), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x01 << 31)), (UINT32) (0x00 << 31));
816   }
817   // RPR 9.18 CCC Interrupt
818   dbCccInt = 4;
819   if ((pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == DISABLED) {
820     if ((pConfig->SATAMODE.SataMode.SataIdeCombMdPriSecOpt) == ENABLED) {
821       dbCccInt = 6;
822     }
823   } else {
824     dbCccInt = 8;
825   }
826   RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint8, 0x07, (dbCccInt << 3));
827
828   shutdownUnconnectedSataPortClock (pConfig, ddBar5);
829
830   WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar);
831
832   // RPR 9.13 Disable SATA FLR Capability
833   // SATA_PCI_config 0x70 [15:8] = 0x00
834   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG70), AccWidthUint32 | S3_SAVE, 0xFFFF00FF, 0x00);
835   //Disable write access to pci header, pm capabilities
836   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0);
837 }
838
839
840 /**
841  * sataInitMidPost - Config SATA controller in Middle POST.
842  *
843  *
844  *
845  * @param[in] pConfig Southbridge configuration structure pointer.
846  *
847  */
848 VOID
849 sataInitMidPost (
850   IN       AMDSBCFG* pConfig
851   )
852 {
853   UINT32   ddBar5;
854   sataBar5setting (pConfig, &ddBar5);
855   //If this is not S3 resume and also if SATA set to one of IDE mode, them implement drive detection workaround.
856   if ( ! (pConfig->S3Resume) && ( ((pConfig->SataClass) != AHCI_MODE)  && ((pConfig->SataClass) != RAID_MODE) ) ) {
857     sataDriveDetection (pConfig, &ddBar5);
858   }
859 #ifdef SATA_BUS_DEV_FUN_FPGA
860   sataBar5settingFpga (pConfig, &ddBar5);
861   sataDriveDetectionFpga (pConfig, &ddBar5);
862 #endif
863 }
864
865 /**
866  * sataDriveDetection - Sata drive detection
867  *
868  *
869  * @param[in] pConfig Southbridge configuration structure pointer.
870  * @param[in] *pBar5 Sata BAR5 base address.
871  *
872  */
873 VOID
874 sataDriveDetection (
875   IN       AMDSBCFG* pConfig,
876   IN       UINT32 *pBar5
877   )
878 {
879   UINT32   ddVar0;
880   UINT8   dbPortNum;
881   UINT8   dbVar0;
882   UINT16   dwIoBase;
883   UINT32   ddVar1;
884   TRACE ((DMSG_SB_TRACE, "CIMx - Entering sata drive detection procedure\n\n"));
885   TRACE ((DMSG_SB_TRACE, "SATA BAR5 is %X \n", *pBar5));
886   if ( (pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE) || (pConfig->SataClass == IDE_TO_AHCI_MODE) ) {
887     for ( dbPortNum = 0; dbPortNum < 4; dbPortNum++ ) {
888       ReadMEM (*pBar5 + SB_SATA_BAR5_REG128 + dbPortNum * 0x80, AccWidthUint32, &ddVar0);
889       if ( ( ddVar0 & 0x0F ) == 0x03 ) {
890         if ( dbPortNum & BIT0 ) {
891           //this port belongs to secondary channel
892           ReadPCI (((UINT32) (SATA_BUS_DEV_FUN << 16) + SB_SATA_REG18), AccWidthUint16, &dwIoBase);
893         } else {
894           //this port belongs to primary channel
895           ReadPCI (((UINT32) (SATA_BUS_DEV_FUN << 16) + SB_SATA_REG10), AccWidthUint16, &dwIoBase);
896         }
897         //if legacy ide mode, then the bar registers don't contain the correct values. So we need to hardcode them
898         if ( pConfig->SataClass == LEGACY_IDE_MODE ) {
899           dwIoBase = ( (0x170) | ((UINT16) ( (~((UINT8) (dbPortNum & BIT0) << 7)) & 0x80 )) );
900         }
901         if ( dbPortNum & BIT1 ) {
902           //this port is slave
903           dbVar0 = 0xB0;
904         } else {
905           //this port is master
906           dbVar0 = 0xA0;
907         }
908         dwIoBase &= 0xFFF8;
909         WriteIO (dwIoBase + 6, AccWidthUint8, &dbVar0);
910         //Wait in loop for 30s for the drive to become ready
911         for ( ddVar1 = 0; ddVar1 < 300000; ddVar1++ ) {
912           ReadIO (dwIoBase + 7, AccWidthUint8, &dbVar0);
913           if ( (dbVar0 & 0x88) == 0 ) {
914             break;
915           }
916           SbStall (100);
917         }
918       } //end of if ( ( ddVar0 & 0x0F ) == 0x03)
919     } //for (dbPortNum = 0; dbPortNum < 4; dbPortNum++)
920   } //if ( (pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE) || (pConfig->SataClass == IDE_TO_AHCI_MODE))
921 }
922
923 #ifdef SATA_BUS_DEV_FUN_FPGA
924 VOID
925 sataDriveDetectionFpga (
926   IN       AMDSBCFG* pConfig,
927   IN       UINT32 *pBar5
928   )
929 {
930   UINT32   ddVar0;
931   UINT8   dbPortNum;
932   UINT8   dbVar0;
933   UINT16   dwIoBase;
934   UINT32   ddVar1;
935   TRACE ((DMSG_SB_TRACE, "CIMx - Entering sata drive detection procedure\n\n"));
936   TRACE ((DMSG_SB_TRACE, "SATA BAR5 is %X \n", *pBar5));
937   for ( dbPortNum = 0; dbPortNum < 4; dbPortNum++ ) {
938     ReadMEM (*pBar5 + SB_SATA_BAR5_REG128 + dbPortNum * 0x80, AccWidthUint32, &ddVar0);
939     if ( ( ddVar0 & 0x0F ) == 0x03 ) {
940       if ( dbPortNum & BIT0 ) {
941         //this port belongs to secondary channel
942         ReadPCI (((UINT32) (SATA_BUS_DEV_FUN_FPGA << 16) + SB_SATA_REG18), AccWidthUint16, &dwIoBase);
943       } else {
944         //this port belongs to primary channel
945         ReadPCI (((UINT32) (SATA_BUS_DEV_FUN_FPGA << 16) + SB_SATA_REG10), AccWidthUint16, &dwIoBase);
946       }
947       //if legacy ide mode, then the bar registers don't contain the correct values. So we need to hardcode them
948       if ( pConfig->SataClass == LEGACY_IDE_MODE ) {
949         dwIoBase = ( (0x170) | ((UINT16) ( (~((UINT8) (dbPortNum & BIT0) << 7)) & 0x80 )) );
950       }
951       if ( dbPortNum & BIT1 ) {
952         //this port is slave
953         dbVar0 = 0xB0;
954       } else {
955         //this port is master
956         dbVar0 = 0xA0;
957       }
958       dwIoBase &= 0xFFF8;
959       WriteIO (dwIoBase + 6, AccWidthUint8, &dbVar0);
960       //Wait in loop for 30s for the drive to become ready
961       for ( ddVar1 = 0; ddVar1 < 300000; ddVar1++ ) {
962         ReadIO (dwIoBase + 7, AccWidthUint8, &dbVar0);
963         if ( (dbVar0 & 0x88) == 0 ) {
964           break;
965         }
966         SbStall (100);
967       }
968     } //end of if ( ( ddVar0 & 0x0F ) == 0x03)
969   } //for (dbPortNum = 0; dbPortNum < 4; dbPortNum++)
970 }
971 #endif
972
973 /**
974  * sataInitLatePost - Prepare SATA controller to boot to OS.
975  *
976  *              - Set class ID to AHCI (if set to AHCI * Mode)
977  *              - Enable AHCI interrupt
978  *
979  * @param[in] pConfig Southbridge configuration structure pointer.
980  *
981  */
982 VOID
983 sataInitLatePost (
984   IN       AMDSBCFG* pConfig
985   )
986 {
987   UINT32  ddBar5;
988   UINT8  dbVar;
989   UINT8  dbPortNum;
990
991   //Return immediately is sata controller is not enabled
992   if ( pConfig->SATAMODE.SataMode.SataController == 0 ) {
993     return;
994   }
995   //Enable write access to pci header, pm capabilities
996   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, 0xff, BIT0);
997
998   sataBar5setting (pConfig, &ddBar5);
999
1000   ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar);
1001   //Enable memory and io access
1002   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, 0xFF, 0x03);
1003
1004   if (( pConfig->SataClass == IDE_TO_AHCI_MODE) || ( pConfig->SataClass == IDE_TO_AHCI_MODE_7804 )) {
1005     //program the AHCI class code
1006     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG08), AccWidthUint32 | S3_SAVE, 0, 0x01060100);
1007     //Set interrupt enable bit
1008     RWMEM ((ddBar5 + 0x04), AccWidthUint8, (UINT32)~0, BIT1);
1009     //program the correct device id for AHCI mode
1010     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, 0, SB_SATA_AHCI_DID);
1011   }
1012
1013   if (( pConfig->SataClass == AHCI_MODE_7804 ) || ( pConfig->SataClass == IDE_TO_AHCI_MODE_7804 )) {
1014     //program the correct device id for AHCI 7804 mode
1015     RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, 0, SB_SATA_AMDAHCI_DID);
1016   }
1017   // OBS236459 IDE controller not shown in device manager when Os installed on IDE mode port
1018   //if ( pConfig->SataClass == IDE_TO_AHCI_MODE_7804 ) {
1019     //Disable IDE2 and Enable 8 channel for IDE-AHCI mode
1020     //RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint8, ~BIT1, BIT3);
1021   //}
1022
1023   //Clear error status
1024   RWMEM ((ddBar5 + SB_SATA_BAR5_REG130), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1025   RWMEM ((ddBar5 + SB_SATA_BAR5_REG1B0), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1026   RWMEM ((ddBar5 + SB_SATA_BAR5_REG230), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1027   RWMEM ((ddBar5 + SB_SATA_BAR5_REG2B0), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1028   RWMEM ((ddBar5 + SB_SATA_BAR5_REG330), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1029   RWMEM ((ddBar5 + SB_SATA_BAR5_REG3B0), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1030   RWMEM ((ddBar5 + SB_SATA_BAR5_REG430), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1031   RWMEM ((ddBar5 + SB_SATA_BAR5_REG4B0), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1032   CaculateAhciPortNumber (pConfig, ddBar5);
1033   //Restore memory and io access bits
1034   WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar );
1035   //Disable write access to pci header and pm capabilities
1036   RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0);
1037   for ( dbPortNum = 0; dbPortNum < 6; dbPortNum++ ) {
1038     RWMEM ((ddBar5 + 0x110 + (dbPortNum * 0x80)), AccWidthUint32, 0xFFFFFFFF, 0x00);
1039   }
1040 }
1041
1042