1 /* SPDX-License-Identifier: GPL-2.0-only */
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
9 #include <boot_device.h>
11 #include <console/console.h>
12 #include <spi_flash.h>
17 static struct spi_flash spi_flash_info
;
18 static bool spi_flash_init_done
;
21 * SPI speed logging for big transfers available with BIOS_DEBUG. The format is:
23 * read SPI 0x62854 0x7db7: 10416 us, 3089 KB/s, 24.712 Mbps
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.
28 static ssize_t
spi_readat(const struct region_device
*rd
, void *b
,
29 size_t offset
, size_t size
)
32 bool show
= size
>= 4 * KiB
&& console_log_level(BIOS_DEBUG
);
36 if (spi_flash_read(&spi_flash_info
, offset
, size
, b
))
41 usecs
= stopwatch_duration_usecs(&sw
);
42 u64 speed
; /* KiB/s */
43 int bps
; /* Bits per second */
45 speed
= size
* (u64
)1000 / usecs
;
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);
54 static ssize_t
spi_writeat(const struct region_device
*rd
, const void *b
,
55 size_t offset
, size_t size
)
57 if (spi_flash_write(&spi_flash_info
, offset
, size
, b
))
62 static ssize_t
spi_eraseat(const struct region_device
*rd
,
63 size_t offset
, size_t size
)
65 if (spi_flash_erase(&spi_flash_info
, offset
, size
))
70 /* Provide all operations on the same device. */
71 static const struct region_device_ops spi_ops
= {
72 .mmap
= mmap_helper_rdev_mmap
,
73 .munmap
= mmap_helper_rdev_munmap
,
75 .writeat
= spi_writeat
,
76 .eraseat
= spi_eraseat
,
79 static struct mmap_helper_region_device mdev
=
80 MMAP_HELPER_DEV_INIT(&spi_ops
, 0, CONFIG_ROM_SIZE
, &cbfs_cache
);
82 void boot_device_init(void)
84 int bus
= CONFIG_BOOT_DEVICE_SPI_FLASH_BUS
;
87 if (spi_flash_init_done
== true)
90 if (spi_flash_probe(bus
, cs
, &spi_flash_info
))
93 spi_flash_init_done
= true;
96 /* Return the CBFS boot device. */
97 const struct region_device
*boot_device_ro(void)
99 if (spi_flash_init_done
!= true)
105 /* The read-only and read-write implementations are symmetric. */
106 const struct region_device
*boot_device_rw(void)
108 return boot_device_ro();
111 const struct spi_flash
*boot_device_spi_flash(void)
115 if (spi_flash_init_done
!= true)
118 return &spi_flash_info
;