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