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