blob: c370491098ac6b0f57b3d061f435b2ce90df524f [file] [log] [blame]
Frank Vibrans69da1b62011-02-14 19:04:45 +00001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2011 Advanced Micro Devices, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Paul Menzela46a7122013-02-23 18:37:27 +010017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Frank Vibrans69da1b62011-02-14 19:04:45 +000018 */
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070019
Frank Vibrans69da1b62011-02-14 19:04:45 +000020#include "agesawrapper.h"
21#include "amdlib.h"
22#include "BiosCallOuts.h"
Frank Vibrans69da1b62011-02-14 19:04:45 +000023#include "heapManager.h"
24#include "SB800.h"
Kimarie Hoot31c5e072013-03-06 16:18:09 -070025#include <northbridge/amd/agesa/family14/dimmSpd.h>
Frank Vibrans69da1b62011-02-14 19:04:45 +000026
Kerry Sheh01f7ab92012-01-19 13:18:36 +080027STATIC BIOS_CALLOUT_STRUCT BiosCallouts[] =
Frank Vibrans69da1b62011-02-14 19:04:45 +000028{
Kyösti Mälkki08df7322014-05-04 14:53:36 +030029 {AGESA_ALLOCATE_BUFFER, BiosAllocateBuffer },
30 {AGESA_DEALLOCATE_BUFFER, BiosDeallocateBuffer },
Kyösti Mälkki08df7322014-05-04 14:53:36 +030031 {AGESA_LOCATE_BUFFER, BiosLocateBuffer },
Kyösti Mälkki5e19fa42014-05-04 23:13:54 +030032 {AGESA_DO_RESET, agesa_Reset },
Kyösti Mälkki08df7322014-05-04 14:53:36 +030033 {AGESA_READ_SPD, BiosReadSpd },
Kyösti Mälkkic459f962014-05-04 17:07:45 +030034 {AGESA_READ_SPD_RECOVERY, agesa_NoopUnsupported },
Kyösti Mälkki08df7322014-05-04 14:53:36 +030035 {AGESA_RUNFUNC_ONAP, BiosRunFuncOnAp },
36 {AGESA_GNB_PCIE_SLOT_RESET, BiosGnbPcieSlotReset },
37 {AGESA_HOOKBEFORE_DRAM_INIT, BiosHookBeforeDramInit },
Kyösti Mälkkic459f962014-05-04 17:07:45 +030038 {AGESA_HOOKBEFORE_DRAM_INIT_RECOVERY, agesa_NoopSuccess },
39 {AGESA_HOOKBEFORE_DQS_TRAINING, agesa_NoopSuccess },
40 {AGESA_HOOKBEFORE_EXIT_SELF_REF, agesa_NoopSuccess },
Frank Vibrans69da1b62011-02-14 19:04:45 +000041};
42
43AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
44{
Kerry Shehf03360f2012-01-19 13:25:55 +080045 UINTN i;
46 AGESA_STATUS CalloutStatus;
Kerry Sheh01f7ab92012-01-19 13:18:36 +080047 UINTN CallOutCount = sizeof (BiosCallouts) / sizeof (BiosCallouts [0]);
Frank Vibrans69da1b62011-02-14 19:04:45 +000048
Kerry Sheh01f7ab92012-01-19 13:18:36 +080049 CalloutStatus = AGESA_UNSUPPORTED;
Frank Vibrans69da1b62011-02-14 19:04:45 +000050
Kerry Sheh01f7ab92012-01-19 13:18:36 +080051 for (i = 0; i < CallOutCount; i++) {
52 if (BiosCallouts[i].CalloutName == Func) {
Kerry Shehf03360f2012-01-19 13:25:55 +080053 CalloutStatus = BiosCallouts[i].CalloutPtr (Func, Data, ConfigPtr);
54 return CalloutStatus;
55 }
56 }
Frank Vibrans69da1b62011-02-14 19:04:45 +000057
Kerry Sheh01f7ab92012-01-19 13:18:36 +080058 return CalloutStatus;
59}
Frank Vibrans69da1b62011-02-14 19:04:45 +000060
Frank Vibrans69da1b62011-02-14 19:04:45 +000061/* Call the host environment interface to provide a user hook opportunity. */
Frank Vibrans69da1b62011-02-14 19:04:45 +000062AGESA_STATUS BiosHookBeforeDramInit (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
63{
Kerry Shehf03360f2012-01-19 13:25:55 +080064 AGESA_STATUS Status;
65 UINTN FcnData;
66 MEM_DATA_STRUCT *MemData;
67 UINT32 AcpiMmioAddr;
68 UINT32 GpioMmioAddr;
69 UINT8 Data8;
70 UINT16 Data16;
71 UINT8 TempData8;
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070072
Kerry Shehf03360f2012-01-19 13:25:55 +080073 FcnData = Data;
74 MemData = ConfigPtr;
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070075
Kerry Shehf03360f2012-01-19 13:25:55 +080076 Status = AGESA_SUCCESS;
Kerry Sheh01f7ab92012-01-19 13:18:36 +080077 /* Get SB MMIO Base (AcpiMmioAddr) */
Kerry Shehf03360f2012-01-19 13:25:55 +080078 WriteIo8 (0xCD6, 0x27);
79 Data8 = ReadIo8(0xCD7);
80 Data16 = Data8<<8;
81 WriteIo8 (0xCD6, 0x26);
82 Data8 = ReadIo8(0xCD7);
83 Data16 |= Data8;
84 AcpiMmioAddr = (UINT32)Data16 << 16;
85 GpioMmioAddr = AcpiMmioAddr + GPIO_BASE;
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070086
Kerry Shehf03360f2012-01-19 13:25:55 +080087 Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG178);
88 Data8 &= ~BIT5;
89 TempData8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG178);
90 TempData8 &= 0x03;
91 TempData8 |= Data8;
92 Write64Mem8(GpioMmioAddr+SB_GPIO_REG178, TempData8);
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070093
Kerry Shehf03360f2012-01-19 13:25:55 +080094 Data8 |= BIT2+BIT3;
95 Data8 &= ~BIT4;
96 TempData8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG178);
97 TempData8 &= 0x23;
98 TempData8 |= Data8;
99 Write64Mem8(GpioMmioAddr+SB_GPIO_REG178, TempData8);
Kerry Sheh01f7ab92012-01-19 13:18:36 +0800100
Kerry Shehf03360f2012-01-19 13:25:55 +0800101 Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG179);
102 Data8 &= ~BIT5;
103 TempData8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG179);
104 TempData8 &= 0x03;
105 TempData8 |= Data8;
106 Write64Mem8(GpioMmioAddr+SB_GPIO_REG179, TempData8);
Kerry Sheh01f7ab92012-01-19 13:18:36 +0800107
Kerry Shehf03360f2012-01-19 13:25:55 +0800108 Data8 |= BIT2+BIT3;
109 Data8 &= ~BIT4;
110 TempData8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG179);
111 TempData8 &= 0x23;
112 TempData8 |= Data8;
113 Write64Mem8(GpioMmioAddr+SB_GPIO_REG179, TempData8);
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700114
Kerry Shehf03360f2012-01-19 13:25:55 +0800115 switch(MemData->ParameterListPtr->DDR3Voltage){
116 case VOLT1_35:
117 Data8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG178);
118 Data8 &= ~(UINT8)BIT6;
119 Write64Mem8(GpioMmioAddr+SB_GPIO_REG178, Data8);
120 Data8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG179);
121 Data8 |= (UINT8)BIT6;
122 Write64Mem8(GpioMmioAddr+SB_GPIO_REG179, Data8);
123 break;
124 case VOLT1_25:
125 Data8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG178);
126 Data8 &= ~(UINT8)BIT6;
127 Write64Mem8(GpioMmioAddr+SB_GPIO_REG178, Data8);
128 Data8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG179);
129 Data8 &= ~(UINT8)BIT6;
130 Write64Mem8(GpioMmioAddr+SB_GPIO_REG179, Data8);
131 break;
132 case VOLT1_5:
133 default:
134 Data8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG178);
135 Data8 |= (UINT8)BIT6;
136 Write64Mem8(GpioMmioAddr+SB_GPIO_REG178, Data8);
137 Data8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG179);
138 Data8 &= ~(UINT8)BIT6;
139 Write64Mem8(GpioMmioAddr+SB_GPIO_REG179, Data8);
140 }
141 return Status;
Frank Vibrans69da1b62011-02-14 19:04:45 +0000142}
Kerry Sheh01f7ab92012-01-19 13:18:36 +0800143
Frank Vibrans69da1b62011-02-14 19:04:45 +0000144/* PCIE slot reset control */
145AGESA_STATUS BiosGnbPcieSlotReset (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
146{
Kerry Shehf03360f2012-01-19 13:25:55 +0800147 AGESA_STATUS Status;
148 UINTN FcnData;
149 PCIe_SLOT_RESET_INFO *ResetInfo;
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700150
Kerry Shehf03360f2012-01-19 13:25:55 +0800151 UINT32 GpioMmioAddr;
152 UINT32 AcpiMmioAddr;
153 UINT8 Data8;
154 UINT16 Data16;
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700155
Kerry Shehf03360f2012-01-19 13:25:55 +0800156 FcnData = Data;
157 ResetInfo = ConfigPtr;
158 // Get SB800 MMIO Base (AcpiMmioAddr)
159 WriteIo8(0xCD6, 0x27);
160 Data8 = ReadIo8(0xCD7);
161 Data16=Data8<<8;
162 WriteIo8(0xCD6, 0x26);
163 Data8 = ReadIo8(0xCD7);
164 Data16|=Data8;
165 AcpiMmioAddr = (UINT32)Data16 << 16;
166 Status = AGESA_UNSUPPORTED;
167 GpioMmioAddr = AcpiMmioAddr + GPIO_BASE;
168 switch (ResetInfo->ResetId)
169 {
170 case 4:
171 switch (ResetInfo->ResetControl) {
172 case AssertSlotReset:
173 Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG21);
174 Data8 &= ~(UINT8)BIT6 ;
175 Write64Mem8(GpioMmioAddr+SB_GPIO_REG21, Data8); // MXM_GPIO0. GPIO21
176 Status = AGESA_SUCCESS;
177 break;
178 case DeassertSlotReset:
179 Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG21);
180 Data8 |= BIT6 ;
181 Write64Mem8 (GpioMmioAddr+SB_GPIO_REG21, Data8); // MXM_GPIO0. GPIO21
182 Status = AGESA_SUCCESS;
183 break;
184 }
185 break;
186 case 6:
187 switch (ResetInfo->ResetControl) {
188 case AssertSlotReset:
189 Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG25);
190 Data8 &= ~(UINT8)BIT6 ;
191 Write64Mem8(GpioMmioAddr+SB_GPIO_REG25, Data8); // PCIE_RST#_LAN, GPIO25
192 Status = AGESA_SUCCESS;
193 break;
194 case DeassertSlotReset:
195 Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG25);
196 Data8 |= BIT6 ;
197 Write64Mem8 (GpioMmioAddr+SB_GPIO_REG25, Data8); // PCIE_RST#_LAN, GPIO25
198 Status = AGESA_SUCCESS;
199 break;
200 }
201 break;
202 case 7:
203 switch (ResetInfo->ResetControl) {
204 case AssertSlotReset:
205 Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG02);
206 Data8 &= ~(UINT8)BIT6 ;
207 Write64Mem8(GpioMmioAddr+SB_GPIO_REG02, Data8); // MPCIE_RST0, GPIO02
208 Status = AGESA_SUCCESS;
209 break;
210 case DeassertSlotReset:
Jens Rottmannf87855c2013-02-18 18:56:48 +0100211 Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG02);
Kerry Shehf03360f2012-01-19 13:25:55 +0800212 Data8 |= BIT6 ;
213 Write64Mem8 (GpioMmioAddr+SB_GPIO_REG02, Data8); // MPCIE_RST0, GPIO02
214 Status = AGESA_SUCCESS;
215 break;
216 }
217 break;
218 }
219 return Status;
Frank Vibrans69da1b62011-02-14 19:04:45 +0000220}