5 * Config Southbridge SATA controller
\r
7 * Init SATA features.
\r
9 * @xrefitem bom "File Content Label" "Release Content"
\r
10 * @e project: CIMx-SB
\r
12 * @e \$Revision:$ @e \$Date:$
\r
16 *****************************************************************************
\r
18 * This file is part of the coreboot project.
\r
20 * Copyright (C) 2010 Advanced Micro Devices, Inc.
\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
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
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
38 #include "SBPLATFORM.h"
\r
41 // Declaration of local functions
\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
49 * sataSetIrqIntResource - Config SATA IRQ/INT# resource
\r
52 * - Private function
\r
54 * @param[in] pConfig Southbridge configuration structure pointer.
\r
58 sataSetIrqIntResource (
\r
59 IN AMDSBCFG* pConfig
\r
63 // IRQ14/IRQ15 come from IDE or SATA
\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
71 if (pConfig->SataIdeMode == 1) {
\r
72 // Both IDE & SATA set to Native mode
\r
73 dbValue = dbValue | 0xF0;
\r
76 WriteIO (SB_IOMAP_REGC01, AccWidthUint8, &dbValue);
\r
80 * sataBar5setting - Config SATA BAR5
\r
82 * - Private function
\r
84 * @param[in] pConfig - Southbridge configuration structure pointer.
\r
85 * @param[in] *pBar5 - SATA BAR5 buffer.
\r
90 IN AMDSBCFG* pConfig,
\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
102 *pBar5 = pConfig->TempMMIO;
\r
104 WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG24), AccWidthUint32, pBar5);
\r
107 *pBar5 = *pBar5 & 0xFFFFFC00;
\r
110 * shutdownUnconnectedSataPortClock - Shutdown unconnected Sata port clock
\r
112 * - Private function
\r
114 * @param[in] pConfig Southbridge configuration structure pointer.
\r
115 * @param[in] ddBar5 Sata BAR5 base address.
\r
119 shutdownUnconnectedSataPortClock (
\r
120 IN AMDSBCFG* pConfig,
\r
125 UINT8 dbPortSataStatus;
\r
127 UINT8 cimSataClkAutoOff;
\r
129 cimSataClkAutoOff = (UINT8) pConfig->SataClkAutoOff;
\r
130 #if SB_CIMx_PARAMETER == 0
\r
131 cimSataClkAutoOff = cimSataClkAutoOffDefault;
\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
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
149 ReadMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, &dbPortSataStatus);
\r
150 for (dbPortNum = 0; dbPortNum < 6; dbPortNum ++) {
\r
151 if (dbPortSataStatus & (1 << dbPortNum)) {
\r
155 if ( NumOfPorts == 0) {
\r
158 RWMEM (ddBar5 + SB_SATA_BAR5_REG00, AccWidthUint8, 0xE0, NumOfPorts - 1);
\r
159 } //end of SataClkAuto Off option
\r
163 * Table for class code of SATA Controller in different modes
\r
169 UINT32 sataIfCodeTable[] =
\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
179 * Table for device id of SATA Controller in different modes
\r
185 UINT16 sataDeviceIDTable[] =
\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
195 * Table for Sata Phy Fine Setting
\r
201 SATAPHYSETTING sataPhyTable[] =
\r
203 {0x3006, 0x0056A607},
\r
204 {0x2006, 0x00061400},
\r
205 {0x1006, 0x00061302},
\r
207 {0x3206, 0x0056A607},
\r
208 {0x2206, 0x00061400},
\r
209 {0x1206, 0x00061302},
\r
211 {0x3406, 0x0056A607},
\r
212 {0x2406, 0x00061402},
\r
213 {0x1406, 0x00064300},
\r
215 {0x3606, 0x0056A607},
\r
216 {0x2606, 0x00061402},
\r
217 {0x1606, 0x00064300},
\r
219 {0x3806, 0x0056A700},
\r
220 {0x2806, 0x00061502},
\r
221 {0x1806, 0x00064302},
\r
223 {0x3A06, 0x0056A700},
\r
224 {0x2A06, 0x00061502},
\r
225 {0x1A06, 0x00064302}
\r
229 * sataInitBeforePciEnum - Config SATA controller before PCI emulation
\r
233 * @param[in] pConfig Southbridge configuration structure pointer.
\r
237 sataInitBeforePciEnum (
\r
238 IN AMDSBCFG* pConfig
\r
244 UINT16 *pDeviceIdptr;
\r
249 SATAPHYSETTING *pPhyTable;
\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
262 if (dbValue == IDE_TO_AHCI_MODE_4394) {
\r
263 dbValue = IDE_TO_AHCI_MODE;
\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
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
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
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
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
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
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
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
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
318 // SATA IRQ Resource
\r
319 sataSetIrqIntResource (pConfig);
\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
329 // CallBackToOEM (SATA_PHY_PROGRAMMING, NULL, pConfig);
\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
337 * sataInitAfterPciEnum - Config SATA controller after PCI emulation
\r
341 * @param[in] pConfig Southbridge configuration structure pointer.
\r
345 sataInitAfterPciEnum (
\r
346 IN AMDSBCFG* pConfig
\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
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
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
383 if ( pConfig->SATAMODE.SataMode.SataController == 0 ) {
\r
384 return; //return if SATA controller is disabled.
\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
392 sataBar5setting (pConfig, &ddBar5);
\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
399 if ( !cimSataPortMultCap ) {
\r
400 ddAndMask |= BIT12;
\r
402 if ( cimSataAggrLinkPmCap ) {
\r
405 ddAndMask |= BIT11;
\r
407 if ( cimSataPscCap ) {
\r
410 if ( cimSataSscCap ) {
\r
413 if ( cimSataFisBasedSwitching ) {
\r
414 if (dbEfuse & BIT1) {
\r
415 ddAndMask |= BIT10;
\r
420 ddAndMask |= BIT10;
\r
422 // RPR 8.10 Disabling CCC (Command Completion Coalescing) support.
\r
423 if ( cimSataCccSupport ) {
\r
426 ddAndMask |= BIT19;
\r
428 RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint32 | S3_SAVE, ~ddAndMask, ddOrMask);
\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
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
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
451 RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, ~(BIT22 + BIT23 + BIT24 + BIT25 + BIT26 + BIT27), (BIT22 + BIT23 + BIT24 + BIT25 + BIT26 + BIT27));
\r
454 RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, ~(BIT22 + BIT23 + BIT24 + BIT25 + BIT26 + BIT27), 0x00);
\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
461 if (((pConfig->SataClass) != NATIVE_IDE_MODE) && ((pConfig->SataClass) != LEGACY_IDE_MODE)) {
\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
468 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2 + BIT1);
\r
470 // RPR 8.10 Disabling CCC (Command Completion Coalescing) support.
\r
471 if ( pConfig->SataCccSupport ) {
\r
473 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2 + BIT1);
\r
476 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2);
\r
481 if ( pConfig->BIOSOSHandoff == 1 ) {
\r
482 RWMEM ((ddBar5 + SB_SATA_BAR5_REG24), AccWidthUint8 | S3_SAVE, ~BIT0, BIT0);
\r
484 RWMEM ((ddBar5 + SB_SATA_BAR5_REG24), AccWidthUint8 | S3_SAVE, ~BIT0, 0x00);
\r
487 SataPortMode = (UINT16)pConfig->SataPortMode;
\r
489 while ( dbPortNum < 6 ) {
\r
490 dbPortMode = (UINT8) (SataPortMode & 3);
\r
491 if ( (dbPortMode == BIT0) || (dbPortMode == BIT1) ) {
\r
492 if ( dbPortMode == BIT0 ) {
\r
494 RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0x0F, 0x10);
\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
500 RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFF, 0x01);
\r
502 SataPortMode >>= 2;
\r
506 SataPortMode = (UINT16)pConfig->SataPortMode;
\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
514 SataPortMode >>= 2;
\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
523 * sataInitMidPost - Config SATA controller in Middle POST.
\r
527 * @param[in] pConfig Southbridge configuration structure pointer.
\r
532 IN AMDSBCFG* pConfig
\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
544 * sataDriveDetection - Sata drive detection
\r
547 * @param[in] pConfig Southbridge configuration structure pointer.
\r
548 * @param[in] *pBar5 Sata BAR5 base address.
\r
552 sataDriveDetection (
\r
553 IN AMDSBCFG* pConfig,
\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
570 //this port belongs to primary channel
\r
571 ReadPCI (((UINT32) (SATA_BUS_DEV_FUN << 16) + SB_SATA_REG10), AccWidthUint16, &dwIoBase);
\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
577 if ( dbPortNum & BIT1 ) {
\r
578 //this port is slave
\r
581 //this port is master
\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
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
600 * sataInitLatePost - Prepare SATA controller to boot to OS.
\r
602 * - Set class ID to AHCI (if set to AHCI * Mode)
\r
603 * - Enable AHCI interrupt
\r
605 * @param[in] pConfig Southbridge configuration structure pointer.
\r
610 IN AMDSBCFG* pConfig
\r
617 //Return immediately is sata controller is not enabled
\r
618 if ( pConfig->SATAMODE.SataMode.SataController == 0 ) {
\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
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
627 sataBar5setting (pConfig, &ddBar5);
\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
633 shutdownUnconnectedSataPortClock (pConfig, ddBar5);
\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
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
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