^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Xilinx Zynq MPSoC Firmware layer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2014-2021 Xilinx, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Michal Simek <michal.simek@xilinx.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Davorin Mista <davorin.mista@aggios.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Jolly Shah <jollys@xilinx.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Rajan Vaja <rajanv@xilinx.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/arm-smccc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/mfd/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/hashtable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/firmware/xlnx-zynqmp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "zynqmp-debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* Max HashMap Order for PM API feature check (1<<7 = 128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define PM_API_FEATURE_CHECK_MAX_ORDER 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static bool feature_check_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * struct pm_api_feature_data - PM API Feature data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * @pm_api_id: PM API Id, used as key to index into hashmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * @feature_status: status of PM API feature: valid, invalid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * @hentry: hlist_node that hooks this entry into hashtable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct pm_api_feature_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u32 pm_api_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int feature_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct hlist_node hentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static const struct mfd_cell firmware_devs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .name = "zynqmp_power_controller",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * @ret_status: PMUFW return code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * Return: corresponding Linux error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int zynqmp_pm_ret_code(u32 ret_status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) switch (ret_status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) case XST_PM_SUCCESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) case XST_PM_DOUBLE_REQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) case XST_PM_NO_FEATURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) case XST_PM_NO_ACCESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) case XST_PM_ABORT_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return -ECANCELED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) case XST_PM_MULT_USER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return -EUSERS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) case XST_PM_INTERNAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) case XST_PM_CONFLICT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) case XST_PM_INVALID_NODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static noinline int do_fw_call_fail(u64 arg0, u64 arg1, u64 arg2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) u32 *ret_payload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * PM function call wrapper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * Invoke do_fw_call_smc or do_fw_call_hvc, depending on the configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int (*do_fw_call)(u64, u64, u64, u32 *ret_payload) = do_fw_call_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * do_fw_call_smc() - Call system-level platform management layer (SMC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * @arg0: Argument 0 to SMC call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * @arg1: Argument 1 to SMC call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * @arg2: Argument 2 to SMC call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * @ret_payload: Returned value array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * Invoke platform management function via SMC call (no hypervisor present).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static noinline int do_fw_call_smc(u64 arg0, u64 arg1, u64 arg2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u32 *ret_payload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) arm_smccc_smc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (ret_payload) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) ret_payload[0] = lower_32_bits(res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) ret_payload[1] = upper_32_bits(res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) ret_payload[2] = lower_32_bits(res.a1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ret_payload[3] = upper_32_bits(res.a1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * do_fw_call_hvc() - Call system-level platform management layer (HVC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * @arg0: Argument 0 to HVC call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * @arg1: Argument 1 to HVC call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * @arg2: Argument 2 to HVC call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * @ret_payload: Returned value array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * Invoke platform management function via HVC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * HVC-based for communication through hypervisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * (no direct communication with ATF).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static noinline int do_fw_call_hvc(u64 arg0, u64 arg1, u64 arg2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u32 *ret_payload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) arm_smccc_hvc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (ret_payload) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ret_payload[0] = lower_32_bits(res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ret_payload[1] = upper_32_bits(res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) ret_payload[2] = lower_32_bits(res.a1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) ret_payload[3] = upper_32_bits(res.a1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * zynqmp_pm_feature() - Check weather given feature is supported or not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * @api_id: API ID to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static int zynqmp_pm_feature(u32 api_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) u32 ret_payload[PAYLOAD_ARG_CNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) u64 smc_arg[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct pm_api_feature_data *feature_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (!feature_check_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /* Check for existing entry in hash table for given api */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) hash_for_each_possible(pm_api_features_map, feature_data, hentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) api_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (feature_data->pm_api_id == api_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return feature_data->feature_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* Add new entry if not present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) feature_data = kmalloc(sizeof(*feature_data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (!feature_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) feature_data->pm_api_id = api_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) smc_arg[0] = PM_SIP_SVC | PM_FEATURE_CHECK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) smc_arg[1] = api_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) ret = do_fw_call(smc_arg[0], smc_arg[1], 0, ret_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) ret = ret_payload[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) feature_data->feature_status = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) hash_add(pm_api_features_map, &feature_data->hentry, api_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * caller function depending on the configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * @pm_api_id: Requested PM-API call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * @arg0: Argument 0 to requested PM-API call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * @arg1: Argument 1 to requested PM-API call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * @arg2: Argument 2 to requested PM-API call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * @arg3: Argument 3 to requested PM-API call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * @ret_payload: Returned value array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * Invoke platform management function for SMC or HVC call, depending on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * Following SMC Calling Convention (SMCCC) for SMC64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * Pm Function Identifier,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * PM_SIP_SVC + PM_API_ID =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * ((SMC_64) << FUNCID_CC_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * ((SIP_START) << FUNCID_OEN_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * ((PM_API_ID) & FUNCID_NUM_MASK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * PM_SIP_SVC - Registered ZynqMP SIP Service Call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * PM_API_ID - Platform Management API ID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) u32 arg2, u32 arg3, u32 *ret_payload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * Added SIP service call Function Identifier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * Make sure to stay in x0 register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) u64 smc_arg[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* Check if feature is supported or not */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ret = zynqmp_pm_feature(pm_api_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) smc_arg[0] = PM_SIP_SVC | pm_api_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) smc_arg[1] = ((u64)arg1 << 32) | arg0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) smc_arg[2] = ((u64)arg3 << 32) | arg2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return do_fw_call(smc_arg[0], smc_arg[1], smc_arg[2], ret_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static u32 pm_api_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static u32 pm_tz_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * zynqmp_pm_get_api_version() - Get version number of PMU PM firmware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * @version: Returned version value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) int zynqmp_pm_get_api_version(u32 *version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) u32 ret_payload[PAYLOAD_ARG_CNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (!version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /* Check is PM API version already verified */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (pm_api_version > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) *version = pm_api_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) ret = zynqmp_pm_invoke_fn(PM_GET_API_VERSION, 0, 0, 0, 0, ret_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) *version = ret_payload[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) EXPORT_SYMBOL_GPL(zynqmp_pm_get_api_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * zynqmp_pm_get_chipid - Get silicon ID registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * @idcode: IDCODE register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * @version: version register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * Return: Returns the status of the operation and the idcode and version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * registers in @idcode and @version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) u32 ret_payload[PAYLOAD_ARG_CNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (!idcode || !version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) *idcode = ret_payload[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) *version = ret_payload[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) EXPORT_SYMBOL_GPL(zynqmp_pm_get_chipid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * @version: Returned version value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static int zynqmp_pm_get_trustzone_version(u32 *version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) u32 ret_payload[PAYLOAD_ARG_CNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (!version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* Check is PM trustzone version already verified */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (pm_tz_version > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) *version = pm_tz_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ret = zynqmp_pm_invoke_fn(PM_GET_TRUSTZONE_VERSION, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 0, 0, ret_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) *version = ret_payload[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * get_set_conduit_method() - Choose SMC or HVC based communication
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * @np: Pointer to the device_node structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * Use SMC or HVC-based functions to communicate with EL2/EL3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * Return: Returns 0 on success or error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) static int get_set_conduit_method(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) const char *method;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (of_property_read_string(np, "method", &method)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) pr_warn("%s missing \"method\" property\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (!strcmp("hvc", method)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) do_fw_call = do_fw_call_hvc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) } else if (!strcmp("smc", method)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) do_fw_call = do_fw_call_smc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) pr_warn("%s Invalid \"method\" property: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) __func__, method);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * zynqmp_pm_query_data() - Get query data from firmware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * @qdata: Variable to the zynqmp_pm_query_data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * @out: Returned output value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, qdata.qid, qdata.arg1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) qdata.arg2, qdata.arg3, out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * For clock name query, all bytes in SMC response are clock name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * characters and return code is always success. For invalid clocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * clock name bytes would be zeros.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) EXPORT_SYMBOL_GPL(zynqmp_pm_query_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * zynqmp_pm_clock_enable() - Enable the clock for given id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * @clock_id: ID of the clock to be enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * This function is used by master to enable the clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * including peripherals and PLL clocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int zynqmp_pm_clock_enable(u32 clock_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) EXPORT_SYMBOL_GPL(zynqmp_pm_clock_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * zynqmp_pm_clock_disable() - Disable the clock for given id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * @clock_id: ID of the clock to be disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * This function is used by master to disable the clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * including peripherals and PLL clocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) int zynqmp_pm_clock_disable(u32 clock_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) EXPORT_SYMBOL_GPL(zynqmp_pm_clock_disable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * zynqmp_pm_clock_getstate() - Get the clock state for given id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * @clock_id: ID of the clock to be queried
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * @state: 1/0 (Enabled/Disabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * This function is used by master to get the state of clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * including peripherals and PLL clocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) u32 ret_payload[PAYLOAD_ARG_CNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, clock_id, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 0, 0, ret_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) *state = ret_payload[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getstate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * zynqmp_pm_clock_setdivider() - Set the clock divider for given id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * @clock_id: ID of the clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * @divider: divider value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * This function is used by master to set divider for any clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * to achieve desired rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, clock_id, divider,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setdivider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * zynqmp_pm_clock_getdivider() - Get the clock divider for given id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * @clock_id: ID of the clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * @divider: divider value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * This function is used by master to get divider values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * for any clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) u32 ret_payload[PAYLOAD_ARG_CNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, clock_id, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 0, 0, ret_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) *divider = ret_payload[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getdivider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * zynqmp_pm_clock_setrate() - Set the clock rate for given id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * @clock_id: ID of the clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * @rate: rate value in hz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * This function is used by master to set rate for any clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return zynqmp_pm_invoke_fn(PM_CLOCK_SETRATE, clock_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) lower_32_bits(rate),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) upper_32_bits(rate),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * zynqmp_pm_clock_getrate() - Get the clock rate for given id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * @clock_id: ID of the clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * @rate: rate value in hz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * This function is used by master to get rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * for any clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) u32 ret_payload[PAYLOAD_ARG_CNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETRATE, clock_id, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 0, 0, ret_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) *rate = ((u64)ret_payload[2] << 32) | ret_payload[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * zynqmp_pm_clock_setparent() - Set the clock parent for given id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * @clock_id: ID of the clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * @parent_id: parent id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * This function is used by master to set parent for any clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, clock_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) parent_id, 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setparent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * zynqmp_pm_clock_getparent() - Get the clock parent for given id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * @clock_id: ID of the clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * @parent_id: parent id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) * This function is used by master to get parent index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) * for any clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) u32 ret_payload[PAYLOAD_ARG_CNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, clock_id, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 0, 0, ret_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) *parent_id = ret_payload[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getparent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) * zynqmp_pm_set_pll_frac_mode() - PM API for set PLL mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) * @clk_id: PLL clock ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * @mode: PLL mode (PLL_MODE_FRAC/PLL_MODE_INT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * This function sets PLL mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) int zynqmp_pm_set_pll_frac_mode(u32 clk_id, u32 mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) clk_id, mode, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * zynqmp_pm_get_pll_frac_mode() - PM API for get PLL mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * @clk_id: PLL clock ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * @mode: PLL mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * This function return current PLL mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) int zynqmp_pm_get_pll_frac_mode(u32 clk_id, u32 *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) clk_id, 0, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * zynqmp_pm_set_pll_frac_data() - PM API for setting pll fraction data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * @clk_id: PLL clock ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * @data: fraction data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * This function sets fraction data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * It is valid for fraction mode only.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) int zynqmp_pm_set_pll_frac_data(u32 clk_id, u32 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) clk_id, data, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * zynqmp_pm_get_pll_frac_data() - PM API for getting pll fraction data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * @clk_id: PLL clock ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * @data: fraction data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) * This function returns fraction data value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) clk_id, 0, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * zynqmp_pm_set_sd_tapdelay() - Set tap delay for the SD device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * @node_id Node ID of the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * @type Type of tap delay to set (input/output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * @value Value to set fot the tap delay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) * This function sets input/output tap delay for the SD device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * @return Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) type, value, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) * zynqmp_pm_sd_dll_reset() - Reset DLL logic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) * @node_id Node ID of the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * @type Reset type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * This function resets DLL logic for the SD device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) * @return Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SD_DLL_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) type, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) * zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * @index GGS register index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * @value Register value to be written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) * This function writes value to GGS register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * @return Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) int zynqmp_pm_write_ggs(u32 index, u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_GGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) index, value, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * zynqmp_pm_write_ggs() - PM API for reading global general storage (ggs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * @index GGS register index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * @value Register value to be written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * This function returns GGS register value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * @return Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) int zynqmp_pm_read_ggs(u32 index, u32 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_GGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) index, 0, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * zynqmp_pm_write_pggs() - PM API for writing persistent global general
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * storage (pggs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * @index PGGS register index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * @value Register value to be written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * This function writes value to PGGS register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * @return Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) int zynqmp_pm_write_pggs(u32 index, u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_PGGS, index, value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * zynqmp_pm_write_pggs() - PM API for reading persistent global general
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * storage (pggs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * @index PGGS register index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) * @value Register value to be written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) * This function returns PGGS register value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) * @return Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) int zynqmp_pm_read_pggs(u32 index, u32 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_PGGS, index, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * @value Status value to be written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * This function sets healthy bit value to indicate boot health status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * to firmware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * @return Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) int zynqmp_pm_set_boot_health_status(u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_BOOT_HEALTH_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) value, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) * @reset: Reset to be configured
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) * @assert_flag: Flag stating should reset be asserted (1) or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) * released (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) const enum zynqmp_pm_reset_action assert_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) * zynqmp_pm_reset_get_status - Get status of the reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * @reset: Reset whose status should be returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * @status: Returned status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) u32 ret_payload[PAYLOAD_ARG_CNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (!status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 0, 0, ret_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) *status = ret_payload[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) * zynqmp_pm_fpga_load - Perform the fpga load
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * @address: Address to write to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) * @size: pl bitstream size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) * @flags: Bitstream type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) * -XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) * -XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) * This function provides access to pmufw. To transfer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) * the required bitstream into PL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) upper_32_bits(address), size, flags, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) * zynqmp_pm_fpga_get_status - Read value from PCAP status register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * @value: Value to read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * This function provides access to the pmufw to get the PCAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) int zynqmp_pm_fpga_get_status(u32 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) u32 ret_payload[PAYLOAD_ARG_CNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (!value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) *value = ret_payload[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) * master has initialized its own power management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * This API function is to be used for notify the power management controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) * about the completed power management initialization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) int zynqmp_pm_init_finalize(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) EXPORT_SYMBOL_GPL(zynqmp_pm_init_finalize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) * zynqmp_pm_set_suspend_mode() - Set system suspend mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) * @mode: Mode to set for system suspend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * This API function is used to set mode of system suspend.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) int zynqmp_pm_set_suspend_mode(u32 mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) * zynqmp_pm_request_node() - Request a node with specific capabilities
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) * @node: Node ID of the slave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * @capabilities: Requested capabilities of the slave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * @qos: Quality of service (not supported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * @ack: Flag to specify whether acknowledge is requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * This function is used by master to request particular node from firmware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * Every master must request node before using it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) const u32 qos, const enum zynqmp_pm_request_ack ack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) qos, ack, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) EXPORT_SYMBOL_GPL(zynqmp_pm_request_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) * zynqmp_pm_release_node() - Release a node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) * @node: Node ID of the slave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) * This function is used by master to inform firmware that master
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) * has released node. Once released, master must not use that node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) * without re-request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) int zynqmp_pm_release_node(const u32 node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) EXPORT_SYMBOL_GPL(zynqmp_pm_release_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) * @node: Node ID of the slave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) * @capabilities: Requested capabilities of the slave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) * @qos: Quality of service (not supported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) * @ack: Flag to specify whether acknowledge is requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) * This API function is to be used for slaves a PU already has requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * to change its capabilities.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) const u32 qos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) const enum zynqmp_pm_request_ack ack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) qos, ack, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) * zynqmp_pm_aes - Access AES hardware to encrypt/decrypt the data using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * AES-GCM core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * @address: Address of the AesParams structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) * @out: Returned output value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) * Return: Returns status, either success or error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) int zynqmp_pm_aes_engine(const u64 address, u32 *out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) u32 ret_payload[PAYLOAD_ARG_CNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (!out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, upper_32_bits(address),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) lower_32_bits(address),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) 0, 0, ret_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) *out = ret_payload[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) * @type: Shutdown or restart? 0 for shutdown, 1 for restart
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * @subtype: Specifies which system should be restarted or shut down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) * Return: Returns status, either success or error+reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) * @subtype: Shutdown subtype
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) * @name: Matching string for scope argument
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) * This struct encapsulates mapping between shutdown scope ID and string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) struct zynqmp_pm_shutdown_scope {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) const enum zynqmp_pm_shutdown_subtype subtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) .name = "subsystem",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) [ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) .name = "ps_only",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) .name = "system",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) static struct zynqmp_pm_shutdown_scope *selected_scope =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) &shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) * @scope_string: Shutdown scope string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) * Return: Return pointer to matching shutdown scope struct from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) * array of available options in system if string is valid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) * otherwise returns NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) static struct zynqmp_pm_shutdown_scope*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) zynqmp_pm_is_shutdown_scope_valid(const char *scope_string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (sysfs_streq(scope_string, shutdown_scopes[count].name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) return &shutdown_scopes[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) static ssize_t shutdown_scope_show(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (&shutdown_scopes[i] == selected_scope) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) strcat(buf, "[");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) strcat(buf, shutdown_scopes[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) strcat(buf, "]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) strcat(buf, shutdown_scopes[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) strcat(buf, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) strcat(buf, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) return strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) static ssize_t shutdown_scope_store(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) struct zynqmp_pm_shutdown_scope *scope;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) scope = zynqmp_pm_is_shutdown_scope_valid(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (!scope)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) scope->subtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) pr_err("unable to set shutdown scope %s\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) selected_scope = scope;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) static DEVICE_ATTR_RW(shutdown_scope);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) static ssize_t health_status_store(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) unsigned int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) ret = kstrtouint(buf, 10, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) ret = zynqmp_pm_set_boot_health_status(value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) dev_err(device, "unable to set healthy bit value to %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) static DEVICE_ATTR_WO(health_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) static ssize_t ggs_show(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) u32 ret_payload[PAYLOAD_ARG_CNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) ret = zynqmp_pm_read_ggs(reg, ret_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) return sprintf(buf, "0x%x\n", ret_payload[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) static ssize_t ggs_store(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) const char *buf, size_t count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) long value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (reg >= GSS_NUM_REGS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) ret = kstrtol(buf, 16, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) count = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) ret = zynqmp_pm_write_ggs(reg, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) count = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) /* GGS register show functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) #define GGS0_SHOW(N) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) ssize_t ggs##N##_show(struct device *device, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) return ggs_show(device, attr, buf, N); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) static GGS0_SHOW(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) static GGS0_SHOW(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) static GGS0_SHOW(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) static GGS0_SHOW(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) /* GGS register store function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) #define GGS0_STORE(N) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) ssize_t ggs##N##_store(struct device *device, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) const char *buf, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) size_t count) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) return ggs_store(device, attr, buf, count, N); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) static GGS0_STORE(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) static GGS0_STORE(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) static GGS0_STORE(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) static GGS0_STORE(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) static ssize_t pggs_show(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) u32 ret_payload[PAYLOAD_ARG_CNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) ret = zynqmp_pm_read_pggs(reg, ret_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return sprintf(buf, "0x%x\n", ret_payload[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) static ssize_t pggs_store(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) const char *buf, size_t count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) long value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) if (reg >= GSS_NUM_REGS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) ret = kstrtol(buf, 16, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) count = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) ret = zynqmp_pm_write_pggs(reg, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) count = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) #define PGGS0_SHOW(N) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) ssize_t pggs##N##_show(struct device *device, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) return pggs_show(device, attr, buf, N); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) #define PGGS0_STORE(N) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) ssize_t pggs##N##_store(struct device *device, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) const char *buf, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) size_t count) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) return pggs_store(device, attr, buf, count, N); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) /* PGGS register show functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) static PGGS0_SHOW(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) static PGGS0_SHOW(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) static PGGS0_SHOW(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) static PGGS0_SHOW(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) /* PGGS register store functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) static PGGS0_STORE(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) static PGGS0_STORE(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) static PGGS0_STORE(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) static PGGS0_STORE(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) /* GGS register attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) static DEVICE_ATTR_RW(ggs0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) static DEVICE_ATTR_RW(ggs1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) static DEVICE_ATTR_RW(ggs2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) static DEVICE_ATTR_RW(ggs3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) /* PGGS register attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) static DEVICE_ATTR_RW(pggs0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) static DEVICE_ATTR_RW(pggs1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) static DEVICE_ATTR_RW(pggs2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) static DEVICE_ATTR_RW(pggs3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) static struct attribute *zynqmp_firmware_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) &dev_attr_ggs0.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) &dev_attr_ggs1.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) &dev_attr_ggs2.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) &dev_attr_ggs3.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) &dev_attr_pggs0.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) &dev_attr_pggs1.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) &dev_attr_pggs2.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) &dev_attr_pggs3.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) &dev_attr_shutdown_scope.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) &dev_attr_health_status.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) ATTRIBUTE_GROUPS(zynqmp_firmware);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) static int zynqmp_firmware_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) np = of_find_compatible_node(NULL, NULL, "xlnx,zynqmp");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) if (!np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) np = of_find_compatible_node(NULL, NULL, "xlnx,versal");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) if (!np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) feature_check_enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) ret = get_set_conduit_method(dev->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) /* Check PM API version number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) zynqmp_pm_get_api_version(&pm_api_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) if (pm_api_version < ZYNQMP_PM_VERSION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) pm_api_version >> 16, pm_api_version & 0xFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) pr_info("%s Platform Management API v%d.%d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) pm_api_version >> 16, pm_api_version & 0xFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) /* Check trustzone version number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) ret = zynqmp_pm_get_trustzone_version(&pm_tz_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) panic("Legacy trustzone found without version support\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) if (pm_tz_version < ZYNQMP_TZ_VERSION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) pm_tz_version >> 16, pm_tz_version & 0xFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) pr_info("%s Trustzone version v%d.%d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) pm_tz_version >> 16, pm_tz_version & 0xFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) ARRAY_SIZE(firmware_devs), NULL, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) zynqmp_pm_api_debugfs_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) return of_platform_populate(dev->of_node, NULL, NULL, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) static int zynqmp_firmware_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) struct pm_api_feature_data *feature_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) struct hlist_node *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) mfd_remove_devices(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) zynqmp_pm_api_debugfs_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) hash_for_each_safe(pm_api_features_map, i, tmp, feature_data, hentry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) hash_del(&feature_data->hentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) kfree(feature_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) static const struct of_device_id zynqmp_firmware_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) {.compatible = "xlnx,zynqmp-firmware"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) {.compatible = "xlnx,versal-firmware"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) static struct platform_driver zynqmp_firmware_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) .name = "zynqmp_firmware",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) .of_match_table = zynqmp_firmware_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) .dev_groups = zynqmp_firmware_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) .probe = zynqmp_firmware_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) .remove = zynqmp_firmware_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) module_platform_driver(zynqmp_firmware_driver);