blob: f9823d8fb5e1f20d7afc0cacd7f9baf17a4366b2 [file] [log] [blame]
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001
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.
Edward O'Callaghanef5981b2014-07-06 19:20:52 +100020 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000021 * 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.
Edward O'Callaghanef5981b2014-07-06 19:20:52 +100028 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
Frank Vibrans2b4c8312011-02-14 18:30:54 +000030 * from this software without specific prior written permission.
Edward O'Callaghanef5981b2014-07-06 19:20:52 +100031 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000032 * 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.
Edward O'Callaghanef5981b2014-07-06 19:20:52 +100042 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000043 * ***************************************************************************
44 *
45 */
Kerry She76d53b22011-06-01 02:00:30 +000046
Frank Vibrans2b4c8312011-02-14 18:30:54 +000047#include "SBPLATFORM.h"
48#include "cbtypes.h"
49
50//
51// Declaration of local functions
52//
53VOID sataSetIrqIntResource (IN AMDSBCFG* pConfig);
54VOID sataBar5setting (IN AMDSBCFG* pConfig, IN UINT32 *pBar5);
55VOID shutdownUnconnectedSataPortClock (IN AMDSBCFG* pConfig, IN UINT32 ddBar5);
56VOID 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 */
67VOID
68sataSetIrqIntResource (
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 */
98VOID
99sataBar5setting (
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 */
128VOID
129shutdownUnconnectedSataPortClock (
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 */
Elyes HAOUASad1456f2019-06-22 09:52:12 +0200179static const UINT32 sataIfCodeTable[] =
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000180{
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 */
Elyes HAOUASad1456f2019-06-22 09:52:12 +0200195static const UINT16 sataDeviceIDTable[] =
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000196{
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 */
Elyes HAOUASad1456f2019-06-22 09:52:12 +0200211static const SATAPHYSETTING sataPhyTable[] =
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000212{
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 */
246VOID
247sataInitBeforePciEnum (
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
Aaron Durbind907a342014-01-30 22:20:01 -0600261 ddTempVar = 0;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000262 // 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 }
Aaron Durbind907a342014-01-30 22:20:01 -0600295 if (pConfig->BuildParameters.IdeSsid != 0 ) {
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000296 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]);
Aaron Durbind907a342014-01-30 22:20:01 -0600300 if ( pConfig->BuildParameters.SataIDESsid != 0 ) {
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000301 ddTempVar = pConfig->BuildParameters.SataIDESsid;
302 }
303 dwDeviceId = pDeviceIdptr[dbValue];
304 if ( pConfig->SataClass == RAID_MODE) {
Aaron Durbind907a342014-01-30 22:20:01 -0600305 if ( pConfig->BuildParameters.SataRAID5Ssid != 0 ) {
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000306 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;
Aaron Durbind907a342014-01-30 22:20:01 -0600313 if ( pConfig->BuildParameters.SataRAIDSsid != 0 ) {
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000314 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) ) {
Aaron Durbind907a342014-01-30 22:20:01 -0600320 if ( pConfig->BuildParameters.SataAHCISsid != 0 ) {
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000321 ddTempVar = pConfig->BuildParameters.SataAHCISsid;
322 }
323 }
324 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, 0, dwDeviceId);
Aaron Durbind907a342014-01-30 22:20:01 -0600325 if ( ddTempVar != 0 ) {
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000326 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 */
354VOID
355sataInitAfterPciEnum (
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 Menzel0b312862013-04-12 14:03:04 +0200472 // RAID or AHCI
Kerry Sheh4e9c4c82011-10-10 18:23:49 +0800473 if ((pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == SATA_IDE_COMBINE_DISABLE) {
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000474 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 */
540VOID
541sataInitMidPost (
542 IN AMDSBCFG* pConfig
543 )
544{
545 UINT32 ddBar5;
546 sataBar5setting (pConfig, &ddBar5);
Paul Menzel00861622013-04-28 14:44:08 +0200547 //If this is not S3 resume and also if SATA set to one of IDE mode, then implement drive detection workaround.
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000548 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 */
561VOID
562sataDriveDetection (
563 IN AMDSBCFG* pConfig,
564 IN UINT32 *pBar5
565 )
566{
567 UINT32 ddVar0;
568 UINT8 dbPortNum;
569 UINT8 dbVar0;
570 UINT16 dwIoBase;
Edward O'Callaghan8a661ed2014-05-21 09:42:56 +1000571 UINT32 dwVar0;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000572 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 */
618VOID
619sataInitLatePost (
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 Sheh4e9c4c82011-10-10 18:23:49 +0800634// if ((pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == SATA_IDE_COMBINE_DISABLE) {
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000635 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