blob: 397ed7d0ab78ab09210a921e6470c8ee2fcbcd07 [file] [log] [blame]
efdesign98ee39ea72011-06-16 16:39:30 -07001
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*
efdesign98ee39ea72011-06-16 16:39:30 -070021* 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
efdesign98ee39ea72011-06-16 16:39:30 -070030* from this software without specific prior written permission.
Edward O'Callaghanef5981b2014-07-06 19:20:52 +100031*
efdesign98ee39ea72011-06-16 16:39:30 -070032* 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*
efdesign98ee39ea72011-06-16 16:39:30 -070043****************************************************************************
44*/
45#include "SbPlatform.h"
46#include "cbtypes.h"
47#include "AmdSbLib.h"
48
49//
50// Declaration of local functions
51//
52VOID sataSetIrqIntResource (IN AMDSBCFG* pConfig);
53VOID sataBar5setting (IN AMDSBCFG* pConfig, IN UINT32 *pBar5);
54#ifdef SATA_BUS_DEV_FUN_FPGA
55 VOID sataBar5settingFpga (IN AMDSBCFG* pConfig, IN UINT32 *pBar5);
56#endif
57VOID shutdownUnconnectedSataPortClock (IN AMDSBCFG* pConfig, IN UINT32 ddBar5);
58VOID CaculateAhciPortNumber (IN AMDSBCFG* pConfig, IN UINT32 ddBar5);
59VOID sataDriveDetection (IN AMDSBCFG* pConfig, IN UINT32 *pBar5);
60#ifdef SATA_BUS_DEV_FUN_FPGA
61 VOID sataDriveDetectionFpga (IN AMDSBCFG* pConfig, IN UINT32 *pBar5);
62#endif
63VOID sataGpioPorcedure (IN AMDSBCFG* pConfig);
64
65/**
66 * sataSetIrqIntResource - Config SATA IRQ/INT# resource
67 *
68 *
69 * - Private function
70 *
71 * @param[in] pConfig Southbridge configuration structure pointer.
72 *
73 */
74VOID
75sataSetIrqIntResource (
76 IN AMDSBCFG* pConfig
77 )
78{
79 UINT8 dbValue;
80 // IRQ14/IRQ15 come from IDE or SATA
81 dbValue = 0x08;
82 WriteIO (SB_IOMAP_REGC00, AccWidthUint8, &dbValue);
83 ReadIO (SB_IOMAP_REGC01, AccWidthUint8, &dbValue);
84 dbValue = dbValue & 0x0F;
85 if (pConfig->SataClass == 3) {
86 dbValue = dbValue | 0x50;
87 } else {
88 if (pConfig->SataIdeMode == 1) {
89 // Both IDE & SATA set to Native mode
90 dbValue = dbValue | 0xF0;
91 }
92 }
93 WriteIO (SB_IOMAP_REGC01, AccWidthUint8, &dbValue);
94}
95
96/**
97 * sataBar5setting - Config SATA BAR5
98 *
99 * - Private function
100 *
101 * @param[in] pConfig - Southbridge configuration structure pointer.
102 * @param[in] *pBar5 - SATA BAR5 buffer.
103 *
104 */
105VOID
106sataBar5setting (
107 IN AMDSBCFG* pConfig,
108 IN UINT32 *pBar5
109 )
110{
111 //Get BAR5 value
112 ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG24), AccWidthUint32, pBar5);
113 //Assign temporary BAR if is not already assigned
114 if ( (*pBar5 == 0) || (*pBar5 == - 1) ) {
115 //assign temporary BAR5
116 if ( (pConfig->TempMMIO == 0) || (pConfig->TempMMIO == - 1) ) {
117 *pBar5 = 0xFEC01000;
118 } else {
119 *pBar5 = pConfig->TempMMIO;
120 }
121 WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG24), AccWidthUint32, pBar5);
122 }
123 //Clear Bits 9:0
124 *pBar5 = *pBar5 & 0xFFFFFC00;
125}
126#ifdef SATA_BUS_DEV_FUN_FPGA
127VOID
128sataBar5settingFpga (
129 IN AMDSBCFG* pConfig,
130 IN UINT32 *pBar5
131 )
132{
133 UINT8 dbValue;
134 //Get BAR5 value
135 ReadPCI (((SATA_BUS_DEV_FUN_FPGA << 16) + SB_SATA_REG24), AccWidthUint32, pBar5);
136 //Assign temporary BAR if is not already assigned
137 if ( (*pBar5 == 0) || (*pBar5 == - 1) ) {
138 //assign temporary BAR5
139 if ( (pConfig->TempMMIO == 0) || (pConfig->TempMMIO == - 1) ) {
140 *pBar5 = 0xFEC01000;
141 } else {
142 *pBar5 = pConfig->TempMMIO;
143 }
144 WritePCI (((SATA_BUS_DEV_FUN_FPGA << 16) + SB_SATA_REG24), AccWidthUint32, pBar5);
145 }
146 //Clear Bits 9:0
147 *pBar5 = *pBar5 & 0xFFFFFC00;
148 dbValue = 0x07;
149 WritePCI (((SATA_BUS_DEV_FUN_FPGA << 16) + 0x04), AccWidthUint8, &dbValue);
150 WritePCI (((PCIB_BUS_DEV_FUN << 16) + 0x04), AccWidthUint8, &dbValue);
151}
152#endif
153/**
154 * shutdownUnconnectedSataPortClock - Shutdown unconnected Sata port clock
155 *
156 * - Private function
157 *
158 * @param[in] pConfig Southbridge configuration structure pointer.
159 * @param[in] ddBar5 Sata BAR5 base address.
160 *
161 */
162VOID
163shutdownUnconnectedSataPortClock (
164 IN AMDSBCFG* pConfig,
165 IN UINT32 ddBar5
166 )
167{
168 UINT8 dbPortNum;
169 UINT32 ddPortSataStatus;
170 UINT8 cimSataClkAutoOff;
171
172 cimSataClkAutoOff = (UINT8) pConfig->SataClkAutoOff;
173#if SB_CIMx_PARAMETER == 0
174 cimSataClkAutoOff = cimSataClkAutoOffDefault;
175#endif
176 if ( cimSataClkAutoOff == TRUE ) {
177 //ENH225976 Enable SATA auto clock control by default ( (pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE) || (pConfig->SataClass == IDE_TO_AHCI_MODE) ) {
178 for ( dbPortNum = 0; dbPortNum < 8; dbPortNum++ ) {
179 ReadMEM (ddBar5 + SB_SATA_BAR5_REG128 + (dbPortNum * 0x80), AccWidthUint32, &ddPortSataStatus);
180 // Shutdown the clock for the port and do the necessary port reporting changes.
181 // ?? Error port status should be 1 not 3
182 ddPortSataStatus &= 0x00000F0F;
183 if ( (!((ddPortSataStatus == 0x601) || (ddPortSataStatus == 0x201) || (ddPortSataStatus == 0x103))) && (! ((pConfig->SATAESPPORT.SataPortReg) & (1 << dbPortNum))) ) {
184 TRACE ((DMSG_SB_TRACE, "Shutting down clock for SATA port %X \n", dbPortNum));
185 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 2), AccWidthUint8, 0xFF, (1 << dbPortNum));
186 }
187 } //end of for (dbPortNum=0;dbPortNum<6;dbPortNum++)
188 } //end of SataClkAuto Off option
189}
190
191/**
192 * CaculateAhciPortNumber - Caculat AHCI Port Number
193 *
194 * - Private function
195 *
196 * @param[in] pConfig Southbridge configuration structure pointer.
197 * @param[in] ddBar5 Sata BAR5 base address.
198 *
199 */
200VOID
201CaculateAhciPortNumber (
202 IN AMDSBCFG* pConfig,
203 IN UINT32 ddBar5
204 )
205{
206 UINT8 dbPortNum;
207 UINT8 dbPortSataStatus;
208 UINT8 NumOfPorts;
209 UINT8 MaxPortNum;
210 NumOfPorts = 0;
211 MaxPortNum = 4;
212 if ( (pConfig->SATAMODE.SataMode.SataIdeCombMdPriSecOpt) == ENABLED ) {
213 MaxPortNum = 6;
214 } else if ( (pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == ENABLED ) {
215 MaxPortNum = 8;
216 }
217 ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 2), AccWidthUint8, &dbPortSataStatus);
218 for ( dbPortNum = 0; dbPortNum < MaxPortNum; dbPortNum++ ) {
219 if ( dbPortSataStatus & (1 << dbPortNum) ) {
220 RWMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, ~(1 << dbPortNum), 00);
221 }
222 }
223 ReadMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, &dbPortSataStatus);
224 //if all ports are in disabled state, report atleast one port
225 if ( (dbPortSataStatus & 0xFF) == 0) {
226 RWMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, (UINT32) ~(0xFF), 01);
227 }
228 ReadMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, &dbPortSataStatus);
229 for (dbPortNum = 0; dbPortNum < MaxPortNum; dbPortNum ++) {
230 if (dbPortSataStatus & (1 << dbPortNum)) {
231 NumOfPorts++;
232 }
233 }
234 if ( NumOfPorts == 0) {
235 NumOfPorts = 0x01;
236 }
237 RWMEM (ddBar5 + SB_SATA_BAR5_REG00, AccWidthUint8, 0xE0, NumOfPorts - 1);
238}
239
240/**
241 * sataGpioPorcedure - Sata GPIO function Procedure
242 *
243 * - Private function
244 *
245 * @param[in] pConfig Southbridge configuration structure pointer.
246 *
247 */
248VOID
249sataGpioPorcedure (
250 IN AMDSBCFG* pConfig
251 )
252{
253 UINT32 ddBar5;
254 UINT32 ddData;
255 UINT32 eMb;
256 UINT32 ddTempVariable;
257 UINT8 cimSataSgpio0;
258
259 ddBar5 = 0;
260 eMb = 0;
261 cimSataSgpio0 = (UINT8) pConfig->SataSgpio0;
262
263#if SB_CIMx_PARAMETER == 0
264 cimSataSgpio0 = cimSataSgpio0Default;
265#endif
266
267 sataBar5setting (pConfig, &ddBar5);
268 ReadMEM (ddBar5 + SB_SATA_BAR5_REG1C , AccWidthUint32 | S3_SAVE, &ddData);
269 eMb = (ddBar5 + (( ddData & 0xFFFF0000) >> 14));
270 if ( eMb ) {
271 ddTempVariable = 0x03040C00;
272 WriteMEM ( ddBar5 + eMb, AccWidthUint32 | S3_SAVE, &ddTempVariable);
273 ddTempVariable = 0x00C08240;
274 WriteMEM ( ddBar5 + eMb + 4, AccWidthUint32 | S3_SAVE, &ddTempVariable);
275 ddTempVariable = 0x00000001;
276 WriteMEM ( ddBar5 + eMb + 8, AccWidthUint32 | S3_SAVE, &ddTempVariable);
277 if ( cimSataSgpio0 ) {
278 ddTempVariable = 0x00000060;
279 } else {
280 ddTempVariable = 0x00000061;
281 }
282 WriteMEM ( ddBar5 + eMb + 0x0C, AccWidthUint32 | S3_SAVE, &ddTempVariable);
283
284 RWMEM ((ddBar5 + SB_SATA_BAR5_REG20), AccWidthUint16 | S3_SAVE, ~(BIT8), BIT8);
285 do {
286 ReadMEM (ddBar5 + SB_SATA_BAR5_REG20 , AccWidthUint32 | S3_SAVE, &ddData);
287 ddData = ddData & BIT8;
288 } while ( ddData != 0 );
289
290 ddTempVariable = 0x03040F00;
291 WriteMEM ( ddBar5 + eMb, AccWidthUint32 | S3_SAVE, &ddTempVariable);
292 ddTempVariable = 0x00008240;
293 WriteMEM ( ddBar5 + eMb + 4, AccWidthUint32 | S3_SAVE, &ddTempVariable);
294 ddTempVariable = 0x00000002;
295 WriteMEM ( ddBar5 + eMb + 8, AccWidthUint32 | S3_SAVE, &ddTempVariable);
296 ddTempVariable = 0x00800000;
297 WriteMEM ( ddBar5 + eMb + 0x0C, AccWidthUint32 | S3_SAVE, &ddTempVariable);
298 ddTempVariable = 0x0F003700;
299 WriteMEM ( ddBar5 + eMb + 0x0C, AccWidthUint32 | S3_SAVE, &ddTempVariable);
300 RWMEM ((ddBar5 + SB_SATA_BAR5_REG20), AccWidthUint16 | S3_SAVE, ~(BIT8), BIT8);
301 do {
302 ReadMEM (ddBar5 + SB_SATA_BAR5_REG20 , AccWidthUint32 | S3_SAVE, &ddData);
303 ddData = ddData & BIT8;
304 } while ( ddData != 0 );
305 }
306}
307
308
309/**
310 * Table for class code of SATA Controller in different modes
311 *
312 *
313 *
314 *
315 */
316UINT32 sataIfCodeTable[] =
317{
318 0x01018F40, //sata class ID of IDE
319 0x01040040, //sata class ID of RAID
320 0x01060140, //sata class ID of AHCI
321 0x01018A40, //sata class ID of Legacy IDE
322 0x01018F40, //sata class ID of IDE to AHCI mode
323};
324
325/**
326 * Table for device id of SATA Controller in different modes
327 *
328 *
329 *
330 *
331 */
332
333UINT16 sataDeviceIDTable[] =
334{
335 SB_SATA_DID, //sata device ID of IDE
336 SB_SATA_RAID_DID, //sata device ID of RAID
337 SB_SATA_AHCI_DID, //sata class ID of AHCI
338 SB_SATA_DID, //sata device ID of Legacy IDE
339 SB_SATA_DID, //sata device ID of IDE->AHCI mode
340};
341
342/**
343 * Table for Sata Phy Fine Setting
344 *
345 *
346 *
347 *
348 */
349SATAPHYSETTING sataPhyTable[] =
350{
351 //Gen3
352 {0x0030, 0x0057A607},
353 {0x0031, 0x0057A607},
354 {0x0032, 0x0057A407},
355 {0x0033, 0x0057A407},
356 {0x0034, 0x0057A607},
357 {0x0035, 0x0057A607},
358 {0x0036, 0x0057A403},
359 {0x0037, 0x0057A403},
360
361 //Gen2
362 {0x0120, 0x00071302},
363
364 //Gen1
365 {0x0110, 0x00174101}
366};
367
368/**
369 * sataInitBeforePciEnum - Config SATA controller before PCI emulation
370 *
371 *
372 *
373 * @param[in] pConfig Southbridge configuration structure pointer.
374 *
375 */
376VOID
377sataInitBeforePciEnum (
378 IN AMDSBCFG* pConfig
379 )
380{
381 UINT32 ddTempVar;
382 UINT32 ddValue;
383 UINT32 *tempptr;
384 UINT16 *pDeviceIdptr;
385 UINT32 dwDeviceId;
386 UINT8 dbValue;
387 UINT8 pValue;
388 UINT8 dbChannel;
389 UINT16 i;
390 SATAPHYSETTING *pPhyTable;
391
392 pConfig->SATAPORTPOWER.SataPortPowerReg = \
393 + pConfig->SATAPORTPOWER.SataPortPower.PORT0 \
394 + (pConfig->SATAPORTPOWER.SataPortPower.PORT1 << 1) \
395 + (pConfig->SATAPORTPOWER.SataPortPower.PORT2 << 2) \
396 + (pConfig->SATAPORTPOWER.SataPortPower.PORT3 << 3) \
397 + (pConfig->SATAPORTPOWER.SataPortPower.PORT4 << 4) \
398 + (pConfig->SATAPORTPOWER.SataPortPower.PORT5 << 5) \
399 + (pConfig->SATAPORTPOWER.SataPortPower.PORT6 << 6) \
400 + (pConfig->SATAPORTPOWER.SataPortPower.PORT7 << 7);
401 // BIT0 Enable write access to PCI header (reg 08h-0Bh) by setting SATA PCI register 40h
402 // BIT4:disable fast boot //?
403 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, 0xff, BIT0 + BIT4);
404 // BIT0 Enable write access to PCI header (reg 08h-0Bh) by setting IDE PCI register 40h
405 RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG40), AccWidthUint8 | S3_SAVE, 0xff, BIT0);
406 // RPR Enable IDE DMA read enhancement
407 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48 + 3), AccWidthUint8 | S3_SAVE, 0xff, BIT7);
408 // RPR Unused SATA Ports Disabled
409 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 2), AccWidthUint8 | S3_SAVE, 0, pConfig->SATAPORTPOWER.SataPortPowerReg);
410 dbValue = (UINT8)pConfig->SataClass;
411 if (dbValue == AHCI_MODE_7804) {
412 dbValue = AHCI_MODE;
413 }
414 if (dbValue == IDE_TO_AHCI_MODE_7804) {
415 dbValue = IDE_TO_AHCI_MODE;
416 }
417 // Disable PATA MSI
418 RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG34), AccWidthUint8 | S3_SAVE, 0x00, 0x00);
419 RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG06), AccWidthUint8 | S3_SAVE, 0xEF, 0x00);
420
421 if ( (pConfig->SataClass == 3) | (pConfig->SataClass == 0)) {
422 dbChannel = 0x00;
423 ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48 + 3), AccWidthUint8, &dbChannel);
424 dbChannel &= 0xCF;
425 if ( pConfig->SataDisUnusedIdePChannel ) {
426 dbChannel |= 0x10;
427 }
428 if ( pConfig->SataDisUnusedIdeSChannel ) {
429 dbChannel |= 0x20;
430 }
431 WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48 + 3), AccWidthUint8, &dbChannel);
432 }
433
434 if ((pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == DISABLED ) {
435 ReadPCI (((IDE_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 11), AccWidthUint8, &dbChannel);
436 dbChannel &= 0xCF;
437 if ( pConfig->IdeDisUnusedIdePChannel ) {
438 dbChannel |= 0x10;
439 }
440 if ( pConfig->IdeDisUnusedIdeSChannel ) {
441 dbChannel |= 0x20;
442 }
443 WritePCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG40 + 11), AccWidthUint8, &dbChannel);
444 }
445 // Get the appropriate class code from the table and write it to PCI register 08h-0Bh
446 // Set the appropriate SATA class based on the input parameters
447 // SATA IDE Controller Class ID & SSID
448 tempptr = (UINT32 *) FIXUP_PTR (&sataIfCodeTable[0]);
449 if ( (pConfig->SataIdeMode == 1) && (pConfig->SataClass != 3) ) {
450 ddValue = tempptr[0];
451 // Write the class code to IDE PCI register 08h-0Bh
452 RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG08), AccWidthUint32 | S3_SAVE, 0, ddValue);
453 }
454 ddValue = tempptr[dbValue];
455 // Write the class code to SATA PCI register 08h-0Bh
456 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG08), AccWidthUint32 | S3_SAVE, 0, ddValue);
457 if ( pConfig->SataClass == LEGACY_IDE_MODE ) {
458 //Set PATA controller to native mode
459 RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG09), AccWidthUint8 | S3_SAVE, 0x00, 0x08F);
460 }
Aaron Durbind907a342014-01-30 22:20:01 -0600461 if (pConfig->BuildParameters.IdeSsid != 0 ) {
efdesign98ee39ea72011-06-16 16:39:30 -0700462 RWPCI ((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG2C, AccWidthUint32 | S3_SAVE, 0x00, pConfig->BuildParameters.IdeSsid);
463 }
464 // SATA Controller Class ID & SSID
465 pDeviceIdptr = (UINT16 *) FIXUP_PTR (&sataDeviceIDTable[0]);
466 ddTempVar = pConfig->BuildParameters.SataIDESsid;
467 dwDeviceId = pDeviceIdptr[dbValue];
468 if ( pConfig->SataClass == RAID_MODE) {
469 ddTempVar = pConfig->BuildParameters.SataRAID5Ssid;
470 dwDeviceId = SB_SATA_RAID5_DID;
471 pValue = SATA_EFUSE_LOCATION;
472 getEfuseStatus (&pValue);
473 if (( pValue & SATA_EFUSE_BIT ) || ( pConfig->SataForceRaid == 1 )) {
474 dwDeviceId = SB_SATA_RAID_DID;
475 ddTempVar = pConfig->BuildParameters.SataRAIDSsid;
476 }
477 }
478 if ( ((pConfig->SataClass) == AHCI_MODE) || ((pConfig->SataClass) == IDE_TO_AHCI_MODE) ||
479 ((pConfig->SataClass) == AHCI_MODE_7804) || ((pConfig->SataClass) == IDE_TO_AHCI_MODE_7804) ) {
480 ddTempVar = pConfig->BuildParameters.SataAHCISsid;
481 }
482 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, 0, dwDeviceId);
483 RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG2C, AccWidthUint32 | S3_SAVE, 0x00, ddTempVar);
484
485 // SATA IRQ Resource
486 sataSetIrqIntResource (pConfig);
487
488 // RPR 9.5 SATA PHY Programming Sequence
489 pPhyTable = (SATAPHYSETTING*)FIXUP_PTR (&sataPhyTable[0]);
Patrick Georgi6b688f52021-02-12 13:49:11 +0100490 for (i = 0; i < ARRAY_SIZE(sataPhyTable); i++) {
efdesign98ee39ea72011-06-16 16:39:30 -0700491 RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG80, AccWidthUint16 | S3_SAVE, 0x00, pPhyTable->wPhyCoreControl);
492 RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG98, AccWidthUint32 | S3_SAVE, 0x00, pPhyTable->dwPhyFineTune);
493 ++pPhyTable;
494 }
495 RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG80, AccWidthUint16 | S3_SAVE, 0x00, 0x110);
496 RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG9C, AccWidthUint32 | S3_SAVE, (UINT32) (~(0x7 << 4)), (UINT32) (0x2 << 4));
497 RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG80, AccWidthUint16 | S3_SAVE, 0x00, 0x10);
498
499 RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0);
500 // Disable write access to PCI header
501 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0);
502 if ( IsSbA12Plus () ) {
503 //SATA PCI Config 0x4C[31:26] program 111111b (six 1's)
504 //SATA PCI Config 0x48[11] program 1
505 //SATA PCI Config 0x84[31] program 0
506 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG4C), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x3f << 26)), (UINT32) (0x3f << 26));
507 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x01 << 11)), (UINT32) (0x01 << 11));
508 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG84), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x01 << 31)), (UINT32) (0x00 << 31));
509 }
510
511 //SATA PCI config register 0x4C [20] =1
512 //SATA PCI config register 0x4C [21] =1
513 //SATA PCI config register 0x4C [18] =1
514 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG4C), AccWidthUint32 | S3_SAVE, ~ (BIT18 + BIT20 + BIT21), (BIT18 + BIT20 + BIT21));
515}
516
517/**
518 * sataInitAfterPciEnum - Config SATA controller after PCI emulation
519 *
520 *
521 *
522 * @param[in] pConfig Southbridge configuration structure pointer.
523 *
524 */
525VOID
526sataInitAfterPciEnum (
527 IN AMDSBCFG* pConfig
528 )
529{
530 UINT32 ddAndMask;
531 UINT32 ddOrMask;
532 UINT32 ddBar5;
533 UINT8 dbVar;
534 UINT8 dbPortNum;
535 UINT8 dbEfuse;
536 UINT8 dbPortMode;
537 UINT16 SataPortMode;
538 UINT8 cimSataAggrLinkPmCap;
539 UINT8 cimSataPortMultCap;
540 UINT8 cimSataPscCap;
541 UINT8 cimSataSscCap;
542 UINT8 cimSataFisBasedSwitching;
543 UINT8 cimSataCccSupport;
544 UINT8 cimSataMsiCapability;
545 UINT8 cimSataTargetSupport8Device;
546 UINT8 cimSataDisableGenericMode;
547 UINT8 cimSataAhciEnclosureManagement;
548 UINT8 cimSataSgpio0;
549 UINT8 cimSataSgpio1;
550 UINT8 cimSataHotRemovelEnh;
551 UINT8 cimSataPhyPllShutDown;
552 UINT8 dbCccInt;
553
554 cimSataAggrLinkPmCap = (UINT8) pConfig->SataAggrLinkPmCap;
555 cimSataPortMultCap = (UINT8) pConfig->SataPortMultCap;
556 cimSataPscCap = (UINT8) pConfig->SataPscCap;
557 cimSataSscCap = (UINT8) pConfig->SataSscCap;
558 cimSataFisBasedSwitching = (UINT8) pConfig->SataFisBasedSwitching;
559 cimSataCccSupport = (UINT8) pConfig->SataCccSupport;
560 cimSataMsiCapability = (UINT8) pConfig->SataMsiCapability;
561 cimSataTargetSupport8Device = (UINT8) pConfig->SataTargetSupport8Device;
562 cimSataDisableGenericMode = (UINT8) pConfig->SataDisableGenericMode;
563 cimSataAhciEnclosureManagement = (UINT8) pConfig->SataAhciEnclosureManagement;
564 cimSataSgpio0 = (UINT8) pConfig->SataSgpio0;
565 cimSataSgpio1 = (UINT8) pConfig->SataSgpio1;
566 cimSataHotRemovelEnh = (UINT8) pConfig->SataHotRemoveEnh;
567 cimSataPhyPllShutDown = (UINT8) pConfig->SataPhyPllShutDown;
568
569#if SB_CIMx_PARAMETER == 0
570 cimSataAggrLinkPmCap = cimSataAggrLinkPmCapDefault;
571 cimSataPortMultCap = cimSataPortMultCapDefault;
572 cimSataPscCap = cimSataPscCapDefault;
573 cimSataSscCap = cimSataSscCapDefault;
574 cimSataFisBasedSwitching = cimSataFisBasedSwitchingDefault;
575 cimSataCccSupport = cimSataCccSupportDefault;
576 cimSataMsiCapability = cimSataMsiCapabilityDefault;
577 cimSataTargetSupport8Device = cimSataTargetSupport8DeviceDefault;
578 cimSataDisableGenericMode = cimSataDisableGenericModeDefault;
579 cimSataAhciEnclosureManagement = cimSataAhciEnclosureManagementDefault;
580 cimSataSgpio0 = cimSataSgpio0Default;
581 cimSataSgpio1 = cimSataSgpio1Default;
582 cimSataHotRemovelEnh = cimSataHotRemoveEnhDefault;
583 cimSataPhyPllShutDown = cimSataPhyPllShutDownDefault;
584#endif
585
586 ddAndMask = 0;
587 ddOrMask = 0;
588 ddBar5 = 0;
589 if ( pConfig->SATAMODE.SataMode.SataController == 0 ) {
590 return; //return if SATA controller is disabled.
591 }
592
593 //Enable write access to pci header, pm capabilities
594 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, 0xFF, BIT0);
595
596 sataBar5setting (pConfig, &ddBar5);
597
598 ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar);
599 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, 0xFF, 0x03); //memory and io access enable
600 dbEfuse = SATA_FIS_BASE_EFUSE_LOC;
601 getEfuseStatus (&dbEfuse);
602
603 if ( !cimSataPortMultCap ) {
604 ddAndMask |= BIT12;
605 }
606 if ( cimSataAggrLinkPmCap ) {
607 ddOrMask |= BIT11;
608 } else {
609 ddAndMask |= BIT11;
610 }
611 if ( cimSataPscCap ) {
612 ddOrMask |= BIT1;
613 } else {
614 ddAndMask |= BIT1;
615 }
616 if ( cimSataSscCap ) {
617 ddOrMask |= BIT26;
618 } else {
619 ddAndMask |= BIT26;
620 }
621 if ( cimSataFisBasedSwitching ) {
622 if (dbEfuse & BIT1) {
623 ddAndMask |= BIT10;
624 } else {
625 ddOrMask |= BIT10;
626 }
627 } else {
628 ddAndMask |= BIT10;
629 }
630 // RPR 8.10 Disabling CCC (Command Completion Coalescing) support.
631 if ( cimSataCccSupport ) {
632 ddOrMask |= BIT19;
633 } else {
634 ddAndMask |= BIT19;
635 }
636 if ( cimSataAhciEnclosureManagement ) {
637 ddOrMask |= BIT27;
638 } else {
639 ddAndMask |= BIT27;
640 }
641 RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint32 | S3_SAVE, ~ddAndMask, ddOrMask);
642
643
644 // SATA ESP port setting
645 // These config bits are set for SATA driver to identify which ports are external SATA ports and need to
646 // support hotplug. If a port is set as an external SATA port and need to support hotplug, then driver will
647 // not enable power management (HIPM & DIPM) for these ports.
648 pConfig->SATAESPPORT.SataPortReg = \
649 + pConfig->SATAESPPORT.SataEspPort.PORT0 \
650 + (pConfig->SATAESPPORT.SataEspPort.PORT1 << 1) \
651 + (pConfig->SATAESPPORT.SataEspPort.PORT2 << 2) \
652 + (pConfig->SATAESPPORT.SataEspPort.PORT3 << 3) \
653 + (pConfig->SATAESPPORT.SataEspPort.PORT4 << 4) \
654 + (pConfig->SATAESPPORT.SataEspPort.PORT5 << 5) \
655 + (pConfig->SATAESPPORT.SataEspPort.PORT6 << 6) \
656 + (pConfig->SATAESPPORT.SataEspPort.PORT7 << 7);
657 if ( pConfig->SATAESPPORT.SataPortReg != 0 ) {
658 RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, ~(pConfig->SATAESPPORT.SataPortReg), 0);
659 RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, 0xFF00FF00, (pConfig->SATAESPPORT.SataPortReg << 16));
660 // RPR 8.7 External SATA Port Indication Registers
661 // If any of the ports was programmed as an external port, HCAP.SXS should also be set
662 RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint32 | S3_SAVE, ~(BIT20), BIT20);
663 } else {
664 // RPR 8.7 External SATA Port Indication Registers
665 // If any of the ports was programmed as an external port, HCAP.SXS should also be set (Clear for no ESP port)
666 RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, 0xFF00FF00, 0x00);
667 RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint32 | S3_SAVE, ~(BIT20), 0x00);
668 }
669
670 if ( cimSataFisBasedSwitching ) {
671 if (dbEfuse & BIT1) {
672 RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, 0x00FFFFFF, 0x00);
673 } else {
674 RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, 0x00FFFFFF, 0xFF000000);
675 }
676 } else {
677 RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, 0x00FFFFFF, 0x00);
678 }
679
680 //SB02712 Turn off MSI for SATA IDE mode.
681 if ((pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE)) {
682 cimSataMsiCapability = 0;
683 }
684 //Enabled SATA MSI capability
685 // RPR 8.11 SATA MSI and D3 Power State Capability
686 if (IsSbA12Plus ()) {
687 if ( cimSataMsiCapability ) {
688 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG34), AccWidthUint8 | S3_SAVE, 0, 0x50);
689 } else {
690 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG34), AccWidthUint8 | S3_SAVE, 0, 0x70);
691 }
692 } else {
693 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG34), AccWidthUint8 | S3_SAVE, 0, 0x70);
694 }
695
696 if (((pConfig->SataClass) != NATIVE_IDE_MODE) && ((pConfig->SataClass) != LEGACY_IDE_MODE)) {
Paul Menzel0b312862013-04-12 14:03:04 +0200697 // RAID or AHCI
efdesign98ee39ea72011-06-16 16:39:30 -0700698 if ((pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == DISABLED) {
699 // IDE2 Controller is enabled
700 if ((pConfig->SATAMODE.SataMode.SataIdeCombMdPriSecOpt) == ENABLED) {
701 // 6 AHCI mode
702 RWMEM ((ddBar5 + SB_SATA_BAR5_REG0C), AccWidthUint8 | S3_SAVE, 0x00, 0x3F);
703 RWMEM ((ddBar5 + SB_SATA_BAR5_REG00), AccWidthUint8 | S3_SAVE, ~(BIT2 + BIT1 + BIT0), BIT2 + BIT0);
704 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2 + BIT1);
705 RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint8, 0x07, 0x30);
706 } else {
707 RWMEM ((ddBar5 + SB_SATA_BAR5_REG0C), AccWidthUint8 | S3_SAVE, 0x00, 0x0F);
708 if ( pConfig->SataCccSupport ) {
709 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2 + BIT1);
710 } else {
711 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2);
712 }
713 }
714 } else {
715 // IDE2 Controller is disabled
716 RWMEM ((ddBar5 + SB_SATA_BAR5_REG00), AccWidthUint8 | S3_SAVE, ~(BIT2 + BIT1 + BIT0), BIT2 + BIT1 + BIT0);
717 RWMEM ((ddBar5 + SB_SATA_BAR5_REG0C), AccWidthUint8 | S3_SAVE, 0x00, 0xFF);
718 if ( pConfig->SataCccSupport ) {
719 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT3);
720 } else {
721 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2 + BIT1);
722 }
723 }
724 }
725 if ( pConfig->BIOSOSHandoff == 1 ) {
726 RWMEM ((ddBar5 + SB_SATA_BAR5_REG24), AccWidthUint8 | S3_SAVE, ~BIT0, BIT0);
727 } else {
728 RWMEM ((ddBar5 + SB_SATA_BAR5_REG24), AccWidthUint8 | S3_SAVE, ~BIT0, 0x00);
729 }
730 pConfig->SATAPORTMODE.SataPortMode = \
731 pConfig->SATAPORTMODE.SataPortMd.PORT0 \
732 + (pConfig->SATAPORTMODE.SataPortMd.PORT1 << 2) \
733 + (pConfig->SATAPORTMODE.SataPortMd.PORT2 << 4) \
734 + (pConfig->SATAPORTMODE.SataPortMd.PORT3 << 6) \
735 + (pConfig->SATAPORTMODE.SataPortMd.PORT4 << 8) \
736 + (pConfig->SATAPORTMODE.SataPortMd.PORT5 << 10) \
737 + (pConfig->SATAPORTMODE.SataPortMd.PORT6 << 12) \
738 + (pConfig->SATAPORTMODE.SataPortMd.PORT7 << 14);
739 SataPortMode = (UINT16)pConfig->SATAPORTMODE.SataPortMode;
740 dbPortNum = 0;
741
742 while ( dbPortNum < 8 ) {
743 dbPortMode = (UINT8) (SataPortMode & 3);
744 if ( (dbPortMode == BIT0) || (dbPortMode == BIT1) ) {
745 if ( dbPortMode == BIT0 ) {
746 // set GEN 1
747 RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0x0F, 0x10);
748 }
749 if ( dbPortMode == BIT1 ) {
750 // set GEN2 (default is GEN3)
751 RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0x0F, 0x20);
752 }
753 RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFF, 0x01);
754 cimSbStall (1000);
755 RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFE, 0x00);
756 }
757 SataPortMode >>= 2;
758 dbPortNum ++;
759 }
760 SbStall (1000);
761 SataPortMode = (UINT16)pConfig->SATAPORTMODE.SataPortMode;
762 dbPortNum = 0;
763
764 while ( dbPortNum < 8 ) {
765 dbPortMode = (UINT8) (SataPortMode & 3);
766 if ( (dbPortMode == BIT0) || (dbPortMode == BIT1) ) {
767 RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFE, 0x00);
768 }
769 dbPortNum ++;
770 SataPortMode >>= 2;
771 }
772
773 if ( cimSataTargetSupport8Device ) {
774 RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint16, ~BIT12, BIT12);
775 } else {
776 RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint16, ~BIT12, 0x00);
777 }
778
779 if ( cimSataDisableGenericMode ) {
780 RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint16, ~BIT13, BIT13);
781 } else {
782 RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint16, ~BIT13, 0x00);
783 }
784 // 9.19 Optionally Disable Hot-removal Detection Enhancement
785 if ( cimSataHotRemovelEnh ) {
786 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG80), AccWidthUint16 | S3_SAVE, ~BIT8, BIT8 );
787 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REGA8), AccWidthUint16 | S3_SAVE, ~BIT0, BIT0);
788 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG80), AccWidthUint16 | S3_SAVE, ~BIT8, 0 );
789 }
790 if ( cimSataSgpio0 ) {
791 sataGpioPorcedure (pConfig);
792 }
793 if ( cimSataSgpio1 ) {
794 sataGpioPorcedure (pConfig);
795 }
796 if ( IsSbA11 () ) {
797 if ( cimSataPhyPllShutDown ) {
798 RWPCI (((SATA_BUS_DEV_FUN << 16) + 0x87), AccWidthUint8 | S3_SAVE, ~(BIT6 + BIT7), BIT6 + BIT7);
799 } else {
800 RWPCI (((SATA_BUS_DEV_FUN << 16) + 0x87), AccWidthUint8 | S3_SAVE, ~(BIT6 + BIT7), 0x00);
801 }
802 } else {
803 if ( cimSataPhyPllShutDown ) {
804 RWPCI (((SATA_BUS_DEV_FUN << 16) + 0x87), AccWidthUint8 | S3_SAVE, ~(BIT6), BIT6);
805 } else {
806 RWPCI (((SATA_BUS_DEV_FUN << 16) + 0x87), AccWidthUint8 | S3_SAVE, ~(BIT6), 0x00);
807 }
808 }
809 if ( IsSbA12Plus () ) {
810 //SATA PCI Config 0x4C[31:26] program 111111b (six 1's)
811 //SATA PCI Config 0x48[11] program 1
812 //SATA PCI Config 0x84[31] program 0
813 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG4C), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x3f << 26)), (UINT32) (0x3f << 26));
814 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x01 << 11)), (UINT32) (0x01 << 11));
815 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG84), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x01 << 31)), (UINT32) (0x00 << 31));
816 }
817 // RPR 9.18 CCC Interrupt
818 dbCccInt = 4;
819 if ((pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == DISABLED) {
820 if ((pConfig->SATAMODE.SataMode.SataIdeCombMdPriSecOpt) == ENABLED) {
821 dbCccInt = 6;
822 }
823 } else {
824 dbCccInt = 8;
825 }
826 RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint8, 0x07, (dbCccInt << 3));
827
828 shutdownUnconnectedSataPortClock (pConfig, ddBar5);
829
830 WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar);
831
832 // RPR 9.13 Disable SATA FLR Capability
833 // SATA_PCI_config 0x70 [15:8] = 0x00
834 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG70), AccWidthUint32 | S3_SAVE, 0xFFFF00FF, 0x00);
835 //Disable write access to pci header, pm capabilities
836 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0);
837}
838
839
840/**
841 * sataInitMidPost - Config SATA controller in Middle POST.
842 *
843 *
844 *
845 * @param[in] pConfig Southbridge configuration structure pointer.
846 *
847 */
848VOID
849sataInitMidPost (
850 IN AMDSBCFG* pConfig
851 )
852{
853 UINT32 ddBar5;
854 sataBar5setting (pConfig, &ddBar5);
Paul Menzel00861622013-04-28 14:44:08 +0200855 //If this is not S3 resume and also if SATA set to one of IDE mode, then implement drive detection workaround.
efdesign98ee39ea72011-06-16 16:39:30 -0700856 if ( ! (pConfig->S3Resume) && ( ((pConfig->SataClass) != AHCI_MODE) && ((pConfig->SataClass) != RAID_MODE) ) ) {
857 sataDriveDetection (pConfig, &ddBar5);
858 }
859#ifdef SATA_BUS_DEV_FUN_FPGA
860 sataBar5settingFpga (pConfig, &ddBar5);
861 sataDriveDetectionFpga (pConfig, &ddBar5);
862#endif
863}
864
865/**
866 * sataDriveDetection - Sata drive detection
867 *
868 *
869 * @param[in] pConfig Southbridge configuration structure pointer.
870 * @param[in] *pBar5 Sata BAR5 base address.
871 *
872 */
873VOID
874sataDriveDetection (
875 IN AMDSBCFG* pConfig,
876 IN UINT32 *pBar5
877 )
878{
879 UINT32 ddVar0;
880 UINT8 dbPortNum;
881 UINT8 dbVar0;
882 UINT16 dwIoBase;
883 UINT32 ddVar1;
884 TRACE ((DMSG_SB_TRACE, "CIMx - Entering sata drive detection procedure\n\n"));
885 TRACE ((DMSG_SB_TRACE, "SATA BAR5 is %X \n", *pBar5));
886 if ( (pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE) || (pConfig->SataClass == IDE_TO_AHCI_MODE) ) {
887 for ( dbPortNum = 0; dbPortNum < 4; dbPortNum++ ) {
888 ReadMEM (*pBar5 + SB_SATA_BAR5_REG128 + dbPortNum * 0x80, AccWidthUint32, &ddVar0);
889 if ( ( ddVar0 & 0x0F ) == 0x03 ) {
890 if ( dbPortNum & BIT0 ) {
891 //this port belongs to secondary channel
892 ReadPCI (((UINT32) (SATA_BUS_DEV_FUN << 16) + SB_SATA_REG18), AccWidthUint16, &dwIoBase);
893 } else {
894 //this port belongs to primary channel
895 ReadPCI (((UINT32) (SATA_BUS_DEV_FUN << 16) + SB_SATA_REG10), AccWidthUint16, &dwIoBase);
896 }
897 //if legacy ide mode, then the bar registers don't contain the correct values. So we need to hardcode them
898 if ( pConfig->SataClass == LEGACY_IDE_MODE ) {
899 dwIoBase = ( (0x170) | ((UINT16) ( (~((UINT8) (dbPortNum & BIT0) << 7)) & 0x80 )) );
900 }
901 if ( dbPortNum & BIT1 ) {
902 //this port is slave
903 dbVar0 = 0xB0;
904 } else {
905 //this port is master
906 dbVar0 = 0xA0;
907 }
908 dwIoBase &= 0xFFF8;
909 WriteIO (dwIoBase + 6, AccWidthUint8, &dbVar0);
910 //Wait in loop for 30s for the drive to become ready
911 for ( ddVar1 = 0; ddVar1 < 300000; ddVar1++ ) {
912 ReadIO (dwIoBase + 7, AccWidthUint8, &dbVar0);
913 if ( (dbVar0 & 0x88) == 0 ) {
914 break;
915 }
916 SbStall (100);
917 }
918 } //end of if ( ( ddVar0 & 0x0F ) == 0x03)
919 } //for (dbPortNum = 0; dbPortNum < 4; dbPortNum++)
920 } //if ( (pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE) || (pConfig->SataClass == IDE_TO_AHCI_MODE))
921}
922
923#ifdef SATA_BUS_DEV_FUN_FPGA
924VOID
925sataDriveDetectionFpga (
926 IN AMDSBCFG* pConfig,
927 IN UINT32 *pBar5
928 )
929{
930 UINT32 ddVar0;
931 UINT8 dbPortNum;
932 UINT8 dbVar0;
933 UINT16 dwIoBase;
934 UINT32 ddVar1;
935 TRACE ((DMSG_SB_TRACE, "CIMx - Entering sata drive detection procedure\n\n"));
936 TRACE ((DMSG_SB_TRACE, "SATA BAR5 is %X \n", *pBar5));
937 for ( dbPortNum = 0; dbPortNum < 4; dbPortNum++ ) {
938 ReadMEM (*pBar5 + SB_SATA_BAR5_REG128 + dbPortNum * 0x80, AccWidthUint32, &ddVar0);
939 if ( ( ddVar0 & 0x0F ) == 0x03 ) {
940 if ( dbPortNum & BIT0 ) {
941 //this port belongs to secondary channel
942 ReadPCI (((UINT32) (SATA_BUS_DEV_FUN_FPGA << 16) + SB_SATA_REG18), AccWidthUint16, &dwIoBase);
943 } else {
944 //this port belongs to primary channel
945 ReadPCI (((UINT32) (SATA_BUS_DEV_FUN_FPGA << 16) + SB_SATA_REG10), AccWidthUint16, &dwIoBase);
946 }
947 //if legacy ide mode, then the bar registers don't contain the correct values. So we need to hardcode them
948 if ( pConfig->SataClass == LEGACY_IDE_MODE ) {
949 dwIoBase = ( (0x170) | ((UINT16) ( (~((UINT8) (dbPortNum & BIT0) << 7)) & 0x80 )) );
950 }
951 if ( dbPortNum & BIT1 ) {
952 //this port is slave
953 dbVar0 = 0xB0;
954 } else {
955 //this port is master
956 dbVar0 = 0xA0;
957 }
958 dwIoBase &= 0xFFF8;
959 WriteIO (dwIoBase + 6, AccWidthUint8, &dbVar0);
960 //Wait in loop for 30s for the drive to become ready
961 for ( ddVar1 = 0; ddVar1 < 300000; ddVar1++ ) {
962 ReadIO (dwIoBase + 7, AccWidthUint8, &dbVar0);
963 if ( (dbVar0 & 0x88) == 0 ) {
964 break;
965 }
966 SbStall (100);
967 }
968 } //end of if ( ( ddVar0 & 0x0F ) == 0x03)
969 } //for (dbPortNum = 0; dbPortNum < 4; dbPortNum++)
970}
971#endif
972
973/**
974 * sataInitLatePost - Prepare SATA controller to boot to OS.
975 *
976 * - Set class ID to AHCI (if set to AHCI * Mode)
977 * - Enable AHCI interrupt
978 *
979 * @param[in] pConfig Southbridge configuration structure pointer.
980 *
981 */
982VOID
983sataInitLatePost (
984 IN AMDSBCFG* pConfig
985 )
986{
987 UINT32 ddBar5;
988 UINT8 dbVar;
989 UINT8 dbPortNum;
990
991 //Return immediately is sata controller is not enabled
992 if ( pConfig->SATAMODE.SataMode.SataController == 0 ) {
993 return;
994 }
995 //Enable write access to pci header, pm capabilities
996 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, 0xff, BIT0);
997
998 sataBar5setting (pConfig, &ddBar5);
999
1000 ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar);
1001 //Enable memory and io access
1002 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, 0xFF, 0x03);
1003
1004 if (( pConfig->SataClass == IDE_TO_AHCI_MODE) || ( pConfig->SataClass == IDE_TO_AHCI_MODE_7804 )) {
1005 //program the AHCI class code
1006 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG08), AccWidthUint32 | S3_SAVE, 0, 0x01060100);
1007 //Set interrupt enable bit
1008 RWMEM ((ddBar5 + 0x04), AccWidthUint8, (UINT32)~0, BIT1);
1009 //program the correct device id for AHCI mode
1010 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, 0, SB_SATA_AHCI_DID);
1011 }
1012
1013 if (( pConfig->SataClass == AHCI_MODE_7804 ) || ( pConfig->SataClass == IDE_TO_AHCI_MODE_7804 )) {
1014 //program the correct device id for AHCI 7804 mode
1015 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, 0, SB_SATA_AMDAHCI_DID);
1016 }
1017 // OBS236459 IDE controller not shown in device manager when Os installed on IDE mode port
1018 //if ( pConfig->SataClass == IDE_TO_AHCI_MODE_7804 ) {
1019 //Disable IDE2 and Enable 8 channel for IDE-AHCI mode
1020 //RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint8, ~BIT1, BIT3);
1021 //}
1022
1023 //Clear error status
1024 RWMEM ((ddBar5 + SB_SATA_BAR5_REG130), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1025 RWMEM ((ddBar5 + SB_SATA_BAR5_REG1B0), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1026 RWMEM ((ddBar5 + SB_SATA_BAR5_REG230), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1027 RWMEM ((ddBar5 + SB_SATA_BAR5_REG2B0), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1028 RWMEM ((ddBar5 + SB_SATA_BAR5_REG330), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1029 RWMEM ((ddBar5 + SB_SATA_BAR5_REG3B0), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1030 RWMEM ((ddBar5 + SB_SATA_BAR5_REG430), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1031 RWMEM ((ddBar5 + SB_SATA_BAR5_REG4B0), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF);
1032 CaculateAhciPortNumber (pConfig, ddBar5);
1033 //Restore memory and io access bits
1034 WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar );
1035 //Disable write access to pci header and pm capabilities
1036 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0);
1037 for ( dbPortNum = 0; dbPortNum < 6; dbPortNum++ ) {
1038 RWMEM ((ddBar5 + 0x110 + (dbPortNum * 0x80)), AccWidthUint32, 0xFFFFFFFF, 0x00);
1039 }
1040}
1041
1042