blob: 58e7db75a10d9515d552946b08cdc9bf80cea8c8 [file] [log] [blame]
Barnali Sarkar89331cd2017-02-16 17:22:37 +05301/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2017 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
Kyösti Mälkki13f66502019-03-03 08:01:05 +020016#include <device/mmio.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053017#include <assert.h>
18#include <device/pci_def.h>
Patrick Rudolphe56189c2018-04-18 10:11:59 +020019#include <device/pci_ops.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053020#include <commonlib/helpers.h>
Aaron Durbin5391e552017-06-02 12:16:04 -050021#include <cpu/x86/mtrr.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053022#include <fast_spi_def.h>
23#include <intelblocks/fast_spi.h>
Aaron Durbin5391e552017-06-02 12:16:04 -050024#include <lib.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053025#include <soc/pci_devs.h>
26#include <spi_flash.h>
27#include <spi-generic.h>
28#include <stdlib.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053029
30/*
31 * Get the FAST_SPIBAR.
32 */
33void *fast_spi_get_bar(void)
34{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +020035#if defined(__SIMPLE_DEVICE__)
36 pci_devfn_t dev = PCH_DEV_SPI;
37#else
38 struct device *dev = PCH_DEV_SPI;
39#endif
Barnali Sarkar89331cd2017-02-16 17:22:37 +053040 uintptr_t bar;
41
42 bar = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
43 assert(bar != 0);
44 /*
45 * Bits 31-12 are the base address as per EDS for SPI,
46 * Don't care about 0-11 bit
47 */
48 return (void *)(bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK);
49}
50
51/*
52 * Disable the BIOS write protect and Enable Prefetching and Caching.
53 */
54void fast_spi_init(void)
55{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +020056#if defined(__SIMPLE_DEVICE__)
57 pci_devfn_t dev = PCH_DEV_SPI;
58#else
59 struct device *dev = PCH_DEV_SPI;
60#endif
Barnali Sarkar89331cd2017-02-16 17:22:37 +053061 uint8_t bios_cntl;
62
63 bios_cntl = pci_read_config8(dev, SPIBAR_BIOS_CONTROL);
64
65 /* Disable the BIOS write protect so write commands are allowed. */
66 bios_cntl &= ~SPIBAR_BIOS_CONTROL_EISS;
67 bios_cntl |= SPIBAR_BIOS_CONTROL_WPD;
68 /* Enable Prefetching and caching. */
69 bios_cntl |= SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE;
70 bios_cntl &= ~SPIBAR_BIOS_CONTROL_CACHE_DISABLE;
71
72 pci_write_config8(dev, SPIBAR_BIOS_CONTROL, bios_cntl);
73}
74
75/*
Subrata Banik8e390092017-07-21 10:06:17 +053076 * Set FAST_SPIBAR BIOS Control register based on input bit field.
Barnali Sarkar89331cd2017-02-16 17:22:37 +053077 */
78static void fast_spi_set_bios_control_reg(uint8_t bios_cntl_bit)
79{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +020080#if defined(__SIMPLE_DEVICE__)
81 pci_devfn_t dev = PCH_DEV_SPI;
82#else
83 struct device *dev = PCH_DEV_SPI;
84#endif
Barnali Sarkar89331cd2017-02-16 17:22:37 +053085 uint8_t bc_cntl;
86
87 assert((bios_cntl_bit & (bios_cntl_bit - 1)) == 0);
88 bc_cntl = pci_read_config8(dev, SPIBAR_BIOS_CONTROL);
89 bc_cntl |= bios_cntl_bit;
90 pci_write_config8(dev, SPIBAR_BIOS_CONTROL, bc_cntl);
91}
92
93/*
Subrata Banik8e390092017-07-21 10:06:17 +053094 * Ensure an additional read back after performing lock down
95 */
96static void fast_spi_read_post_write(uint8_t reg)
97{
98 pci_read_config8(PCH_DEV_SPI, reg);
99}
100
101/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530102 * Set FAST_SPIBAR BIOS Control BILD bit.
103 */
104void fast_spi_set_bios_interface_lock_down(void)
105{
106 fast_spi_set_bios_control_reg(SPIBAR_BIOS_CONTROL_BILD);
Subrata Banik8e390092017-07-21 10:06:17 +0530107
108 fast_spi_read_post_write(SPIBAR_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530109}
110
111/*
112 * Set FAST_SPIBAR BIOS Control LE bit.
113 */
114void fast_spi_set_lock_enable(void)
115{
116 fast_spi_set_bios_control_reg(SPIBAR_BIOS_CONTROL_LOCK_ENABLE);
Subrata Banik8e390092017-07-21 10:06:17 +0530117
118
119 fast_spi_read_post_write(SPIBAR_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530120}
121
122/*
123 * Set FAST_SPIBAR BIOS Control EISS bit.
124 */
125void fast_spi_set_eiss(void)
126{
127 fast_spi_set_bios_control_reg(SPIBAR_BIOS_CONTROL_EISS);
Subrata Banik8e390092017-07-21 10:06:17 +0530128
129 fast_spi_read_post_write(SPIBAR_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530130}
131
132/*
133 * Set FAST_SPI opcode menu.
134 */
135void fast_spi_set_opcode_menu(void)
136{
137 void *spibar = fast_spi_get_bar();
138
139 write16(spibar + SPIBAR_PREOP, SPI_OPPREFIX);
140 write16(spibar + SPIBAR_OPTYPE, SPI_OPTYPE);
141 write32(spibar + SPIBAR_OPMENU_LOWER, SPI_OPMENU_LOWER);
142 write32(spibar + SPIBAR_OPMENU_UPPER, SPI_OPMENU_UPPER);
143}
144
145/*
146 * Lock FAST_SPIBAR.
Barnali Sarkar8e513192017-07-19 16:09:56 +0530147 * Use 16bit write to avoid touching two upper bytes what may cause the write
148 * cycle to fail in case a prior transaction has not completed.
149 * While WRSDIS is lockable with FLOCKDN, writing both in the same
150 * cycle is guaranteed to work by design.
151 *
152 * Avoid read->modify->write not to clear RW1C bits unintentionally.
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530153 */
154void fast_spi_lock_bar(void)
155{
156 void *spibar = fast_spi_get_bar();
Duncan Lauriedc1e6bc2017-08-15 13:32:26 -0700157 uint16_t hsfs = SPIBAR_HSFSTS_FLOCKDN;
158
Julius Wernercd49cce2019-03-05 16:53:33 -0800159 if (CONFIG(FAST_SPI_DISABLE_WRITE_STATUS))
Duncan Lauriedc1e6bc2017-08-15 13:32:26 -0700160 hsfs |= SPIBAR_HSFSTS_WRSDIS;
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530161
Barnali Sarkar8e513192017-07-19 16:09:56 +0530162 write16(spibar + SPIBAR_HSFSTS_CTL, hsfs);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530163}
164
165/*
Barnali Sarkar4f6e3412017-08-17 11:49:27 +0530166 * Set FAST_SPIBAR + DLOCK (0x0C) register bits to discrete lock the
167 * FAST_SPI Protected Range (PR) registers.
168 */
169void fast_spi_pr_dlock(void)
170{
171 void *spibar = fast_spi_get_bar();
172 uint32_t dlock;
173
174 dlock = read32(spibar + SPIBAR_DLOCK);
175 dlock |= (SPIBAR_DLOCK_PR0LOCKDN | SPIBAR_DLOCK_PR1LOCKDN
176 | SPIBAR_DLOCK_PR2LOCKDN | SPIBAR_DLOCK_PR3LOCKDN
177 | SPIBAR_DLOCK_PR4LOCKDN);
178
179 write32(spibar + SPIBAR_DLOCK, dlock);
180}
181
182/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530183 * Set FAST_SPIBAR Soft Reset Data Register value.
184 */
185void fast_spi_set_strap_msg_data(uint32_t soft_reset_data)
186{
187 void *spibar = fast_spi_get_bar();
188 uint32_t ssl, ssms;
189
190 /* Set Strap Lock Disable */
191 ssl = read32(spibar + SPIBAR_RESET_LOCK);
192 ssl &= ~SPIBAR_RESET_LOCK_ENABLE;
193 write32(spibar + SPIBAR_RESET_LOCK, ssl);
194
195 /* Write Soft Reset Data register at SPIBAR0 offset 0xF8[0:15] */
196 write32(spibar + SPIBAR_RESET_DATA, soft_reset_data);
197
198 /* Set Strap Mux Select set to '1' */
199 ssms = read32(spibar + SPIBAR_RESET_CTRL);
200 ssms |= SPIBAR_RESET_CTRL_SSMC;
201 write32(spibar + SPIBAR_RESET_CTRL, ssms);
202
203 /* Set Strap Lock Enable */
204 ssl = read32(spibar + SPIBAR_RESET_LOCK);
205 ssl |= SPIBAR_RESET_LOCK_ENABLE;
206 write32(spibar + SPIBAR_RESET_LOCK, ssl);
207}
208
209/*
210 * Returns bios_start and fills in size of the BIOS region.
211 */
212size_t fast_spi_get_bios_region(size_t *bios_size)
213{
214 size_t bios_start, bios_end;
215 /*
216 * BIOS_BFPREG provides info about BIOS Flash Primary Region
217 * Base and Limit.
218 * Base and Limit fields are in units of 4KiB.
219 */
220 uint32_t val = read32(fast_spi_get_bar() + SPIBAR_BFPREG);
221
222 bios_start = (val & SPIBAR_BFPREG_PRB_MASK) * 4 * KiB;
223 bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >>
224 SPIBAR_BFPREG_PRL_SHIFT) + 1) * 4 * KiB;
225 *bios_size = bios_end - bios_start;
226 return bios_start;
227}
228
Aaron Durbin5391e552017-06-02 12:16:04 -0500229void fast_spi_cache_bios_region(void)
230{
Aaron Durbin5391e552017-06-02 12:16:04 -0500231 size_t bios_size;
232 uint32_t alignment;
Aaron Durbin0b34fc62017-06-08 10:52:58 -0500233 const int type = MTRR_TYPE_WRPROT;
234 uintptr_t base;
Aaron Durbin5391e552017-06-02 12:16:04 -0500235
236 /* Only the IFD BIOS region is memory mapped (at top of 4G) */
237 fast_spi_get_bios_region(&bios_size);
238
Lijian Zhaoad1e49a2018-11-29 16:24:24 -0800239 /* LOCAL APIC default address is 0xFEE0000, bios_size over 16MB will
240 * cause memory type conflict when setting memory type to write
241 * protection, so limit the cached bios region to be no more than 16MB.
242 * */
243 bios_size = MIN(bios_size, 16 * MiB);
John Zhao2bb432e2019-05-21 19:32:51 -0700244 if (!bios_size)
245 return;
Lijian Zhaoad1e49a2018-11-29 16:24:24 -0800246
Aaron Durbin5391e552017-06-02 12:16:04 -0500247 /* Round to power of two */
Paul Menzel64e83402017-10-27 11:05:14 +0200248 alignment = 1UL << (log2_ceil(bios_size));
Aaron Durbin5391e552017-06-02 12:16:04 -0500249 bios_size = ALIGN_UP(bios_size, alignment);
Aaron Durbin0b34fc62017-06-08 10:52:58 -0500250 base = 4ULL*GiB - bios_size;
251
252 if (ENV_RAMSTAGE) {
253 mtrr_use_temp_range(base, bios_size, type);
254 } else {
255 int mtrr = get_free_var_mtrr();
256
257 if (mtrr == -1)
258 return;
259
260 set_var_mtrr(mtrr, base, bios_size, type);
261 }
Aaron Durbin5391e552017-06-02 12:16:04 -0500262}
263
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530264/*
265 * Program temporary BAR for SPI in case any of the stages before ramstage need
266 * to access FAST_SPI MMIO regs. Ramstage will assign a new BAR during PCI
267 * enumeration.
268 */
269void fast_spi_early_init(uintptr_t spi_base_address)
270{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +0200271#if defined(__SIMPLE_DEVICE__)
272 pci_devfn_t dev = PCH_DEV_SPI;
273#else
274 struct device *dev = PCH_DEV_SPI;
275#endif
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530276 uint8_t pcireg;
277
278 /* Assign Resources to SPI Controller */
279 /* Clear BIT 1-2 SPI Command Register */
280 pcireg = pci_read_config8(dev, PCI_COMMAND);
281 pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
282 pci_write_config8(dev, PCI_COMMAND, pcireg);
283
284 /* Program Temporary BAR for SPI */
285 pci_write_config32(dev, PCI_BASE_ADDRESS_0,
286 spi_base_address | PCI_BASE_ADDRESS_SPACE_MEMORY);
287
288 /* Enable Bus Master and MMIO Space */
289 pcireg = pci_read_config8(dev, PCI_COMMAND);
290 pcireg |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
291 pci_write_config8(dev, PCI_COMMAND, pcireg);
292
293 /* Initialize SPI to allow BIOS to write/erase on flash. */
294 fast_spi_init();
295}
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700296
297/* Read SPI Write Protect disable status. */
298bool fast_spi_wpd_status(void)
299{
300 return pci_read_config16(PCH_DEV_SPI, SPIBAR_BIOS_CONTROL) &
301 SPIBAR_BIOS_CONTROL_WPD;
302}
303
304/* Enable SPI Write Protect. */
305void fast_spi_enable_wp(void)
306{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +0200307#if defined(__SIMPLE_DEVICE__)
308 pci_devfn_t dev = PCH_DEV_SPI;
309#else
310 struct device *dev = PCH_DEV_SPI;
311#endif
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700312 uint8_t bios_cntl;
313
314 bios_cntl = pci_read_config8(dev, SPIBAR_BIOS_CONTROL);
315 bios_cntl &= ~SPIBAR_BIOS_CONTROL_WPD;
316 pci_write_config8(dev, SPIBAR_BIOS_CONTROL, bios_cntl);
317}