152 lines
4.9 KiB
C
152 lines
4.9 KiB
C
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
|
/*
|
|
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <command.h>
|
|
#include <linux/arm-smccc.h>
|
|
#include <vsprintf.h>
|
|
#include <linux/errno.h>
|
|
#include <stdio.h>
|
|
#include <asm/amlogic/arch/register.h>
|
|
#include <amlogic/cpu_id.h>
|
|
|
|
#define DMC_MON_RW 0x8200004A
|
|
|
|
unsigned long dmc_rw(uint64_t addr, uint64_t value, uint64_t rw)
|
|
{
|
|
struct arm_smccc_res res;
|
|
|
|
arm_smccc_smc(DMC_MON_RW, addr, value, rw, 0, 0, 0, 0, &res);
|
|
|
|
return res.a0;
|
|
}
|
|
|
|
int do_dmc_rw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
{
|
|
if (argc < 4 || argc > 5)
|
|
return cmd_usage(cmdtp);
|
|
|
|
uint64_t addr = simple_strtoul(argv[1], NULL, 16);
|
|
uint64_t value = simple_strtoul(argv[2], NULL, 16);
|
|
uint64_t rw = simple_strtoul(argv[3], NULL, 16);
|
|
uint64_t dmc_back;
|
|
|
|
dmc_back = dmc_rw(addr, value, rw);
|
|
|
|
printf("return value is %llx\n", dmc_back);
|
|
|
|
return dmc_back;
|
|
}
|
|
|
|
static char dmc_help_text[] =
|
|
"\n"
|
|
"dmc_rw fe037470 ffffffff 0 - show dmc read information\n"
|
|
"dmc_rw fe037470 ffffffff 1 - show dmc write information\n";
|
|
|
|
U_BOOT_CMD(dmc_rw, 4, 0, do_dmc_rw,
|
|
"dmc read write function",
|
|
dmc_help_text
|
|
);
|
|
|
|
static int dmc_sec_check(unsigned int dmc_number)
|
|
{
|
|
#define DMC_READ 0
|
|
#define DMC_WRITE 1
|
|
cpu_id_t cpu_id = get_cpu_id();
|
|
unsigned int offset = 0;
|
|
|
|
if (cpu_id.family_id == MESON_CPU_MAJOR_ID_T3X ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_T6X)
|
|
offset = 0x4000 * dmc_number;
|
|
else
|
|
offset = 0x2000 * dmc_number;
|
|
|
|
unsigned int dmc_vio_status = dmc_rw(DMC_SEC_STATUS + offset, 0, DMC_READ);
|
|
unsigned int dmc_vio_reg0 = dmc_rw(DMC_VIO_ADDR0 + offset, 0, DMC_READ);
|
|
unsigned int dmc_vio_reg1 = dmc_rw(DMC_VIO_ADDR1 + offset, 0, DMC_READ);
|
|
unsigned int dmc_vio_reg2 = dmc_rw(DMC_VIO_ADDR2 + offset, 0, DMC_READ);
|
|
unsigned int dmc_vio_reg3 = dmc_rw(DMC_VIO_ADDR3 + offset, 0, DMC_READ);
|
|
unsigned int dmc_vio_reg4 = 0;
|
|
unsigned int dmc_vio_reg5 = 0;
|
|
unsigned int dmc_vio_reg6 = 0;
|
|
unsigned int dmc_vio_reg7 = 0;
|
|
|
|
if (cpu_id.family_id == MESON_CPU_MAJOR_ID_GXBB ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_GXTVBB ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_GXL ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_GXM ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_TXL ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_TXLX ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_AXG ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_GXLX ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_TXHD) {
|
|
dmc_vio_reg4 = dmc_rw(DMC_VIO_ADDR3 + 4 + offset, 0, DMC_READ);
|
|
dmc_vio_reg5 = dmc_rw(DMC_VIO_ADDR3 + 8 + offset, 0, DMC_READ);
|
|
dmc_vio_reg6 = dmc_rw(DMC_VIO_ADDR3 + 12 + offset, 0, DMC_READ);
|
|
dmc_vio_reg7 = dmc_rw(DMC_VIO_ADDR3 + 16 + offset, 0, DMC_READ);
|
|
}
|
|
|
|
if (dmc_vio_status || dmc_vio_reg0 || dmc_vio_reg1 || dmc_vio_reg2 || dmc_vio_reg3 ||
|
|
dmc_vio_reg4 || dmc_vio_reg5 || dmc_vio_reg6 || dmc_vio_reg7) {
|
|
printf("WARNING: DMC%d SEC VIOLATION CHECK FAILED!!!\n", dmc_number);
|
|
printf("DMC%d_SEC_STATUS:%d\n", dmc_number, dmc_vio_status);
|
|
printf("DMC%d_VIO_ADDR0:%x\n", dmc_number, dmc_vio_reg0);
|
|
printf("DMC%d_VIO_ADDR1:%x\n", dmc_number, dmc_vio_reg1);
|
|
printf("DMC%d_VIO_ADDR2:%x\n", dmc_number, dmc_vio_reg2);
|
|
printf("DMC%d_VIO_ADDR3:%x\n", dmc_number, dmc_vio_reg3);
|
|
|
|
if (cpu_id.family_id == MESON_CPU_MAJOR_ID_GXBB ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_GXTVBB ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_GXL ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_GXM ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_TXL ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_TXLX ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_AXG ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_GXLX ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_TXHD) {
|
|
printf("DMC%d_VIO_ADDR4:%x\n", dmc_number, dmc_vio_reg4);
|
|
printf("DMC%d_VIO_ADDR5:%x\n", dmc_number, dmc_vio_reg5);
|
|
printf("DMC%d_VIO_ADDR6:%x\n", dmc_number, dmc_vio_reg6);
|
|
printf("DMC%d_VIO_ADDR7:%x\n", dmc_number, dmc_vio_reg7);
|
|
}
|
|
} else {
|
|
printf("DMC%d SEC VIOLATION CHECK PASS.\n", dmc_number);
|
|
}
|
|
dmc_rw(DMC_SEC_STATUS + offset, 0x3, DMC_WRITE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int do_dmc_sec_vio_check(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
{
|
|
cpu_id_t cpu_id = get_cpu_id();
|
|
unsigned int dmc_number = 1;
|
|
unsigned int i;
|
|
|
|
if (cpu_id.family_id == MESON_CPU_MAJOR_ID_T3 ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_T7 ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_T5M ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_T6X ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_T3X) {
|
|
dmc_number = 2;
|
|
} else if (cpu_id.family_id == MESON_CPU_MAJOR_ID_P1 ||
|
|
cpu_id.family_id == MESON_CPU_MAJOR_ID_S5) {
|
|
dmc_number = 4;
|
|
}
|
|
|
|
for (i = 0; i < dmc_number; i++)
|
|
dmc_sec_check(i);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static char dmc_vio_check_help_text[] =
|
|
"\n"
|
|
"dmc_vio_check - show dmc sec vio reg check information\n";
|
|
|
|
U_BOOT_CMD(dmc_vio_check, 1, 0, do_dmc_sec_vio_check,
|
|
"dmc sec violation reg check",
|
|
dmc_vio_check_help_text
|
|
);
|