[PATCH v2 0/8] Add SM uclass and Meson SM driver

Hello!
At the moment, there is no single general approach to using secure monitor in U-Boot, there is only the smc_call() function, over which everyone builds their own add-ons. This patchset is designed to solve this problem by adding a new uclass - SM_UCLASS. This UCLASS export following generic API:
1. sm_call() - generic SMC call to the secure-monitor 2. sm_call_read() - retrieve data from secure-monitor 3. sm_call_write() - send data to secure-monitor
In the future, it is necessary to completely get rid of raw smc_call() calls, replacing them with the use of SM_UCLASS based drivers.
V2:
- Add SM UCLASS - Add SM sandbox driver - Add test for sandbox driver - Meson Secure Monitor driver now based on SM_UCLASS - Fix include order in arch/arm/mach-meson/sm.c
Also, during the discussion in V1 of this patchset, it was discussed to create MESON_SM_UCLASS, but I considered such a uclass to be too arch-specific. That's why I suggest SM_UCLASS, which is not so arch-specific: secure monitor can used for whole ARM devices, not only for Amlogic SoC's.
Alexey Romanov (8): drivers: introduce Secure Monitor uclass sandbox: add sandobx sm uclass driver sandbox: dts: add meson secure monitor node sandbox: add tests for UCLASS_SM sandbox: defconfig: enable CONFIG_SM option drivers: introduce Meson Secure Monitor driver arch: meson: sm: set correct order of the includes arch: meson: use secure monitor driver
MAINTAINERS | 1 + arch/arm/mach-meson/Kconfig | 1 + arch/arm/mach-meson/sm.c | 116 +++++++++++---------- arch/sandbox/dts/test.dts | 4 + configs/sandbox_defconfig | 1 + drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/sm/Kconfig | 9 ++ drivers/sm/Makefile | 5 + drivers/sm/meson-sm.c | 198 ++++++++++++++++++++++++++++++++++++ drivers/sm/sandbox-sm.c | 76 ++++++++++++++ drivers/sm/sm-uclass.c | 55 ++++++++++ include/dm/uclass-id.h | 1 + include/meson/sm.h | 19 ++++ include/sandbox-sm.h | 18 ++++ include/sm-uclass.h | 72 +++++++++++++ include/sm.h | 67 ++++++++++++ test/dm/Makefile | 1 + test/dm/sm.c | 65 ++++++++++++ 19 files changed, 656 insertions(+), 56 deletions(-) create mode 100644 drivers/sm/Kconfig create mode 100644 drivers/sm/Makefile create mode 100644 drivers/sm/meson-sm.c create mode 100644 drivers/sm/sandbox-sm.c create mode 100644 drivers/sm/sm-uclass.c create mode 100644 include/meson/sm.h create mode 100644 include/sandbox-sm.h create mode 100644 include/sm-uclass.h create mode 100644 include/sm.h create mode 100644 test/dm/sm.c

