blob: 62baf24c33c61d9d2adcb29534fd5a70d3d307a4 [file] [log] [blame]
efdesign9895b66112011-07-20 13:23:04 -06001/*
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
efdesign9895b66112011-07-20 13:23:04 -060018 */
19
20#include "agesawrapper.h"
21#include "amdlib.h"
22#include "BiosCallOuts.h"
23#include "Ids.h"
24#include "OptionsIds.h"
25#include "heapManager.h"
Kimarie Hooteef45f92013-03-08 13:54:10 -070026#include <northbridge/amd/agesa/family15/dimmSpd.h>
27#include <arch/io.h>
Kimarie Hooteef45f92013-03-08 13:54:10 -070028
29#ifdef __PRE_RAM__
30/* These defines are used to select the appropriate socket for the SPD read
31 * because this is a multi-socket design.
32 */
33#define PCI_REG_GPIO_56_to_53_CNTRL (0x52)
34#define GPIO_OUT_BIT_GPIO53 (BIT0)
35#define GPIO_OUT_BIT_GPIO54 (BIT1)
36#define GPIO_OUT_ENABLE_BIT_GPIO53 (BIT4)
37#define GPIO_OUT_ENABLE_BIT_GPIO54 (BIT5)
38
39#define GPIO_OUT_BIT_GPIO54_to_53_MASK \
40 (GPIO_OUT_BIT_GPIO54 | GPIO_OUT_BIT_GPIO53)
41#define GPIO_OUT_ENABLE_BIT_GPIO54_to_53_MASK \
42 (GPIO_OUT_ENABLE_BIT_GPIO54 | GPIO_OUT_ENABLE_BIT_GPIO53)
43
44static UINT8 select_socket(UINT8 socket_id)
45{
46 device_t sm_dev = PCI_DEV(0, 0x14, 0); //SMBus
47 UINT8 value = 0;
48 UINT8 gpio56_to_53 = 0;
49
50 /* Configure GPIO54,53 to select the desired socket
51 * GPIO54,53 control the HC4052 S1,S0
52 * S1 S0 true table
53 * 0 0 channel 1 (Socket1)
54 * 0 1 channel 2 (Socket2)
55 * 1 0 channel 3 (Socket3)
56 * 1 1 channel 4 (Socket4)
57 */
58 gpio56_to_53 = pci_read_config8(sm_dev, PCI_REG_GPIO_56_to_53_CNTRL);
59 value = gpio56_to_53 & (~GPIO_OUT_BIT_GPIO54_to_53_MASK);
60 value |= socket_id;
61 value &= (~GPIO_OUT_ENABLE_BIT_GPIO54_to_53_MASK); // 0=Output Enabled, 1=Tristate
62 pci_write_config8(sm_dev, PCI_REG_GPIO_56_to_53_CNTRL, value);
63
64 return gpio56_to_53;
65}
66
67static void restore_socket(UINT8 original_value)
68{
69 device_t sm_dev = PCI_DEV(0, 0x14, 0); //SMBus
70 pci_write_config8(sm_dev, PCI_REG_GPIO_56_to_53_CNTRL, original_value);
71}
72#endif
efdesign9895b66112011-07-20 13:23:04 -060073
Aladyshev Konstantin3d63b0a2012-12-19 00:58:35 +040074STATIC BIOS_CALLOUT_STRUCT BiosCallouts[] =
efdesign9895b66112011-07-20 13:23:04 -060075{
Kyösti Mälkki08df7322014-05-04 14:53:36 +030076 {AGESA_ALLOCATE_BUFFER, BiosAllocateBuffer },
77 {AGESA_DEALLOCATE_BUFFER, BiosDeallocateBuffer },
78 {AGESA_DO_RESET, BiosReset },
79 {AGESA_LOCATE_BUFFER, BiosLocateBuffer },
80 {AGESA_READ_SPD, BiosReadSpd },
Kyösti Mälkkic459f962014-05-04 17:07:45 +030081 {AGESA_READ_SPD_RECOVERY, agesa_NoopUnsupported },
Kyösti Mälkki08df7322014-05-04 14:53:36 +030082 {AGESA_RUNFUNC_ONAP, BiosRunFuncOnAp },
Kyösti Mälkkic459f962014-05-04 17:07:45 +030083 {AGESA_GET_IDS_INIT_DATA, agesa_EmptyIdsInitData },
84 {AGESA_HOOKBEFORE_DQS_TRAINING, agesa_NoopSuccess },
85 {AGESA_HOOKBEFORE_DRAM_INIT, agesa_NoopSuccess },
86 {AGESA_HOOKBEFORE_EXIT_SELF_REF, agesa_NoopSuccess },
efdesign9895b66112011-07-20 13:23:04 -060087};
88
efdesign9895b66112011-07-20 13:23:04 -060089AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
90{
91 UINTN i;
92 AGESA_STATUS CalloutStatus;
Aladyshev Konstantin3d63b0a2012-12-19 00:58:35 +040093 UINTN CallOutCount = sizeof (BiosCallouts) / sizeof (BiosCallouts [0]);
efdesign9895b66112011-07-20 13:23:04 -060094
Aladyshev Konstantin3d63b0a2012-12-19 00:58:35 +040095 for (i = 0; i < CallOutCount; i++) {
efdesign9895b66112011-07-20 13:23:04 -060096 if (BiosCallouts[i].CalloutName == Func) {
97 break;
98 }
99 }
100
Aladyshev Konstantin3d63b0a2012-12-19 00:58:35 +0400101 if(i >= CallOutCount) {
efdesign9895b66112011-07-20 13:23:04 -0600102 return AGESA_UNSUPPORTED;
103 }
104
105 CalloutStatus = BiosCallouts[i].CalloutPtr (Func, Data, ConfigPtr);
106
107 return CalloutStatus;
108}
109
efdesign9895b66112011-07-20 13:23:04 -0600110AGESA_STATUS BiosReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
111{
112 AGESA_STATUS Status;
Kimarie Hooteef45f92013-03-08 13:54:10 -0700113#ifdef __PRE_RAM__
114 UINT8 original_value = 0;
115
116 if (ConfigPtr == NULL)
117 return AGESA_ERROR;
118
119 original_value = select_socket(((AGESA_READ_SPD_PARAMS *)ConfigPtr)->SocketId);
120
121 Status = agesa_ReadSPD (Func, Data, ConfigPtr);
122
123 restore_socket(original_value);
124#else
125 Status = AGESA_UNSUPPORTED;
126#endif
efdesign9895b66112011-07-20 13:23:04 -0600127
128 return Status;
129}