GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
if ARCH_MESON
|
||||
|
||||
config MESON64_COMMON
|
||||
bool
|
||||
select ARM64
|
||||
select CLK
|
||||
select DM
|
||||
select DM_SERIAL
|
||||
select SYSCON
|
||||
select REGMAP
|
||||
select BOARD_LATE_INIT
|
||||
imply CMD_DM
|
||||
|
||||
config MESON_GX
|
||||
bool
|
||||
select MESON64_COMMON
|
||||
|
||||
choice
|
||||
prompt "Platform select"
|
||||
default MESON_GXBB
|
||||
|
||||
config MESON_GXBB
|
||||
bool "GXBB"
|
||||
select MESON_GX
|
||||
help
|
||||
Select this if your SoC is an S905
|
||||
|
||||
config MESON_GXL
|
||||
bool "GXL"
|
||||
select MESON_GX
|
||||
help
|
||||
Select this if your SoC is an S905X/D or S805X
|
||||
|
||||
config MESON_GXM
|
||||
bool "GXM"
|
||||
select MESON_GX
|
||||
help
|
||||
Select this if your SoC is an S912
|
||||
|
||||
config MESON_AXG
|
||||
bool "AXG"
|
||||
select MESON64_COMMON
|
||||
help
|
||||
Select this if your SoC is an A113X/D
|
||||
|
||||
config MESON_G12A
|
||||
bool "G12A"
|
||||
select MESON64_COMMON
|
||||
help
|
||||
Select this if your SoC is an S905X/D2
|
||||
|
||||
endchoice
|
||||
|
||||
config SYS_SOC
|
||||
default "meson"
|
||||
|
||||
config SYS_MALLOC_F_LEN
|
||||
default 0x1000
|
||||
|
||||
config SYS_VENDOR
|
||||
string "Vendor name"
|
||||
default "amlogic"
|
||||
help
|
||||
This option contains information about board name.
|
||||
Based on this option board/<CONFIG_SYS_VENDOR>/<CONFIG_SYS_BOARD> will
|
||||
be used.
|
||||
|
||||
config SYS_BOARD
|
||||
string "Board name"
|
||||
default "p200" if MESON_GXBB
|
||||
default "p212" if MESON_GXL
|
||||
default "q200" if MESON_GXM
|
||||
default "s400" if MESON_AXG
|
||||
default "u200" if MESON_G12A
|
||||
default ""
|
||||
help
|
||||
This option contains information about board name.
|
||||
Based on this option board/<CONFIG_SYS_VENDOR>/<CONFIG_SYS_BOARD> will
|
||||
be used.
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
string "Board configuration name"
|
||||
default "meson64"
|
||||
help
|
||||
This option contains information about board configuration name.
|
||||
Based on this option include/configs/<CONFIG_SYS_CONFIG_NAME>.h header
|
||||
will be used for board configuration.
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,8 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright (c) 2016 Beniamino Galvani <b.galvani@gmail.com>
|
||||
|
||||
obj-y += board-common.o sm.o board-info.o
|
||||
obj-$(CONFIG_MESON_GX) += board-gx.o
|
||||
obj-$(CONFIG_MESON_AXG) += board-axg.o
|
||||
obj-$(CONFIG_MESON_G12A) += board-g12a.o
|
||||
@@ -0,0 +1,118 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2016 Beniamino Galvani <b.galvani@gmail.com>
|
||||
* (C) Copyright 2018 Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/boot.h>
|
||||
#include <asm/arch/eth.h>
|
||||
#include <asm/arch/axg.h>
|
||||
#include <asm/arch/mem.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/armv8/mmu.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <phy.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int meson_get_boot_device(void)
|
||||
{
|
||||
return readl(AXG_AO_SEC_GP_CFG0) & AXG_AO_BOOT_DEVICE;
|
||||
}
|
||||
|
||||
/* Configure the reserved memory zones exported by the secure registers
|
||||
* into EFI and DTB reserved memory entries.
|
||||
*/
|
||||
void meson_init_reserved_memory(void *fdt)
|
||||
{
|
||||
u64 bl31_size, bl31_start;
|
||||
u64 bl32_size, bl32_start;
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* Get ARM Trusted Firmware reserved memory zones in :
|
||||
* - AO_SEC_GP_CFG3: bl32 & bl31 size in KiB, can be 0
|
||||
* - AO_SEC_GP_CFG5: bl31 physical start address, can be NULL
|
||||
* - AO_SEC_GP_CFG4: bl32 physical start address, can be NULL
|
||||
*/
|
||||
reg = readl(AXG_AO_SEC_GP_CFG3);
|
||||
|
||||
bl31_size = ((reg & AXG_AO_BL31_RSVMEM_SIZE_MASK)
|
||||
>> AXG_AO_BL31_RSVMEM_SIZE_SHIFT) * SZ_1K;
|
||||
bl32_size = (reg & AXG_AO_BL32_RSVMEM_SIZE_MASK) * SZ_1K;
|
||||
|
||||
bl31_start = readl(AXG_AO_SEC_GP_CFG5);
|
||||
bl32_start = readl(AXG_AO_SEC_GP_CFG4);
|
||||
|
||||
/* Add BL31 reserved zone */
|
||||
if (bl31_start && bl31_size)
|
||||
meson_board_add_reserved_memory(fdt, bl31_start, bl31_size);
|
||||
|
||||
/* Add BL32 reserved zone */
|
||||
if (bl32_start && bl32_size)
|
||||
meson_board_add_reserved_memory(fdt, bl32_start, bl32_size);
|
||||
}
|
||||
|
||||
phys_size_t get_effective_memsize(void)
|
||||
{
|
||||
/* Size is reported in MiB, convert it in bytes */
|
||||
return ((readl(AXG_AO_SEC_GP_CFG0) & AXG_AO_MEM_SIZE_MASK)
|
||||
>> AXG_AO_MEM_SIZE_SHIFT) * SZ_1M;
|
||||
}
|
||||
|
||||
static struct mm_region axg_mem_map[] = {
|
||||
{
|
||||
.virt = 0x0UL,
|
||||
.phys = 0x0UL,
|
||||
.size = 0x80000000UL,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
|
||||
PTE_BLOCK_INNER_SHARE
|
||||
}, {
|
||||
.virt = 0xf0000000UL,
|
||||
.phys = 0xf0000000UL,
|
||||
.size = 0x10000000UL,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE |
|
||||
PTE_BLOCK_PXN | PTE_BLOCK_UXN
|
||||
}, {
|
||||
/* List terminator */
|
||||
0,
|
||||
}
|
||||
};
|
||||
|
||||
struct mm_region *mem_map = axg_mem_map;
|
||||
|
||||
/* Configure the Ethernet MAC with the requested interface mode
|
||||
* with some optional flags.
|
||||
*/
|
||||
void meson_eth_init(phy_interface_t mode, unsigned int flags)
|
||||
{
|
||||
switch (mode) {
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
/* Set RGMII mode */
|
||||
setbits_le32(AXG_ETH_REG_0, AXG_ETH_REG_0_PHY_INTF_RGMII |
|
||||
AXG_ETH_REG_0_TX_PHASE(1) |
|
||||
AXG_ETH_REG_0_TX_RATIO(4) |
|
||||
AXG_ETH_REG_0_PHY_CLK_EN |
|
||||
AXG_ETH_REG_0_CLK_EN);
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_RMII:
|
||||
/* Set RMII mode */
|
||||
out_le32(AXG_ETH_REG_0, AXG_ETH_REG_0_PHY_INTF_RMII |
|
||||
AXG_ETH_REG_0_INVERT_RMII_CLK |
|
||||
AXG_ETH_REG_0_CLK_EN);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Invalid Ethernet interface mode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable power gate */
|
||||
clrbits_le32(AXG_MEM_PD_REG_0, AXG_MEM_PD_REG_0_ETH_MASK);
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2016 Beniamino Galvani <b.galvani@gmail.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <init.h>
|
||||
#include <asm/arch/boot.h>
|
||||
#include <env.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <linux/err.h>
|
||||
#include <asm/arch/mem.h>
|
||||
#include <asm/arch/sm.h>
|
||||
#include <asm/armv8/mmu.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <efi_loader.h>
|
||||
#include <u-boot/crc.h>
|
||||
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT)
|
||||
#include <asm/psci.h>
|
||||
#include <fastboot.h>
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
__weak int board_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
const fdt64_t *val;
|
||||
int offset;
|
||||
int len;
|
||||
|
||||
offset = fdt_path_offset(gd->fdt_blob, "/memory");
|
||||
if (offset < 0)
|
||||
return -EINVAL;
|
||||
|
||||
val = fdt_getprop(gd->fdt_blob, offset, "reg", &len);
|
||||
if (len < sizeof(*val) * 2)
|
||||
return -EINVAL;
|
||||
|
||||
/* Use unaligned access since cache is still disabled */
|
||||
gd->ram_size = get_unaligned_be64(&val[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__weak int meson_ft_board_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ft_board_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
meson_init_reserved_memory(blob);
|
||||
|
||||
return meson_ft_board_setup(blob, bd);
|
||||
}
|
||||
|
||||
void meson_board_add_reserved_memory(void *fdt, u64 start, u64 size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = fdt_add_mem_rsv(fdt, start, size);
|
||||
if (ret)
|
||||
printf("Could not reserve zone @ 0x%llx\n", start);
|
||||
|
||||
if (IS_ENABLED(CONFIG_EFI_LOADER)) {
|
||||
efi_add_memory_map(start,
|
||||
ALIGN(size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT,
|
||||
EFI_RESERVED_MEMORY_TYPE, false);
|
||||
}
|
||||
}
|
||||
|
||||
int meson_generate_serial_ethaddr(void)
|
||||
{
|
||||
u8 mac_addr[ARP_HLEN];
|
||||
char serial[SM_SERIAL_SIZE];
|
||||
u32 sid;
|
||||
u16 sid16;
|
||||
|
||||
if (!meson_sm_get_serial(serial, SM_SERIAL_SIZE)) {
|
||||
sid = crc32(0, (unsigned char *)serial, SM_SERIAL_SIZE);
|
||||
sid16 = crc16_ccitt(0, (unsigned char *)serial, SM_SERIAL_SIZE);
|
||||
|
||||
/* Ensure the NIC specific bytes of the mac are not all 0 */
|
||||
if ((sid & 0xffffff) == 0)
|
||||
sid |= 0x800000;
|
||||
|
||||
/* Non OUI / registered MAC address */
|
||||
mac_addr[0] = ((sid16 >> 8) & 0xfc) | 0x02;
|
||||
mac_addr[1] = (sid16 >> 0) & 0xff;
|
||||
mac_addr[2] = (sid >> 24) & 0xff;
|
||||
mac_addr[3] = (sid >> 16) & 0xff;
|
||||
mac_addr[4] = (sid >> 8) & 0xff;
|
||||
mac_addr[5] = (sid >> 0) & 0xff;
|
||||
|
||||
eth_env_set_enetaddr("ethaddr", mac_addr);
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void meson_set_boot_source(void)
|
||||
{
|
||||
const char *source;
|
||||
|
||||
switch (meson_get_boot_device()) {
|
||||
case BOOT_DEVICE_EMMC:
|
||||
source = "emmc";
|
||||
break;
|
||||
|
||||
case BOOT_DEVICE_NAND:
|
||||
source = "nand";
|
||||
break;
|
||||
|
||||
case BOOT_DEVICE_SPI:
|
||||
source = "spi";
|
||||
break;
|
||||
|
||||
case BOOT_DEVICE_SD:
|
||||
source = "sd";
|
||||
break;
|
||||
|
||||
case BOOT_DEVICE_USB:
|
||||
source = "usb";
|
||||
break;
|
||||
|
||||
default:
|
||||
source = "unknown";
|
||||
}
|
||||
|
||||
env_set("boot_source", source);
|
||||
}
|
||||
|
||||
__weak int meson_board_late_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_late_init(void)
|
||||
{
|
||||
meson_set_boot_source();
|
||||
|
||||
return meson_board_late_init();
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT)
|
||||
static unsigned int reboot_reason = REBOOT_REASON_NORMAL;
|
||||
|
||||
int fastboot_set_reboot_flag()
|
||||
{
|
||||
reboot_reason = REBOOT_REASON_BOOTLOADER;
|
||||
|
||||
printf("Using reboot reason: 0x%x\n", reboot_reason);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void reset_cpu(ulong addr)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
||||
regs.regs[0] = ARM_PSCI_0_2_FN_SYSTEM_RESET;
|
||||
regs.regs[1] = reboot_reason;
|
||||
|
||||
printf("Rebooting with reason: 0x%lx\n", regs.regs[1]);
|
||||
|
||||
smc_call(®s);
|
||||
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
#else
|
||||
void reset_cpu(ulong addr)
|
||||
{
|
||||
psci_system_reset();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,282 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2016 Beniamino Galvani <b.galvani@gmail.com>
|
||||
* (C) Copyright 2018 Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/boot.h>
|
||||
#include <asm/arch/eth.h>
|
||||
#include <asm/arch/g12a.h>
|
||||
#include <asm/arch/mem.h>
|
||||
#include <asm/arch/meson-vpu.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/armv8/mmu.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <usb.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <asm/arch/usb.h>
|
||||
#include <usb/dwc2_udc.h>
|
||||
#include <phy.h>
|
||||
#include <clk.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int meson_get_boot_device(void)
|
||||
{
|
||||
return readl(G12A_AO_SEC_GP_CFG0) & G12A_AO_BOOT_DEVICE;
|
||||
}
|
||||
|
||||
/* Configure the reserved memory zones exported by the secure registers
|
||||
* into EFI and DTB reserved memory entries.
|
||||
*/
|
||||
void meson_init_reserved_memory(void *fdt)
|
||||
{
|
||||
u64 bl31_size, bl31_start;
|
||||
u64 bl32_size, bl32_start;
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* Get ARM Trusted Firmware reserved memory zones in :
|
||||
* - AO_SEC_GP_CFG3: bl32 & bl31 size in KiB, can be 0
|
||||
* - AO_SEC_GP_CFG5: bl31 physical start address, can be NULL
|
||||
* - AO_SEC_GP_CFG4: bl32 physical start address, can be NULL
|
||||
*/
|
||||
reg = readl(G12A_AO_SEC_GP_CFG3);
|
||||
|
||||
bl31_size = ((reg & G12A_AO_BL31_RSVMEM_SIZE_MASK)
|
||||
>> G12A_AO_BL31_RSVMEM_SIZE_SHIFT) * SZ_1K;
|
||||
bl32_size = (reg & G12A_AO_BL32_RSVMEM_SIZE_MASK) * SZ_1K;
|
||||
|
||||
bl31_start = readl(G12A_AO_SEC_GP_CFG5);
|
||||
bl32_start = readl(G12A_AO_SEC_GP_CFG4);
|
||||
|
||||
/* Add BL31 reserved zone */
|
||||
if (bl31_start && bl31_size)
|
||||
meson_board_add_reserved_memory(fdt, bl31_start, bl31_size);
|
||||
|
||||
/* Add BL32 reserved zone */
|
||||
if (bl32_start && bl32_size)
|
||||
meson_board_add_reserved_memory(fdt, bl32_start, bl32_size);
|
||||
|
||||
#if defined(CONFIG_VIDEO_MESON)
|
||||
meson_vpu_rsv_fb(fdt);
|
||||
#endif
|
||||
}
|
||||
|
||||
phys_size_t get_effective_memsize(void)
|
||||
{
|
||||
/* Size is reported in MiB, convert it in bytes */
|
||||
return min(((readl(G12A_AO_SEC_GP_CFG0) & G12A_AO_MEM_SIZE_MASK)
|
||||
>> G12A_AO_MEM_SIZE_SHIFT) * SZ_1M, 0xf5000000);
|
||||
}
|
||||
|
||||
static struct mm_region g12a_mem_map[] = {
|
||||
{
|
||||
.virt = 0x0UL,
|
||||
.phys = 0x0UL,
|
||||
.size = 0xf5000000UL,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
|
||||
PTE_BLOCK_INNER_SHARE
|
||||
}, {
|
||||
.virt = 0xf5000000UL,
|
||||
.phys = 0xf5000000UL,
|
||||
.size = 0x0b000000UL,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE |
|
||||
PTE_BLOCK_PXN | PTE_BLOCK_UXN
|
||||
}, {
|
||||
/* List terminator */
|
||||
0,
|
||||
}
|
||||
};
|
||||
|
||||
struct mm_region *mem_map = g12a_mem_map;
|
||||
|
||||
static void g12a_enable_external_mdio(void)
|
||||
{
|
||||
writel(0x0, ETH_PHY_CNTL2);
|
||||
}
|
||||
|
||||
static void g12a_enable_internal_mdio(void)
|
||||
{
|
||||
/* Fire up the PHY PLL */
|
||||
writel(0x29c0040a, ETH_PLL_CNTL0);
|
||||
writel(0x927e0000, ETH_PLL_CNTL1);
|
||||
writel(0xac5f49e5, ETH_PLL_CNTL2);
|
||||
writel(0x00000000, ETH_PLL_CNTL3);
|
||||
writel(0x00000000, ETH_PLL_CNTL4);
|
||||
writel(0x20200000, ETH_PLL_CNTL5);
|
||||
writel(0x0000c002, ETH_PLL_CNTL6);
|
||||
writel(0x00000023, ETH_PLL_CNTL7);
|
||||
writel(0x39c0040a, ETH_PLL_CNTL0);
|
||||
writel(0x19c0040a, ETH_PLL_CNTL0);
|
||||
|
||||
/* Select the internal MDIO */
|
||||
writel(0x33000180, ETH_PHY_CNTL0);
|
||||
writel(0x00074043, ETH_PHY_CNTL1);
|
||||
writel(0x00000260, ETH_PHY_CNTL2);
|
||||
}
|
||||
|
||||
/* Configure the Ethernet MAC with the requested interface mode
|
||||
* with some optional flags.
|
||||
*/
|
||||
void meson_eth_init(phy_interface_t mode, unsigned int flags)
|
||||
{
|
||||
switch (mode) {
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
/* Set RGMII mode */
|
||||
setbits_le32(G12A_ETH_REG_0, G12A_ETH_REG_0_PHY_INTF_RGMII |
|
||||
G12A_ETH_REG_0_TX_PHASE(1) |
|
||||
G12A_ETH_REG_0_TX_RATIO(4) |
|
||||
G12A_ETH_REG_0_PHY_CLK_EN |
|
||||
G12A_ETH_REG_0_CLK_EN);
|
||||
g12a_enable_external_mdio();
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_RMII:
|
||||
/* Set RMII mode */
|
||||
out_le32(G12A_ETH_REG_0, G12A_ETH_REG_0_PHY_INTF_RMII |
|
||||
G12A_ETH_REG_0_INVERT_RMII_CLK |
|
||||
G12A_ETH_REG_0_CLK_EN);
|
||||
|
||||
/* Use G12A RMII Internal PHY */
|
||||
if (flags & MESON_USE_INTERNAL_RMII_PHY)
|
||||
g12a_enable_internal_mdio();
|
||||
else
|
||||
g12a_enable_external_mdio();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Invalid Ethernet interface mode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable power gate */
|
||||
clrbits_le32(G12A_MEM_PD_REG_0, G12A_MEM_PD_REG_0_ETH_MASK);
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(USB_DWC3_MESON_G12A) && \
|
||||
CONFIG_IS_ENABLED(USB_GADGET_DWC2_OTG)
|
||||
static struct dwc2_plat_otg_data meson_g12a_dwc2_data;
|
||||
|
||||
int board_usb_init(int index, enum usb_init_type init)
|
||||
{
|
||||
struct fdtdec_phandle_args args;
|
||||
const void *blob = gd->fdt_blob;
|
||||
int node, dwc2_node;
|
||||
struct udevice *dev, *clk_dev;
|
||||
struct clk clk;
|
||||
int ret;
|
||||
|
||||
/* find the usb glue node */
|
||||
node = fdt_node_offset_by_compatible(blob, -1,
|
||||
"amlogic,meson-g12a-usb-ctrl");
|
||||
if (node < 0) {
|
||||
debug("Not found usb-control node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!fdtdec_get_is_enabled(blob, node)) {
|
||||
debug("usb is disabled in the device tree\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = uclass_get_device_by_of_offset(UCLASS_SIMPLE_BUS, node, &dev);
|
||||
if (ret) {
|
||||
debug("Not found usb-control device\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* find the dwc2 node */
|
||||
dwc2_node = fdt_node_offset_by_compatible(blob, node,
|
||||
"amlogic,meson-g12a-usb");
|
||||
if (dwc2_node < 0) {
|
||||
debug("Not found dwc2 node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!fdtdec_get_is_enabled(blob, dwc2_node)) {
|
||||
debug("dwc2 is disabled in the device tree\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
meson_g12a_dwc2_data.regs_otg = fdtdec_get_addr(blob, dwc2_node, "reg");
|
||||
if (meson_g12a_dwc2_data.regs_otg == FDT_ADDR_T_NONE) {
|
||||
debug("usbotg: can't get base address\n");
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
/* Enable clock */
|
||||
ret = fdtdec_parse_phandle_with_args(blob, dwc2_node, "clocks",
|
||||
"#clock-cells", 0, 0, &args);
|
||||
if (ret) {
|
||||
debug("usbotg has no clocks defined in the device tree\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &clk_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (args.args_count != 1) {
|
||||
debug("Can't find clock ID in the device tree\n");
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
clk.dev = clk_dev;
|
||||
clk.id = args.args[0];
|
||||
|
||||
ret = clk_enable(&clk);
|
||||
if (ret) {
|
||||
debug("Failed to enable usbotg clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
meson_g12a_dwc2_data.rx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
|
||||
"g-rx-fifo-size", 0);
|
||||
meson_g12a_dwc2_data.np_tx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
|
||||
"g-np-tx-fifo-size", 0);
|
||||
meson_g12a_dwc2_data.tx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
|
||||
"g-tx-fifo-size", 0);
|
||||
|
||||
/* Switch to peripheral mode */
|
||||
ret = dwc3_meson_g12a_force_mode(dev, USB_DR_MODE_PERIPHERAL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return dwc2_udc_probe(&meson_g12a_dwc2_data);
|
||||
}
|
||||
|
||||
int board_usb_cleanup(int index, enum usb_init_type init)
|
||||
{
|
||||
const void *blob = gd->fdt_blob;
|
||||
struct udevice *dev;
|
||||
int node;
|
||||
int ret;
|
||||
|
||||
/* find the usb glue node */
|
||||
node = fdt_node_offset_by_compatible(blob, -1,
|
||||
"amlogic,meson-g12a-usb-ctrl");
|
||||
if (node < 0)
|
||||
return -ENODEV;
|
||||
|
||||
if (!fdtdec_get_is_enabled(blob, node))
|
||||
return -ENODEV;
|
||||
|
||||
ret = uclass_get_device_by_of_offset(UCLASS_SIMPLE_BUS, node, &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Switch to OTG mode */
|
||||
ret = dwc3_meson_g12a_force_mode(dev, USB_DR_MODE_HOST);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,150 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2016 Beniamino Galvani <b.galvani@gmail.com>
|
||||
* (C) Copyright 2018 Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/boot.h>
|
||||
#include <asm/arch/eth.h>
|
||||
#include <asm/arch/gx.h>
|
||||
#include <asm/arch/mem.h>
|
||||
#include <asm/arch/meson-vpu.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/armv8/mmu.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <phy.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int meson_get_boot_device(void)
|
||||
{
|
||||
return readl(GX_AO_SEC_GP_CFG0) & GX_AO_BOOT_DEVICE;
|
||||
}
|
||||
|
||||
/* Configure the reserved memory zones exported by the secure registers
|
||||
* into EFI and DTB reserved memory entries.
|
||||
*/
|
||||
void meson_init_reserved_memory(void *fdt)
|
||||
{
|
||||
u64 bl31_size, bl31_start;
|
||||
u64 bl32_size, bl32_start;
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* Get ARM Trusted Firmware reserved memory zones in :
|
||||
* - AO_SEC_GP_CFG3: bl32 & bl31 size in KiB, can be 0
|
||||
* - AO_SEC_GP_CFG5: bl31 physical start address, can be NULL
|
||||
* - AO_SEC_GP_CFG4: bl32 physical start address, can be NULL
|
||||
*/
|
||||
reg = readl(GX_AO_SEC_GP_CFG3);
|
||||
|
||||
bl31_size = ((reg & GX_AO_BL31_RSVMEM_SIZE_MASK)
|
||||
>> GX_AO_BL31_RSVMEM_SIZE_SHIFT) * SZ_1K;
|
||||
bl32_size = (reg & GX_AO_BL32_RSVMEM_SIZE_MASK) * SZ_1K;
|
||||
|
||||
bl31_start = readl(GX_AO_SEC_GP_CFG5);
|
||||
bl32_start = readl(GX_AO_SEC_GP_CFG4);
|
||||
|
||||
/*
|
||||
* Early Meson GX Firmware revisions did not provide the reserved
|
||||
* memory zones in the registers, keep fixed memory zone handling.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_MESON_GX) &&
|
||||
!reg && !bl31_start && !bl32_start) {
|
||||
bl31_start = 0x10000000;
|
||||
bl31_size = 0x200000;
|
||||
}
|
||||
|
||||
/* Add first 16MiB reserved zone */
|
||||
meson_board_add_reserved_memory(fdt, 0, GX_FIRMWARE_MEM_SIZE);
|
||||
|
||||
/* Add BL31 reserved zone */
|
||||
if (bl31_start && bl31_size)
|
||||
meson_board_add_reserved_memory(fdt, bl31_start, bl31_size);
|
||||
|
||||
/* Add BL32 reserved zone */
|
||||
if (bl32_start && bl32_size)
|
||||
meson_board_add_reserved_memory(fdt, bl32_start, bl32_size);
|
||||
|
||||
#if defined(CONFIG_VIDEO_MESON)
|
||||
meson_vpu_rsv_fb(fdt);
|
||||
#endif
|
||||
}
|
||||
|
||||
phys_size_t get_effective_memsize(void)
|
||||
{
|
||||
/* Size is reported in MiB, convert it in bytes */
|
||||
return ((readl(GX_AO_SEC_GP_CFG0) & GX_AO_MEM_SIZE_MASK)
|
||||
>> GX_AO_MEM_SIZE_SHIFT) * SZ_1M;
|
||||
}
|
||||
|
||||
static struct mm_region gx_mem_map[] = {
|
||||
{
|
||||
.virt = 0x0UL,
|
||||
.phys = 0x0UL,
|
||||
.size = 0xc0000000UL,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
|
||||
PTE_BLOCK_INNER_SHARE
|
||||
}, {
|
||||
.virt = 0xc0000000UL,
|
||||
.phys = 0xc0000000UL,
|
||||
.size = 0x30000000UL,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE |
|
||||
PTE_BLOCK_PXN | PTE_BLOCK_UXN
|
||||
}, {
|
||||
/* List terminator */
|
||||
0,
|
||||
}
|
||||
};
|
||||
|
||||
struct mm_region *mem_map = gx_mem_map;
|
||||
|
||||
/* Configure the Ethernet MAC with the requested interface mode
|
||||
* with some optional flags.
|
||||
*/
|
||||
void meson_eth_init(phy_interface_t mode, unsigned int flags)
|
||||
{
|
||||
switch (mode) {
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
/* Set RGMII mode */
|
||||
setbits_le32(GX_ETH_REG_0, GX_ETH_REG_0_PHY_INTF |
|
||||
GX_ETH_REG_0_TX_PHASE(1) |
|
||||
GX_ETH_REG_0_TX_RATIO(4) |
|
||||
GX_ETH_REG_0_PHY_CLK_EN |
|
||||
GX_ETH_REG_0_CLK_EN);
|
||||
|
||||
/* Reset to external PHY */
|
||||
if(!IS_ENABLED(CONFIG_MESON_GXBB))
|
||||
writel(0x2009087f, GX_ETH_REG_3);
|
||||
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_RMII:
|
||||
/* Set RMII mode */
|
||||
out_le32(GX_ETH_REG_0, GX_ETH_REG_0_INVERT_RMII_CLK |
|
||||
GX_ETH_REG_0_CLK_EN);
|
||||
|
||||
/* Use GXL RMII Internal PHY (also on GXM) */
|
||||
if (!IS_ENABLED(CONFIG_MESON_GXBB)) {
|
||||
if ((flags & MESON_USE_INTERNAL_RMII_PHY)) {
|
||||
writel(0x10110181, GX_ETH_REG_2);
|
||||
writel(0xe40908ff, GX_ETH_REG_3);
|
||||
} else
|
||||
writel(0x2009087f, GX_ETH_REG_3);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Invalid Ethernet interface mode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable power gate */
|
||||
clrbits_le32(GX_MEM_PD_REG_0, GX_MEM_PD_REG_0_ETH_MASK);
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2019 Julien Masson <jmasson@baylibre.com>
|
||||
* (C) Copyright 2019 Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <dm.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <regmap.h>
|
||||
#include <syscon.h>
|
||||
|
||||
#define AO_SEC_SD_CFG8 0xe0
|
||||
#define AO_SEC_SOCINFO_OFFSET AO_SEC_SD_CFG8
|
||||
|
||||
#define SOCINFO_MAJOR GENMASK(31, 24)
|
||||
#define SOCINFO_PACK GENMASK(23, 16)
|
||||
#define SOCINFO_MINOR GENMASK(15, 8)
|
||||
#define SOCINFO_MISC GENMASK(7, 0)
|
||||
|
||||
static const struct meson_gx_soc_id {
|
||||
const char *name;
|
||||
unsigned int id;
|
||||
} soc_ids[] = {
|
||||
{ "GXBB", 0x1f },
|
||||
{ "GXTVBB", 0x20 },
|
||||
{ "GXL", 0x21 },
|
||||
{ "GXM", 0x22 },
|
||||
{ "TXL", 0x23 },
|
||||
{ "TXLX", 0x24 },
|
||||
{ "AXG", 0x25 },
|
||||
{ "GXLX", 0x26 },
|
||||
{ "TXHD", 0x27 },
|
||||
{ "G12A", 0x28 },
|
||||
{ "G12B", 0x29 },
|
||||
{ "SM1", 0x2b },
|
||||
};
|
||||
|
||||
static const struct meson_gx_package_id {
|
||||
const char *name;
|
||||
unsigned int major_id;
|
||||
unsigned int pack_id;
|
||||
unsigned int pack_mask;
|
||||
} soc_packages[] = {
|
||||
{ "S905", 0x1f, 0, 0x20 }, /* pack_id != 0x20 */
|
||||
{ "S905H", 0x1f, 0x3, 0xf }, /* pack_id & 0xf == 0x3 */
|
||||
{ "S905M", 0x1f, 0x20, 0xf0 }, /* pack_id == 0x20 */
|
||||
{ "S905D", 0x21, 0, 0xf0 },
|
||||
{ "S905X", 0x21, 0x80, 0xf0 },
|
||||
{ "S905W", 0x21, 0xa0, 0xf0 },
|
||||
{ "S905L", 0x21, 0xc0, 0xf0 },
|
||||
{ "S905M2", 0x21, 0xe0, 0xf0 },
|
||||
{ "S805X", 0x21, 0x30, 0xf0 },
|
||||
{ "S805Y", 0x21, 0xb0, 0xf0 },
|
||||
{ "S912", 0x22, 0, 0x0 }, /* Only S912 is known for GXM */
|
||||
{ "962X", 0x24, 0x10, 0xf0 },
|
||||
{ "962E", 0x24, 0x20, 0xf0 },
|
||||
{ "A113X", 0x25, 0x37, 0xff },
|
||||
{ "A113D", 0x25, 0x22, 0xff },
|
||||
{ "S905D2", 0x28, 0x10, 0xf0 },
|
||||
{ "S905X2", 0x28, 0x40, 0xf0 },
|
||||
{ "A311D", 0x29, 0x10, 0xf0 },
|
||||
{ "S922X", 0x29, 0x40, 0xf0 },
|
||||
{ "S905X3", 0x2b, 0x5, 0xf },
|
||||
};
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static inline unsigned int socinfo_to_major(u32 socinfo)
|
||||
{
|
||||
return FIELD_GET(SOCINFO_MAJOR, socinfo);
|
||||
}
|
||||
|
||||
static inline unsigned int socinfo_to_minor(u32 socinfo)
|
||||
{
|
||||
return FIELD_GET(SOCINFO_MINOR, socinfo);
|
||||
}
|
||||
|
||||
static inline unsigned int socinfo_to_pack(u32 socinfo)
|
||||
{
|
||||
return FIELD_GET(SOCINFO_PACK, socinfo);
|
||||
}
|
||||
|
||||
static inline unsigned int socinfo_to_misc(u32 socinfo)
|
||||
{
|
||||
return FIELD_GET(SOCINFO_MISC, socinfo);
|
||||
}
|
||||
|
||||
static const char *socinfo_to_package_id(u32 socinfo)
|
||||
{
|
||||
unsigned int pack = socinfo_to_pack(socinfo);
|
||||
unsigned int major = socinfo_to_major(socinfo);
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < ARRAY_SIZE(soc_packages) ; ++i) {
|
||||
if (soc_packages[i].major_id == major &&
|
||||
soc_packages[i].pack_id ==
|
||||
(pack & soc_packages[i].pack_mask))
|
||||
return soc_packages[i].name;
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static const char *socinfo_to_soc_id(u32 socinfo)
|
||||
{
|
||||
unsigned int id = socinfo_to_major(socinfo);
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < ARRAY_SIZE(soc_ids) ; ++i) {
|
||||
if (soc_ids[i].id == id)
|
||||
return soc_ids[i].name;
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static void print_board_model(void)
|
||||
{
|
||||
const char *model;
|
||||
model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
|
||||
printf("Model: %s\n", model ? model : "Unknown");
|
||||
}
|
||||
|
||||
int show_board_info(void)
|
||||
{
|
||||
struct regmap *regmap;
|
||||
int nodeoffset, ret;
|
||||
ofnode node;
|
||||
unsigned int socinfo;
|
||||
|
||||
/* find the offset of compatible node */
|
||||
nodeoffset = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
|
||||
"amlogic,meson-gx-ao-secure");
|
||||
if (nodeoffset < 0)
|
||||
return 0;
|
||||
|
||||
/* check if chip-id is available */
|
||||
if (!fdt_getprop(gd->fdt_blob, nodeoffset, "amlogic,has-chip-id", NULL))
|
||||
return 0;
|
||||
|
||||
/* get regmap from the syscon node */
|
||||
node = offset_to_ofnode(nodeoffset);
|
||||
regmap = syscon_node_to_regmap(node);
|
||||
if (IS_ERR(regmap)) {
|
||||
printf("%s: failed to get regmap\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read soc info */
|
||||
ret = regmap_read(regmap, AO_SEC_SOCINFO_OFFSET, &socinfo);
|
||||
if (ret && !socinfo) {
|
||||
printf("%s: invalid chipid value\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* print board information */
|
||||
print_board_model();
|
||||
printf("SoC: Amlogic Meson %s (%s) Revision %x:%x (%x:%x)\n",
|
||||
socinfo_to_soc_id(socinfo),
|
||||
socinfo_to_package_id(socinfo),
|
||||
socinfo_to_major(socinfo),
|
||||
socinfo_to_minor(socinfo),
|
||||
socinfo_to_pack(socinfo),
|
||||
socinfo_to_misc(socinfo));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2016 Beniamino Galvani <b.galvani@gmail.com>
|
||||
*
|
||||
* Secure monitor calls.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/sm.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <dm.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <regmap.h>
|
||||
#include <syscon.h>
|
||||
|
||||
#define FN_GET_SHARE_MEM_INPUT_BASE 0x82000020
|
||||
#define FN_GET_SHARE_MEM_OUTPUT_BASE 0x82000021
|
||||
#define FN_EFUSE_READ 0x82000030
|
||||
#define FN_EFUSE_WRITE 0x82000031
|
||||
#define FN_CHIP_ID 0x82000044
|
||||
|
||||
static void *shmem_input;
|
||||
static void *shmem_output;
|
||||
|
||||
static void meson_init_shmem(void)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
||||
if (shmem_input && shmem_output)
|
||||
return;
|
||||
|
||||
regs.regs[0] = FN_GET_SHARE_MEM_INPUT_BASE;
|
||||
smc_call(®s);
|
||||
shmem_input = (void *)regs.regs[0];
|
||||
|
||||
regs.regs[0] = FN_GET_SHARE_MEM_OUTPUT_BASE;
|
||||
smc_call(®s);
|
||||
shmem_output = (void *)regs.regs[0];
|
||||
|
||||
debug("Secure Monitor shmem: 0x%p 0x%p\n", shmem_input, shmem_output);
|
||||
}
|
||||
|
||||
ssize_t meson_sm_read_efuse(uintptr_t offset, void *buffer, size_t size)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
||||
meson_init_shmem();
|
||||
|
||||
regs.regs[0] = FN_EFUSE_READ;
|
||||
regs.regs[1] = offset;
|
||||
regs.regs[2] = size;
|
||||
|
||||
smc_call(®s);
|
||||
|
||||
if (regs.regs[0] == 0)
|
||||
return -1;
|
||||
|
||||
memcpy(buffer, shmem_output, min(size, regs.regs[0]));
|
||||
|
||||
return regs.regs[0];
|
||||
}
|
||||
|
||||
#define SM_CHIP_ID_LENGTH 119
|
||||
#define SM_CHIP_ID_OFFSET 4
|
||||
#define SM_CHIP_ID_SIZE 12
|
||||
|
||||
int meson_sm_get_serial(void *buffer, size_t size)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
||||
meson_init_shmem();
|
||||
|
||||
regs.regs[0] = FN_CHIP_ID;
|
||||
regs.regs[1] = 0;
|
||||
regs.regs[2] = 0;
|
||||
|
||||
smc_call(®s);
|
||||
|
||||
memcpy(buffer, shmem_output + SM_CHIP_ID_OFFSET,
|
||||
min_t(size_t, size, SM_CHIP_ID_SIZE));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define AO_SEC_SD_CFG15 0xfc
|
||||
#define REBOOT_REASON_MASK GENMASK(15, 12)
|
||||
|
||||
int meson_sm_get_reboot_reason(void)
|
||||
{
|
||||
struct regmap *regmap;
|
||||
int nodeoffset;
|
||||
ofnode node;
|
||||
unsigned int reason;
|
||||
|
||||
/* find the offset of compatible node */
|
||||
nodeoffset = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
|
||||
"amlogic,meson-gx-ao-secure");
|
||||
if (nodeoffset < 0) {
|
||||
printf("%s: failed to get amlogic,meson-gx-ao-secure\n",
|
||||
__func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* get regmap from the syscon node */
|
||||
node = offset_to_ofnode(nodeoffset);
|
||||
regmap = syscon_node_to_regmap(node);
|
||||
if (IS_ERR(regmap)) {
|
||||
printf("%s: failed to get regmap\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regmap_read(regmap, AO_SEC_SD_CFG15, &reason);
|
||||
|
||||
/* The SMC call is not used, we directly use AO_SEC_SD_CFG15 */
|
||||
return FIELD_GET(REBOOT_REASON_MASK, reason);
|
||||
}
|
||||
|
||||
static int do_sm_serial(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char *const argv[])
|
||||
{
|
||||
ulong address;
|
||||
int ret;
|
||||
|
||||
if (argc < 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
address = simple_strtoul(argv[1], NULL, 0);
|
||||
|
||||
ret = meson_sm_get_serial((void *)address, SM_CHIP_ID_SIZE);
|
||||
if (ret)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
#define MAX_REBOOT_REASONS 14
|
||||
|
||||
static const char *reboot_reasons[MAX_REBOOT_REASONS] = {
|
||||
[REBOOT_REASON_COLD] = "cold_boot",
|
||||
[REBOOT_REASON_NORMAL] = "normal",
|
||||
[REBOOT_REASON_RECOVERY] = "recovery",
|
||||
[REBOOT_REASON_UPDATE] = "update",
|
||||
[REBOOT_REASON_FASTBOOT] = "fastboot",
|
||||
[REBOOT_REASON_SUSPEND_OFF] = "suspend_off",
|
||||
[REBOOT_REASON_HIBERNATE] = "hibernate",
|
||||
[REBOOT_REASON_BOOTLOADER] = "bootloader",
|
||||
[REBOOT_REASON_SHUTDOWN_REBOOT] = "shutdown_reboot",
|
||||
[REBOOT_REASON_RPMBP] = "rpmbp",
|
||||
[REBOOT_REASON_CRASH_DUMP] = "crash_dump",
|
||||
[REBOOT_REASON_KERNEL_PANIC] = "kernel_panic",
|
||||
[REBOOT_REASON_WATCHDOG_REBOOT] = "watchdog_reboot",
|
||||
};
|
||||
|
||||
static int do_sm_reboot_reason(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char *const argv[])
|
||||
{
|
||||
const char *reason_str;
|
||||
char *destarg = NULL;
|
||||
int reason;
|
||||
|
||||
if (argc > 1)
|
||||
destarg = argv[1];
|
||||
|
||||
reason = meson_sm_get_reboot_reason();
|
||||
if (reason < 0)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
if (reason >= MAX_REBOOT_REASONS ||
|
||||
!reboot_reasons[reason])
|
||||
reason_str = "unknown";
|
||||
else
|
||||
reason_str = reboot_reasons[reason];
|
||||
|
||||
if (destarg)
|
||||
env_set(destarg, reason_str);
|
||||
else
|
||||
printf("reboot reason: %s (%x)\n", reason_str, reason);
|
||||
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
static cmd_tbl_t cmd_sm_sub[] = {
|
||||
U_BOOT_CMD_MKENT(serial, 2, 1, do_sm_serial, "", ""),
|
||||
U_BOOT_CMD_MKENT(reboot_reason, 1, 1, do_sm_reboot_reason, "", ""),
|
||||
};
|
||||
|
||||
static int do_sm(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char *const argv[])
|
||||
{
|
||||
cmd_tbl_t *c;
|
||||
|
||||
if (argc < 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
/* Strip off leading 'sm' command argument */
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
c = find_cmd_tbl(argv[0], &cmd_sm_sub[0], ARRAY_SIZE(cmd_sm_sub));
|
||||
|
||||
if (c)
|
||||
return c->cmd(cmdtp, flag, argc, argv);
|
||||
else
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
sm, 5, 0, do_sm,
|
||||
"Secure Monitor Control",
|
||||
"serial <address> - read chip unique id to memory address\n"
|
||||
"sm reboot_reason [name] - get reboot reason and store to to environment"
|
||||
);
|
||||
Reference in New Issue
Block a user