At the moment, we don't have a common API for working with SM, only the smc_call() function. This approach is not generic and difficult to configure and maintain.
This patch adds UCLASS_SM with the generic API:
- sm_call() - sm_call_write() - sm_call_read()
These functions operate with struct pt_regs, which describes Secure Monitor arguments.
Signed-off-by: Alexey Romanov avromanov@salutedevices.com --- drivers/Kconfig | 2 ++ drivers/Makefile | 1 + drivers/sm/Kconfig | 2 ++ drivers/sm/Makefile | 3 ++ drivers/sm/sm-uclass.c | 55 ++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/sm-uclass.h | 72 ++++++++++++++++++++++++++++++++++++++++++ include/sm.h | 67 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 203 insertions(+) create mode 100644 drivers/sm/Kconfig create mode 100644 drivers/sm/Makefile create mode 100644 drivers/sm/sm-uclass.c create mode 100644 include/sm-uclass.h create mode 100644 include/sm.h
diff --git a/drivers/Kconfig b/drivers/Kconfig index 75ac149d31..72e6405322 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -112,6 +112,8 @@ source "drivers/scsi/Kconfig"
source "drivers/serial/Kconfig"
+source "drivers/sm/Kconfig" + source "drivers/smem/Kconfig"
source "drivers/sound/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 6f1de58e00..b7bd3633b1 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -124,3 +124,4 @@ obj-$(CONFIG_DM_RNG) += rng/ endif
obj-y += soc/ +obj-y += sm/ diff --git a/drivers/sm/Kconfig b/drivers/sm/Kconfig new file mode 100644 index 0000000000..6cc6d55578 --- /dev/null +++ b/drivers/sm/Kconfig @@ -0,0 +1,2 @@ +config SM + bool "Enable Secure Monitor driver support" diff --git a/drivers/sm/Makefile b/drivers/sm/Makefile new file mode 100644 index 0000000000..9f4683ba06 --- /dev/null +++ b/drivers/sm/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-y += sm-uclass.o diff --git a/drivers/sm/sm-uclass.c b/drivers/sm/sm-uclass.c new file mode 100644 index 0000000000..78af857026 --- /dev/null +++ b/drivers/sm/sm-uclass.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2023 SberDevices, Inc. + * + * Author: Alexey Romanov avromanov@salutedevices.com + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <sm-uclass.h> + +static const struct sm_ops *get_sm_ops(struct udevice *dev) +{ + return (const struct sm_ops *)dev->driver->ops; +} + +int sm_call(struct udevice *dev, u32 cmd, s32 *ret, struct pt_regs *args) +{ + const struct sm_ops *ops = get_sm_ops(dev); + + if (ops->sm_call) + return ops->sm_call(dev, cmd, ret, args); + + return -EPROTONOSUPPORT; +} + +int sm_call_read(struct udevice *dev, void *buffer, size_t size, + u32 cmd, struct pt_regs *args) +{ + const struct sm_ops *ops = get_sm_ops(dev); + + if (ops->sm_call_read) + return ops->sm_call_read(dev, buffer, size, cmd, + args); + + return -EPROTONOSUPPORT; +} + +int sm_call_write(struct udevice *dev, void *buffer, size_t size, + u32 cmd, struct pt_regs *args) +{ + const struct sm_ops *ops = get_sm_ops(dev); + + if (ops->sm_call_write) + return ops->sm_call_write(dev, buffer, size, cmd, + args); + + return -EPROTONOSUPPORT; +} + +UCLASS_DRIVER(sm) = { + .name = "sm", + .id = UCLASS_SM, +}; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 376f741cc2..545c9352a8 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -80,6 +80,7 @@ enum uclass_id { UCLASS_MDIO, /* MDIO bus */ UCLASS_MDIO_MUX, /* MDIO MUX/switch */ UCLASS_MEMORY, /* Memory Controller device */ + UCLASS_SM, /* Secure Monitor driver */ UCLASS_MISC, /* Miscellaneous device */ UCLASS_MMC, /* SD / MMC card or chip */ UCLASS_MOD_EXP, /* RSA Mod Exp device */ diff --git a/include/sm-uclass.h b/include/sm-uclass.h new file mode 100644 index 0000000000..c114484044 --- /dev/null +++ b/include/sm-uclass.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2023 SberDevices, Inc. + * + * Author: Alexey Romanov avromanov@salutedevices.com + */ + +#ifndef __SM_UCLASS_H__ +#define __SM_UCLASS_H__ + +#include <asm/types.h> +#include <asm/ptrace.h> + +struct udevice; + +/** + * struct sm_ops - The functions that a SM driver must implement. + * + * @sm_call: Request a secure monitor call with specified command. + * + * @sm_call_read: Request a secure monitor call and retrieve data + * from secure-monitor (depends on specified command). + * + * @sm_call_write: Request a secure monitor call and send data + * to secure-monitor (depends on specified command). + * + * The individual methods are described more fully below. + */ +struct sm_ops { + /** + * sm_call - generic SMC call to the secure-monitor + * + * @dev: Pointer to UCLASS_SM device + * @cmd_index: Index of the SMC function ID + * @smc_ret: Returned value from secure world + * @args: SMC arguments + * + * @return: 0 on success, a negative value on error + */ + int (*sm_call)(struct udevice *dev, u32 cmd, s32 *smc_ret, + struct pt_regs *args); + + /** + * sm_call_write - send data to secure-monitor + * + * @dev: Pointer to UCLASS_SM device + * @buffer: Buffer containing data to send + * @size: Size of the buffer + * @cmd: Index of the SMC function ID + * @args: SMC arguments + * + * @return: size of sent data on success, a negative value on error + */ + int (*sm_call_write)(struct udevice *dev, void *buffer, + size_t size, u32 cmd, struct pt_regs *args); + + /** + * sm_call_read - retrieve data from secure-monitor + * + * @dev: Pointer to UCLASS_SM device + * @buffer: Buffer to store the retrieved data + * @size: Size of the buffer + * @cmd: Index of the SMC function ID + * @args: SMC arguments + * + * @return: size of read data on success, a negative value on error + */ + int (*sm_call_read)(struct udevice *dev, void *buffer, + size_t size, u32 cmd, struct pt_regs *args); +}; + +#endif /* __SM_UCLASS_H__ */ diff --git a/include/sm.h b/include/sm.h new file mode 100644 index 0000000000..afa9c89055 --- /dev/null +++ b/include/sm.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2023 SberDevices, Inc. + * + * Author: Alexey Romanov avromanov@salutedevices.ru + */ + +#ifndef __SM_H__ +#define __SM_H__ + +/* + * NOTE: UCLASS_SM is designed with the idea that + * each driver should convert @cmd to some raw + * value, which is known only for driver, and set this + * value to the first element of the @args->regs array. + * Therefore, it is necessary to pass the remaining + * arguments starting at index = 1. Anyway, driver + * implementation may vary, so, please, check the specific + * implementation of the driver you are using. + */ + +#include <asm/types.h> +#include <asm/ptrace.h> + +struct udevice; + +/** + * sm_call - generic SMC call to the secure-monitor + * + * @dev: Pointer to UCLASS_SM device + * @cmd_index: Index of the SMC function ID + * @smc_ret: Returned value from secure world + * @args: SMC arguments + * + * @return: 0 on success, a negative value on error + */ +int sm_call(struct udevice *dev, u32 cmd, s32 *ret, struct pt_regs *args); + +/** + * sm_call_read - retrieve data from secure-monitor + * + * @dev: Pointer to UCLASS_MESON_SM device + * @buffer: Buffer to store the retrieved data + * @size: Size of the buffer + * @cmd: Index of the SMC function ID + * @args: SMC arguments + * + * @return: size of read data on success, a negative value on error + */ +int sm_call_read(struct udevice *dev, void *buffer, size_t size, + u32 cmd, struct pt_regs *args); + +/** + * sm_call_write - send data to secure-monitor + * + * @dev: Pointer to UCLASS_SM device + * @buffer: Buffer containing data to send + * @size: Size of the buffer + * @cmd: Index of the SMC function ID + * @args: SMC arguments + * + * @return: size of sent data on success, a negative value on error + */ +int sm_call_write(struct udevice *dev, void *buffer, size_t size, + u32 cmd, struct pt_regs *args); + +#endif /* __SM_H__ */

Hi Alexey,
On Mon, 11 Sept 2023 at 10:35, Alexey Romanov avromanov@salutedevices.com wrote:
At the moment, we don't have a common API for working with SM, only the smc_call() function. This approach is not generic and difficult to configure and maintain.
This patch adds UCLASS_SM with the generic API:
- sm_call()
- sm_call_write()
- sm_call_read()
These functions operate with struct pt_regs, which describes Secure Monitor arguments.
Signed-off-by: Alexey Romanov avromanov@salutedevices.com
drivers/Kconfig | 2 ++ drivers/Makefile | 1 + drivers/sm/Kconfig | 2 ++ drivers/sm/Makefile | 3 ++ drivers/sm/sm-uclass.c | 55 ++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/sm-uclass.h | 72 ++++++++++++++++++++++++++++++++++++++++++ include/sm.h | 67 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 203 insertions(+) create mode 100644 drivers/sm/Kconfig create mode 100644 drivers/sm/Makefile create mode 100644 drivers/sm/sm-uclass.c create mode 100644 include/sm-uclass.h create mode 100644 include/sm.h
Reviewed-by: Simon Glass sjg@chromium.org
nit below
diff --git a/drivers/Kconfig b/drivers/Kconfig index 75ac149d31..72e6405322 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -112,6 +112,8 @@ source "drivers/scsi/Kconfig"
source "drivers/serial/Kconfig"
+source "drivers/sm/Kconfig"
source "drivers/smem/Kconfig"
source "drivers/sound/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 6f1de58e00..b7bd3633b1 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -124,3 +124,4 @@ obj-$(CONFIG_DM_RNG) += rng/ endif
obj-y += soc/ +obj-y += sm/ diff --git a/drivers/sm/Kconfig b/drivers/sm/Kconfig new file mode 100644 index 0000000000..6cc6d55578 --- /dev/null +++ b/drivers/sm/Kconfig @@ -0,0 +1,2 @@ +config SM
bool "Enable Secure Monitor driver support"
diff --git a/drivers/sm/Makefile b/drivers/sm/Makefile new file mode 100644 index 0000000000..9f4683ba06 --- /dev/null +++ b/drivers/sm/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only
+obj-y += sm-uclass.o diff --git a/drivers/sm/sm-uclass.c b/drivers/sm/sm-uclass.c new file mode 100644 index 0000000000..78af857026 --- /dev/null +++ b/drivers/sm/sm-uclass.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (c) 2023 SberDevices, Inc.
- Author: Alexey Romanov avromanov@salutedevices.com
- */
+#include <common.h> +#include <dm.h> +#include <errno.h> +#include <sm-uclass.h>
+static const struct sm_ops *get_sm_ops(struct udevice *dev) +{
return (const struct sm_ops *)dev->driver->ops;
+}
+int sm_call(struct udevice *dev, u32 cmd, s32 *ret, struct pt_regs *args) +{
const struct sm_ops *ops = get_sm_ops(dev);
if (ops->sm_call)
return ops->sm_call(dev, cmd, ret, args);
return -EPROTONOSUPPORT;
We normally use -ENOSYS in U-Boot
Regards, Simon

This patch adds sandbox secure monitor driver.
Signed-off-by: Alexey Romanov avromanov@salutedevices.com --- drivers/sm/Makefile | 1 + drivers/sm/sandbox-sm.c | 76 +++++++++++++++++++++++++++++++++++++++++ include/sandbox-sm.h | 18 ++++++++++ 3 files changed, 95 insertions(+) create mode 100644 drivers/sm/sandbox-sm.c create mode 100644 include/sandbox-sm.h
diff --git a/drivers/sm/Makefile b/drivers/sm/Makefile index 9f4683ba06..af5f475c2b 100644 --- a/drivers/sm/Makefile +++ b/drivers/sm/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only
obj-y += sm-uclass.o +obj-$(CONFIG_SANDBOX) += sandbox-sm.o diff --git a/drivers/sm/sandbox-sm.c b/drivers/sm/sandbox-sm.c new file mode 100644 index 0000000000..109ddb2af5 --- /dev/null +++ b/drivers/sm/sandbox-sm.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2023 SberDevices, Inc. + * + * Author: Alexey Romanov avromanov@salutedevices.com + */ + +#include <common.h> +#include <sm.h> +#include <sm-uclass.h> +#include <sandbox-sm.h> +#include <asm/ptrace.h> +#include <dm/device.h> +#include <linux/sizes.h> + +static u8 test_buffer[SZ_4K]; + +static int sandbox_sm_call(struct udevice *dev, u32 cmd_index, s32 *smc_ret, + struct pt_regs *args) +{ + if (cmd_index >= SANDBOX_SMC_CMD_COUNT) + return -EINVAL; + + if (smc_ret) + *smc_ret = 0; + + return 0; +} + +static int sandbox_sm_call_read(struct udevice *dev, void *buffer, size_t size, + u32 cmd_index, struct pt_regs *args) +{ + if (cmd_index >= SANDBOX_SMC_CMD_COUNT || !buffer) + return -EINVAL; + + if (size > sizeof(test_buffer)) + return -EINVAL; + + memcpy(buffer, test_buffer, size); + + return size; +} + +static int sandbox_sm_call_write(struct udevice *dev, void *buffer, size_t size, + u32 cmd_index, struct pt_regs *args) +{ + if (cmd_index >= SANDBOX_SMC_CMD_COUNT || !buffer) + return -EINVAL; + + if (size > sizeof(test_buffer)) + return -EINVAL; + + memcpy(test_buffer, buffer, size); + + return size; +} + +static const struct udevice_id sandbox_sm_ids[] = { + { + .compatible = "sandbox,sm", + }, + {}, +}; + +static const struct sm_ops sandbox_sm_ops = { + .sm_call = sandbox_sm_call, + .sm_call_read = sandbox_sm_call_read, + .sm_call_write = sandbox_sm_call_write, +}; + +U_BOOT_DRIVER(sm) = { + .name = "sm", + .id = UCLASS_SM, + .of_match = sandbox_sm_ids, + .ops = &sandbox_sm_ops, +}; diff --git a/include/sandbox-sm.h b/include/sandbox-sm.h new file mode 100644 index 0000000000..91c30d501d --- /dev/null +++ b/include/sandbox-sm.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2023 SberDevices, Inc. + * + * Author: Alexey Romanov avromanov@salutedevices.com + */ + +#ifndef __SANDBOX_SM_H__ +#define __SANDBOX_SM_H__ + +enum sandbox_smc_cmd { + SANDBOX_SMC_CMD_READ_MEM, + SANDBOX_SMC_CMD_WRITE_MEM, + SANDBOX_SMC_CMD_COMMON, + SANDBOX_SMC_CMD_COUNT, +}; + +#endif

Hi Alexey,
On Mon, 11 Sept 2023 at 10:35, Alexey Romanov avromanov@salutedevices.com wrote:
This patch adds sandbox secure monitor driver.
Please fix typo in subject
Signed-off-by: Alexey Romanov avromanov@salutedevices.com
drivers/sm/Makefile | 1 + drivers/sm/sandbox-sm.c | 76 +++++++++++++++++++++++++++++++++++++++++ include/sandbox-sm.h | 18 ++++++++++ 3 files changed, 95 insertions(+) create mode 100644 drivers/sm/sandbox-sm.c create mode 100644 include/sandbox-sm.h
Reviewed-by: Simon Glass sjg@chromium.org

We need this to test UCLASS_SM.
Signed-off-by: Alexey Romanov avromanov@salutedevices.com --- arch/sandbox/dts/test.dts | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index dffe10adbf..4475aa58a6 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -693,6 +693,10 @@ }; }; }; + + sm: secure-monitor { + compatible = "sandbox,sm"; + }; };
fpga {

On Mon, 11 Sept 2023 at 10:35, Alexey Romanov avromanov@salutedevices.com wrote:
We need this to test UCLASS_SM.
Signed-off-by: Alexey Romanov avromanov@salutedevices.com
arch/sandbox/dts/test.dts | 4 ++++ 1 file changed, 4 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

This patchs adds simple tests for Secure Monitor uclass.
Signed-off-by: Alexey Romanov avromanov@salutedevices.com --- test/dm/Makefile | 1 + test/dm/sm.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 test/dm/sm.c
diff --git a/test/dm/Makefile b/test/dm/Makefile index 7a79b6e1a2..30550a62ad 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -107,6 +107,7 @@ obj-$(CONFIG_DM_SPI) += spi.o obj-$(CONFIG_SPMI) += spmi.o obj-y += syscon.o obj-$(CONFIG_RESET_SYSCON) += syscon-reset.o +obj-$(CONFIG_SM) += sm.o obj-$(CONFIG_SYSINFO) += sysinfo.o obj-$(CONFIG_SYSINFO_GPIO) += sysinfo-gpio.o obj-$(CONFIG_UT_DM) += tag.o diff --git a/test/dm/sm.c b/test/dm/sm.c new file mode 100644 index 0000000000..7ebb0c9c85 --- /dev/null +++ b/test/dm/sm.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2023 SberDevices, Inc. + * + * Author: Alexey Romanov avromanov@salutedevices.com + */ + +#include <common.h> +#include <dm.h> +#include <sm.h> +#include <sandbox-sm.h> +#include <asm/ptrace.h> +#include <dm/device-internal.h> +#include <dm/test.h> +#include <test/ut.h> +#include <linux/sizes.h> + +static int dm_test_sm(struct unit_test_state *uts) +{ + struct udevice *dev; + struct pt_regs regs; + char buffer[128] = { 0 }; + char test_string[] = "secure-monitor"; + int ret, val; + + ut_assertok(uclass_get_device_by_name(UCLASS_SM, + "secure-monitor", &dev)); + + ret = sm_call(dev, SANDBOX_SMC_CMD_COUNT, NULL, ®s); + ut_asserteq(ret, -EINVAL); + + ret = sm_call(dev, SANDBOX_SMC_CMD_COMMON, &val, ®s); + ut_asserteq(ret, 0); + ut_asserteq(val, 0); + + ret = sm_call_write(dev, buffer, sizeof(buffer), + SANDBOX_SMC_CMD_COUNT, ®s); + ut_asserteq(ret, -EINVAL); + + ret = sm_call_write(dev, buffer, SZ_4K + 1, + SANDBOX_SMC_CMD_WRITE_MEM, ®s); + ut_asserteq(ret, -EINVAL); + + ret = sm_call_write(dev, buffer, sizeof(buffer), + SANDBOX_SMC_CMD_COUNT, ®s); + ut_asserteq(ret, -EINVAL); + + ret = sm_call_write(dev, buffer, SZ_4K + 1, + SANDBOX_SMC_CMD_READ_MEM, ®s); + ut_asserteq(ret, -EINVAL); + + ret = sm_call_write(dev, test_string, sizeof(test_string), + SANDBOX_SMC_CMD_WRITE_MEM, ®s); + ut_asserteq(ret, sizeof(test_string)); + + ret = sm_call_read(dev, buffer, sizeof(buffer), + SANDBOX_SMC_CMD_READ_MEM, ®s); + ut_asserteq(ret, sizeof(buffer)); + + ut_asserteq_str(buffer, test_string); + + return 0; +} + +DM_TEST(dm_test_sm, UT_TESTF_SCAN_FDT);

On Mon, 11 Sept 2023 at 10:35, Alexey Romanov avromanov@salutedevices.com wrote:
This patchs adds simple tests for Secure Monitor uclass.
Signed-off-by: Alexey Romanov avromanov@salutedevices.com
test/dm/Makefile | 1 + test/dm/sm.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 test/dm/sm.c
Reviewed-by: Simon Glass sjg@chromium.org

We use this option for test UCLASS_SM.
Signed-off-by: Alexey Romanov avromanov@salutedevices.com --- configs/sandbox_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index be46cae7aa..0745a4ecca 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -270,6 +270,7 @@ CONFIG_RTC_RV8803=y CONFIG_SCSI=y CONFIG_DM_SCSI=y CONFIG_SANDBOX_SERIAL=y +CONFIG_SM=y CONFIG_SMEM=y CONFIG_SANDBOX_SMEM=y CONFIG_SOUND=y

On Mon, 11 Sept 2023 at 10:35, Alexey Romanov avromanov@salutedevices.com wrote:
We use this option for test UCLASS_SM.
s/for/to/
Signed-off-by: Alexey Romanov avromanov@salutedevices.com
configs/sandbox_defconfig | 1 + 1 file changed, 1 insertion(+)
Reviewed-by: Simon Glass sjg@chromium.org
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index be46cae7aa..0745a4ecca 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -270,6 +270,7 @@ CONFIG_RTC_RV8803=y CONFIG_SCSI=y CONFIG_DM_SCSI=y CONFIG_SANDBOX_SERIAL=y +CONFIG_SM=y CONFIG_SMEM=y CONFIG_SANDBOX_SMEM=y CONFIG_SOUND=y -- 2.25.1

This patch adds an implementation of the Meson Secure Monitor driver based on UCLASS_SM.
Signed-off-by: Alexey Romanov avromanov@salutedevices.com --- MAINTAINERS | 1 + drivers/sm/Kconfig | 7 ++ drivers/sm/Makefile | 1 + drivers/sm/meson-sm.c | 198 ++++++++++++++++++++++++++++++++++++++++++ include/meson/sm.h | 19 ++++ 5 files changed, 226 insertions(+) create mode 100644 drivers/sm/meson-sm.c create mode 100644 include/meson/sm.h
diff --git a/MAINTAINERS b/MAINTAINERS index 6c64427782..bdc364fd4c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -158,6 +158,7 @@ F: drivers/net/phy/meson-gxl.c F: drivers/adc/meson-saradc.c F: drivers/phy/meson* F: drivers/mmc/meson_gx_mmc.c +F: drivers/sm/meson-sm.c F: drivers/spi/meson_spifc.c F: drivers/pinctrl/meson/ F: drivers/power/domain/meson-gx-pwrc-vpu.c diff --git a/drivers/sm/Kconfig b/drivers/sm/Kconfig index 6cc6d55578..b4cc3f768e 100644 --- a/drivers/sm/Kconfig +++ b/drivers/sm/Kconfig @@ -1,2 +1,9 @@ config SM bool "Enable Secure Monitor driver support" + +config MESON_SM + bool "Amlogic Secure Monitor driver" + depends on SM + default n + help + Say y here to enable the Amlogic secure monitor driver. diff --git a/drivers/sm/Makefile b/drivers/sm/Makefile index af5f475c2b..da81ee898a 100644 --- a/drivers/sm/Makefile +++ b/drivers/sm/Makefile @@ -2,3 +2,4 @@
obj-y += sm-uclass.o obj-$(CONFIG_SANDBOX) += sandbox-sm.o +obj-$(CONFIG_MESON_SM) += meson-sm.o diff --git a/drivers/sm/meson-sm.c b/drivers/sm/meson-sm.c new file mode 100644 index 0000000000..25adaf4560 --- /dev/null +++ b/drivers/sm/meson-sm.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2023 SberDevices, Inc. + * + * Author: Alexey Romanov avromanov@salutedevices.com + */ + +#include <common.h> +#include <dm.h> +#include <regmap.h> +#include <sm.h> +#include <sm-uclass.h> +#include <stdlib.h> +#include <syscon.h> +#include <asm/ptrace.h> +#include <asm/system.h> +#include <meson/sm.h> +#include <linux/bitfield.h> +#include <linux/err.h> +#include <linux/sizes.h> + +struct meson_sm_cmd { + u32 smc_id; +}; + +#define SET_CMD(index, id) \ + [index] = { \ + .smc_id = (id), \ + } + +struct meson_sm_data { + u32 cmd_get_shmem_in; + u32 cmd_get_shmem_out; + unsigned int shmem_size; + struct meson_sm_cmd cmd[]; +}; + +struct meson_sm_priv { + void *sm_shmem_in; + void *sm_shmem_out; + const struct meson_sm_data *data; +}; + +static unsigned long __meson_sm_call(u32 cmd, const struct pt_regs *args) +{ + struct pt_regs r = *args; + + r.regs[0] = cmd; + smc_call(&r); + + return r.regs[0]; +}; + +static u32 meson_sm_get_cmd(const struct meson_sm_data *data, + u32 cmd_index) +{ + struct meson_sm_cmd cmd; + + if (cmd_index >= MESON_SMC_CMD_COUNT) + return 0; + + cmd = data->cmd[cmd_index]; + return cmd.smc_id; +} + +static int meson_sm_call(struct udevice *dev, u32 cmd_index, s32 *retval, + struct pt_regs *args) +{ + struct meson_sm_priv *priv = dev_get_priv(dev); + u32 cmd, ret; + + cmd = meson_sm_get_cmd(priv->data, cmd_index); + if (!cmd) + return -ENOENT; + + ret = __meson_sm_call(cmd, args); + if (retval) + *retval = ret; + + return 0; +} + +static int meson_sm_call_read(struct udevice *dev, void *buffer, size_t size, + u32 cmd_index, struct pt_regs *args) +{ + struct meson_sm_priv *priv = dev_get_priv(dev); + s32 nbytes; + int ret; + + if (!buffer || size > priv->data->shmem_size) + return -EINVAL; + + ret = meson_sm_call(dev, cmd_index, &nbytes, args); + if (ret) + return ret; + + if (nbytes < 0 || nbytes > size) + return -ENOBUFS; + + /* In some cases (for example GET_CHIP_ID command), + * SMC doesn't return the number of bytes read, even + * though the bytes were actually read into sm_shmem_out. + * So this check is needed. + */ + ret = nbytes; + if (!nbytes) + nbytes = size; + + memcpy(buffer, priv->sm_shmem_out, nbytes); + + return ret; +} + +static int meson_sm_call_write(struct udevice *dev, void *buffer, size_t size, + u32 cmd_index, struct pt_regs *args) +{ + struct meson_sm_priv *priv = dev_get_priv(dev); + s32 nbytes; + int ret; + + if (!buffer || size > priv->data->shmem_size) + return -EINVAL; + + memcpy(priv->sm_shmem_in, buffer, size); + + ret = meson_sm_call(dev, cmd_index, &nbytes, args); + if (ret) + return ret; + + if (nbytes <= 0 || nbytes > size) + return -EIO; + + return nbytes; +} + +static int meson_sm_probe(struct udevice *dev) +{ + struct meson_sm_priv *priv = dev_get_priv(dev); + struct pt_regs regs = { 0 }; + + priv->data = (struct meson_sm_data *)dev_get_driver_data(dev); + if (!priv->data) + return -EINVAL; + + priv->sm_shmem_in = + (void *)__meson_sm_call(priv->data->cmd_get_shmem_in, ®s); + + if (!priv->sm_shmem_in) + return -ENOMEM; + + priv->sm_shmem_out = + (void *)__meson_sm_call(priv->data->cmd_get_shmem_out, ®s); + + if (!priv->sm_shmem_out) + return -ENOMEM; + + pr_debug("meson sm driver probed\n" + "shmem_in addr: 0x%p, shmem_out addr: 0x%p\n", + priv->sm_shmem_in, + priv->sm_shmem_out); + + return 0; +} + +static const struct meson_sm_data meson_sm_gxbb_data = { + .cmd_get_shmem_in = 0x82000020, + .cmd_get_shmem_out = 0x82000021, + .shmem_size = SZ_4K, + .cmd = { + SET_CMD(MESON_SMC_CMD_EFUSE_READ, 0x82000030), + SET_CMD(MESON_SMC_CMD_EFUSE_WRITE, 0x82000031), + SET_CMD(MESON_SMC_CMD_CHIP_ID_GET, 0x82000044), + SET_CMD(MESON_SMC_CMD_PWRDM_SET, 0x82000093), + }, +}; + +static const struct udevice_id meson_sm_ids[] = { + { + .compatible = "amlogic,meson-gxbb-sm", + .data = (ulong)&meson_sm_gxbb_data, + }, + { } +}; + +static const struct sm_ops sm_ops = { + .sm_call = meson_sm_call, + .sm_call_read = meson_sm_call_read, + .sm_call_write = meson_sm_call_write, +}; + +U_BOOT_DRIVER(meson_sm) = { + .name = "meson_sm", + .id = UCLASS_SM, + .of_match = meson_sm_ids, + .probe = meson_sm_probe, + .priv_auto = sizeof(struct meson_sm_priv), + .ops = &sm_ops, +}; diff --git a/include/meson/sm.h b/include/meson/sm.h new file mode 100644 index 0000000000..fbaab1f1ee --- /dev/null +++ b/include/meson/sm.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2023 SberDevices, Inc. + * + * Author: Alexey Romanov avromanov@salutedevices.com + */ + +#ifndef __MESON_SM_CMD_H__ +#define __MESON_SM_CMD_H__ + +enum meson_smc_cmd { + MESON_SMC_CMD_EFUSE_READ, /* read efuse memory */ + MESON_SMC_CMD_EFUSE_WRITE, /* write efuse memory */ + MESON_SMC_CMD_CHIP_ID_GET, /* readh chip unique id */ + MESON_SMC_CMD_PWRDM_SET, /* do command at specified power domain */ + MESON_SMC_CMD_COUNT, +}; + +#endif

On Mon, 11 Sept 2023 at 10:35, Alexey Romanov avromanov@salutedevices.com wrote:
This patch adds an implementation of the Meson Secure Monitor driver based on UCLASS_SM.
Signed-off-by: Alexey Romanov avromanov@salutedevices.com
MAINTAINERS | 1 + drivers/sm/Kconfig | 7 ++ drivers/sm/Makefile | 1 + drivers/sm/meson-sm.c | 198 ++++++++++++++++++++++++++++++++++++++++++ include/meson/sm.h | 19 ++++ 5 files changed, 226 insertions(+) create mode 100644 drivers/sm/meson-sm.c create mode 100644 include/meson/sm.h
Reviewed-by: Simon Glass sjg@chromium.org

The common.h header should always be first, followed by other headers in order, then headers with directories, then local files.
Signed-off-by: Alexey Romanov avromanov@salutedevices.com --- arch/arm/mach-meson/sm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c index d600c64d0b..b5dd6c6d39 100644 --- a/arch/arm/mach-meson/sm.c +++ b/arch/arm/mach-meson/sm.c @@ -6,7 +6,10 @@ */
#include <common.h> +#include <dm.h> #include <log.h> +#include <regmap.h> +#include <syscon.h> #include <asm/arch/sm.h> #include <asm/cache.h> #include <asm/global_data.h> @@ -14,10 +17,7 @@ #include <linux/bitops.h> #include <linux/err.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

On Mon, 11 Sept 2023 at 10:35, Alexey Romanov avromanov@salutedevices.com wrote:
The common.h header should always be first, followed by other headers in order, then headers with directories, then local files.
Signed-off-by: Alexey Romanov avromanov@salutedevices.com
arch/arm/mach-meson/sm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c index d600c64d0b..b5dd6c6d39 100644 --- a/arch/arm/mach-meson/sm.c +++ b/arch/arm/mach-meson/sm.c @@ -6,7 +6,10 @@ */
#include <common.h> +#include <dm.h> #include <log.h> +#include <regmap.h> +#include <syscon.h> #include <asm/arch/sm.h> #include <asm/cache.h> #include <asm/global_data.h> @@ -14,10 +17,7 @@ #include <linux/bitops.h> #include <linux/err.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
2.25.1

Now we have to use UCLASS_SM driver instead of raw smc_call() function call.
Signed-off-by: Alexey Romanov avromanov@salutedevices.com --- arch/arm/mach-meson/Kconfig | 1 + arch/arm/mach-meson/sm.c | 110 +++++++++++++++++++----------------- 2 files changed, 58 insertions(+), 53 deletions(-)
diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig index 669ca09a00..d6c8905806 100644 --- a/arch/arm/mach-meson/Kconfig +++ b/arch/arm/mach-meson/Kconfig @@ -11,6 +11,7 @@ config MESON64_COMMON select PWRSEQ select MMC_PWRSEQ select BOARD_LATE_INIT + select MESON_SM imply CMD_DM
config MESON_GX diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c index b5dd6c6d39..0c60aa8695 100644 --- a/arch/arm/mach-meson/sm.c +++ b/arch/arm/mach-meson/sm.c @@ -9,6 +9,7 @@ #include <dm.h> #include <log.h> #include <regmap.h> +#include <sm.h> #include <syscon.h> #include <asm/arch/sm.h> #include <asm/cache.h> @@ -18,70 +19,62 @@ #include <linux/err.h> #include <linux/kernel.h> #include <linux/bitfield.h> +#include <meson/sm.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 -#define FN_PWRDM_SET 0x82000093 - -static void *shmem_input; -static void *shmem_output; - -static void meson_init_shmem(void) +static inline struct udevice *meson_get_sm_device(void) { - struct pt_regs regs; - - if (shmem_input && shmem_output) - return; + struct udevice *dev; + int err;
- 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]; + err = uclass_get_device_by_name(UCLASS_SM, "secure-monitor", &dev); + if (err) { + pr_err("Mesom SM device not found\n"); + return ERR_PTR(err); + }
- debug("Secure Monitor shmem: 0x%p 0x%p\n", shmem_input, shmem_output); + return dev; }
ssize_t meson_sm_read_efuse(uintptr_t offset, void *buffer, size_t size) { - struct pt_regs regs; + struct udevice *dev; + struct pt_regs regs = { 0 }; + int err;
- meson_init_shmem(); + dev = meson_get_sm_device(); + if (IS_ERR(dev)) + return PTR_ERR(dev);
- regs.regs[0] = FN_EFUSE_READ; regs.regs[1] = offset; regs.regs[2] = size;
- smc_call(®s); + err = sm_call_read(dev, buffer, size, + MESON_SMC_CMD_EFUSE_READ, ®s); + if (err < 0) + pr_err("Failed to read efuse memory (%d)\n", err);
- if (regs.regs[0] == 0) - return -1; - - memcpy(buffer, shmem_output, min(size, regs.regs[0])); - - return regs.regs[0]; + return err; }
ssize_t meson_sm_write_efuse(uintptr_t offset, void *buffer, size_t size) { - struct pt_regs regs; - - meson_init_shmem(); + struct udevice *dev; + struct pt_regs regs = { 0 }; + int err;
- memcpy(shmem_input, buffer, size); + dev = meson_get_sm_device(); + if (IS_ERR(dev)) + return PTR_ERR(dev);
- regs.regs[0] = FN_EFUSE_WRITE; regs.regs[1] = offset; regs.regs[2] = size;
- smc_call(®s); + err = sm_call_write(dev, buffer, size, + MESON_SMC_CMD_EFUSE_WRITE, ®s); + if (err < 0) + pr_err("Failed to write efuse memory (%d)\n", err);
- return regs.regs[0]; + return err; }
#define SM_CHIP_ID_LENGTH 119 @@ -90,18 +83,21 @@ ssize_t meson_sm_write_efuse(uintptr_t offset, void *buffer, size_t size)
int meson_sm_get_serial(void *buffer, size_t size) { - struct pt_regs regs; + struct udevice *dev; + struct pt_regs regs = { 0 }; + u8 id_buffer[SM_CHIP_ID_LENGTH]; + int err;
- meson_init_shmem(); + dev = meson_get_sm_device(); + if (IS_ERR(dev)) + return PTR_ERR(dev);
- regs.regs[0] = FN_CHIP_ID; - regs.regs[1] = 0; - regs.regs[2] = 0; + err = sm_call_read(dev, id_buffer, SM_CHIP_ID_LENGTH, + MESON_SMC_CMD_CHIP_ID_GET, ®s); + if (err < 0) + pr_err("Failed to read serial number (%d)\n", err);
- smc_call(®s); - - memcpy(buffer, shmem_output + SM_CHIP_ID_OFFSET, - min_t(size_t, size, SM_CHIP_ID_SIZE)); + memcpy(buffer, id_buffer + SM_CHIP_ID_OFFSET, size);
return 0; } @@ -141,13 +137,21 @@ int meson_sm_get_reboot_reason(void)
int meson_sm_pwrdm_set(size_t index, int cmd) { - struct pt_regs regs; + struct udevice *dev; + struct pt_regs regs = { 0 }; + int err; + + dev = meson_get_sm_device(); + if (IS_ERR(dev)) + return PTR_ERR(dev);
- regs.regs[0] = FN_PWRDM_SET; regs.regs[1] = index; regs.regs[2] = cmd;
- smc_call(®s); + err = sm_call(dev, MESON_SMC_CMD_PWRDM_SET, NULL, ®s); + if (err) + pr_err("Failed to %s power domain ind=%zu (%d)\n", cmd == PWRDM_ON ? + "enable" : "disable", index, err);
- return regs.regs[0]; + return err; }

