blob: 3dc74408dc82abe5e4d0ad3cd92577b59d52b98e [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
Werner Zeh53553e82022-05-05 11:55:30 +02005#include <acpi/acpi.h>
6#include <acpi/acpigen.h>
Srinidhi N Kaushik4eb489f2020-11-25 02:21:57 -08007#include <arch/romstage.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02008#include <device/mmio.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +05309#include <assert.h>
Werner Zehbae84982022-05-05 11:04:04 +020010#include <device/pci.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053011#include <device/pci_def.h>
Werner Zehbae84982022-05-05 11:04:04 +020012#include <device/pci_ids.h>
Patrick Rudolphe56189c2018-04-18 10:11:59 +020013#include <device/pci_ops.h>
Subrata Banikdef18c42022-03-31 00:16:00 +053014#include <console/console.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053015#include <commonlib/helpers.h>
Aaron Durbin5391e552017-06-02 12:16:04 -050016#include <cpu/x86/mtrr.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053017#include <fast_spi_def.h>
18#include <intelblocks/fast_spi.h>
Subrata Banik211be9c2022-04-13 12:13:09 +053019#include <intelblocks/gpmr.h>
Aaron Durbin5391e552017-06-02 12:16:04 -050020#include <lib.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053021#include <soc/pci_devs.h>
22#include <spi_flash.h>
23#include <spi-generic.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053024
25/*
26 * Get the FAST_SPIBAR.
27 */
28void *fast_spi_get_bar(void)
29{
Angel Pons52072432021-02-15 13:09:36 +010030 const pci_devfn_t dev = PCH_DEV_SPI;
Barnali Sarkar89331cd2017-02-16 17:22:37 +053031 uintptr_t bar;
32
33 bar = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
34 assert(bar != 0);
35 /*
36 * Bits 31-12 are the base address as per EDS for SPI,
37 * Don't care about 0-11 bit
38 */
39 return (void *)(bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK);
40}
41
42/*
43 * Disable the BIOS write protect and Enable Prefetching and Caching.
44 */
45void fast_spi_init(void)
46{
Angel Pons52072432021-02-15 13:09:36 +010047 const pci_devfn_t dev = PCH_DEV_SPI;
Barnali Sarkar89331cd2017-02-16 17:22:37 +053048 uint8_t bios_cntl;
49
Angel Pons122cc8c2021-02-15 17:18:55 +010050 bios_cntl = pci_read_config8(dev, SPI_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053051
52 /* Disable the BIOS write protect so write commands are allowed. */
Angel Pons122cc8c2021-02-15 17:18:55 +010053 bios_cntl &= ~SPI_BIOS_CONTROL_EISS;
54 bios_cntl |= SPI_BIOS_CONTROL_WPD;
Barnali Sarkar89331cd2017-02-16 17:22:37 +053055 /* Enable Prefetching and caching. */
Angel Pons122cc8c2021-02-15 17:18:55 +010056 bios_cntl |= SPI_BIOS_CONTROL_PREFETCH_ENABLE;
57 bios_cntl &= ~SPI_BIOS_CONTROL_CACHE_DISABLE;
Barnali Sarkar89331cd2017-02-16 17:22:37 +053058
Angel Pons122cc8c2021-02-15 17:18:55 +010059 pci_write_config8(dev, SPI_BIOS_CONTROL, bios_cntl);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053060}
61
62/*
Subrata Banik8e390092017-07-21 10:06:17 +053063 * Set FAST_SPIBAR BIOS Control register based on input bit field.
Barnali Sarkar89331cd2017-02-16 17:22:37 +053064 */
Srinidhi N Kaushik28e1d0e2020-11-25 21:57:37 -080065static void fast_spi_set_bios_control_reg(uint32_t bios_cntl_bit)
Barnali Sarkar89331cd2017-02-16 17:22:37 +053066{
Angel Pons52072432021-02-15 13:09:36 +010067 const pci_devfn_t dev = PCH_DEV_SPI;
Srinidhi N Kaushik28e1d0e2020-11-25 21:57:37 -080068 uint32_t bc_cntl;
Barnali Sarkar89331cd2017-02-16 17:22:37 +053069
70 assert((bios_cntl_bit & (bios_cntl_bit - 1)) == 0);
Angel Pons122cc8c2021-02-15 17:18:55 +010071 bc_cntl = pci_read_config32(dev, SPI_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053072 bc_cntl |= bios_cntl_bit;
Angel Pons122cc8c2021-02-15 17:18:55 +010073 pci_write_config32(dev, SPI_BIOS_CONTROL, bc_cntl);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053074}
75
76/*
Subrata Banik8e390092017-07-21 10:06:17 +053077 * Ensure an additional read back after performing lock down
78 */
79static void fast_spi_read_post_write(uint8_t reg)
80{
81 pci_read_config8(PCH_DEV_SPI, reg);
82}
83
84/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +053085 * Set FAST_SPIBAR BIOS Control BILD bit.
86 */
87void fast_spi_set_bios_interface_lock_down(void)
88{
Angel Pons122cc8c2021-02-15 17:18:55 +010089 fast_spi_set_bios_control_reg(SPI_BIOS_CONTROL_BILD);
Subrata Banik8e390092017-07-21 10:06:17 +053090
Angel Pons122cc8c2021-02-15 17:18:55 +010091 fast_spi_read_post_write(SPI_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053092}
93
94/*
95 * Set FAST_SPIBAR BIOS Control LE bit.
96 */
97void fast_spi_set_lock_enable(void)
98{
Angel Pons122cc8c2021-02-15 17:18:55 +010099 fast_spi_set_bios_control_reg(SPI_BIOS_CONTROL_LOCK_ENABLE);
Subrata Banik8e390092017-07-21 10:06:17 +0530100
Angel Pons122cc8c2021-02-15 17:18:55 +0100101 fast_spi_read_post_write(SPI_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530102}
103
104/*
Srinidhi N Kaushik28e1d0e2020-11-25 21:57:37 -0800105 * Set FAST_SPIBAR BIOS Control EXT BIOS LE bit.
106 */
107void fast_spi_set_ext_bios_lock_enable(void)
108{
109 if (!CONFIG(FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW))
110 return;
111
Angel Pons122cc8c2021-02-15 17:18:55 +0100112 fast_spi_set_bios_control_reg(SPI_BIOS_CONTROL_EXT_BIOS_LOCK_ENABLE);
Srinidhi N Kaushik28e1d0e2020-11-25 21:57:37 -0800113
Angel Pons122cc8c2021-02-15 17:18:55 +0100114 fast_spi_read_post_write(SPI_BIOS_CONTROL);
Srinidhi N Kaushik28e1d0e2020-11-25 21:57:37 -0800115}
116
117/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530118 * Set FAST_SPIBAR BIOS Control EISS bit.
119 */
120void fast_spi_set_eiss(void)
121{
Angel Pons122cc8c2021-02-15 17:18:55 +0100122 fast_spi_set_bios_control_reg(SPI_BIOS_CONTROL_EISS);
Subrata Banik8e390092017-07-21 10:06:17 +0530123
Angel Pons122cc8c2021-02-15 17:18:55 +0100124 fast_spi_read_post_write(SPI_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530125}
126
127/*
128 * Set FAST_SPI opcode menu.
129 */
130void fast_spi_set_opcode_menu(void)
131{
132 void *spibar = fast_spi_get_bar();
133
134 write16(spibar + SPIBAR_PREOP, SPI_OPPREFIX);
135 write16(spibar + SPIBAR_OPTYPE, SPI_OPTYPE);
136 write32(spibar + SPIBAR_OPMENU_LOWER, SPI_OPMENU_LOWER);
137 write32(spibar + SPIBAR_OPMENU_UPPER, SPI_OPMENU_UPPER);
138}
139
140/*
141 * Lock FAST_SPIBAR.
Barnali Sarkar8e513192017-07-19 16:09:56 +0530142 * Use 16bit write to avoid touching two upper bytes what may cause the write
143 * cycle to fail in case a prior transaction has not completed.
144 * While WRSDIS is lockable with FLOCKDN, writing both in the same
145 * cycle is guaranteed to work by design.
146 *
147 * Avoid read->modify->write not to clear RW1C bits unintentionally.
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530148 */
149void fast_spi_lock_bar(void)
150{
151 void *spibar = fast_spi_get_bar();
Marc Jones051bf5d2021-03-30 12:16:09 -0600152 uint16_t hsfs = SPIBAR_HSFSTS_FLOCKDN | SPIBAR_HSFSTS_PRR34_LOCKDN;
Duncan Lauriedc1e6bc2017-08-15 13:32:26 -0700153
Julius Wernercd49cce2019-03-05 16:53:33 -0800154 if (CONFIG(FAST_SPI_DISABLE_WRITE_STATUS))
Duncan Lauriedc1e6bc2017-08-15 13:32:26 -0700155 hsfs |= SPIBAR_HSFSTS_WRSDIS;
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530156
Barnali Sarkar8e513192017-07-19 16:09:56 +0530157 write16(spibar + SPIBAR_HSFSTS_CTL, hsfs);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530158}
159
160/*
Barnali Sarkar4f6e3412017-08-17 11:49:27 +0530161 * Set FAST_SPIBAR + DLOCK (0x0C) register bits to discrete lock the
162 * FAST_SPI Protected Range (PR) registers.
163 */
164void fast_spi_pr_dlock(void)
165{
166 void *spibar = fast_spi_get_bar();
167 uint32_t dlock;
168
169 dlock = read32(spibar + SPIBAR_DLOCK);
170 dlock |= (SPIBAR_DLOCK_PR0LOCKDN | SPIBAR_DLOCK_PR1LOCKDN
171 | SPIBAR_DLOCK_PR2LOCKDN | SPIBAR_DLOCK_PR3LOCKDN
172 | SPIBAR_DLOCK_PR4LOCKDN);
173
174 write32(spibar + SPIBAR_DLOCK, dlock);
175}
176
177/*
Subrata Banikd6431652022-04-13 20:30:53 +0530178 * Set FAST_SPIBAR + VSCC0 (0xC4) register VCL (bit 30).
179 */
180void fast_spi_vscc0_lock(void)
181{
182 void *spibar = fast_spi_get_bar();
183
184 /*
185 * SPI Flash Programming Guide Section 5.5.2 describes Vendor Component Lock (VCL).
186 * It is recommended to set the VCL bit. VCL applies to both VSCC0 and VSCC1.
187 * Without this bit being set, it is possible to modify Host/GbE VSCC register(s),
188 * which might results in undesired host and integrated GbE Serial Flash
189 * functionality.
190 */
191 setbits32(spibar + SPIBAR_SFDP0_VSCC0, SPIBAR_VSCC0_VCL);
192}
193
194/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530195 * Set FAST_SPIBAR Soft Reset Data Register value.
196 */
197void fast_spi_set_strap_msg_data(uint32_t soft_reset_data)
198{
199 void *spibar = fast_spi_get_bar();
200 uint32_t ssl, ssms;
201
202 /* Set Strap Lock Disable */
203 ssl = read32(spibar + SPIBAR_RESET_LOCK);
204 ssl &= ~SPIBAR_RESET_LOCK_ENABLE;
205 write32(spibar + SPIBAR_RESET_LOCK, ssl);
206
207 /* Write Soft Reset Data register at SPIBAR0 offset 0xF8[0:15] */
208 write32(spibar + SPIBAR_RESET_DATA, soft_reset_data);
209
210 /* Set Strap Mux Select set to '1' */
211 ssms = read32(spibar + SPIBAR_RESET_CTRL);
212 ssms |= SPIBAR_RESET_CTRL_SSMC;
213 write32(spibar + SPIBAR_RESET_CTRL, ssms);
214
215 /* Set Strap Lock Enable */
216 ssl = read32(spibar + SPIBAR_RESET_LOCK);
217 ssl |= SPIBAR_RESET_LOCK_ENABLE;
218 write32(spibar + SPIBAR_RESET_LOCK, ssl);
219}
220
Subrata Banikdef18c42022-03-31 00:16:00 +0530221static void fast_spi_enable_cache_range(unsigned int base, unsigned int size)
222{
223 const int type = MTRR_TYPE_WRPROT;
224 int mtrr = get_free_var_mtrr();
225 if (mtrr == -1) {
226 printk(BIOS_WARNING, "ROM caching failed due to no free MTRR available!\n");
227 return;
228 }
229
230 set_var_mtrr(mtrr, base, size, type);
231}
232
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530233/*
234 * Returns bios_start and fills in size of the BIOS region.
235 */
236size_t fast_spi_get_bios_region(size_t *bios_size)
237{
238 size_t bios_start, bios_end;
239 /*
240 * BIOS_BFPREG provides info about BIOS Flash Primary Region
241 * Base and Limit.
242 * Base and Limit fields are in units of 4KiB.
243 */
244 uint32_t val = read32(fast_spi_get_bar() + SPIBAR_BFPREG);
245
246 bios_start = (val & SPIBAR_BFPREG_PRB_MASK) * 4 * KiB;
247 bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >>
248 SPIBAR_BFPREG_PRL_SHIFT) + 1) * 4 * KiB;
249 *bios_size = bios_end - bios_start;
250 return bios_start;
251}
252
Srinidhi N Kaushik4eb489f2020-11-25 02:21:57 -0800253static bool fast_spi_ext_bios_cache_range(uintptr_t *base, size_t *size)
254{
255 uint32_t alignment;
256 if (!CONFIG(FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW))
257 return false;
258
259 fast_spi_get_ext_bios_window(base, size);
260
261 /* Enable extended bios only if Size of Bios region is greater than 16MiB */
262 if (*size == 0 || *base == 0)
263 return false;
264
265 /* Round to power of two */
266 alignment = 1UL << (log2_ceil(*size));
267 *size = ALIGN_UP(*size, alignment);
268 *base = ALIGN_DOWN(*base, *size);
269
270 return true;
271}
272
273static void fast_spi_cache_ext_bios_window(void)
274{
275 size_t ext_bios_size;
276 uintptr_t ext_bios_base;
Srinidhi N Kaushik4eb489f2020-11-25 02:21:57 -0800277
278 if (!fast_spi_ext_bios_cache_range(&ext_bios_base, &ext_bios_size))
279 return;
280
Subrata Banikdef18c42022-03-31 00:16:00 +0530281 fast_spi_enable_cache_range(ext_bios_base, ext_bios_size);
Srinidhi N Kaushik4eb489f2020-11-25 02:21:57 -0800282}
283
284void fast_spi_cache_ext_bios_postcar(struct postcar_frame *pcf)
285{
286 size_t ext_bios_size;
287 uintptr_t ext_bios_base;
288 const int type = MTRR_TYPE_WRPROT;
289
290 if (!fast_spi_ext_bios_cache_range(&ext_bios_base, &ext_bios_size))
291 return;
292
293 postcar_frame_add_mtrr(pcf, ext_bios_base, ext_bios_size, type);
294}
295
Aaron Durbin5391e552017-06-02 12:16:04 -0500296void fast_spi_cache_bios_region(void)
297{
Aaron Durbin5391e552017-06-02 12:16:04 -0500298 size_t bios_size;
299 uint32_t alignment;
Aaron Durbin0b34fc62017-06-08 10:52:58 -0500300 uintptr_t base;
Aaron Durbin5391e552017-06-02 12:16:04 -0500301
302 /* Only the IFD BIOS region is memory mapped (at top of 4G) */
303 fast_spi_get_bios_region(&bios_size);
304
Lijian Zhaoad1e49a2018-11-29 16:24:24 -0800305 /* LOCAL APIC default address is 0xFEE0000, bios_size over 16MB will
306 * cause memory type conflict when setting memory type to write
Elyes HAOUAS6dc9d032020-02-16 16:22:52 +0100307 * protection, so limit the cached BIOS region to be no more than 16MB.
Lijian Zhaoad1e49a2018-11-29 16:24:24 -0800308 * */
309 bios_size = MIN(bios_size, 16 * MiB);
John Zhao1ceac4e2019-07-09 14:27:28 -0700310 if (bios_size <= 0)
John Zhao2bb432e2019-05-21 19:32:51 -0700311 return;
Lijian Zhaoad1e49a2018-11-29 16:24:24 -0800312
Aaron Durbin5391e552017-06-02 12:16:04 -0500313 /* Round to power of two */
Paul Menzel64e83402017-10-27 11:05:14 +0200314 alignment = 1UL << (log2_ceil(bios_size));
Aaron Durbin5391e552017-06-02 12:16:04 -0500315 bios_size = ALIGN_UP(bios_size, alignment);
Aaron Durbin0b34fc62017-06-08 10:52:58 -0500316 base = 4ULL*GiB - bios_size;
317
Subrata Banikdef18c42022-03-31 00:16:00 +0530318 fast_spi_enable_cache_range(base, bios_size);
Srinidhi N Kaushik4eb489f2020-11-25 02:21:57 -0800319
320 /* Check if caching is needed for extended bios region if supported */
321 fast_spi_cache_ext_bios_window();
Aaron Durbin5391e552017-06-02 12:16:04 -0500322}
323
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530324/*
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800325 * Enable extended BIOS support
326 * Checks BIOS region in the flashmap, if its more than 16Mib, enables extended BIOS
327 * region support.
328 */
329static void fast_spi_enable_ext_bios(void)
330{
Angel Pons52072432021-02-15 13:09:36 +0100331 const pci_devfn_t dev = PCH_DEV_SPI;
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800332 if (!CONFIG(FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW))
333 return;
334
335#if CONFIG(FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW)
336 /*
337 * Ensure that the base for the extended window in host space is a multiple of 32 MiB
338 * and size is fixed at 32 MiB. Controller assumes that the extended window has a fixed
339 * size of 32 MiB even if the actual BIOS region is smaller. The mapping of the BIOS
340 * region happens at the top of the extended window in this case.
341 */
342 _Static_assert(ALIGN_UP(CONFIG_EXT_BIOS_WIN_BASE, 32 * MiB) == CONFIG_EXT_BIOS_WIN_BASE,
343 "Extended BIOS window base must be a multiple of 32 * MiB!");
344 _Static_assert(CONFIG_EXT_BIOS_WIN_SIZE == (32 * MiB),
345 "Only 32MiB windows are supported for extended BIOS!");
346#endif
347
Wonkyu Kimaaec8092021-09-15 15:52:51 -0700348 /* Configure Source decode for Extended BIOS Region */
Subrata Banik211be9c2022-04-13 12:13:09 +0530349 if (enable_gpmr(CONFIG_EXT_BIOS_WIN_BASE, CONFIG_EXT_BIOS_WIN_SIZE,
Wonkyu Kimaaec8092021-09-15 15:52:51 -0700350 soc_get_spi_psf_destination_id()) == CB_ERR)
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800351 return;
352
353 /* Program EXT_BIOS_BAR1 with obtained ext_bios_base */
354 pci_write_config32(dev, SPI_CFG_BAR1,
355 CONFIG_EXT_BIOS_WIN_BASE | PCI_BASE_ADDRESS_SPACE_MEMORY);
356
357 /*
358 * Since the top 16MiB of the BIOS region is always decoded by the standard window
359 * below the 4G boundary, we need to map the rest of the BIOS region that lies
360 * below the top 16MiB in the extended window. Thus, EXT_BIOS_LIMIT will be set to
361 * 16MiB. This determines the maximum address in the SPI flash space that is mapped
362 * to the top of the extended window in the host address space. EXT_BIOS_LIMIT is
363 * basically the offset from the end of the BIOS region that will be mapped to the top
364 * of the extended window.
365 * This enables the decoding as follows:
366 -Standard decode window: (bios_region_top - 16MiB) to bios_region_top
367 -Extended decode window:
368 (bios_region_top - 16MiB - MIN(extended_window_size, bios_size - 16MiB))
369 to (bios_region_top - 16MiB).
370 */
Angel Pons122cc8c2021-02-15 17:18:55 +0100371 pci_or_config32(dev, SPI_BIOS_CONTROL, SPI_BIOS_CONTROL_EXT_BIOS_LIMIT(16 * MiB));
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800372
373 /* Program EXT_BIOS EN */
Angel Pons122cc8c2021-02-15 17:18:55 +0100374 pci_or_config32(dev, SPI_BIOS_CONTROL, SPI_BIOS_CONTROL_EXT_BIOS_ENABLE);
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800375}
376
377/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530378 * Program temporary BAR for SPI in case any of the stages before ramstage need
379 * to access FAST_SPI MMIO regs. Ramstage will assign a new BAR during PCI
380 * enumeration.
381 */
382void fast_spi_early_init(uintptr_t spi_base_address)
383{
Angel Pons52072432021-02-15 13:09:36 +0100384 const pci_devfn_t dev = PCH_DEV_SPI;
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200385 uint16_t pcireg;
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530386
387 /* Assign Resources to SPI Controller */
388 /* Clear BIT 1-2 SPI Command Register */
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200389 pcireg = pci_read_config16(dev, PCI_COMMAND);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530390 pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200391 pci_write_config16(dev, PCI_COMMAND, pcireg);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530392
393 /* Program Temporary BAR for SPI */
394 pci_write_config32(dev, PCI_BASE_ADDRESS_0,
395 spi_base_address | PCI_BASE_ADDRESS_SPACE_MEMORY);
396
Srinidhi N Kaushik60949082020-11-25 01:58:34 -0800397 /*
398 * Enable extended bios support. Since it configures memory BAR, this is done before
399 * enabling MMIO space.
400 */
401 fast_spi_enable_ext_bios();
402
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530403 /* Enable Bus Master and MMIO Space */
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200404 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530405
406 /* Initialize SPI to allow BIOS to write/erase on flash. */
407 fast_spi_init();
408}
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700409
Angel Pons967753f2021-02-15 17:44:09 +0100410/* Clear SPI Synchronous SMI status bit and return its value. */
411bool fast_spi_clear_sync_smi_status(void)
412{
413 const uint32_t bios_cntl = pci_read_config32(PCH_DEV_SPI, SPI_BIOS_CONTROL);
414 const bool smi_asserted = bios_cntl & SPI_BIOS_CONTROL_SYNC_SS;
415 /*
416 * Do not unconditionally write 1 to clear SYNC_SS. Hardware could set
417 * SYNC_SS here (after we read but before we write SPI_BIOS_CONTROL),
418 * and the event would be lost when unconditionally clearing SYNC_SS.
419 */
420 pci_write_config32(PCH_DEV_SPI, SPI_BIOS_CONTROL, bios_cntl);
421 return smi_asserted;
422}
423
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700424/* Read SPI Write Protect disable status. */
425bool fast_spi_wpd_status(void)
426{
Angel Pons122cc8c2021-02-15 17:18:55 +0100427 return pci_read_config16(PCH_DEV_SPI, SPI_BIOS_CONTROL) &
428 SPI_BIOS_CONTROL_WPD;
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700429}
430
431/* Enable SPI Write Protect. */
432void fast_spi_enable_wp(void)
433{
Angel Pons52072432021-02-15 13:09:36 +0100434 const pci_devfn_t dev = PCH_DEV_SPI;
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700435 uint8_t bios_cntl;
436
Angel Pons122cc8c2021-02-15 17:18:55 +0100437 bios_cntl = pci_read_config8(dev, SPI_BIOS_CONTROL);
438 bios_cntl &= ~SPI_BIOS_CONTROL_WPD;
439 pci_write_config8(dev, SPI_BIOS_CONTROL, bios_cntl);
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700440}
Angel Ponsd21b4632021-02-10 17:12:05 +0100441
442/* Disable SPI Write Protect. */
443void fast_spi_disable_wp(void)
444{
445 const pci_devfn_t dev = PCH_DEV_SPI;
446 uint8_t bios_cntl;
447
448 bios_cntl = pci_read_config8(dev, SPI_BIOS_CONTROL);
449 bios_cntl |= SPI_BIOS_CONTROL_WPD;
450 pci_write_config8(dev, SPI_BIOS_CONTROL, bios_cntl);
451}
Subrata Banikd5e7c632022-04-14 00:08:05 +0530452
453void fast_spi_clear_outstanding_status(void)
454{
455 void *spibar = fast_spi_get_bar();
456
457 /* Make sure all W1C status bits get cleared. */
458 write32(spibar + SPIBAR_HSFSTS_CTL, SPIBAR_HSFSTS_W1C_BITS);
459}
Werner Zehbae84982022-05-05 11:04:04 +0200460
Werner Zeh53553e82022-05-05 11:55:30 +0200461
462/* As there is no official ACPI ID for this controller use the generic PNP ID for now. */
463static const char *fast_spi_acpi_hid(const struct device *dev)
464{
465 return "PNP0C02";
466}
467
468static const char *fast_spi_acpi_name(const struct device *dev)
469{
470 return "FSPI";
471}
472
473/*
474 * Generate an ACPI entry for the SPI controller. This way the allocated resources
475 * for the SPI controller can be communicated to the OS even if the device is
476 * not visible on PCI (because it is hidden) and therefore can not be probed by the OS.
477 */
478static void fast_spi_fill_ssdt(const struct device *dev)
479{
480 const char *scope = acpi_device_scope(dev);
481 const char *hid = fast_spi_acpi_hid(dev);
482 struct resource *res;
483
484 /* Do not add SSDT if the fast SPI device is hidden. */
485 if (dev->hidden || !CONFIG(FAST_SPI_GENERATE_SSDT))
486 return;
487 if (!scope || !hid)
488 return;
489
490 res = probe_resource(dev, PCI_BASE_ADDRESS_0);
491 if (!res)
492 return;
493
494 /* Scope */
495 acpigen_write_scope(scope);
496
497 /* Device */
498 acpigen_write_device(acpi_device_name(dev));
499 acpigen_write_name_string("_HID", hid);
500 acpi_device_write_uid(dev);
501 acpigen_write_name_string("_DDN", "ACPI Fast SPI");
502 acpigen_write_STA(acpi_device_status(dev));
503
504 /* Resources */
505 acpigen_write_name("_CRS");
506 acpigen_write_resourcetemplate_header();
507
508 /* Add BAR0 resource. */
509 acpigen_write_mem32fixed(1, res->base, res->size);
510
511 acpigen_write_resourcetemplate_footer();
512
513 acpigen_pop_len(); /* Device */
514 acpigen_pop_len(); /* Scope */
515}
516
Werner Zehbae84982022-05-05 11:04:04 +0200517static struct device_operations fast_spi_dev_ops = {
518 .read_resources = pci_dev_read_resources,
519 .set_resources = pci_dev_set_resources,
520 .enable_resources = pci_dev_enable_resources,
Werner Zeh53553e82022-05-05 11:55:30 +0200521 .acpi_fill_ssdt = fast_spi_fill_ssdt,
522 .acpi_name = fast_spi_acpi_name,
Werner Zehbae84982022-05-05 11:04:04 +0200523};
524
525static const unsigned short pci_device_ids[] = {
526 PCI_DID_INTEL_APL_HWSEQ_SPI,
527 0
528};
529
530static const struct pci_driver fast_spi __pci_driver = {
531 .ops = &fast_spi_dev_ops,
532 .vendor = PCI_VID_INTEL,
533 .devices = pci_device_ids,
534};