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