1 /* SPDX-License-Identifier: GPL-2.0-only */
4 * This file is basically drivers/spi/cbfs_spi.cb but the boot device is not known at build time
7 #include <boot_device.h>
9 #include <console/console.h>
10 #include <device/mmio.h>
12 #include <soc/addressmap.h>
13 #include <soc/clock.h>
15 #include <spi_flash.h>
16 #include <spi_sdcard.h>
20 // There are two different means of accessing the SPI flash.
21 // They are controlled by the fctrl register.
22 // 1. memory mapped access
23 // 2. FIFO based access
25 /* follow is the FSBL boot device defined by ZSBL of sifive
26 * FSBL replaced by bootblock of coreboot
27 * MSEL_SPInx1 -> test if boot from memory-mapped on SPIn
28 * MSEL_SPInx4 -> test if boot from memory-mapped on QPIn
29 * MSEL_SPInSD -> test if boot from sdcard mount on SPIn */
30 #define MSEL_SPI0x1(m) (((m) == 5) || ((m) == 14))
31 #define MSEL_SPI0x4(m) (((m) == 6) || ((m) == 10) || ((m) == 15))
32 #define MSEL_SPI1x1(m) ((m) == 12)
33 #define MSEL_SPI1x4(m) (((m) == 7) || ((m) == 13))
34 #define MSEL_SPI1SD(m) ((m) == 8)
35 #define MSEL_SPI2x1(m) ((m) == 9)
36 #define MSEL_SPI2SD(m) ((m) == 11)
38 #define MSEL_ACCESS_METHOD_MMAP(m) ((m == 5) || (m == 6) || (m == 7) || (m == 10) || (m == 13))
40 // probably something for devicetree
41 struct fu740_spi_config fu740_spi_configs
[] = {
49 static struct spi_sdcard spi2_sdcard
; //TODO initialize SPI2
50 //static struct spi_flash spi0_flash;
51 //static struct spi_flash spi1_flash;
52 static struct spi_flash spi_flash
;
53 static bool spi_flash_init_done
;
55 static ssize_t
sd_readat(const struct region_device
*rdev
, void *dest
,
56 size_t offset
, size_t count
)
58 spi_sdcard_read(&spi2_sdcard
, dest
, offset
, count
);
62 static ssize_t
spi_readat(const struct region_device
*rd
, void *b
, size_t offset
, size_t size
)
64 if (spi_flash_read(&spi_flash
, offset
, size
, b
))
69 static ssize_t
spi_writeat(const struct region_device
*rd
, const void *b
,
70 size_t offset
, size_t size
)
72 if (spi_flash_write(&spi_flash
, offset
, size
, b
))
77 static ssize_t
spi_eraseat(const struct region_device
*rd
, size_t offset
, size_t size
)
79 if (spi_flash_erase(&spi_flash
, offset
, size
))
84 static const struct region_device_ops sd_ops
= {
85 .mmap
= mmap_helper_rdev_mmap
,
86 .munmap
= mmap_helper_rdev_munmap
,
90 static const struct region_device_ops spi_ops
= {
91 .mmap
= mmap_helper_rdev_mmap
,
92 .munmap
= mmap_helper_rdev_munmap
,
94 .writeat
= spi_writeat
,
95 .eraseat
= spi_eraseat
,
98 //TODO using postram cache means that all spi transitions are transferred to actual memory.
99 // Native memory mapping obviously doesnt have that problem. That can however only happen if
100 // memory has been initialized before accessing the boot device. So no CBFS access before boot.
101 //static struct mem_pool mem_cbfs_cache =
102 // MEM_POOL_INIT(_postram_cbfs_cache, REGION_SIZE(postram_cbfs_cache), CONFIG_CBFS_CACHE_ALIGN);
103 //static struct mmap_helper_region_device spi_mdev =
104 // MMAP_HELPER_DEV_INIT(&spi_ops, 0, CONFIG_ROM_SIZE, &mem_cbfs_cache);
106 static struct mmap_helper_region_device spi_mdev
=
107 MMAP_HELPER_DEV_INIT(&spi_ops
, 0, CONFIG_ROM_SIZE
, &cbfs_cache
);
109 static struct mmap_helper_region_device sd_mdev
=
110 MMAP_HELPER_DEV_INIT(&sd_ops
, 0, CONFIG_ROM_SIZE
, &cbfs_cache
);
112 void boot_device_init(void)
114 printk(BIOS_DEBUG
, "%s 0\n", __func__
);
115 if (spi_flash_init_done
== true)
118 uint32_t m
= read32((uint32_t *)FU740_MSEL
) & 0xf;
119 printk(BIOS_DEBUG
, "%s MSEL %#x\n", __func__
, m
);
121 // We have not yet found a way to reliably program the
122 // on-board SPI part (sifive neglected to put a diode on vcc ...)
123 // Once we work that out, we can test this code.
124 // It is left here as a hint of what needs to be done.
125 // Pass the information of the flash read operation to the spi controller
126 if (MSEL_SPI0x4(m
)) {
127 die("SPI0x4 is not supported yet");
128 //config.ffmt_config.data_proto = FU740_SPI_PROTO_Q;
129 //config.ffmt_config.cmd_code = 0x6B; // Quad output read
133 if (MSEL_SPI1x4(m
)) {
134 printk(BIOS_DEBUG
, "%s SPI1x4 1\n", __func__
);
135 fu740_spi_configs
[1].ffmt_config
.data_proto
= FU740_SPI_PROTO_Q
;
136 fu740_spi_configs
[1].ffmt_config
.cmd_code
= 0x6b; // quad
137 if (spi_flash_probe(1, 0, &spi_flash
)) {
138 printk(BIOS_EMERG
, "SPI1x4 failed to init SPI flash\n");
141 if (fu740_spi_setup(&spi_flash
.spi
) == -1) {
142 printk(BIOS_EMERG
, "SPI1x4 failed to configure mmap for SPI flash\n");
144 printk(BIOS_DEBUG
, "%s SPI1x4 2\n", __func__
);
145 } else if (MSEL_SPI1x1(m
)) {
146 printk(BIOS_DEBUG
, "%s 1\n", __func__
);
147 fu740_spi_configs
[1].ffmt_config
.data_proto
= FU740_SPI_PROTO_S
;
148 fu740_spi_configs
[1].ffmt_config
.cmd_code
= 0x03; // Normal read
149 //TODO SPI1x1 is always using programmed IO (FIFO)? (memory map did not work...)
150 if (spi_flash_probe(1, 0, &spi_flash
)) {
151 printk(BIOS_EMERG
, "failed to init SPI flash\n");
154 printk(BIOS_DEBUG
, "%s 2\n", __func__
);
155 } else if (MSEL_SPI2SD(m
)) {
156 spi_sdcard_init(&spi2_sdcard
, 2, 0);
158 printk(BIOS_EMERG
, "MSEL: %#02x: ", m
);
159 die("unsupported configuration of MSEL\n");
162 spi_flash_init_done
= true;
165 /* Return the CBFS boot device. */
166 const struct region_device
*boot_device_ro(void)
168 if (spi_flash_init_done
!= true)
171 uint32_t m
= read32((uint32_t *)FU740_MSEL
);
173 if (MSEL_SPI2SD(m
) || MSEL_SPI1SD(m
))
174 return &sd_mdev
.rdev
;
175 return &spi_mdev
.rdev
;
178 //const struct spi_flash *boot_device_spi_flash(void)
180 // boot_device_init();
182 // if (spi_flash_init_done != true)
185 // return &spi_flash;