diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/boards/raspberry-pi/env/init/ps1 | 7 | ||||
-rw-r--r-- | arch/arm/boards/raspberry-pi/rpi.c | 163 | ||||
-rw-r--r-- | arch/arm/mach-bcm2835/core.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-bcm2835/include/mach/mbox.h | 97 | ||||
-rw-r--r-- | arch/arm/mach-bcm2835/mbox.c | 2 |
5 files changed, 268 insertions, 3 deletions
diff --git a/arch/arm/boards/raspberry-pi/env/init/ps1 b/arch/arm/boards/raspberry-pi/env/init/ps1 new file mode 100644 index 0000000000..f8948466d3 --- /dev/null +++ b/arch/arm/boards/raspberry-pi/env/init/ps1 @@ -0,0 +1,7 @@ +#!/bin/sh + +if [ ${global.allow_color} = "true" ]; then + export PS1="\e[1;32mbarebox@\e[1;36m\h:\w\e[0m\n# " +else + export PS1="barebox@\h:\w\n# " +fi diff --git a/arch/arm/boards/raspberry-pi/rpi.c b/arch/arm/boards/raspberry-pi/rpi.c index 03a16d7561..f9406d4623 100644 --- a/arch/arm/boards/raspberry-pi/rpi.c +++ b/arch/arm/boards/raspberry-pi/rpi.c @@ -20,6 +20,10 @@ #include <linux/clk.h> #include <linux/clkdev.h> #include <envfs.h> +#include <malloc.h> +#include <gpio.h> +#include <net.h> +#include <led.h> #include <asm/armlinux.h> #include <generated/mach-types.h> @@ -38,6 +42,18 @@ struct msg_get_clock_rate { u32 end_tag; }; +struct msg_get_board_rev { + struct bcm2835_mbox_hdr hdr; + struct bcm2835_mbox_tag_get_board_rev get_board_rev; + u32 end_tag; +}; + +struct msg_get_mac_address { + struct bcm2835_mbox_hdr hdr; + struct bcm2835_mbox_tag_get_mac_address get_mac_address; + u32 end_tag; +}; + static int rpi_get_arm_mem(u32 *size) { BCM2835_MBOX_STACK_ALIGN(struct msg_get_arm_mem, msg); @@ -79,6 +95,150 @@ static int rpi_register_clkdev(u32 clock_id, const char *name) return 0; } +static void rpi_set_usbethaddr(void) +{ + BCM2835_MBOX_STACK_ALIGN(struct msg_get_mac_address, msg); + int ret; + + BCM2835_MBOX_INIT_HDR(msg); + BCM2835_MBOX_INIT_TAG(&msg->get_mac_address, GET_MAC_ADDRESS); + + ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); + if (ret) { + printf("bcm2835: Could not query MAC address\n"); + /* Ignore error; not critical */ + return; + } + + eth_register_ethaddr(0, msg->get_mac_address.body.resp.mac); +} + +static struct gpio_led leds[] = { + { + .gpio = -EINVAL, + .led = { + .name = "ACT", + }, + }, { + .gpio = -EINVAL, + .led = { + .name = "PWR", + }, + }, +}; + +static void rpi_add_led(void) +{ + int i; + struct gpio_led *l; + + for (i = 0; i < ARRAY_SIZE(leds); i++) { + l = &leds[i]; + + if (gpio_is_valid(l->gpio)) + led_gpio_register(l); + } + + l = &leds[0]; + if (gpio_is_valid(l->gpio)) + led_set_trigger(LED_TRIGGER_HEARTBEAT, &l->led); +} + +static void rpi_b_plus_init(void) +{ + leds[0].gpio = 47; + leds[1].gpio = 35; + rpi_set_usbethaddr(); +} + +static void rpi_b_init(void) +{ + leds[0].gpio = 16; + leds[0].active_low = 1; + rpi_set_usbethaddr(); +} + +#define RPI_MODEL(_id, _name, _init) \ + [_id] = { \ + .name = _name,\ + .init = _init,\ + } +/* See comments in mbox.h for data source */ +static const struct { + const char *name; + void (*init)(void); +} models[] = { + RPI_MODEL(0, "Unknown model", NULL), + RPI_MODEL(BCM2835_BOARD_REV_B_I2C0_2, "Model B (no P5)", rpi_b_init), + RPI_MODEL(BCM2835_BOARD_REV_B_I2C0_3, "Model B (no P5)", rpi_b_init), + RPI_MODEL(BCM2835_BOARD_REV_B_I2C1_4, "Model B", rpi_b_init), + RPI_MODEL(BCM2835_BOARD_REV_B_I2C1_5, "Model B", rpi_b_init), + RPI_MODEL(BCM2835_BOARD_REV_B_I2C1_6, "Model B", rpi_b_init), + RPI_MODEL(BCM2835_BOARD_REV_A_7, "Model A", NULL), + RPI_MODEL(BCM2835_BOARD_REV_A_8, "Model A", NULL), + RPI_MODEL(BCM2835_BOARD_REV_A_9, "Model A", NULL), + RPI_MODEL(BCM2835_BOARD_REV_B_REV2_d, "Model B rev2", rpi_b_init), + RPI_MODEL(BCM2835_BOARD_REV_B_REV2_e, "Model B rev2", rpi_b_init), + RPI_MODEL(BCM2835_BOARD_REV_B_REV2_f, "Model B rev2", rpi_b_init), + RPI_MODEL(BCM2835_BOARD_REV_B_PLUS, "Model B+", rpi_b_plus_init), + RPI_MODEL(BCM2835_BOARD_REV_CM, "Compute Module", NULL), + RPI_MODEL(BCM2835_BOARD_REV_A_PLUS, "Model A+", NULL), +}; + +static int rpi_board_rev = 0; + +static void rpi_get_board_rev(void) +{ + int ret; + char *name; + + BCM2835_MBOX_STACK_ALIGN(struct msg_get_board_rev, msg); + BCM2835_MBOX_INIT_HDR(msg); + BCM2835_MBOX_INIT_TAG(&msg->get_board_rev, GET_BOARD_REV); + + ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); + if (ret) { + printf("bcm2835: Could not query board revision\n"); + /* Ignore error; not critical */ + return; + } + + rpi_board_rev = msg->get_board_rev.body.resp.rev; + if (rpi_board_rev >= ARRAY_SIZE(models)) { + printf("RPI: Board rev %u outside known range\n", + rpi_board_rev); + goto unknown_rev; + } + + if (!models[rpi_board_rev].name) { + printf("RPI: Board rev %u unknown\n", rpi_board_rev); + goto unknown_rev; + } + + if (!rpi_board_rev) + goto unknown_rev; + + name = asprintf("RaspberryPi %s (BCM2835/ARM1176JZF-S)", + models[rpi_board_rev].name); + barebox_set_model(name); + free(name); + + return; + +unknown_rev: + rpi_board_rev = 0; + barebox_set_model("RaspberryPi (BCM2835/ARM1176JZF-S)"); +} + +static void rpi_model_init(void) +{ + if (!models[rpi_board_rev].init) + return; + + models[rpi_board_rev].init(); + rpi_add_led(); +} + static int rpi_mem_init(void) { u32 size = 0; @@ -96,7 +256,7 @@ mem_initcall(rpi_mem_init); static int rpi_console_init(void) { - barebox_set_model("RaspberryPi (BCM2835/ARM1176JZF-S)"); + rpi_get_board_rev(); barebox_set_hostname("rpi"); bcm2835_register_uart(); @@ -139,6 +299,7 @@ static int rpi_env_init(void) static int rpi_devices_init(void) { + rpi_model_init(); bcm2835_register_mci(); bcm2835_register_fb(); armlinux_set_architecture(MACH_TYPE_BCM2708); diff --git a/arch/arm/mach-bcm2835/core.c b/arch/arm/mach-bcm2835/core.c index 7f3d7e7629..5d08012f8b 100644 --- a/arch/arm/mach-bcm2835/core.c +++ b/arch/arm/mach-bcm2835/core.c @@ -72,7 +72,7 @@ void bcm2835_add_device_sdram(u32 size) } #define RESET_TIMEOUT 10 -void __noreturn reset_cpu (unsigned long addr) +void __noreturn reset_cpu(unsigned long addr) { uint32_t rstc; diff --git a/arch/arm/mach-bcm2835/include/mach/mbox.h b/arch/arm/mach-bcm2835/include/mach/mbox.h index fb8a9bf029..4c3fd775dd 100644 --- a/arch/arm/mach-bcm2835/include/mach/mbox.h +++ b/arch/arm/mach-bcm2835/include/mach/mbox.h @@ -124,6 +124,54 @@ struct bcm2835_mbox_tag_hdr { * }; */ +#define BCM2835_MBOX_TAG_GET_BOARD_REV 0x00010002 + +/* + * 0x2..0xf from: + * http://raspberryalphaomega.org.uk/2013/02/06/automatic-raspberry-pi-board-revision-detection-model-a-b1-and-b2/ + * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=32733 + * 0x10, 0x11 from swarren's testing + */ +#define BCM2835_BOARD_REV_B_I2C0_2 0x2 +#define BCM2835_BOARD_REV_B_I2C0_3 0x3 +#define BCM2835_BOARD_REV_B_I2C1_4 0x4 +#define BCM2835_BOARD_REV_B_I2C1_5 0x5 +#define BCM2835_BOARD_REV_B_I2C1_6 0x6 +#define BCM2835_BOARD_REV_A_7 0x7 +#define BCM2835_BOARD_REV_A_8 0x8 +#define BCM2835_BOARD_REV_A_9 0x9 +#define BCM2835_BOARD_REV_B_REV2_d 0xd +#define BCM2835_BOARD_REV_B_REV2_e 0xe +#define BCM2835_BOARD_REV_B_REV2_f 0xf +#define BCM2835_BOARD_REV_B_PLUS 0x10 +#define BCM2835_BOARD_REV_CM 0x11 +#define BCM2835_BOARD_REV_A_PLUS 0x12 + +struct bcm2835_mbox_tag_get_board_rev { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + } req; + struct { + u32 rev; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_MAC_ADDRESS 0x00010003 + +struct bcm2835_mbox_tag_get_mac_address { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + } req; + struct { + u8 mac[6]; + u8 pad[2]; + } resp; + } body; +}; + #define BCM2835_MBOX_TAG_GET_ARM_MEMORY 0x00010005 struct bcm2835_mbox_tag_get_arm_mem { @@ -138,6 +186,55 @@ struct bcm2835_mbox_tag_get_arm_mem { } body; }; +#define BCM2835_MBOX_POWER_DEVID_SDHCI 0 +#define BCM2835_MBOX_POWER_DEVID_UART0 1 +#define BCM2835_MBOX_POWER_DEVID_UART1 2 +#define BCM2835_MBOX_POWER_DEVID_USB_HCD 3 +#define BCM2835_MBOX_POWER_DEVID_I2C0 4 +#define BCM2835_MBOX_POWER_DEVID_I2C1 5 +#define BCM2835_MBOX_POWER_DEVID_I2C2 6 +#define BCM2835_MBOX_POWER_DEVID_SPI 7 +#define BCM2835_MBOX_POWER_DEVID_CCP2TX 8 + +#define BCM2835_MBOX_POWER_STATE_RESP_ON (1 << 0) +/* Device doesn't exist */ +#define BCM2835_MBOX_POWER_STATE_RESP_NODEV (1 << 1) + +#define BCM2835_MBOX_TAG_GET_POWER_STATE 0x00020001 + +struct bcm2835_mbox_tag_get_power_state { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + u32 device_id; + } req; + struct { + u32 device_id; + u32 state; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_SET_POWER_STATE 0x00028001 + +#define BCM2835_MBOX_SET_POWER_STATE_REQ_OFF (0 << 0) +#define BCM2835_MBOX_SET_POWER_STATE_REQ_ON (1 << 0) +#define BCM2835_MBOX_SET_POWER_STATE_REQ_WAIT (1 << 1) + +struct bcm2835_mbox_tag_set_power_state { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + u32 device_id; + u32 state; + } req; + struct { + u32 device_id; + u32 state; + } resp; + } body; +}; + #define BCM2835_MBOX_TAG_GET_CLOCK_RATE 0x00030002 #define BCM2835_MBOX_CLOCK_ID_EMMC 1 diff --git a/arch/arm/mach-bcm2835/mbox.c b/arch/arm/mach-bcm2835/mbox.c index 2bca567f39..1a8077182a 100644 --- a/arch/arm/mach-bcm2835/mbox.c +++ b/arch/arm/mach-bcm2835/mbox.c @@ -13,7 +13,7 @@ #include <mach/mbox.h> -#define TIMEOUT (MSECOND * 100) /* 100mS */ +#define TIMEOUT (MSECOND * 1000) static int bcm2835_mbox_call_raw(u32 chan, struct bcm2835_mbox_hdr *buffer, u32 *recv) |