SB700 southbridge: AMD SB700/SP5100 southbridge CIMX code
[coreboot.git] / src / vendorcode / amd / cimx / sb700 / SATA.c
1 /*****************************************************************************
2  *
3  * Copyright (C) 2012 Advanced Micro Devices, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *     * Redistributions of source code must retain the above copyright
9  *       notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above copyright
11  *       notice, this list of conditions and the following disclaimer in the
12  *       documentation and/or other materials provided with the distribution.
13  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of
14  *       its contributors may be used to endorse or promote products derived
15  *       from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  *
29  ***************************************************************************/
30
31
32 #include        "Platform.h"
33
34 //Table for class code of SATA Controller in different modes
35 UINT32 sataIfCodeTable[] = {
36         0x01018f00,     //sata class ID of IDE
37         0x01040000,     //sata class ID of RAID
38         0x01060100,     //sata class ID of AHCI
39         0x01018a00,     //sata class ID of Legacy IDE
40         0x01018f00,     //sata class ID of IDE to AHCI mode
41         0x01060100,     //sata class ID of AMD-AHCI mode
42         0x01018f00      //sata class ID of IDE to AMD-AHCI mode
43 };
44
45 //Table for device id of SATA Controller in different modes
46 UINT16 sataDeviceIDTable[] = {
47         0x4390, //sata device ID of IDE
48         0x4392, //sata device ID of RAID
49         0x4391, //sata class ID of AHCI
50         0x4390, //sata device ID of Legacy IDE
51         0x4390, //sata device ID of IDE->AHCI mode
52         0x4394, //sata device ID for AMD-AHCI mode
53         0x4390  //sata device ID of IDE->AMDAHCI mode
54 };
55
56
57 void sataInitBeforePciEnum(AMDSBCFG*    pConfig){
58         UINT32  ddValue, *tempptr;
59         UINT16  *pDeviceIdptr, dwDeviceId;
60         UINT8   dbValue, dbOrMask, dbAndMask;
61
62
63         dbAndMask=0;
64         dbOrMask=0;
65         // Enable/Disable Combined mode & do primary/secondary selections, enable/disable
66         if (pConfig->SataIdeCombinedMode == CIMX_OPTION_DISABLED)               dbAndMask= BIT3;                //Clear BIT3
67         if (pConfig->SataIdeCombMdPriSecOpt == 1)       dbOrMask = BIT4;                //Set BIT4
68         if (pConfig->SataSmbus == 0)    dbOrMask = BIT1;
69
70         RWPCI(((SMBUS_BUS_DEV_FUN << 16) + SB_SMBUS_REGAD), AccWidthUint8 | S3_SAVE, ~(dbAndMask), dbOrMask);
71
72         if (pConfig->SataController == 0){
73                 // SATA Controller Disabled & set Power Saving mode to disabled
74                 RWPCI(((SMBUS_BUS_DEV_FUN << 16) + SB_SMBUS_REGAD), AccWidthUint8 | S3_SAVE, ~(UINT32)BIT0, BIT1);
75                 return;
76         }
77
78         restrictSataCapabilities(pConfig);
79
80         //      Get the appropriate class code from the table and write it to PCI register 08h-0Bh
81         //      Set the appropriate SATA class based on the input parameters
82         dbValue=pConfig->SataClass;
83         tempptr= (UINT32 *) FIXUP_PTR (&sataIfCodeTable[0]);
84         ddValue=tempptr[dbValue];
85
86         // BIT0: Enable write access to PCI header (reg 08h-0Bh) by setting SATA PCI register 40h, bit 0
87         // BIT4:disable fast boot
88         RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, 0xff, BIT4+BIT0);
89
90         // Write the class code to SATA PCI register 08h-0Bh
91         RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG08), AccWidthUint32 | S3_SAVE, 0, ddValue);
92
93         if      (pConfig->SataClass == LEGACY_IDE_MODE)         //SATA = Legacy IDE
94                 //Set PATA controller to native mode
95                 RWPCI(((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG09), AccWidthUint8 | S3_SAVE, 0x00, 0x08F);
96
97         //Change the appropriate device id
98         if (pConfig->SataClass == AMD_AHCI_MODE)        {
99                 RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 3), AccWidthUint8 | S3_SAVE, 0xff, BIT0);
100         }
101         pDeviceIdptr= (UINT16 *) FIXUP_PTR (&sataDeviceIDTable[0]);
102
103         ReadPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, &dwDeviceId);
104         if ( !((dwDeviceId==SB750_SATA_DEFAULT_DEVICE_ID) && (pConfig->SataClass == RAID_MODE)) ){
105                 //if not (SB750 & RAID mode), then program the device id
106                 dwDeviceId=pDeviceIdptr[dbValue];
107                 RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, 0, dwDeviceId);
108         }
109
110         if (pConfig->AcpiS1Supported)
111                 RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG34), AccWidthUint8 | S3_SAVE, 00, 0x70);//Disable SATA PM & MSI capability
112         else
113                 RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG60+1), AccWidthUint8 | S3_SAVE, 00, 0x70);//Disable SATA MSI capability
114
115         if (getRevisionID() >= SB700_A13){
116                 //Enable test/enhancement mode for A13
117                 RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40+3), AccWidthUint8 | S3_SAVE, ~(UINT32)BIT5, 00);
118                 RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48), AccWidthUint32 | S3_SAVE, ~(UINT32)(BIT24+BIT21), 0xBF80);
119         }
120
121         if (getRevisionID() >= SB700_A14){
122                 //Fix for TT SB01352 -  LED Stays On When ODD Attached To Slave Port In IDE Mode
123                 RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48), AccWidthUint8 | S3_SAVE, 0xFF, BIT6);
124         }
125
126         // Disable write access to PCI header
127         RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, ~(UINT32)BIT0, 0);
128
129         // RPR 6.5 SATA PHY Programming Sequence
130         RWPCI((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG86, AccWidthUint16 | S3_SAVE, 0x00, 0x2C00);
131         RWPCI((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG88, AccWidthUint32 | S3_SAVE, 0x00, 0x01B48016);
132         RWPCI((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG8C, AccWidthUint32 | S3_SAVE, 0x00, 0x01B48016);
133         RWPCI((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG90, AccWidthUint32 | S3_SAVE, 0x00, 0x01B48016);
134         RWPCI((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG94, AccWidthUint32 | S3_SAVE, 0x00, 0x01B48016);
135         RWPCI((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG98, AccWidthUint32 | S3_SAVE, 0x00, 0x01B48016);
136         RWPCI((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG9C, AccWidthUint32 | S3_SAVE, 0x00, 0x01B48016);
137         RWPCI((SATA_BUS_DEV_FUN << 16) + SB_SATA_REGA0, AccWidthUint32 | S3_SAVE, 0x00, 0xA07AA07A);
138         RWPCI((SATA_BUS_DEV_FUN << 16) + SB_SATA_REGA4, AccWidthUint32 | S3_SAVE, 0x00, 0xA07AA07A);
139         RWPCI((SATA_BUS_DEV_FUN << 16) + SB_SATA_REGA8, AccWidthUint32 | S3_SAVE, 0x00, 0xA07AA07A);
140
141         CallBackToOEM(SATA_PHY_PROGRAMMING, NULL, pConfig);
142 }
143
144 void sataInitAfterPciEnum(AMDSBCFG* pConfig){
145         UINT32  ddAndMask=0, ddOrMask=0, ddBar5=0;
146         UINT8   dbVar, dbPortNum;
147
148         if (pConfig->SataController == 0) return;               //return if SATA controller is disabled.
149
150         //Enable write access to pci header, pm capabilities
151         RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, 0xFF, BIT0);
152
153         //Disable AHCI enhancement function (RPR 7.2)
154         RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 2), AccWidthUint8 | S3_SAVE, 0xFF, BIT7);
155
156         restrictSataCapabilities(pConfig);
157
158         ReadPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG24), AccWidthUint32, &ddBar5);
159
160         if      ( (ddBar5 == 0) || (ddBar5 == -1) ) {
161                 //assign temporary BAR5
162                 if      ( (pConfig->TempMMIO == 0) || (pConfig->TempMMIO == -1))
163                         ddBar5 = 0xFEC01000;
164                 else
165                         ddBar5=pConfig->TempMMIO;
166
167                 WritePCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG24), AccWidthUint32, &ddBar5);
168         }
169
170         ReadPCI( ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar);
171         RWPCI( ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8,0xFF, 0x03);   //memory and io access enable
172
173         ddBar5 &= 0xFFFFFC00;                   //Clear Bits 9:0
174         if (!pConfig->SataPortMultCap)
175                 ddAndMask |= BIT12;
176         if (!pConfig->SataAggrLinkPmCap)
177                 ddAndMask |= BIT11;
178         if (pConfig->SataSscPscCap)
179                 ddOrMask |= BIT1;
180
181         RWMEM((ddBar5 + SB_SATA_BAR5_REGFC),AccWidthUint32 | S3_SAVE, ~ddAndMask, ddOrMask);
182
183
184         //Clear HPCP and ESP by default
185         RWMEM((ddBar5 + SB_SATA_BAR5_REGF8),AccWidthUint32 | S3_SAVE, 0xFFFC0FC0, 0);
186
187         if      (pConfig->SataHpcpButNonESP !=0) {
188                 RWMEM((ddBar5 + SB_SATA_BAR5_REGF8),AccWidthUint32 | S3_SAVE, 0xFFFFFFC0, pConfig->SataHpcpButNonESP);
189         }
190
191         // SATA ESP port setting
192         // These config bits are set for SATA driver to identify which ports are external SATA ports and need to
193         // support hotplug. If a port is set as an external SATA port and need to support hotplug, then driver will
194         // not enable power management(HIPM & DIPM) for these ports.
195         if      (pConfig->SataEspPort !=0) {
196                 RWMEM((ddBar5 + SB_SATA_BAR5_REGFC),AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, BIT20);
197                 RWMEM((ddBar5 + SB_SATA_BAR5_REGF8),AccWidthUint32 | S3_SAVE, ~(pConfig->SataEspPort), 0);
198                 RWMEM((ddBar5 + SB_SATA_BAR5_REGF8),AccWidthUint32 | S3_SAVE, ~(UINT32)(BIT17+BIT16+BIT15+BIT14+BIT13+BIT12),(pConfig->SataEspPort << 12));
199         }
200
201         if      ( ((pConfig->SataClass) != NATIVE_IDE_MODE)  && ((pConfig->SataClass) != LEGACY_IDE_MODE) )
202                 RWPCI( ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50+2), AccWidthUint8, ~(UINT32)(BIT3+BIT2+BIT1), BIT2+BIT1); //set MSI to 8 messages
203
204         if      ( ((pConfig->SataClass) != NATIVE_IDE_MODE)  && ((pConfig->SataClass) != LEGACY_IDE_MODE) && ((pConfig->SataIdeCombinedMode) == CIMX_OPTION_DISABLED) ){
205                 RWMEM((ddBar5 + SB_SATA_BAR5_REG00),AccWidthUint8 | S3_SAVE, ~(UINT32)(BIT2+BIT1+BIT0), BIT2+BIT0);
206                 RWMEM((ddBar5 + SB_SATA_BAR5_REG0C),AccWidthUint8 | S3_SAVE, 0xC0, 0x3F);
207         }
208
209         for (dbPortNum=0;dbPortNum<=5;dbPortNum++){
210                 if (pConfig->SataPortMode & (1 << dbPortNum)){
211                         //downgrade to GEN1
212                         RWMEM(ddBar5+ SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0x0F, 0x10);
213                         RWMEM(ddBar5+ SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFF, 0x01);
214                         Stall(1000);
215                         RWMEM(ddBar5+ SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFE, 0x00);
216                 }
217         }
218
219         //If this is not S3 resume and also if SATA set to one of IDE mode, then implement drive detection workaround.
220         if ( !(pConfig->S3Resume) && ( ((pConfig->SataClass) != AHCI_MODE)  && ((pConfig->SataClass) != RAID_MODE) && ((pConfig->SataClass) != AMD_AHCI_MODE) ) )
221                 sataDriveDetection(pConfig, ddBar5);
222
223         if ( (pConfig->SataPhyWorkaround==1) || ( (pConfig->SataPhyWorkaround==0) && (getRevisionID() < SB700_A13)) )
224                 sataPhyWorkaround(pConfig, ddBar5);
225
226         // Set the handshake bit for IDE driver to detect the disabled IDE channel correctly.
227         // Set IDE PCI Config 0x63 [3] if primary channel disabled, [4] if secondary channel disabled.
228         if (pConfig->SataIdeCombinedMode == CIMX_OPTION_DISABLED)
229                 RWPCI( ((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG63), AccWidthUint8 , 0xF9, (0x02 << (pConfig->SataIdeCombMdPriSecOpt)) );
230
231         WritePCI( ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar);
232
233         //Disable write access to pci header, pm capabilities
234         RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, ~(UINT32)BIT0, 0);
235 }
236
237
238 void sataDriveDetection(AMDSBCFG* pConfig, UINT32 ddBar5){
239         UINT32  ddVar0;
240         UINT8   dbPortNum, dbVar0;
241         UINT16  dwIoBase, dwVar0;
242
243         TRACE((DMSG_SB_TRACE, "CIMx - Entering sata drive detection procedure\n\n"));
244         TRACE((DMSG_SB_TRACE, "SATA BAR5 is %X \n", ddBar5));
245
246         if ( (pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE) || (pConfig->SataClass == IDE_TO_AHCI_MODE) || (pConfig->SataClass == IDE_TO_AMD_AHCI_MODE) ){
247                 for (dbPortNum=0;dbPortNum<4;dbPortNum++){
248                         ReadMEM(ddBar5+ SB_SATA_BAR5_REG128 + dbPortNum * 0x80, AccWidthUint32, &ddVar0);
249                         if ( ( ddVar0 & 0x0F ) == 0x03){
250                                 if ( dbPortNum & BIT0)
251                                         //this port belongs to secondary channel
252                                         ReadPCI( ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG18), AccWidthUint16, &dwIoBase);
253                                 else
254                                         //this port belongs to primary channel
255                                         ReadPCI( ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG10), AccWidthUint16, &dwIoBase);
256
257                                 //if legacy ide mode, then the bar registers don't contain the correct values. So we need to hardcode them
258                                 if (pConfig->SataClass == LEGACY_IDE_MODE)
259                                         dwIoBase = ( (0x170) | ( (~((dbPortNum & BIT0) << 7)) & 0x80 ) );
260
261                                 if ( dbPortNum & BIT1)
262                                         //this port is slave
263                                         dbVar0=0xB0;
264                                 else
265                                         //this port is master
266                                         dbVar0=0xA0;
267                                 dwIoBase &= 0xFFF8;
268                                 WriteIO(dwIoBase+6, AccWidthUint8, &dbVar0);
269
270                                 //Wait in loop for 30s for the drive to become ready
271                                 for (dwVar0=0;dwVar0<3000;dwVar0++){
272                                         ReadIO(dwIoBase+7, AccWidthUint8, &dbVar0);
273                                         if ( (dbVar0 & 0x88) == 0)
274                                                 break;
275                                         Stall(10000);
276                                 }
277                         }       //end of if ( ( ddVar0 & 0x0F ) == 0x03)
278                 }       //for (dbPortNum=0;dbPortNum<4;dbPortNum++)
279         }       //if ( (pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE) || (pConfig->SataClass == IDE_TO_AHCI_MODE) || (pConfig->SataClass == IDE_TO_AMD_AHCI_MODE) )
280 }
281
282
283 //This patch is to workaround the SATA PHY logic hardware issue in the SB700.
284 //Internally this workaround is called as 7NewA
285 void    sataPhyWorkaround(AMDSBCFG* pConfig, UINT32 ddBar5){
286
287         UINT8   dbPortNum, dbVar0;
288
289         if (pConfig->Gen1DeviceShutdownDuringPhyWrknd == 0x01){
290                 for (dbPortNum=0;dbPortNum<=5;dbPortNum++){
291                         ReadMEM(ddBar5+ SB_SATA_BAR5_REG128 + dbPortNum * 0x80, AccWidthUint8, &dbVar0);
292                         if ( (dbVar0 & 0xF0) == 0x10){
293                                 RWPCI((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40+2, AccWidthUint8 | S3_SAVE, 0xFF, (01 << dbPortNum));
294                         }
295
296                 }
297         }
298
299         RWPMIO(SB_PMIO_REGD0, AccWidthUint8, ~(UINT32)(BIT4+BIT3), BIT4+BIT3);//set PMIO_D0[4:3] = 11b // this is to tell SATA PHY to use the internal 100MHz clock
300         RWPCI((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG86, AccWidthUint8 | S3_SAVE, 0x00, 0x40);// set SATA PCI_CFG 0x86[7:0] = 0x40  //after the reset is done, perform this to turn on the diff clock path into SATA PHY
301         Stall(2000);//  Wait for 2ms
302         RWPMIO(SB_PMIO_REGD0, AccWidthUint8, ~(UINT32)(BIT4+BIT3), 00);//13.    set PMIO_D0[4:3] = 00b
303         Stall(20000);// Wait 20ms
304         forceOOB(ddBar5);//     Force OOB
305
306         RWPCI((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40+2, AccWidthUint8 | S3_SAVE, ~(0x03F), 00);
307 }
308
309
310 void    forceOOB(UINT32 ddBar5){
311         UINT8 dbPortNum;
312         for (dbPortNum=0;dbPortNum<=5;dbPortNum++)
313                 RWMEM(ddBar5+ SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFF, 0x01);
314         Stall(2000);
315         for (dbPortNum=0;dbPortNum<=5;dbPortNum++)
316                 RWMEM(ddBar5+ SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFE, 0x00);
317         Stall(2000);//  Wait for 2ms
318 }
319
320 /*++
321
322 Routine Description:
323
324   SATA Late Configuration
325
326   if the mode is selected as IDE->AHCI
327   { 1. Set class ID to AHCI
328     2. Enable AHCI interrupt
329   }
330
331 Arguments:
332
333   pConfig - SBconfiguration
334
335 Returns:
336
337   void
338
339 --*/
340 void sataInitLatePost(AMDSBCFG* pConfig){
341         UINT32  ddBar5;
342         UINT8   dbVar;
343
344         //Return immediately is sata controller is not enabled
345         if (pConfig->SataController == 0) return;
346
347         restrictSataCapabilities(pConfig);
348
349         //Get BAR5 value
350         ReadPCI( ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG24), AccWidthUint32, &ddBar5);
351
352         //Assign temporary BAR if is not already assigned
353         if      ( (ddBar5 == 0) || (ddBar5 == -1) ){
354                 //assign temporary BAR5
355                 if      ( (pConfig->TempMMIO == 0) || (pConfig->TempMMIO == -1))
356                         ddBar5 = 0xFEC01000;
357                 else
358                         ddBar5=pConfig->TempMMIO;
359                 WritePCI( ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG24), AccWidthUint32, &ddBar5);
360         }
361
362         ReadPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar);
363         //Enable memory and io access
364         RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, 0xFF, 0x03);
365         //Enable write access to pci header, pm capabilities
366         RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, 0xff, BIT0);
367
368         shutdownUnconnectedSataPortClock(pConfig, ddBar5);
369
370         if ( (pConfig->SataClass == IDE_TO_AHCI_MODE) || (pConfig->SataClass == IDE_TO_AMD_AHCI_MODE)){
371                 //program the AHCI class code
372                 RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG08), AccWidthUint32 | S3_SAVE, 0, 0x01060100);
373                 //Set interrupt enable bit
374                 RWMEM((ddBar5 + 0x04),AccWidthUint8,~(UINT32)0,BIT1);
375                 //program the correct device id for AHCI mode
376                 RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, 0, 0x4391);
377
378                 if (pConfig->SataClass == IDE_TO_AMD_AHCI_MODE)
379                         //program the correct device id for AMD-AHCI mode
380                         RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 3), AccWidthUint8 | S3_SAVE, 0xFF, BIT0);
381         }
382
383         //Disable write access to pci header and pm capabilities
384         RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, ~(UINT32)BIT0, 0);
385         //Clear error status
386         RWMEM((ddBar5 + SB_SATA_BAR5_REG130),AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
387         RWMEM((ddBar5 + SB_SATA_BAR5_REG1B0),AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
388         RWMEM((ddBar5 + SB_SATA_BAR5_REG230),AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
389         RWMEM((ddBar5 + SB_SATA_BAR5_REG2B0),AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
390         //Restore memory and io access bits
391         WritePCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar );
392 }
393
394
395 void shutdownUnconnectedSataPortClock(AMDSBCFG* pConfig, UINT32 ddBar5){
396         UINT8   dbPortNum, dbPortSataStatus, NumOfPorts=0;
397         UINT8   UnusedPortBitMap;
398         UINT8   SataType;
399         UINT8   ClockOffEnabled ;
400
401         UnusedPortBitMap = 0;
402
403         // First scan for all unused SATA ports
404         for (dbPortNum = 5; dbPortNum <= 5; dbPortNum--) {
405           ReadMEM (ddBar5 + SB_SATA_BAR5_REG128 + (dbPortNum * 0x80), AccWidthUint8, &dbPortSataStatus);
406           if ((!(dbPortSataStatus & 0x01)) && (!((pConfig->SataEspPort) & (1 << dbPortNum)))) {
407             UnusedPortBitMap |= (1 << dbPortNum);
408           }
409         }
410
411         // Decide if we need to shutdown the clock for all unused ports
412         SataType = pConfig->SataClass;
413         ClockOffEnabled = (pConfig->SataClkAutoOff && ((SataType == NATIVE_IDE_MODE) || (SataType == LEGACY_IDE_MODE) || \
414                                                         (SataType == IDE_TO_AHCI_MODE) || (SataType == IDE_TO_AMD_AHCI_MODE))) || \
415                           (pConfig->SataClkAutoOffAhciMode && ((SataType == AHCI_MODE) || (SataType == AMD_AHCI_MODE)));
416
417         if (ClockOffEnabled) {
418           //Shutdown the clock for the port and do the necessary port reporting changes.
419           TRACE((DMSG_SB_TRACE, "Shutting down clock for SATA ports %X \n", UnusedPortBitMap));
420           RWPCI(((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 2), AccWidthUint8, 0xFF, UnusedPortBitMap);
421           RWMEM(ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, ~UnusedPortBitMap, 00);
422         }
423
424         // If all ports are in disabled state, report at least one
425         ReadMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, &dbPortSataStatus);
426         if ( (dbPortSataStatus & 0x3F) == 0) {
427           dbPortSataStatus = 1;
428           RWMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, ~(0x3F), dbPortSataStatus);
429         }
430
431         // Decide if we need to hide unused ports from being seen by OS (this saves OS startup time)
432         if (pConfig->SataHideUnusedPort && ClockOffEnabled) {
433           dbPortSataStatus &= ~UnusedPortBitMap;    // Mask off unused ports
434           for (dbPortNum = 0; dbPortNum <= 6; dbPortNum++) {
435             if (dbPortSataStatus & (1 << dbPortNum))
436               NumOfPorts++;
437             }
438           if (NumOfPorts == 0 ) {
439                 NumOfPorts = 0x01;
440             }
441           RWMEM (ddBar5 + SB_SATA_BAR5_REG00, AccWidthUint8, 0xE0, NumOfPorts - 1);
442         }
443 }
444
445
446 void    restrictSataCapabilities(AMDSBCFG* pConfig){
447         //Restrict capabilities
448         if ( ((getSbCapability(Sb_Raid0_1_Capability)== 0x02) && (pConfig->SataClass == RAID_MODE)) || \
449                 ((getSbCapability(Sb_Raid5_Capability)== 0x02) && (pConfig->SataClass == RAID_MODE))  || \
450                 ((getSbCapability(Sb_Ahci_Capability)== 0x02) && ((pConfig->SataClass == AHCI_MODE) || (pConfig->SataClass == IDE_TO_AHCI_MODE)))){
451                         pConfig->SataClass = NATIVE_IDE_MODE;
452                 }
453 }