blob: 2585c461382bcfcc99db4224434f69a227719778 [file] [log] [blame]
Furquan Shaikhf318e032020-05-04 23:38:53 -07001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
3
4#include <amdblocks/chip.h>
5#include <amdblocks/espi.h>
6#include <amdblocks/lpc.h>
7#include <arch/mmio.h>
8#include <console/console.h>
9#include <soc/pci_devs.h>
10#include <stddef.h>
11#include <stdint.h>
12#include <types.h>
13
14static uintptr_t espi_get_bar(void)
15{
16 uintptr_t espi_spi_base = lpc_get_spibase();
17 return espi_spi_base + ESPI_OFFSET_FROM_BAR;
18}
19
20static uint32_t espi_read32(int reg)
21{
22 return read32((void *)(espi_get_bar() + reg));
23}
24
25static void espi_write32(int reg, uint32_t val)
26{
27 write32((void *)(espi_get_bar() + reg), val);
28}
29
30static uint16_t espi_read16(int reg)
31{
32 return read16((void *)(espi_get_bar() + reg));
33}
34
35static void espi_write16(int reg, uint16_t val)
36{
37 write16((void *)(espi_get_bar() + reg), val);
38}
39
40static uint8_t espi_read8(int reg)
41{
42 return read8((void *)(espi_get_bar() + reg));
43}
44
45static void espi_write8(int reg, uint8_t val)
46{
47 write8((void *)(espi_get_bar() + reg), val);
48}
49
50static void espi_enable_decode(int decode_en)
51{
52 uint32_t val;
53
54 val = espi_read32(ESPI_DECODE);
55 val |= decode_en;
56 espi_write32(ESPI_DECODE, val);
57}
58
59static bool espi_is_decode_enabled(int decode)
60{
61 uint32_t val;
62
63 val = espi_read32(ESPI_DECODE);
64 return !!(val & decode);
65}
66
67static int espi_find_io_window(uint16_t win_base)
68{
69 int i;
70
71 for (i = 0; i < ESPI_GENERIC_IO_WIN_COUNT; i++) {
72 if (!espi_is_decode_enabled(ESPI_DECODE_IO_RANGE_EN(i)))
73 continue;
74
75 if (espi_read16(ESPI_IO_RANGE_BASE(i)) == win_base)
76 return i;
77 }
78
79 return -1;
80}
81
82static int espi_get_unused_io_window(void)
83{
84 int i;
85
86 for (i = 0; i < ESPI_GENERIC_IO_WIN_COUNT; i++) {
87 if (!espi_is_decode_enabled(ESPI_DECODE_IO_RANGE_EN(i)))
88 return i;
89 }
90
91 return -1;
92}
93
94/*
95 * Returns decode enable bits for standard IO port addresses. If port address is not supported
96 * by standard decode or if the size of window is not 1, then it returns -1.
97 */
98static int espi_std_io_decode(uint16_t base, size_t size)
99{
100 int ret = -1;
101
102 if (size != 1)
103 return ret;
104
105 switch (base) {
106 case 0x80:
107 ret = ESPI_DECODE_IO_0x80_EN;
108 break;
109 case 0x60:
110 case 0x64:
111 ret = ESPI_DECODE_IO_0X60_0X64_EN;
112 break;
113 case 0x2e:
114 case 0x2f:
115 ret = ESPI_DECODE_IO_0X2E_0X2F_EN;
116 break;
117 default:
118 ret = -1;
119 break;
120 }
121
122 return ret;
123}
124
125static size_t espi_get_io_window_size(int idx)
126{
127 return espi_read8(ESPI_IO_RANGE_SIZE(idx)) + 1;
128}
129
130static void espi_write_io_window(int idx, uint16_t base, size_t size)
131{
132 espi_write16(ESPI_IO_RANGE_BASE(idx), base);
133 espi_write8(ESPI_IO_RANGE_SIZE(idx), size - 1);
134}
135
136static int espi_open_generic_io_window(uint16_t base, size_t size)
137{
138 size_t win_size;
139 int idx;
140
141 for (; size; size -= win_size, base += win_size) {
142 win_size = MIN(size, ESPI_GENERIC_IO_MAX_WIN_SIZE);
143
144 idx = espi_find_io_window(base);
145 if (idx != -1) {
146 size_t curr_size = espi_get_io_window_size(idx);
147
148 if (curr_size > win_size) {
149 printk(BIOS_INFO, "eSPI window already configured to be larger than requested! ");
150 printk(BIOS_INFO, "Base: 0x%x, Requested size: 0x%zx, Actual size: 0x%zx\n",
151 base, win_size, curr_size);
152 } else if (curr_size < win_size) {
153 espi_write_io_window(idx, base, win_size);
154 printk(BIOS_INFO, "eSPI window at base: 0x%x resized from 0x%zx to 0x%zx\n",
155 base, curr_size, win_size);
156 }
157
158 continue;
159 }
160
161 idx = espi_get_unused_io_window();
162 if (idx == -1) {
163 printk(BIOS_ERR, "Cannot open IO window base %x size %zx\n", base,
164 size);
165 printk(BIOS_ERR, "ERROR: No more available IO windows!\n");
166 return -1;
167 }
168
169 espi_write_io_window(idx, base, win_size);
170 espi_enable_decode(ESPI_DECODE_IO_RANGE_EN(idx));
171 }
172
173 return 0;
174}
175
176int espi_open_io_window(uint16_t base, size_t size)
177{
178 int std_io;
179
180 std_io = espi_std_io_decode(base, size);
181 if (std_io != -1) {
182 espi_enable_decode(std_io);
183 return 0;
184 }
185
186 return espi_open_generic_io_window(base, size);
187}
188
189static int espi_find_mmio_window(uint32_t win_base)
190{
191 int i;
192
193 for (i = 0; i < ESPI_GENERIC_MMIO_WIN_COUNT; i++) {
194 if (!espi_is_decode_enabled(ESPI_DECODE_MMIO_RANGE_EN(i)))
195 continue;
196
197 if (espi_read32(ESPI_MMIO_RANGE_BASE(i)) == win_base)
198 return i;
199 }
200
201 return -1;
202}
203
204static int espi_get_unused_mmio_window(void)
205{
206 int i;
207
208 for (i = 0; i < ESPI_GENERIC_MMIO_WIN_COUNT; i++) {
209 if (!espi_is_decode_enabled(ESPI_DECODE_MMIO_RANGE_EN(i)))
210 return i;
211 }
212
213 return -1;
214
215}
216
217static size_t espi_get_mmio_window_size(int idx)
218{
219 return espi_read16(ESPI_MMIO_RANGE_SIZE(idx)) + 1;
220}
221
222static void espi_write_mmio_window(int idx, uint32_t base, size_t size)
223{
224 espi_write32(ESPI_MMIO_RANGE_BASE(idx), base);
225 espi_write16(ESPI_MMIO_RANGE_SIZE(idx), size - 1);
226}
227
228int espi_open_mmio_window(uint32_t base, size_t size)
229{
230 size_t win_size;
231 int idx;
232
233 for (; size; size -= win_size, base += win_size) {
234 win_size = MIN(size, ESPI_GENERIC_MMIO_MAX_WIN_SIZE);
235
236 idx = espi_find_mmio_window(base);
237 if (idx != -1) {
238 size_t curr_size = espi_get_mmio_window_size(idx);
239
240 if (curr_size > win_size) {
241 printk(BIOS_INFO, "eSPI window already configured to be larger than requested! ");
242 printk(BIOS_INFO, "Base: 0x%x, Requested size: 0x%zx, Actual size: 0x%zx\n",
243 base, win_size, curr_size);
244 } else if (curr_size < win_size) {
245 espi_write_mmio_window(idx, base, win_size);
246 printk(BIOS_INFO, "eSPI window at base: 0x%x resized from 0x%zx to 0x%zx\n",
247 base, curr_size, win_size);
248 }
249
250 continue;
251 }
252
253 idx = espi_get_unused_mmio_window();
254 if (idx == -1) {
255 printk(BIOS_ERR, "Cannot open IO window base %x size %zx\n", base,
256 size);
257 printk(BIOS_ERR, "ERROR: No more available MMIO windows!\n");
258 return -1;
259 }
260
261 espi_write_mmio_window(idx, base, win_size);
262 espi_enable_decode(ESPI_DECODE_MMIO_RANGE_EN(idx));
263 }
264
265 return 0;
266}
267
268static const struct espi_config *espi_get_config(void)
269{
270 const struct soc_amd_common_config *soc_cfg = soc_get_common_config();
271
272 if (!soc_cfg)
273 die("Common config structure is NULL!\n");
274
275 return &soc_cfg->espi_config;
276}
277
278void espi_configure_decodes(void)
279{
280 int i;
281 const struct espi_config *cfg = espi_get_config();
282
283 espi_enable_decode(cfg->std_io_decode_bitmap);
284
285 for (i = 0; i < ESPI_GENERIC_IO_WIN_COUNT; i++) {
286 if (cfg->generic_io_range[i].size == 0)
287 continue;
288 espi_open_generic_io_window(cfg->generic_io_range[i].base,
289 cfg->generic_io_range[i].size);
290 }
291}