blob: 15a18b72e4e9c41a232c78eddd6503895377c32e [file] [log] [blame]
Angel Pons8a3453f2020-04-02 23:48:19 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Vadim Bendeburyadcb0952014-05-01 12:23:09 -07002
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
Aaron Durbinc6588c52015-05-15 13:15:34 -05009#include <boot_device.h>
Julius Werner9b1f3cc2020-12-30 17:30:12 -080010#include <cbfs.h>
Furquan Shaikhc28984d2016-11-20 21:04:00 -080011#include <console/console.h>
Vadim Bendeburyadcb0952014-05-01 12:23:09 -070012#include <spi_flash.h>
Julius Wernerec5e5e02014-08-20 15:29:56 -070013#include <symbols.h>
Furquan Shaikh30221b42017-05-15 14:35:15 -070014#include <stdint.h>
Simon Glassaa58a9e2016-08-27 15:03:02 -060015#include <timer.h>
Vadim Bendeburyadcb0952014-05-01 12:23:09 -070016
Furquan Shaikh30221b42017-05-15 14:35:15 -070017static struct spi_flash spi_flash_info;
18static bool spi_flash_init_done;
Aaron Durbinc6588c52015-05-15 13:15:34 -050019
Simon Glassaa58a9e2016-08-27 15:03:02 -060020/*
Julius Werner8dcf24f2019-06-06 17:35:25 -070021 * SPI speed logging for big transfers available with BIOS_DEBUG. The format is:
Simon Glassaa58a9e2016-08-27 15:03:02 -060022 *
Julius Werner8dcf24f2019-06-06 17:35:25 -070023 * read SPI 0x62854 0x7db7: 10416 us, 3089 KB/s, 24.712 Mbps
Simon Glassaa58a9e2016-08-27 15:03:02 -060024 *
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 */
Aaron Durbinc6588c52015-05-15 13:15:34 -050028static ssize_t spi_readat(const struct region_device *rd, void *b,
29 size_t offset, size_t size)
30{
Simon Glassaa58a9e2016-08-27 15:03:02 -060031 struct stopwatch sw;
Julius Werner8dcf24f2019-06-06 17:35:25 -070032 bool show = size >= 4 * KiB && console_log_level(BIOS_DEBUG);
Simon Glassaa58a9e2016-08-27 15:03:02 -060033
34 if (show)
35 stopwatch_init(&sw);
Furquan Shaikh30221b42017-05-15 14:35:15 -070036 if (spi_flash_read(&spi_flash_info, offset, size, b))
Aaron Durbinc6588c52015-05-15 13:15:34 -050037 return -1;
Simon Glassaa58a9e2016-08-27 15:03:02 -060038 if (show) {
39 long usecs;
40
41 usecs = stopwatch_duration_usecs(&sw);
42 u64 speed; /* KiB/s */
43 int bps; /* Bits per second */
44
Julius Wernerf96d9052019-08-16 15:35:39 -070045 speed = size * (u64)1000 / usecs;
Simon Glassaa58a9e2016-08-27 15:03:02 -060046 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 }
Aaron Durbinc6588c52015-05-15 13:15:34 -050051 return size;
52}
53
Aaron Durbin504b8f22016-08-11 11:10:42 -050054static ssize_t spi_writeat(const struct region_device *rd, const void *b,
55 size_t offset, size_t size)
56{
Furquan Shaikh30221b42017-05-15 14:35:15 -070057 if (spi_flash_write(&spi_flash_info, offset, size, b))
Aaron Durbin504b8f22016-08-11 11:10:42 -050058 return -1;
59 return size;
60}
61
62static ssize_t spi_eraseat(const struct region_device *rd,
63 size_t offset, size_t size)
64{
Furquan Shaikh30221b42017-05-15 14:35:15 -070065 if (spi_flash_erase(&spi_flash_info, offset, size))
Aaron Durbin504b8f22016-08-11 11:10:42 -050066 return -1;
67 return size;
68}
69
70/* Provide all operations on the same device. */
Aaron Durbinc6588c52015-05-15 13:15:34 -050071static const struct region_device_ops spi_ops = {
72 .mmap = mmap_helper_rdev_mmap,
73 .munmap = mmap_helper_rdev_munmap,
74 .readat = spi_readat,
Aaron Durbin504b8f22016-08-11 11:10:42 -050075 .writeat = spi_writeat,
76 .eraseat = spi_eraseat,
Vadim Bendeburyadcb0952014-05-01 12:23:09 -070077};
78
Aaron Durbinc6588c52015-05-15 13:15:34 -050079static struct mmap_helper_region_device mdev =
Julius Werner9b1f3cc2020-12-30 17:30:12 -080080 MMAP_HELPER_DEV_INIT(&spi_ops, 0, CONFIG_ROM_SIZE, &cbfs_cache);
Mary Ruthvenf82e8ab2015-11-13 14:05:27 -080081
Aaron Durbinc6588c52015-05-15 13:15:34 -050082void boot_device_init(void)
83{
Aaron Durbin08e842c2016-08-11 14:40:09 -050084 int bus = CONFIG_BOOT_DEVICE_SPI_FLASH_BUS;
Aaron Durbinc6588c52015-05-15 13:15:34 -050085 int cs = 0;
86
Furquan Shaikh30221b42017-05-15 14:35:15 -070087 if (spi_flash_init_done == true)
Aaron Durbinc6588c52015-05-15 13:15:34 -050088 return;
89
Furquan Shaikh30221b42017-05-15 14:35:15 -070090 if (spi_flash_probe(bus, cs, &spi_flash_info))
91 return;
92
93 spi_flash_init_done = true;
Aaron Durbinc6588c52015-05-15 13:15:34 -050094}
95
96/* Return the CBFS boot device. */
97const struct region_device *boot_device_ro(void)
98{
Furquan Shaikh30221b42017-05-15 14:35:15 -070099 if (spi_flash_init_done != true)
Aaron Durbinc6588c52015-05-15 13:15:34 -0500100 return NULL;
101
102 return &mdev.rdev;
103}
Aaron Durbin504b8f22016-08-11 11:10:42 -0500104
105/* The read-only and read-write implementations are symmetric. */
106const struct region_device *boot_device_rw(void)
107{
108 return boot_device_ro();
109}
Furquan Shaikh78bc6dd2017-05-16 13:32:34 -0700110
111const struct spi_flash *boot_device_spi_flash(void)
112{
113 boot_device_init();
Furquan Shaikh30221b42017-05-15 14:35:15 -0700114
115 if (spi_flash_init_done != true)
116 return NULL;
117
118 return &spi_flash_info;
Furquan Shaikh78bc6dd2017-05-16 13:32:34 -0700119}