summaryrefslogtreecommitdiff
path: root/cmd/smc.c
blob: 22f1cecb6207984b1cf7735012ad3660f1cc0d4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
 * Copyright 2000-2009
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <command.h>
#include <cli.h>
#include <asm-offsets.h>
#include <asm/system.h>

#define ARM_STD_SVC_VERSION             0x8400ff03

void atf_get_version(uint64_t* major, uint64_t* minor)
{
        struct pt_regs regs;

        regs.regs[0] = ARM_STD_SVC_VERSION;

	smc_call(&regs);

	*major = regs.regs[0];
	*minor = regs.regs[1];
}

#define SUNXI_SVC_BASE            0x83000000
#define SUNXI_SVC_UID             (SUNXI_SVC_BASE + 0xffff)
#define SUNXI_SVC_GET_CPUCLOCK    (SUNXI_SVC_BASE + 0)
#define SUNXI_SVC_SET_CPUCLOCK    (SUNXI_SVC_BASE + 1)
#define SUNXI_SVC_AXP_READ_REG    (SUNXI_SVC_BASE + 2)
#define SUNXI_SVC_AXP_WRITE_REG   (SUNXI_SVC_BASE + 3)

int atf_sunxi_axp_read_reg(uint8_t address)
{
        struct pt_regs regs;

        regs.regs[0] = SUNXI_SVC_AXP_READ_REG;
	regs.regs[1] = address;

	smc_call(&regs);

	return regs.regs[0];
}

int atf_sunxi_axp_write_reg(uint8_t address, uint8_t value)
{
        struct pt_regs regs;

        regs.regs[0] = SUNXI_SVC_AXP_WRITE_REG;
	regs.regs[1] = address;
	regs.regs[2] = value;

	smc_call(&regs);

	return regs.regs[0];
}

static int do_smc_axp(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	int reg, val;

	if (argc < 2)
		return CMD_RET_USAGE;

	if (argc < 3) {
		reg = simple_strtoul(argv[1], NULL, 16);
		printf ("axp reg %x reads %x\n", reg, atf_sunxi_axp_read_reg(reg));
		return 0;
	} else {
		reg = simple_strtoul(argv[1], NULL, 16);
		val = simple_strtoul(argv[2], NULL, 16);
		printf("axp reg %x write %x returns %d\n",
		       reg, val, atf_sunxi_axp_write_reg(reg, val));
	}
	return 0;
}

static int do_smc_version(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	uint64_t major, minor;
	atf_get_version(&major, &minor);
	printf("ATF version: %ld.%ld\n", major, minor);
	return 0;
}

static cmd_tbl_t cmd_smc_sub[] = {
	U_BOOT_CMD_MKENT(version, 0, 1, do_smc_version, "", ""),
	U_BOOT_CMD_MKENT(axp, 2, 1, do_smc_axp, "", ""),
};

static int do_smc(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 'smc' command argument */
	argc--;
	argv++;

	c = find_cmd_tbl(argv[0], &cmd_smc_sub[0], ARRAY_SIZE(cmd_smc_sub));
	if (c)
		return c->cmd(cmdtp, flag, argc, argv);

	return CMD_RET_USAGE;
}

U_BOOT_CMD(
	smc,   4,		1,	do_smc,
	"Secure monitor call (TSD test infrastructure)",
	"version - show the ATF version\n"
	"smc axp reg [value] - read/write a register in the AXP803\n"
);