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