summaryrefslogtreecommitdiff
path: root/platform/generic/sifive/sifive_dev_platform.c
blob: 579d46516bbdcadf06b7814ca78a7a1eb873c71a (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
/*
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Copyright (c) 2026 SiFive Inc.
 */

#include <platform_override.h>
#include <sbi/sbi_hart.h>
#include <sbi/sbi_scratch.h>

/*
 * Instead of allocating individual PMP entries for each M-mode
 * MMIO driver, configure SMEPMP regions to grant R/W permission
 * to peripheral and system ports for all privilege modes.
 * Finer-grained access control is enforced by wgChecker rules.
 */
static int sifive_smepmp_setup(void)
{
	struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
	int rc;

	if (!sbi_hart_has_extension(scratch, SBI_HART_EXT_SMEPMP))
		return 0;

	/* Peripheral port region: 0 to 2GiB */
	rc = sbi_domain_root_add_memrange(0x0, 0x80000000, 0x80000000,
					  SBI_DOMAIN_MEMREGION_MMIO |
					  SBI_DOMAIN_MEMREGION_SHARED_SURW_MRW);
	if (rc)
		return rc;

#if __riscv_xlen > 32
	/* System port region: 512GiB to 1TiB */
	rc = sbi_domain_root_add_memrange(0x8000000000ULL, 0x8000000000ULL, 0x8000000000ULL,
					  SBI_DOMAIN_MEMREGION_MMIO |
					  SBI_DOMAIN_MEMREGION_SHARED_SURW_MRW);
	if (rc)
		return rc;
#endif

	return 0;
}

static int sifive_early_init(bool cold_boot)
{
	int rc;

	if (cold_boot) {
		rc = sifive_smepmp_setup();
		if (rc)
			return rc;
	}

	return generic_early_init(cold_boot);
}

static int sifive_platform_init(const void *fdt, int nodeoff,
				const struct fdt_match *match)
{
	generic_platform_ops.early_init = sifive_early_init;

	return 0;
}

static const struct fdt_match sifive_dev_platform_match[] = {
	{ .compatible = "sifive-dev" },
	{ },
};

const struct fdt_driver sifive_dev_platform = {
	.match_table = sifive_dev_platform_match,
	.init = sifive_platform_init,
};