blob: 4abc15f59ad2d95115755af43ebd22b0859b26a8 [file] [log] [blame]
Subrata Banik7609c652017-05-19 14:50:09 +05301/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2017 Intel Corporation.
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
16#include <arch/io.h>
17#include <delay.h>
18#include <device/device.h>
19#include <device/pci.h>
20#include <intelblocks/systemagent.h>
21#include <soc/iomap.h>
22#include <soc/pci_devs.h>
23#include <soc/systemagent.h>
24#include "systemagent_def.h"
25#include <timer.h>
26
27#if !ENV_RAMSTAGE
28void bootblock_systemagent_early_init(void)
29{
30 uint32_t reg;
31 uint8_t pciexbar_length;
32
33 /*
34 * The PCIEXBAR is assumed to live in the memory mapped IO space under
35 * 4GiB.
36 */
37 reg = 0;
38 pci_io_write_config32(SA_DEV_ROOT, PCIEXBAR + 4, reg);
39
40 /* Get PCI Express Region Length */
41 switch (CONFIG_SA_PCIEX_LENGTH) {
42 case 256 * MiB:
43 pciexbar_length = PCIEXBAR_LENGTH_256MB;
44 break;
45 case 128 * MiB:
46 pciexbar_length = PCIEXBAR_LENGTH_128MB;
47 break;
48 case 64 * MiB:
49 pciexbar_length = PCIEXBAR_LENGTH_64MB;
50 break;
51 default:
52 pciexbar_length = PCIEXBAR_LENGTH_256MB;
53 }
54 reg = CONFIG_MMCONF_BASE_ADDRESS | (pciexbar_length << 1)
55 | PCIEXBAR_PCIEXBAREN;
56 pci_io_write_config32(SA_DEV_ROOT, PCIEXBAR, reg);
57
58 /*
59 * TSEG defines the base of SMM range. BIOS determines the base
60 * of TSEG memory which must be at or below Graphics base of GTT
61 * Stolen memory, hence its better to clear TSEG register early
62 * to avoid power on default non-zero value (if any).
63 */
64 pci_write_config32(SA_DEV_ROOT, TSEG, 0);
65}
66#endif
67
68void sa_set_pci_bar(const struct sa_mmio_descriptor *fixed_set_resources,
69 size_t count)
70{
71 int i;
72
73 for (i = 0; i < count; i++) {
74 uintptr_t base;
75 unsigned int index;
76
77 index = fixed_set_resources[i].index;
78 /* Check if PCI BAR already enabled */
79 base = pci_read_config32(SA_DEV_ROOT, index);
80
81 /* If enabled don't program it. */
82 if (base & 0x1)
83 return;
84
85 base = fixed_set_resources[i].base;
86
87 pci_write_config32(SA_DEV_ROOT, index, base | 1);
88 }
89}
90
91/*
92 * There are special BARs that actually are programmed in the MCHBAR. These
93 * Intel special features, but they do consume resources that need to be
94 * accounted for.
95 */
96void sa_set_mch_bar(const struct sa_mmio_descriptor *fixed_set_resources,
97 size_t count)
98{
99 int i;
100
101 for (i = 0; i < count; i++) {
102 uintptr_t base;
103 unsigned int index;
104
105 base = fixed_set_resources[i].base;
106 index = fixed_set_resources[i].index;
107 write32((void *)(MCH_BASE_ADDRESS + index), base | 1);
108 }
109}
110
111void enable_pam_region(void)
112{
113 /* All read and writes in this region are serviced by DRAM */
114 pci_write_config8(SA_DEV_ROOT, PAM0, 0x30);
115 pci_write_config8(SA_DEV_ROOT, PAM1, 0x33);
116 pci_write_config8(SA_DEV_ROOT, PAM2, 0x33);
117 pci_write_config8(SA_DEV_ROOT, PAM3, 0x33);
118 pci_write_config8(SA_DEV_ROOT, PAM4, 0x33);
119 pci_write_config8(SA_DEV_ROOT, PAM5, 0x33);
120 pci_write_config8(SA_DEV_ROOT, PAM6, 0x33);
121}
122
123void enable_bios_reset_cpl(void)
124{
125 u8 bios_reset_cpl;
126
127 /*
128 * Set bits 0+1 of BIOS_RESET_CPL to indicate to the CPU
129 * that BIOS has initialized memory and power management
130 */
131 bios_reset_cpl = MCHBAR8(BIOS_RESET_CPL);
132 bios_reset_cpl |= 3;
133 MCHBAR8(BIOS_RESET_CPL) = bios_reset_cpl;
134}
Subrata Banikbd6ac222017-08-21 16:42:15 +0530135
Subrata Banik73f448f2017-08-29 18:51:14 +0530136uintptr_t sa_get_tolud_base(void)
Subrata Banikbd6ac222017-08-21 16:42:15 +0530137{
138 /* All regions concerned for have 1 MiB alignment. */
139 return ALIGN_DOWN(pci_read_config32(SA_DEV_ROOT, TOLUD), 1*MiB);
140}
141
142static uint16_t sa_get_ggc_reg(void)
143{
144 return pci_read_config16(SA_DEV_ROOT, GGC);
145}
146
147size_t sa_get_dsm_size(void)
148{
149 return (((sa_get_ggc_reg() & G_GMS_MASK) >> G_GMS_OFFSET) * 32*MiB);
150}
151
Subrata Banik73f448f2017-08-29 18:51:14 +0530152static uintptr_t sa_get_gsm_base(void)
153{
154 /* All regions concerned for have 1 MiB alignment. */
155 return ALIGN_DOWN(pci_read_config32(SA_DEV_ROOT, BGSM), 1*MiB);
156}
157
Subrata Banikbd6ac222017-08-21 16:42:15 +0530158size_t sa_get_gsm_size(void)
159{
160 uint8_t ggms;
161
162 ggms = (sa_get_ggc_reg() & G_GGMS_MASK) >> G_GGMS_OFFSET;
163
164 /*
165 * Size of GSM: 0x0: No Preallocated Memory 0x1: 2MB Memory
166 * 0x2: 4MB Memory 0x3: 8MB Memory
167 */
168 if (ggms)
169 return 1*MiB << ggms;
170 else
171 return 0;
172}
173
Subrata Banik73f448f2017-08-29 18:51:14 +0530174uintptr_t sa_get_tseg_base(void)
175{
176 /* All regions concerned for have 1 MiB alignment. */
177 return ALIGN_DOWN(pci_read_config32(SA_DEV_ROOT, TSEG), 1*MiB);
178}
179
180size_t sa_get_tseg_size(void)
181{
182 return sa_get_gsm_base() - sa_get_tseg_base();
183}
184
Subrata Banikbd6ac222017-08-21 16:42:15 +0530185/*
186 * Get DPR size in case CONFIG_SA_ENABLE_DPR is selected by SoC.
187 */
188size_t sa_get_dpr_size(void)
189{
190 uintptr_t dpr_reg;
191 size_t size = 0;
192 /*
193 * DMA Protected Range can be reserved below TSEG for PCODE patch
194 * or TXT/BootGuard related data. Rather than report a base address
195 * the DPR register reports the TOP of the region, which is the same
196 * as TSEG base. The region size is reported in MiB in bits 11:4.
197 */
198 dpr_reg = pci_read_config32(SA_DEV_ROOT, DPR);
199 if (dpr_reg & DPR_EPM)
200 size = (dpr_reg & DPR_SIZE_MASK) << 16;
201
202 return size;
203}