blob: 9788493e1e2cf52c73e415ff5ea90decab9a613c [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>
Werner Zehbae84982022-05-05 11:04:04 +02008#include <device/pci.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +05309#include <device/pci_def.h>
Werner Zehbae84982022-05-05 11:04:04 +020010#include <device/pci_ids.h>
Patrick Rudolphe56189c2018-04-18 10:11:59 +020011#include <device/pci_ops.h>
Subrata Banikdef18c42022-03-31 00:16:00 +053012#include <console/console.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053013#include <commonlib/helpers.h>
Aaron Durbin5391e552017-06-02 12:16:04 -050014#include <cpu/x86/mtrr.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053015#include <fast_spi_def.h>
16#include <intelblocks/fast_spi.h>
Subrata Banik211be9c2022-04-13 12:13:09 +053017#include <intelblocks/gpmr.h>
Aaron Durbin5391e552017-06-02 12:16:04 -050018#include <lib.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053019#include <soc/pci_devs.h>
20#include <spi_flash.h>
21#include <spi-generic.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053022
23/*
24 * Get the FAST_SPIBAR.
25 */
26void *fast_spi_get_bar(void)
27{
Angel Pons52072432021-02-15 13:09:36 +010028 const pci_devfn_t dev = PCH_DEV_SPI;
Barnali Sarkar89331cd2017-02-16 17:22:37 +053029 uintptr_t bar;
30
31 bar = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
32 assert(bar != 0);
33 /*
34 * Bits 31-12 are the base address as per EDS for SPI,
35 * Don't care about 0-11 bit
36 */
37 return (void *)(bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK);
38}
39
40/*
41 * Disable the BIOS write protect and Enable Prefetching and Caching.
42 */
43void fast_spi_init(void)
44{
Angel Pons52072432021-02-15 13:09:36 +010045 const pci_devfn_t dev = PCH_DEV_SPI;
Barnali Sarkar89331cd2017-02-16 17:22:37 +053046 uint8_t bios_cntl;
47
Angel Pons122cc8c2021-02-15 17:18:55 +010048 bios_cntl = pci_read_config8(dev, SPI_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053049
50 /* Disable the BIOS write protect so write commands are allowed. */
Angel Pons122cc8c2021-02-15 17:18:55 +010051 bios_cntl &= ~SPI_BIOS_CONTROL_EISS;
52 bios_cntl |= SPI_BIOS_CONTROL_WPD;
Barnali Sarkar89331cd2017-02-16 17:22:37 +053053 /* Enable Prefetching and caching. */
Angel Pons122cc8c2021-02-15 17:18:55 +010054 bios_cntl |= SPI_BIOS_CONTROL_PREFETCH_ENABLE;
55 bios_cntl &= ~SPI_BIOS_CONTROL_CACHE_DISABLE;
Barnali Sarkar89331cd2017-02-16 17:22:37 +053056
Angel Pons122cc8c2021-02-15 17:18:55 +010057 pci_write_config8(dev, SPI_BIOS_CONTROL, bios_cntl);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053058}
59
60/*
Subrata Banik8e390092017-07-21 10:06:17 +053061 * Set FAST_SPIBAR BIOS Control register based on input bit field.
Barnali Sarkar89331cd2017-02-16 17:22:37 +053062 */
Srinidhi N Kaushik28e1d0e2020-11-25 21:57:37 -080063static void fast_spi_set_bios_control_reg(uint32_t bios_cntl_bit)
Barnali Sarkar89331cd2017-02-16 17:22:37 +053064{
Angel Pons52072432021-02-15 13:09:36 +010065 const pci_devfn_t dev = PCH_DEV_SPI;
Srinidhi N Kaushik28e1d0e2020-11-25 21:57:37 -080066 uint32_t bc_cntl;
Barnali Sarkar89331cd2017-02-16 17:22:37 +053067
68 assert((bios_cntl_bit & (bios_cntl_bit - 1)) == 0);
Angel Pons122cc8c2021-02-15 17:18:55 +010069 bc_cntl = pci_read_config32(dev, SPI_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053070 bc_cntl |= bios_cntl_bit;
Angel Pons122cc8c2021-02-15 17:18:55 +010071 pci_write_config32(dev, SPI_BIOS_CONTROL, bc_cntl);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053072}
73
74/*
Subrata Banik8e390092017-07-21 10:06:17 +053075 * Ensure an additional read back after performing lock down
76 */
77static void fast_spi_read_post_write(uint8_t reg)
78{
79 pci_read_config8(PCH_DEV_SPI, reg);
80}
81
82/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +053083 * Set FAST_SPIBAR BIOS Control BILD bit.
84 */
85void fast_spi_set_bios_interface_lock_down(void)
86{
Angel Pons122cc8c2021-02-15 17:18:55 +010087 fast_spi_set_bios_control_reg(SPI_BIOS_CONTROL_BILD);
Subrata Banik8e390092017-07-21 10:06:17 +053088
Angel Pons122cc8c2021-02-15 17:18:55 +010089 fast_spi_read_post_write(SPI_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053090}
91
92/*
93 * Set FAST_SPIBAR BIOS Control LE bit.
94 */
95void fast_spi_set_lock_enable(void)
96{
Angel Pons122cc8c2021-02-15 17:18:55 +010097 fast_spi_set_bios_control_reg(SPI_BIOS_CONTROL_LOCK_ENABLE);
Subrata Banik8e390092017-07-21 10:06:17 +053098
Angel Pons122cc8c2021-02-15 17:18:55 +010099 fast_spi_read_post_write(SPI_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530100}
101
102/*
Srinidhi N Kaushik28e1d0e2020-11-25 21:57:37 -0800103 * Set FAST_SPIBAR BIOS Control EXT BIOS LE bit.
104 */
105void fast_spi_set_ext_bios_lock_enable(void)
106{
107 if (!CONFIG(FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW))
108 return;
109
Angel Pons122cc8c2021-02-15 17:18:55 +0100110 fast_spi_set_bios_control_reg(SPI_BIOS_CONTROL_EXT_BIOS_LOCK_ENABLE);
Srinidhi N Kaushik28e1d0e2020-11-25 21:57:37 -0800111
Angel Pons122cc8c2021-02-15 17:18:55 +0100112 fast_spi_read_post_write(SPI_BIOS_CONTROL);
Srinidhi N Kaushik28e1d0e2020-11-25 21:57:37 -0800113}
114
115/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530116 * Set FAST_SPIBAR BIOS Control EISS bit.
117 */
118void fast_spi_set_eiss(void)
119{
Angel Pons122cc8c2021-02-15 17:18:55 +0100120 fast_spi_set_bios_control_reg(SPI_BIOS_CONTROL_EISS);
Subrata Banik8e390092017-07-21 10:06:17 +0530121
Angel Pons122cc8c2021-02-15 17:18:55 +0100122 fast_spi_read_post_write(SPI_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530123}
124
125/*
126 * Set FAST_SPI opcode menu.
127 */
128void fast_spi_set_opcode_menu(void)
129{
130 void *spibar = fast_spi_get_bar();
131
132 write16(spibar + SPIBAR_PREOP, SPI_OPPREFIX);
133 write16(spibar + SPIBAR_OPTYPE, SPI_OPTYPE);
134 write32(spibar + SPIBAR_OPMENU_LOWER, SPI_OPMENU_LOWER);
135 write32(spibar + SPIBAR_OPMENU_UPPER, SPI_OPMENU_UPPER);
136}
137
138/*
139 * Lock FAST_SPIBAR.
Barnali Sarkar8e513192017-07-19 16:09:56 +0530140 * Use 16bit write to avoid touching two upper bytes what may cause the write
141 * cycle to fail in case a prior transaction has not completed.
142 * While WRSDIS is lockable with FLOCKDN, writing both in the same
143 * cycle is guaranteed to work by design.
144 *
145 * Avoid read->modify->write not to clear RW1C bits unintentionally.
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530146 */
147void fast_spi_lock_bar(void)
148{
149 void *spibar = fast_spi_get_bar();
Marc Jones051bf5d2021-03-30 12:16:09 -0600150 uint16_t hsfs = SPIBAR_HSFSTS_FLOCKDN | SPIBAR_HSFSTS_PRR34_LOCKDN;
Duncan Lauriedc1e6bc2017-08-15 13:32:26 -0700151
Julius Wernercd49cce2019-03-05 16:53:33 -0800152 if (CONFIG(FAST_SPI_DISABLE_WRITE_STATUS))
Duncan Lauriedc1e6bc2017-08-15 13:32:26 -0700153 hsfs |= SPIBAR_HSFSTS_WRSDIS;
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530154
Barnali Sarkar8e513192017-07-19 16:09:56 +0530155 write16(spibar + SPIBAR_HSFSTS_CTL, hsfs);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530156}
157
158/*
Barnali Sarkar4f6e3412017-08-17 11:49:27 +0530159 * Set FAST_SPIBAR + DLOCK (0x0C) register bits to discrete lock the
160 * FAST_SPI Protected Range (PR) registers.
161 */
162void fast_spi_pr_dlock(void)
163{
164 void *spibar = fast_spi_get_bar();
165 uint32_t dlock;
166
167 dlock = read32(spibar + SPIBAR_DLOCK);
168 dlock |= (SPIBAR_DLOCK_PR0LOCKDN | SPIBAR_DLOCK_PR1LOCKDN
169 | SPIBAR_DLOCK_PR2LOCKDN | SPIBAR_DLOCK_PR3LOCKDN
170 | SPIBAR_DLOCK_PR4LOCKDN);
171
172 write32(spibar + SPIBAR_DLOCK, dlock);
173}
174
175/*
Subrata Banikd6431652022-04-13 20:30:53 +0530176 * Set FAST_SPIBAR + VSCC0 (0xC4) register VCL (bit 30).
177 */
178void fast_spi_vscc0_lock(void)
179{
180 void *spibar = fast_spi_get_bar();
181
182 /*
183 * SPI Flash Programming Guide Section 5.5.2 describes Vendor Component Lock (VCL).
184 * It is recommended to set the VCL bit. VCL applies to both VSCC0 and VSCC1.
185 * Without this bit being set, it is possible to modify Host/GbE VSCC register(s),
186 * which might results in undesired host and integrated GbE Serial Flash
187 * functionality.
188 */
189 setbits32(spibar + SPIBAR_SFDP0_VSCC0, SPIBAR_VSCC0_VCL);
190}
191
192/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530193 * Set FAST_SPIBAR Soft Reset Data Register value.
194 */
195void fast_spi_set_strap_msg_data(uint32_t soft_reset_data)
196{
197 void *spibar = fast_spi_get_bar();
198 uint32_t ssl, ssms;
199
200 /* Set Strap Lock Disable */
201 ssl = read32(spibar + SPIBAR_RESET_LOCK);
202 ssl &= ~SPIBAR_RESET_LOCK_ENABLE;
203 write32(spibar + SPIBAR_RESET_LOCK, ssl);
204
205 /* Write Soft Reset Data register at SPIBAR0 offset 0xF8[0:15] */
206 write32(spibar + SPIBAR_RESET_DATA, soft_reset_data);
207
208 /* Set Strap Mux Select set to '1' */
209 ssms = read32(spibar + SPIBAR_RESET_CTRL);
210 ssms |= SPIBAR_RESET_CTRL_SSMC;
211 write32(spibar + SPIBAR_RESET_CTRL, ssms);
212
213 /* Set Strap Lock Enable */
214 ssl = read32(spibar + SPIBAR_RESET_LOCK);
215 ssl |= SPIBAR_RESET_LOCK_ENABLE;
216 write32(spibar + SPIBAR_RESET_LOCK, ssl);
217}
218
Subrata Banikdef18c42022-03-31 00:16:00 +0530219static void fast_spi_enable_cache_range(unsigned int base, unsigned int size)
220{
221 const int type = MTRR_TYPE_WRPROT;
222 int mtrr = get_free_var_mtrr();
223 if (mtrr == -1) {
224 printk(BIOS_WARNING, "ROM caching failed due to no free MTRR available!\n");
225 return;
226 }
227
228 set_var_mtrr(mtrr, base, size, type);
229}
230
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530231/*
232 * Returns bios_start and fills in size of the BIOS region.
233 */
234size_t fast_spi_get_bios_region(size_t *bios_size)
235{
236 size_t bios_start, bios_end;
237 /*
238 * BIOS_BFPREG provides info about BIOS Flash Primary Region
239 * Base and Limit.
240 * Base and Limit fields are in units of 4KiB.
241 */
242 uint32_t val = read32(fast_spi_get_bar() + SPIBAR_BFPREG);
243
244 bios_start = (val & SPIBAR_BFPREG_PRB_MASK) * 4 * KiB;
245 bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >>
246 SPIBAR_BFPREG_PRL_SHIFT) + 1) * 4 * KiB;
247 *bios_size = bios_end - bios_start;
248 return bios_start;
249}
250
Srinidhi N Kaushik4eb489f2020-11-25 02:21:57 -0800251static bool fast_spi_ext_bios_cache_range(uintptr_t *base, size_t *size)
252{
253 uint32_t alignment;
254 if (!CONFIG(FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW))
255 return false;
256
257 fast_spi_get_ext_bios_window(base, size);
258
259 /* Enable extended bios only if Size of Bios region is greater than 16MiB */
260 if (*size == 0 || *base == 0)
261 return false;
262
263 /* Round to power of two */
264 alignment = 1UL << (log2_ceil(*size));
265 *size = ALIGN_UP(*size, alignment);
266 *base = ALIGN_DOWN(*base, *size);
267
268 return true;
269}
270
271static void fast_spi_cache_ext_bios_window(void)
272{
273 size_t ext_bios_size;
274 uintptr_t ext_bios_base;
Srinidhi N Kaushik4eb489f2020-11-25 02:21:57 -0800275
276 if (!fast_spi_ext_bios_cache_range(&ext_bios_base, &ext_bios_size))
277 return;
278
Subrata Banikdef18c42022-03-31 00:16:00 +0530279 fast_spi_enable_cache_range(ext_bios_base, ext_bios_size);
Srinidhi N Kaushik4eb489f2020-11-25 02:21:57 -0800280}
281
282void fast_spi_cache_ext_bios_postcar(struct postcar_frame *pcf)
283{
284 size_t ext_bios_size;
285 uintptr_t ext_bios_base;
286 const int type = MTRR_TYPE_WRPROT;
287
288 if (!fast_spi_ext_bios_cache_range(&ext_bios_base, &ext_bios_size))
289 return;
290
291 postcar_frame_add_mtrr(pcf, ext_bios_base, ext_bios_size, type);
292}
293
Aaron Durbin5391e552017-06-02 12:16:04 -0500294void fast_spi_cache_bios_region(void)
295{
Aaron Durbin5391e552017-06-02 12:16:04 -0500296 size_t bios_size;
297 uint32_t alignment;
Aaron Durbin0b34fc62017-06-08 10:52:58 -0500298 uintptr_t base;
Aaron Durbin5391e552017-06-02 12:16:04 -0500299
300 /* Only the IFD BIOS region is memory mapped (at top of 4G) */
301 fast_spi_get_bios_region(&bios_size);
302
Lijian Zhaoad1e49a2018-11-29 16:24:24 -0800303 /* LOCAL APIC default address is 0xFEE0000, bios_size over 16MB will
304 * cause memory type conflict when setting memory type to write
Elyes HAOUAS6dc9d032020-02-16 16:22:52 +0100305 * protection, so limit the cached BIOS region to be no more than 16MB.
Lijian Zhaoad1e49a2018-11-29 16:24:24 -0800306 * */
307 bios_size = MIN(bios_size, 16 * MiB);
John Zhao1ceac4e2019-07-09 14:27:28 -0700308 if (bios_size <= 0)
John Zhao2bb432e2019-05-21 19:32:51 -0700309 return;
Lijian Zhaoad1e49a2018-11-29 16:24:24 -0800310
Aaron Durbin5391e552017-06-02 12:16:04 -0500311 /* Round to power of two */
Paul Menzel64e83402017-10-27 11:05:14 +0200312 alignment = 1UL << (log2_ceil(bios_size));
Aaron Durbin5391e552017-06-02 12:16:04 -0500313 bios_size = ALIGN_UP(bios_size, alignment);
Aaron Durbin0b34fc62017-06-08 10:52:58 -0500314 base = 4ULL*GiB - bios_size;
315
Subrata Banikdef18c42022-03-31 00:16:00 +0530316 fast_spi_enable_cache_range(base, bios_size);
Srinidhi N Kaushik4eb489f2020-11-25 02:21:57 -0800317
318 /* Check if caching is needed for extended bios region if supported */
319 fast_spi_cache_ext_bios_window();
Aaron Durbin5391e552017-06-02 12:16:04 -0500320}
321
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530322/*
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800323 * Enable extended BIOS support
324 * Checks BIOS region in the flashmap, if its more than 16Mib, enables extended BIOS
325 * region support.
326 */
327static void fast_spi_enable_ext_bios(void)
328{
Angel Pons52072432021-02-15 13:09:36 +0100329 const pci_devfn_t dev = PCH_DEV_SPI;
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800330 if (!CONFIG(FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW))
331 return;
332
333#if CONFIG(FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW)
334 /*
335 * Ensure that the base for the extended window in host space is a multiple of 32 MiB
336 * and size is fixed at 32 MiB. Controller assumes that the extended window has a fixed
337 * size of 32 MiB even if the actual BIOS region is smaller. The mapping of the BIOS
338 * region happens at the top of the extended window in this case.
339 */
340 _Static_assert(ALIGN_UP(CONFIG_EXT_BIOS_WIN_BASE, 32 * MiB) == CONFIG_EXT_BIOS_WIN_BASE,
341 "Extended BIOS window base must be a multiple of 32 * MiB!");
342 _Static_assert(CONFIG_EXT_BIOS_WIN_SIZE == (32 * MiB),
343 "Only 32MiB windows are supported for extended BIOS!");
344#endif
345
Wonkyu Kimaaec8092021-09-15 15:52:51 -0700346 /* Configure Source decode for Extended BIOS Region */
Subrata Banik211be9c2022-04-13 12:13:09 +0530347 if (enable_gpmr(CONFIG_EXT_BIOS_WIN_BASE, CONFIG_EXT_BIOS_WIN_SIZE,
Wonkyu Kimaaec8092021-09-15 15:52:51 -0700348 soc_get_spi_psf_destination_id()) == CB_ERR)
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800349 return;
350
351 /* Program EXT_BIOS_BAR1 with obtained ext_bios_base */
352 pci_write_config32(dev, SPI_CFG_BAR1,
353 CONFIG_EXT_BIOS_WIN_BASE | PCI_BASE_ADDRESS_SPACE_MEMORY);
354
355 /*
356 * Since the top 16MiB of the BIOS region is always decoded by the standard window
357 * below the 4G boundary, we need to map the rest of the BIOS region that lies
358 * below the top 16MiB in the extended window. Thus, EXT_BIOS_LIMIT will be set to
359 * 16MiB. This determines the maximum address in the SPI flash space that is mapped
360 * to the top of the extended window in the host address space. EXT_BIOS_LIMIT is
361 * basically the offset from the end of the BIOS region that will be mapped to the top
362 * of the extended window.
363 * This enables the decoding as follows:
364 -Standard decode window: (bios_region_top - 16MiB) to bios_region_top
365 -Extended decode window:
366 (bios_region_top - 16MiB - MIN(extended_window_size, bios_size - 16MiB))
367 to (bios_region_top - 16MiB).
368 */
Angel Pons122cc8c2021-02-15 17:18:55 +0100369 pci_or_config32(dev, SPI_BIOS_CONTROL, SPI_BIOS_CONTROL_EXT_BIOS_LIMIT(16 * MiB));
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800370
371 /* Program EXT_BIOS EN */
Angel Pons122cc8c2021-02-15 17:18:55 +0100372 pci_or_config32(dev, SPI_BIOS_CONTROL, SPI_BIOS_CONTROL_EXT_BIOS_ENABLE);
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800373}
374
375/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530376 * Program temporary BAR for SPI in case any of the stages before ramstage need
377 * to access FAST_SPI MMIO regs. Ramstage will assign a new BAR during PCI
378 * enumeration.
379 */
380void fast_spi_early_init(uintptr_t spi_base_address)
381{
Angel Pons52072432021-02-15 13:09:36 +0100382 const pci_devfn_t dev = PCH_DEV_SPI;
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200383 uint16_t pcireg;
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530384
385 /* Assign Resources to SPI Controller */
386 /* Clear BIT 1-2 SPI Command Register */
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200387 pcireg = pci_read_config16(dev, PCI_COMMAND);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530388 pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200389 pci_write_config16(dev, PCI_COMMAND, pcireg);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530390
391 /* Program Temporary BAR for SPI */
392 pci_write_config32(dev, PCI_BASE_ADDRESS_0,
393 spi_base_address | PCI_BASE_ADDRESS_SPACE_MEMORY);
394
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800395 /*
396 * Enable extended bios support. Since it configures memory BAR, this is done before
397 * enabling MMIO space.
398 */
399 fast_spi_enable_ext_bios();
400
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530401 /* Enable Bus Master and MMIO Space */
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200402 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530403
404 /* Initialize SPI to allow BIOS to write/erase on flash. */
405 fast_spi_init();
406}
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700407
Angel Pons967753f2021-02-15 17:44:09 +0100408/* Clear SPI Synchronous SMI status bit and return its value. */
409bool fast_spi_clear_sync_smi_status(void)
410{
411 const uint32_t bios_cntl = pci_read_config32(PCH_DEV_SPI, SPI_BIOS_CONTROL);
412 const bool smi_asserted = bios_cntl & SPI_BIOS_CONTROL_SYNC_SS;
413 /*
414 * Do not unconditionally write 1 to clear SYNC_SS. Hardware could set
415 * SYNC_SS here (after we read but before we write SPI_BIOS_CONTROL),
416 * and the event would be lost when unconditionally clearing SYNC_SS.
417 */
418 pci_write_config32(PCH_DEV_SPI, SPI_BIOS_CONTROL, bios_cntl);
419 return smi_asserted;
420}
421
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700422/* Read SPI Write Protect disable status. */
423bool fast_spi_wpd_status(void)
424{
Angel Pons122cc8c2021-02-15 17:18:55 +0100425 return pci_read_config16(PCH_DEV_SPI, SPI_BIOS_CONTROL) &
426 SPI_BIOS_CONTROL_WPD;
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700427}
428
429/* Enable SPI Write Protect. */
430void fast_spi_enable_wp(void)
431{
Angel Pons52072432021-02-15 13:09:36 +0100432 const pci_devfn_t dev = PCH_DEV_SPI;
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700433 uint8_t bios_cntl;
434
Angel Pons122cc8c2021-02-15 17:18:55 +0100435 bios_cntl = pci_read_config8(dev, SPI_BIOS_CONTROL);
436 bios_cntl &= ~SPI_BIOS_CONTROL_WPD;
437 pci_write_config8(dev, SPI_BIOS_CONTROL, bios_cntl);
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700438}
Angel Ponsd21b4632021-02-10 17:12:05 +0100439
440/* Disable SPI Write Protect. */
441void fast_spi_disable_wp(void)
442{
443 const pci_devfn_t dev = PCH_DEV_SPI;
444 uint8_t bios_cntl;
445
446 bios_cntl = pci_read_config8(dev, SPI_BIOS_CONTROL);
447 bios_cntl |= SPI_BIOS_CONTROL_WPD;
448 pci_write_config8(dev, SPI_BIOS_CONTROL, bios_cntl);
449}
Subrata Banikd5e7c632022-04-14 00:08:05 +0530450
451void fast_spi_clear_outstanding_status(void)
452{
453 void *spibar = fast_spi_get_bar();
454
455 /* Make sure all W1C status bits get cleared. */
456 write32(spibar + SPIBAR_HSFSTS_CTL, SPIBAR_HSFSTS_W1C_BITS);
457}
Werner Zehbae84982022-05-05 11:04:04 +0200458
459static struct device_operations fast_spi_dev_ops = {
460 .read_resources = pci_dev_read_resources,
461 .set_resources = pci_dev_set_resources,
462 .enable_resources = pci_dev_enable_resources,
463};
464
465static const unsigned short pci_device_ids[] = {
466 PCI_DID_INTEL_APL_HWSEQ_SPI,
467 0
468};
469
470static const struct pci_driver fast_spi __pci_driver = {
471 .ops = &fast_spi_dev_ops,
472 .vendor = PCI_VID_INTEL,
473 .devices = pci_device_ids,
474};