arch/arm: meson: sm: introduce power domain functions

This commit adds functions to manage secure power domain for
Amlogic SoC's using smc functionality.

Signed-off-by: Alexey Romanov <avromanov@sberdevices.ru>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Link: https://lore.kernel.org/r/20230531093156.29240-2-avromanov@sberdevices.ru
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
diff --git a/arch/arm/include/asm/arch-meson/sm.h b/arch/arm/include/asm/arch-meson/sm.h
index 53b7517..4b1d564 100644
--- a/arch/arm/include/asm/arch-meson/sm.h
+++ b/arch/arm/include/asm/arch-meson/sm.h
@@ -58,4 +58,34 @@
  */
 int meson_sm_get_reboot_reason(void);
 
+#define PWRDM_OFF 0
+#define PWRDM_ON 1
+
+/**
+ * meson_sm_pwrdm_set - do command at specified power domain.
+ *
+ * @index: power domain index.
+ * @cmd: command index.
+ * @return: zero on success or error code on failure.
+ */
+int meson_sm_pwrdm_set(size_t index, int cmd);
+
+/**
+ * meson_sm_pwrdm_off - disable specified power domain.
+ *
+ * @index: power domain index.
+ * @return: zero on success or error code on failure.
+ */
+#define meson_sm_pwrdm_off(index) \
+	meson_sm_pwrdm_set(index, PWRDM_OFF)
+
+/**
+ * meson_sm_pwrdm_on - enable specified power domain.
+ *
+ * @index: power domain index.
+ * @return: zero on success or error code on failure.
+ */
+#define meson_sm_pwrdm_on(index) \
+	meson_sm_pwrdm_set(index, PWRDM_ON)
+
 #endif /* __MESON_SM_H__ */
diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c
index f2ca7e7..d600c64d 100644
--- a/arch/arm/mach-meson/sm.c
+++ b/arch/arm/mach-meson/sm.c
@@ -24,6 +24,7 @@
 #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;
@@ -137,3 +138,16 @@
 	/* The SMC call is not used, we directly use AO_SEC_SD_CFG15 */
 	return FIELD_GET(REBOOT_REASON_MASK, reason);
 }
+
+int meson_sm_pwrdm_set(size_t index, int cmd)
+{
+	struct pt_regs regs;
+
+	regs.regs[0] = FN_PWRDM_SET;
+	regs.regs[1] = index;
+	regs.regs[2] = cmd;
+
+	smc_call(&regs);
+
+	return regs.regs[0];
+}