blob: 9c0324114b9311240b3af99b9f06c802954a20ba [file] [log] [blame]
Chuan Liu554bb332024-11-19 16:03:48 +08001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <common.h>
7#include <command.h>
8#include <linux/arm-smccc.h>
9#include <linux/libfdt_env.h>
10
11#define SIP_SMC_SCMI_CMD 0x820000C1
12#define SCMI_SUBID_GET_SHMEM_ADDR 0x1
13
14
15static uint32_t get_scmi_shmem_addr(void)
16{
17 struct arm_smccc_res res;
18
19 arm_smccc_smc(SIP_SMC_SCMI_CMD, SCMI_SUBID_GET_SHMEM_ADDR,
20 0, 0, 0, 0, 0, 0, &res);
21
22 return res.a0;
23}
24
25static int ftd_get_root_address_cells(void)
26{
27 char *address_cells_str = NULL;
28 int ret = 0;
29
30 ret = run_command("fdt get value address_cells / \\#address-cells", 0);
31 if (ret != 0) {
32 printf("Error: Failed to get address_cells for root\n");
33 return -EBADMSG;
34 }
35
36 address_cells_str = env_get("address_cells");
37 if (!address_cells_str) {
38 printf("Error: Failed to retrieve address_cells from environment\n");
39 return -EBADMSG;
40 }
41
42 return strtoul(address_cells_str, NULL, 16);
43}
44
45static int ftd_get_scmi_shmem_addr(void)
46{
47 char *shmem_addr_str = NULL;
48 u32 *shmem_addr = NULL;
49 int root_addrs_cells = ftd_get_root_address_cells();
50 int ret = 0;
51
52 ret = run_command("fdt get addr shmem_addr /shmem reg", 0);
53 if (ret != 0) {
54 printf("Error: Failed to get shmem_addr for /shmem\n");
55 return -EBADMSG;
56 }
57
58 shmem_addr_str = env_get("shmem_addr");
59 if (!shmem_addr_str) {
60 printf("Error: Failed to retrieve shmem_addr from environment\n");
61 return -EBADMSG;
62 }
63 shmem_addr = (u32 *)strtoul(shmem_addr_str, NULL, 16);
64 if (!shmem_addr)
65 return -EFAULT;
66
67 if (root_addrs_cells == 2) /* CONFIG_ARM64 */
68 return be32_to_cpu(*(++shmem_addr));
69 else /* CONFIG_ARM */
70 return be32_to_cpu(*shmem_addr);
71}
72
73static int fdt_set_scmi_shmem_reg(void)
74{
75 int ret = 0;
76 char cmdbuf[256] = {0};
77 u32 bl31_shmem_addr = get_scmi_shmem_addr();
78 u32 dtb_shmem_addr = ftd_get_scmi_shmem_addr();
79
80 if (dtb_shmem_addr == bl31_shmem_addr)
81 return 0;
82
83 printf("Warning: Address of shmem in DTB is inconsistent with BL31!!!\n");
84 printf("bl31_shmem_addr = 0x%x, dtb_shmem_addr = 0x%x\n",
85 bl31_shmem_addr, dtb_shmem_addr);
86 printf("Update the address of shmem in DTB\n");
87 memset(cmdbuf, 0, sizeof(cmdbuf));
88 if (ftd_get_root_address_cells() == 1) { /* CONFIG_ARM */
89 sprintf(cmdbuf, "fdt set /shmem reg <0x%x 0x100>",
90 bl31_shmem_addr);
91 } else if (ftd_get_root_address_cells() == 2) { /* CONFIG_ARM64 */
92 sprintf(cmdbuf, "fdt set /shmem reg <0 0x%x 0 0x100>",
93 bl31_shmem_addr);
94 } else {
95 printf("Error: Failed to adapt address-cells for DTB.\n");
96 return -ENXIO;
97 }
98 ret = run_command(cmdbuf, 0);
99 if (ret != 0) {
100 printf("Error: Failed to set reg of scmi_shmem for DTB\n");
101 return -EBADMSG;
102 }
103
104 memset(cmdbuf, 0, sizeof(cmdbuf));
105 sprintf(cmdbuf, "fdt set /shmem ranges <0 0 0x%x 0x100>",
106 bl31_shmem_addr);
107 ret = run_command(cmdbuf, 0);
108 if (ret != 0) {
109 printf("Error: Failed to set ranges of scmi_shmem for DTB\n");
110 return -EBADMSG;
111 }
112
113 return 0;
114}
115
116static int do_update_scmi_shmem(cmd_tbl_t *cmdtp, int flag, int argc,
117 char * const argv[])
118{
119 return fdt_set_scmi_shmem_reg();
120}
121
122U_BOOT_CMD(update_scmi_shmem, 1, 0, do_update_scmi_shmem,
123 "Update the shared memory address of the SCMI in the DTB",
124 ""
125);