blob: b0c8f4265a4c7f3701f5ea73ebe6b9c7f483f582 [file] [log] [blame]
Angel Pons230e4f9d2020-04-05 15:47:14 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Lee Leahyd9351092017-05-24 13:23:26 -07003
Kyösti Mälkki13f66502019-03-03 08:01:05 +02004#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02005#include <device/pci_ops.h>
Lee Leahyd9351092017-05-24 13:23:26 -07006#include <bootstate.h>
7#include <console/console.h>
8#include <device/pci_ids.h>
9#include <device/pci_def.h>
10#include <delay.h>
11#include <soc/pci_devs.h>
12#include <soc/QuarkNcSocId.h>
13#include <soc/spi.h>
Elyes HAOUASa1e22b82019-03-18 22:49:36 +010014#include <string.h>
Lee Leahyd9351092017-05-24 13:23:26 -070015
16struct spi_context spi_driver_context = {
17 NULL,
18 0,
19 0
20};
21
22void spi_bios_base(uint32_t bios_base_address)
23{
24 uint32_t address;
25 volatile struct flash_ctrlr *ctrlr = spi_driver_context.ctrlr;
26
27 /* Prevent all SPI operations below this address */
28 address = 0xff000000 | bios_base_address;
29 ctrlr->bbar = address;
30}
31
32void spi_controller_lock(void)
33{
34 volatile struct flash_ctrlr *ctrlr = spi_driver_context.ctrlr;
35
36 /* Prevent BIOS and system from changing the SPI controller setup */
37 ctrlr->status |= SPISTS_CLD;
38}
39
40int spi_protection(uint32_t address, uint32_t length)
41{
42 uint32_t base;
43 volatile struct flash_ctrlr *ctrlr = spi_driver_context.ctrlr;
44 int index;
45 uint32_t limit;
46 uint32_t protect;
47 uint32_t value;
48
49 /* Determine the protection range */
50 base = address;
51 limit = address + length - 1;
52 protect = SPIPBR_WPE | (limit & SPIPBR_PRL)
53 | ((base >> SPIPBR_PRB_SHIFT) & SPIPBR_PRB);
54
55 /* Walk the list of protected areas */
56 for (index = 0; index < ARRAY_SIZE(ctrlr->pbr); index++) {
57 value = read32(&ctrlr->pbr[index]);
58
59 /* Don't duplicate if the range is already protected */
60 if (value == protect)
61 return 0;
62
63 /* Use the first free register to protect this range */
64 if ((value & SPIPBR_WPE) == 0) {
65 write32(&ctrlr->pbr[index], protect);
66 return 0;
67 }
68 }
69
70 /* No free protection range registers */
71 printk(BIOS_ERR,
72 "Failed to set protection: 0x%08x - 0x%08x, PRRs full!\n",
73 address, address + length - 1);
74 return -1;
75}
76
77static int xfer(const struct spi_slave *slave, const void *dout,
78 size_t bytesout, void *din, size_t bytesin)
79{
80 struct spi_context *context;
81 uint16_t control;
82 volatile struct flash_ctrlr *ctrlr;
83 uint8_t *data;
84 int index;
85 uint8_t opcode;
86 uint32_t status;
87 int type;
88
89 /* Locate the context structure */
90 context = &spi_driver_context;
91 ctrlr = context->ctrlr;
92
93 /* Validate the buffer sizes */
94 if (bytesin > sizeof(ctrlr->data)) {
Paul Menzel11015342017-10-21 10:10:27 +020095 printk(BIOS_ERR, "bytesin > %zu\n", sizeof(ctrlr->data));
Lee Leahyd9351092017-05-24 13:23:26 -070096 goto error;
97 }
98
99 if (bytesin && (din == NULL)) {
100 printk(BIOS_ERR, "din is NULL\n");
101 goto error;
102 }
103
104 if (bytesout == 0) {
105 /* Check for a read operation */
106 if (bytesin == 0) {
107 printk(BIOS_ERR, "bytesout and bytesin == 0\n");
108 goto error;
109 }
110
111 /* Issue the read operation */
112 control = context->control;
113 control |= SPICTL_DC | ((bytesin - 1) << SPICTL_DBCNT_SHIFT);
114 goto start_cycle;
115 }
116
117 /* Locate the opcode in the opcode table */
118 data = (uint8_t *)dout;
119 opcode = *data++;
120 bytesout -= 1;
121 for (index = 0; index < sizeof(ctrlr->opmenu); index++)
122 if (opcode == ctrlr->opmenu[index])
123 break;
124
125 /* Check for a prefix byte */
126 if (index == sizeof(ctrlr->opmenu)) {
127 for (index = 0; index < sizeof(ctrlr->prefix); index++)
128 if (opcode == ctrlr->prefix[index])
129 break;
130
131 /* Handle the unknown opcode error */
132 if (index == sizeof(ctrlr->prefix)) {
133 printk(BIOS_ERR, "Unknown SPI flash opcode\n");
134 goto error;
135 }
136
137 /* Save the index for the next operation */
138 context->prefix = index;
139 return 0;
140 }
141
142 /* Get the opcode type */
143 type = (ctrlr->type >> (index * 2))
144 & (SPITYPE_ADDRESS | SPITYPE_PREFIX);
145
146 /* Determine if the opcode has an address */
147 if (type & SPITYPE_ADDRESS) {
148 if (bytesout < 3) {
149 printk(BIOS_ERR, "Missing address bytes\n");
150 goto error;
151 }
152
153 /* Use chip select 0 */
154 ctrlr->address = (data[0] << 16)
155 | (data[1] << 8)
156 | data[2];
Martin Kepplingerd9d351d2017-06-30 14:12:33 +0200157
158 /* read in order to flush the write buffer */
Lee Leahyd9351092017-05-24 13:23:26 -0700159 status = ctrlr->address;
Martin Kepplingerd9d351d2017-06-30 14:12:33 +0200160
Lee Leahyd9351092017-05-24 13:23:26 -0700161 data += 3;
162 bytesout -= 3;
163 }
164
165 /* Build the control value */
166 control = (index << SPICTL_COPTR_SHIFT)
167 | (context->prefix << SPICTL_SOPTR_SHIFT)
168 | SPICTL_CG | SPICTL_AR;
169 if (bytesout) {
170 memcpy((void *)&ctrlr->data[0], data, bytesout);
171 control |= SPICTL_DC | ((bytesout - 1) << SPICTL_DBCNT_SHIFT);
172 }
173
174 /* Save the control value for the read operation request */
175 if (!(type & SPITYPE_PREFIX)) {
176 context->control = control;
177 return 0;
178 }
179
180 /* Write operations require a prefix */
181 control |= SPICTL_ACS;
182
183start_cycle:
184 /* Start the SPI cycle */
185 ctrlr->control = control;
186 status = ctrlr->control;
187 context->prefix = 0;
188
189 /* Wait for the access to complete */
190 while ((status = ctrlr->status) & SPISTS_CIP)
191 udelay(1);
192
193 /* Clear any errors */
194 ctrlr->status = status;
195
196 /* Handle the blocked access error */
197 if (status & SPISTS_BA) {
198 printk(BIOS_ERR, "SPI access blocked!\n");
199 return -1;
200 }
201
202 /* Check for done */
203 if (status & SPISTS_CD) {
204 /* Return any receive data */
205 if (bytesin)
206 memcpy(din, (void *)&ctrlr->data[0], bytesin);
207 return 0;
208 }
209
210 /* Handle the timeout error */
211 printk(BIOS_ERR, "SPI transaction timeout!\n");
212
213error:
214 context->prefix = 0;
215 return -1;
216}
217
218void spi_init(void)
219{
220 uint32_t bios_control;
221 struct spi_context *context;
222 volatile struct flash_ctrlr *ctrlr;
Elyes HAOUAS696545d2018-05-25 13:11:37 +0200223 struct device *dev;
Lee Leahyd9351092017-05-24 13:23:26 -0700224 uint32_t rcba;
225
226 /* Determine the base address of the SPI flash controller */
227 context = &spi_driver_context;
228 dev = dev_find_device(PCI_VENDOR_ID_INTEL, LPC_DEVID, NULL);
229 rcba = pci_read_config32(dev, R_QNC_LPC_RCBA);
230 if (!(rcba & B_QNC_LPC_RCBA_EN)) {
231 printk(BIOS_ERR, "RBCA not enabled\n");
232 return;
233 }
234 rcba &= B_QNC_LPC_RCBA_MASK;
235 ctrlr = (volatile struct flash_ctrlr *)rcba;
236
237 /* Enable writes to the SPI flash */
238 bios_control = pci_read_config32(dev, R_QNC_LPC_BIOS_CNTL);
239 bios_control |= B_QNC_LPC_BIOS_CNTL_BIOSWE;
240 pci_write_config32(dev, R_QNC_LPC_BIOS_CNTL, bios_control);
241
242 /* Setup the SPI flash controller */
243 context->ctrlr = ctrlr;
244 ctrlr->opmenu[0] = 0x03; /* Read */
245 ctrlr->opmenu[1] = 0x0b; /* Read fast */
246 ctrlr->opmenu[2] = 0x05; /* Read status */
247 ctrlr->opmenu[3] = 0x9f; /* Read ID */
248 ctrlr->opmenu[4] = 0x02; /* Page program */
249 ctrlr->opmenu[5] = 0x20; /* Erase 4 KiB */
250 ctrlr->opmenu[6] = 0xd8; /* Erase 64 KiB */
251 ctrlr->opmenu[7] = 0x01; /* Write status */
252 ctrlr->prefix[0] = 0x50; /* Write status enable */
253 ctrlr->prefix[1] = 0x06; /* Write enable */
254 ctrlr->type = SPITYPE_ADDRESS /* Read */
255 | (SPITYPE_ADDRESS << 2) /* Read fast */
256 | (0 << 4) /* Read status */
257 | (0 << 6) /* Read ID */
258 | ((SPITYPE_ADDRESS | SPITYPE_PREFIX) << 8) /* Page program */
259 | ((SPITYPE_ADDRESS | SPITYPE_PREFIX) << 10) /* Erase 4 KiB */
260 | ((SPITYPE_ADDRESS | SPITYPE_PREFIX) << 12) /* Erase 64 KiB */
261 | (SPITYPE_PREFIX << 14); /* Write status */
262}
263
264static void spi_init_cb(void *unused)
265{
266 struct spi_flash flash;
267
268 spi_init();
269 if (spi_flash_probe(0, 0, &flash)) {
270 printk(BIOS_DEBUG, "SPI flash failed initialization!\n");
271 return;
272 }
273 printk(BIOS_DEBUG, "SPI flash successfully initialized\n");
274}
275
276BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, spi_init_cb, NULL);
277
278const struct spi_ctrlr spi_driver = {
279 .xfer = xfer,
280 .max_xfer_size = 64,
Lee Leahyd9351092017-05-24 13:23:26 -0700281};
282
283const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
284 {
285 .ctrlr = &spi_driver,
286 .bus_start = 0,
287 .bus_end = 0,
288 },
289};
290
291const size_t spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map);