summaryrefslogtreecommitdiff
path: root/board/armltd/vexpress64/vexpress64.c
blob: 20db81222e796b80ca2d988b377457807b05ced1 (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
150
/*
 * (C) Copyright 2013
 * David Feng <fenghua@phytium.com.cn>
 * Sharma Bhupesh <bhupesh.sharma@freescale.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */
#include <common.h>
#include <malloc.h>
#include <errno.h>
#include <netdev.h>
#include <asm/io.h>
#include <linux/compiler.h>
#include <asm/semihosting.h>

DECLARE_GLOBAL_DATA_PTR;

int board_init(void)
{
	return 0;
}

int dram_init(void)
{
	/*
	 * Clear spin table so that secondary processors
	 * observe the correct value after waken up from wfe.
	 */
	*(unsigned long *)CPU_RELEASE_ADDR = 0;

	gd->ram_size = PHYS_SDRAM_1_SIZE;
	return 0;
}

/*
 * Board specific reset that is system reset.
 */
void reset_cpu(ulong addr)
{
}

#ifdef CONFIG_BOARD_LATE_INIT
int board_late_init(void)
{
#ifdef CONFIG_SEMIHOSTING
	/*
	 * Please refer to doc/README.semihosting for a more complete
	 * description.
	 *
	 * We require that the board include file defines these env variables:
	 * - kernel_name
	 * - kernel_addr_r
	 * - initrd_name
	 * - initrd_addr_r
	 * - fdt_name
	 * - fdt_addr_r
	 *
	 * For the "fdt chosen" startup macro, this code will then define:
	 * - initrd_end (based on initrd_addr_r plus actual initrd_size)
	 *
	 * We will then load the kernel, initrd, and fdt into the specified
	 * locations in memory in a similar way that the ATF fastmodel code
	 * uses semihosting calls to load other boot stages and u-boot itself.
	 */

	/* Env variable strings */
	char *kernel_name = getenv("kernel_name");
	char *kernel_addr_str = getenv("kernel_addr_r");
	char *initrd_name = getenv("initrd_name");
	char *initrd_addr_str = getenv("initrd_addr_r");
	char *fdt_name = getenv("fdt_name");
	char *fdt_addr_str = getenv("fdt_addr_r");
	char initrd_end_str[64];

	/* Actual addresses converted from env variables */
	void *kernel_addr_r;
	void *initrd_addr_r;
	void *fdt_addr_r;

	/* Actual initrd base and size */
	unsigned long initrd_base;
	unsigned long initrd_size;

	/* Space available */
	int avail;

	/* Make sure the environment variables needed are set */
	if (!(kernel_addr_str && initrd_addr_str && fdt_addr_str)) {
		printf("%s: Define {kernel/initrd/fdt}_addr_r\n", __func__);
		return -1;
	}
	if (!(kernel_name && initrd_name && fdt_name)) {
		printf("%s: Define {kernel/initrd/fdt}_name\n", __func__);
		return -1;
	}

	/* Get exact initrd_size */
	initrd_size = smh_len(initrd_name);
	if (initrd_size == -1) {
		printf("%s: Can't get file size for \'%s\'\n", __func__,
		       initrd_name);
		return -1;
	}

	/* Set initrd_end */
	initrd_base = simple_strtoul(initrd_addr_str, NULL, 16);
	initrd_addr_r = (void *)initrd_base;
	sprintf(initrd_end_str, "0x%lx", initrd_base + initrd_size - 1);
	setenv("initrd_end", initrd_end_str);

	/* Load kernel to memory */
	fdt_addr_r = (void *)simple_strtoul(fdt_addr_str, NULL, 16);
	kernel_addr_r = (void *)simple_strtoul(kernel_addr_str, NULL, 16);

	/*
	 * The kernel must be lower in memory than fdt and loading the
	 * kernel must not trample the fdt or vice versa.
	 */
	avail = fdt_addr_r - kernel_addr_r;
	if (avail < 0) {
		printf("%s: fdt must be after kernel\n", __func__);
		return -1;
	}
	smh_load(kernel_name, kernel_addr_r, avail, 1);

	/* Load fdt to memory */
	smh_load(fdt_name, fdt_addr_r, 0x20000, 1);

	/* Load initrd to memory */
	smh_load(initrd_name, initrd_addr_r, initrd_size, 1);

#endif				/* CONFIG_SEMIHOSTING */
	return 0;
}
#endif				/* CONFIG_BOARD_LATE_INIT */

/*
 * Board specific ethernet initialization routine.
 */
int board_eth_init(bd_t *bis)
{
	int rc = 0;
#ifdef CONFIG_SMC91111
	rc = smc91111_initialize(0, CONFIG_SMC91111_BASE);
#endif
#ifdef CONFIG_SMC911X
	rc = smc911x_initialize(0, CONFIG_SMC911X_BASE);
#endif
	return rc;
}