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