coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
spi.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #include <device/pci_ops.h>
5 #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>
13 #include <string.h>
14 
16  NULL,
17  0,
18  0
19 };
20 
21 void spi_bios_base(uint32_t bios_base_address)
22 {
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 
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 
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;
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 */
71  "Failed to set protection: 0x%08x - 0x%08x, PRRs full!\n",
72  address, address + length - 1);
73  return -1;
74 }
75 
76 static 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;
81  volatile struct flash_ctrlr *ctrlr;
82  uint8_t *data;
83  int index;
84  uint8_t opcode;
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)) {
94  printk(BIOS_ERR, "bytesin > %zu\n", sizeof(ctrlr->data));
95  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))
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];
156 
157  /* read in order to flush the write buffer */
158  status = ctrlr->address;
159 
160  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 
182 start_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 
212 error:
213  context->prefix = 0;
214  return -1;
215 }
216 
217 void spi_init(void)
218 {
219  uint32_t bios_control;
220  struct spi_context *context;
221  volatile struct flash_ctrlr *ctrlr;
222  struct device *dev;
223  uint32_t rcba;
224 
225  /* Determine the base address of the SPI flash controller */
226  context = &spi_driver_context;
228  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 
263 static 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 
276 
277 const struct spi_ctrlr spi_driver = {
278  .xfer = xfer,
279  .max_xfer_size = 64,
280 };
281 
282 const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
283  {
284  .ctrlr = &spi_driver,
285  .bus_start = 0,
286  .bus_end = 0,
287  },
288 };
289 
#define B_QNC_LPC_RCBA_EN
Definition: QuarkNcSocId.h:622
#define R_QNC_LPC_RCBA
Definition: QuarkNcSocId.h:620
#define R_QNC_LPC_BIOS_CNTL
Definition: QuarkNcSocId.h:610
#define B_QNC_LPC_RCBA_MASK
Definition: QuarkNcSocId.h:621
#define B_QNC_LPC_BIOS_CNTL_BIOSWE
Definition: QuarkNcSocId.h:616
pte_t value
Definition: mmu.c:91
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
void * memcpy(void *dest, const void *src, size_t n)
Definition: memcpy.c:7
@ BS_DEV_INIT
Definition: bootstate.h:83
@ BS_ON_ENTRY
Definition: bootstate.h:95
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define printk(level,...)
Definition: stdlib.h:16
struct device * dev_find_device(u16 vendor, u16 device, struct device *from)
Find a device of a given vendor and type.
Definition: device_util.c:42
uint64_t length
Definition: fw_cfg_if.h:1
uint64_t address
Definition: fw_cfg_if.h:0
static __always_inline void pci_write_config32(const struct device *dev, u16 reg, u32 val)
Definition: pci_ops.h:76
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
unsigned int type
Definition: edid.c:57
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define PCI_VID_INTEL
Definition: pci_ids.h:2157
uintptr_t base
Definition: uart.c:17
const struct spi_ctrlr_buses spi_ctrlr_bus_map[]
Definition: spi.c:401
void spi_init(void)
Init all SPI controllers with default values and enable all SPI controller.
Definition: spi.c:280
const size_t spi_ctrlr_bus_map_count
Definition: spi.c:408
#define LPC_DEVID
Definition: pci_devs.h:141
#define SPICTL_AR
Definition: spi.h:52
#define SPIPBR_PRL
Definition: spi.h:64
#define SPISTS_CD
Definition: spi.h:38
#define SPIPBR_PRB
Definition: spi.h:66
#define SPITYPE_ADDRESS
Definition: spi.h:55
#define SPICTL_DBCNT_SHIFT
Definition: spi.h:45
#define SPICTL_CG
Definition: spi.h:51
#define SPICTL_DC
Definition: spi.h:43
#define SPISTS_CIP
Definition: spi.h:39
#define SPICTL_SOPTR_SHIFT
Definition: spi.h:49
#define SPICTL_COPTR_SHIFT
Definition: spi.h:47
#define SPICTL_ACS
Definition: spi.h:50
#define SPIPBR_WPE
Definition: spi.h:63
#define SPISTS_CLD
Definition: spi.h:36
#define SPISTS_BA
Definition: spi.h:37
#define SPIPBR_PRB_SHIFT
Definition: spi.h:65
#define SPITYPE_PREFIX
Definition: spi.h:56
static int xfer(const struct spi_slave *slave, const void *dout, size_t bytesout, void *din, size_t bytesin)
Definition: spi.c:76
int spi_protection(uint32_t address, uint32_t length)
Definition: spi.c:39
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, spi_init_cb, NULL)
void spi_controller_lock(void)
Definition: spi.c:31
static void spi_init_cb(void *unused)
Definition: spi.c:263
const struct spi_ctrlr spi_driver
Definition: spi.c:277
struct spi_context spi_driver_context
Definition: spi.c:15
void spi_bios_base(uint32_t bios_base_address)
Definition: spi.c:21
int spi_flash_probe(unsigned int bus, unsigned int cs, struct spi_flash *flash)
Definition: spi_flash.c:486
static struct spi_slave slave
Definition: spiconsole.c:7
#define NULL
Definition: stddef.h:19
unsigned short uint16_t
Definition: stdint.h:11
unsigned int uint32_t
Definition: stdint.h:14
unsigned char uint8_t
Definition: stdint.h:8
Definition: device.h:107
uint8_t opmenu[8]
Definition: spi.h:31
uint16_t type
Definition: spi.h:30
uint8_t data[64]
Definition: spi.h:26
uint32_t address
Definition: spi.h:25
uint32_t bbar
Definition: spi.h:28
uint16_t control
Definition: spi.h:24
uint32_t pbr[3]
Definition: spi.h:32
uint16_t status
Definition: spi.h:23
uint8_t prefix[2]
Definition: spi.h:29
uint16_t prefix
Definition: spi.h:71
volatile struct flash_ctrlr * ctrlr
Definition: spi.h:69
uint16_t control
Definition: spi.h:70
const struct spi_ctrlr * ctrlr
Definition: spi-generic.h:175
int(* xfer)(const struct spi_slave *slave, const void *dout, size_t bytesout, void *din, size_t bytesin)
Definition: spi-generic.h:152
void udelay(uint32_t us)
Definition: udelay.c:15