diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2013-11-07 08:31:47 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2013-11-07 08:31:47 +0100 |
commit | ded25480d8c5e56d9dcbf53a88d05f023b9740c4 (patch) | |
tree | 8691bdf7f0fc801b08b114204c83d25007eb8fba /arch | |
parent | b3055b0f6b1687089b914eb8cde5bbb73cfca7a1 (diff) | |
parent | 97607e85cdc44824e9617c74325bc9bc6405c383 (diff) | |
download | barebox-ded25480d8c5e56d9dcbf53a88d05f023b9740c4.tar.gz barebox-ded25480d8c5e56d9dcbf53a88d05f023b9740c4.tar.xz |
Merge branch 'for-next/rpi'
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/boards/at91sam9x5ek/hw_version.c | 4 | ||||
-rw-r--r-- | arch/arm/boards/highbank/init.c | 4 | ||||
-rw-r--r-- | arch/arm/boards/raspberry-pi/env/init/bootargs-base | 2 | ||||
-rw-r--r-- | arch/arm/boards/raspberry-pi/rpi.c | 110 | ||||
-rw-r--r-- | arch/arm/configs/rpi_defconfig | 45 | ||||
-rw-r--r-- | arch/arm/cpu/cache.c | 18 | ||||
-rw-r--r-- | arch/arm/cpu/start.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-bcm2835/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-bcm2835/core.c | 33 | ||||
-rw-r--r-- | arch/arm/mach-bcm2835/include/mach/core.h | 13 | ||||
-rw-r--r-- | arch/arm/mach-bcm2835/include/mach/mbox.h | 421 | ||||
-rw-r--r-- | arch/arm/mach-bcm2835/mbox.c | 152 | ||||
-rw-r--r-- | arch/ppc/mach-mpc5xxx/cpu.c | 4 | ||||
-rw-r--r-- | arch/ppc/mach-mpc85xx/fdt.c | 4 |
14 files changed, 760 insertions, 56 deletions
diff --git a/arch/arm/boards/at91sam9x5ek/hw_version.c b/arch/arm/boards/at91sam9x5ek/hw_version.c index 1207a3e49d..2da4e5ed8c 100644 --- a/arch/arm/boards/at91sam9x5ek/hw_version.c +++ b/arch/arm/boards/at91sam9x5ek/hw_version.c @@ -229,7 +229,7 @@ static void at91sam9x5ek_devices_detect_one(const char *name) #define NODE_NAME_LEN 128 -static int cm_cogent_fixup(struct device_node *root) +static int cm_cogent_fixup(struct device_node *root, void *unused) { int ret; struct device_node *node; @@ -260,5 +260,5 @@ void at91sam9x5ek_devices_detect_hw(void) armlinux_set_serial(sn); if (at91sam9x5ek_cm_is_vendor(VENDOR_COGENT)) - of_register_fixup(cm_cogent_fixup); + of_register_fixup(cm_cogent_fixup, NULL); } diff --git a/arch/arm/boards/highbank/init.c b/arch/arm/boards/highbank/init.c index 7b1be046a5..8a24b21a73 100644 --- a/arch/arm/boards/highbank/init.c +++ b/arch/arm/boards/highbank/init.c @@ -24,7 +24,7 @@ struct fdt_header *fdt = NULL; -static int hb_fixup(struct device_node *root) +static int hb_fixup(struct device_node *root, void *unused) { struct device_node *node; u32 reg = readl(sregs_base + HB_SREG_A9_PWRDOM_DATA); @@ -108,7 +108,7 @@ mem_initcall(highbank_mem_init); static int highbank_devices_init(void) { - of_register_fixup(hb_fixup); + of_register_fixup(hb_fixup, NULL); if (!fdt) { highbank_register_gpio(0); highbank_register_gpio(1); diff --git a/arch/arm/boards/raspberry-pi/env/init/bootargs-base b/arch/arm/boards/raspberry-pi/env/init/bootargs-base index d86975406e..4dda5501e3 100644 --- a/arch/arm/boards/raspberry-pi/env/init/bootargs-base +++ b/arch/arm/boards/raspberry-pi/env/init/bootargs-base @@ -5,4 +5,4 @@ if [ "$1" = menu ]; then exit fi -global.linux.bootargs.base="console=ttymxc0,115200" +global.linux.bootargs.base="console=ttyAMA0,115200" diff --git a/arch/arm/boards/raspberry-pi/rpi.c b/arch/arm/boards/raspberry-pi/rpi.c index d4912ccdc7..96025ba9b1 100644 --- a/arch/arm/boards/raspberry-pi/rpi.c +++ b/arch/arm/boards/raspberry-pi/rpi.c @@ -15,16 +15,83 @@ #include <common.h> #include <init.h> +#include <fs.h> +#include <linux/stat.h> +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <envfs.h> #include <asm/armlinux.h> #include <generated/mach-types.h> #include <mach/core.h> +#include <mach/mbox.h> -static int rpi_mem_init(void) +struct msg_get_arm_mem { + struct bcm2835_mbox_hdr hdr; + struct bcm2835_mbox_tag_get_arm_mem get_arm_mem; + u32 end_tag; +}; + +struct msg_get_clock_rate { + struct bcm2835_mbox_hdr hdr; + struct bcm2835_mbox_tag_get_clock_rate get_clock_rate; + u32 end_tag; +}; + +static int rpi_get_arm_mem(u32 *size) { - bcm2835_add_device_sdram(0); + BCM2835_MBOX_STACK_ALIGN(struct msg_get_arm_mem, msg); + int ret; + + BCM2835_MBOX_INIT_HDR(msg); + BCM2835_MBOX_INIT_TAG(&msg->get_arm_mem, GET_ARM_MEMORY); + + ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); + if (ret) + return ret; + + *size = msg->get_arm_mem.body.resp.mem_size; + return 0; } + +static int rpi_register_clkdev(u32 clock_id, const char *name) +{ + BCM2835_MBOX_STACK_ALIGN(struct msg_get_clock_rate, msg); + struct clk *clk; + int ret; + + BCM2835_MBOX_INIT_HDR(msg); + BCM2835_MBOX_INIT_TAG(&msg->get_clock_rate, GET_CLOCK_RATE); + msg->get_clock_rate.body.req.clock_id = clock_id; + + ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); + if (ret) + return ret; + + clk = clk_fixed(name, msg->get_clock_rate.body.resp.rate_hz); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + if (!clk_register_clkdev(clk, NULL, name)) + return -ENODEV; + + return 0; +} + +static int rpi_mem_init(void) +{ + u32 size = 0; + int ret; + + ret = rpi_get_arm_mem(&size); + if (ret) + printf("could not query ARM memory size\n"); + + bcm2835_add_device_sdram(size); + + return ret; +} mem_initcall(rpi_mem_init); static int rpi_console_init(void) @@ -37,11 +104,46 @@ static int rpi_console_init(void) } console_initcall(rpi_console_init); +static int rpi_clock_init(void) +{ + rpi_register_clkdev(BCM2835_MBOX_CLOCK_ID_EMMC, "bcm2835_mci0"); + return 0; +} +postconsole_initcall(rpi_clock_init); + +static int rpi_env_init(void) +{ + struct stat s; + const char *diskdev = "/dev/disk0.0"; + int ret; + + device_detect_by_name("mci0"); + + ret = stat(diskdev, &s); + if (ret) { + printf("no %s. using default env\n", diskdev); + return 0; + } + + mkdir("/boot", 0666); + ret = mount(diskdev, "fat", "/boot"); + if (ret) { + printf("failed to mount %s\n", diskdev); + return 0; + } + + default_environment_path = "/boot/barebox.env"; + + return 0; +} + static int rpi_devices_init(void) { + bcm2835_register_mci(); + bcm2835_register_fb(); armlinux_set_architecture(MACH_TYPE_BCM2708); armlinux_set_bootparams((void *)(0x00000100)); + rpi_env_init(); return 0; } - -device_initcall(rpi_devices_init); +late_initcall(rpi_devices_init); diff --git a/arch/arm/configs/rpi_defconfig b/arch/arm/configs/rpi_defconfig index 014e28c73d..76029d025f 100644 --- a/arch/arm/configs/rpi_defconfig +++ b/arch/arm/configs/rpi_defconfig @@ -1,41 +1,66 @@ CONFIG_ARCH_BCM2835=y -CONFIG_GPIO_BCM2835=y +CONFIG_AEABI=y CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_ARM_UNWIND=y +CONFIG_MMU=y +CONFIG_MALLOC_TLSF=y +CONFIG_KALLSYMS=y CONFIG_PROMPT="R-Pi> " CONFIG_LONGHELP=y -CONFIG_GLOB=y CONFIG_HUSH_FANCY_PROMPT=y CONFIG_CMDLINE_EDITING=y CONFIG_AUTO_COMPLETE=y CONFIG_MENU=y -CONFIG_PARTITION=y +CONFIG_BLSPEC=y CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/raspberry-pi/env" CONFIG_CMD_EDIT=y CONFIG_CMD_SLEEP=y +CONFIG_CMD_MSLEEP=y CONFIG_CMD_SAVEENV=y -CONFIG_CMD_LOADENV=y CONFIG_CMD_EXPORT=y CONFIG_CMD_PRINTENV=y CONFIG_CMD_READLINE=y +CONFIG_CMD_LET=y CONFIG_CMD_MENU=y CONFIG_CMD_MENU_MANAGEMENT=y CONFIG_CMD_PASSWD=y +CONFIG_CMD_TIME=y +CONFIG_CMD_LN=y +CONFIG_CMD_FILETYPE=y CONFIG_CMD_ECHO_E=y CONFIG_CMD_LOADB=y CONFIG_CMD_MEMINFO=y -CONFIG_CMD_MTEST=y -CONFIG_CMD_MTEST_ALTERNATIVE=y -CONFIG_CMD_BOOTM_ZLIB=y -CONFIG_CMD_BOOTM_BZLIB=y +CONFIG_CMD_IOMEM=y +CONFIG_CMD_MM=y +CONFIG_CMD_CRC=y +CONFIG_CMD_CRC_CMP=y +CONFIG_CMD_MD5SUM=y CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_BOOTM_VERBOSE=y +CONFIG_CMD_BOOTM_INITRD=y +CONFIG_CMD_BOOTM_OFTREE=y +CONFIG_CMD_UIMAGE=y CONFIG_CMD_RESET=y -CONFIG_CMD_CLK=y CONFIG_CMD_GO=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_OF_PROPERTY=y +CONFIG_CMD_OF_NODE=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y -CONFIG_CMD_UNCOMPRESS=y +CONFIG_CMD_MAGICVAR=y +CONFIG_CMD_MAGICVAR_HELP=y CONFIG_CMD_GPIO=y +CONFIG_CMD_UNCOMPRESS=y +CONFIG_CMD_CLK=y +CONFIG_CMD_DETECT=y CONFIG_SERIAL_AMBA_PL011=y +CONFIG_MCI=y +CONFIG_MCI_BCM2835=y +CONFIG_GPIO_BCM2835=y +CONFIG_FS_EXT4=y +CONFIG_FS_FAT=y +CONFIG_FS_FAT_WRITE=y +CONFIG_FS_FAT_LFN=y CONFIG_SHA1=y CONFIG_SHA256=y diff --git a/arch/arm/cpu/cache.c b/arch/arm/cpu/cache.c index 7aab55b6bc..223e3089b2 100644 --- a/arch/arm/cpu/cache.c +++ b/arch/arm/cpu/cache.c @@ -41,32 +41,38 @@ DEFINE_CPU_FNS(v7) void __dma_clean_range(unsigned long start, unsigned long end) { - cache_fns->dma_clean_range(start, end); + if (cache_fns) + cache_fns->dma_clean_range(start, end); } void __dma_flush_range(unsigned long start, unsigned long end) { - cache_fns->dma_flush_range(start, end); + if (cache_fns) + cache_fns->dma_flush_range(start, end); } void __dma_inv_range(unsigned long start, unsigned long end) { - cache_fns->dma_inv_range(start, end); + if (cache_fns) + cache_fns->dma_inv_range(start, end); } void __mmu_cache_on(void) { - cache_fns->mmu_cache_on(); + if (cache_fns) + cache_fns->mmu_cache_on(); } void __mmu_cache_off(void) { - cache_fns->mmu_cache_off(); + if (cache_fns) + cache_fns->mmu_cache_off(); } void __mmu_cache_flush(void) { - cache_fns->mmu_cache_flush(); + if (cache_fns) + cache_fns->mmu_cache_flush(); } int arm_set_cache_functions(void) diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c index f8d343f4ec..f0a7df37bd 100644 --- a/arch/arm/cpu/start.c +++ b/arch/arm/cpu/start.c @@ -70,7 +70,9 @@ static noinline __noreturn void __start(uint32_t membase, uint32_t memsize, endmem &= ~0x3fff; endmem -= SZ_16K; /* ttb */ - if (!IS_ENABLED(CONFIG_PBL_IMAGE)) { + if (IS_ENABLED(CONFIG_PBL_IMAGE)) { + arm_set_cache_functions(); + } else { arm_early_mmu_cache_invalidate(); mmu_early_enable(membase, memsize, endmem); } diff --git a/arch/arm/mach-bcm2835/Makefile b/arch/arm/mach-bcm2835/Makefile index 820eb10ac2..940f98cbce 100644 --- a/arch/arm/mach-bcm2835/Makefile +++ b/arch/arm/mach-bcm2835/Makefile @@ -1 +1 @@ -obj-y += core.o +obj-y += core.o mbox.o diff --git a/arch/arm/mach-bcm2835/core.c b/arch/arm/mach-bcm2835/core.c index 906e4344dd..04bc89751d 100644 --- a/arch/arm/mach-bcm2835/core.c +++ b/arch/arm/mach-bcm2835/core.c @@ -32,45 +32,28 @@ #include <mach/core.h> #include <linux/amba/bus.h> -enum brcm_clks { - dummy, clk_ref_3, clk_ref_1, clks_max -}; - -static struct clk *clks[clks_max]; - static int bcm2835_clk_init(void) { - int ret; + struct clk *clk; - clks[dummy] = clk_fixed("dummy", 0); - clks[clk_ref_3] = clk_fixed("ref3", 3 * 1000 * 1000); - clks[clk_ref_1] = clk_fixed("ref1", 1 * 1000 * 1000); + clk = clk_fixed("apb_pclk", 0); + clk_register_clkdev(clk, "apb_pclk", NULL); - ret = clk_register_clkdev(clks[dummy], "apb_pclk", NULL); - if (ret) - goto clk_err; + clk = clk_fixed("uart0-pl0110", 3 * 1000 * 1000); + clk_register_clkdev(clk, NULL, "uart0-pl0110"); - ret = clk_register_clkdev(clks[clk_ref_3], NULL, "uart0-pl0110"); - if (ret) - goto clk_err; + clk = clk_fixed("bcm2835-cs", 1 * 1000 * 1000); + clk_register_clkdev(clk, NULL, "bcm2835-cs"); - ret = clk_register_clkdev(clks[clk_ref_1], NULL, "bcm2835-cs"); - if (ret) - goto clk_err; + add_generic_device("bcm2835-cs", DEVICE_ID_SINGLE, NULL, BCM2835_ST_BASE, 0x1C, IORESOURCE_MEM, NULL); return 0; - -clk_err: - return ret; - } postcore_initcall(bcm2835_clk_init); static int bcm2835_dev_init(void) { add_generic_device("bcm2835-gpio", 0, NULL, BCM2835_GPIO_BASE, 0xB0, IORESOURCE_MEM, NULL); - add_generic_device("bcm2835-cs", DEVICE_ID_SINGLE, NULL, BCM2835_ST_BASE, 0x1C, IORESOURCE_MEM, NULL); - add_generic_device("bcm2835_mci", 0, NULL, BCM2835_EMMC_BASE, 0xFC, IORESOURCE_MEM, NULL); return 0; } coredevice_initcall(bcm2835_dev_init); diff --git a/arch/arm/mach-bcm2835/include/mach/core.h b/arch/arm/mach-bcm2835/include/mach/core.h index 9379af209b..477ecb977c 100644 --- a/arch/arm/mach-bcm2835/include/mach/core.h +++ b/arch/arm/mach-bcm2835/include/mach/core.h @@ -16,7 +16,20 @@ #ifndef __BCM2835_CORE_H__ #define __BCM2835_CORE_H__ +#include <mach/platform.h> + void bcm2835_register_uart(void); void bcm2835_add_device_sdram(u32 size); +static void inline bcm2835_register_mci(void) +{ + add_generic_device("bcm2835_mci", 0, NULL, BCM2835_EMMC_BASE, 0xFC, + IORESOURCE_MEM, NULL); +} + +static void inline bcm2835_register_fb(void) +{ + add_generic_device("bcm2835_fb", 0, NULL, 0, 0, 0, NULL); +} + #endif diff --git a/arch/arm/mach-bcm2835/include/mach/mbox.h b/arch/arm/mach-bcm2835/include/mach/mbox.h new file mode 100644 index 0000000000..fb8a9bf029 --- /dev/null +++ b/arch/arm/mach-bcm2835/include/mach/mbox.h @@ -0,0 +1,421 @@ +/* + * based on U-Boot code + * + * (C) Copyright 2012 Stephen Warren + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _BCM2835_MBOX_H +#define _BCM2835_MBOX_H + +#include <common.h> + +/* + * The BCM2835 SoC contains (at least) two CPUs; the VideoCore (a/k/a "GPU") + * and the ARM CPU. The ARM CPU is often thought of as the main CPU. + * However, the VideoCore actually controls the initial SoC boot, and hides + * much of the hardware behind a protocol. This protocol is transported + * using the SoC's mailbox hardware module. + * + * The mailbox hardware supports passing 32-bit values back and forth. + * Presumably by software convention of the firmware, the bottom 4 bits of the + * value are used to indicate a logical channel, and the upper 28 bits are the + * actual payload. Various channels exist using these simple raw messages. See + * https://github.com/raspberrypi/firmware/wiki/Mailboxes for a list. As an + * example, the messages on the power management channel are a bitmask of + * devices whose power should be enabled. + * + * The property mailbox channel passes messages that contain the (16-byte + * aligned) ARM physical address of a memory buffer. This buffer is passed to + * the VC for processing, is modified in-place by the VC, and the address then + * passed back to the ARM CPU as the response mailbox message to indicate + * request completion. The buffers have a generic and extensible format; each + * buffer contains a standard header, a list of "tags", and a terminating zero + * entry. Each tag contains an ID indicating its type, and length fields for + * generic parsing. With some limitations, an arbitrary set of tags may be + * combined together into a single message buffer. This file defines structs + * representing the header and many individual tag layouts and IDs. + */ + +/* Raw mailbox HW */ + +#define BCM2835_MBOX_PHYSADDR 0x2000b880 + +struct bcm2835_mbox_regs { + u32 read; + u32 rsvd0[5]; + u32 status; + u32 config; + u32 write; +}; + +#define BCM2835_MBOX_STATUS_WR_FULL 0x80000000 +#define BCM2835_MBOX_STATUS_RD_EMPTY 0x40000000 + +/* Lower 4-bits are channel ID */ +#define BCM2835_CHAN_MASK 0xf +#define BCM2835_MBOX_PACK(chan, data) (((data) & (~BCM2835_CHAN_MASK)) | \ + (chan & BCM2835_CHAN_MASK)) +#define BCM2835_MBOX_UNPACK_CHAN(val) ((val) & BCM2835_CHAN_MASK) +#define BCM2835_MBOX_UNPACK_DATA(val) ((val) & (~BCM2835_CHAN_MASK)) + +/* Property mailbox buffer structures */ + +#define BCM2835_MBOX_PROP_CHAN 8 + +/* All message buffers must start with this header */ +struct bcm2835_mbox_hdr { + u32 buf_size; + u32 code; +}; + +#define BCM2835_MBOX_REQ_CODE 0 +#define BCM2835_MBOX_RESP_CODE_SUCCESS 0x80000000 + +#define BCM2835_MBOX_STACK_ALIGN(type, name) \ + STACK_ALIGN_ARRAY(type, name, 1, BCM2835_CHAN_MASK + 1) + +#define BCM2835_MBOX_INIT_HDR(_m_) { \ + memset((_m_), 0, sizeof(*(_m_))); \ + (_m_)->hdr.buf_size = sizeof(*(_m_)); \ + (_m_)->hdr.code = 0; \ + (_m_)->end_tag = 0; \ + } + +/* + * A message buffer contains a list of tags. Each tag must also start with + * a standardized header. + */ +struct bcm2835_mbox_tag_hdr { + u32 tag; + u32 val_buf_size; + u32 val_len; +}; + +#define BCM2835_MBOX_INIT_TAG(_t_, _id_) { \ + (_t_)->tag_hdr.tag = BCM2835_MBOX_TAG_##_id_; \ + (_t_)->tag_hdr.val_buf_size = sizeof((_t_)->body); \ + (_t_)->tag_hdr.val_len = sizeof((_t_)->body.req); \ + } + +#define BCM2835_MBOX_INIT_TAG_NO_REQ(_t_, _id_) { \ + (_t_)->tag_hdr.tag = BCM2835_MBOX_TAG_##_id_; \ + (_t_)->tag_hdr.val_buf_size = sizeof((_t_)->body); \ + (_t_)->tag_hdr.val_len = 0; \ + } + +/* When responding, the VC sets this bit in val_len to indicate a response */ +#define BCM2835_MBOX_TAG_VAL_LEN_RESPONSE 0x80000000 + +/* + * Below we define the ID and struct for many possible tags. This header only + * defines individual tag structs, not entire message structs, since in + * general an arbitrary set of tags may be combined into a single message. + * Clients of the mbox API are expected to define their own overall message + * structures by combining the header, a set of tags, and a terminating + * entry. For example, + * + * struct msg { + * struct bcm2835_mbox_hdr hdr; + * struct bcm2835_mbox_tag_get_arm_mem get_arm_mem; + * ... perhaps other tags here ... + * u32 end_tag; + * }; + */ + +#define BCM2835_MBOX_TAG_GET_ARM_MEMORY 0x00010005 + +struct bcm2835_mbox_tag_get_arm_mem { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + } req; + struct { + u32 mem_base; + u32 mem_size; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_CLOCK_RATE 0x00030002 + +#define BCM2835_MBOX_CLOCK_ID_EMMC 1 +#define BCM2835_MBOX_CLOCK_ID_UART 2 +#define BCM2835_MBOX_CLOCK_ID_ARM 3 +#define BCM2835_MBOX_CLOCK_ID_CORE 4 +#define BCM2835_MBOX_CLOCK_ID_V3D 5 +#define BCM2835_MBOX_CLOCK_ID_H264 6 +#define BCM2835_MBOX_CLOCK_ID_ISP 7 +#define BCM2835_MBOX_CLOCK_ID_SDRAM 8 +#define BCM2835_MBOX_CLOCK_ID_PIXEL 9 +#define BCM2835_MBOX_CLOCK_ID_PWM 10 + +struct bcm2835_mbox_tag_get_clock_rate { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + u32 clock_id; + } req; + struct { + u32 clock_id; + u32 rate_hz; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_ALLOCATE_BUFFER 0x00040001 + +struct bcm2835_mbox_tag_allocate_buffer { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + u32 alignment; + } req; + struct { + u32 fb_address; + u32 fb_size; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_RELEASE_BUFFER 0x00048001 + +struct bcm2835_mbox_tag_release_buffer { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + } req; + struct { + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_BLANK_SCREEN 0x00040002 + +struct bcm2835_mbox_tag_blank_screen { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + /* bit 0 means on, other bits reserved */ + u32 state; + } req; + struct { + u32 state; + } resp; + } body; +}; + +/* Physical means output signal */ +#define BCM2835_MBOX_TAG_GET_PHYSICAL_W_H 0x00040003 +#define BCM2835_MBOX_TAG_TEST_PHYSICAL_W_H 0x00044003 +#define BCM2835_MBOX_TAG_SET_PHYSICAL_W_H 0x00048003 + +struct bcm2835_mbox_tag_physical_w_h { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + /* req not used for get */ + struct { + u32 width; + u32 height; + } req; + struct { + u32 width; + u32 height; + } resp; + } body; +}; + +/* Virtual means display buffer */ +#define BCM2835_MBOX_TAG_GET_VIRTUAL_W_H 0x00040004 +#define BCM2835_MBOX_TAG_TEST_VIRTUAL_W_H 0x00044004 +#define BCM2835_MBOX_TAG_SET_VIRTUAL_W_H 0x00048004 + +struct bcm2835_mbox_tag_virtual_w_h { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + /* req not used for get */ + struct { + u32 width; + u32 height; + } req; + struct { + u32 width; + u32 height; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_DEPTH 0x00040005 +#define BCM2835_MBOX_TAG_TEST_DEPTH 0x00044005 +#define BCM2835_MBOX_TAG_SET_DEPTH 0x00048005 + +struct bcm2835_mbox_tag_depth { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + /* req not used for get */ + struct { + u32 bpp; + } req; + struct { + u32 bpp; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_PIXEL_ORDER 0x00040006 +#define BCM2835_MBOX_TAG_TEST_PIXEL_ORDER 0x00044005 +#define BCM2835_MBOX_TAG_SET_PIXEL_ORDER 0x00048006 + +#define BCM2835_MBOX_PIXEL_ORDER_BGR 0 +#define BCM2835_MBOX_PIXEL_ORDER_RGB 1 + +struct bcm2835_mbox_tag_pixel_order { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + /* req not used for get */ + struct { + u32 order; + } req; + struct { + u32 order; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_ALPHA_MODE 0x00040007 +#define BCM2835_MBOX_TAG_TEST_ALPHA_MODE 0x00044007 +#define BCM2835_MBOX_TAG_SET_ALPHA_MODE 0x00048007 + +#define BCM2835_MBOX_ALPHA_MODE_0_OPAQUE 0 +#define BCM2835_MBOX_ALPHA_MODE_0_TRANSPARENT 1 +#define BCM2835_MBOX_ALPHA_MODE_IGNORED 2 + +struct bcm2835_mbox_tag_alpha_mode { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + /* req not used for get */ + struct { + u32 alpha; + } req; + struct { + u32 alpha; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_PITCH 0x00040008 + +struct bcm2835_mbox_tag_pitch { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + } req; + struct { + u32 pitch; + } resp; + } body; +}; + +/* Offset of display window within buffer */ +#define BCM2835_MBOX_TAG_GET_VIRTUAL_OFFSET 0x00040009 +#define BCM2835_MBOX_TAG_TEST_VIRTUAL_OFFSET 0x00044009 +#define BCM2835_MBOX_TAG_SET_VIRTUAL_OFFSET 0x00048009 + +struct bcm2835_mbox_tag_virtual_offset { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + /* req not used for get */ + struct { + u32 x; + u32 y; + } req; + struct { + u32 x; + u32 y; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_OVERSCAN 0x0004000a +#define BCM2835_MBOX_TAG_TEST_OVERSCAN 0x0004400a +#define BCM2835_MBOX_TAG_SET_OVERSCAN 0x0004800a + +struct bcm2835_mbox_tag_overscan { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + /* req not used for get */ + struct { + u32 top; + u32 bottom; + u32 left; + u32 right; + } req; + struct { + u32 top; + u32 bottom; + u32 left; + u32 right; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_PALETTE 0x0004000b + +struct bcm2835_mbox_tag_get_palette { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + } req; + struct { + u32 data[1024]; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_TEST_PALETTE 0x0004400b + +struct bcm2835_mbox_tag_test_palette { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + u32 offset; + u32 num_entries; + u32 data[256]; + } req; + struct { + u32 is_invalid; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_SET_PALETTE 0x0004800b + +struct bcm2835_mbox_tag_set_palette { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + u32 offset; + u32 num_entries; + u32 data[256]; + } req; + struct { + u32 is_invalid; + } resp; + } body; +}; + +/* + * Pass a complete property-style buffer to the VC, and wait until it has + * been processed. + * + * This function expects a pointer to the mbox_hdr structure in an attempt + * to ensure some degree of type safety. However, some number of tags and + * a termination value are expected to immediately follow the header in + * memory, as required by the property protocol. + * + * Returns 0 for success, any other value for error. + */ +int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer); + +#endif diff --git a/arch/arm/mach-bcm2835/mbox.c b/arch/arm/mach-bcm2835/mbox.c new file mode 100644 index 0000000000..2bca567f39 --- /dev/null +++ b/arch/arm/mach-bcm2835/mbox.c @@ -0,0 +1,152 @@ +/* + * based on U-Boot code + * + * (C) Copyright 2012 Stephen Warren + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/io.h> +#include <asm/mmu.h> +#include <common.h> +#include <clock.h> + +#include <mach/mbox.h> + +#define TIMEOUT (MSECOND * 100) /* 100mS */ + +static int bcm2835_mbox_call_raw(u32 chan, struct bcm2835_mbox_hdr *buffer, + u32 *recv) +{ + struct bcm2835_mbox_regs __iomem *regs = + (struct bcm2835_mbox_regs *)BCM2835_MBOX_PHYSADDR; + uint64_t starttime = get_time_ns(); + u32 send = virt_to_phys(buffer); + u32 val; + + if (send & BCM2835_CHAN_MASK) { + printf("mbox: Illegal mbox data 0x%08x\n", send); + return -EINVAL; + } + + /* Drain any stale responses */ + for (;;) { + val = readl(®s->status); + if (val & BCM2835_MBOX_STATUS_RD_EMPTY) + break; + if (is_timeout(starttime, TIMEOUT)) { + printf("mbox: Timeout draining stale responses\n"); + return -ETIMEDOUT; + } + val = readl(®s->read); + } + + /* Wait for space to send */ + for (;;) { + val = readl(®s->status); + if (!(val & BCM2835_MBOX_STATUS_WR_FULL)) + break; + if (is_timeout(starttime, TIMEOUT)) { + printf("mbox: Timeout waiting for send space\n"); + return -ETIMEDOUT; + } + } + + /* Send the request */ + val = BCM2835_MBOX_PACK(chan, send); + debug("mbox: TX raw: 0x%08x\n", val); + dma_flush_range(send, send + buffer->buf_size); + writel(val, ®s->write); + + /* Wait for the response */ + for (;;) { + val = readl(®s->status); + if (!(val & BCM2835_MBOX_STATUS_RD_EMPTY)) + break; + if (is_timeout(starttime, TIMEOUT)) { + printf("mbox: Timeout waiting for response\n"); + return -ETIMEDOUT; + } + } + + /* Read the response */ + val = readl(®s->read); + debug("mbox: RX raw: 0x%08x\n", val); + dma_inv_range(send, send + buffer->buf_size); + + /* Validate the response */ + if (BCM2835_MBOX_UNPACK_CHAN(val) != chan) { + printf("mbox: Response channel mismatch\n"); + return -EIO; + } + + *recv = BCM2835_MBOX_UNPACK_DATA(val); + + return 0; +} + +#ifdef DEBUG +void dump_buf(struct bcm2835_mbox_hdr *buffer) +{ + u32 *p; + u32 words; + int i; + + p = (u32 *)buffer; + words = buffer->buf_size / 4; + for (i = 0; i < words; i++) + printf(" 0x%04x: 0x%08x\n", i * 4, p[i]); +} +#endif + +int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer) +{ + int ret; + u32 rbuffer; + struct bcm2835_mbox_tag_hdr *tag; + int tag_index; + +#ifdef DEBUG + printf("mbox: TX buffer\n"); + dump_buf(buffer); +#endif + + ret = bcm2835_mbox_call_raw(chan, buffer, &rbuffer); + if (ret) + return ret; + if (rbuffer != (u32)buffer) { + printf("mbox: Response buffer mismatch\n"); + return -EIO; + } + +#ifdef DEBUG + printf("mbox: RX buffer\n"); + dump_buf(buffer); +#endif + + /* Validate overall response status */ + if (buffer->code != BCM2835_MBOX_RESP_CODE_SUCCESS) { + printf("mbox: Header response code invalid\n"); + return -EIO; + } + + /* Validate each tag's response status */ + tag = (void *)(buffer + 1); + tag_index = 0; + while (tag->tag) { + if (!(tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE)) { + printf("mbox: Tag %d missing val_len response bit\n", + tag_index); + return -EIO; + } + /* + * Clear the reponse bit so clients can just look right at the + * length field without extra processing + */ + tag->val_len &= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE; + tag = (void *)(((u8 *)tag) + sizeof(*tag) + tag->val_buf_size); + tag_index++; + } + + return 0; +} diff --git a/arch/ppc/mach-mpc5xxx/cpu.c b/arch/ppc/mach-mpc5xxx/cpu.c index 0ece4a9ed9..c860e709f2 100644 --- a/arch/ppc/mach-mpc5xxx/cpu.c +++ b/arch/ppc/mach-mpc5xxx/cpu.c @@ -77,7 +77,7 @@ void __noreturn reset_cpu (unsigned long addr) /* ------------------------------------------------------------------------- */ #ifdef CONFIG_OFTREE -static int of_mpc5200_fixup(struct device_node *root) +static int of_mpc5200_fixup(struct device_node *root, void *unused) { struct device_node *node; @@ -103,7 +103,7 @@ static int of_mpc5200_fixup(struct device_node *root) static int of_register_mpc5200_fixup(void) { - return of_register_fixup(of_mpc5200_fixup); + return of_register_fixup(of_mpc5200_fixup, NULL); } late_initcall(of_register_mpc5200_fixup); #endif diff --git a/arch/ppc/mach-mpc85xx/fdt.c b/arch/ppc/mach-mpc85xx/fdt.c index 65de6f1104..fd919a56e7 100644 --- a/arch/ppc/mach-mpc85xx/fdt.c +++ b/arch/ppc/mach-mpc85xx/fdt.c @@ -89,7 +89,7 @@ error: return -ENODEV; } -static int fdt_cpu_setup(struct device_node *blob) +static int fdt_cpu_setup(struct device_node *blob, void *unused) { struct device_node *node; struct sys_info sysinfo; @@ -139,6 +139,6 @@ static int fdt_cpu_setup(struct device_node *blob) static int of_register_mpc85xx_fixup(void) { - return of_register_fixup(fdt_cpu_setup); + return of_register_fixup(fdt_cpu_setup, NULL); } late_initcall(of_register_mpc85xx_fixup); |