coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
cbfs_spi.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 /*
4  * This file provides a common CBFS wrapper for SPI storage. SPI driver
5  * context is expanded with the buffer descriptor used to store data read from
6  * SPI.
7  */
8 
9 #include <boot_device.h>
10 #include <cbfs.h>
11 #include <console/console.h>
12 #include <spi_flash.h>
13 #include <symbols.h>
14 #include <stdint.h>
15 #include <timer.h>
16 
17 static struct spi_flash spi_flash_info;
18 static bool spi_flash_init_done;
19 
20 /*
21  * SPI speed logging for big transfers available with BIOS_DEBUG. The format is:
22  *
23  * read SPI 0x62854 0x7db7: 10416 us, 3089 KB/s, 24.712 Mbps
24  *
25  * The important number is the last one. It should roughly match your SPI
26  * clock. If it doesn't, your driver might need a little tuning.
27  */
28 static ssize_t spi_readat(const struct region_device *rd, void *b,
29  size_t offset, size_t size)
30 {
31  struct stopwatch sw;
32  bool show = size >= 4 * KiB && console_log_level(BIOS_DEBUG);
33 
34  if (show)
35  stopwatch_init(&sw);
36  if (spi_flash_read(&spi_flash_info, offset, size, b))
37  return -1;
38  if (show) {
39  long usecs;
40 
41  usecs = stopwatch_duration_usecs(&sw);
42  u64 speed; /* KiB/s */
43  int bps; /* Bits per second */
44 
45  speed = size * (u64)1000 / usecs;
46  bps = speed * 8;
47 
48  printk(BIOS_DEBUG, "read SPI %#zx %#zx: %ld us, %lld KB/s, %d.%03d Mbps\n",
49  offset, size, usecs, speed, bps / 1000, bps % 1000);
50  }
51  return size;
52 }
53 
54 static ssize_t spi_writeat(const struct region_device *rd, const void *b,
55  size_t offset, size_t size)
56 {
57  if (spi_flash_write(&spi_flash_info, offset, size, b))
58  return -1;
59  return size;
60 }
61 
62 static ssize_t spi_eraseat(const struct region_device *rd,
63  size_t offset, size_t size)
64 {
66  return -1;
67  return size;
68 }
69 
70 /* Provide all operations on the same device. */
71 static const struct region_device_ops spi_ops = {
73  .munmap = mmap_helper_rdev_munmap,
74  .readat = spi_readat,
75  .writeat = spi_writeat,
76  .eraseat = spi_eraseat,
77 };
78 
79 static struct mmap_helper_region_device mdev =
80  MMAP_HELPER_DEV_INIT(&spi_ops, 0, CONFIG_ROM_SIZE, &cbfs_cache);
81 
82 void boot_device_init(void)
83 {
84  int bus = CONFIG_BOOT_DEVICE_SPI_FLASH_BUS;
85  int cs = 0;
86 
87  if (spi_flash_init_done == true)
88  return;
89 
91  return;
92 
93  spi_flash_init_done = true;
94 }
95 
96 /* Return the CBFS boot device. */
97 const struct region_device *boot_device_ro(void)
98 {
99  if (spi_flash_init_done != true)
100  return NULL;
101 
102  return &mdev.rdev;
103 }
104 
105 /* The read-only and read-write implementations are symmetric. */
106 const struct region_device *boot_device_rw(void)
107 {
108  return boot_device_ro();
109 }
110 
111 const struct spi_flash *boot_device_spi_flash(void)
112 {
114 
115  if (spi_flash_init_done != true)
116  return NULL;
117 
118  return &spi_flash_info;
119 }
#define KiB
Definition: helpers.h:75
struct mem_pool cbfs_cache
Definition: cbfs.c:26
static const struct region_device_ops spi_ops
Definition: cbfs_spi.c:71
static struct mmap_helper_region_device mdev
Definition: cbfs_spi.c:79
const struct region_device * boot_device_ro(void)
Definition: cbfs_spi.c:97
static ssize_t spi_readat(const struct region_device *rd, void *b, size_t offset, size_t size)
Definition: cbfs_spi.c:28
const struct region_device * boot_device_rw(void)
Definition: cbfs_spi.c:106
static struct spi_flash spi_flash_info
Definition: cbfs_spi.c:17
static bool spi_flash_init_done
Definition: cbfs_spi.c:18
const struct spi_flash * boot_device_spi_flash(void)
Definition: cbfs_spi.c:111
static ssize_t spi_writeat(const struct region_device *rd, const void *b, size_t offset, size_t size)
Definition: cbfs_spi.c:54
void boot_device_init(void)
Definition: cbfs_spi.c:82
static ssize_t spi_eraseat(const struct region_device *rd, size_t offset, size_t size)
Definition: cbfs_spi.c:62
#define printk(level,...)
Definition: stdlib.h:16
static size_t offset
Definition: flashconsole.c:16
static void stopwatch_init(struct stopwatch *sw)
Definition: timer.h:117
static long stopwatch_duration_usecs(struct stopwatch *sw)
Definition: timer.h:170
int console_log_level(int msg_level)
Definition: init.c:33
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
void * mmap_helper_rdev_mmap(const struct region_device *, size_t, size_t)
Definition: region.c:303
int mmap_helper_rdev_munmap(const struct region_device *, void *)
Definition: region.c:324
#define MMAP_HELPER_DEV_INIT(ops_, offset_, size_, mpool_)
Definition: region.h:219
int spi_flash_probe(unsigned int bus, unsigned int cs, struct spi_flash *flash)
Definition: spi_flash.c:486
int spi_flash_read(const struct spi_flash *flash, u32 offset, size_t len, void *buf)
Definition: spi_flash.c:531
int spi_flash_write(const struct spi_flash *flash, u32 offset, size_t len, const void *buf)
Definition: spi_flash.c:537
int spi_flash_erase(const struct spi_flash *flash, u32 offset, size_t len)
Definition: spi_flash.c:553
#define NULL
Definition: stddef.h:19
__SIZE_TYPE__ ssize_t
Definition: stddef.h:13
uint64_t u64
Definition: stdint.h:54
Definition: device.h:76
struct region_device rdev
Definition: region.h:216
void *(* mmap)(const struct region_device *, size_t, size_t)
Definition: region.h:68
u32 size
Definition: spi_flash.h:95