blob: 04f27b4b8f420b32d9ef842dbd445dfa5cdcf04e [file] [log] [blame]
Stephen Warren0d04f342012-08-05 16:07:22 +00001/*
Stephen Warrenf031f502016-03-24 22:15:20 -06002 * (C) Copyright 2012-2016 Stephen Warren
Stephen Warren0d04f342012-08-05 16:07:22 +00003 *
Stephen Warrena0331712015-02-16 12:16:13 -07004 * SPDX-License-Identifier: GPL-2.0
Stephen Warren0d04f342012-08-05 16:07:22 +00005 */
6
7#include <common.h>
Lubomir Rintel757cd142016-02-22 22:06:47 +01008#include <inttypes.h>
Stephen Warrenea697ae2013-05-27 18:31:18 +00009#include <config.h>
Simon Glass41e98e02014-09-22 17:30:56 -060010#include <dm.h>
Jeroen Hofstee5dfd1622014-07-13 22:01:51 +020011#include <fdt_support.h>
Nikita Kiryanov033167c2015-02-03 13:32:31 +020012#include <fdt_simplefb.h>
Stephen Warrenea697ae2013-05-27 18:31:18 +000013#include <lcd.h>
Simon Glasscf92e052015-09-02 17:24:58 -060014#include <memalign.h>
Jeroen Hofstee5dfd1622014-07-13 22:01:51 +020015#include <mmc.h>
Simon Glass41e98e02014-09-22 17:30:56 -060016#include <asm/gpio.h>
Stephen Warren3f397782013-01-29 16:37:37 +000017#include <asm/arch/mbox.h>
Stephen Warren131a1e62013-01-29 16:37:42 +000018#include <asm/arch/sdhci.h>
Stephen Warren0d04f342012-08-05 16:07:22 +000019#include <asm/global_data.h>
Stephen Warrenf031f502016-03-24 22:15:20 -060020#include <dm/platform_data/serial_bcm283x_mu.h>
Stephen Warrend22a7652016-04-01 21:14:15 -060021#ifdef CONFIG_ARM64
22#include <asm/armv8/mmu.h>
23#endif
Stephen Warren0d04f342012-08-05 16:07:22 +000024
25DECLARE_GLOBAL_DATA_PTR;
26
Cédric Schieliade243a2016-11-11 11:59:07 +010027/* From lowlevel_init.S */
28extern unsigned long fw_dtb_pointer;
29
Simon Glass11506662014-11-24 21:36:34 -070030
Stephen Warren3f397782013-01-29 16:37:37 +000031struct msg_get_arm_mem {
32 struct bcm2835_mbox_hdr hdr;
33 struct bcm2835_mbox_tag_get_arm_mem get_arm_mem;
34 u32 end_tag;
35};
36
Stephen Warren6fe78452014-11-18 21:40:21 -070037struct msg_get_board_rev {
38 struct bcm2835_mbox_hdr hdr;
39 struct bcm2835_mbox_tag_get_board_rev get_board_rev;
40 u32 end_tag;
41};
42
Lubomir Rintel757cd142016-02-22 22:06:47 +010043struct msg_get_board_serial {
44 struct bcm2835_mbox_hdr hdr;
45 struct bcm2835_mbox_tag_get_board_serial get_board_serial;
46 u32 end_tag;
47};
48
Stephen Warren4f80a062014-09-26 20:51:39 -060049struct msg_get_mac_address {
50 struct bcm2835_mbox_hdr hdr;
51 struct bcm2835_mbox_tag_get_mac_address get_mac_address;
52 u32 end_tag;
53};
54
Stephen Warrenf66f2aa2014-01-13 19:50:11 -070055struct msg_set_power_state {
56 struct bcm2835_mbox_hdr hdr;
57 struct bcm2835_mbox_tag_set_power_state set_power_state;
58 u32 end_tag;
59};
60
Stephen Warren131a1e62013-01-29 16:37:42 +000061struct msg_get_clock_rate {
62 struct bcm2835_mbox_hdr hdr;
63 struct bcm2835_mbox_tag_get_clock_rate get_clock_rate;
64 u32 end_tag;
65};
66
Stephen Warrendbe6f1e2015-12-04 22:07:44 -070067/*
68 * http://raspberryalphaomega.org.uk/2013/02/06/automatic-raspberry-pi-board-revision-detection-model-a-b1-and-b2/
69 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=32733
Stephen Warrenc4ea1ed2015-12-04 22:07:45 -070070 * http://git.drogon.net/?p=wiringPi;a=blob;f=wiringPi/wiringPi.c;h=503151f61014418b9c42f4476a6086f75cd4e64b;hb=refs/heads/master#l922
Stephen Warrendba060c2016-01-28 22:24:44 -070071 *
72 * In http://lists.denx.de/pipermail/u-boot/2016-January/243752.html
73 * ("[U-Boot] [PATCH] rpi: fix up Model B entries") Dom Cobley at the RPi
74 * Foundation stated that the following source was accurate:
75 * https://github.com/AndrewFromMelbourne/raspberry_pi_revision
Stephen Warrendbe6f1e2015-12-04 22:07:44 -070076 */
Stephen Warrenc4ea1ed2015-12-04 22:07:45 -070077struct rpi_model {
Stephen Warren6fe78452014-11-18 21:40:21 -070078 const char *name;
79 const char *fdtfile;
Stephen Warren3207d8f2014-12-05 20:56:46 -070080 bool has_onboard_eth;
Stephen Warrenc4ea1ed2015-12-04 22:07:45 -070081};
82
83static const struct rpi_model rpi_model_unknown = {
84 "Unknown model",
Stephen Warren29937ca2016-03-24 22:15:17 -060085 "bcm283x-rpi-other.dtb",
Stephen Warrenc4ea1ed2015-12-04 22:07:45 -070086 false,
87};
88
89static const struct rpi_model rpi_models_new_scheme[] = {
Stephen Warrendbe6f1e2015-12-04 22:07:44 -070090 [0x4] = {
Stephen Warren46414292015-02-16 12:16:15 -070091 "2 Model B",
92 "bcm2836-rpi-2-b.dtb",
93 true,
94 },
Stephen Warren7233fb32016-03-24 22:15:18 -060095 [0x8] = {
96 "3 Model B",
97 "bcm2837-rpi-3-b.dtb",
98 true,
99 },
Stephen Warrenaf7c03e2015-12-04 22:07:46 -0700100 [0x9] = {
101 "Zero",
102 "bcm2835-rpi-zero.dtb",
103 false,
104 },
Stephen Warrenc4ea1ed2015-12-04 22:07:45 -0700105};
106
107static const struct rpi_model rpi_models_old_scheme[] = {
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700108 [0x2] = {
Lubomir Rintel7443a9c2016-01-29 09:35:52 +0100109 "Model B",
110 "bcm2835-rpi-b.dtb",
Stephen Warren3207d8f2014-12-05 20:56:46 -0700111 true,
Stephen Warren6fe78452014-11-18 21:40:21 -0700112 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700113 [0x3] = {
Lubomir Rintel7443a9c2016-01-29 09:35:52 +0100114 "Model B",
115 "bcm2835-rpi-b.dtb",
Stephen Warren3207d8f2014-12-05 20:56:46 -0700116 true,
Stephen Warren6fe78452014-11-18 21:40:21 -0700117 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700118 [0x4] = {
Lubomir Rintel7443a9c2016-01-29 09:35:52 +0100119 "Model B rev2",
120 "bcm2835-rpi-b-rev2.dtb",
Stephen Warren3207d8f2014-12-05 20:56:46 -0700121 true,
Stephen Warren6fe78452014-11-18 21:40:21 -0700122 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700123 [0x5] = {
Lubomir Rintel7443a9c2016-01-29 09:35:52 +0100124 "Model B rev2",
125 "bcm2835-rpi-b-rev2.dtb",
Stephen Warren3207d8f2014-12-05 20:56:46 -0700126 true,
Stephen Warren6fe78452014-11-18 21:40:21 -0700127 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700128 [0x6] = {
Lubomir Rintel7443a9c2016-01-29 09:35:52 +0100129 "Model B rev2",
130 "bcm2835-rpi-b-rev2.dtb",
Stephen Warren3207d8f2014-12-05 20:56:46 -0700131 true,
Stephen Warren6fe78452014-11-18 21:40:21 -0700132 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700133 [0x7] = {
Stephen Warren6fe78452014-11-18 21:40:21 -0700134 "Model A",
135 "bcm2835-rpi-a.dtb",
Stephen Warren3207d8f2014-12-05 20:56:46 -0700136 false,
Stephen Warren6fe78452014-11-18 21:40:21 -0700137 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700138 [0x8] = {
Stephen Warren6fe78452014-11-18 21:40:21 -0700139 "Model A",
140 "bcm2835-rpi-a.dtb",
Stephen Warren3207d8f2014-12-05 20:56:46 -0700141 false,
Stephen Warren6fe78452014-11-18 21:40:21 -0700142 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700143 [0x9] = {
Stephen Warren6fe78452014-11-18 21:40:21 -0700144 "Model A",
145 "bcm2835-rpi-a.dtb",
Stephen Warren3207d8f2014-12-05 20:56:46 -0700146 false,
Stephen Warren6fe78452014-11-18 21:40:21 -0700147 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700148 [0xd] = {
Stephen Warren6fe78452014-11-18 21:40:21 -0700149 "Model B rev2",
150 "bcm2835-rpi-b-rev2.dtb",
Stephen Warren3207d8f2014-12-05 20:56:46 -0700151 true,
Stephen Warren6fe78452014-11-18 21:40:21 -0700152 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700153 [0xe] = {
Stephen Warren6fe78452014-11-18 21:40:21 -0700154 "Model B rev2",
155 "bcm2835-rpi-b-rev2.dtb",
Stephen Warren3207d8f2014-12-05 20:56:46 -0700156 true,
Stephen Warren6fe78452014-11-18 21:40:21 -0700157 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700158 [0xf] = {
Stephen Warren6fe78452014-11-18 21:40:21 -0700159 "Model B rev2",
160 "bcm2835-rpi-b-rev2.dtb",
Stephen Warren3207d8f2014-12-05 20:56:46 -0700161 true,
Stephen Warren6fe78452014-11-18 21:40:21 -0700162 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700163 [0x10] = {
Stephen Warren6fe78452014-11-18 21:40:21 -0700164 "Model B+",
165 "bcm2835-rpi-b-plus.dtb",
Stephen Warren3207d8f2014-12-05 20:56:46 -0700166 true,
Stephen Warren6fe78452014-11-18 21:40:21 -0700167 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700168 [0x11] = {
Stephen Warren6fe78452014-11-18 21:40:21 -0700169 "Compute Module",
170 "bcm2835-rpi-cm.dtb",
Stephen Warren3207d8f2014-12-05 20:56:46 -0700171 false,
Stephen Warren6fe78452014-11-18 21:40:21 -0700172 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700173 [0x12] = {
Stephen Warren47705ef2014-12-23 20:01:43 -0700174 "Model A+",
175 "bcm2835-rpi-a-plus.dtb",
176 false,
177 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700178 [0x13] = {
Stephen Warren787affb2015-04-12 21:43:25 -0600179 "Model B+",
180 "bcm2835-rpi-b-plus.dtb",
181 true,
182 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700183 [0x14] = {
Stephen Warren787affb2015-04-12 21:43:25 -0600184 "Compute Module",
185 "bcm2835-rpi-cm.dtb",
186 false,
187 },
Stephen Warrendbe6f1e2015-12-04 22:07:44 -0700188 [0x15] = {
Lubomir Rintel79ad5ce2015-10-14 17:17:54 +0200189 "Model A+",
190 "bcm2835-rpi-a-plus.dtb",
191 false,
192 },
Stephen Warren6fe78452014-11-18 21:40:21 -0700193};
194
Stephen Warrenc4ea1ed2015-12-04 22:07:45 -0700195static uint32_t revision;
196static uint32_t rev_scheme;
197static uint32_t rev_type;
198static const struct rpi_model *model;
Stephen Warren6fe78452014-11-18 21:40:21 -0700199
Stephen Warrend22a7652016-04-01 21:14:15 -0600200#ifdef CONFIG_ARM64
201static struct mm_region bcm2837_mem_map[] = {
202 {
York Suncd4b0c52016-06-24 16:46:22 -0700203 .virt = 0x00000000UL,
204 .phys = 0x00000000UL,
Stephen Warrend22a7652016-04-01 21:14:15 -0600205 .size = 0x3f000000UL,
206 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
207 PTE_BLOCK_INNER_SHARE
208 }, {
York Suncd4b0c52016-06-24 16:46:22 -0700209 .virt = 0x3f000000UL,
210 .phys = 0x3f000000UL,
Stephen Warrend22a7652016-04-01 21:14:15 -0600211 .size = 0x01000000UL,
212 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
213 PTE_BLOCK_NON_SHARE |
214 PTE_BLOCK_PXN | PTE_BLOCK_UXN
215 }, {
216 /* List terminator */
217 0,
218 }
219};
220
221struct mm_region *mem_map = bcm2837_mem_map;
222#endif
223
Stephen Warren0d04f342012-08-05 16:07:22 +0000224int dram_init(void)
225{
Alexander Stein927753a2015-07-24 09:22:12 +0200226 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_arm_mem, msg, 1);
Stephen Warren3f397782013-01-29 16:37:37 +0000227 int ret;
228
229 BCM2835_MBOX_INIT_HDR(msg);
230 BCM2835_MBOX_INIT_TAG(&msg->get_arm_mem, GET_ARM_MEMORY);
231
232 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
233 if (ret) {
234 printf("bcm2835: Could not query ARM memory size\n");
235 return -1;
236 }
237
238 gd->ram_size = msg->get_arm_mem.body.resp.mem_size;
Stephen Warren0d04f342012-08-05 16:07:22 +0000239
240 return 0;
241}
242
Stephen Warren6fe78452014-11-18 21:40:21 -0700243static void set_fdtfile(void)
244{
245 const char *fdtfile;
246
247 if (getenv("fdtfile"))
248 return;
249
Stephen Warrenc4ea1ed2015-12-04 22:07:45 -0700250 fdtfile = model->fdtfile;
Stephen Warren6fe78452014-11-18 21:40:21 -0700251 setenv("fdtfile", fdtfile);
252}
253
Cédric Schieliade243a2016-11-11 11:59:07 +0100254/*
255 * If the firmware provided a valid FDT at boot time, let's expose it in
256 * ${fdt_addr} so it may be passed unmodified to the kernel.
257 */
258static void set_fdt_addr(void)
259{
260 if (getenv("fdt_addr"))
261 return;
262
263 if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC)
264 return;
265
266 setenv_hex("fdt_addr", fw_dtb_pointer);
267}
268
269/*
270 * Prevent relocation from stomping on a firmware provided FDT blob.
271 */
272unsigned long board_get_usable_ram_top(unsigned long total_size)
273{
274 if ((gd->ram_top - fw_dtb_pointer) > SZ_64M)
275 return gd->ram_top;
276 return fw_dtb_pointer & ~0xffff;
277}
278
Stephen Warren6fe78452014-11-18 21:40:21 -0700279static void set_usbethaddr(void)
Stephen Warren4f80a062014-09-26 20:51:39 -0600280{
Alexander Stein927753a2015-07-24 09:22:12 +0200281 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_mac_address, msg, 1);
Stephen Warren4f80a062014-09-26 20:51:39 -0600282 int ret;
283
Stephen Warrenc4ea1ed2015-12-04 22:07:45 -0700284 if (!model->has_onboard_eth)
Stephen Warren3207d8f2014-12-05 20:56:46 -0700285 return;
286
Stephen Warren4f80a062014-09-26 20:51:39 -0600287 if (getenv("usbethaddr"))
Stephen Warren6fe78452014-11-18 21:40:21 -0700288 return;
Stephen Warren4f80a062014-09-26 20:51:39 -0600289
290 BCM2835_MBOX_INIT_HDR(msg);
291 BCM2835_MBOX_INIT_TAG(&msg->get_mac_address, GET_MAC_ADDRESS);
292
293 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
294 if (ret) {
295 printf("bcm2835: Could not query MAC address\n");
296 /* Ignore error; not critical */
Stephen Warren6fe78452014-11-18 21:40:21 -0700297 return;
Stephen Warren4f80a062014-09-26 20:51:39 -0600298 }
299
300 eth_setenv_enetaddr("usbethaddr", msg->get_mac_address.body.resp.mac);
301
Lubomir Rintel859f1432016-02-03 16:08:09 +0100302 if (!getenv("ethaddr"))
303 setenv("ethaddr", getenv("usbethaddr"));
304
Stephen Warren6fe78452014-11-18 21:40:21 -0700305 return;
306}
307
Guillaume GARDETbff78562015-08-25 15:10:26 +0200308#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
309static void set_board_info(void)
310{
Stephen Warrenc4ea1ed2015-12-04 22:07:45 -0700311 char s[11];
312
313 snprintf(s, sizeof(s), "0x%X", revision);
314 setenv("board_revision", s);
315 snprintf(s, sizeof(s), "%d", rev_scheme);
316 setenv("board_rev_scheme", s);
317 /* Can't rename this to board_rev_type since it's an ABI for scripts */
318 snprintf(s, sizeof(s), "0x%X", rev_type);
319 setenv("board_rev", s);
320 setenv("board_name", model->name);
Guillaume GARDETbff78562015-08-25 15:10:26 +0200321}
322#endif /* CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG */
323
Lubomir Rintel757cd142016-02-22 22:06:47 +0100324static void set_serial_number(void)
325{
326 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_serial, msg, 1);
327 int ret;
328 char serial_string[17] = { 0 };
329
330 if (getenv("serial#"))
331 return;
332
333 BCM2835_MBOX_INIT_HDR(msg);
334 BCM2835_MBOX_INIT_TAG_NO_REQ(&msg->get_board_serial, GET_BOARD_SERIAL);
335
336 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
337 if (ret) {
338 printf("bcm2835: Could not query board serial\n");
339 /* Ignore error; not critical */
340 return;
341 }
342
343 snprintf(serial_string, sizeof(serial_string), "%016" PRIx64,
344 msg->get_board_serial.body.resp.serial);
345 setenv("serial#", serial_string);
346}
347
Stephen Warren6fe78452014-11-18 21:40:21 -0700348int misc_init_r(void)
349{
Cédric Schieliade243a2016-11-11 11:59:07 +0100350 set_fdt_addr();
Stephen Warren6fe78452014-11-18 21:40:21 -0700351 set_fdtfile();
352 set_usbethaddr();
Guillaume GARDETbff78562015-08-25 15:10:26 +0200353#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
354 set_board_info();
355#endif
Lubomir Rintel757cd142016-02-22 22:06:47 +0100356 set_serial_number();
357
Stephen Warren4f80a062014-09-26 20:51:39 -0600358 return 0;
359}
360
Stephen Warrenf66f2aa2014-01-13 19:50:11 -0700361static int power_on_module(u32 module)
362{
Alexander Stein927753a2015-07-24 09:22:12 +0200363 ALLOC_CACHE_ALIGN_BUFFER(struct msg_set_power_state, msg_pwr, 1);
Stephen Warrenf66f2aa2014-01-13 19:50:11 -0700364 int ret;
365
366 BCM2835_MBOX_INIT_HDR(msg_pwr);
367 BCM2835_MBOX_INIT_TAG(&msg_pwr->set_power_state,
368 SET_POWER_STATE);
369 msg_pwr->set_power_state.body.req.device_id = module;
370 msg_pwr->set_power_state.body.req.state =
371 BCM2835_MBOX_SET_POWER_STATE_REQ_ON |
372 BCM2835_MBOX_SET_POWER_STATE_REQ_WAIT;
373
374 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN,
375 &msg_pwr->hdr);
376 if (ret) {
377 printf("bcm2835: Could not set module %u power state\n",
378 module);
379 return -1;
380 }
381
382 return 0;
383}
384
Stephen Warren6fe78452014-11-18 21:40:21 -0700385static void get_board_rev(void)
386{
Alexander Stein927753a2015-07-24 09:22:12 +0200387 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_rev, msg, 1);
Stephen Warren6fe78452014-11-18 21:40:21 -0700388 int ret;
Stephen Warrenc4ea1ed2015-12-04 22:07:45 -0700389 const struct rpi_model *models;
390 uint32_t models_count;
Stephen Warren6fe78452014-11-18 21:40:21 -0700391
392 BCM2835_MBOX_INIT_HDR(msg);
393 BCM2835_MBOX_INIT_TAG(&msg->get_board_rev, GET_BOARD_REV);
394
395 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
396 if (ret) {
397 printf("bcm2835: Could not query board revision\n");
398 /* Ignore error; not critical */
399 return;
400 }
401
Stephen Warren46414292015-02-16 12:16:15 -0700402 /*
403 * For details of old-vs-new scheme, see:
404 * https://github.com/pimoroni/RPi.version/blob/master/RPi/version.py
405 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=99293&p=690282
406 * (a few posts down)
Stephen Warren95b4f112015-03-23 23:00:25 -0600407 *
408 * For the RPi 1, bit 24 is the "warranty bit", so we mask off just the
409 * lower byte to use as the board rev:
410 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=98367&start=250
411 * http://www.raspberrypi.org/forums/viewtopic.php?f=31&t=20594
Stephen Warren46414292015-02-16 12:16:15 -0700412 */
Stephen Warrenc4ea1ed2015-12-04 22:07:45 -0700413 revision = msg->get_board_rev.body.resp.rev;
414 if (revision & 0x800000) {
415 rev_scheme = 1;
416 rev_type = (revision >> 4) & 0xff;
417 models = rpi_models_new_scheme;
418 models_count = ARRAY_SIZE(rpi_models_new_scheme);
419 } else {
420 rev_scheme = 0;
421 rev_type = revision & 0xff;
422 models = rpi_models_old_scheme;
423 models_count = ARRAY_SIZE(rpi_models_old_scheme);
Stephen Warren47705ef2014-12-23 20:01:43 -0700424 }
Stephen Warrenc4ea1ed2015-12-04 22:07:45 -0700425 if (rev_type >= models_count) {
426 printf("RPI: Board rev 0x%x outside known range\n", rev_type);
427 model = &rpi_model_unknown;
428 } else if (!models[rev_type].name) {
429 printf("RPI: Board rev 0x%x unknown\n", rev_type);
430 model = &rpi_model_unknown;
431 } else {
432 model = &models[rev_type];
Stephen Warren914627f2014-12-23 20:01:44 -0700433 }
Stephen Warren6fe78452014-11-18 21:40:21 -0700434
Stephen Warrenc4ea1ed2015-12-04 22:07:45 -0700435 printf("RPI %s (0x%x)\n", model->name, revision);
Stephen Warren6fe78452014-11-18 21:40:21 -0700436}
437
Alexander Graf601147b2016-08-15 17:48:51 +0200438#ifndef CONFIG_PL01X_SERIAL
439static bool rpi_is_serial_active(void)
440{
441 int serial_gpio = 15;
442 struct udevice *dev;
443
444 /*
445 * The RPi3 disables the mini uart by default. The easiest way to find
446 * out whether it is available is to check if the RX pin is muxed.
447 */
448
449 if (uclass_first_device(UCLASS_GPIO, &dev) || !dev)
450 return true;
451
452 if (bcm2835_gpio_get_func_id(dev, serial_gpio) != BCM2835_GPIO_ALT5)
453 return false;
454
455 return true;
456}
Fabian Vogtd8396a32016-09-26 14:26:50 +0200457
458/* Disable mini-UART I/O if it's not pinmuxed to our pins.
459 * The firmware only enables it if explicitly done in config.txt: enable_uart=1
460 */
461static void rpi_disable_inactive_uart(void)
462{
463 struct udevice *dev;
464 struct bcm283x_mu_serial_platdata *plat;
465
466 if (uclass_get_device_by_driver(UCLASS_SERIAL,
467 DM_GET_DRIVER(serial_bcm283x_mu),
468 &dev) || !dev)
469 return;
470
471 if (!rpi_is_serial_active()) {
472 plat = dev_get_platdata(dev);
473 plat->disabled = true;
474 }
475}
Alexander Graf601147b2016-08-15 17:48:51 +0200476#endif
477
Fabian Vogtd8396a32016-09-26 14:26:50 +0200478int board_init(void)
Alexander Graf601147b2016-08-15 17:48:51 +0200479{
480#ifndef CONFIG_PL01X_SERIAL
Fabian Vogtd8396a32016-09-26 14:26:50 +0200481 rpi_disable_inactive_uart();
Alexander Graf601147b2016-08-15 17:48:51 +0200482#endif
483
Fabian Vogtd8396a32016-09-26 14:26:50 +0200484 get_board_rev();
485
486 gd->bd->bi_boot_params = 0x100;
487
488 return power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD);
Alexander Graf601147b2016-08-15 17:48:51 +0200489}
490
Jeroen Hofstee5dfd1622014-07-13 22:01:51 +0200491int board_mmc_init(bd_t *bis)
Stephen Warren131a1e62013-01-29 16:37:42 +0000492{
Alexander Stein927753a2015-07-24 09:22:12 +0200493 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_clock_rate, msg_clk, 1);
Stephen Warren131a1e62013-01-29 16:37:42 +0000494 int ret;
495
Stephen Warrenf66f2aa2014-01-13 19:50:11 -0700496 power_on_module(BCM2835_MBOX_POWER_DEVID_SDHCI);
497
Stephen Warren131a1e62013-01-29 16:37:42 +0000498 BCM2835_MBOX_INIT_HDR(msg_clk);
499 BCM2835_MBOX_INIT_TAG(&msg_clk->get_clock_rate, GET_CLOCK_RATE);
500 msg_clk->get_clock_rate.body.req.clock_id = BCM2835_MBOX_CLOCK_ID_EMMC;
501
502 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_clk->hdr);
503 if (ret) {
504 printf("bcm2835: Could not query eMMC clock rate\n");
505 return -1;
506 }
507
508 return bcm2835_sdhci_init(BCM2835_SDHCI_BASE,
509 msg_clk->get_clock_rate.body.resp.rate_hz);
510}
Stephen Warrenea697ae2013-05-27 18:31:18 +0000511
Simon Glasse895a4b2014-10-23 18:58:47 -0600512int ft_board_setup(void *blob, bd_t *bd)
Stephen Warrenea697ae2013-05-27 18:31:18 +0000513{
514 /*
515 * For now, we simply always add the simplefb DT node. Later, we
516 * should be more intelligent, and e.g. only do this if no enabled DT
517 * node exists for the "real" graphics driver.
518 */
519 lcd_dt_simplefb_add_node(blob);
Simon Glasse895a4b2014-10-23 18:58:47 -0600520
521 return 0;
Stephen Warrenea697ae2013-05-27 18:31:18 +0000522}