blob: f7ef68561fea2d921178c2cea8aa33d069d30491 [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>
19#include <commonlib/helpers.h>
20#include <console/console.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/intel/common/spi_flash.h>
26#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{
37 device_t dev = PCH_DEV_SPI;
38 uintptr_t bar;
39
40 bar = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
41 assert(bar != 0);
42 /*
43 * Bits 31-12 are the base address as per EDS for SPI,
44 * Don't care about 0-11 bit
45 */
46 return (void *)(bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK);
47}
48
49/*
50 * Disable the BIOS write protect and Enable Prefetching and Caching.
51 */
52void fast_spi_init(void)
53{
54 device_t dev = PCH_DEV_SPI;
55 uint8_t bios_cntl;
56
57 bios_cntl = pci_read_config8(dev, SPIBAR_BIOS_CONTROL);
58
59 /* Disable the BIOS write protect so write commands are allowed. */
60 bios_cntl &= ~SPIBAR_BIOS_CONTROL_EISS;
61 bios_cntl |= SPIBAR_BIOS_CONTROL_WPD;
62 /* Enable Prefetching and caching. */
63 bios_cntl |= SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE;
64 bios_cntl &= ~SPIBAR_BIOS_CONTROL_CACHE_DISABLE;
65
66 pci_write_config8(dev, SPIBAR_BIOS_CONTROL, bios_cntl);
67}
68
69/*
Subrata Banik8e390092017-07-21 10:06:17 +053070 * Set FAST_SPIBAR BIOS Control register based on input bit field.
Barnali Sarkar89331cd2017-02-16 17:22:37 +053071 */
72static void fast_spi_set_bios_control_reg(uint8_t bios_cntl_bit)
73{
74 device_t dev = PCH_DEV_SPI;
75 uint8_t bc_cntl;
76
77 assert((bios_cntl_bit & (bios_cntl_bit - 1)) == 0);
78 bc_cntl = pci_read_config8(dev, SPIBAR_BIOS_CONTROL);
79 bc_cntl |= bios_cntl_bit;
80 pci_write_config8(dev, SPIBAR_BIOS_CONTROL, bc_cntl);
81}
82
83/*
Subrata Banik8e390092017-07-21 10:06:17 +053084 * Ensure an additional read back after performing lock down
85 */
86static void fast_spi_read_post_write(uint8_t reg)
87{
88 pci_read_config8(PCH_DEV_SPI, reg);
89}
90
91/*
Barnali Sarkar89331cd2017-02-16 17:22:37 +053092 * Set FAST_SPIBAR BIOS Control BILD bit.
93 */
94void fast_spi_set_bios_interface_lock_down(void)
95{
96 fast_spi_set_bios_control_reg(SPIBAR_BIOS_CONTROL_BILD);
Subrata Banik8e390092017-07-21 10:06:17 +053097
98 fast_spi_read_post_write(SPIBAR_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +053099}
100
101/*
102 * Set FAST_SPIBAR BIOS Control LE bit.
103 */
104void fast_spi_set_lock_enable(void)
105{
106 fast_spi_set_bios_control_reg(SPIBAR_BIOS_CONTROL_LOCK_ENABLE);
Subrata Banik8e390092017-07-21 10:06:17 +0530107
108
109 fast_spi_read_post_write(SPIBAR_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530110}
111
112/*
113 * Set FAST_SPIBAR BIOS Control EISS bit.
114 */
115void fast_spi_set_eiss(void)
116{
117 fast_spi_set_bios_control_reg(SPIBAR_BIOS_CONTROL_EISS);
Subrata Banik8e390092017-07-21 10:06:17 +0530118
119 fast_spi_read_post_write(SPIBAR_BIOS_CONTROL);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530120}
121
122/*
123 * Set FAST_SPI opcode menu.
124 */
125void fast_spi_set_opcode_menu(void)
126{
127 void *spibar = fast_spi_get_bar();
128
129 write16(spibar + SPIBAR_PREOP, SPI_OPPREFIX);
130 write16(spibar + SPIBAR_OPTYPE, SPI_OPTYPE);
131 write32(spibar + SPIBAR_OPMENU_LOWER, SPI_OPMENU_LOWER);
132 write32(spibar + SPIBAR_OPMENU_UPPER, SPI_OPMENU_UPPER);
133}
134
135/*
136 * Lock FAST_SPIBAR.
Barnali Sarkar8e513192017-07-19 16:09:56 +0530137 * Use 16bit write to avoid touching two upper bytes what may cause the write
138 * cycle to fail in case a prior transaction has not completed.
139 * While WRSDIS is lockable with FLOCKDN, writing both in the same
140 * cycle is guaranteed to work by design.
141 *
142 * Avoid read->modify->write not to clear RW1C bits unintentionally.
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530143 */
144void fast_spi_lock_bar(void)
145{
146 void *spibar = fast_spi_get_bar();
Duncan Lauriedc1e6bc2017-08-15 13:32:26 -0700147 uint16_t hsfs = SPIBAR_HSFSTS_FLOCKDN;
148
149 if (IS_ENABLED(CONFIG_FAST_SPI_DISABLE_WRITE_STATUS))
150 hsfs |= SPIBAR_HSFSTS_WRSDIS;
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530151
Barnali Sarkar8e513192017-07-19 16:09:56 +0530152 write16(spibar + SPIBAR_HSFSTS_CTL, hsfs);
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530153}
154
155/*
156 * Set FAST_SPIBAR Soft Reset Data Register value.
157 */
158void fast_spi_set_strap_msg_data(uint32_t soft_reset_data)
159{
160 void *spibar = fast_spi_get_bar();
161 uint32_t ssl, ssms;
162
163 /* Set Strap Lock Disable */
164 ssl = read32(spibar + SPIBAR_RESET_LOCK);
165 ssl &= ~SPIBAR_RESET_LOCK_ENABLE;
166 write32(spibar + SPIBAR_RESET_LOCK, ssl);
167
168 /* Write Soft Reset Data register at SPIBAR0 offset 0xF8[0:15] */
169 write32(spibar + SPIBAR_RESET_DATA, soft_reset_data);
170
171 /* Set Strap Mux Select set to '1' */
172 ssms = read32(spibar + SPIBAR_RESET_CTRL);
173 ssms |= SPIBAR_RESET_CTRL_SSMC;
174 write32(spibar + SPIBAR_RESET_CTRL, ssms);
175
176 /* Set Strap Lock Enable */
177 ssl = read32(spibar + SPIBAR_RESET_LOCK);
178 ssl |= SPIBAR_RESET_LOCK_ENABLE;
179 write32(spibar + SPIBAR_RESET_LOCK, ssl);
180}
181
182/*
183 * Returns bios_start and fills in size of the BIOS region.
184 */
185size_t fast_spi_get_bios_region(size_t *bios_size)
186{
187 size_t bios_start, bios_end;
188 /*
189 * BIOS_BFPREG provides info about BIOS Flash Primary Region
190 * Base and Limit.
191 * Base and Limit fields are in units of 4KiB.
192 */
193 uint32_t val = read32(fast_spi_get_bar() + SPIBAR_BFPREG);
194
195 bios_start = (val & SPIBAR_BFPREG_PRB_MASK) * 4 * KiB;
196 bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >>
197 SPIBAR_BFPREG_PRL_SHIFT) + 1) * 4 * KiB;
198 *bios_size = bios_end - bios_start;
199 return bios_start;
200}
201
Aaron Durbin5391e552017-06-02 12:16:04 -0500202void fast_spi_cache_bios_region(void)
203{
Aaron Durbin5391e552017-06-02 12:16:04 -0500204 size_t bios_size;
205 uint32_t alignment;
Aaron Durbin0b34fc62017-06-08 10:52:58 -0500206 const int type = MTRR_TYPE_WRPROT;
207 uintptr_t base;
Aaron Durbin5391e552017-06-02 12:16:04 -0500208
209 /* Only the IFD BIOS region is memory mapped (at top of 4G) */
210 fast_spi_get_bios_region(&bios_size);
211
212 if (!bios_size)
213 return;
214
215 /* Round to power of two */
216 alignment = 1 << (log2_ceil(bios_size));
217 bios_size = ALIGN_UP(bios_size, alignment);
Aaron Durbin0b34fc62017-06-08 10:52:58 -0500218 base = 4ULL*GiB - bios_size;
219
220 if (ENV_RAMSTAGE) {
221 mtrr_use_temp_range(base, bios_size, type);
222 } else {
223 int mtrr = get_free_var_mtrr();
224
225 if (mtrr == -1)
226 return;
227
228 set_var_mtrr(mtrr, base, bios_size, type);
229 }
Aaron Durbin5391e552017-06-02 12:16:04 -0500230}
231
Barnali Sarkar89331cd2017-02-16 17:22:37 +0530232/*
233 * Program temporary BAR for SPI in case any of the stages before ramstage need
234 * to access FAST_SPI MMIO regs. Ramstage will assign a new BAR during PCI
235 * enumeration.
236 */
237void fast_spi_early_init(uintptr_t spi_base_address)
238{
239 device_t dev = PCH_DEV_SPI;
240 uint8_t pcireg;
241
242 /* Assign Resources to SPI Controller */
243 /* Clear BIT 1-2 SPI Command Register */
244 pcireg = pci_read_config8(dev, PCI_COMMAND);
245 pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
246 pci_write_config8(dev, PCI_COMMAND, pcireg);
247
248 /* Program Temporary BAR for SPI */
249 pci_write_config32(dev, PCI_BASE_ADDRESS_0,
250 spi_base_address | PCI_BASE_ADDRESS_SPACE_MEMORY);
251
252 /* Enable Bus Master and MMIO Space */
253 pcireg = pci_read_config8(dev, PCI_COMMAND);
254 pcireg |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
255 pci_write_config8(dev, PCI_COMMAND, pcireg);
256
257 /* Initialize SPI to allow BIOS to write/erase on flash. */
258 fast_spi_init();
259}