summaryrefslogtreecommitdiff
path: root/src/mainboard/sifive/hifive-unleashed/media.c
blob: 757b50ac28c8a4978578e70d1f71ce5d5c6a8c3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
 * This file is part of the coreboot project.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <boot_device.h>
#include <symbols.h>
#include <cbfs.h>
#include <device/mmio.h>
#include <soc/addressmap.h>
#include <soc/spi.h>
#include <soc/clock.h>
#include <console/console.h>
#include <spi_sdcard.h>

/* follow is the FSBL boot device defined by ZSBL of sifive
 * FSBL replaced by bootblock of coreboot
 * MSEL_SPInx1 -> test if boot from memory-mapped on SPIn
 * MSEL_SPInx4 -> test if boot from memory-mapped on QPIn
 * MSEL_SPInSD -> test if boot from sdcard mount on SPIn */
#define MSEL_SPI0x1(m)	(((m) == 5) || ((m) == 14))
#define MSEL_SPI0x4(m)	(((m) == 6) || ((m) == 10) || ((m) == 15))
#define MSEL_SPI1x1(m)	((m) == 12)
#define MSEL_SPI1x4(m)	(((m) == 7) || ((m) == 13))
#define MSEL_SPI1SD(m)	((m) ==  8)
#define MSEL_SPI2x1(m)	((m) ==  9)
#define MSEL_SPI2SD(m)	((m) == 11)

static struct spi_sdcard card;

/* At 0x20000000: A 256MiB long memory-mapped view of the flash at QSPI0 */
static struct mem_region_device spi_mdev =
	MEM_REGION_DEV_RO_INIT((void *)0x20000000, CONFIG_ROM_SIZE);

static ssize_t unleashed_sd_readat(const struct region_device *rdev, void *dest,
					size_t offset, size_t count)
{
	spi_sdcard_read(&card, dest, offset, count);
	return count;
}

static const struct region_device_ops unleashed_sd_ops = {
	.mmap   = mmap_helper_rdev_mmap,
	.munmap = mmap_helper_rdev_munmap,
	.readat = unleashed_sd_readat,
};


static struct mmap_helper_region_device sd_mdev =
	MMAP_HELPER_REGION_INIT(&unleashed_sd_ops, 0, CONFIG_ROM_SIZE);

const struct region_device *boot_device_ro(void)
{
	uint32_t m = read32((uint32_t *)FU540_MSEL);
	if (MSEL_SPI0x1(m) || MSEL_SPI0x4(m))
		return &spi_mdev.rdev;
	if (MSEL_SPI2SD(m))
		return &sd_mdev.rdev;
	die("Wrong configuration of MSEL\n");
	return NULL;
}

const static struct fu540_spi_mmap_config spi_mmap_config = {
	.cmd_en = 1,
	.addr_len = 4,
	.pad_cnt = 6,
	.cmd_proto = FU540_SPI_PROTO_S,
	.addr_proto = FU540_SPI_PROTO_Q,
	.data_proto = FU540_SPI_PROTO_Q,
	.cmd_code = 0xec,
	.pad_code = 0
};

void boot_device_init(void)
{
	uint32_t m = read32((uint32_t *)FU540_MSEL);
	if (MSEL_SPI0x1(m) || MSEL_SPI0x4(m)) {
		struct spi_slave slave;
		/* initialize spi controller */
		spi_setup_slave(0, 0, &slave);
		/* map flash to memory space */
		fu540_spi_mmap(&slave, &spi_mmap_config);
		return;
	}
	if (MSEL_SPI2SD(m)) {
		spi_sdcard_init(&card, 2, 0);
		mmap_helper_device_init(&sd_mdev,
			_cbfs_cache, REGION_SIZE(cbfs_cache));
		return;
	}
	die("Wrong configuration of MSEL\n");
}