aboutsummaryrefslogtreecommitdiff
path: root/platform/generic/openhwgroup/openpiton.c
blob: 60d719e15ceb57ff6c645c77fe49f283b165fa1a (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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// SPDX-License-Identifier: BSD-2-Clause
/*
 * Copyright (c) 2020 Western Digital Corporation or its affiliates.
 */

#include <platform_override.h>
#include <sbi_utils/fdt/fdt_helper.h>
#include <sbi_utils/fdt/fdt_fixup.h>
#include <sbi_utils/ipi/aclint_mswi.h>
#include <sbi_utils/irqchip/plic.h>
#include <sbi_utils/timer/aclint_mtimer.h>

#define OPENPITON_DEFAULT_PLIC_ADDR		0xfff1100000ULL
#define OPENPITON_DEFAULT_PLIC_SIZE		(0x200000 + \
				(OPENPITON_DEFAULT_HART_COUNT * 0x1000))
#define OPENPITON_DEFAULT_PLIC_NUM_SOURCES	2
#define OPENPITON_DEFAULT_HART_COUNT		3
#define OPENPITON_DEFAULT_CLINT_ADDR		0xfff1020000ULL
#define OPENPITON_DEFAULT_ACLINT_MTIMER_FREQ	1000000
#define OPENPITON_DEFAULT_ACLINT_MSWI_ADDR	\
		(OPENPITON_DEFAULT_CLINT_ADDR + CLINT_MSWI_OFFSET)
#define OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR	\
		(OPENPITON_DEFAULT_CLINT_ADDR + CLINT_MTIMER_OFFSET)

static struct plic_data plic = {
	.addr = (unsigned long)OPENPITON_DEFAULT_PLIC_ADDR,
	.size = OPENPITON_DEFAULT_PLIC_SIZE,
	.num_src = OPENPITON_DEFAULT_PLIC_NUM_SOURCES,
	.flags = PLIC_FLAG_ARIANE_BUG,
	.context_map = {
		[0] = { 0, 1 },
		[1] = { 2, 3 },
		[2] = { 4, 5 },
	},
};

static struct aclint_mswi_data mswi = {
	.addr = (unsigned long)OPENPITON_DEFAULT_ACLINT_MSWI_ADDR,
	.size = ACLINT_MSWI_SIZE,
	.first_hartid = 0,
	.hart_count = OPENPITON_DEFAULT_HART_COUNT,
};

static struct aclint_mtimer_data mtimer = {
	.mtime_freq = OPENPITON_DEFAULT_ACLINT_MTIMER_FREQ,
	.mtime_addr = (unsigned long)OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
		      ACLINT_DEFAULT_MTIME_OFFSET,
	.mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
	.mtimecmp_addr = (unsigned long)OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
			 ACLINT_DEFAULT_MTIMECMP_OFFSET,
	.mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
	.first_hartid = 0,
	.hart_count = OPENPITON_DEFAULT_HART_COUNT,
	.has_64bit_mmio = true,
};

/*
 * OpenPiton platform early initialization.
 */
static int openpiton_early_init(bool cold_boot)
{
	const void *fdt;
	struct plic_data plic_data = plic;
	unsigned long aclint_freq;
	uint64_t clint_addr;
	int rc;

	if (!cold_boot)
		return 0;
	fdt = fdt_get_address();

	rc = generic_early_init(cold_boot);
	if (rc)
		return rc;

	rc = fdt_parse_plic(fdt, &plic_data, "riscv,plic0");
	if (!rc)
		plic = plic_data;

	rc = fdt_parse_timebase_frequency(fdt, &aclint_freq);
	if (!rc)
		mtimer.mtime_freq = aclint_freq;

	rc = fdt_parse_compat_addr(fdt, &clint_addr, "riscv,clint0");
	if (!rc) {
		mswi.addr = clint_addr;
		mtimer.mtime_addr = clint_addr + CLINT_MTIMER_OFFSET +
				    ACLINT_DEFAULT_MTIME_OFFSET;
		mtimer.mtimecmp_addr = clint_addr + CLINT_MTIMER_OFFSET +
				    ACLINT_DEFAULT_MTIMECMP_OFFSET;
	}

	if (rc)
		return rc;

	return aclint_mswi_cold_init(&mswi);
}

/*
 * OpenPiton platform final initialization.
 */
static int openpiton_final_init(bool cold_boot)
{
	void *fdt;

	if (!cold_boot)
		return 0;

	fdt = fdt_get_address_rw();
	fdt_fixups(fdt);

	return 0;
}

/*
 * Initialize the openpiton interrupt controller during cold boot.
 */
static int openpiton_irqchip_init(void)
{
	return plic_cold_irqchip_init(&plic);
}

/*
 * Initialize openpiton timer during cold boot.
 */
static int openpiton_timer_init(void)
{
	return aclint_mtimer_cold_init(&mtimer, NULL);
}

static int openhwgroup_openpiton_platform_init(const void *fdt, int nodeoff, const struct fdt_match *match)
{
	generic_platform_ops.early_init = openpiton_early_init;
	generic_platform_ops.timer_init = openpiton_timer_init;
	generic_platform_ops.irqchip_init = openpiton_irqchip_init;
	generic_platform_ops.final_init = openpiton_final_init;

	return 0;
}

static const struct fdt_match openhwgroup_openpiton_match[] = {
	{ .compatible = "openpiton,cva6platform" },
	{ },
};

const struct fdt_driver openhwgroup_openpiton = {
	.match_table = openhwgroup_openpiton_match,
	.init = openhwgroup_openpiton_platform_init,
};