2 * (C) Copyright 2012-2016 Stephen Warren
4 * SPDX-License-Identifier: GPL-2.0
11 #include <fdt_support.h>
12 #include <fdt_simplefb.h>
17 #include <asm/arch/mbox.h>
18 #include <asm/arch/sdhci.h>
19 #include <asm/global_data.h>
20 #include <dm/platform_data/serial_pl01x.h>
21 #include <dm/platform_data/serial_bcm283x_mu.h>
23 DECLARE_GLOBAL_DATA_PTR
;
25 static const struct bcm2835_gpio_platdata gpio_platdata
= {
26 .base
= BCM2835_GPIO_BASE
,
29 U_BOOT_DEVICE(bcm2835_gpios
) = {
30 .name
= "gpio_bcm2835",
31 .platdata
= &gpio_platdata
,
34 #ifdef CONFIG_PL01X_SERIAL
35 static const struct pl01x_serial_platdata serial_platdata
= {
36 #ifndef CONFIG_BCM2835
45 U_BOOT_DEVICE(bcm2835_serials
) = {
46 .name
= "serial_pl01x",
47 .platdata
= &serial_platdata
,
50 static const struct bcm283x_mu_serial_platdata serial_platdata
= {
56 U_BOOT_DEVICE(bcm2837_serials
) = {
57 .name
= "serial_bcm283x_mu",
58 .platdata
= &serial_platdata
,
62 struct msg_get_arm_mem
{
63 struct bcm2835_mbox_hdr hdr
;
64 struct bcm2835_mbox_tag_get_arm_mem get_arm_mem
;
68 struct msg_get_board_rev
{
69 struct bcm2835_mbox_hdr hdr
;
70 struct bcm2835_mbox_tag_get_board_rev get_board_rev
;
74 struct msg_get_board_serial
{
75 struct bcm2835_mbox_hdr hdr
;
76 struct bcm2835_mbox_tag_get_board_serial get_board_serial
;
80 struct msg_get_mac_address
{
81 struct bcm2835_mbox_hdr hdr
;
82 struct bcm2835_mbox_tag_get_mac_address get_mac_address
;
86 struct msg_set_power_state
{
87 struct bcm2835_mbox_hdr hdr
;
88 struct bcm2835_mbox_tag_set_power_state set_power_state
;
92 struct msg_get_clock_rate
{
93 struct bcm2835_mbox_hdr hdr
;
94 struct bcm2835_mbox_tag_get_clock_rate get_clock_rate
;
99 * http://raspberryalphaomega.org.uk/2013/02/06/automatic-raspberry-pi-board-revision-detection-model-a-b1-and-b2/
100 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=32733
101 * http://git.drogon.net/?p=wiringPi;a=blob;f=wiringPi/wiringPi.c;h=503151f61014418b9c42f4476a6086f75cd4e64b;hb=refs/heads/master#l922
103 * In http://lists.denx.de/pipermail/u-boot/2016-January/243752.html
104 * ("[U-Boot] [PATCH] rpi: fix up Model B entries") Dom Cobley at the RPi
105 * Foundation stated that the following source was accurate:
106 * https://github.com/AndrewFromMelbourne/raspberry_pi_revision
111 bool has_onboard_eth
;
114 static const struct rpi_model rpi_model_unknown
= {
116 "bcm283x-rpi-other.dtb",
120 static const struct rpi_model rpi_models_new_scheme
[] = {
123 "bcm2836-rpi-2-b.dtb",
128 "bcm2837-rpi-3-b.dtb",
133 "bcm2835-rpi-zero.dtb",
138 static const struct rpi_model rpi_models_old_scheme
[] = {
151 "bcm2835-rpi-b-rev2.dtb",
156 "bcm2835-rpi-b-rev2.dtb",
161 "bcm2835-rpi-b-rev2.dtb",
181 "bcm2835-rpi-b-rev2.dtb",
186 "bcm2835-rpi-b-rev2.dtb",
191 "bcm2835-rpi-b-rev2.dtb",
196 "bcm2835-rpi-b-plus.dtb",
201 "bcm2835-rpi-cm.dtb",
206 "bcm2835-rpi-a-plus.dtb",
211 "bcm2835-rpi-b-plus.dtb",
216 "bcm2835-rpi-cm.dtb",
221 "bcm2835-rpi-a-plus.dtb",
226 static uint32_t revision
;
227 static uint32_t rev_scheme
;
228 static uint32_t rev_type
;
229 static const struct rpi_model
*model
;
233 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_arm_mem
, msg
, 1);
236 BCM2835_MBOX_INIT_HDR(msg
);
237 BCM2835_MBOX_INIT_TAG(&msg
->get_arm_mem
, GET_ARM_MEMORY
);
239 ret
= bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN
, &msg
->hdr
);
241 printf("bcm2835: Could not query ARM memory size\n");
245 gd
->ram_size
= msg
->get_arm_mem
.body
.resp
.mem_size
;
250 static void set_fdtfile(void)
254 if (getenv("fdtfile"))
257 fdtfile
= model
->fdtfile
;
258 setenv("fdtfile", fdtfile
);
261 static void set_usbethaddr(void)
263 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_mac_address
, msg
, 1);
266 if (!model
->has_onboard_eth
)
269 if (getenv("usbethaddr"))
272 BCM2835_MBOX_INIT_HDR(msg
);
273 BCM2835_MBOX_INIT_TAG(&msg
->get_mac_address
, GET_MAC_ADDRESS
);
275 ret
= bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN
, &msg
->hdr
);
277 printf("bcm2835: Could not query MAC address\n");
278 /* Ignore error; not critical */
282 eth_setenv_enetaddr("usbethaddr", msg
->get_mac_address
.body
.resp
.mac
);
284 if (!getenv("ethaddr"))
285 setenv("ethaddr", getenv("usbethaddr"));
290 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
291 static void set_board_info(void)
295 snprintf(s
, sizeof(s
), "0x%X", revision
);
296 setenv("board_revision", s
);
297 snprintf(s
, sizeof(s
), "%d", rev_scheme
);
298 setenv("board_rev_scheme", s
);
299 /* Can't rename this to board_rev_type since it's an ABI for scripts */
300 snprintf(s
, sizeof(s
), "0x%X", rev_type
);
301 setenv("board_rev", s
);
302 setenv("board_name", model
->name
);
304 #endif /* CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG */
306 static void set_serial_number(void)
308 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_serial
, msg
, 1);
310 char serial_string
[17] = { 0 };
312 if (getenv("serial#"))
315 BCM2835_MBOX_INIT_HDR(msg
);
316 BCM2835_MBOX_INIT_TAG_NO_REQ(&msg
->get_board_serial
, GET_BOARD_SERIAL
);
318 ret
= bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN
, &msg
->hdr
);
320 printf("bcm2835: Could not query board serial\n");
321 /* Ignore error; not critical */
325 snprintf(serial_string
, sizeof(serial_string
), "%016" PRIx64
,
326 msg
->get_board_serial
.body
.resp
.serial
);
327 setenv("serial#", serial_string
);
330 int misc_init_r(void)
334 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
342 static int power_on_module(u32 module
)
344 ALLOC_CACHE_ALIGN_BUFFER(struct msg_set_power_state
, msg_pwr
, 1);
347 BCM2835_MBOX_INIT_HDR(msg_pwr
);
348 BCM2835_MBOX_INIT_TAG(&msg_pwr
->set_power_state
,
350 msg_pwr
->set_power_state
.body
.req
.device_id
= module
;
351 msg_pwr
->set_power_state
.body
.req
.state
=
352 BCM2835_MBOX_SET_POWER_STATE_REQ_ON
|
353 BCM2835_MBOX_SET_POWER_STATE_REQ_WAIT
;
355 ret
= bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN
,
358 printf("bcm2835: Could not set module %u power state\n",
366 static void get_board_rev(void)
368 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_rev
, msg
, 1);
370 const struct rpi_model
*models
;
371 uint32_t models_count
;
373 BCM2835_MBOX_INIT_HDR(msg
);
374 BCM2835_MBOX_INIT_TAG(&msg
->get_board_rev
, GET_BOARD_REV
);
376 ret
= bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN
, &msg
->hdr
);
378 printf("bcm2835: Could not query board revision\n");
379 /* Ignore error; not critical */
384 * For details of old-vs-new scheme, see:
385 * https://github.com/pimoroni/RPi.version/blob/master/RPi/version.py
386 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=99293&p=690282
389 * For the RPi 1, bit 24 is the "warranty bit", so we mask off just the
390 * lower byte to use as the board rev:
391 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=98367&start=250
392 * http://www.raspberrypi.org/forums/viewtopic.php?f=31&t=20594
394 revision
= msg
->get_board_rev
.body
.resp
.rev
;
395 if (revision
& 0x800000) {
397 rev_type
= (revision
>> 4) & 0xff;
398 models
= rpi_models_new_scheme
;
399 models_count
= ARRAY_SIZE(rpi_models_new_scheme
);
402 rev_type
= revision
& 0xff;
403 models
= rpi_models_old_scheme
;
404 models_count
= ARRAY_SIZE(rpi_models_old_scheme
);
406 if (rev_type
>= models_count
) {
407 printf("RPI: Board rev 0x%x outside known range\n", rev_type
);
408 model
= &rpi_model_unknown
;
409 } else if (!models
[rev_type
].name
) {
410 printf("RPI: Board rev 0x%x unknown\n", rev_type
);
411 model
= &rpi_model_unknown
;
413 model
= &models
[rev_type
];
416 printf("RPI %s (0x%x)\n", model
->name
, revision
);
423 gd
->bd
->bi_boot_params
= 0x100;
425 return power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD
);
428 int board_mmc_init(bd_t
*bis
)
430 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_clock_rate
, msg_clk
, 1);
433 power_on_module(BCM2835_MBOX_POWER_DEVID_SDHCI
);
435 BCM2835_MBOX_INIT_HDR(msg_clk
);
436 BCM2835_MBOX_INIT_TAG(&msg_clk
->get_clock_rate
, GET_CLOCK_RATE
);
437 msg_clk
->get_clock_rate
.body
.req
.clock_id
= BCM2835_MBOX_CLOCK_ID_EMMC
;
439 ret
= bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN
, &msg_clk
->hdr
);
441 printf("bcm2835: Could not query eMMC clock rate\n");
445 return bcm2835_sdhci_init(BCM2835_SDHCI_BASE
,
446 msg_clk
->get_clock_rate
.body
.resp
.rate_hz
);
449 int ft_board_setup(void *blob
, bd_t
*bd
)
452 * For now, we simply always add the simplefb DT node. Later, we
453 * should be more intelligent, and e.g. only do this if no enabled DT
454 * node exists for the "real" graphics driver.
456 lcd_dt_simplefb_add_node(blob
);