blob: e7f81fc32345153e142053d901001b4e3e74a1cb [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
16#include <arch/io.h>
17#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>
21#include <console/console.h>
Aaron Durbin5391e552017-06-02 12:16:04 -050022#include <cpu/x86/mtrr.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053023#include <fast_spi_def.h>
24#include <intelblocks/fast_spi.h>
Aaron Durbin5391e552017-06-02 12:16:04 -050025#include <lib.h>
Barnali Sarkar89331cd2017-02-16 17:22:37 +053026#include <soc/pci_devs.h>
27#include <spi_flash.h>
28#include <spi-generic.h>
29#include <stdlib.h>
30#include <string.h>
31
32/*
33 * Get the FAST_SPIBAR.
34 */
35void *fast_spi_get_bar(void)
36{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +020037#if defined(__SIMPLE_DEVICE__)
38 pci_devfn_t dev = PCH_DEV_SPI;
39#else
40 struct device *dev = PCH_DEV_SPI;
41#endif
Barnali Sarkar89331cd2017-02-16 17:22:37 +053042 uintptr_t bar;
43
44 bar = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
45 assert(bar != 0);
46 /*
47 * Bits 31-12 are the base address as per EDS for SPI,
48 * Don't care about 0-11 bit
49 */
50 return (void *)(bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK);
51}
52
53/*
54 * Disable the BIOS write protect and Enable Prefetching and Caching.
55 */
56void fast_spi_init(void)
57{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +020058#if defined(__SIMPLE_DEVICE__)
59 pci_devfn_t dev = PCH_DEV_SPI;
60#else
61 struct device *dev = PCH_DEV_SPI;
62#endif
Barnali Sarkar89331cd2017-02-16 17:22:37 +053063 uint8_t bios_cntl;
64
65 bios_cntl = pci_read_config8(dev, SPIBAR_BIOS_CONTROL);
66
67 /* Disable the BIOS write protect so write commands are allowed. */
68 bios_cntl &= ~SPIBAR_BIOS_CONTROL_EISS;
69 bios_cntl |= SPIBAR_BIOS_CONTROL_WPD;
70 /* Enable Prefetching and caching. */
71 bios_cntl |= SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE;
72 bios_cntl &= ~SPIBAR_BIOS_CONTROL_CACHE_DISABLE;
73
74 pci_write_config8(dev, SPIBAR_BIOS_CONTROL, bios_cntl);
75}
76
77/*
Subrata Banik8e390092017-07-21 10:06:17 +053078 * Set FAST_SPIBAR BIOS Control register based on input bit field.
Barnali Sarkar89331cd2017-02-16 17:22:37 +053079 */
80static void fast_spi_set_bios_control_reg(uint8_t bios_cntl_bit)
81{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +020082#if defined(__SIMPLE_DEVICE__)
83 pci_devfn_t dev = PCH_DEV_SPI;
84#else
85 struct device *dev = PCH_DEV_SPI;
86#endif
Barnali Sarkar89331cd2017-02-16 17:22:37 +053087 uint8_t bc_cntl;
88
89 assert((bios_cntl_bit & (bios_cntl_bit - 1)) == 0);
90 bc_cntl = pci_read_config8(dev, SPIBAR_BIOS_CONTROL);
91 bc_cntl |= bios_cntl_bit;
92 pci_write_config8(dev, SPIBAR_BIOS_CONTROL, bc_cntl);
93}
94
95/*
Subrata Banik8e390092017-07-21 10:06:17 +053096 * Ensure an additional read back after performing lock down
97 */
98static void fast_spi_read_post_write(uint8_t reg)
99{
100 pci_read_config8(PCH_DEV_SPI, reg);
101}
102
103/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530104 * Set FAST_SPIBAR BIOS Control BILD bit.
105 */
106void fast_spi_set_bios_interface_lock_down(void)
107{
108 fast_spi_set_bios_control_reg(SPIBAR_BIOS_CONTROL_BILD);
Subrata Banik8e390092017-07-21 10:06:17 +0530109
110 fast_spi_read_post_write(SPIBAR_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530111}
112
113/*
114 * Set FAST_SPIBAR BIOS Control LE bit.
115 */
116void fast_spi_set_lock_enable(void)
117{
118 fast_spi_set_bios_control_reg(SPIBAR_BIOS_CONTROL_LOCK_ENABLE);
Subrata Banik8e390092017-07-21 10:06:17 +0530119
120
121 fast_spi_read_post_write(SPIBAR_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530122}
123
124/*
125 * Set FAST_SPIBAR BIOS Control EISS bit.
126 */
127void fast_spi_set_eiss(void)
128{
129 fast_spi_set_bios_control_reg(SPIBAR_BIOS_CONTROL_EISS);
Subrata Banik8e390092017-07-21 10:06:17 +0530130
131 fast_spi_read_post_write(SPIBAR_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530132}
133
134/*
135 * Set FAST_SPI opcode menu.
136 */
137void fast_spi_set_opcode_menu(void)
138{
139 void *spibar = fast_spi_get_bar();
140
141 write16(spibar + SPIBAR_PREOP, SPI_OPPREFIX);
142 write16(spibar + SPIBAR_OPTYPE, SPI_OPTYPE);
143 write32(spibar + SPIBAR_OPMENU_LOWER, SPI_OPMENU_LOWER);
144 write32(spibar + SPIBAR_OPMENU_UPPER, SPI_OPMENU_UPPER);
145}
146
147/*
148 * Lock FAST_SPIBAR.
Barnali Sarkar8e513192017-07-19 16:09:56 +0530149 * Use 16bit write to avoid touching two upper bytes what may cause the write
150 * cycle to fail in case a prior transaction has not completed.
151 * While WRSDIS is lockable with FLOCKDN, writing both in the same
152 * cycle is guaranteed to work by design.
153 *
154 * Avoid read->modify->write not to clear RW1C bits unintentionally.
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530155 */
156void fast_spi_lock_bar(void)
157{
158 void *spibar = fast_spi_get_bar();
Duncan Lauriedc1e6bc2017-08-15 13:32:26 -0700159 uint16_t hsfs = SPIBAR_HSFSTS_FLOCKDN;
160
161 if (IS_ENABLED(CONFIG_FAST_SPI_DISABLE_WRITE_STATUS))
162 hsfs |= SPIBAR_HSFSTS_WRSDIS;
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530163
Barnali Sarkar8e513192017-07-19 16:09:56 +0530164 write16(spibar + SPIBAR_HSFSTS_CTL, hsfs);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530165}
166
167/*
Barnali Sarkar4f6e3412017-08-17 11:49:27 +0530168 * Set FAST_SPIBAR + DLOCK (0x0C) register bits to discrete lock the
169 * FAST_SPI Protected Range (PR) registers.
170 */
171void fast_spi_pr_dlock(void)
172{
173 void *spibar = fast_spi_get_bar();
174 uint32_t dlock;
175
176 dlock = read32(spibar + SPIBAR_DLOCK);
177 dlock |= (SPIBAR_DLOCK_PR0LOCKDN | SPIBAR_DLOCK_PR1LOCKDN
178 | SPIBAR_DLOCK_PR2LOCKDN | SPIBAR_DLOCK_PR3LOCKDN
179 | SPIBAR_DLOCK_PR4LOCKDN);
180
181 write32(spibar + SPIBAR_DLOCK, dlock);
182}
183
184/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530185 * Set FAST_SPIBAR Soft Reset Data Register value.
186 */
187void fast_spi_set_strap_msg_data(uint32_t soft_reset_data)
188{
189 void *spibar = fast_spi_get_bar();
190 uint32_t ssl, ssms;
191
192 /* Set Strap Lock Disable */
193 ssl = read32(spibar + SPIBAR_RESET_LOCK);
194 ssl &= ~SPIBAR_RESET_LOCK_ENABLE;
195 write32(spibar + SPIBAR_RESET_LOCK, ssl);
196
197 /* Write Soft Reset Data register at SPIBAR0 offset 0xF8[0:15] */
198 write32(spibar + SPIBAR_RESET_DATA, soft_reset_data);
199
200 /* Set Strap Mux Select set to '1' */
201 ssms = read32(spibar + SPIBAR_RESET_CTRL);
202 ssms |= SPIBAR_RESET_CTRL_SSMC;
203 write32(spibar + SPIBAR_RESET_CTRL, ssms);
204
205 /* Set Strap Lock Enable */
206 ssl = read32(spibar + SPIBAR_RESET_LOCK);
207 ssl |= SPIBAR_RESET_LOCK_ENABLE;
208 write32(spibar + SPIBAR_RESET_LOCK, ssl);
209}
210
211/*
212 * Returns bios_start and fills in size of the BIOS region.
213 */
214size_t fast_spi_get_bios_region(size_t *bios_size)
215{
216 size_t bios_start, bios_end;
217 /*
218 * BIOS_BFPREG provides info about BIOS Flash Primary Region
219 * Base and Limit.
220 * Base and Limit fields are in units of 4KiB.
221 */
222 uint32_t val = read32(fast_spi_get_bar() + SPIBAR_BFPREG);
223
224 bios_start = (val & SPIBAR_BFPREG_PRB_MASK) * 4 * KiB;
225 bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >>
226 SPIBAR_BFPREG_PRL_SHIFT) + 1) * 4 * KiB;
227 *bios_size = bios_end - bios_start;
228 return bios_start;
229}
230
Aaron Durbin5391e552017-06-02 12:16:04 -0500231void fast_spi_cache_bios_region(void)
232{
Aaron Durbin5391e552017-06-02 12:16:04 -0500233 size_t bios_size;
234 uint32_t alignment;
Aaron Durbin0b34fc62017-06-08 10:52:58 -0500235 const int type = MTRR_TYPE_WRPROT;
236 uintptr_t base;
Aaron Durbin5391e552017-06-02 12:16:04 -0500237
238 /* Only the IFD BIOS region is memory mapped (at top of 4G) */
239 fast_spi_get_bios_region(&bios_size);
240
241 if (!bios_size)
242 return;
243
244 /* Round to power of two */
Paul Menzel64e83402017-10-27 11:05:14 +0200245 alignment = 1UL << (log2_ceil(bios_size));
Aaron Durbin5391e552017-06-02 12:16:04 -0500246 bios_size = ALIGN_UP(bios_size, alignment);
Aaron Durbin0b34fc62017-06-08 10:52:58 -0500247 base = 4ULL*GiB - bios_size;
248
249 if (ENV_RAMSTAGE) {
250 mtrr_use_temp_range(base, bios_size, type);
251 } else {
252 int mtrr = get_free_var_mtrr();
253
254 if (mtrr == -1)
255 return;
256
257 set_var_mtrr(mtrr, base, bios_size, type);
258 }
Aaron Durbin5391e552017-06-02 12:16:04 -0500259}
260
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530261/*
262 * Program temporary BAR for SPI in case any of the stages before ramstage need
263 * to access FAST_SPI MMIO regs. Ramstage will assign a new BAR during PCI
264 * enumeration.
265 */
266void fast_spi_early_init(uintptr_t spi_base_address)
267{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +0200268#if defined(__SIMPLE_DEVICE__)
269 pci_devfn_t dev = PCH_DEV_SPI;
270#else
271 struct device *dev = PCH_DEV_SPI;
272#endif
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530273 uint8_t pcireg;
274
275 /* Assign Resources to SPI Controller */
276 /* Clear BIT 1-2 SPI Command Register */
277 pcireg = pci_read_config8(dev, PCI_COMMAND);
278 pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
279 pci_write_config8(dev, PCI_COMMAND, pcireg);
280
281 /* Program Temporary BAR for SPI */
282 pci_write_config32(dev, PCI_BASE_ADDRESS_0,
283 spi_base_address | PCI_BASE_ADDRESS_SPACE_MEMORY);
284
285 /* Enable Bus Master and MMIO Space */
286 pcireg = pci_read_config8(dev, PCI_COMMAND);
287 pcireg |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
288 pci_write_config8(dev, PCI_COMMAND, pcireg);
289
290 /* Initialize SPI to allow BIOS to write/erase on flash. */
291 fast_spi_init();
292}
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700293
294/* Read SPI Write Protect disable status. */
295bool fast_spi_wpd_status(void)
296{
297 return pci_read_config16(PCH_DEV_SPI, SPIBAR_BIOS_CONTROL) &
298 SPIBAR_BIOS_CONTROL_WPD;
299}
300
301/* Enable SPI Write Protect. */
302void fast_spi_enable_wp(void)
303{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +0200304#if defined(__SIMPLE_DEVICE__)
305 pci_devfn_t dev = PCH_DEV_SPI;
306#else
307 struct device *dev = PCH_DEV_SPI;
308#endif
Ravi Sarawadib051a9f52017-09-07 12:15:45 -0700309 uint8_t bios_cntl;
310
311 bios_cntl = pci_read_config8(dev, SPIBAR_BIOS_CONTROL);
312 bios_cntl &= ~SPIBAR_BIOS_CONTROL_WPD;
313 pci_write_config8(dev, SPIBAR_BIOS_CONTROL, bios_cntl);
314}