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