blob: 787d8e7af363a7a5ebd12aa99cafe59dbfce09cd [file] [log] [blame]
Maximilian Brunee26bcae2024-01-14 22:31:15 +06001/* SPDX-License-Identifier: GPL-2.0-only */
2
3/*
4 * This file is basically drivers/spi/cbfs_spi.cb but the boot device is not known at build time
5 */
6
7#include <boot_device.h>
8#include <cbfs.h>
9#include <console/console.h>
10#include <device/mmio.h>
11#include <lib.h>
12#include <soc/addressmap.h>
13#include <soc/clock.h>
14#include <soc/spi.h>
15#include <spi_flash.h>
16#include <spi_sdcard.h>
17#include <stdint.h>
18#include <symbols.h>
19#include <timer.h>
20
21// There are two different means of accessing the SPI flash.
22// They are controlled by the fctrl register.
23// 1. memory mapped access
24// 2. FIFO based access
25
26/* follow is the FSBL boot device defined by ZSBL of sifive
27 * FSBL replaced by bootblock of coreboot
28 * MSEL_SPInx1 -> test if boot from memory-mapped on SPIn
29 * MSEL_SPInx4 -> test if boot from memory-mapped on QPIn
30 * MSEL_SPInSD -> test if boot from sdcard mount on SPIn */
31#define MSEL_SPI0x1(m) (((m) == 5) || ((m) == 14))
32#define MSEL_SPI0x4(m) (((m) == 6) || ((m) == 10) || ((m) == 15))
33#define MSEL_SPI1x1(m) ((m) == 12)
34#define MSEL_SPI1x4(m) (((m) == 7) || ((m) == 13))
35#define MSEL_SPI1SD(m) ((m) == 8)
36#define MSEL_SPI2x1(m) ((m) == 9)
37#define MSEL_SPI2SD(m) ((m) == 11)
38
39#define MSEL_ACCESS_METHOD_MMAP(m) ((m == 5) || (m == 6) || (m == 7) || (m == 10) || (m == 13))
40
41// probably something for devicetree
42struct fu740_spi_config fu740_spi_configs[] = {
43 { 0 },
44 {
45 .freq = 10*1000*1000,
46 },
47 { 0 },
48};
49
50static struct spi_sdcard spi2_sdcard; //TODO initialize SPI2
51//static struct spi_flash spi0_flash;
52//static struct spi_flash spi1_flash;
53static struct spi_flash spi_flash;
54static bool spi_flash_init_done;
55
56static ssize_t sd_readat(const struct region_device *rdev, void *dest,
57 size_t offset, size_t count)
58{
59 spi_sdcard_read(&spi2_sdcard, dest, offset, count);
60 return count;
61}
62
63static ssize_t spi_readat(const struct region_device *rd, void *b, size_t offset, size_t size)
64{
65 if (spi_flash_read(&spi_flash, offset, size, b))
66 return -1;
67 return size;
68}
69
70static ssize_t spi_writeat(const struct region_device *rd, const void *b,
71 size_t offset, size_t size)
72{
73 if (spi_flash_write(&spi_flash, offset, size, b))
74 return -1;
75 return size;
76}
77
78static ssize_t spi_eraseat(const struct region_device *rd, size_t offset, size_t size)
79{
80 if (spi_flash_erase(&spi_flash, offset, size))
81 return -1;
82 return size;
83}
84
85static const struct region_device_ops sd_ops = {
86 .mmap = mmap_helper_rdev_mmap,
87 .munmap = mmap_helper_rdev_munmap,
88 .readat = sd_readat,
89};
90
91static const struct region_device_ops spi_ops = {
92 .mmap = mmap_helper_rdev_mmap,
93 .munmap = mmap_helper_rdev_munmap,
94 .readat = spi_readat,
95 .writeat = spi_writeat,
96 .eraseat = spi_eraseat,
97};
98
99//TODO using postram cache means that all spi transitions are transferred to actual memory.
100// Native memory mapping obviously doesnt have that problem. That can however only happen if
101// memory has been initialized before accessing the boot device. So no CBFS access before boot.
102//static struct mem_pool mem_cbfs_cache =
103// MEM_POOL_INIT(_postram_cbfs_cache, REGION_SIZE(postram_cbfs_cache), CONFIG_CBFS_CACHE_ALIGN);
104//static struct mmap_helper_region_device spi_mdev =
105// MMAP_HELPER_DEV_INIT(&spi_ops, 0, CONFIG_ROM_SIZE, &mem_cbfs_cache);
106
107static struct mmap_helper_region_device spi_mdev =
108 MMAP_HELPER_DEV_INIT(&spi_ops, 0, CONFIG_ROM_SIZE, &cbfs_cache);
109
110static struct mmap_helper_region_device sd_mdev =
111 MMAP_HELPER_DEV_INIT(&sd_ops, 0, CONFIG_ROM_SIZE, &cbfs_cache);
112
113void boot_device_init(void)
114{
115 printk(BIOS_DEBUG, "%s 0\n", __func__);
116 if (spi_flash_init_done == true)
117 return;
118
119 uint32_t m = read32((uint32_t *)FU740_MSEL);
120 // Pass the information of the flash read operation to the spi controller
121 //.pad_cnt = 6,
122 if (MSEL_SPI0x4(m) || MSEL_SPI1x4(m)) {
123 //config.ffmt_config.data_proto = FU740_SPI_PROTO_Q;
124 //config.ffmt_config.cmd_code = 0x6B; // Quad output read
125 //.cmd_code = 0xec,
126 }
127 if (MSEL_SPI1x1(m)) {
128 printk(BIOS_DEBUG, "%s 1\n", __func__);
129 fu740_spi_configs[1].ffmt_config.data_proto = FU740_SPI_PROTO_S;
130 fu740_spi_configs[1].ffmt_config.cmd_code = 0x03; // Normal read
131 //TODO SPI1x1 is always using programmed IO (FIFO)? (memory map did not work...)
132 if (spi_flash_probe(1, 0, &spi_flash)) {
133 printk(BIOS_EMERG, "failed to init SPI flash\n");
134 return;
135 }
136 // initialize soc spi controller
137 //if (fu740_spi_setup(&spi1_flash.spi) == -1) {
138 // printk(BIOS_EMERG, "failed to configure mmap for SPI flash\n");
139 //}
140 //hexdump((void*)0x10041000, 0x100);
141 //hexdump((void*)0x30000000, 0x100);
142 printk(BIOS_DEBUG, "%s 2\n", __func__);
143 } else if (MSEL_SPI2SD(m)) {
144 spi_sdcard_init(&spi2_sdcard, 2, 0);
145 } else {
146 die("Wrong configuration of MSEL\n");
147 }
148
149 spi_flash_init_done = true;
150}
151
152/* Return the CBFS boot device. */
153const struct region_device *boot_device_ro(void)
154{
155 if (spi_flash_init_done != true)
156 return NULL;
157
158 uint32_t m = read32((uint32_t *)FU740_MSEL);
159
160 if (MSEL_SPI2SD(m) || MSEL_SPI1SD(m))
161 return &sd_mdev.rdev;
162 return &spi_mdev.rdev;
163}
164
165//const struct spi_flash *boot_device_spi_flash(void)
166//{
167// boot_device_init();
168//
169// if (spi_flash_init_done != true)
170// return NULL;
171//
172// return &spi_flash;
173//}