blob: 5c0b17ba2a0772ecd3f895a5ec41a383ff412d88 [file] [log] [blame]
Barnali Sarkar89331cd2017-02-16 17:22:37 +05301/*
2 * This file is part of the coreboot project.
3 *
Barnali Sarkar89331cd2017-02-16 17:22:37 +05304 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
Kyösti Mälkki13f66502019-03-03 08:01:05 +020015#include <device/mmio.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053016#include <assert.h>
17#include <device/pci_def.h>
Patrick Rudolphe56189c2018-04-18 10:11:59 +020018#include <device/pci_ops.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053019#include <commonlib/helpers.h>
Aaron Durbin5391e552017-06-02 12:16:04 -050020#include <cpu/x86/mtrr.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053021#include <fast_spi_def.h>
22#include <intelblocks/fast_spi.h>
Aaron Durbin5391e552017-06-02 12:16:04 -050023#include <lib.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053024#include <soc/pci_devs.h>
25#include <spi_flash.h>
26#include <spi-generic.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053027
28/*
29 * Get the FAST_SPIBAR.
30 */
31void *fast_spi_get_bar(void)
32{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +020033#if defined(__SIMPLE_DEVICE__)
34 pci_devfn_t dev = PCH_DEV_SPI;
35#else
36 struct device *dev = PCH_DEV_SPI;
37#endif
Barnali Sarkar89331cd2017-02-16 17:22:37 +053038 uintptr_t bar;
39
40 bar = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
41 assert(bar != 0);
42 /*
43 * Bits 31-12 are the base address as per EDS for SPI,
44 * Don't care about 0-11 bit
45 */
46 return (void *)(bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK);
47}
48
49/*
50 * Disable the BIOS write protect and Enable Prefetching and Caching.
51 */
52void fast_spi_init(void)
53{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +020054#if defined(__SIMPLE_DEVICE__)
55 pci_devfn_t dev = PCH_DEV_SPI;
56#else
57 struct device *dev = PCH_DEV_SPI;
58#endif
Barnali Sarkar89331cd2017-02-16 17:22:37 +053059 uint8_t bios_cntl;
60
61 bios_cntl = pci_read_config8(dev, SPIBAR_BIOS_CONTROL);
62
63 /* Disable the BIOS write protect so write commands are allowed. */
64 bios_cntl &= ~SPIBAR_BIOS_CONTROL_EISS;
65 bios_cntl |= SPIBAR_BIOS_CONTROL_WPD;
66 /* Enable Prefetching and caching. */
67 bios_cntl |= SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE;
68 bios_cntl &= ~SPIBAR_BIOS_CONTROL_CACHE_DISABLE;
69
70 pci_write_config8(dev, SPIBAR_BIOS_CONTROL, bios_cntl);
71}
72
73/*
Subrata Banik8e390092017-07-21 10:06:17 +053074 * Set FAST_SPIBAR BIOS Control register based on input bit field.
Barnali Sarkar89331cd2017-02-16 17:22:37 +053075 */
76static void fast_spi_set_bios_control_reg(uint8_t bios_cntl_bit)
77{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +020078#if defined(__SIMPLE_DEVICE__)
79 pci_devfn_t dev = PCH_DEV_SPI;
80#else
81 struct device *dev = PCH_DEV_SPI;
82#endif
Barnali Sarkar89331cd2017-02-16 17:22:37 +053083 uint8_t bc_cntl;
84
85 assert((bios_cntl_bit & (bios_cntl_bit - 1)) == 0);
86 bc_cntl = pci_read_config8(dev, SPIBAR_BIOS_CONTROL);
87 bc_cntl |= bios_cntl_bit;
88 pci_write_config8(dev, SPIBAR_BIOS_CONTROL, bc_cntl);
89}
90
91/*
Subrata Banik8e390092017-07-21 10:06:17 +053092 * Ensure an additional read back after performing lock down
93 */
94static void fast_spi_read_post_write(uint8_t reg)
95{
96 pci_read_config8(PCH_DEV_SPI, reg);
97}
98
99/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530100 * Set FAST_SPIBAR BIOS Control BILD bit.
101 */
102void fast_spi_set_bios_interface_lock_down(void)
103{
104 fast_spi_set_bios_control_reg(SPIBAR_BIOS_CONTROL_BILD);
Subrata Banik8e390092017-07-21 10:06:17 +0530105
106 fast_spi_read_post_write(SPIBAR_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530107}
108
109/*
110 * Set FAST_SPIBAR BIOS Control LE bit.
111 */
112void fast_spi_set_lock_enable(void)
113{
114 fast_spi_set_bios_control_reg(SPIBAR_BIOS_CONTROL_LOCK_ENABLE);
Subrata Banik8e390092017-07-21 10:06:17 +0530115
116
117 fast_spi_read_post_write(SPIBAR_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530118}
119
120/*
121 * Set FAST_SPIBAR BIOS Control EISS bit.
122 */
123void fast_spi_set_eiss(void)
124{
125 fast_spi_set_bios_control_reg(SPIBAR_BIOS_CONTROL_EISS);
Subrata Banik8e390092017-07-21 10:06:17 +0530126
127 fast_spi_read_post_write(SPIBAR_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530128}
129
130/*
131 * Set FAST_SPI opcode menu.
132 */
133void fast_spi_set_opcode_menu(void)
134{
135 void *spibar = fast_spi_get_bar();
136
137 write16(spibar + SPIBAR_PREOP, SPI_OPPREFIX);
138 write16(spibar + SPIBAR_OPTYPE, SPI_OPTYPE);
139 write32(spibar + SPIBAR_OPMENU_LOWER, SPI_OPMENU_LOWER);
140 write32(spibar + SPIBAR_OPMENU_UPPER, SPI_OPMENU_UPPER);
141}
142
143/*
144 * Lock FAST_SPIBAR.
Barnali Sarkar8e513192017-07-19 16:09:56 +0530145 * Use 16bit write to avoid touching two upper bytes what may cause the write
146 * cycle to fail in case a prior transaction has not completed.
147 * While WRSDIS is lockable with FLOCKDN, writing both in the same
148 * cycle is guaranteed to work by design.
149 *
150 * Avoid read->modify->write not to clear RW1C bits unintentionally.
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530151 */
152void fast_spi_lock_bar(void)
153{
154 void *spibar = fast_spi_get_bar();
Duncan Lauriedc1e6bc2017-08-15 13:32:26 -0700155 uint16_t hsfs = SPIBAR_HSFSTS_FLOCKDN;
156
Julius Wernercd49cce2019-03-05 16:53:33 -0800157 if (CONFIG(FAST_SPI_DISABLE_WRITE_STATUS))
Duncan Lauriedc1e6bc2017-08-15 13:32:26 -0700158 hsfs |= SPIBAR_HSFSTS_WRSDIS;
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530159
Barnali Sarkar8e513192017-07-19 16:09:56 +0530160 write16(spibar + SPIBAR_HSFSTS_CTL, hsfs);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530161}
162
163/*
Barnali Sarkar4f6e3412017-08-17 11:49:27 +0530164 * Set FAST_SPIBAR + DLOCK (0x0C) register bits to discrete lock the
165 * FAST_SPI Protected Range (PR) registers.
166 */
167void fast_spi_pr_dlock(void)
168{
169 void *spibar = fast_spi_get_bar();
170 uint32_t dlock;
171
172 dlock = read32(spibar + SPIBAR_DLOCK);
173 dlock |= (SPIBAR_DLOCK_PR0LOCKDN | SPIBAR_DLOCK_PR1LOCKDN
174 | SPIBAR_DLOCK_PR2LOCKDN | SPIBAR_DLOCK_PR3LOCKDN
175 | SPIBAR_DLOCK_PR4LOCKDN);
176
177 write32(spibar + SPIBAR_DLOCK, dlock);
178}
179
180/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530181 * Set FAST_SPIBAR Soft Reset Data Register value.
182 */
183void fast_spi_set_strap_msg_data(uint32_t soft_reset_data)
184{
185 void *spibar = fast_spi_get_bar();
186 uint32_t ssl, ssms;
187
188 /* Set Strap Lock Disable */
189 ssl = read32(spibar + SPIBAR_RESET_LOCK);
190 ssl &= ~SPIBAR_RESET_LOCK_ENABLE;
191 write32(spibar + SPIBAR_RESET_LOCK, ssl);
192
193 /* Write Soft Reset Data register at SPIBAR0 offset 0xF8[0:15] */
194 write32(spibar + SPIBAR_RESET_DATA, soft_reset_data);
195
196 /* Set Strap Mux Select set to '1' */
197 ssms = read32(spibar + SPIBAR_RESET_CTRL);
198 ssms |= SPIBAR_RESET_CTRL_SSMC;
199 write32(spibar + SPIBAR_RESET_CTRL, ssms);
200
201 /* Set Strap Lock Enable */
202 ssl = read32(spibar + SPIBAR_RESET_LOCK);
203 ssl |= SPIBAR_RESET_LOCK_ENABLE;
204 write32(spibar + SPIBAR_RESET_LOCK, ssl);
205}
206
207/*
208 * Returns bios_start and fills in size of the BIOS region.
209 */
210size_t fast_spi_get_bios_region(size_t *bios_size)
211{
212 size_t bios_start, bios_end;
213 /*
214 * BIOS_BFPREG provides info about BIOS Flash Primary Region
215 * Base and Limit.
216 * Base and Limit fields are in units of 4KiB.
217 */
218 uint32_t val = read32(fast_spi_get_bar() + SPIBAR_BFPREG);
219
220 bios_start = (val & SPIBAR_BFPREG_PRB_MASK) * 4 * KiB;
221 bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >>
222 SPIBAR_BFPREG_PRL_SHIFT) + 1) * 4 * KiB;
223 *bios_size = bios_end - bios_start;
224 return bios_start;
225}
226
Aaron Durbin5391e552017-06-02 12:16:04 -0500227void fast_spi_cache_bios_region(void)
228{
Aaron Durbin5391e552017-06-02 12:16:04 -0500229 size_t bios_size;
230 uint32_t alignment;
Aaron Durbin0b34fc62017-06-08 10:52:58 -0500231 const int type = MTRR_TYPE_WRPROT;
232 uintptr_t base;
Aaron Durbin5391e552017-06-02 12:16:04 -0500233
234 /* Only the IFD BIOS region is memory mapped (at top of 4G) */
235 fast_spi_get_bios_region(&bios_size);
236
Lijian Zhaoad1e49a2018-11-29 16:24:24 -0800237 /* LOCAL APIC default address is 0xFEE0000, bios_size over 16MB will
238 * cause memory type conflict when setting memory type to write
Elyes HAOUAS6dc9d032020-02-16 16:22:52 +0100239 * protection, so limit the cached BIOS region to be no more than 16MB.
Lijian Zhaoad1e49a2018-11-29 16:24:24 -0800240 * */
241 bios_size = MIN(bios_size, 16 * MiB);
John Zhao1ceac4e2019-07-09 14:27:28 -0700242 if (bios_size <= 0)
John Zhao2bb432e2019-05-21 19:32:51 -0700243 return;
Lijian Zhaoad1e49a2018-11-29 16:24:24 -0800244
Aaron Durbin5391e552017-06-02 12:16:04 -0500245 /* Round to power of two */
Paul Menzel64e83402017-10-27 11:05:14 +0200246 alignment = 1UL << (log2_ceil(bios_size));
Aaron Durbin5391e552017-06-02 12:16:04 -0500247 bios_size = ALIGN_UP(bios_size, alignment);
Aaron Durbin0b34fc62017-06-08 10:52:58 -0500248 base = 4ULL*GiB - bios_size;
249
Subrata Banik42c44c22019-05-15 20:27:04 +0530250 if (ENV_PAYLOAD_LOADER) {
Aaron Durbin0b34fc62017-06-08 10:52:58 -0500251 mtrr_use_temp_range(base, bios_size, type);
252 } else {
253 int mtrr = get_free_var_mtrr();
254
255 if (mtrr == -1)
256 return;
257
258 set_var_mtrr(mtrr, base, bios_size, type);
259 }
Aaron Durbin5391e552017-06-02 12:16:04 -0500260}
261
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530262/*
263 * Program temporary BAR for SPI in case any of the stages before ramstage need
264 * to access FAST_SPI MMIO regs. Ramstage will assign a new BAR during PCI
265 * enumeration.
266 */
267void fast_spi_early_init(uintptr_t spi_base_address)
268{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +0200269#if defined(__SIMPLE_DEVICE__)
270 pci_devfn_t dev = PCH_DEV_SPI;
271#else
272 struct device *dev = PCH_DEV_SPI;
273#endif
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530274 uint8_t pcireg;
275
276 /* Assign Resources to SPI Controller */
277 /* Clear BIT 1-2 SPI Command Register */
278 pcireg = pci_read_config8(dev, PCI_COMMAND);
279 pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
280 pci_write_config8(dev, PCI_COMMAND, pcireg);
281
282 /* Program Temporary BAR for SPI */
283 pci_write_config32(dev, PCI_BASE_ADDRESS_0,
284 spi_base_address | PCI_BASE_ADDRESS_SPACE_MEMORY);
285
286 /* Enable Bus Master and MMIO Space */
287 pcireg = pci_read_config8(dev, PCI_COMMAND);
288 pcireg |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
289 pci_write_config8(dev, PCI_COMMAND, pcireg);
290
291 /* Initialize SPI to allow BIOS to write/erase on flash. */
292 fast_spi_init();
293}
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700294
295/* Read SPI Write Protect disable status. */
296bool fast_spi_wpd_status(void)
297{
298 return pci_read_config16(PCH_DEV_SPI, SPIBAR_BIOS_CONTROL) &
299 SPIBAR_BIOS_CONTROL_WPD;
300}
301
302/* Enable SPI Write Protect. */
303void fast_spi_enable_wp(void)
304{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +0200305#if defined(__SIMPLE_DEVICE__)
306 pci_devfn_t dev = PCH_DEV_SPI;
307#else
308 struct device *dev = PCH_DEV_SPI;
309#endif
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700310 uint8_t bios_cntl;
311
312 bios_cntl = pci_read_config8(dev, SPIBAR_BIOS_CONTROL);
313 bios_cntl &= ~SPIBAR_BIOS_CONTROL_WPD;
314 pci_write_config8(dev, SPIBAR_BIOS_CONTROL, bios_cntl);
315}