1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2022 ARM Limited
4 * (C) Copyright 2022 Linaro
5 * Rui Miguel Silva <rui.silva@linaro.org>
6 */
7
8#include <blk.h>
9#include <common.h>
10#include <cpu_func.h>
11#include <dm.h>
12#include <env.h>
13#include <fwu.h>
14#include <netdev.h>
15#include <nvmxip.h>
16#include <part.h>
17#include <dm/platform_data/serial_pl01x.h>
18#include <asm/armv8/mmu.h>
19#include <asm/global_data.h>
20
21#define CORSTONE1000_KERNEL_PARTS 2
22#define CORSTONE1000_KERNEL_PRIMARY "kernel_primary"
23#define CORSTONE1000_KERNEL_SECONDARY "kernel_secondary"
24
25static int corstone1000_boot_idx;
26
27static struct mm_region corstone1000_mem_map[] = {
28	{
29		/* CVM */
30		.virt = 0x02000000UL,
31		.phys = 0x02000000UL,
32		.size = 0x02000000UL,
33		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
34			PTE_BLOCK_INNER_SHARE
35	}, {
36		/* QSPI */
37		.virt = 0x08000000UL,
38		.phys = 0x08000000UL,
39		.size = 0x08000000UL,
40		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
41			PTE_BLOCK_INNER_SHARE
42	}, {
43		/* Host Peripherals */
44		.virt = 0x1A000000UL,
45		.phys = 0x1A000000UL,
46		.size = 0x26000000UL,
47		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
48			PTE_BLOCK_NON_SHARE |
49			PTE_BLOCK_PXN | PTE_BLOCK_UXN
50	}, {
51		/* USB */
52		.virt = 0x40200000UL,
53		.phys = 0x40200000UL,
54		.size = 0x00100000UL,
55		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
56			PTE_BLOCK_NON_SHARE |
57			PTE_BLOCK_PXN | PTE_BLOCK_UXN
58	}, {
59		/* ethernet */
60		.virt = 0x40100000UL,
61		.phys = 0x40100000UL,
62		.size = 0x00100000UL,
63		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
64			PTE_BLOCK_NON_SHARE |
65			PTE_BLOCK_PXN | PTE_BLOCK_UXN
66	}, {
67		/* OCVM */
68		.virt = 0x80000000UL,
69		.phys = 0x80000000UL,
70		.size = 0x80000000UL,
71		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
72			PTE_BLOCK_INNER_SHARE
73	}, {
74		/* List terminator */
75		0,
76	}
77};
78
79struct mm_region *mem_map = corstone1000_mem_map;
80
81int board_init(void)
82{
83	return 0;
84}
85
86int dram_init(void)
87{
88	gd->ram_size = PHYS_SDRAM_1_SIZE;
89
90	return 0;
91}
92
93int dram_init_banksize(void)
94{
95	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
96	gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
97
98	return 0;
99}
100
101void fwu_plat_get_bootidx(uint *boot_idx)
102{
103	int ret;
104
105	/*
106	 * in our platform, the Secure Enclave is the one who controls
107	 * all the boot tries and status, so, every time we get here
108	 * we know that the we are booting from the active index
109	 */
110	ret = fwu_get_active_index(boot_idx);
111	if (ret < 0) {
112		*boot_idx = CONFIG_FWU_NUM_BANKS;
113		log_err("corstone1000: failed to read active index\n");
114	}
115}
116
117int board_late_init(void)
118{
119	struct disk_partition part_info;
120	struct udevice *dev, *bdev;
121	struct nvmxip_plat *plat;
122	struct blk_desc *desc;
123	int ret;
124
125	ret = uclass_first_device_err(UCLASS_NVMXIP, &dev);
126	if (ret < 0) {
127		log_err("Cannot find kernel device\n");
128		return ret;
129	}
130
131	plat = dev_get_plat(dev);
132	device_find_first_child(dev, &bdev);
133	desc = dev_get_uclass_plat(bdev);
134	ret = fwu_get_active_index(&corstone1000_boot_idx);
135	if (ret < 0) {
136		log_err("corstone1000: failed to read boot index\n");
137		return ret;
138	}
139
140	if (!corstone1000_boot_idx)
141		ret = part_get_info_by_name(desc, CORSTONE1000_KERNEL_PRIMARY,
142					    &part_info);
143	else
144		ret = part_get_info_by_name(desc, CORSTONE1000_KERNEL_SECONDARY,
145					    &part_info);
146
147	if (ret < 0) {
148		log_err("failed to fetch kernel partition index: %d\n",
149			corstone1000_boot_idx);
150		return ret;
151	}
152
153	ret = 0;
154
155	ret |= env_set_hex("kernel_addr", plat->phys_base +
156			   (part_info.start * part_info.blksz));
157	ret |= env_set_hex("kernel_size", part_info.size * part_info.blksz);
158
159	if (ret < 0)
160		log_err("failed to setup kernel addr and size\n");
161
162	return ret;
163}
164