mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-24 11:16:51 +00:00
Allwinner: u-boot: add support for loading Crust
This commit is contained in:
parent
338fb56238
commit
3cf9be56bd
@ -5,3 +5,5 @@
|
||||
CONFIG_BOOTDELAY=0
|
||||
CONFIG_MACPWR=""
|
||||
# CONFIG_EFI_LOADER is not set
|
||||
CONFIG_SPL_LOAD_FIT=y
|
||||
CONFIG_SPL_FIT_IMAGE_TINY=y
|
||||
|
@ -0,0 +1,181 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Przywara <andre.przywara@arm.com>
|
||||
Date: Wed, 18 Nov 2020 17:32:02 +0000
|
||||
Subject: [PATCH] sunxi: Factor out eGON BROM header description
|
||||
|
||||
To be able to easily share the Allwinner eGON BROM header structure
|
||||
between the tools and the SPL code, move the struct definition into a
|
||||
separate header file.
|
||||
|
||||
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
|
||||
---
|
||||
arch/arm/include/asm/arch-sunxi/spl.h | 65 +--------------------
|
||||
include/sunxi_image.h | 81 +++++++++++++++++++++++++++
|
||||
2 files changed, 82 insertions(+), 64 deletions(-)
|
||||
create mode 100644 include/sunxi_image.h
|
||||
|
||||
--- a/arch/arm/include/asm/arch-sunxi/spl.h
|
||||
+++ b/arch/arm/include/asm/arch-sunxi/spl.h
|
||||
@@ -7,19 +7,7 @@
|
||||
#ifndef _ASM_ARCH_SPL_H_
|
||||
#define _ASM_ARCH_SPL_H_
|
||||
|
||||
-#define BOOT0_MAGIC "eGON.BT0"
|
||||
-#define SPL_SIGNATURE "SPL" /* marks "sunxi" SPL header */
|
||||
-#define SPL_MAJOR_BITS 3
|
||||
-#define SPL_MINOR_BITS 5
|
||||
-#define SPL_VERSION(maj, min) \
|
||||
- ((((maj) & ((1U << SPL_MAJOR_BITS) - 1)) << SPL_MINOR_BITS) | \
|
||||
- ((min) & ((1U << SPL_MINOR_BITS) - 1)))
|
||||
-
|
||||
-#define SPL_HEADER_VERSION SPL_VERSION(0, 2)
|
||||
-
|
||||
-#define SPL_ENV_HEADER_VERSION SPL_VERSION(0, 1)
|
||||
-#define SPL_DT_HEADER_VERSION SPL_VERSION(0, 2)
|
||||
-#define SPL_DRAM_HEADER_VERSION SPL_VERSION(0, 3)
|
||||
+#include <sunxi_image.h>
|
||||
|
||||
#define SPL_ADDR CONFIG_SUNXI_SRAM_ADDRESS
|
||||
|
||||
@@ -31,57 +19,6 @@
|
||||
#define SUNXI_BOOTED_FROM_MMC0_HIGH 0x10
|
||||
#define SUNXI_BOOTED_FROM_MMC2_HIGH 0x12
|
||||
|
||||
-/* boot head definition from sun4i boot code */
|
||||
-struct boot_file_head {
|
||||
- uint32_t b_instruction; /* one intruction jumping to real code */
|
||||
- uint8_t magic[8]; /* ="eGON.BT0" or "eGON.BT1", not C-style str */
|
||||
- uint32_t check_sum; /* generated by PC */
|
||||
- uint32_t length; /* generated by PC */
|
||||
- /*
|
||||
- * We use a simplified header, only filling in what is needed
|
||||
- * by the boot ROM. To be compatible with Allwinner tools we
|
||||
- * would need to implement the proper fields here instead of
|
||||
- * padding.
|
||||
- *
|
||||
- * Actually we want the ability to recognize our "sunxi" variant
|
||||
- * of the SPL. To do so, let's place a special signature into the
|
||||
- * "pub_head_size" field. We can reasonably expect Allwinner's
|
||||
- * boot0 to always have the upper 16 bits of this set to 0 (after
|
||||
- * all the value shouldn't be larger than the limit imposed by
|
||||
- * SRAM size).
|
||||
- * If the signature is present (at 0x14), then we know it's safe
|
||||
- * to use the remaining 8 bytes (at 0x18) for our own purposes.
|
||||
- * (E.g. sunxi-tools "fel" utility can pass information there.)
|
||||
- */
|
||||
- union {
|
||||
- uint32_t pub_head_size;
|
||||
- uint8_t spl_signature[4];
|
||||
- };
|
||||
- uint32_t fel_script_address; /* since v0.1, set by sunxi-fel */
|
||||
- /*
|
||||
- * If the fel_uEnv_length member below is set to a non-zero value,
|
||||
- * it specifies the size (byte count) of data at fel_script_address.
|
||||
- * At the same time this indicates that the data is in uEnv.txt
|
||||
- * compatible format, ready to be imported via "env import -t".
|
||||
- */
|
||||
- uint32_t fel_uEnv_length; /* since v0.1, set by sunxi-fel */
|
||||
- /*
|
||||
- * Offset of an ASCIIZ string (relative to the SPL header), which
|
||||
- * contains the default device tree name (CONFIG_DEFAULT_DEVICE_TREE).
|
||||
- * This is optional and may be set to NULL. Is intended to be used
|
||||
- * by flash programming tools for providing nice informative messages
|
||||
- * to the users.
|
||||
- */
|
||||
- uint32_t dt_name_offset; /* since v0.2, set by mksunxiboot */
|
||||
- uint32_t dram_size; /* in MiB, since v0.3, set by SPL */
|
||||
- uint32_t boot_media; /* written here by the boot ROM */
|
||||
- /* A padding area (may be used for storing text strings) */
|
||||
- uint32_t string_pool[13]; /* since v0.2, filled by mksunxiboot */
|
||||
- /* The header must be a multiple of 32 bytes (for VBAR alignment) */
|
||||
-};
|
||||
-
|
||||
-/* Compile time check to assure proper alignment of structure */
|
||||
-typedef char boot_file_head_not_multiple_of_32[1 - 2*(sizeof(struct boot_file_head) % 32)];
|
||||
|
||||
#define is_boot0_magic(addr) (memcmp((void *)addr, BOOT0_MAGIC, 8) == 0)
|
||||
|
||||
--- /dev/null
|
||||
+++ b/include/sunxi_image.h
|
||||
@@ -0,0 +1,81 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
+/*
|
||||
+ * (C) Copyright 2007-2011
|
||||
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
|
||||
+ * Tom Cubie <tangliang@allwinnertech.com>
|
||||
+ *
|
||||
+ * Constants and data structures used in Allwinner "eGON" images, as
|
||||
+ * parsed by the Boot-ROM.
|
||||
+ *
|
||||
+ * Shared between mkimage and the SPL.
|
||||
+ */
|
||||
+#ifndef SUNXI_IMAGE_H
|
||||
+#define SUNXI_IMAGE_H
|
||||
+
|
||||
+#define BOOT0_MAGIC "eGON.BT0"
|
||||
+#define SPL_SIGNATURE "SPL" /* marks "sunxi" SPL header */
|
||||
+#define SPL_MAJOR_BITS 3
|
||||
+#define SPL_MINOR_BITS 5
|
||||
+#define SPL_VERSION(maj, min) \
|
||||
+ ((((maj) & ((1U << SPL_MAJOR_BITS) - 1)) << SPL_MINOR_BITS) | \
|
||||
+ ((min) & ((1U << SPL_MINOR_BITS) - 1)))
|
||||
+
|
||||
+#define SPL_HEADER_VERSION SPL_VERSION(0, 2)
|
||||
+
|
||||
+#define SPL_ENV_HEADER_VERSION SPL_VERSION(0, 1)
|
||||
+#define SPL_DT_HEADER_VERSION SPL_VERSION(0, 2)
|
||||
+#define SPL_DRAM_HEADER_VERSION SPL_VERSION(0, 3)
|
||||
+
|
||||
+/* boot head definition from sun4i boot code */
|
||||
+struct boot_file_head {
|
||||
+ uint32_t b_instruction; /* one intruction jumping to real code */
|
||||
+ uint8_t magic[8]; /* ="eGON.BT0" or "eGON.BT1", not C-style str */
|
||||
+ uint32_t check_sum; /* generated by PC */
|
||||
+ uint32_t length; /* generated by PC */
|
||||
+ /*
|
||||
+ * We use a simplified header, only filling in what is needed
|
||||
+ * by the boot ROM. To be compatible with Allwinner tools we
|
||||
+ * would need to implement the proper fields here instead of
|
||||
+ * padding.
|
||||
+ *
|
||||
+ * Actually we want the ability to recognize our "sunxi" variant
|
||||
+ * of the SPL. To do so, let's place a special signature into the
|
||||
+ * "pub_head_size" field. We can reasonably expect Allwinner's
|
||||
+ * boot0 to always have the upper 16 bits of this set to 0 (after
|
||||
+ * all the value shouldn't be larger than the limit imposed by
|
||||
+ * SRAM size).
|
||||
+ * If the signature is present (at 0x14), then we know it's safe
|
||||
+ * to use the remaining 8 bytes (at 0x18) for our own purposes.
|
||||
+ * (E.g. sunxi-tools "fel" utility can pass information there.)
|
||||
+ */
|
||||
+ union {
|
||||
+ uint32_t pub_head_size;
|
||||
+ uint8_t spl_signature[4];
|
||||
+ };
|
||||
+ uint32_t fel_script_address; /* since v0.1, set by sunxi-fel */
|
||||
+ /*
|
||||
+ * If the fel_uEnv_length member below is set to a non-zero value,
|
||||
+ * it specifies the size (byte count) of data at fel_script_address.
|
||||
+ * At the same time this indicates that the data is in uEnv.txt
|
||||
+ * compatible format, ready to be imported via "env import -t".
|
||||
+ */
|
||||
+ uint32_t fel_uEnv_length; /* since v0.1, set by sunxi-fel */
|
||||
+ /*
|
||||
+ * Offset of an ASCIIZ string (relative to the SPL header), which
|
||||
+ * contains the default device tree name (CONFIG_DEFAULT_DEVICE_TREE).
|
||||
+ * This is optional and may be set to NULL. Is intended to be used
|
||||
+ * by flash programming tools for providing nice informative messages
|
||||
+ * to the users.
|
||||
+ */
|
||||
+ uint32_t dt_name_offset; /* since v0.2, set by mksunxiboot */
|
||||
+ uint32_t dram_size; /* in MiB, since v0.3, set by SPL */
|
||||
+ uint32_t boot_media; /* written here by the boot ROM */
|
||||
+ /* A padding area (may be used for storing text strings) */
|
||||
+ uint32_t string_pool[13]; /* since v0.2, filled by mksunxiboot */
|
||||
+ /* The header must be a multiple of 32 bytes (for VBAR alignment) */
|
||||
+};
|
||||
+
|
||||
+/* Compile time check to assure proper alignment of structure */
|
||||
+typedef char boot_file_head_not_multiple_of_32[1 - 2*(sizeof(struct boot_file_head) % 32)];
|
||||
+
|
||||
+#endif
|
@ -0,0 +1,202 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Przywara <andre.przywara@arm.com>
|
||||
Date: Wed, 18 Nov 2020 17:32:03 +0000
|
||||
Subject: [PATCH] tools: mkimage: Add Allwinner eGON support
|
||||
|
||||
So far we used the separate mksunxiboot tool for generating a bootable
|
||||
image for Allwinner SPLs, probably just for historical reasons.
|
||||
|
||||
Use the mkimage framework to generate a so called eGON image the
|
||||
Allwinner BROM expects.
|
||||
The new image type is called "sunxi_egon", to differentiate it
|
||||
from the (still to be implemented) secure boot TOC0 image.
|
||||
|
||||
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
|
||||
---
|
||||
common/image.c | 1 +
|
||||
include/image.h | 1 +
|
||||
include/sunxi_image.h | 1 +
|
||||
tools/Makefile | 1 +
|
||||
tools/sunxi_egon.c | 136 ++++++++++++++++++++++++++++++++++++++++++
|
||||
5 files changed, 140 insertions(+)
|
||||
create mode 100644 tools/sunxi_egon.c
|
||||
|
||||
--- a/common/image.c
|
||||
+++ b/common/image.c
|
||||
@@ -189,6 +189,7 @@ static const table_entry_t uimage_type[]
|
||||
{ IH_TYPE_STM32IMAGE, "stm32image", "STMicroelectronics STM32 Image" },
|
||||
{ IH_TYPE_MTKIMAGE, "mtk_image", "MediaTek BootROM loadable Image" },
|
||||
{ IH_TYPE_COPRO, "copro", "Coprocessor Image"},
|
||||
+ { IH_TYPE_SUNXI_EGON, "sunxi_egon", "Allwinner eGON Boot Image" },
|
||||
{ -1, "", "", },
|
||||
};
|
||||
|
||||
--- a/include/image.h
|
||||
+++ b/include/image.h
|
||||
@@ -308,6 +308,7 @@ enum {
|
||||
IH_TYPE_IMX8MIMAGE, /* Freescale IMX8MBoot Image */
|
||||
IH_TYPE_IMX8IMAGE, /* Freescale IMX8Boot Image */
|
||||
IH_TYPE_COPRO, /* Coprocessor Image for remoteproc*/
|
||||
+ IH_TYPE_SUNXI_EGON, /* Allwinner eGON Boot Image */
|
||||
|
||||
IH_TYPE_COUNT, /* Number of image types */
|
||||
};
|
||||
--- a/include/sunxi_image.h
|
||||
+++ b/include/sunxi_image.h
|
||||
@@ -13,6 +13,7 @@
|
||||
#define SUNXI_IMAGE_H
|
||||
|
||||
#define BOOT0_MAGIC "eGON.BT0"
|
||||
+#define BROM_STAMP_VALUE 0x5f0a6c39
|
||||
#define SPL_SIGNATURE "SPL" /* marks "sunxi" SPL header */
|
||||
#define SPL_MAJOR_BITS 3
|
||||
#define SPL_MINOR_BITS 5
|
||||
--- a/tools/Makefile
|
||||
+++ b/tools/Makefile
|
||||
@@ -104,6 +104,7 @@ dumpimage-mkimage-objs := aisimage.o \
|
||||
stm32image.o \
|
||||
$(ROCKCHIP_OBS) \
|
||||
socfpgaimage.o \
|
||||
+ sunxi_egon.o \
|
||||
lib/crc16.o \
|
||||
lib/sha1.o \
|
||||
lib/sha256.o \
|
||||
--- /dev/null
|
||||
+++ b/tools/sunxi_egon.c
|
||||
@@ -0,0 +1,136 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0+
|
||||
+/*
|
||||
+ * (C) Copyright 2018 Arm Ltd.
|
||||
+ */
|
||||
+
|
||||
+#include "imagetool.h"
|
||||
+#include <image.h>
|
||||
+
|
||||
+#include <sunxi_image.h>
|
||||
+
|
||||
+/*
|
||||
+ * NAND requires 8K padding. SD/eMMC gets away with 512 bytes,
|
||||
+ * but let's use the larger padding to cover both.
|
||||
+ */
|
||||
+#define PAD_SIZE 8192
|
||||
+
|
||||
+static int egon_check_params(struct image_tool_params *params)
|
||||
+{
|
||||
+ /* We just need a binary image file. */
|
||||
+ return !params->dflag;
|
||||
+}
|
||||
+
|
||||
+static int egon_verify_header(unsigned char *ptr, int image_size,
|
||||
+ struct image_tool_params *params)
|
||||
+{
|
||||
+ const struct boot_file_head *header = (void *)ptr;
|
||||
+ uint32_t length;
|
||||
+
|
||||
+ /* First 4 bytes must be an ARM branch instruction. */
|
||||
+ if ((le32_to_cpu(header->b_instruction) & 0xff000000) != 0xea000000)
|
||||
+ return EXIT_FAILURE;
|
||||
+
|
||||
+ if (memcmp(header->magic, BOOT0_MAGIC, sizeof(header->magic)))
|
||||
+ return EXIT_FAILURE;
|
||||
+
|
||||
+ length = le32_to_cpu(header->length);
|
||||
+ /* Must be at least 512 byte aligned. */
|
||||
+ if (length & 511)
|
||||
+ return EXIT_FAILURE;
|
||||
+
|
||||
+ /*
|
||||
+ * Image could also contain U-Boot proper, so could be bigger.
|
||||
+ * But it must not be shorter.
|
||||
+ */
|
||||
+ if (image_size < length)
|
||||
+ return EXIT_FAILURE;
|
||||
+
|
||||
+ return EXIT_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+static void egon_print_header(const void *buf)
|
||||
+{
|
||||
+ const struct boot_file_head *header = buf;
|
||||
+
|
||||
+ printf("Allwinner eGON image, size: %d bytes\n",
|
||||
+ le32_to_cpu(header->length));
|
||||
+
|
||||
+ if (memcmp(header->spl_signature, SPL_SIGNATURE, 3))
|
||||
+ return;
|
||||
+
|
||||
+ printf("\tSPL header version %d.%d\n",
|
||||
+ header->spl_signature[3] >> SPL_MINOR_BITS,
|
||||
+ header->spl_signature[3] & ((1U << SPL_MINOR_BITS) - 1));
|
||||
+ if (header->spl_signature[3] >= SPL_DT_HEADER_VERSION) {
|
||||
+ uint32_t dt_name_offs = le32_to_cpu(header->dt_name_offset);
|
||||
+
|
||||
+ if (dt_name_offs > 0)
|
||||
+ printf("\tDT name: %s\n", (char *)buf + dt_name_offs);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void egon_set_header(void *buf, struct stat *sbuf, int infd,
|
||||
+ struct image_tool_params *params)
|
||||
+{
|
||||
+ struct boot_file_head *header = buf;
|
||||
+ uint32_t *buf32 = buf;
|
||||
+ uint32_t checksum = 0, value;
|
||||
+ int i;
|
||||
+
|
||||
+ /* Generate an ARM branch instruction to jump over the header. */
|
||||
+ value = 0xea000000 | (sizeof(struct boot_file_head) / 4 - 2);
|
||||
+ header->b_instruction = cpu_to_le32(value);
|
||||
+
|
||||
+ memcpy(header->magic, BOOT0_MAGIC, sizeof(header->magic));
|
||||
+ header->check_sum = cpu_to_le32(BROM_STAMP_VALUE);
|
||||
+ header->length = cpu_to_le32(params->file_size);
|
||||
+
|
||||
+ memcpy(header->spl_signature, SPL_SIGNATURE, 3);
|
||||
+
|
||||
+ /* If an image name has been provided, use it as the DT name. */
|
||||
+ if (params->imagename && params->imagename[0]) {
|
||||
+ header->spl_signature[3] = SPL_DT_HEADER_VERSION;
|
||||
+
|
||||
+ value = offsetof(struct boot_file_head, string_pool);
|
||||
+ header->dt_name_offset = cpu_to_le32(value);
|
||||
+
|
||||
+ strncpy((char *)header->string_pool, params->imagename, 52);
|
||||
+ /* Make sure we have a terminating zero byte. */
|
||||
+ ((char *)header->string_pool)[51] = 0;
|
||||
+ } else
|
||||
+ header->spl_signature[3] = SPL_ENV_HEADER_VERSION;
|
||||
+
|
||||
+ /* Calculate the checksum. Yes, it's that simple. */
|
||||
+ for (i = 0; i < sbuf->st_size / 4; i++)
|
||||
+ checksum += le32_to_cpu(buf32[i]);
|
||||
+ header->check_sum = cpu_to_le32(checksum);
|
||||
+}
|
||||
+
|
||||
+static int egon_check_image_type(uint8_t type)
|
||||
+{
|
||||
+ return type == IH_TYPE_SUNXI_EGON ? 0 : 1;
|
||||
+}
|
||||
+
|
||||
+static int egon_vrec_header(struct image_tool_params *params,
|
||||
+ struct image_type_params *tparams)
|
||||
+{
|
||||
+ tparams->hdr = calloc(sizeof(struct boot_file_head), 1);
|
||||
+
|
||||
+ /* Return padding to 8K blocks. */
|
||||
+ return ALIGN(params->file_size, PAD_SIZE) - params->file_size;
|
||||
+}
|
||||
+
|
||||
+U_BOOT_IMAGE_TYPE(
|
||||
+ sunxi_egon,
|
||||
+ "Allwinner eGON Boot Image support",
|
||||
+ sizeof(struct boot_file_head),
|
||||
+ NULL,
|
||||
+ egon_check_params,
|
||||
+ egon_verify_header,
|
||||
+ egon_print_header,
|
||||
+ egon_set_header,
|
||||
+ NULL,
|
||||
+ egon_check_image_type,
|
||||
+ NULL,
|
||||
+ egon_vrec_header
|
||||
+);
|
@ -0,0 +1,35 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Przywara <andre.przywara@arm.com>
|
||||
Date: Wed, 18 Nov 2020 17:32:04 +0000
|
||||
Subject: [PATCH] sunxi: Use mkimage for SPL boot image generation
|
||||
|
||||
Switch the SPL boot image generation from using mksunxiboot to the new
|
||||
sunxi_egon format of mkimage.
|
||||
|
||||
Verified to create identical results for all 152 Allwinner boards.
|
||||
|
||||
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
|
||||
Reviewed-by: Simon Glass <sjg@chromium.org>
|
||||
Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
|
||||
---
|
||||
scripts/Makefile.spl | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/scripts/Makefile.spl
|
||||
+++ b/scripts/Makefile.spl
|
||||
@@ -382,11 +382,11 @@ endif
|
||||
$(obj)/$(SPL_BIN).sfp: $(obj)/$(SPL_BIN).bin FORCE
|
||||
$(call if_changed,mkimage)
|
||||
|
||||
-quiet_cmd_mksunxiboot = MKSUNXI $@
|
||||
-cmd_mksunxiboot = $(objtree)/tools/mksunxiboot \
|
||||
- --default-dt $(CONFIG_DEFAULT_DEVICE_TREE) $< $@
|
||||
+MKIMAGEFLAGS_sunxi-spl.bin = -T sunxi_egon \
|
||||
+ -n $(CONFIG_DEFAULT_DEVICE_TREE)
|
||||
+
|
||||
$(obj)/sunxi-spl.bin: $(obj)/$(SPL_BIN).bin FORCE
|
||||
- $(call if_changed,mksunxiboot)
|
||||
+ $(call if_changed,mkimage)
|
||||
|
||||
quiet_cmd_sunxi_spl_image_builder = SUNXI_SPL_IMAGE_BUILDER $@
|
||||
cmd_sunxi_spl_image_builder = $(objtree)/tools/sunxi-spl-image-builder \
|
@ -0,0 +1,51 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Holland <samuel@sholland.org>
|
||||
Date: Fri, 20 Nov 2020 01:26:34 -0600
|
||||
Subject: [PATCH] sunxi: Put secure monitor in SRAM A2
|
||||
|
||||
Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
---
|
||||
arch/arm/include/asm/arch-sunxi/cpu.h | 9 +++++++++
|
||||
arch/arm/include/asm/arch-sunxi/cpu_sun4i.h | 1 -
|
||||
include/configs/sunxi-common.h | 2 ++
|
||||
3 files changed, 11 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/arm/include/asm/arch-sunxi/cpu.h
|
||||
+++ b/arch/arm/include/asm/arch-sunxi/cpu.h
|
||||
@@ -14,6 +14,15 @@
|
||||
#include <asm/arch/cpu_sun4i.h>
|
||||
#endif
|
||||
|
||||
+#if defined(CONFIG_MACH_SUN4I)
|
||||
+#define SUNXI_SRAM_A2_BASE 0x00004000
|
||||
+#elif defined(CONFIG_MACH_SUN6I) || \
|
||||
+ defined(CONFIG_MACH_SUN8I) || \
|
||||
+ defined(CONFIG_MACH_SUN50I) || \
|
||||
+ defined(CONFIG_MACH_SUN50I_H5)
|
||||
+#define SUNXI_SRAM_A2_BASE 0x00040000
|
||||
+#endif
|
||||
+
|
||||
#define SOCID_A64 0x1689
|
||||
#define SOCID_H3 0x1680
|
||||
#define SOCID_V3S 0x1681
|
||||
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
|
||||
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
|
||||
@@ -11,7 +11,6 @@
|
||||
#define SUNXI_SRAM_A1_BASE 0x00000000
|
||||
#define SUNXI_SRAM_A1_SIZE (16 * 1024) /* 16 kiB */
|
||||
|
||||
-#define SUNXI_SRAM_A2_BASE 0x00004000 /* 16 kiB */
|
||||
#define SUNXI_SRAM_A3_BASE 0x00008000 /* 13 kiB */
|
||||
#define SUNXI_SRAM_A4_BASE 0x0000b400 /* 3 kiB */
|
||||
#define SUNXI_SRAM_D_BASE 0x00010000 /* 4 kiB */
|
||||
--- a/include/configs/sunxi-common.h
|
||||
+++ b/include/configs/sunxi-common.h
|
||||
@@ -192,6 +192,8 @@
|
||||
|
||||
#define CONFIG_SPL_PAD_TO 32768 /* decimal for 'dd' */
|
||||
|
||||
+#define CONFIG_ARMV7_SECURE_BASE SUNXI_SRAM_A2_BASE + 0x4000
|
||||
+#define CONFIG_ARMV7_SECURE_MAX_SIZE (16 * 1024) /* 16 KB */
|
||||
|
||||
/* I2C */
|
||||
#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
|
@ -0,0 +1,575 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Holland <samuel@sholland.org>
|
||||
Date: Fri, 20 Nov 2020 01:25:26 -0600
|
||||
Subject: [PATCH] sunxi: A wild PSCI implementation appears...
|
||||
|
||||
Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
---
|
||||
arch/arm/cpu/armv7/Kconfig | 1 -
|
||||
arch/arm/cpu/armv7/sunxi/Makefile | 2 +-
|
||||
arch/arm/cpu/armv7/sunxi/psci-scpi.c | 463 +++++++++++++++++++++++++++
|
||||
arch/arm/include/asm/psci.h | 9 +-
|
||||
arch/arm/include/asm/system.h | 13 +-
|
||||
tools/sunxi_egon.c | 2 +-
|
||||
6 files changed, 480 insertions(+), 10 deletions(-)
|
||||
create mode 100644 arch/arm/cpu/armv7/sunxi/psci-scpi.c
|
||||
|
||||
--- a/arch/arm/cpu/armv7/Kconfig
|
||||
+++ b/arch/arm/cpu/armv7/Kconfig
|
||||
@@ -44,7 +44,6 @@ config ARMV7_PSCI
|
||||
choice
|
||||
prompt "Supported PSCI version"
|
||||
depends on ARMV7_PSCI
|
||||
- default ARMV7_PSCI_0_1 if ARCH_SUNXI
|
||||
default ARMV7_PSCI_1_0
|
||||
help
|
||||
Select the supported PSCI version.
|
||||
--- a/arch/arm/cpu/armv7/sunxi/Makefile
|
||||
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
|
||||
@@ -11,7 +11,7 @@ obj-$(CONFIG_MACH_SUN6I) += tzpc.o
|
||||
obj-$(CONFIG_MACH_SUN8I_H3) += tzpc.o
|
||||
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
-obj-$(CONFIG_ARMV7_PSCI) += psci.o
|
||||
+obj-$(CONFIG_ARMV7_PSCI) += psci-scpi.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/cpu/armv7/sunxi/psci-scpi.c
|
||||
@@ -0,0 +1,463 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright (C) 2016
|
||||
+ * Author: Chen-Yu Tsai <wens@csie.org>
|
||||
+ *
|
||||
+ * Based on assembly code by Marc Zyngier <marc.zyngier@arm.com>,
|
||||
+ * which was based on code by Carl van Schaik <carl@ok-labs.com>.
|
||||
+ */
|
||||
+
|
||||
+#include <config.h>
|
||||
+#include <common.h>
|
||||
+#include <asm/cache.h>
|
||||
+
|
||||
+#include <asm/arch/cpu.h>
|
||||
+#include <asm/arch/cpucfg.h>
|
||||
+#include <asm/arch/prcm.h>
|
||||
+#include <asm/armv7.h>
|
||||
+#include <asm/gic.h>
|
||||
+#include <asm/io.h>
|
||||
+#include <asm/psci.h>
|
||||
+#include <asm/secure.h>
|
||||
+#include <asm/system.h>
|
||||
+
|
||||
+#define SUNXI_SCP_BASE 0x00048000
|
||||
+#define SUNXI_SCP_MAGIC 0xb4400012
|
||||
+
|
||||
+#define OR1K_VEC_FIRST 0x01
|
||||
+#define OR1K_VEC_LAST 0x0e
|
||||
+#define OR1K_VEC_ADDR(n) (0x100 * (n))
|
||||
+
|
||||
+#define GICD_BASE (SUNXI_GIC400_BASE + GIC_DIST_OFFSET)
|
||||
+#define GICC_BASE (SUNXI_GIC400_BASE + GIC_CPU_OFFSET_A15)
|
||||
+
|
||||
+#define HW_ON 0
|
||||
+#define HW_OFF 1
|
||||
+#define HW_STANDBY 2
|
||||
+
|
||||
+#define MPIDR_AFFLVL0(mpidr) (mpidr & 0xf)
|
||||
+#define MPIDR_AFFLVL1(mpidr) (mpidr >> 8 & 0xf)
|
||||
+
|
||||
+enum {
|
||||
+ CORE_POWER_LEVEL = 0,
|
||||
+ CLUSTER_POWER_LEVEL = 1,
|
||||
+ CSS_POWER_LEVEL = 2,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ SCPI_CMD_SCP_READY = 0x01,
|
||||
+ SCPI_CMD_SET_CSS_POWER_STATE = 0x03,
|
||||
+ SCPI_CMD_GET_CSS_POWER_STATE = 0x04,
|
||||
+ SCPI_CMD_SET_SYS_POWER_STATE = 0x05,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ SCPI_E_OK = 0,
|
||||
+ SCPI_E_PARAM = 1,
|
||||
+ SCPI_E_ALIGN = 2,
|
||||
+ SCPI_E_SIZE = 3,
|
||||
+ SCPI_E_HANDLER = 4,
|
||||
+ SCPI_E_ACCESS = 5,
|
||||
+ SCPI_E_RANGE = 6,
|
||||
+ SCPI_E_TIMEOUT = 7,
|
||||
+ SCPI_E_NOMEM = 8,
|
||||
+ SCPI_E_PWRSTATE = 9,
|
||||
+ SCPI_E_SUPPORT = 10,
|
||||
+ SCPI_E_DEVICE = 11,
|
||||
+ SCPI_E_BUSY = 12,
|
||||
+ SCPI_E_OS = 13,
|
||||
+ SCPI_E_DATA = 14,
|
||||
+ SCPI_E_STATE = 15,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ SCPI_POWER_ON = 0x00,
|
||||
+ SCPI_POWER_RETENTION = 0x01,
|
||||
+ SCPI_POWER_OFF = 0x03,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ SCPI_SYSTEM_SHUTDOWN = 0x00,
|
||||
+ SCPI_SYSTEM_REBOOT = 0x01,
|
||||
+ SCPI_SYSTEM_RESET = 0x02,
|
||||
+};
|
||||
+
|
||||
+#define SCPI_SHMEM_BASE 0x0004be00
|
||||
+#define SCPI_SHMEM ((struct scpi_shmem *)SCPI_SHMEM_BASE)
|
||||
+
|
||||
+#define SCPI_MESSAGE_SIZE 0x100
|
||||
+#define SCPI_PAYLOAD_SIZE (SCPI_MESSAGE_SIZE - sizeof(struct scpi_header))
|
||||
+
|
||||
+#define SCPI_RX_CHANNEL 1
|
||||
+#define SCPI_TX_CHANNEL 0
|
||||
+#define SCPI_VIRTUAL_CHANNEL BIT(0)
|
||||
+
|
||||
+struct scpi_header {
|
||||
+ u8 command;
|
||||
+ u8 sender;
|
||||
+ u16 size;
|
||||
+ u32 status;
|
||||
+};
|
||||
+
|
||||
+struct scpi_message {
|
||||
+ struct scpi_header header;
|
||||
+ u8 payload[SCPI_PAYLOAD_SIZE];
|
||||
+};
|
||||
+
|
||||
+struct scpi_shmem {
|
||||
+ struct scpi_message rx;
|
||||
+ struct scpi_message tx;
|
||||
+};
|
||||
+
|
||||
+#define SUNXI_MSGBOX_BASE 0x01c17000
|
||||
+#define REMOTE_IRQ_STAT_REG (SUNXI_MSGBOX_BASE + 0x0050)
|
||||
+#define LOCAL_IRQ_STAT_REG (SUNXI_MSGBOX_BASE + 0x0070)
|
||||
+#define MSG_STAT_REG(n) (SUNXI_MSGBOX_BASE + 0x0140 + 0x4 * (n))
|
||||
+#define MSG_DATA_REG(n) (SUNXI_MSGBOX_BASE + 0x0180 + 0x4 * (n))
|
||||
+
|
||||
+#define RX_IRQ(n) BIT(0 + 2 * (n))
|
||||
+#define TX_IRQ(n) BIT(1 + 2 * (n))
|
||||
+
|
||||
+static u32 __secure_data ccu_save[2];
|
||||
+
|
||||
+static u32 __secure_data lock;
|
||||
+
|
||||
+static inline u32 __secure read_mpidr(void)
|
||||
+{
|
||||
+ u32 v;
|
||||
+ asm volatile ("mrc p15, 0, %0, c0, c0, 5" : "=r" (v));
|
||||
+ return v;
|
||||
+}
|
||||
+
|
||||
+static void __secure scpi_begin_command(void)
|
||||
+{
|
||||
+ u32 mpidr = read_mpidr();
|
||||
+
|
||||
+ do {
|
||||
+ while (readl(&lock));
|
||||
+ writel(mpidr, &lock);
|
||||
+ dsb();
|
||||
+ } while (readl(&lock) != mpidr);
|
||||
+ while (readl(REMOTE_IRQ_STAT_REG) & RX_IRQ(SCPI_TX_CHANNEL));
|
||||
+}
|
||||
+
|
||||
+static void __secure scpi_send_command(void)
|
||||
+{
|
||||
+ writel(SCPI_VIRTUAL_CHANNEL, MSG_DATA_REG(SCPI_TX_CHANNEL));
|
||||
+}
|
||||
+
|
||||
+static void __secure scpi_wait_response(void)
|
||||
+{
|
||||
+ while (!readl(MSG_STAT_REG(SCPI_RX_CHANNEL)));
|
||||
+}
|
||||
+
|
||||
+static void __secure scpi_end_command(void)
|
||||
+{
|
||||
+ while (readl(MSG_STAT_REG(SCPI_RX_CHANNEL)))
|
||||
+ readl(MSG_DATA_REG(SCPI_RX_CHANNEL));
|
||||
+ writel(RX_IRQ(SCPI_RX_CHANNEL), LOCAL_IRQ_STAT_REG);
|
||||
+ writel(0, &lock);
|
||||
+}
|
||||
+
|
||||
+static void __secure scpi_set_css_power_state(u32 target_cpu, u32 core_state,
|
||||
+ u32 cluster_state, u32 css_state)
|
||||
+{
|
||||
+ struct scpi_shmem *shmem = SCPI_SHMEM;
|
||||
+
|
||||
+ scpi_begin_command();
|
||||
+
|
||||
+ shmem->tx.header.command = SCPI_CMD_SET_CSS_POWER_STATE;
|
||||
+ shmem->tx.header.size = 4;
|
||||
+
|
||||
+ shmem->tx.payload[0] = target_cpu >> 4 | target_cpu;
|
||||
+ shmem->tx.payload[1] = cluster_state << 4 | core_state;
|
||||
+ shmem->tx.payload[2] = css_state;
|
||||
+ shmem->tx.payload[3] = 0;
|
||||
+
|
||||
+ scpi_send_command();
|
||||
+ scpi_end_command();
|
||||
+}
|
||||
+
|
||||
+static s32 __secure scpi_get_css_power_state(u32 target_cpu, u8 *core_states,
|
||||
+ u8 *cluster_state)
|
||||
+{
|
||||
+ struct scpi_shmem *shmem = SCPI_SHMEM;
|
||||
+ u32 cluster = MPIDR_AFFLVL1(target_cpu);
|
||||
+ u32 offset;
|
||||
+ s32 ret;
|
||||
+
|
||||
+ scpi_begin_command();
|
||||
+
|
||||
+ shmem->tx.header.command = SCPI_CMD_GET_CSS_POWER_STATE;
|
||||
+ shmem->tx.header.size = 0;
|
||||
+
|
||||
+ scpi_send_command();
|
||||
+ scpi_wait_response();
|
||||
+
|
||||
+ for (offset = 0; offset < shmem->rx.header.size; offset += 2) {
|
||||
+ if ((shmem->rx.payload[offset] & 0xf) == cluster) {
|
||||
+ *cluster_state = shmem->rx.payload[offset+0] >> 4;
|
||||
+ *core_states = shmem->rx.payload[offset+1];
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ret = shmem->rx.header.status;
|
||||
+
|
||||
+ scpi_end_command();
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static s32 __secure scpi_set_sys_power_state(u32 sys_state)
|
||||
+{
|
||||
+ struct scpi_shmem *shmem = SCPI_SHMEM;
|
||||
+ s32 ret;
|
||||
+
|
||||
+ scpi_begin_command();
|
||||
+
|
||||
+ shmem->tx.header.command = SCPI_CMD_SET_SYS_POWER_STATE;
|
||||
+ shmem->tx.header.size = 1;
|
||||
+
|
||||
+ shmem->tx.payload[0] = sys_state;
|
||||
+
|
||||
+ scpi_send_command();
|
||||
+ scpi_wait_response();
|
||||
+
|
||||
+ ret = shmem->rx.header.status;
|
||||
+
|
||||
+ scpi_end_command();
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+void psci_enable_smp(void);
|
||||
+
|
||||
+static s32 __secure psci_suspend_common(u32 pc, u32 context_id, u32 core_state,
|
||||
+ u32 cluster_state, u32 css_state)
|
||||
+
|
||||
+{
|
||||
+ u32 target_cpu = read_mpidr();
|
||||
+
|
||||
+ if (core_state == SCPI_POWER_OFF) {
|
||||
+ psci_save(MPIDR_AFFLVL0(target_cpu), pc, context_id);
|
||||
+
|
||||
+ if (MPIDR_AFFLVL0(target_cpu) == 0) {
|
||||
+ ccu_save[0] = readl(0x1c20050);
|
||||
+ ccu_save[1] = readl(0x1c20054);
|
||||
+ writel((ccu_save[1] & ~(3 << 12)) | (1 << 12), 0x1c20054);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ scpi_set_css_power_state(target_cpu, core_state,
|
||||
+ cluster_state, css_state);
|
||||
+
|
||||
+ psci_cpu_off_common();
|
||||
+
|
||||
+ wfi();
|
||||
+
|
||||
+ psci_enable_smp();
|
||||
+
|
||||
+ return ARM_PSCI_RET_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+u32 __secure psci_version(void)
|
||||
+{
|
||||
+ return ARM_PSCI_VER_1_1;
|
||||
+}
|
||||
+
|
||||
+s32 __secure psci_cpu_suspend(u32 __always_unused function_id,
|
||||
+ u32 power_state, u32 pc, u32 context_id)
|
||||
+{
|
||||
+ return psci_suspend_common(pc, context_id,
|
||||
+ power_state >> 0 & 0xf,
|
||||
+ power_state >> 4 & 0xf,
|
||||
+ power_state >> 8 & 0xf);
|
||||
+}
|
||||
+
|
||||
+s32 __secure psci_cpu_off(void)
|
||||
+{
|
||||
+ u32 pc = 0, context_id = 0;
|
||||
+
|
||||
+ return psci_suspend_common(pc, context_id, SCPI_POWER_OFF,
|
||||
+ SCPI_POWER_OFF, SCPI_POWER_ON);
|
||||
+}
|
||||
+
|
||||
+s32 __secure psci_cpu_on(u32 __always_unused function_id,
|
||||
+ u32 target_cpu, u32 pc, u32 context_id)
|
||||
+{
|
||||
+ psci_save(MPIDR_AFFLVL0(target_cpu), pc, context_id);
|
||||
+
|
||||
+ scpi_set_css_power_state(target_cpu, SCPI_POWER_ON,
|
||||
+ SCPI_POWER_ON, SCPI_POWER_ON);
|
||||
+
|
||||
+ return ARM_PSCI_RET_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+s32 __secure psci_affinity_info(u32 function_id,
|
||||
+ u32 target_cpu, u32 power_level)
|
||||
+{
|
||||
+ if (power_level != CORE_POWER_LEVEL)
|
||||
+ return ARM_PSCI_RET_INVAL;
|
||||
+
|
||||
+ /* This happens to have the same HW_ON/HW_OFF encoding. */
|
||||
+ return psci_node_hw_state(function_id, target_cpu, power_level);
|
||||
+}
|
||||
+
|
||||
+void __secure psci_system_off(void)
|
||||
+{
|
||||
+ scpi_set_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
|
||||
+
|
||||
+ /* Wait to be turned off. */
|
||||
+ for (;;) wfi();
|
||||
+}
|
||||
+
|
||||
+void __secure psci_system_reset(void)
|
||||
+{
|
||||
+ scpi_set_sys_power_state(SCPI_SYSTEM_REBOOT);
|
||||
+
|
||||
+ /* Wait to be turned off. */
|
||||
+ for (;;) wfi();
|
||||
+}
|
||||
+
|
||||
+s32 __secure psci_features(u32 __always_unused function_id,
|
||||
+ u32 psci_fid)
|
||||
+{
|
||||
+ switch (psci_fid) {
|
||||
+ case ARM_PSCI_0_2_FN_PSCI_VERSION:
|
||||
+ case ARM_PSCI_0_2_FN_CPU_SUSPEND:
|
||||
+ case ARM_PSCI_0_2_FN_CPU_OFF:
|
||||
+ case ARM_PSCI_0_2_FN_CPU_ON:
|
||||
+ case ARM_PSCI_0_2_FN_AFFINITY_INFO:
|
||||
+ case ARM_PSCI_0_2_FN_SYSTEM_OFF:
|
||||
+ case ARM_PSCI_0_2_FN_SYSTEM_RESET:
|
||||
+ case ARM_PSCI_1_0_FN_PSCI_FEATURES:
|
||||
+ case ARM_PSCI_1_0_FN_CPU_DEFAULT_SUSPEND:
|
||||
+ case ARM_PSCI_1_0_FN_NODE_HW_STATE:
|
||||
+ case ARM_PSCI_1_0_FN_SYSTEM_SUSPEND:
|
||||
+ case ARM_PSCI_1_1_FN_SYSTEM_RESET2:
|
||||
+ return ARM_PSCI_RET_SUCCESS;
|
||||
+ default:
|
||||
+ return ARM_PSCI_RET_NI;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+s32 __secure psci_cpu_default_suspend(u32 __always_unused function_id,
|
||||
+ u32 pc, u32 context_id)
|
||||
+{
|
||||
+ return psci_suspend_common(pc, context_id, SCPI_POWER_RETENTION,
|
||||
+ SCPI_POWER_RETENTION, SCPI_POWER_RETENTION);
|
||||
+}
|
||||
+
|
||||
+s32 __secure psci_node_hw_state(u32 __always_unused function_id,
|
||||
+ u32 target_cpu, u32 power_level)
|
||||
+{
|
||||
+ u32 core = MPIDR_AFFLVL0(target_cpu);
|
||||
+ u8 core_states, cluster_state;
|
||||
+
|
||||
+ if (power_level >= CSS_POWER_LEVEL)
|
||||
+ return HW_ON;
|
||||
+ if (scpi_get_css_power_state(target_cpu, &core_states, &cluster_state))
|
||||
+ return ARM_PSCI_RET_NI;
|
||||
+ if (power_level == CLUSTER_POWER_LEVEL) {
|
||||
+ if (cluster_state == SCPI_POWER_ON)
|
||||
+ return HW_ON;
|
||||
+ if (cluster_state < SCPI_POWER_OFF)
|
||||
+ return HW_STANDBY;
|
||||
+ return HW_OFF;
|
||||
+ }
|
||||
+
|
||||
+ return (core_states & BIT(core)) ? HW_ON : HW_OFF;
|
||||
+}
|
||||
+
|
||||
+s32 __secure psci_system_suspend(u32 __always_unused function_id,
|
||||
+ u32 pc, u32 context_id)
|
||||
+{
|
||||
+ return psci_suspend_common(pc, context_id, SCPI_POWER_OFF,
|
||||
+ SCPI_POWER_OFF, SCPI_POWER_OFF);
|
||||
+}
|
||||
+
|
||||
+s32 __secure psci_system_reset2(u32 __always_unused function_id,
|
||||
+ u32 reset_type, u32 cookie)
|
||||
+{
|
||||
+ s32 ret;
|
||||
+
|
||||
+ if (reset_type)
|
||||
+ return ARM_PSCI_RET_INVAL;
|
||||
+
|
||||
+ ret = scpi_set_sys_power_state(SCPI_SYSTEM_RESET);
|
||||
+ if (ret)
|
||||
+ return ARM_PSCI_RET_INVAL;
|
||||
+
|
||||
+ /* Wait to be turned off. */
|
||||
+ for (;;) wfi();
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * R40 is different from other single cluster SoCs. The secondary core
|
||||
+ * entry address register is in the SRAM controller address range.
|
||||
+ */
|
||||
+#define SUN8I_R40_SRAMC_SOFT_ENTRY_REG0 (0xbc)
|
||||
+
|
||||
+#ifdef CONFIG_MACH_SUN8I_R40
|
||||
+/* secondary core entry address is programmed differently on R40 */
|
||||
+static void __secure sunxi_set_entry_address(void *entry)
|
||||
+{
|
||||
+ writel((u32)entry,
|
||||
+ SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
|
||||
+}
|
||||
+#else
|
||||
+static void __secure sunxi_set_entry_address(void *entry)
|
||||
+{
|
||||
+ struct sunxi_cpucfg_reg *cpucfg =
|
||||
+ (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
|
||||
+
|
||||
+ writel((u32)entry, &cpucfg->priv0);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+void __secure psci_arch_init(void)
|
||||
+{
|
||||
+ static bool __secure_data once;
|
||||
+
|
||||
+ /* Be cool with non-secure. */
|
||||
+ writel(0xff, GICC_BASE + GICC_PMR);
|
||||
+
|
||||
+ if (!once) {
|
||||
+ once = true;
|
||||
+
|
||||
+ /* Redirect CPU0 to PSCI. */
|
||||
+ writel(0x16aaefe8, 0x1f01da0);
|
||||
+ writel(0xaa16efe8, 0x1f01da0);
|
||||
+ writel(0x47000, 0x1f01da8);
|
||||
+
|
||||
+ /* Set secondary core power-on PC. */
|
||||
+ sunxi_set_entry_address(psci_cpu_entry);
|
||||
+
|
||||
+ /* Wait for the SCP firmware to boot. */
|
||||
+ scpi_begin_command();
|
||||
+ scpi_wait_response();
|
||||
+ scpi_end_command();
|
||||
+ } else if (MPIDR_AFFLVL0(read_mpidr()) == 0) {
|
||||
+ writel(ccu_save[0], 0x1c20050);
|
||||
+ writel(ccu_save[1], 0x1c20054);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void psci_board_init(void)
|
||||
+{
|
||||
+ /* Check for a valid SCP firmware, and boot the SCP if found. */
|
||||
+ if (readl(SUNXI_SCP_BASE) == SUNXI_SCP_MAGIC) {
|
||||
+ /* Program exception vectors to the firmware entry point. */
|
||||
+ for (u32 i = OR1K_VEC_FIRST; i <= OR1K_VEC_LAST; ++i) {
|
||||
+ u32 vector = SUNXI_SRAM_A2_BASE + OR1K_VEC_ADDR(i);
|
||||
+ u32 offset = SUNXI_SCP_BASE - vector;
|
||||
+
|
||||
+ writel(offset >> 2, vector);
|
||||
+ }
|
||||
+
|
||||
+ /* Take the SCP out of reset. */
|
||||
+ writel(0x1, SUNXI_CPUCFG_BASE);
|
||||
+ }
|
||||
+}
|
||||
--- a/arch/arm/include/asm/psci.h
|
||||
+++ b/arch/arm/include/asm/psci.h
|
||||
@@ -22,8 +22,9 @@
|
||||
#include <linux/bitops.h>
|
||||
#endif
|
||||
|
||||
-#define ARM_PSCI_VER_1_0 (0x00010000)
|
||||
#define ARM_PSCI_VER_0_2 (0x00000002)
|
||||
+#define ARM_PSCI_VER_1_0 (0x00010000)
|
||||
+#define ARM_PSCI_VER_1_1 (0x00010001)
|
||||
|
||||
/* PSCI 0.1 interface */
|
||||
#define ARM_PSCI_FN_BASE 0x95c1ba5e
|
||||
@@ -68,7 +69,6 @@
|
||||
#define ARM_PSCI_0_2_FN64_AFFINITY_INFO ARM_PSCI_0_2_FN64(4)
|
||||
#define ARM_PSCI_0_2_FN64_MIGRATE ARM_PSCI_0_2_FN64(5)
|
||||
#define ARM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU ARM_PSCI_0_2_FN64(7)
|
||||
-#define ARM_PSCI_0_2_FN64_SYSTEM_RESET2 ARM_PSCI_0_2_FN64(18)
|
||||
|
||||
/* PSCI 1.0 interface */
|
||||
#define ARM_PSCI_1_0_FN_PSCI_FEATURES ARM_PSCI_0_2_FN(10)
|
||||
@@ -86,6 +86,11 @@
|
||||
#define ARM_PSCI_1_0_FN64_STAT_RESIDENCY ARM_PSCI_0_2_FN64(16)
|
||||
#define ARM_PSCI_1_0_FN64_STAT_COUNT ARM_PSCI_0_2_FN64(17)
|
||||
|
||||
+/* PSCI 1.1 interface */
|
||||
+#define ARM_PSCI_1_1_FN_SYSTEM_RESET2 ARM_PSCI_0_2_FN(18)
|
||||
+
|
||||
+#define ARM_PSCI_1_1_FN64_SYSTEM_RESET2 ARM_PSCI_0_2_FN64(18)
|
||||
+
|
||||
/* 1KB stack per core */
|
||||
#define ARM_PSCI_STACK_SHIFT 10
|
||||
#define ARM_PSCI_STACK_SIZE (1 << ARM_PSCI_STACK_SHIFT)
|
||||
--- a/arch/arm/include/asm/system.h
|
||||
+++ b/arch/arm/include/asm/system.h
|
||||
@@ -549,17 +549,20 @@ void mmu_page_table_flush(unsigned long
|
||||
#ifdef CONFIG_ARMV7_PSCI
|
||||
void psci_arch_cpu_entry(void);
|
||||
void psci_arch_init(void);
|
||||
+
|
||||
u32 psci_version(void);
|
||||
-s32 psci_features(u32 function_id, u32 psci_fid);
|
||||
+s32 psci_cpu_suspend(u32 function_id, u32 power_state, u32 pc, u32 context_id);
|
||||
s32 psci_cpu_off(void);
|
||||
-s32 psci_cpu_on(u32 function_id, u32 target_cpu, u32 pc,
|
||||
- u32 context_id);
|
||||
-s32 psci_affinity_info(u32 function_id, u32 target_affinity,
|
||||
- u32 lowest_affinity_level);
|
||||
+s32 psci_cpu_on(u32 function_id, u32 target_cpu, u32 pc, u32 context_id);
|
||||
+s32 psci_affinity_info(u32 function_id, u32 target_affinity, u32 power_level);
|
||||
u32 psci_migrate_info_type(void);
|
||||
void psci_system_off(void);
|
||||
void psci_system_reset(void);
|
||||
s32 psci_features(u32 function_id, u32 psci_fid);
|
||||
+s32 psci_cpu_default_suspend(u32 function_id, u32 pc, u32 context_id);
|
||||
+s32 psci_node_hw_state(u32 function_id, u32 target_cpu, u32 power_level);
|
||||
+s32 psci_system_suspend(u32 function_id, u32 pc, u32 context_id);
|
||||
+s32 psci_system_reset2(u32 function_id, u32 reset_type, u32 cookie);
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
--- a/tools/sunxi_egon.c
|
||||
+++ b/tools/sunxi_egon.c
|
||||
@@ -12,7 +12,7 @@
|
||||
* NAND requires 8K padding. SD/eMMC gets away with 512 bytes,
|
||||
* but let's use the larger padding to cover both.
|
||||
*/
|
||||
-#define PAD_SIZE 8192
|
||||
+#define PAD_SIZE 1024
|
||||
|
||||
static int egon_check_params(struct image_tool_params *params)
|
||||
{
|
@ -0,0 +1,44 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Holland <samuel@sholland.org>
|
||||
Date: Sat, 12 Dec 2020 23:55:04 -0600
|
||||
Subject: [PATCH] Makefile: Add support for building a sunxi resume shim
|
||||
|
||||
---
|
||||
.gitignore | 1 +
|
||||
Makefile | 15 +++++++++++++++
|
||||
2 files changed, 16 insertions(+)
|
||||
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -44,6 +44,7 @@ fit-dtb.blob*
|
||||
/u-boot*
|
||||
/boards.cfg
|
||||
/*.log
|
||||
+/resume.*
|
||||
|
||||
#
|
||||
# git files that we don't want to ignore even it they are dot-files
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -961,6 +961,21 @@ INPUTS-$(CONFIG_X86) += u-boot-x86-start
|
||||
$(if $(CONFIG_SPL_X86_16BIT_INIT),spl/u-boot-spl.bin) \
|
||||
$(if $(CONFIG_TPL_X86_16BIT_INIT),tpl/u-boot-tpl.bin)
|
||||
|
||||
+INPUTS-$(CONFIG_ARCH_SUNXI) += resume.egon
|
||||
+
|
||||
+MKIMAGEFLAGS_resume.egon := -T sunxi_egon
|
||||
+
|
||||
+resume.egon: resume.bin
|
||||
+ $(call if_changed,mkimage)
|
||||
+
|
||||
+OBJCOPYFLAGS_resume.bin := -O binary
|
||||
+
|
||||
+resume.bin: resume.o
|
||||
+ $(call if_changed,objcopy)
|
||||
+
|
||||
+resume.S: u-boot
|
||||
+ @sed -En 's/(0x[[:xdigit:]]+) +psci_cpu_entry/ldr pc, =\1/p' $<.map > $@
|
||||
+
|
||||
LDFLAGS_u-boot += $(LDFLAGS_FINAL)
|
||||
|
||||
# Avoid 'Not enough room for program headers' error on binutils 2.28 onwards.
|
@ -0,0 +1,21 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Holland <samuel@sholland.org>
|
||||
Date: Wed, 18 Nov 2020 23:00:07 -0600
|
||||
Subject: [PATCH] sunxi: binman: Respect the default FIT configuration
|
||||
|
||||
Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
---
|
||||
arch/arm/dts/sunxi-u-boot.dtsi | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/arm/dts/sunxi-u-boot.dtsi
|
||||
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
|
||||
@@ -82,7 +82,7 @@
|
||||
};
|
||||
|
||||
configurations {
|
||||
- default = "config-1";
|
||||
+ default = "@config-DEFAULT-SEQ";
|
||||
|
||||
@config-SEQ {
|
||||
description = "NAME";
|
@ -0,0 +1,21 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Holland <samuel@sholland.org>
|
||||
Date: Wed, 18 Nov 2020 23:04:49 -0600
|
||||
Subject: [PATCH] sunxi: binman: Do not hardcode U-Boot load address
|
||||
|
||||
Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
---
|
||||
arch/arm/dts/sunxi-u-boot.dtsi | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/arm/dts/sunxi-u-boot.dtsi
|
||||
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
|
||||
@@ -40,7 +40,7 @@
|
||||
os = "u-boot";
|
||||
arch = "arm64";
|
||||
compression = "none";
|
||||
- load = <0x4a000000>;
|
||||
+ load = <CONFIG_SYS_TEXT_BASE>;
|
||||
|
||||
u-boot-nodtb {
|
||||
};
|
@ -0,0 +1,20 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Holland <samuel@sholland.org>
|
||||
Date: Wed, 18 Nov 2020 23:27:07 -0600
|
||||
Subject: [PATCH] sunxi: binman: Explicitly pad SPL to expected size
|
||||
|
||||
Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
---
|
||||
arch/arm/dts/sunxi-u-boot.dtsi | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/arch/arm/dts/sunxi-u-boot.dtsi
|
||||
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
|
||||
@@ -30,6 +30,7 @@
|
||||
#ifdef CONFIG_ARM64
|
||||
fit {
|
||||
description = "Configuration to load ATF before U-Boot";
|
||||
+ offset = <CONFIG_SPL_PAD_TO>;
|
||||
#address-cells = <1>;
|
||||
fit,fdt-list = "of-list";
|
||||
|
@ -0,0 +1,97 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Holland <samuel@sholland.org>
|
||||
Date: Wed, 18 Nov 2020 23:31:47 -0600
|
||||
Subject: [PATCH] sunxi: binman: Support FIT images for 32-bit boards
|
||||
|
||||
Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
---
|
||||
arch/arm/dts/sunxi-u-boot.dtsi | 58 ++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 58 insertions(+)
|
||||
|
||||
--- a/arch/arm/dts/sunxi-u-boot.dtsi
|
||||
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <config.h>
|
||||
|
||||
+#ifdef CONFIG_ARM64
|
||||
#ifdef CONFIG_MACH_SUN50I_H6
|
||||
#define BL31_ADDR 0x104000
|
||||
#define SCP_ADDR 0x114000
|
||||
@@ -7,6 +8,9 @@
|
||||
#define BL31_ADDR 0x44000
|
||||
#define SCP_ADDR 0x50000
|
||||
#endif
|
||||
+#else
|
||||
+#define SCP_ADDR 0x48000
|
||||
+#endif
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
@@ -27,6 +31,7 @@
|
||||
filename = "spl/sunxi-spl.bin";
|
||||
};
|
||||
|
||||
+#ifdef CONFIG_SPL_FIT
|
||||
#ifdef CONFIG_ARM64
|
||||
fit {
|
||||
description = "Configuration to load ATF before U-Boot";
|
||||
@@ -94,6 +99,59 @@
|
||||
};
|
||||
};
|
||||
#else
|
||||
+ fit {
|
||||
+ description = "Configuration to load SCP firmware with U-Boot";
|
||||
+ offset = <CONFIG_SPL_PAD_TO>;
|
||||
+ #address-cells = <1>;
|
||||
+ fit,fdt-list = "of-list";
|
||||
+
|
||||
+ images {
|
||||
+ uboot {
|
||||
+ description = "U-Boot (32-bit)";
|
||||
+ type = "standalone";
|
||||
+ os = "u-boot";
|
||||
+ arch = "arm";
|
||||
+ compression = "none";
|
||||
+ load = <CONFIG_SYS_TEXT_BASE>;
|
||||
+
|
||||
+ u-boot-nodtb {
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ scp {
|
||||
+ description = "SCP firmware";
|
||||
+ type = "firmware";
|
||||
+ arch = "or1k";
|
||||
+ compression = "none";
|
||||
+ load = <SCP_ADDR>;
|
||||
+
|
||||
+ scp {
|
||||
+ filename = "scp.bin";
|
||||
+ missing-msg = "scp-sunxi";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ @fdt-SEQ {
|
||||
+ description = "NAME";
|
||||
+ type = "flat_dt";
|
||||
+ compression = "none";
|
||||
+
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ configurations {
|
||||
+ default = "@config-DEFAULT-SEQ";
|
||||
+
|
||||
+ @config-SEQ {
|
||||
+ description = "NAME";
|
||||
+ firmware = "uboot";
|
||||
+ loadables = "scp";
|
||||
+ fdt = "fdt-SEQ";
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+#endif
|
||||
+#else
|
||||
u-boot-img {
|
||||
offset = <CONFIG_SPL_PAD_TO>;
|
||||
};
|
@ -0,0 +1,48 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Holland <samuel@sholland.org>
|
||||
Date: Sun, 13 Dec 2020 00:07:28 -0600
|
||||
Subject: [PATCH] sunxi: binman: Add a resume shim
|
||||
|
||||
Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
---
|
||||
arch/arm/dts/sunxi-u-boot.dtsi | 15 ++++++++++++++-
|
||||
1 file changed, 14 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/arm/dts/sunxi-u-boot.dtsi
|
||||
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
|
||||
@@ -10,6 +10,7 @@
|
||||
#endif
|
||||
#else
|
||||
#define SCP_ADDR 0x48000
|
||||
+#define RESUME_ADDR 0x47000
|
||||
#endif
|
||||
|
||||
/ {
|
||||
@@ -118,6 +119,18 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ resume {
|
||||
+ description = "resume shim";
|
||||
+ type = "standalone";
|
||||
+ arch = "arm";
|
||||
+ compression = "none";
|
||||
+ load = <RESUME_ADDR>;
|
||||
+
|
||||
+ blob-ext {
|
||||
+ filename = "resume.egon";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
scp {
|
||||
description = "SCP firmware";
|
||||
type = "firmware";
|
||||
@@ -145,7 +158,7 @@
|
||||
@config-SEQ {
|
||||
description = "NAME";
|
||||
firmware = "uboot";
|
||||
- loadables = "scp";
|
||||
+ loadables = "resume", "scp";
|
||||
fdt = "fdt-SEQ";
|
||||
};
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user