coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
fast_spi.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #define __SIMPLE_DEVICE__
4 
5 #include <arch/romstage.h>
6 #include <device/mmio.h>
7 #include <assert.h>
8 #include <device/pci_def.h>
9 #include <device/pci_ops.h>
10 #include <console/console.h>
11 #include <commonlib/helpers.h>
12 #include <cpu/x86/mtrr.h>
13 #include <fast_spi_def.h>
14 #include <intelblocks/fast_spi.h>
15 #include <intelblocks/gpmr.h>
16 #include <lib.h>
17 #include <soc/pci_devs.h>
18 #include <spi_flash.h>
19 #include <spi-generic.h>
20 
21 /*
22  * Get the FAST_SPIBAR.
23  */
24 void *fast_spi_get_bar(void)
25 {
26  const pci_devfn_t dev = PCH_DEV_SPI;
27  uintptr_t bar;
28 
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  */
41 void fast_spi_init(void)
42 {
43  const pci_devfn_t dev = PCH_DEV_SPI;
44  uint8_t bios_cntl;
45 
46  bios_cntl = pci_read_config8(dev, SPI_BIOS_CONTROL);
47 
48  /* Disable the BIOS write protect so write commands are allowed. */
49  bios_cntl &= ~SPI_BIOS_CONTROL_EISS;
50  bios_cntl |= SPI_BIOS_CONTROL_WPD;
51  /* Enable Prefetching and caching. */
53  bios_cntl &= ~SPI_BIOS_CONTROL_CACHE_DISABLE;
54 
55  pci_write_config8(dev, SPI_BIOS_CONTROL, bios_cntl);
56 }
57 
58 /*
59  * Set FAST_SPIBAR BIOS Control register based on input bit field.
60  */
61 static void fast_spi_set_bios_control_reg(uint32_t bios_cntl_bit)
62 {
63  const pci_devfn_t dev = PCH_DEV_SPI;
64  uint32_t bc_cntl;
65 
66  assert((bios_cntl_bit & (bios_cntl_bit - 1)) == 0);
67  bc_cntl = pci_read_config32(dev, SPI_BIOS_CONTROL);
68  bc_cntl |= bios_cntl_bit;
69  pci_write_config32(dev, SPI_BIOS_CONTROL, bc_cntl);
70 }
71 
72 /*
73  * Ensure an additional read back after performing lock down
74  */
76 {
78 }
79 
80 /*
81  * Set FAST_SPIBAR BIOS Control BILD bit.
82  */
84 {
86 
88 }
89 
90 /*
91  * Set FAST_SPIBAR BIOS Control LE bit.
92  */
94 {
96 
98 }
99 
100 /*
101  * Set FAST_SPIBAR BIOS Control EXT BIOS LE bit.
102  */
104 {
105  if (!CONFIG(FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW))
106  return;
107 
109 
111 }
112 
113 /*
114  * Set FAST_SPIBAR BIOS Control EISS bit.
115  */
117 {
119 
121 }
122 
123 /*
124  * Set FAST_SPI opcode menu.
125  */
127 {
128  void *spibar = fast_spi_get_bar();
129 
134 }
135 
136 /*
137  * Lock FAST_SPIBAR.
138  * 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.
144  */
146 {
147  void *spibar = fast_spi_get_bar();
149 
150  if (CONFIG(FAST_SPI_DISABLE_WRITE_STATUS))
151  hsfs |= SPIBAR_HSFSTS_WRSDIS;
152 
154 }
155 
156 /*
157  * Set FAST_SPIBAR + DLOCK (0x0C) register bits to discrete lock the
158  * FAST_SPI Protected Range (PR) registers.
159  */
161 {
162  void *spibar = fast_spi_get_bar();
163  uint32_t dlock;
164 
165  dlock = read32(spibar + SPIBAR_DLOCK);
169 
170  write32(spibar + SPIBAR_DLOCK, dlock);
171 }
172 
173 /*
174  * Set FAST_SPIBAR + VSCC0 (0xC4) register VCL (bit 30).
175  */
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  */
188 }
189 
190 /*
191  * Set FAST_SPIBAR Soft Reset Data Register value.
192  */
194 {
195  void *spibar = fast_spi_get_bar();
196  uint32_t ssl, ssms;
197 
198  /* Set Strap Lock Disable */
200  ssl &= ~SPIBAR_RESET_LOCK_ENABLE;
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;
210 
211  /* Set Strap Lock Enable */
215 }
216 
217 static 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 
229 /*
230  * Returns bios_start and fills in size of the BIOS region.
231  */
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  */
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 
249 static 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 
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 
270 {
271  size_t ext_bios_size;
272  uintptr_t ext_bios_base;
273 
274  if (!fast_spi_ext_bios_cache_range(&ext_bios_base, &ext_bios_size))
275  return;
276 
277  fast_spi_enable_cache_range(ext_bios_base, ext_bios_size);
278 }
279 
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 
293 {
294  size_t bios_size;
295  uint32_t alignment;
296  uintptr_t base;
297 
298  /* Only the IFD BIOS region is memory mapped (at top of 4G) */
300 
301  /* LOCAL APIC default address is 0xFEE0000, bios_size over 16MB will
302  * cause memory type conflict when setting memory type to write
303  * protection, so limit the cached BIOS region to be no more than 16MB.
304  * */
305  bios_size = MIN(bios_size, 16 * MiB);
306  if (bios_size <= 0)
307  return;
308 
309  /* Round to power of two */
310  alignment = 1UL << (log2_ceil(bios_size));
311  bios_size = ALIGN_UP(bios_size, alignment);
312  base = 4ULL*GiB - bios_size;
313 
315 
316  /* Check if caching is needed for extended bios region if supported */
318 }
319 
320 /*
321  * Enable extended BIOS support
322  * Checks BIOS region in the flashmap, if its more than 16Mib, enables extended BIOS
323  * region support.
324  */
325 static void fast_spi_enable_ext_bios(void)
326 {
327  const pci_devfn_t dev = PCH_DEV_SPI;
328  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 
344  /* Configure Source decode for Extended BIOS Region */
345  if (enable_gpmr(CONFIG_EXT_BIOS_WIN_BASE, CONFIG_EXT_BIOS_WIN_SIZE,
347  return;
348 
349  /* Program EXT_BIOS_BAR1 with obtained ext_bios_base */
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  */
368 
369  /* Program EXT_BIOS EN */
371 }
372 
373 /*
374  * 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  */
378 void fast_spi_early_init(uintptr_t spi_base_address)
379 {
380  const pci_devfn_t dev = PCH_DEV_SPI;
381  uint16_t pcireg;
382 
383  /* Assign Resources to SPI Controller */
384  /* Clear BIT 1-2 SPI Command Register */
385  pcireg = pci_read_config16(dev, PCI_COMMAND);
386  pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
387  pci_write_config16(dev, PCI_COMMAND, pcireg);
388 
389  /* Program Temporary BAR for SPI */
391  spi_base_address | PCI_BASE_ADDRESS_SPACE_MEMORY);
392 
393  /*
394  * Enable extended bios support. Since it configures memory BAR, this is done before
395  * enabling MMIO space.
396  */
398 
399  /* Enable Bus Master and MMIO Space */
401 
402  /* Initialize SPI to allow BIOS to write/erase on flash. */
403  fast_spi_init();
404 }
405 
406 /* Clear SPI Synchronous SMI status bit and return its value. */
408 {
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  */
417  return smi_asserted;
418 }
419 
420 /* Read SPI Write Protect disable status. */
422 {
425 }
426 
427 /* Enable SPI Write Protect. */
429 {
430  const pci_devfn_t dev = PCH_DEV_SPI;
431  uint8_t bios_cntl;
432 
433  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);
436 }
437 
438 /* Disable SPI Write Protect. */
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 }
448 
450 {
451  void *spibar = fast_spi_get_bar();
452 
453  /* Make sure all W1C status bits get cleared. */
455 }
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
static void write16(void *addr, uint16_t val)
Definition: mmio.h:35
void postcar_frame_add_mtrr(struct postcar_frame *pcf, uintptr_t addr, size_t size, int type)
#define assert(statement)
Definition: assert.h:74
#define MIN(a, b)
Definition: helpers.h:37
#define ALIGN_DOWN(x, a)
Definition: helpers.h:18
#define MiB
Definition: helpers.h:76
#define KiB
Definition: helpers.h:75
#define GiB
Definition: helpers.h:77
#define ALIGN_UP(x, a)
Definition: helpers.h:17
@ CB_ERR
Generic error code.
Definition: cb_err.h:17
#define printk(level,...)
Definition: stdlib.h:16
@ CONFIG
Definition: dsi_common.h:201
void fast_spi_set_lock_enable(void)
Definition: fast_spi.c:93
void fast_spi_early_init(uintptr_t spi_base_address)
Definition: fast_spi.c:378
void fast_spi_set_ext_bios_lock_enable(void)
Definition: fast_spi.c:103
void fast_spi_vscc0_lock(void)
Definition: fast_spi.c:176
void fast_spi_set_eiss(void)
Definition: fast_spi.c:116
void fast_spi_init(void)
Definition: fast_spi.c:41
static bool fast_spi_ext_bios_cache_range(uintptr_t *base, size_t *size)
Definition: fast_spi.c:249
void fast_spi_enable_wp(void)
Definition: fast_spi.c:428
void fast_spi_cache_bios_region(void)
Definition: fast_spi.c:292
static void fast_spi_read_post_write(uint8_t reg)
Definition: fast_spi.c:75
size_t fast_spi_get_bios_region(size_t *bios_size)
Definition: fast_spi.c:232
static void fast_spi_cache_ext_bios_window(void)
Definition: fast_spi.c:269
void fast_spi_clear_outstanding_status(void)
Definition: fast_spi.c:449
void fast_spi_set_bios_interface_lock_down(void)
Definition: fast_spi.c:83
void * fast_spi_get_bar(void)
Definition: fast_spi.c:24
void fast_spi_cache_ext_bios_postcar(struct postcar_frame *pcf)
Definition: fast_spi.c:280
bool fast_spi_clear_sync_smi_status(void)
Definition: fast_spi.c:407
void fast_spi_pr_dlock(void)
Definition: fast_spi.c:160
bool fast_spi_wpd_status(void)
Definition: fast_spi.c:421
void fast_spi_lock_bar(void)
Definition: fast_spi.c:145
static void fast_spi_enable_ext_bios(void)
Definition: fast_spi.c:325
void fast_spi_disable_wp(void)
Definition: fast_spi.c:439
static void fast_spi_enable_cache_range(unsigned int base, unsigned int size)
Definition: fast_spi.c:217
void fast_spi_set_strap_msg_data(uint32_t soft_reset_data)
Definition: fast_spi.c:193
static void fast_spi_set_bios_control_reg(uint32_t bios_cntl_bit)
Definition: fast_spi.c:61
void fast_spi_set_opcode_menu(void)
Definition: fast_spi.c:126
#define SPI_BIOS_CONTROL_PREFETCH_ENABLE
Definition: fast_spi_def.h:17
#define SPIBAR_BFPREG_PRL_SHIFT
Definition: fast_spi_def.h:45
#define SPI_BIOS_CONTROL_CACHE_DISABLE
Definition: fast_spi_def.h:16
#define SPIBAR_DLOCK_PR2LOCKDN
Definition: fast_spi_def.h:86
#define SPIBAR_HSFSTS_W1C_BITS
Definition: fast_spi_def.h:78
#define SPI_BIOS_CONTROL
Definition: fast_spi_def.h:8
#define SPIBAR_DLOCK_PR1LOCKDN
Definition: fast_spi_def.h:85
#define SPIBAR_HSFSTS_WRSDIS
Definition: fast_spi_def.h:68
#define SPIBAR_DLOCK_PR4LOCKDN
Definition: fast_spi_def.h:88
#define SPIBAR_HSFSTS_FLOCKDN
Definition: fast_spi_def.h:64
#define SPIBAR_RESET_CTRL_SSMC
Definition: fast_spi_def.h:159
#define SPIBAR_OPMENU_UPPER
Definition: fast_spi_def.h:37
#define SPI_BIOS_CONTROL_EXT_BIOS_ENABLE
Definition: fast_spi_def.h:21
#define SPIBAR_DLOCK_PR0LOCKDN
Definition: fast_spi_def.h:84
#define SPI_BIOS_CONTROL_EXT_BIOS_LOCK_ENABLE
Definition: fast_spi_def.h:22
#define SPIBAR_HSFSTS_PRR34_LOCKDN
Definition: fast_spi_def.h:67
#define SPIBAR_BFPREG_PRB_MASK
Definition: fast_spi_def.h:44
#define SPIBAR_BFPREG_PRL_MASK
Definition: fast_spi_def.h:46
#define SPI_BIOS_CONTROL_EXT_BIOS_LIMIT(x)
Definition: fast_spi_def.h:23
#define SPIBAR_HSFSTS_CTL
Definition: fast_spi_def.h:28
#define SPI_BIOS_CONTROL_SYNC_SS
Definition: fast_spi_def.h:20
#define SPIBAR_PREOP
Definition: fast_spi_def.h:34
#define SPIBAR_DLOCK
Definition: fast_spi_def.h:30
#define SPI_CFG_BAR1
Definition: fast_spi_def.h:11
#define SPIBAR_RESET_CTRL
Definition: fast_spi_def.h:151
#define SPIBAR_BFPREG
Definition: fast_spi_def.h:27
#define SPIBAR_RESET_DATA
Definition: fast_spi_def.h:152
#define SPIBAR_DLOCK_PR3LOCKDN
Definition: fast_spi_def.h:87
#define SPIBAR_OPTYPE
Definition: fast_spi_def.h:35
#define SPI_BIOS_CONTROL_EISS
Definition: fast_spi_def.h:18
#define SPIBAR_SFDP0_VSCC0
Definition: fast_spi_def.h:138
#define SPI_BIOS_CONTROL_BILD
Definition: fast_spi_def.h:19
#define SPI_BIOS_CONTROL_WPD
Definition: fast_spi_def.h:14
#define SPIBAR_RESET_LOCK
Definition: fast_spi_def.h:150
#define SPIBAR_OPMENU_LOWER
Definition: fast_spi_def.h:36
#define SPIBAR_VSCC0_VCL
Definition: fast_spi_def.h:139
#define SPI_BIOS_CONTROL_LOCK_ENABLE
Definition: fast_spi_def.h:15
#define SPIBAR_RESET_LOCK_ENABLE
Definition: fast_spi_def.h:156
#define SPI_OPMENU_LOWER
Definition: w25q64.c:40
#define SPI_OPTYPE
Definition: w25q64.c:34
#define SPI_OPPREFIX
Definition: w25q64.c:33
#define SPI_OPMENU_UPPER
Definition: w25q64.c:38
enum cb_err enable_gpmr(uint32_t base, uint32_t size, uint32_t dest_id)
Definition: gpmr.c:41
#define setbits32(addr, set)
Definition: mmio.h:21
static __always_inline void pci_or_config32(const struct device *dev, u16 reg, u32 ormask)
Definition: pci_ops.h:191
static __always_inline void pci_write_config32(const struct device *dev, u16 reg, u32 val)
Definition: pci_ops.h:76
static __always_inline void pci_or_config16(const struct device *dev, u16 reg, u16 ormask)
Definition: pci_ops.h:180
static __always_inline u16 pci_read_config16(const struct device *dev, u16 reg)
Definition: pci_ops.h:52
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
static __always_inline u8 pci_read_config8(const struct device *dev, u16 reg)
Definition: pci_ops.h:46
static __always_inline void pci_write_config16(const struct device *dev, u16 reg, u16 val)
Definition: pci_ops.h:70
static __always_inline void pci_write_config8(const struct device *dev, u16 reg, u8 val)
Definition: pci_ops.h:64
unsigned int type
Definition: edid.c:57
static int log2_ceil(u32 x)
Definition: lib.h:60
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
Definition: loglevel.h:86
_Static_assert(sizeof(hls_t)==HLS_SIZE, "HLS_SIZE must equal to sizeof(hls_t)")
int get_free_var_mtrr(void)
Definition: mtrrlib.c:11
void set_var_mtrr(unsigned int reg, unsigned int base, unsigned int size, unsigned int type)
Definition: mtrrlib.c:30
#define PCI_BASE_ADDRESS_MEM_ATTR_MASK
Definition: pci_def.h:77
#define PCI_COMMAND_MASTER
Definition: pci_def.h:13
#define PCI_COMMAND_MEMORY
Definition: pci_def.h:12
#define PCI_BASE_ADDRESS_0
Definition: pci_def.h:63
#define PCI_COMMAND
Definition: pci_def.h:10
#define PCI_BASE_ADDRESS_SPACE_MEMORY
Definition: pci_def.h:71
u32 pci_devfn_t
Definition: pci_type.h:8
uintptr_t base
Definition: uart.c:17
#define PCH_DEV_SPI
Definition: pci_devs.h:241
uint32_t soc_get_spi_psf_destination_id(void)
Definition: spi.c:32
static size_t bios_size
Definition: mmap_boot.c:43
void fast_spi_get_ext_bios_window(uintptr_t *base, size_t *size)
Definition: mmap_boot.c:146
static uintptr_t spibar
Definition: spi.c:32
unsigned short uint16_t
Definition: stdint.h:11
unsigned int uint32_t
Definition: stdint.h:14
unsigned long uintptr_t
Definition: stdint.h:21
unsigned char uint8_t
Definition: stdint.h:8
u8 val
Definition: sys.c:300
#define MTRR_TYPE_WRPROT
Definition: mtrr.h:13