xref: /openbmc/u-boot/board/broadcom/bcmstb/bcmstb.c (revision 12308b12)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2018  Cisco Systems, Inc.
4  *
5  * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
6  */
7 
8 #include <linux/types.h>
9 #include <common.h>
10 #include <asm/io.h>
11 #include <asm/bootm.h>
12 #include <mach/sdhci.h>
13 #include <mach/timer.h>
14 #include <mmc.h>
15 #include <fdtdec.h>
16 
17 DECLARE_GLOBAL_DATA_PTR;
18 
19 #define BCMSTB_DATA_SECTION __attribute__((section(".data")))
20 
21 struct bcmstb_boot_parameters bcmstb_boot_parameters BCMSTB_DATA_SECTION;
22 
23 phys_addr_t prior_stage_fdt_address BCMSTB_DATA_SECTION;
24 
25 union reg_value_union {
26 	const char *data;
27 	const phys_addr_t *address;
28 };
29 
board_init(void)30 int board_init(void)
31 {
32 	return 0;
33 }
34 
get_board_rev(void)35 u32 get_board_rev(void)
36 {
37 	return 0;
38 }
39 
reset_cpu(ulong ignored)40 void reset_cpu(ulong ignored)
41 {
42 }
43 
print_cpuinfo(void)44 int print_cpuinfo(void)
45 {
46 	return 0;
47 }
48 
dram_init(void)49 int dram_init(void)
50 {
51 	if (fdtdec_setup_mem_size_base() != 0)
52 		return -EINVAL;
53 
54 	return 0;
55 }
56 
dram_init_banksize(void)57 int dram_init_banksize(void)
58 {
59 	fdtdec_setup_memory_banksize();
60 
61 	/*
62 	 * On this SoC, U-Boot is running as an ELF file.  Change the
63 	 * relocation address to CONFIG_SYS_TEXT_BASE, so that in
64 	 * setup_reloc, gd->reloc_off works out to 0, effectively
65 	 * disabling relocation.  Otherwise U-Boot hangs in the setup
66 	 * instructions just before relocate_code in
67 	 * arch/arm/lib/crt0.S.
68 	 */
69 	gd->relocaddr = CONFIG_SYS_TEXT_BASE;
70 
71 	return 0;
72 }
73 
enable_caches(void)74 void enable_caches(void)
75 {
76 	/*
77 	 * This port assumes that the prior stage bootloader has
78 	 * enabled I-cache and D-cache already.  Implementing this
79 	 * function silences the warning in the default function.
80 	 */
81 }
82 
bcmstb_sdhci_address(u32 alias_index)83 static const phys_addr_t bcmstb_sdhci_address(u32 alias_index)
84 {
85 	int node = 0;
86 	int ret = 0;
87 	char sdhci[16] = { 0 };
88 	const void *fdt = gd->fdt_blob;
89 	const char *path = NULL;
90 	struct fdt_resource resource = { 0 };
91 
92 	if (!fdt) {
93 		printf("%s: Invalid gd->fdt_blob\n", __func__);
94 		return 0;
95 	}
96 
97 	node = fdt_path_offset(fdt, "/aliases");
98 	if (node < 0) {
99 		printf("%s: Failed to find /aliases node\n", __func__);
100 		return 0;
101 	}
102 
103 	sprintf(sdhci, "sdhci%d", alias_index);
104 	path = fdt_getprop(fdt, node, sdhci, NULL);
105 	if (!path) {
106 		printf("%s: Failed to find alias for %s\n", __func__, sdhci);
107 		return 0;
108 	}
109 
110 	node = fdt_path_offset(fdt, path);
111 	if (node < 0) {
112 		printf("%s: Failed to resolve BCMSTB SDHCI alias\n", __func__);
113 		return 0;
114 	}
115 
116 	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
117 				     "host", &resource);
118 	if (ret) {
119 		printf("%s: Failed to read BCMSTB SDHCI host resource\n",
120 		       __func__);
121 		return 0;
122 	}
123 
124 	return resource.start;
125 }
126 
board_mmc_init(bd_t * bis)127 int board_mmc_init(bd_t *bis)
128 {
129 	phys_addr_t sdhci_base_address = 0;
130 
131 	sdhci_base_address = bcmstb_sdhci_address(CONFIG_BCMSTB_SDHCI_INDEX);
132 
133 	if (!sdhci_base_address) {
134 		sdhci_base_address = BCMSTB_SDHCI_BASE;
135 		printf("%s: Assuming BCMSTB SDHCI address: 0x%p\n",
136 		       __func__, (void *)sdhci_base_address);
137 	}
138 
139 	debug("BCMSTB SDHCI base address: 0x%p\n", (void *)sdhci_base_address);
140 
141 	bcmstb_sdhci_init(sdhci_base_address);
142 
143 	return 0;
144 }
145 
timer_init(void)146 int timer_init(void)
147 {
148 	gd->arch.timer_rate_hz = readl(BCMSTB_TIMER_FREQUENCY);
149 
150 	return 0;
151 }
152 
get_tbclk(void)153 ulong get_tbclk(void)
154 {
155 	return gd->arch.timer_rate_hz;
156 }
157 
get_ticks(void)158 uint64_t get_ticks(void)
159 {
160 	gd->timebase_h = readl(BCMSTB_TIMER_HIGH);
161 	gd->timebase_l = readl(BCMSTB_TIMER_LOW);
162 
163 	return ((uint64_t)gd->timebase_h << 32) | gd->timebase_l;
164 }
165 
board_late_init(void)166 int board_late_init(void)
167 {
168 	debug("Arguments from prior stage bootloader:\n");
169 	debug("General Purpose Register 0: 0x%x\n", bcmstb_boot_parameters.r0);
170 	debug("General Purpose Register 1: 0x%x\n", bcmstb_boot_parameters.r1);
171 	debug("General Purpose Register 2: 0x%x\n", bcmstb_boot_parameters.r2);
172 	debug("General Purpose Register 3: 0x%x\n", bcmstb_boot_parameters.r3);
173 	debug("Stack Pointer Register:     0x%x\n", bcmstb_boot_parameters.sp);
174 	debug("Link Register:              0x%x\n", bcmstb_boot_parameters.lr);
175 	debug("Assuming timer frequency register at: 0x%p\n",
176 	      (void *)BCMSTB_TIMER_FREQUENCY);
177 	debug("Read timer frequency (in Hz): %ld\n", gd->arch.timer_rate_hz);
178 	debug("Prior stage provided DTB at: 0x%p\n",
179 	      (void *)prior_stage_fdt_address);
180 
181 	/*
182 	 * Set fdtcontroladdr in the environment so that scripts can
183 	 * refer to it, for example, to reuse it for fdtaddr.
184 	 */
185 	env_set_hex("fdtcontroladdr", prior_stage_fdt_address);
186 
187 	/*
188 	 * Do not set machid to the machine identifier value provided
189 	 * by the prior stage bootloader (bcmstb_boot_parameters.r1)
190 	 * because we're using a device tree to boot Linux.
191 	 */
192 
193 	return 0;
194 }
195