1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * u-boot/board/socionext/developerbox/developerbox.c
4  *
5  * Copyright (C) 2016-2017 Socionext Inc.
6  * Copyright (C) 2021 Linaro Ltd.
7  */
8 #include <asm/types.h>
9 #include <asm/armv8/mmu.h>
10 #include <asm/global_data.h>
11 #include <asm/io.h>
12 #include <common.h>
13 #include <env_internal.h>
14 #include <fdt_support.h>
15 #include <log.h>
16 
17 static struct mm_region sc2a11_mem_map[] = {
18 	{
19 		.virt = 0x0UL,
20 		.phys = 0x0UL,
21 		.size = 0x80000000UL,
22 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
23 			 PTE_BLOCK_OUTER_SHARE
24 	}, {
25 		/* 1st DDR block */
26 		.virt = 0x80000000UL,
27 		.phys = 0x80000000UL,
28 		.size = PHYS_SDRAM_SIZE,
29 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
30 			 PTE_BLOCK_OUTER_SHARE
31 	}, {
32 		/* 2nd DDR place holder */
33 		0,
34 	}, {
35 		/* 3rd DDR place holder */
36 		0,
37 	}, {
38 		/* List terminator */
39 		0,
40 	}
41 };
42 
43 struct mm_region *mem_map = sc2a11_mem_map;
44 
45 #define DDR_REGION_INDEX(i)	(1 + (i))
46 #define MAX_DDR_REGIONS		3
47 
48 struct draminfo_entry {
49 	u64	base;
50 	u64	size;
51 };
52 
53 struct draminfo {
54 	u32	nr_regions;
55 	u32	reserved;
56 	struct draminfo_entry	entry[3];
57 };
58 
59 struct draminfo *synquacer_draminfo = (void *)SQ_DRAMINFO_BASE;
60 
61 DECLARE_GLOBAL_DATA_PTR;
62 
63 #define LOAD_OFFSET 0x100
64 
65 /* SCBM System MMU is used for eMMC and NETSEC */
66 #define SCBM_SMMU_ADDR				(0x52e00000UL)
67 #define SMMU_SCR0_OFFS				(0x0)
68 #define SMMU_SCR0_SHCFG_INNER			(0x2 << 22)
69 #define SMMU_SCR0_MTCFG				(0x1 << 20)
70 #define SMMU_SCR0_MEMATTR_INNER_OUTER_WB	(0xf << 16)
71 
synquacer_setup_scbm_smmu(void)72 static void synquacer_setup_scbm_smmu(void)
73 {
74 	writel(SMMU_SCR0_SHCFG_INNER | SMMU_SCR0_MTCFG | SMMU_SCR0_MEMATTR_INNER_OUTER_WB,
75 	       SCBM_SMMU_ADDR + SMMU_SCR0_OFFS);
76 }
77 
78 /*
79  * Miscellaneous platform dependent initialisations
80  */
board_init(void)81 int board_init(void)
82 {
83 	gd->bd->bi_boot_params = CONFIG_SYS_LOAD_ADDR + LOAD_OFFSET;
84 
85 	synquacer_setup_scbm_smmu();
86 
87 	return 0;
88 }
89 
ft_board_setup(void * blob,struct bd_info * bd)90 int ft_board_setup(void *blob, struct bd_info *bd)
91 {
92 	/* Remove SPI NOR and I2C0 for making DT compatible with EDK2 */
93 	fdt_del_node_and_alias(blob, "spi_nor");
94 	fdt_del_node_and_alias(blob, "i2c0");
95 
96 	return 0;
97 }
98 
99 /*
100  * DRAM configuration
101  */
102 
dram_init(void)103 int dram_init(void)
104 {
105 	struct draminfo_entry *ent = synquacer_draminfo->entry;
106 	struct mm_region *mr;
107 	int i, ri;
108 
109 	if (synquacer_draminfo->nr_regions < 1) {
110 		log_err("Failed to get correct DRAM information\n");
111 		return -1;
112 	}
113 
114 	/*
115 	 * U-Boot RAM size must be under the first DRAM region so that it doesn't
116 	 * access secure memory which is at the end of the first DRAM region.
117 	 */
118 	gd->ram_size = ent[0].size;
119 
120 	/* Update memory region maps */
121 	for (i = 0; i < synquacer_draminfo->nr_regions; i++) {
122 		if (i >= MAX_DDR_REGIONS)
123 			break;
124 
125 		ri = DDR_REGION_INDEX(i);
126 		mem_map[ri].phys = ent[i].base;
127 		mem_map[ri].size = ent[i].size;
128 		if (i == 0)
129 			continue;
130 
131 		mr = &mem_map[DDR_REGION_INDEX(0)];
132 		mem_map[ri].virt = mr->virt + mr->size;
133 		mem_map[ri].attrs = mr->attrs;
134 	}
135 
136 	return 0;
137 }
138 
dram_init_banksize(void)139 int dram_init_banksize(void)
140 {
141 	struct draminfo_entry *ent = synquacer_draminfo->entry;
142 	int i;
143 
144 	for (i = 0; i < ARRAY_SIZE(gd->bd->bi_dram); i++) {
145 		if (i < synquacer_draminfo->nr_regions) {
146 			debug("%s: dram[%d] = %llx@%llx\n", __func__, i, ent[i].size, ent[i].base);
147 			gd->bd->bi_dram[i].start = ent[i].base;
148 			gd->bd->bi_dram[i].size = ent[i].size;
149 		}
150 	}
151 
152 	return 0;
153 }
154 
print_cpuinfo(void)155 int print_cpuinfo(void)
156 {
157 	printf("CPU:   SC2A11:Cortex-A53 MPCore 24cores\n");
158 	return 0;
159 }
160