Hi Alexey,
On Mon, 11 Sept 2023 at 10:35, Alexey Romanov avromanov@salutedevices.com wrote:
Now we have to use UCLASS_SM driver instead of raw smc_call() function call.
Signed-off-by: Alexey Romanov avromanov@salutedevices.com
arch/arm/mach-meson/Kconfig | 1 + arch/arm/mach-meson/sm.c | 110 +++++++++++++++++++----------------- 2 files changed, 58 insertions(+), 53 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
with fix below
diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig index 669ca09a00..d6c8905806 100644 --- a/arch/arm/mach-meson/Kconfig +++ b/arch/arm/mach-meson/Kconfig @@ -11,6 +11,7 @@ config MESON64_COMMON select PWRSEQ select MMC_PWRSEQ select BOARD_LATE_INIT
select MESON_SM imply CMD_DM
config MESON_GX diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c index b5dd6c6d39..0c60aa8695 100644 --- a/arch/arm/mach-meson/sm.c +++ b/arch/arm/mach-meson/sm.c @@ -9,6 +9,7 @@ #include <dm.h> #include <log.h> #include <regmap.h> +#include <sm.h> #include <syscon.h> #include <asm/arch/sm.h> #include <asm/cache.h> @@ -18,70 +19,62 @@ #include <linux/err.h> #include <linux/kernel.h> #include <linux/bitfield.h> +#include <meson/sm.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 -#define FN_PWRDM_SET 0x82000093
-static void *shmem_input; -static void *shmem_output;
-static void meson_init_shmem(void) +static inline struct udevice *meson_get_sm_device(void) {
struct pt_regs regs;
if (shmem_input && shmem_output)
return;
struct udevice *dev;
int err;
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];
err = uclass_get_device_by_name(UCLASS_SM, "secure-monitor", &dev);
Can you use uclass_first_device_err(UCLASS_SM, ...
instead? We should not be looking up devices by name.
if (err) {
pr_err("Mesom SM device not found\n");
return ERR_PTR(err);
}
debug("Secure Monitor shmem: 0x%p 0x%p\n", shmem_input, shmem_output);
return dev;
}
ssize_t meson_sm_read_efuse(uintptr_t offset, void *buffer, size_t size) {
struct pt_regs regs;
struct udevice *dev;
struct pt_regs regs = { 0 };
int err;
meson_init_shmem();
dev = meson_get_sm_device();
if (IS_ERR(dev))
return PTR_ERR(dev);
regs.regs[0] = FN_EFUSE_READ; regs.regs[1] = offset; regs.regs[2] = size;
smc_call(®s);
err = sm_call_read(dev, buffer, size,
MESON_SMC_CMD_EFUSE_READ, ®s);
if (err < 0)
pr_err("Failed to read efuse memory (%d)\n", err);
if (regs.regs[0] == 0)
return -1;
memcpy(buffer, shmem_output, min(size, regs.regs[0]));
return regs.regs[0];
return err;
}
ssize_t meson_sm_write_efuse(uintptr_t offset, void *buffer, size_t size) {
struct pt_regs regs;
meson_init_shmem();
struct udevice *dev;
struct pt_regs regs = { 0 };
int err;
memcpy(shmem_input, buffer, size);
dev = meson_get_sm_device();
if (IS_ERR(dev))
return PTR_ERR(dev);
regs.regs[0] = FN_EFUSE_WRITE; regs.regs[1] = offset; regs.regs[2] = size;
smc_call(®s);
err = sm_call_write(dev, buffer, size,
MESON_SMC_CMD_EFUSE_WRITE, ®s);
if (err < 0)
pr_err("Failed to write efuse memory (%d)\n", err);
return regs.regs[0];
return err;
}
#define SM_CHIP_ID_LENGTH 119 @@ -90,18 +83,21 @@ ssize_t meson_sm_write_efuse(uintptr_t offset, void *buffer, size_t size)
int meson_sm_get_serial(void *buffer, size_t size) {
struct pt_regs regs;
struct udevice *dev;
struct pt_regs regs = { 0 };
u8 id_buffer[SM_CHIP_ID_LENGTH];
int err;
meson_init_shmem();
dev = meson_get_sm_device();
if (IS_ERR(dev))
return PTR_ERR(dev);
regs.regs[0] = FN_CHIP_ID;
regs.regs[1] = 0;
regs.regs[2] = 0;
err = sm_call_read(dev, id_buffer, SM_CHIP_ID_LENGTH,
MESON_SMC_CMD_CHIP_ID_GET, ®s);
if (err < 0)
pr_err("Failed to read serial number (%d)\n", err);
smc_call(®s);
memcpy(buffer, shmem_output + SM_CHIP_ID_OFFSET,
min_t(size_t, size, SM_CHIP_ID_SIZE));
memcpy(buffer, id_buffer + SM_CHIP_ID_OFFSET, size); return 0;
} @@ -141,13 +137,21 @@ int meson_sm_get_reboot_reason(void)
int meson_sm_pwrdm_set(size_t index, int cmd) {
struct pt_regs regs;
struct udevice *dev;
struct pt_regs regs = { 0 };
int err;
dev = meson_get_sm_device();
if (IS_ERR(dev))
return PTR_ERR(dev);
regs.regs[0] = FN_PWRDM_SET; regs.regs[1] = index; regs.regs[2] = cmd;
smc_call(®s);
err = sm_call(dev, MESON_SMC_CMD_PWRDM_SET, NULL, ®s);
if (err)
pr_err("Failed to %s power domain ind=%zu (%d)\n", cmd == PWRDM_ON ?
"enable" : "disable", index, err);
return regs.regs[0];
return err;
}
2.25.1
Regards, Simon
participants (2)
-
Alexey Romanov
-
Simon Glass