blob: 7e8a1a28443f0986d3f98b9209b3f09b298592da [file] [log] [blame]
Angel Pons0612b272020-04-05 15:46:56 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Barnali Sarkar89331cd2017-02-16 17:22:37 +05302
Angel Pons52072432021-02-15 13:09:36 +01003#define __SIMPLE_DEVICE__
4
Srinidhi N Kaushik4eb489f2020-11-25 02:21:57 -08005#include <arch/romstage.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02006#include <device/mmio.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +05307#include <assert.h>
8#include <device/pci_def.h>
Patrick Rudolphe56189c2018-04-18 10:11:59 +02009#include <device/pci_ops.h>
Subrata Banikdef18c42022-03-31 00:16:00 +053010#include <console/console.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053011#include <commonlib/helpers.h>
Aaron Durbin5391e552017-06-02 12:16:04 -050012#include <cpu/x86/mtrr.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053013#include <fast_spi_def.h>
Srinidhi N Kaushik60949082020-11-25 01:58:34 -080014#include <intelblocks/dmi.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053015#include <intelblocks/fast_spi.h>
Aaron Durbin5391e552017-06-02 12:16:04 -050016#include <lib.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053017#include <soc/pci_devs.h>
18#include <spi_flash.h>
19#include <spi-generic.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053020
21/*
22 * Get the FAST_SPIBAR.
23 */
24void *fast_spi_get_bar(void)
25{
Angel Pons52072432021-02-15 13:09:36 +010026 const pci_devfn_t dev = PCH_DEV_SPI;
Barnali Sarkar89331cd2017-02-16 17:22:37 +053027 uintptr_t bar;
28
29 bar = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
30 assert(bar != 0);
31 /*
32 * Bits 31-12 are the base address as per EDS for SPI,
33 * Don't care about 0-11 bit
34 */
35 return (void *)(bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK);
36}
37
38/*
39 * Disable the BIOS write protect and Enable Prefetching and Caching.
40 */
41void fast_spi_init(void)
42{
Angel Pons52072432021-02-15 13:09:36 +010043 const pci_devfn_t dev = PCH_DEV_SPI;
Barnali Sarkar89331cd2017-02-16 17:22:37 +053044 uint8_t bios_cntl;
45
Angel Pons122cc8c2021-02-15 17:18:55 +010046 bios_cntl = pci_read_config8(dev, SPI_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053047
48 /* Disable the BIOS write protect so write commands are allowed. */
Angel Pons122cc8c2021-02-15 17:18:55 +010049 bios_cntl &= ~SPI_BIOS_CONTROL_EISS;
50 bios_cntl |= SPI_BIOS_CONTROL_WPD;
Barnali Sarkar89331cd2017-02-16 17:22:37 +053051 /* Enable Prefetching and caching. */
Angel Pons122cc8c2021-02-15 17:18:55 +010052 bios_cntl |= SPI_BIOS_CONTROL_PREFETCH_ENABLE;
53 bios_cntl &= ~SPI_BIOS_CONTROL_CACHE_DISABLE;
Barnali Sarkar89331cd2017-02-16 17:22:37 +053054
Angel Pons122cc8c2021-02-15 17:18:55 +010055 pci_write_config8(dev, SPI_BIOS_CONTROL, bios_cntl);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053056}
57
58/*
Subrata Banik8e390092017-07-21 10:06:17 +053059 * Set FAST_SPIBAR BIOS Control register based on input bit field.
Barnali Sarkar89331cd2017-02-16 17:22:37 +053060 */
Srinidhi N Kaushik28e1d0e2020-11-25 21:57:37 -080061static void fast_spi_set_bios_control_reg(uint32_t bios_cntl_bit)
Barnali Sarkar89331cd2017-02-16 17:22:37 +053062{
Angel Pons52072432021-02-15 13:09:36 +010063 const pci_devfn_t dev = PCH_DEV_SPI;
Srinidhi N Kaushik28e1d0e2020-11-25 21:57:37 -080064 uint32_t bc_cntl;
Barnali Sarkar89331cd2017-02-16 17:22:37 +053065
66 assert((bios_cntl_bit & (bios_cntl_bit - 1)) == 0);
Angel Pons122cc8c2021-02-15 17:18:55 +010067 bc_cntl = pci_read_config32(dev, SPI_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053068 bc_cntl |= bios_cntl_bit;
Angel Pons122cc8c2021-02-15 17:18:55 +010069 pci_write_config32(dev, SPI_BIOS_CONTROL, bc_cntl);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053070}
71
72/*
Subrata Banik8e390092017-07-21 10:06:17 +053073 * Ensure an additional read back after performing lock down
74 */
75static void fast_spi_read_post_write(uint8_t reg)
76{
77 pci_read_config8(PCH_DEV_SPI, reg);
78}
79
80/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +053081 * Set FAST_SPIBAR BIOS Control BILD bit.
82 */
83void fast_spi_set_bios_interface_lock_down(void)
84{
Angel Pons122cc8c2021-02-15 17:18:55 +010085 fast_spi_set_bios_control_reg(SPI_BIOS_CONTROL_BILD);
Subrata Banik8e390092017-07-21 10:06:17 +053086
Angel Pons122cc8c2021-02-15 17:18:55 +010087 fast_spi_read_post_write(SPI_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053088}
89
90/*
91 * Set FAST_SPIBAR BIOS Control LE bit.
92 */
93void fast_spi_set_lock_enable(void)
94{
Angel Pons122cc8c2021-02-15 17:18:55 +010095 fast_spi_set_bios_control_reg(SPI_BIOS_CONTROL_LOCK_ENABLE);
Subrata Banik8e390092017-07-21 10:06:17 +053096
Angel Pons122cc8c2021-02-15 17:18:55 +010097 fast_spi_read_post_write(SPI_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053098}
99
100/*
Srinidhi N Kaushik28e1d0e2020-11-25 21:57:37 -0800101 * Set FAST_SPIBAR BIOS Control EXT BIOS LE bit.
102 */
103void fast_spi_set_ext_bios_lock_enable(void)
104{
105 if (!CONFIG(FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW))
106 return;
107
Angel Pons122cc8c2021-02-15 17:18:55 +0100108 fast_spi_set_bios_control_reg(SPI_BIOS_CONTROL_EXT_BIOS_LOCK_ENABLE);
Srinidhi N Kaushik28e1d0e2020-11-25 21:57:37 -0800109
Angel Pons122cc8c2021-02-15 17:18:55 +0100110 fast_spi_read_post_write(SPI_BIOS_CONTROL);
Srinidhi N Kaushik28e1d0e2020-11-25 21:57:37 -0800111}
112
113/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530114 * Set FAST_SPIBAR BIOS Control EISS bit.
115 */
116void fast_spi_set_eiss(void)
117{
Angel Pons122cc8c2021-02-15 17:18:55 +0100118 fast_spi_set_bios_control_reg(SPI_BIOS_CONTROL_EISS);
Subrata Banik8e390092017-07-21 10:06:17 +0530119
Angel Pons122cc8c2021-02-15 17:18:55 +0100120 fast_spi_read_post_write(SPI_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530121}
122
123/*
124 * Set FAST_SPI opcode menu.
125 */
126void fast_spi_set_opcode_menu(void)
127{
128 void *spibar = fast_spi_get_bar();
129
130 write16(spibar + SPIBAR_PREOP, SPI_OPPREFIX);
131 write16(spibar + SPIBAR_OPTYPE, SPI_OPTYPE);
132 write32(spibar + SPIBAR_OPMENU_LOWER, SPI_OPMENU_LOWER);
133 write32(spibar + SPIBAR_OPMENU_UPPER, SPI_OPMENU_UPPER);
134}
135
136/*
137 * Lock FAST_SPIBAR.
Barnali Sarkar8e513192017-07-19 16:09:56 +0530138 * Use 16bit write to avoid touching two upper bytes what may cause the write
139 * cycle to fail in case a prior transaction has not completed.
140 * While WRSDIS is lockable with FLOCKDN, writing both in the same
141 * cycle is guaranteed to work by design.
142 *
143 * Avoid read->modify->write not to clear RW1C bits unintentionally.
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530144 */
145void fast_spi_lock_bar(void)
146{
147 void *spibar = fast_spi_get_bar();
Marc Jones051bf5d2021-03-30 12:16:09 -0600148 uint16_t hsfs = SPIBAR_HSFSTS_FLOCKDN | SPIBAR_HSFSTS_PRR34_LOCKDN;
Duncan Lauriedc1e6bc2017-08-15 13:32:26 -0700149
Julius Wernercd49cce2019-03-05 16:53:33 -0800150 if (CONFIG(FAST_SPI_DISABLE_WRITE_STATUS))
Duncan Lauriedc1e6bc2017-08-15 13:32:26 -0700151 hsfs |= SPIBAR_HSFSTS_WRSDIS;
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530152
Barnali Sarkar8e513192017-07-19 16:09:56 +0530153 write16(spibar + SPIBAR_HSFSTS_CTL, hsfs);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530154}
155
156/*
Barnali Sarkar4f6e3412017-08-17 11:49:27 +0530157 * Set FAST_SPIBAR + DLOCK (0x0C) register bits to discrete lock the
158 * FAST_SPI Protected Range (PR) registers.
159 */
160void fast_spi_pr_dlock(void)
161{
162 void *spibar = fast_spi_get_bar();
163 uint32_t dlock;
164
165 dlock = read32(spibar + SPIBAR_DLOCK);
166 dlock |= (SPIBAR_DLOCK_PR0LOCKDN | SPIBAR_DLOCK_PR1LOCKDN
167 | SPIBAR_DLOCK_PR2LOCKDN | SPIBAR_DLOCK_PR3LOCKDN
168 | SPIBAR_DLOCK_PR4LOCKDN);
169
170 write32(spibar + SPIBAR_DLOCK, dlock);
171}
172
173/*
Subrata Banikd6431652022-04-13 20:30:53 +0530174 * Set FAST_SPIBAR + VSCC0 (0xC4) register VCL (bit 30).
175 */
176void fast_spi_vscc0_lock(void)
177{
178 void *spibar = fast_spi_get_bar();
179
180 /*
181 * SPI Flash Programming Guide Section 5.5.2 describes Vendor Component Lock (VCL).
182 * It is recommended to set the VCL bit. VCL applies to both VSCC0 and VSCC1.
183 * Without this bit being set, it is possible to modify Host/GbE VSCC register(s),
184 * which might results in undesired host and integrated GbE Serial Flash
185 * functionality.
186 */
187 setbits32(spibar + SPIBAR_SFDP0_VSCC0, SPIBAR_VSCC0_VCL);
188}
189
190/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530191 * Set FAST_SPIBAR Soft Reset Data Register value.
192 */
193void fast_spi_set_strap_msg_data(uint32_t soft_reset_data)
194{
195 void *spibar = fast_spi_get_bar();
196 uint32_t ssl, ssms;
197
198 /* Set Strap Lock Disable */
199 ssl = read32(spibar + SPIBAR_RESET_LOCK);
200 ssl &= ~SPIBAR_RESET_LOCK_ENABLE;
201 write32(spibar + SPIBAR_RESET_LOCK, ssl);
202
203 /* Write Soft Reset Data register at SPIBAR0 offset 0xF8[0:15] */
204 write32(spibar + SPIBAR_RESET_DATA, soft_reset_data);
205
206 /* Set Strap Mux Select set to '1' */
207 ssms = read32(spibar + SPIBAR_RESET_CTRL);
208 ssms |= SPIBAR_RESET_CTRL_SSMC;
209 write32(spibar + SPIBAR_RESET_CTRL, ssms);
210
211 /* Set Strap Lock Enable */
212 ssl = read32(spibar + SPIBAR_RESET_LOCK);
213 ssl |= SPIBAR_RESET_LOCK_ENABLE;
214 write32(spibar + SPIBAR_RESET_LOCK, ssl);
215}
216
Subrata Banikdef18c42022-03-31 00:16:00 +0530217static void fast_spi_enable_cache_range(unsigned int base, unsigned int size)
218{
219 const int type = MTRR_TYPE_WRPROT;
220 int mtrr = get_free_var_mtrr();
221 if (mtrr == -1) {
222 printk(BIOS_WARNING, "ROM caching failed due to no free MTRR available!\n");
223 return;
224 }
225
226 set_var_mtrr(mtrr, base, size, type);
227}
228
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530229/*
230 * Returns bios_start and fills in size of the BIOS region.
231 */
232size_t fast_spi_get_bios_region(size_t *bios_size)
233{
234 size_t bios_start, bios_end;
235 /*
236 * BIOS_BFPREG provides info about BIOS Flash Primary Region
237 * Base and Limit.
238 * Base and Limit fields are in units of 4KiB.
239 */
240 uint32_t val = read32(fast_spi_get_bar() + SPIBAR_BFPREG);
241
242 bios_start = (val & SPIBAR_BFPREG_PRB_MASK) * 4 * KiB;
243 bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >>
244 SPIBAR_BFPREG_PRL_SHIFT) + 1) * 4 * KiB;
245 *bios_size = bios_end - bios_start;
246 return bios_start;
247}
248
Srinidhi N Kaushik4eb489f2020-11-25 02:21:57 -0800249static bool fast_spi_ext_bios_cache_range(uintptr_t *base, size_t *size)
250{
251 uint32_t alignment;
252 if (!CONFIG(FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW))
253 return false;
254
255 fast_spi_get_ext_bios_window(base, size);
256
257 /* Enable extended bios only if Size of Bios region is greater than 16MiB */
258 if (*size == 0 || *base == 0)
259 return false;
260
261 /* Round to power of two */
262 alignment = 1UL << (log2_ceil(*size));
263 *size = ALIGN_UP(*size, alignment);
264 *base = ALIGN_DOWN(*base, *size);
265
266 return true;
267}
268
269static void fast_spi_cache_ext_bios_window(void)
270{
271 size_t ext_bios_size;
272 uintptr_t ext_bios_base;
Srinidhi N Kaushik4eb489f2020-11-25 02:21:57 -0800273
274 if (!fast_spi_ext_bios_cache_range(&ext_bios_base, &ext_bios_size))
275 return;
276
Subrata Banikdef18c42022-03-31 00:16:00 +0530277 fast_spi_enable_cache_range(ext_bios_base, ext_bios_size);
Srinidhi N Kaushik4eb489f2020-11-25 02:21:57 -0800278}
279
280void fast_spi_cache_ext_bios_postcar(struct postcar_frame *pcf)
281{
282 size_t ext_bios_size;
283 uintptr_t ext_bios_base;
284 const int type = MTRR_TYPE_WRPROT;
285
286 if (!fast_spi_ext_bios_cache_range(&ext_bios_base, &ext_bios_size))
287 return;
288
289 postcar_frame_add_mtrr(pcf, ext_bios_base, ext_bios_size, type);
290}
291
Aaron Durbin5391e552017-06-02 12:16:04 -0500292void fast_spi_cache_bios_region(void)
293{
Aaron Durbin5391e552017-06-02 12:16:04 -0500294 size_t bios_size;
295 uint32_t alignment;
Aaron Durbin0b34fc62017-06-08 10:52:58 -0500296 uintptr_t base;
Aaron Durbin5391e552017-06-02 12:16:04 -0500297
298 /* Only the IFD BIOS region is memory mapped (at top of 4G) */
299 fast_spi_get_bios_region(&bios_size);
300
Lijian Zhaoad1e49a2018-11-29 16:24:24 -0800301 /* LOCAL APIC default address is 0xFEE0000, bios_size over 16MB will
302 * cause memory type conflict when setting memory type to write
Elyes HAOUAS6dc9d032020-02-16 16:22:52 +0100303 * protection, so limit the cached BIOS region to be no more than 16MB.
Lijian Zhaoad1e49a2018-11-29 16:24:24 -0800304 * */
305 bios_size = MIN(bios_size, 16 * MiB);
John Zhao1ceac4e2019-07-09 14:27:28 -0700306 if (bios_size <= 0)
John Zhao2bb432e2019-05-21 19:32:51 -0700307 return;
Lijian Zhaoad1e49a2018-11-29 16:24:24 -0800308
Aaron Durbin5391e552017-06-02 12:16:04 -0500309 /* Round to power of two */
Paul Menzel64e83402017-10-27 11:05:14 +0200310 alignment = 1UL << (log2_ceil(bios_size));
Aaron Durbin5391e552017-06-02 12:16:04 -0500311 bios_size = ALIGN_UP(bios_size, alignment);
Aaron Durbin0b34fc62017-06-08 10:52:58 -0500312 base = 4ULL*GiB - bios_size;
313
Subrata Banikdef18c42022-03-31 00:16:00 +0530314 fast_spi_enable_cache_range(base, bios_size);
Srinidhi N Kaushik4eb489f2020-11-25 02:21:57 -0800315
316 /* Check if caching is needed for extended bios region if supported */
317 fast_spi_cache_ext_bios_window();
Aaron Durbin5391e552017-06-02 12:16:04 -0500318}
319
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530320/*
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800321 * Enable extended BIOS support
322 * Checks BIOS region in the flashmap, if its more than 16Mib, enables extended BIOS
323 * region support.
324 */
325static void fast_spi_enable_ext_bios(void)
326{
Angel Pons52072432021-02-15 13:09:36 +0100327 const pci_devfn_t dev = PCH_DEV_SPI;
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800328 if (!CONFIG(FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW))
329 return;
330
331#if CONFIG(FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW)
332 /*
333 * Ensure that the base for the extended window in host space is a multiple of 32 MiB
334 * and size is fixed at 32 MiB. Controller assumes that the extended window has a fixed
335 * size of 32 MiB even if the actual BIOS region is smaller. The mapping of the BIOS
336 * region happens at the top of the extended window in this case.
337 */
338 _Static_assert(ALIGN_UP(CONFIG_EXT_BIOS_WIN_BASE, 32 * MiB) == CONFIG_EXT_BIOS_WIN_BASE,
339 "Extended BIOS window base must be a multiple of 32 * MiB!");
340 _Static_assert(CONFIG_EXT_BIOS_WIN_SIZE == (32 * MiB),
341 "Only 32MiB windows are supported for extended BIOS!");
342#endif
343
Wonkyu Kimaaec8092021-09-15 15:52:51 -0700344 /* Configure Source decode for Extended BIOS Region */
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800345 if (dmi_enable_gpmr(CONFIG_EXT_BIOS_WIN_BASE, CONFIG_EXT_BIOS_WIN_SIZE,
Wonkyu Kimaaec8092021-09-15 15:52:51 -0700346 soc_get_spi_psf_destination_id()) == CB_ERR)
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800347 return;
348
349 /* Program EXT_BIOS_BAR1 with obtained ext_bios_base */
350 pci_write_config32(dev, SPI_CFG_BAR1,
351 CONFIG_EXT_BIOS_WIN_BASE | PCI_BASE_ADDRESS_SPACE_MEMORY);
352
353 /*
354 * Since the top 16MiB of the BIOS region is always decoded by the standard window
355 * below the 4G boundary, we need to map the rest of the BIOS region that lies
356 * below the top 16MiB in the extended window. Thus, EXT_BIOS_LIMIT will be set to
357 * 16MiB. This determines the maximum address in the SPI flash space that is mapped
358 * to the top of the extended window in the host address space. EXT_BIOS_LIMIT is
359 * basically the offset from the end of the BIOS region that will be mapped to the top
360 * of the extended window.
361 * This enables the decoding as follows:
362 -Standard decode window: (bios_region_top - 16MiB) to bios_region_top
363 -Extended decode window:
364 (bios_region_top - 16MiB - MIN(extended_window_size, bios_size - 16MiB))
365 to (bios_region_top - 16MiB).
366 */
Angel Pons122cc8c2021-02-15 17:18:55 +0100367 pci_or_config32(dev, SPI_BIOS_CONTROL, SPI_BIOS_CONTROL_EXT_BIOS_LIMIT(16 * MiB));
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800368
369 /* Program EXT_BIOS EN */
Angel Pons122cc8c2021-02-15 17:18:55 +0100370 pci_or_config32(dev, SPI_BIOS_CONTROL, SPI_BIOS_CONTROL_EXT_BIOS_ENABLE);
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800371}
372
373/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530374 * Program temporary BAR for SPI in case any of the stages before ramstage need
375 * to access FAST_SPI MMIO regs. Ramstage will assign a new BAR during PCI
376 * enumeration.
377 */
378void fast_spi_early_init(uintptr_t spi_base_address)
379{
Angel Pons52072432021-02-15 13:09:36 +0100380 const pci_devfn_t dev = PCH_DEV_SPI;
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200381 uint16_t pcireg;
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530382
383 /* Assign Resources to SPI Controller */
384 /* Clear BIT 1-2 SPI Command Register */
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200385 pcireg = pci_read_config16(dev, PCI_COMMAND);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530386 pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200387 pci_write_config16(dev, PCI_COMMAND, pcireg);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530388
389 /* Program Temporary BAR for SPI */
390 pci_write_config32(dev, PCI_BASE_ADDRESS_0,
391 spi_base_address | PCI_BASE_ADDRESS_SPACE_MEMORY);
392
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800393 /*
394 * Enable extended bios support. Since it configures memory BAR, this is done before
395 * enabling MMIO space.
396 */
397 fast_spi_enable_ext_bios();
398
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530399 /* Enable Bus Master and MMIO Space */
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200400 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530401
402 /* Initialize SPI to allow BIOS to write/erase on flash. */
403 fast_spi_init();
404}
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700405
Angel Pons967753f2021-02-15 17:44:09 +0100406/* Clear SPI Synchronous SMI status bit and return its value. */
407bool fast_spi_clear_sync_smi_status(void)
408{
409 const uint32_t bios_cntl = pci_read_config32(PCH_DEV_SPI, SPI_BIOS_CONTROL);
410 const bool smi_asserted = bios_cntl & SPI_BIOS_CONTROL_SYNC_SS;
411 /*
412 * Do not unconditionally write 1 to clear SYNC_SS. Hardware could set
413 * SYNC_SS here (after we read but before we write SPI_BIOS_CONTROL),
414 * and the event would be lost when unconditionally clearing SYNC_SS.
415 */
416 pci_write_config32(PCH_DEV_SPI, SPI_BIOS_CONTROL, bios_cntl);
417 return smi_asserted;
418}
419
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700420/* Read SPI Write Protect disable status. */
421bool fast_spi_wpd_status(void)
422{
Angel Pons122cc8c2021-02-15 17:18:55 +0100423 return pci_read_config16(PCH_DEV_SPI, SPI_BIOS_CONTROL) &
424 SPI_BIOS_CONTROL_WPD;
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700425}
426
427/* Enable SPI Write Protect. */
428void fast_spi_enable_wp(void)
429{
Angel Pons52072432021-02-15 13:09:36 +0100430 const pci_devfn_t dev = PCH_DEV_SPI;
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700431 uint8_t bios_cntl;
432
Angel Pons122cc8c2021-02-15 17:18:55 +0100433 bios_cntl = pci_read_config8(dev, SPI_BIOS_CONTROL);
434 bios_cntl &= ~SPI_BIOS_CONTROL_WPD;
435 pci_write_config8(dev, SPI_BIOS_CONTROL, bios_cntl);
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700436}
Angel Ponsd21b4632021-02-10 17:12:05 +0100437
438/* Disable SPI Write Protect. */
439void fast_spi_disable_wp(void)
440{
441 const pci_devfn_t dev = PCH_DEV_SPI;
442 uint8_t bios_cntl;
443
444 bios_cntl = pci_read_config8(dev, SPI_BIOS_CONTROL);
445 bios_cntl |= SPI_BIOS_CONTROL_WPD;
446 pci_write_config8(dev, SPI_BIOS_CONTROL, bios_cntl);
447}
Subrata Banikd5e7c632022-04-14 00:08:05 +0530448
449void fast_spi_clear_outstanding_status(void)
450{
451 void *spibar = fast_spi_get_bar();
452
453 /* Make sure all W1C status bits get cleared. */
454 write32(spibar + SPIBAR_HSFSTS_CTL, SPIBAR_HSFSTS_W1C_BITS);
455}