176582671SRajan Vaja // SPDX-License-Identifier: GPL-2.0 276582671SRajan Vaja /* 376582671SRajan Vaja * Xilinx Zynq MPSoC Firmware layer 476582671SRajan Vaja * 5acd6510dSTanmay Shah * Copyright (C) 2014-2022 Xilinx, Inc. 676582671SRajan Vaja * 776582671SRajan Vaja * Michal Simek <michal.simek@xilinx.com> 876582671SRajan Vaja * Davorin Mista <davorin.mista@aggios.com> 976582671SRajan Vaja * Jolly Shah <jollys@xilinx.com> 1076582671SRajan Vaja * Rajan Vaja <rajanv@xilinx.com> 1176582671SRajan Vaja */ 1276582671SRajan Vaja 1376582671SRajan Vaja #include <linux/arm-smccc.h> 1476582671SRajan Vaja #include <linux/compiler.h> 1576582671SRajan Vaja #include <linux/device.h> 1676582671SRajan Vaja #include <linux/init.h> 17e23d9c6dSJolly Shah #include <linux/mfd/core.h> 1876582671SRajan Vaja #include <linux/module.h> 1976582671SRajan Vaja #include <linux/of.h> 2076582671SRajan Vaja #include <linux/of_platform.h> 2176582671SRajan Vaja #include <linux/slab.h> 2276582671SRajan Vaja #include <linux/uaccess.h> 23acfdd185SAmit Sunil Dhamne #include <linux/hashtable.h> 2476582671SRajan Vaja 2576582671SRajan Vaja #include <linux/firmware/xlnx-zynqmp.h> 26a515814eSAbhyuday Godhasara #include <linux/firmware/xlnx-event-manager.h> 27b3217252SRajan Vaja #include "zynqmp-debug.h" 2876582671SRajan Vaja 29acfdd185SAmit Sunil Dhamne /* Max HashMap Order for PM API feature check (1<<7 = 128) */ 30acfdd185SAmit Sunil Dhamne #define PM_API_FEATURE_CHECK_MAX_ORDER 7 31acfdd185SAmit Sunil Dhamne 3223c64d76SPiyush Mehta /* CRL registers and bitfields */ 3323c64d76SPiyush Mehta #define CRL_APB_BASE 0xFF5E0000U 3423c64d76SPiyush Mehta /* BOOT_PIN_CTRL- Used to control the mode pins after boot */ 3523c64d76SPiyush Mehta #define CRL_APB_BOOT_PIN_CTRL (CRL_APB_BASE + (0x250U)) 3623c64d76SPiyush Mehta /* BOOT_PIN_CTRL_MASK- out_val[11:8], out_en[3:0] */ 3723c64d76SPiyush Mehta #define CRL_APB_BOOTPIN_CTRL_MASK 0xF0FU 3823c64d76SPiyush Mehta 39f918cfc0SRonak Jain /* IOCTL/QUERY feature payload size */ 40f918cfc0SRonak Jain #define FEATURE_PAYLOAD_SIZE 2 41f918cfc0SRonak Jain 42f918cfc0SRonak Jain /* Firmware feature check version mask */ 43f918cfc0SRonak Jain #define FIRMWARE_VERSION_MASK GENMASK(15, 0) 44f918cfc0SRonak Jain 45461011b1SRavi Patel static bool feature_check_enabled; 4669fe24d1SZou Wei static DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER); 47f918cfc0SRonak Jain static u32 ioctl_features[FEATURE_PAYLOAD_SIZE]; 48f918cfc0SRonak Jain static u32 query_features[FEATURE_PAYLOAD_SIZE]; 49acfdd185SAmit Sunil Dhamne 50a515814eSAbhyuday Godhasara static struct platform_device *em_dev; 51a515814eSAbhyuday Godhasara 52acfdd185SAmit Sunil Dhamne /** 532c5d8f7cSRonak Jain * struct zynqmp_devinfo - Structure for Zynqmp device instance 542c5d8f7cSRonak Jain * @dev: Device Pointer 552c5d8f7cSRonak Jain * @feature_conf_id: Feature conf id 562c5d8f7cSRonak Jain */ 572c5d8f7cSRonak Jain struct zynqmp_devinfo { 582c5d8f7cSRonak Jain struct device *dev; 592c5d8f7cSRonak Jain u32 feature_conf_id; 602c5d8f7cSRonak Jain }; 612c5d8f7cSRonak Jain 622c5d8f7cSRonak Jain /** 63acfdd185SAmit Sunil Dhamne * struct pm_api_feature_data - PM API Feature data 64acfdd185SAmit Sunil Dhamne * @pm_api_id: PM API Id, used as key to index into hashmap 65acfdd185SAmit Sunil Dhamne * @feature_status: status of PM API feature: valid, invalid 66acfdd185SAmit Sunil Dhamne * @hentry: hlist_node that hooks this entry into hashtable 67acfdd185SAmit Sunil Dhamne */ 68acfdd185SAmit Sunil Dhamne struct pm_api_feature_data { 69acfdd185SAmit Sunil Dhamne u32 pm_api_id; 70acfdd185SAmit Sunil Dhamne int feature_status; 71acfdd185SAmit Sunil Dhamne struct hlist_node hentry; 72acfdd185SAmit Sunil Dhamne }; 73461011b1SRavi Patel 74e23d9c6dSJolly Shah static const struct mfd_cell firmware_devs[] = { 75e23d9c6dSJolly Shah { 76e23d9c6dSJolly Shah .name = "zynqmp_power_controller", 77e23d9c6dSJolly Shah }, 78e23d9c6dSJolly Shah }; 79e23d9c6dSJolly Shah 8076582671SRajan Vaja /** 8176582671SRajan Vaja * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes 8276582671SRajan Vaja * @ret_status: PMUFW return code 8376582671SRajan Vaja * 8476582671SRajan Vaja * Return: corresponding Linux error code 8576582671SRajan Vaja */ 8676582671SRajan Vaja static int zynqmp_pm_ret_code(u32 ret_status) 8776582671SRajan Vaja { 8876582671SRajan Vaja switch (ret_status) { 8976582671SRajan Vaja case XST_PM_SUCCESS: 9076582671SRajan Vaja case XST_PM_DOUBLE_REQ: 9176582671SRajan Vaja return 0; 92461011b1SRavi Patel case XST_PM_NO_FEATURE: 93461011b1SRavi Patel return -ENOTSUPP; 9476582671SRajan Vaja case XST_PM_NO_ACCESS: 9576582671SRajan Vaja return -EACCES; 9676582671SRajan Vaja case XST_PM_ABORT_SUSPEND: 9776582671SRajan Vaja return -ECANCELED; 98df2a4d94SRajan Vaja case XST_PM_MULT_USER: 99df2a4d94SRajan Vaja return -EUSERS; 10076582671SRajan Vaja case XST_PM_INTERNAL: 10176582671SRajan Vaja case XST_PM_CONFLICT: 10276582671SRajan Vaja case XST_PM_INVALID_NODE: 10376582671SRajan Vaja default: 10476582671SRajan Vaja return -EINVAL; 10576582671SRajan Vaja } 10676582671SRajan Vaja } 10776582671SRajan Vaja 10876582671SRajan Vaja static noinline int do_fw_call_fail(u64 arg0, u64 arg1, u64 arg2, 10976582671SRajan Vaja u32 *ret_payload) 11076582671SRajan Vaja { 11176582671SRajan Vaja return -ENODEV; 11276582671SRajan Vaja } 11376582671SRajan Vaja 11476582671SRajan Vaja /* 11576582671SRajan Vaja * PM function call wrapper 11676582671SRajan Vaja * Invoke do_fw_call_smc or do_fw_call_hvc, depending on the configuration 11776582671SRajan Vaja */ 11876582671SRajan Vaja static int (*do_fw_call)(u64, u64, u64, u32 *ret_payload) = do_fw_call_fail; 11976582671SRajan Vaja 12076582671SRajan Vaja /** 12176582671SRajan Vaja * do_fw_call_smc() - Call system-level platform management layer (SMC) 12276582671SRajan Vaja * @arg0: Argument 0 to SMC call 12376582671SRajan Vaja * @arg1: Argument 1 to SMC call 12476582671SRajan Vaja * @arg2: Argument 2 to SMC call 12576582671SRajan Vaja * @ret_payload: Returned value array 12676582671SRajan Vaja * 12776582671SRajan Vaja * Invoke platform management function via SMC call (no hypervisor present). 12876582671SRajan Vaja * 12976582671SRajan Vaja * Return: Returns status, either success or error+reason 13076582671SRajan Vaja */ 13176582671SRajan Vaja static noinline int do_fw_call_smc(u64 arg0, u64 arg1, u64 arg2, 13276582671SRajan Vaja u32 *ret_payload) 13376582671SRajan Vaja { 13476582671SRajan Vaja struct arm_smccc_res res; 13576582671SRajan Vaja 13676582671SRajan Vaja arm_smccc_smc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res); 13776582671SRajan Vaja 13876582671SRajan Vaja if (ret_payload) { 13976582671SRajan Vaja ret_payload[0] = lower_32_bits(res.a0); 14076582671SRajan Vaja ret_payload[1] = upper_32_bits(res.a0); 14176582671SRajan Vaja ret_payload[2] = lower_32_bits(res.a1); 14276582671SRajan Vaja ret_payload[3] = upper_32_bits(res.a1); 14376582671SRajan Vaja } 14476582671SRajan Vaja 14576582671SRajan Vaja return zynqmp_pm_ret_code((enum pm_ret_status)res.a0); 14676582671SRajan Vaja } 14776582671SRajan Vaja 14876582671SRajan Vaja /** 14976582671SRajan Vaja * do_fw_call_hvc() - Call system-level platform management layer (HVC) 15076582671SRajan Vaja * @arg0: Argument 0 to HVC call 15176582671SRajan Vaja * @arg1: Argument 1 to HVC call 15276582671SRajan Vaja * @arg2: Argument 2 to HVC call 15376582671SRajan Vaja * @ret_payload: Returned value array 15476582671SRajan Vaja * 15576582671SRajan Vaja * Invoke platform management function via HVC 15676582671SRajan Vaja * HVC-based for communication through hypervisor 15776582671SRajan Vaja * (no direct communication with ATF). 15876582671SRajan Vaja * 15976582671SRajan Vaja * Return: Returns status, either success or error+reason 16076582671SRajan Vaja */ 16176582671SRajan Vaja static noinline int do_fw_call_hvc(u64 arg0, u64 arg1, u64 arg2, 16276582671SRajan Vaja u32 *ret_payload) 16376582671SRajan Vaja { 16476582671SRajan Vaja struct arm_smccc_res res; 16576582671SRajan Vaja 16676582671SRajan Vaja arm_smccc_hvc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res); 16776582671SRajan Vaja 16876582671SRajan Vaja if (ret_payload) { 16976582671SRajan Vaja ret_payload[0] = lower_32_bits(res.a0); 17076582671SRajan Vaja ret_payload[1] = upper_32_bits(res.a0); 17176582671SRajan Vaja ret_payload[2] = lower_32_bits(res.a1); 17276582671SRajan Vaja ret_payload[3] = upper_32_bits(res.a1); 17376582671SRajan Vaja } 17476582671SRajan Vaja 17576582671SRajan Vaja return zynqmp_pm_ret_code((enum pm_ret_status)res.a0); 17676582671SRajan Vaja } 17776582671SRajan Vaja 178218f01a8SRonak Jain static int __do_feature_check_call(const u32 api_id, u32 *ret_payload) 17994ae7f22SRonak Jain { 18094ae7f22SRonak Jain int ret; 18194ae7f22SRonak Jain u64 smc_arg[2]; 18294ae7f22SRonak Jain 18394ae7f22SRonak Jain smc_arg[0] = PM_SIP_SVC | PM_FEATURE_CHECK; 18494ae7f22SRonak Jain smc_arg[1] = api_id; 18594ae7f22SRonak Jain 18694ae7f22SRonak Jain ret = do_fw_call(smc_arg[0], smc_arg[1], 0, ret_payload); 18794ae7f22SRonak Jain if (ret) 18894ae7f22SRonak Jain ret = -EOPNOTSUPP; 18994ae7f22SRonak Jain else 19094ae7f22SRonak Jain ret = ret_payload[1]; 19194ae7f22SRonak Jain 19294ae7f22SRonak Jain return ret; 19394ae7f22SRonak Jain } 19494ae7f22SRonak Jain 195218f01a8SRonak Jain static int do_feature_check_call(const u32 api_id) 196461011b1SRavi Patel { 197461011b1SRavi Patel int ret; 198461011b1SRavi Patel u32 ret_payload[PAYLOAD_ARG_CNT]; 199acfdd185SAmit Sunil Dhamne struct pm_api_feature_data *feature_data; 200461011b1SRavi Patel 201acfdd185SAmit Sunil Dhamne /* Check for existing entry in hash table for given api */ 202acfdd185SAmit Sunil Dhamne hash_for_each_possible(pm_api_features_map, feature_data, hentry, 203acfdd185SAmit Sunil Dhamne api_id) { 204acfdd185SAmit Sunil Dhamne if (feature_data->pm_api_id == api_id) 205acfdd185SAmit Sunil Dhamne return feature_data->feature_status; 206acfdd185SAmit Sunil Dhamne } 207f3217d6fSArnd Bergmann 208acfdd185SAmit Sunil Dhamne /* Add new entry if not present */ 209acfdd185SAmit Sunil Dhamne feature_data = kmalloc(sizeof(*feature_data), GFP_KERNEL); 210acfdd185SAmit Sunil Dhamne if (!feature_data) 211acfdd185SAmit Sunil Dhamne return -ENOMEM; 212461011b1SRavi Patel 213acfdd185SAmit Sunil Dhamne feature_data->pm_api_id = api_id; 214218f01a8SRonak Jain ret = __do_feature_check_call(api_id, ret_payload); 215461011b1SRavi Patel 216acfdd185SAmit Sunil Dhamne feature_data->feature_status = ret; 217acfdd185SAmit Sunil Dhamne hash_add(pm_api_features_map, &feature_data->hentry, api_id); 218461011b1SRavi Patel 219f918cfc0SRonak Jain if (api_id == PM_IOCTL) 220f918cfc0SRonak Jain /* Store supported IOCTL IDs mask */ 221f918cfc0SRonak Jain memcpy(ioctl_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4); 222f918cfc0SRonak Jain else if (api_id == PM_QUERY_DATA) 223f918cfc0SRonak Jain /* Store supported QUERY IDs mask */ 224f918cfc0SRonak Jain memcpy(query_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4); 225f918cfc0SRonak Jain 226acfdd185SAmit Sunil Dhamne return ret; 227461011b1SRavi Patel } 228f4d77525SAbhyuday Godhasara EXPORT_SYMBOL_GPL(zynqmp_pm_feature); 229461011b1SRavi Patel 230461011b1SRavi Patel /** 231218f01a8SRonak Jain * zynqmp_pm_feature() - Check whether given feature is supported or not and 232218f01a8SRonak Jain * store supported IOCTL/QUERY ID mask 233218f01a8SRonak Jain * @api_id: API ID to check 234218f01a8SRonak Jain * 235218f01a8SRonak Jain * Return: Returns status, either success or error+reason 236218f01a8SRonak Jain */ 237218f01a8SRonak Jain int zynqmp_pm_feature(const u32 api_id) 238218f01a8SRonak Jain { 239218f01a8SRonak Jain int ret; 240218f01a8SRonak Jain 241218f01a8SRonak Jain if (!feature_check_enabled) 242218f01a8SRonak Jain return 0; 243218f01a8SRonak Jain 244218f01a8SRonak Jain ret = do_feature_check_call(api_id); 245218f01a8SRonak Jain 246218f01a8SRonak Jain return ret; 247218f01a8SRonak Jain } 248218f01a8SRonak Jain 249218f01a8SRonak Jain /** 250f918cfc0SRonak Jain * zynqmp_pm_is_function_supported() - Check whether given IOCTL/QUERY function 251f918cfc0SRonak Jain * is supported or not 252f918cfc0SRonak Jain * @api_id: PM_IOCTL or PM_QUERY_DATA 253f918cfc0SRonak Jain * @id: IOCTL or QUERY function IDs 254f918cfc0SRonak Jain * 255f918cfc0SRonak Jain * Return: Returns status, either success or error+reason 256f918cfc0SRonak Jain */ 257f918cfc0SRonak Jain int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id) 258f918cfc0SRonak Jain { 259f918cfc0SRonak Jain int ret; 260f918cfc0SRonak Jain u32 *bit_mask; 261f918cfc0SRonak Jain 262f918cfc0SRonak Jain /* Input arguments validation */ 263f918cfc0SRonak Jain if (id >= 64 || (api_id != PM_IOCTL && api_id != PM_QUERY_DATA)) 264f918cfc0SRonak Jain return -EINVAL; 265f918cfc0SRonak Jain 266f918cfc0SRonak Jain /* Check feature check API version */ 267218f01a8SRonak Jain ret = do_feature_check_call(PM_FEATURE_CHECK); 268f918cfc0SRonak Jain if (ret < 0) 269f918cfc0SRonak Jain return ret; 270f918cfc0SRonak Jain 271f918cfc0SRonak Jain /* Check if feature check version 2 is supported or not */ 272f918cfc0SRonak Jain if ((ret & FIRMWARE_VERSION_MASK) == PM_API_VERSION_2) { 273f918cfc0SRonak Jain /* 274f918cfc0SRonak Jain * Call feature check for IOCTL/QUERY API to get IOCTL ID or 275f918cfc0SRonak Jain * QUERY ID feature status. 276f918cfc0SRonak Jain */ 277218f01a8SRonak Jain ret = do_feature_check_call(api_id); 278f918cfc0SRonak Jain if (ret < 0) 279f918cfc0SRonak Jain return ret; 280f918cfc0SRonak Jain 281f918cfc0SRonak Jain bit_mask = (api_id == PM_IOCTL) ? ioctl_features : query_features; 282f918cfc0SRonak Jain 283f918cfc0SRonak Jain if ((bit_mask[(id / 32)] & BIT((id % 32))) == 0U) 284f918cfc0SRonak Jain return -EOPNOTSUPP; 285f918cfc0SRonak Jain } else { 286f918cfc0SRonak Jain return -ENODATA; 287f918cfc0SRonak Jain } 288f918cfc0SRonak Jain 289f918cfc0SRonak Jain return 0; 290f918cfc0SRonak Jain } 291f918cfc0SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_is_function_supported); 292f918cfc0SRonak Jain 293f918cfc0SRonak Jain /** 29476582671SRajan Vaja * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer 29576582671SRajan Vaja * caller function depending on the configuration 29676582671SRajan Vaja * @pm_api_id: Requested PM-API call 29776582671SRajan Vaja * @arg0: Argument 0 to requested PM-API call 29876582671SRajan Vaja * @arg1: Argument 1 to requested PM-API call 29976582671SRajan Vaja * @arg2: Argument 2 to requested PM-API call 30076582671SRajan Vaja * @arg3: Argument 3 to requested PM-API call 30176582671SRajan Vaja * @ret_payload: Returned value array 30276582671SRajan Vaja * 30376582671SRajan Vaja * Invoke platform management function for SMC or HVC call, depending on 30476582671SRajan Vaja * configuration. 30576582671SRajan Vaja * Following SMC Calling Convention (SMCCC) for SMC64: 30676582671SRajan Vaja * Pm Function Identifier, 30776582671SRajan Vaja * PM_SIP_SVC + PM_API_ID = 30876582671SRajan Vaja * ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) 30976582671SRajan Vaja * ((SMC_64) << FUNCID_CC_SHIFT) 31076582671SRajan Vaja * ((SIP_START) << FUNCID_OEN_SHIFT) 31176582671SRajan Vaja * ((PM_API_ID) & FUNCID_NUM_MASK)) 31276582671SRajan Vaja * 31376582671SRajan Vaja * PM_SIP_SVC - Registered ZynqMP SIP Service Call. 31476582671SRajan Vaja * PM_API_ID - Platform Management API ID. 31576582671SRajan Vaja * 31676582671SRajan Vaja * Return: Returns status, either success or error+reason 31776582671SRajan Vaja */ 31876582671SRajan Vaja int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1, 31976582671SRajan Vaja u32 arg2, u32 arg3, u32 *ret_payload) 32076582671SRajan Vaja { 32176582671SRajan Vaja /* 32276582671SRajan Vaja * Added SIP service call Function Identifier 32376582671SRajan Vaja * Make sure to stay in x0 register 32476582671SRajan Vaja */ 32576582671SRajan Vaja u64 smc_arg[4]; 326acfdd185SAmit Sunil Dhamne int ret; 32776582671SRajan Vaja 328acfdd185SAmit Sunil Dhamne /* Check if feature is supported or not */ 329acfdd185SAmit Sunil Dhamne ret = zynqmp_pm_feature(pm_api_id); 330acfdd185SAmit Sunil Dhamne if (ret < 0) 331acfdd185SAmit Sunil Dhamne return ret; 332461011b1SRavi Patel 33376582671SRajan Vaja smc_arg[0] = PM_SIP_SVC | pm_api_id; 33476582671SRajan Vaja smc_arg[1] = ((u64)arg1 << 32) | arg0; 33576582671SRajan Vaja smc_arg[2] = ((u64)arg3 << 32) | arg2; 33676582671SRajan Vaja 33776582671SRajan Vaja return do_fw_call(smc_arg[0], smc_arg[1], smc_arg[2], ret_payload); 33876582671SRajan Vaja } 33976582671SRajan Vaja 34076582671SRajan Vaja static u32 pm_api_version; 34176582671SRajan Vaja static u32 pm_tz_version; 34276582671SRajan Vaja 343acd6510dSTanmay Shah int zynqmp_pm_register_sgi(u32 sgi_num, u32 reset) 344acd6510dSTanmay Shah { 345acd6510dSTanmay Shah int ret; 346acd6510dSTanmay Shah 347acd6510dSTanmay Shah ret = zynqmp_pm_invoke_fn(TF_A_PM_REGISTER_SGI, sgi_num, reset, 0, 0, 348acd6510dSTanmay Shah NULL); 349acd6510dSTanmay Shah if (!ret) 350acd6510dSTanmay Shah return ret; 351acd6510dSTanmay Shah 352acd6510dSTanmay Shah /* try old implementation as fallback strategy if above fails */ 353acd6510dSTanmay Shah return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_REGISTER_SGI, sgi_num, 354acd6510dSTanmay Shah reset, NULL); 355acd6510dSTanmay Shah } 356acd6510dSTanmay Shah 35776582671SRajan Vaja /** 35876582671SRajan Vaja * zynqmp_pm_get_api_version() - Get version number of PMU PM firmware 35976582671SRajan Vaja * @version: Returned version value 36076582671SRajan Vaja * 36176582671SRajan Vaja * Return: Returns status, either success or error+reason 36276582671SRajan Vaja */ 363b9b3a8beSRajan Vaja int zynqmp_pm_get_api_version(u32 *version) 36476582671SRajan Vaja { 36576582671SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 36676582671SRajan Vaja int ret; 36776582671SRajan Vaja 36876582671SRajan Vaja if (!version) 36976582671SRajan Vaja return -EINVAL; 37076582671SRajan Vaja 37176582671SRajan Vaja /* Check is PM API version already verified */ 37276582671SRajan Vaja if (pm_api_version > 0) { 37376582671SRajan Vaja *version = pm_api_version; 37476582671SRajan Vaja return 0; 37576582671SRajan Vaja } 37676582671SRajan Vaja ret = zynqmp_pm_invoke_fn(PM_GET_API_VERSION, 0, 0, 0, 0, ret_payload); 37776582671SRajan Vaja *version = ret_payload[1]; 37876582671SRajan Vaja 37976582671SRajan Vaja return ret; 38076582671SRajan Vaja } 381b9b3a8beSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_api_version); 38276582671SRajan Vaja 38376582671SRajan Vaja /** 384fe6f42cfSNava kishore Manne * zynqmp_pm_get_chipid - Get silicon ID registers 385fe6f42cfSNava kishore Manne * @idcode: IDCODE register 386fe6f42cfSNava kishore Manne * @version: version register 387fe6f42cfSNava kishore Manne * 388fe6f42cfSNava kishore Manne * Return: Returns the status of the operation and the idcode and version 389fe6f42cfSNava kishore Manne * registers in @idcode and @version. 390fe6f42cfSNava kishore Manne */ 39121cd93baSRajan Vaja int zynqmp_pm_get_chipid(u32 *idcode, u32 *version) 392fe6f42cfSNava kishore Manne { 393fe6f42cfSNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT]; 394fe6f42cfSNava kishore Manne int ret; 395fe6f42cfSNava kishore Manne 396fe6f42cfSNava kishore Manne if (!idcode || !version) 397fe6f42cfSNava kishore Manne return -EINVAL; 398fe6f42cfSNava kishore Manne 399fe6f42cfSNava kishore Manne ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload); 400fe6f42cfSNava kishore Manne *idcode = ret_payload[1]; 401fe6f42cfSNava kishore Manne *version = ret_payload[2]; 402fe6f42cfSNava kishore Manne 403fe6f42cfSNava kishore Manne return ret; 404fe6f42cfSNava kishore Manne } 40521cd93baSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_chipid); 406fe6f42cfSNava kishore Manne 407fe6f42cfSNava kishore Manne /** 40876582671SRajan Vaja * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version 40976582671SRajan Vaja * @version: Returned version value 41076582671SRajan Vaja * 41176582671SRajan Vaja * Return: Returns status, either success or error+reason 41276582671SRajan Vaja */ 41376582671SRajan Vaja static int zynqmp_pm_get_trustzone_version(u32 *version) 41476582671SRajan Vaja { 41576582671SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 41676582671SRajan Vaja int ret; 41776582671SRajan Vaja 41876582671SRajan Vaja if (!version) 41976582671SRajan Vaja return -EINVAL; 42076582671SRajan Vaja 42176582671SRajan Vaja /* Check is PM trustzone version already verified */ 42276582671SRajan Vaja if (pm_tz_version > 0) { 42376582671SRajan Vaja *version = pm_tz_version; 42476582671SRajan Vaja return 0; 42576582671SRajan Vaja } 42676582671SRajan Vaja ret = zynqmp_pm_invoke_fn(PM_GET_TRUSTZONE_VERSION, 0, 0, 42776582671SRajan Vaja 0, 0, ret_payload); 42876582671SRajan Vaja *version = ret_payload[1]; 42976582671SRajan Vaja 43076582671SRajan Vaja return ret; 43176582671SRajan Vaja } 43276582671SRajan Vaja 43376582671SRajan Vaja /** 43476582671SRajan Vaja * get_set_conduit_method() - Choose SMC or HVC based communication 43576582671SRajan Vaja * @np: Pointer to the device_node structure 43676582671SRajan Vaja * 43776582671SRajan Vaja * Use SMC or HVC-based functions to communicate with EL2/EL3. 43876582671SRajan Vaja * 43976582671SRajan Vaja * Return: Returns 0 on success or error code 44076582671SRajan Vaja */ 44176582671SRajan Vaja static int get_set_conduit_method(struct device_node *np) 44276582671SRajan Vaja { 44376582671SRajan Vaja const char *method; 44476582671SRajan Vaja 44576582671SRajan Vaja if (of_property_read_string(np, "method", &method)) { 44676582671SRajan Vaja pr_warn("%s missing \"method\" property\n", __func__); 44776582671SRajan Vaja return -ENXIO; 44876582671SRajan Vaja } 44976582671SRajan Vaja 45076582671SRajan Vaja if (!strcmp("hvc", method)) { 45176582671SRajan Vaja do_fw_call = do_fw_call_hvc; 45276582671SRajan Vaja } else if (!strcmp("smc", method)) { 45376582671SRajan Vaja do_fw_call = do_fw_call_smc; 45476582671SRajan Vaja } else { 45576582671SRajan Vaja pr_warn("%s Invalid \"method\" property: %s\n", 45676582671SRajan Vaja __func__, method); 45776582671SRajan Vaja return -EINVAL; 45876582671SRajan Vaja } 45976582671SRajan Vaja 46076582671SRajan Vaja return 0; 46176582671SRajan Vaja } 46276582671SRajan Vaja 46359ecdd77SRajan Vaja /** 46459ecdd77SRajan Vaja * zynqmp_pm_query_data() - Get query data from firmware 46559ecdd77SRajan Vaja * @qdata: Variable to the zynqmp_pm_query_data structure 46659ecdd77SRajan Vaja * @out: Returned output value 46759ecdd77SRajan Vaja * 46859ecdd77SRajan Vaja * Return: Returns status, either success or error+reason 46959ecdd77SRajan Vaja */ 4706366c1baSRajan Vaja int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out) 47159ecdd77SRajan Vaja { 472f9627312SRajan Vaja int ret; 473f9627312SRajan Vaja 474f9627312SRajan Vaja ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, qdata.qid, qdata.arg1, 47559ecdd77SRajan Vaja qdata.arg2, qdata.arg3, out); 476f9627312SRajan Vaja 477f9627312SRajan Vaja /* 478f9627312SRajan Vaja * For clock name query, all bytes in SMC response are clock name 479f9627312SRajan Vaja * characters and return code is always success. For invalid clocks, 480f9627312SRajan Vaja * clock name bytes would be zeros. 481f9627312SRajan Vaja */ 482f9627312SRajan Vaja return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret; 483f9627312SRajan Vaja } 4846366c1baSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_query_data); 485f9627312SRajan Vaja 486f9627312SRajan Vaja /** 487f9627312SRajan Vaja * zynqmp_pm_clock_enable() - Enable the clock for given id 488f9627312SRajan Vaja * @clock_id: ID of the clock to be enabled 489f9627312SRajan Vaja * 490f9627312SRajan Vaja * This function is used by master to enable the clock 491f9627312SRajan Vaja * including peripherals and PLL clocks. 492f9627312SRajan Vaja * 493f9627312SRajan Vaja * Return: Returns status, either success or error+reason 494f9627312SRajan Vaja */ 4953637e84cSRajan Vaja int zynqmp_pm_clock_enable(u32 clock_id) 496f9627312SRajan Vaja { 497f9627312SRajan Vaja return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL); 498f9627312SRajan Vaja } 4993637e84cSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_enable); 500f9627312SRajan Vaja 501f9627312SRajan Vaja /** 502f9627312SRajan Vaja * zynqmp_pm_clock_disable() - Disable the clock for given id 503f9627312SRajan Vaja * @clock_id: ID of the clock to be disable 504f9627312SRajan Vaja * 505f9627312SRajan Vaja * This function is used by master to disable the clock 506f9627312SRajan Vaja * including peripherals and PLL clocks. 507f9627312SRajan Vaja * 508f9627312SRajan Vaja * Return: Returns status, either success or error+reason 509f9627312SRajan Vaja */ 510f5ccd54bSRajan Vaja int zynqmp_pm_clock_disable(u32 clock_id) 511f9627312SRajan Vaja { 512f9627312SRajan Vaja return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL); 513f9627312SRajan Vaja } 514f5ccd54bSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_disable); 515f9627312SRajan Vaja 516f9627312SRajan Vaja /** 517f9627312SRajan Vaja * zynqmp_pm_clock_getstate() - Get the clock state for given id 518f9627312SRajan Vaja * @clock_id: ID of the clock to be queried 519f9627312SRajan Vaja * @state: 1/0 (Enabled/Disabled) 520f9627312SRajan Vaja * 521f9627312SRajan Vaja * This function is used by master to get the state of clock 522f9627312SRajan Vaja * including peripherals and PLL clocks. 523f9627312SRajan Vaja * 524f9627312SRajan Vaja * Return: Returns status, either success or error+reason 525f9627312SRajan Vaja */ 5265e76731dSRajan Vaja int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state) 527f9627312SRajan Vaja { 528f9627312SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 529f9627312SRajan Vaja int ret; 530f9627312SRajan Vaja 531f9627312SRajan Vaja ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, clock_id, 0, 532f9627312SRajan Vaja 0, 0, ret_payload); 533f9627312SRajan Vaja *state = ret_payload[1]; 534f9627312SRajan Vaja 535f9627312SRajan Vaja return ret; 536f9627312SRajan Vaja } 5375e76731dSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getstate); 538f9627312SRajan Vaja 539f9627312SRajan Vaja /** 540f9627312SRajan Vaja * zynqmp_pm_clock_setdivider() - Set the clock divider for given id 541f9627312SRajan Vaja * @clock_id: ID of the clock 542f9627312SRajan Vaja * @divider: divider value 543f9627312SRajan Vaja * 544f9627312SRajan Vaja * This function is used by master to set divider for any clock 545f9627312SRajan Vaja * to achieve desired rate. 546f9627312SRajan Vaja * 547f9627312SRajan Vaja * Return: Returns status, either success or error+reason 548f9627312SRajan Vaja */ 549fc9fb8fbSRajan Vaja int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider) 550f9627312SRajan Vaja { 551f9627312SRajan Vaja return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, clock_id, divider, 552f9627312SRajan Vaja 0, 0, NULL); 553f9627312SRajan Vaja } 554fc9fb8fbSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setdivider); 555f9627312SRajan Vaja 556f9627312SRajan Vaja /** 557f9627312SRajan Vaja * zynqmp_pm_clock_getdivider() - Get the clock divider for given id 558f9627312SRajan Vaja * @clock_id: ID of the clock 559f9627312SRajan Vaja * @divider: divider value 560f9627312SRajan Vaja * 561f9627312SRajan Vaja * This function is used by master to get divider values 562f9627312SRajan Vaja * for any clock. 563f9627312SRajan Vaja * 564f9627312SRajan Vaja * Return: Returns status, either success or error+reason 565f9627312SRajan Vaja */ 5660667a8d1SRajan Vaja int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider) 567f9627312SRajan Vaja { 568f9627312SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 569f9627312SRajan Vaja int ret; 570f9627312SRajan Vaja 571f9627312SRajan Vaja ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, clock_id, 0, 572f9627312SRajan Vaja 0, 0, ret_payload); 573f9627312SRajan Vaja *divider = ret_payload[1]; 574f9627312SRajan Vaja 575f9627312SRajan Vaja return ret; 576f9627312SRajan Vaja } 5770667a8d1SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getdivider); 578f9627312SRajan Vaja 579f9627312SRajan Vaja /** 580f9627312SRajan Vaja * zynqmp_pm_clock_setrate() - Set the clock rate for given id 581f9627312SRajan Vaja * @clock_id: ID of the clock 582f9627312SRajan Vaja * @rate: rate value in hz 583f9627312SRajan Vaja * 584f9627312SRajan Vaja * This function is used by master to set rate for any clock. 585f9627312SRajan Vaja * 586f9627312SRajan Vaja * Return: Returns status, either success or error+reason 587f9627312SRajan Vaja */ 5887a1e1062SRajan Vaja int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate) 589f9627312SRajan Vaja { 590f9627312SRajan Vaja return zynqmp_pm_invoke_fn(PM_CLOCK_SETRATE, clock_id, 591f9627312SRajan Vaja lower_32_bits(rate), 592f9627312SRajan Vaja upper_32_bits(rate), 593f9627312SRajan Vaja 0, NULL); 594f9627312SRajan Vaja } 5957a1e1062SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setrate); 596f9627312SRajan Vaja 597f9627312SRajan Vaja /** 598f9627312SRajan Vaja * zynqmp_pm_clock_getrate() - Get the clock rate for given id 599f9627312SRajan Vaja * @clock_id: ID of the clock 600f9627312SRajan Vaja * @rate: rate value in hz 601f9627312SRajan Vaja * 602f9627312SRajan Vaja * This function is used by master to get rate 603f9627312SRajan Vaja * for any clock. 604f9627312SRajan Vaja * 605f9627312SRajan Vaja * Return: Returns status, either success or error+reason 606f9627312SRajan Vaja */ 6077a1e1062SRajan Vaja int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate) 608f9627312SRajan Vaja { 609f9627312SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 610f9627312SRajan Vaja int ret; 611f9627312SRajan Vaja 612f9627312SRajan Vaja ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETRATE, clock_id, 0, 613f9627312SRajan Vaja 0, 0, ret_payload); 614f9627312SRajan Vaja *rate = ((u64)ret_payload[2] << 32) | ret_payload[1]; 615f9627312SRajan Vaja 616f9627312SRajan Vaja return ret; 617f9627312SRajan Vaja } 6187a1e1062SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getrate); 619f9627312SRajan Vaja 620f9627312SRajan Vaja /** 621f9627312SRajan Vaja * zynqmp_pm_clock_setparent() - Set the clock parent for given id 622f9627312SRajan Vaja * @clock_id: ID of the clock 623f9627312SRajan Vaja * @parent_id: parent id 624f9627312SRajan Vaja * 625f9627312SRajan Vaja * This function is used by master to set parent for any clock. 626f9627312SRajan Vaja * 627f9627312SRajan Vaja * Return: Returns status, either success or error+reason 628f9627312SRajan Vaja */ 62970c0d364SRajan Vaja int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id) 630f9627312SRajan Vaja { 631f9627312SRajan Vaja return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, clock_id, 632f9627312SRajan Vaja parent_id, 0, 0, NULL); 633f9627312SRajan Vaja } 63470c0d364SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setparent); 635f9627312SRajan Vaja 636f9627312SRajan Vaja /** 637f9627312SRajan Vaja * zynqmp_pm_clock_getparent() - Get the clock parent for given id 638f9627312SRajan Vaja * @clock_id: ID of the clock 639f9627312SRajan Vaja * @parent_id: parent id 640f9627312SRajan Vaja * 641f9627312SRajan Vaja * This function is used by master to get parent index 642f9627312SRajan Vaja * for any clock. 643f9627312SRajan Vaja * 644f9627312SRajan Vaja * Return: Returns status, either success or error+reason 645f9627312SRajan Vaja */ 64670c0d364SRajan Vaja int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id) 647f9627312SRajan Vaja { 648f9627312SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 649f9627312SRajan Vaja int ret; 650f9627312SRajan Vaja 651f9627312SRajan Vaja ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, clock_id, 0, 652f9627312SRajan Vaja 0, 0, ret_payload); 653f9627312SRajan Vaja *parent_id = ret_payload[1]; 654f9627312SRajan Vaja 655f9627312SRajan Vaja return ret; 65659ecdd77SRajan Vaja } 65770c0d364SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getparent); 65859ecdd77SRajan Vaja 6593b0296b8SRajan Vaja /** 660426c8d85SRajan Vaja * zynqmp_pm_set_pll_frac_mode() - PM API for set PLL mode 6613b0296b8SRajan Vaja * 662426c8d85SRajan Vaja * @clk_id: PLL clock ID 663426c8d85SRajan Vaja * @mode: PLL mode (PLL_MODE_FRAC/PLL_MODE_INT) 6643b0296b8SRajan Vaja * 665426c8d85SRajan Vaja * This function sets PLL mode 6663b0296b8SRajan Vaja * 6673b0296b8SRajan Vaja * Return: Returns status, either success or error+reason 6683b0296b8SRajan Vaja */ 669426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_mode(u32 clk_id, u32 mode) 6703b0296b8SRajan Vaja { 671426c8d85SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_MODE, 672426c8d85SRajan Vaja clk_id, mode, NULL); 6733b0296b8SRajan Vaja } 674426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_mode); 675426c8d85SRajan Vaja 676426c8d85SRajan Vaja /** 677426c8d85SRajan Vaja * zynqmp_pm_get_pll_frac_mode() - PM API for get PLL mode 678426c8d85SRajan Vaja * 679426c8d85SRajan Vaja * @clk_id: PLL clock ID 680426c8d85SRajan Vaja * @mode: PLL mode 681426c8d85SRajan Vaja * 682426c8d85SRajan Vaja * This function return current PLL mode 683426c8d85SRajan Vaja * 684426c8d85SRajan Vaja * Return: Returns status, either success or error+reason 685426c8d85SRajan Vaja */ 686426c8d85SRajan Vaja int zynqmp_pm_get_pll_frac_mode(u32 clk_id, u32 *mode) 687426c8d85SRajan Vaja { 688426c8d85SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_MODE, 689426c8d85SRajan Vaja clk_id, 0, mode); 690426c8d85SRajan Vaja } 691426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_mode); 692426c8d85SRajan Vaja 693426c8d85SRajan Vaja /** 694426c8d85SRajan Vaja * zynqmp_pm_set_pll_frac_data() - PM API for setting pll fraction data 695426c8d85SRajan Vaja * 696426c8d85SRajan Vaja * @clk_id: PLL clock ID 697426c8d85SRajan Vaja * @data: fraction data 698426c8d85SRajan Vaja * 699426c8d85SRajan Vaja * This function sets fraction data. 700426c8d85SRajan Vaja * It is valid for fraction mode only. 701426c8d85SRajan Vaja * 702426c8d85SRajan Vaja * Return: Returns status, either success or error+reason 703426c8d85SRajan Vaja */ 704426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_data(u32 clk_id, u32 data) 705426c8d85SRajan Vaja { 706426c8d85SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_DATA, 707426c8d85SRajan Vaja clk_id, data, NULL); 708426c8d85SRajan Vaja } 709426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_data); 710426c8d85SRajan Vaja 711426c8d85SRajan Vaja /** 712426c8d85SRajan Vaja * zynqmp_pm_get_pll_frac_data() - PM API for getting pll fraction data 713426c8d85SRajan Vaja * 714426c8d85SRajan Vaja * @clk_id: PLL clock ID 715426c8d85SRajan Vaja * @data: fraction data 716426c8d85SRajan Vaja * 717426c8d85SRajan Vaja * This function returns fraction data value. 718426c8d85SRajan Vaja * 719426c8d85SRajan Vaja * Return: Returns status, either success or error+reason 720426c8d85SRajan Vaja */ 721426c8d85SRajan Vaja int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data) 722426c8d85SRajan Vaja { 723426c8d85SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_DATA, 724426c8d85SRajan Vaja clk_id, 0, data); 725426c8d85SRajan Vaja } 726426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data); 727426c8d85SRajan Vaja 728426c8d85SRajan Vaja /** 729426c8d85SRajan Vaja * zynqmp_pm_set_sd_tapdelay() - Set tap delay for the SD device 730426c8d85SRajan Vaja * 731332bee16SMichal Simek * @node_id: Node ID of the device 732332bee16SMichal Simek * @type: Type of tap delay to set (input/output) 733332bee16SMichal Simek * @value: Value to set fot the tap delay 734426c8d85SRajan Vaja * 735426c8d85SRajan Vaja * This function sets input/output tap delay for the SD device. 736426c8d85SRajan Vaja * 737332bee16SMichal Simek * Return: Returns status, either success or error+reason 738426c8d85SRajan Vaja */ 739426c8d85SRajan Vaja int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value) 740426c8d85SRajan Vaja { 741426c8d85SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY, 742426c8d85SRajan Vaja type, value, NULL); 743426c8d85SRajan Vaja } 744426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay); 745426c8d85SRajan Vaja 746426c8d85SRajan Vaja /** 747426c8d85SRajan Vaja * zynqmp_pm_sd_dll_reset() - Reset DLL logic 748426c8d85SRajan Vaja * 749332bee16SMichal Simek * @node_id: Node ID of the device 750332bee16SMichal Simek * @type: Reset type 751426c8d85SRajan Vaja * 752426c8d85SRajan Vaja * This function resets DLL logic for the SD device. 753426c8d85SRajan Vaja * 754332bee16SMichal Simek * Return: Returns status, either success or error+reason 755426c8d85SRajan Vaja */ 756426c8d85SRajan Vaja int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type) 757426c8d85SRajan Vaja { 758f4426311SManish Narani return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SD_DLL_RESET, 759426c8d85SRajan Vaja type, 0, NULL); 760426c8d85SRajan Vaja } 761426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset); 7623b0296b8SRajan Vaja 763bc3843d4SNava kishore Manne /** 76474e78adcSSai Krishna Potthuri * zynqmp_pm_ospi_mux_select() - OSPI Mux selection 76574e78adcSSai Krishna Potthuri * 76674e78adcSSai Krishna Potthuri * @dev_id: Device Id of the OSPI device. 76774e78adcSSai Krishna Potthuri * @select: OSPI Mux select value. 76874e78adcSSai Krishna Potthuri * 76974e78adcSSai Krishna Potthuri * This function select the OSPI Mux. 77074e78adcSSai Krishna Potthuri * 77174e78adcSSai Krishna Potthuri * Return: Returns status, either success or error+reason 77274e78adcSSai Krishna Potthuri */ 77374e78adcSSai Krishna Potthuri int zynqmp_pm_ospi_mux_select(u32 dev_id, u32 select) 77474e78adcSSai Krishna Potthuri { 77574e78adcSSai Krishna Potthuri return zynqmp_pm_invoke_fn(PM_IOCTL, dev_id, IOCTL_OSPI_MUX_SELECT, 77674e78adcSSai Krishna Potthuri select, 0, NULL); 77774e78adcSSai Krishna Potthuri } 77874e78adcSSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_ospi_mux_select); 77974e78adcSSai Krishna Potthuri 78074e78adcSSai Krishna Potthuri /** 7814f680b72SRajan Vaja * zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs) 782332bee16SMichal Simek * @index: GGS register index 783332bee16SMichal Simek * @value: Register value to be written 7844f680b72SRajan Vaja * 7854f680b72SRajan Vaja * This function writes value to GGS register. 7864f680b72SRajan Vaja * 787332bee16SMichal Simek * Return: Returns status, either success or error+reason 7884f680b72SRajan Vaja */ 7894f680b72SRajan Vaja int zynqmp_pm_write_ggs(u32 index, u32 value) 7904f680b72SRajan Vaja { 7914f680b72SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_GGS, 7924f680b72SRajan Vaja index, value, NULL); 7934f680b72SRajan Vaja } 7944f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs); 7954f680b72SRajan Vaja 7964f680b72SRajan Vaja /** 7972a8faf8dSMichal Simek * zynqmp_pm_read_ggs() - PM API for reading global general storage (ggs) 798332bee16SMichal Simek * @index: GGS register index 799332bee16SMichal Simek * @value: Register value to be written 8004f680b72SRajan Vaja * 8014f680b72SRajan Vaja * This function returns GGS register value. 8024f680b72SRajan Vaja * 803332bee16SMichal Simek * Return: Returns status, either success or error+reason 8044f680b72SRajan Vaja */ 8054f680b72SRajan Vaja int zynqmp_pm_read_ggs(u32 index, u32 *value) 8064f680b72SRajan Vaja { 8074f680b72SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_GGS, 8084f680b72SRajan Vaja index, 0, value); 8094f680b72SRajan Vaja } 8104f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs); 8114f680b72SRajan Vaja 8124f680b72SRajan Vaja /** 8134f680b72SRajan Vaja * zynqmp_pm_write_pggs() - PM API for writing persistent global general 8144f680b72SRajan Vaja * storage (pggs) 815332bee16SMichal Simek * @index: PGGS register index 816332bee16SMichal Simek * @value: Register value to be written 8174f680b72SRajan Vaja * 8184f680b72SRajan Vaja * This function writes value to PGGS register. 8194f680b72SRajan Vaja * 820332bee16SMichal Simek * Return: Returns status, either success or error+reason 8214f680b72SRajan Vaja */ 8224f680b72SRajan Vaja int zynqmp_pm_write_pggs(u32 index, u32 value) 8234f680b72SRajan Vaja { 8244f680b72SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_PGGS, index, value, 8254f680b72SRajan Vaja NULL); 8264f680b72SRajan Vaja } 8274f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs); 8284f680b72SRajan Vaja 8294f680b72SRajan Vaja /** 8302a8faf8dSMichal Simek * zynqmp_pm_read_pggs() - PM API for reading persistent global general 8314f680b72SRajan Vaja * storage (pggs) 832332bee16SMichal Simek * @index: PGGS register index 833332bee16SMichal Simek * @value: Register value to be written 8344f680b72SRajan Vaja * 8354f680b72SRajan Vaja * This function returns PGGS register value. 8364f680b72SRajan Vaja * 837332bee16SMichal Simek * Return: Returns status, either success or error+reason 8384f680b72SRajan Vaja */ 8394f680b72SRajan Vaja int zynqmp_pm_read_pggs(u32 index, u32 *value) 8404f680b72SRajan Vaja { 8414f680b72SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_PGGS, index, 0, 8424f680b72SRajan Vaja value); 8434f680b72SRajan Vaja } 8444f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs); 8454f680b72SRajan Vaja 8464f680b72SRajan Vaja /** 847a2cc220aSRajan Vaja * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status 848332bee16SMichal Simek * @value: Status value to be written 849a2cc220aSRajan Vaja * 850a2cc220aSRajan Vaja * This function sets healthy bit value to indicate boot health status 851a2cc220aSRajan Vaja * to firmware. 852a2cc220aSRajan Vaja * 853332bee16SMichal Simek * Return: Returns status, either success or error+reason 854a2cc220aSRajan Vaja */ 855a2cc220aSRajan Vaja int zynqmp_pm_set_boot_health_status(u32 value) 856a2cc220aSRajan Vaja { 857a2cc220aSRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_BOOT_HEALTH_STATUS, 858a2cc220aSRajan Vaja value, 0, NULL); 859a2cc220aSRajan Vaja } 860a2cc220aSRajan Vaja 861a2cc220aSRajan Vaja /** 862bc3843d4SNava kishore Manne * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release) 863bc3843d4SNava kishore Manne * @reset: Reset to be configured 864bc3843d4SNava kishore Manne * @assert_flag: Flag stating should reset be asserted (1) or 865bc3843d4SNava kishore Manne * released (0) 866bc3843d4SNava kishore Manne * 867bc3843d4SNava kishore Manne * Return: Returns status, either success or error+reason 868bc3843d4SNava kishore Manne */ 869cf23ec35SRajan Vaja int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset, 870bc3843d4SNava kishore Manne const enum zynqmp_pm_reset_action assert_flag) 871bc3843d4SNava kishore Manne { 872bc3843d4SNava kishore Manne return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag, 873bc3843d4SNava kishore Manne 0, 0, NULL); 874bc3843d4SNava kishore Manne } 875cf23ec35SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert); 876bc3843d4SNava kishore Manne 877bc3843d4SNava kishore Manne /** 878bc3843d4SNava kishore Manne * zynqmp_pm_reset_get_status - Get status of the reset 879bc3843d4SNava kishore Manne * @reset: Reset whose status should be returned 880bc3843d4SNava kishore Manne * @status: Returned status 881bc3843d4SNava kishore Manne * 882bc3843d4SNava kishore Manne * Return: Returns status, either success or error+reason 883bc3843d4SNava kishore Manne */ 8841b413581SRajan Vaja int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status) 885bc3843d4SNava kishore Manne { 886bc3843d4SNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT]; 887bc3843d4SNava kishore Manne int ret; 888bc3843d4SNava kishore Manne 889bc3843d4SNava kishore Manne if (!status) 890bc3843d4SNava kishore Manne return -EINVAL; 891bc3843d4SNava kishore Manne 892bc3843d4SNava kishore Manne ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0, 893bc3843d4SNava kishore Manne 0, 0, ret_payload); 894bc3843d4SNava kishore Manne *status = ret_payload[1]; 895bc3843d4SNava kishore Manne 896bc3843d4SNava kishore Manne return ret; 897bc3843d4SNava kishore Manne } 8981b413581SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status); 899bc3843d4SNava kishore Manne 900e178df31SJolly Shah /** 901e840deccSNava kishore Manne * zynqmp_pm_fpga_load - Perform the fpga load 902e840deccSNava kishore Manne * @address: Address to write to 903e840deccSNava kishore Manne * @size: pl bitstream size 904e840deccSNava kishore Manne * @flags: Bitstream type 905e840deccSNava kishore Manne * -XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration 906e840deccSNava kishore Manne * -XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration 907e840deccSNava kishore Manne * 908e840deccSNava kishore Manne * This function provides access to pmufw. To transfer 909e840deccSNava kishore Manne * the required bitstream into PL. 910e840deccSNava kishore Manne * 911e840deccSNava kishore Manne * Return: Returns status, either success or error+reason 912e840deccSNava kishore Manne */ 9134db8180fSRajan Vaja int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags) 914e840deccSNava kishore Manne { 915e840deccSNava kishore Manne return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address), 916e840deccSNava kishore Manne upper_32_bits(address), size, flags, NULL); 917e840deccSNava kishore Manne } 91856a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load); 919e840deccSNava kishore Manne 920e840deccSNava kishore Manne /** 921e840deccSNava kishore Manne * zynqmp_pm_fpga_get_status - Read value from PCAP status register 922e840deccSNava kishore Manne * @value: Value to read 923e840deccSNava kishore Manne * 924e840deccSNava kishore Manne * This function provides access to the pmufw to get the PCAP 925e840deccSNava kishore Manne * status 926e840deccSNava kishore Manne * 927e840deccSNava kishore Manne * Return: Returns status, either success or error+reason 928e840deccSNava kishore Manne */ 9294db8180fSRajan Vaja int zynqmp_pm_fpga_get_status(u32 *value) 930e840deccSNava kishore Manne { 931e840deccSNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT]; 932e840deccSNava kishore Manne int ret; 933e840deccSNava kishore Manne 934e840deccSNava kishore Manne if (!value) 935e840deccSNava kishore Manne return -EINVAL; 936e840deccSNava kishore Manne 937e840deccSNava kishore Manne ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload); 938e840deccSNava kishore Manne *value = ret_payload[1]; 939e840deccSNava kishore Manne 940e840deccSNava kishore Manne return ret; 941e840deccSNava kishore Manne } 94256a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status); 943e840deccSNava kishore Manne 944e840deccSNava kishore Manne /** 945fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_request - Request Pin from firmware 946fa989ae7SSai Krishna Potthuri * @pin: Pin number to request 947fa989ae7SSai Krishna Potthuri * 948fa989ae7SSai Krishna Potthuri * This function requests pin from firmware. 949fa989ae7SSai Krishna Potthuri * 950fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason. 951fa989ae7SSai Krishna Potthuri */ 952fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_request(const u32 pin) 953fa989ae7SSai Krishna Potthuri { 954fa989ae7SSai Krishna Potthuri return zynqmp_pm_invoke_fn(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL); 955fa989ae7SSai Krishna Potthuri } 956fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_request); 957fa989ae7SSai Krishna Potthuri 958fa989ae7SSai Krishna Potthuri /** 959fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_release - Inform firmware that Pin control is released 960fa989ae7SSai Krishna Potthuri * @pin: Pin number to release 961fa989ae7SSai Krishna Potthuri * 962fa989ae7SSai Krishna Potthuri * This function release pin from firmware. 963fa989ae7SSai Krishna Potthuri * 964fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason. 965fa989ae7SSai Krishna Potthuri */ 966fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_release(const u32 pin) 967fa989ae7SSai Krishna Potthuri { 968fa989ae7SSai Krishna Potthuri return zynqmp_pm_invoke_fn(PM_PINCTRL_RELEASE, pin, 0, 0, 0, NULL); 969fa989ae7SSai Krishna Potthuri } 970fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_release); 971fa989ae7SSai Krishna Potthuri 972fa989ae7SSai Krishna Potthuri /** 973fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_get_function - Read function id set for the given pin 974fa989ae7SSai Krishna Potthuri * @pin: Pin number 975fa989ae7SSai Krishna Potthuri * @id: Buffer to store function ID 976fa989ae7SSai Krishna Potthuri * 977fa989ae7SSai Krishna Potthuri * This function provides the function currently set for the given pin. 978fa989ae7SSai Krishna Potthuri * 979fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason 980fa989ae7SSai Krishna Potthuri */ 981fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_get_function(const u32 pin, u32 *id) 982fa989ae7SSai Krishna Potthuri { 983fa989ae7SSai Krishna Potthuri u32 ret_payload[PAYLOAD_ARG_CNT]; 984fa989ae7SSai Krishna Potthuri int ret; 985fa989ae7SSai Krishna Potthuri 986fa989ae7SSai Krishna Potthuri if (!id) 987fa989ae7SSai Krishna Potthuri return -EINVAL; 988fa989ae7SSai Krishna Potthuri 989fa989ae7SSai Krishna Potthuri ret = zynqmp_pm_invoke_fn(PM_PINCTRL_GET_FUNCTION, pin, 0, 990fa989ae7SSai Krishna Potthuri 0, 0, ret_payload); 991fa989ae7SSai Krishna Potthuri *id = ret_payload[1]; 992fa989ae7SSai Krishna Potthuri 993fa989ae7SSai Krishna Potthuri return ret; 994fa989ae7SSai Krishna Potthuri } 995fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_function); 996fa989ae7SSai Krishna Potthuri 997fa989ae7SSai Krishna Potthuri /** 998fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_set_function - Set requested function for the pin 999fa989ae7SSai Krishna Potthuri * @pin: Pin number 1000fa989ae7SSai Krishna Potthuri * @id: Function ID to set 1001fa989ae7SSai Krishna Potthuri * 1002fa989ae7SSai Krishna Potthuri * This function sets requested function for the given pin. 1003fa989ae7SSai Krishna Potthuri * 1004fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason. 1005fa989ae7SSai Krishna Potthuri */ 1006fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id) 1007fa989ae7SSai Krishna Potthuri { 1008fa989ae7SSai Krishna Potthuri return zynqmp_pm_invoke_fn(PM_PINCTRL_SET_FUNCTION, pin, id, 1009fa989ae7SSai Krishna Potthuri 0, 0, NULL); 1010fa989ae7SSai Krishna Potthuri } 1011fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_function); 1012fa989ae7SSai Krishna Potthuri 1013fa989ae7SSai Krishna Potthuri /** 1014fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_get_config - Get configuration parameter for the pin 1015fa989ae7SSai Krishna Potthuri * @pin: Pin number 1016fa989ae7SSai Krishna Potthuri * @param: Parameter to get 1017fa989ae7SSai Krishna Potthuri * @value: Buffer to store parameter value 1018fa989ae7SSai Krishna Potthuri * 1019fa989ae7SSai Krishna Potthuri * This function gets requested configuration parameter for the given pin. 1020fa989ae7SSai Krishna Potthuri * 1021fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason. 1022fa989ae7SSai Krishna Potthuri */ 1023fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param, 1024fa989ae7SSai Krishna Potthuri u32 *value) 1025fa989ae7SSai Krishna Potthuri { 1026fa989ae7SSai Krishna Potthuri u32 ret_payload[PAYLOAD_ARG_CNT]; 1027fa989ae7SSai Krishna Potthuri int ret; 1028fa989ae7SSai Krishna Potthuri 1029fa989ae7SSai Krishna Potthuri if (!value) 1030fa989ae7SSai Krishna Potthuri return -EINVAL; 1031fa989ae7SSai Krishna Potthuri 1032fa989ae7SSai Krishna Potthuri ret = zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_GET, pin, param, 1033fa989ae7SSai Krishna Potthuri 0, 0, ret_payload); 1034fa989ae7SSai Krishna Potthuri *value = ret_payload[1]; 1035fa989ae7SSai Krishna Potthuri 1036fa989ae7SSai Krishna Potthuri return ret; 1037fa989ae7SSai Krishna Potthuri } 1038fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_config); 1039fa989ae7SSai Krishna Potthuri 1040fa989ae7SSai Krishna Potthuri /** 1041fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_set_config - Set configuration parameter for the pin 1042fa989ae7SSai Krishna Potthuri * @pin: Pin number 1043fa989ae7SSai Krishna Potthuri * @param: Parameter to set 1044fa989ae7SSai Krishna Potthuri * @value: Parameter value to set 1045fa989ae7SSai Krishna Potthuri * 1046fa989ae7SSai Krishna Potthuri * This function sets requested configuration parameter for the given pin. 1047fa989ae7SSai Krishna Potthuri * 1048fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason. 1049fa989ae7SSai Krishna Potthuri */ 1050fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param, 1051fa989ae7SSai Krishna Potthuri u32 value) 1052fa989ae7SSai Krishna Potthuri { 1053fa989ae7SSai Krishna Potthuri return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, pin, 1054fa989ae7SSai Krishna Potthuri param, value, 0, NULL); 1055fa989ae7SSai Krishna Potthuri } 1056fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_config); 1057fa989ae7SSai Krishna Potthuri 1058fa989ae7SSai Krishna Potthuri /** 105923c64d76SPiyush Mehta * zynqmp_pm_bootmode_read() - PM Config API for read bootpin status 106023c64d76SPiyush Mehta * @ps_mode: Returned output value of ps_mode 106123c64d76SPiyush Mehta * 106223c64d76SPiyush Mehta * This API function is to be used for notify the power management controller 106323c64d76SPiyush Mehta * to read bootpin status. 106423c64d76SPiyush Mehta * 106523c64d76SPiyush Mehta * Return: status, either success or error+reason 106623c64d76SPiyush Mehta */ 106723c64d76SPiyush Mehta unsigned int zynqmp_pm_bootmode_read(u32 *ps_mode) 106823c64d76SPiyush Mehta { 106923c64d76SPiyush Mehta unsigned int ret; 107023c64d76SPiyush Mehta u32 ret_payload[PAYLOAD_ARG_CNT]; 107123c64d76SPiyush Mehta 107223c64d76SPiyush Mehta ret = zynqmp_pm_invoke_fn(PM_MMIO_READ, CRL_APB_BOOT_PIN_CTRL, 0, 107323c64d76SPiyush Mehta 0, 0, ret_payload); 107423c64d76SPiyush Mehta 107523c64d76SPiyush Mehta *ps_mode = ret_payload[1]; 107623c64d76SPiyush Mehta 107723c64d76SPiyush Mehta return ret; 107823c64d76SPiyush Mehta } 107923c64d76SPiyush Mehta EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_read); 108023c64d76SPiyush Mehta 108123c64d76SPiyush Mehta /** 108223c64d76SPiyush Mehta * zynqmp_pm_bootmode_write() - PM Config API for Configure bootpin 108323c64d76SPiyush Mehta * @ps_mode: Value to be written to the bootpin ctrl register 108423c64d76SPiyush Mehta * 108523c64d76SPiyush Mehta * This API function is to be used for notify the power management controller 108623c64d76SPiyush Mehta * to configure bootpin. 108723c64d76SPiyush Mehta * 108823c64d76SPiyush Mehta * Return: Returns status, either success or error+reason 108923c64d76SPiyush Mehta */ 109023c64d76SPiyush Mehta int zynqmp_pm_bootmode_write(u32 ps_mode) 109123c64d76SPiyush Mehta { 109223c64d76SPiyush Mehta return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, CRL_APB_BOOT_PIN_CTRL, 109323c64d76SPiyush Mehta CRL_APB_BOOTPIN_CTRL_MASK, ps_mode, 0, NULL); 109423c64d76SPiyush Mehta } 109523c64d76SPiyush Mehta EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_write); 109623c64d76SPiyush Mehta 109723c64d76SPiyush Mehta /** 1098e178df31SJolly Shah * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller 1099e178df31SJolly Shah * master has initialized its own power management 1100e178df31SJolly Shah * 1101332bee16SMichal Simek * Return: Returns status, either success or error+reason 1102332bee16SMichal Simek * 1103e178df31SJolly Shah * This API function is to be used for notify the power management controller 1104e178df31SJolly Shah * about the completed power management initialization. 1105e178df31SJolly Shah */ 11069474da95SRajan Vaja int zynqmp_pm_init_finalize(void) 1107e178df31SJolly Shah { 1108e178df31SJolly Shah return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL); 1109e178df31SJolly Shah } 11109474da95SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_init_finalize); 1111e178df31SJolly Shah 1112e178df31SJolly Shah /** 1113e178df31SJolly Shah * zynqmp_pm_set_suspend_mode() - Set system suspend mode 1114e178df31SJolly Shah * @mode: Mode to set for system suspend 1115e178df31SJolly Shah * 1116e178df31SJolly Shah * This API function is used to set mode of system suspend. 1117e178df31SJolly Shah * 1118e178df31SJolly Shah * Return: Returns status, either success or error+reason 1119e178df31SJolly Shah */ 1120951d0a97SRajan Vaja int zynqmp_pm_set_suspend_mode(u32 mode) 1121e178df31SJolly Shah { 1122e178df31SJolly Shah return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL); 1123e178df31SJolly Shah } 1124951d0a97SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode); 1125e178df31SJolly Shah 1126c1986ac3SRajan Vaja /** 1127c1986ac3SRajan Vaja * zynqmp_pm_request_node() - Request a node with specific capabilities 1128c1986ac3SRajan Vaja * @node: Node ID of the slave 1129c1986ac3SRajan Vaja * @capabilities: Requested capabilities of the slave 1130c1986ac3SRajan Vaja * @qos: Quality of service (not supported) 1131c1986ac3SRajan Vaja * @ack: Flag to specify whether acknowledge is requested 1132c1986ac3SRajan Vaja * 1133c1986ac3SRajan Vaja * This function is used by master to request particular node from firmware. 1134c1986ac3SRajan Vaja * Every master must request node before using it. 1135c1986ac3SRajan Vaja * 1136c1986ac3SRajan Vaja * Return: Returns status, either success or error+reason 1137c1986ac3SRajan Vaja */ 1138bf8b27edSRajan Vaja int zynqmp_pm_request_node(const u32 node, const u32 capabilities, 1139bf8b27edSRajan Vaja const u32 qos, const enum zynqmp_pm_request_ack ack) 1140c1986ac3SRajan Vaja { 1141c1986ac3SRajan Vaja return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities, 1142c1986ac3SRajan Vaja qos, ack, NULL); 1143c1986ac3SRajan Vaja } 1144bf8b27edSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_request_node); 1145c1986ac3SRajan Vaja 1146c1986ac3SRajan Vaja /** 1147c1986ac3SRajan Vaja * zynqmp_pm_release_node() - Release a node 1148c1986ac3SRajan Vaja * @node: Node ID of the slave 1149c1986ac3SRajan Vaja * 1150c1986ac3SRajan Vaja * This function is used by master to inform firmware that master 1151c1986ac3SRajan Vaja * has released node. Once released, master must not use that node 1152c1986ac3SRajan Vaja * without re-request. 1153c1986ac3SRajan Vaja * 1154c1986ac3SRajan Vaja * Return: Returns status, either success or error+reason 1155c1986ac3SRajan Vaja */ 115607fb1a46SRajan Vaja int zynqmp_pm_release_node(const u32 node) 1157c1986ac3SRajan Vaja { 1158c1986ac3SRajan Vaja return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL); 1159c1986ac3SRajan Vaja } 116007fb1a46SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_release_node); 1161c1986ac3SRajan Vaja 1162c1986ac3SRajan Vaja /** 1163c1986ac3SRajan Vaja * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves 1164c1986ac3SRajan Vaja * @node: Node ID of the slave 1165c1986ac3SRajan Vaja * @capabilities: Requested capabilities of the slave 1166c1986ac3SRajan Vaja * @qos: Quality of service (not supported) 1167c1986ac3SRajan Vaja * @ack: Flag to specify whether acknowledge is requested 1168c1986ac3SRajan Vaja * 1169c1986ac3SRajan Vaja * This API function is to be used for slaves a PU already has requested 1170c1986ac3SRajan Vaja * to change its capabilities. 1171c1986ac3SRajan Vaja * 1172c1986ac3SRajan Vaja * Return: Returns status, either success or error+reason 1173c1986ac3SRajan Vaja */ 1174cbbbda71SRajan Vaja int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities, 1175c1986ac3SRajan Vaja const u32 qos, 1176c1986ac3SRajan Vaja const enum zynqmp_pm_request_ack ack) 1177c1986ac3SRajan Vaja { 1178c1986ac3SRajan Vaja return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities, 1179c1986ac3SRajan Vaja qos, ack, NULL); 1180c1986ac3SRajan Vaja } 1181cbbbda71SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement); 1182c1986ac3SRajan Vaja 1183057a0fb6SKalyani Akula /** 11842b9fc773SNava kishore Manne * zynqmp_pm_load_pdi - Load and process PDI 11852b9fc773SNava kishore Manne * @src: Source device where PDI is located 11862b9fc773SNava kishore Manne * @address: PDI src address 11872b9fc773SNava kishore Manne * 11882b9fc773SNava kishore Manne * This function provides support to load PDI from linux 11892b9fc773SNava kishore Manne * 11902b9fc773SNava kishore Manne * Return: Returns status, either success or error+reason 11912b9fc773SNava kishore Manne */ 11922b9fc773SNava kishore Manne int zynqmp_pm_load_pdi(const u32 src, const u64 address) 11932b9fc773SNava kishore Manne { 11942b9fc773SNava kishore Manne return zynqmp_pm_invoke_fn(PM_LOAD_PDI, src, 11952b9fc773SNava kishore Manne lower_32_bits(address), 11962b9fc773SNava kishore Manne upper_32_bits(address), 0, NULL); 11972b9fc773SNava kishore Manne } 11982b9fc773SNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_load_pdi); 11992b9fc773SNava kishore Manne 12002b9fc773SNava kishore Manne /** 12012a8faf8dSMichal Simek * zynqmp_pm_aes_engine - Access AES hardware to encrypt/decrypt the data using 1202057a0fb6SKalyani Akula * AES-GCM core. 1203057a0fb6SKalyani Akula * @address: Address of the AesParams structure. 1204057a0fb6SKalyani Akula * @out: Returned output value 1205057a0fb6SKalyani Akula * 1206057a0fb6SKalyani Akula * Return: Returns status, either success or error code. 1207057a0fb6SKalyani Akula */ 1208bc86f9c5SRajan Vaja int zynqmp_pm_aes_engine(const u64 address, u32 *out) 1209057a0fb6SKalyani Akula { 1210057a0fb6SKalyani Akula u32 ret_payload[PAYLOAD_ARG_CNT]; 1211057a0fb6SKalyani Akula int ret; 1212057a0fb6SKalyani Akula 1213057a0fb6SKalyani Akula if (!out) 1214057a0fb6SKalyani Akula return -EINVAL; 1215057a0fb6SKalyani Akula 1216057a0fb6SKalyani Akula ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, upper_32_bits(address), 1217057a0fb6SKalyani Akula lower_32_bits(address), 1218057a0fb6SKalyani Akula 0, 0, ret_payload); 1219057a0fb6SKalyani Akula *out = ret_payload[1]; 1220057a0fb6SKalyani Akula 1221057a0fb6SKalyani Akula return ret; 1222057a0fb6SKalyani Akula } 1223bc86f9c5SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine); 1224057a0fb6SKalyani Akula 1225fdd2ed88SRajan Vaja /** 122680f940efSHarsha * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash 122780f940efSHarsha * @address: Address of the data/ Address of output buffer where 122880f940efSHarsha * hash should be stored. 122980f940efSHarsha * @size: Size of the data. 123080f940efSHarsha * @flags: 123180f940efSHarsha * BIT(0) - for initializing csudma driver and SHA3(Here address 123280f940efSHarsha * and size inputs can be NULL). 123380f940efSHarsha * BIT(1) - to call Sha3_Update API which can be called multiple 123480f940efSHarsha * times when data is not contiguous. 123580f940efSHarsha * BIT(2) - to get final hash of the whole updated data. 123680f940efSHarsha * Hash will be overwritten at provided address with 123780f940efSHarsha * 48 bytes. 123880f940efSHarsha * 123980f940efSHarsha * Return: Returns status, either success or error code. 124080f940efSHarsha */ 124180f940efSHarsha int zynqmp_pm_sha_hash(const u64 address, const u32 size, const u32 flags) 124280f940efSHarsha { 124380f940efSHarsha u32 lower_addr = lower_32_bits(address); 124480f940efSHarsha u32 upper_addr = upper_32_bits(address); 124580f940efSHarsha 124680f940efSHarsha return zynqmp_pm_invoke_fn(PM_SECURE_SHA, upper_addr, lower_addr, 124780f940efSHarsha size, flags, NULL); 124880f940efSHarsha } 124980f940efSHarsha EXPORT_SYMBOL_GPL(zynqmp_pm_sha_hash); 125080f940efSHarsha 125180f940efSHarsha /** 12521881eadbSAbhyuday Godhasara * zynqmp_pm_register_notifier() - PM API for register a subsystem 12531881eadbSAbhyuday Godhasara * to be notified about specific 12541881eadbSAbhyuday Godhasara * event/error. 12551881eadbSAbhyuday Godhasara * @node: Node ID to which the event is related. 12561881eadbSAbhyuday Godhasara * @event: Event Mask of Error events for which wants to get notified. 12571881eadbSAbhyuday Godhasara * @wake: Wake subsystem upon capturing the event if value 1 12581881eadbSAbhyuday Godhasara * @enable: Enable the registration for value 1, disable for value 0 12591881eadbSAbhyuday Godhasara * 12601881eadbSAbhyuday Godhasara * This function is used to register/un-register for particular node-event 12611881eadbSAbhyuday Godhasara * combination in firmware. 12621881eadbSAbhyuday Godhasara * 12631881eadbSAbhyuday Godhasara * Return: Returns status, either success or error+reason 12641881eadbSAbhyuday Godhasara */ 12651881eadbSAbhyuday Godhasara 12661881eadbSAbhyuday Godhasara int zynqmp_pm_register_notifier(const u32 node, const u32 event, 12671881eadbSAbhyuday Godhasara const u32 wake, const u32 enable) 12681881eadbSAbhyuday Godhasara { 12691881eadbSAbhyuday Godhasara return zynqmp_pm_invoke_fn(PM_REGISTER_NOTIFIER, node, event, 12701881eadbSAbhyuday Godhasara wake, enable, NULL); 12711881eadbSAbhyuday Godhasara } 12721881eadbSAbhyuday Godhasara EXPORT_SYMBOL_GPL(zynqmp_pm_register_notifier); 12731881eadbSAbhyuday Godhasara 12741881eadbSAbhyuday Godhasara /** 1275fdd2ed88SRajan Vaja * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart 1276fdd2ed88SRajan Vaja * @type: Shutdown or restart? 0 for shutdown, 1 for restart 1277fdd2ed88SRajan Vaja * @subtype: Specifies which system should be restarted or shut down 1278fdd2ed88SRajan Vaja * 1279fdd2ed88SRajan Vaja * Return: Returns status, either success or error+reason 1280fdd2ed88SRajan Vaja */ 1281fdd2ed88SRajan Vaja int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype) 1282fdd2ed88SRajan Vaja { 1283fdd2ed88SRajan Vaja return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype, 1284fdd2ed88SRajan Vaja 0, 0, NULL); 1285fdd2ed88SRajan Vaja } 1286fdd2ed88SRajan Vaja 1287b3ae24c4SRajan Vaja /** 1288f1d0821bSRonak Jain * zynqmp_pm_set_feature_config - PM call to request IOCTL for feature config 1289f1d0821bSRonak Jain * @id: The config ID of the feature to be configured 1290f1d0821bSRonak Jain * @value: The config value of the feature to be configured 1291f1d0821bSRonak Jain * 1292f1d0821bSRonak Jain * Return: Returns 0 on success or error value on failure. 1293f1d0821bSRonak Jain */ 1294f1d0821bSRonak Jain int zynqmp_pm_set_feature_config(enum pm_feature_config_id id, u32 value) 1295f1d0821bSRonak Jain { 1296f1d0821bSRonak Jain return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_FEATURE_CONFIG, 1297f1d0821bSRonak Jain id, value, NULL); 1298f1d0821bSRonak Jain } 1299f1d0821bSRonak Jain 1300f1d0821bSRonak Jain /** 1301f1d0821bSRonak Jain * zynqmp_pm_get_feature_config - PM call to get value of configured feature 1302f1d0821bSRonak Jain * @id: The config id of the feature to be queried 1303f1d0821bSRonak Jain * @payload: Returned value array 1304f1d0821bSRonak Jain * 1305f1d0821bSRonak Jain * Return: Returns 0 on success or error value on failure. 1306f1d0821bSRonak Jain */ 1307f1d0821bSRonak Jain int zynqmp_pm_get_feature_config(enum pm_feature_config_id id, 1308f1d0821bSRonak Jain u32 *payload) 1309f1d0821bSRonak Jain { 1310f1d0821bSRonak Jain return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_FEATURE_CONFIG, 1311f1d0821bSRonak Jain id, 0, payload); 1312f1d0821bSRonak Jain } 1313f1d0821bSRonak Jain 1314f1d0821bSRonak Jain /** 1315*256dea91SRonak Jain * zynqmp_pm_set_sd_config - PM call to set value of SD config registers 1316*256dea91SRonak Jain * @node: SD node ID 1317*256dea91SRonak Jain * @config: The config type of SD registers 1318*256dea91SRonak Jain * @value: Value to be set 1319*256dea91SRonak Jain * 1320*256dea91SRonak Jain * Return: Returns 0 on success or error value on failure. 1321*256dea91SRonak Jain */ 1322*256dea91SRonak Jain int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value) 1323*256dea91SRonak Jain { 1324*256dea91SRonak Jain return zynqmp_pm_invoke_fn(PM_IOCTL, node, IOCTL_SET_SD_CONFIG, 1325*256dea91SRonak Jain config, value, NULL); 1326*256dea91SRonak Jain } 1327*256dea91SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_config); 1328*256dea91SRonak Jain 1329*256dea91SRonak Jain /** 1330*256dea91SRonak Jain * zynqmp_pm_set_gem_config - PM call to set value of GEM config registers 1331*256dea91SRonak Jain * @node: GEM node ID 1332*256dea91SRonak Jain * @config: The config type of GEM registers 1333*256dea91SRonak Jain * @value: Value to be set 1334*256dea91SRonak Jain * 1335*256dea91SRonak Jain * Return: Returns 0 on success or error value on failure. 1336*256dea91SRonak Jain */ 1337*256dea91SRonak Jain int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config, 1338*256dea91SRonak Jain u32 value) 1339*256dea91SRonak Jain { 1340*256dea91SRonak Jain return zynqmp_pm_invoke_fn(PM_IOCTL, node, IOCTL_SET_GEM_CONFIG, 1341*256dea91SRonak Jain config, value, NULL); 1342*256dea91SRonak Jain } 1343*256dea91SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_set_gem_config); 1344*256dea91SRonak Jain 1345*256dea91SRonak Jain /** 1346b3ae24c4SRajan Vaja * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope 1347b3ae24c4SRajan Vaja * @subtype: Shutdown subtype 1348b3ae24c4SRajan Vaja * @name: Matching string for scope argument 1349b3ae24c4SRajan Vaja * 1350b3ae24c4SRajan Vaja * This struct encapsulates mapping between shutdown scope ID and string. 1351b3ae24c4SRajan Vaja */ 1352b3ae24c4SRajan Vaja struct zynqmp_pm_shutdown_scope { 1353b3ae24c4SRajan Vaja const enum zynqmp_pm_shutdown_subtype subtype; 1354b3ae24c4SRajan Vaja const char *name; 1355b3ae24c4SRajan Vaja }; 1356b3ae24c4SRajan Vaja 1357b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = { 1358b3ae24c4SRajan Vaja [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = { 1359b3ae24c4SRajan Vaja .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM, 1360b3ae24c4SRajan Vaja .name = "subsystem", 1361b3ae24c4SRajan Vaja }, 1362b3ae24c4SRajan Vaja [ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = { 1363b3ae24c4SRajan Vaja .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY, 1364b3ae24c4SRajan Vaja .name = "ps_only", 1365b3ae24c4SRajan Vaja }, 1366b3ae24c4SRajan Vaja [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = { 1367b3ae24c4SRajan Vaja .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM, 1368b3ae24c4SRajan Vaja .name = "system", 1369b3ae24c4SRajan Vaja }, 1370b3ae24c4SRajan Vaja }; 1371b3ae24c4SRajan Vaja 1372b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope *selected_scope = 1373b3ae24c4SRajan Vaja &shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM]; 1374b3ae24c4SRajan Vaja 1375b3ae24c4SRajan Vaja /** 1376b3ae24c4SRajan Vaja * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid 1377b3ae24c4SRajan Vaja * @scope_string: Shutdown scope string 1378b3ae24c4SRajan Vaja * 1379b3ae24c4SRajan Vaja * Return: Return pointer to matching shutdown scope struct from 1380b3ae24c4SRajan Vaja * array of available options in system if string is valid, 1381b3ae24c4SRajan Vaja * otherwise returns NULL. 1382b3ae24c4SRajan Vaja */ 1383b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope* 1384b3ae24c4SRajan Vaja zynqmp_pm_is_shutdown_scope_valid(const char *scope_string) 1385b3ae24c4SRajan Vaja { 1386b3ae24c4SRajan Vaja int count; 1387b3ae24c4SRajan Vaja 1388b3ae24c4SRajan Vaja for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++) 1389b3ae24c4SRajan Vaja if (sysfs_streq(scope_string, shutdown_scopes[count].name)) 1390b3ae24c4SRajan Vaja return &shutdown_scopes[count]; 1391b3ae24c4SRajan Vaja 1392b3ae24c4SRajan Vaja return NULL; 1393b3ae24c4SRajan Vaja } 1394b3ae24c4SRajan Vaja 1395b3ae24c4SRajan Vaja static ssize_t shutdown_scope_show(struct device *device, 1396b3ae24c4SRajan Vaja struct device_attribute *attr, 1397b3ae24c4SRajan Vaja char *buf) 1398b3ae24c4SRajan Vaja { 1399b3ae24c4SRajan Vaja int i; 1400b3ae24c4SRajan Vaja 1401b3ae24c4SRajan Vaja for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) { 1402b3ae24c4SRajan Vaja if (&shutdown_scopes[i] == selected_scope) { 1403b3ae24c4SRajan Vaja strcat(buf, "["); 1404b3ae24c4SRajan Vaja strcat(buf, shutdown_scopes[i].name); 1405b3ae24c4SRajan Vaja strcat(buf, "]"); 1406b3ae24c4SRajan Vaja } else { 1407b3ae24c4SRajan Vaja strcat(buf, shutdown_scopes[i].name); 1408b3ae24c4SRajan Vaja } 1409b3ae24c4SRajan Vaja strcat(buf, " "); 1410b3ae24c4SRajan Vaja } 1411b3ae24c4SRajan Vaja strcat(buf, "\n"); 1412b3ae24c4SRajan Vaja 1413b3ae24c4SRajan Vaja return strlen(buf); 1414b3ae24c4SRajan Vaja } 1415b3ae24c4SRajan Vaja 1416b3ae24c4SRajan Vaja static ssize_t shutdown_scope_store(struct device *device, 1417b3ae24c4SRajan Vaja struct device_attribute *attr, 1418b3ae24c4SRajan Vaja const char *buf, size_t count) 1419b3ae24c4SRajan Vaja { 1420b3ae24c4SRajan Vaja int ret; 1421b3ae24c4SRajan Vaja struct zynqmp_pm_shutdown_scope *scope; 1422b3ae24c4SRajan Vaja 1423b3ae24c4SRajan Vaja scope = zynqmp_pm_is_shutdown_scope_valid(buf); 1424b3ae24c4SRajan Vaja if (!scope) 1425b3ae24c4SRajan Vaja return -EINVAL; 1426b3ae24c4SRajan Vaja 1427b3ae24c4SRajan Vaja ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY, 1428b3ae24c4SRajan Vaja scope->subtype); 1429b3ae24c4SRajan Vaja if (ret) { 1430b3ae24c4SRajan Vaja pr_err("unable to set shutdown scope %s\n", buf); 1431b3ae24c4SRajan Vaja return ret; 1432b3ae24c4SRajan Vaja } 1433b3ae24c4SRajan Vaja 1434b3ae24c4SRajan Vaja selected_scope = scope; 1435b3ae24c4SRajan Vaja 1436b3ae24c4SRajan Vaja return count; 1437b3ae24c4SRajan Vaja } 1438b3ae24c4SRajan Vaja 1439b3ae24c4SRajan Vaja static DEVICE_ATTR_RW(shutdown_scope); 1440b3ae24c4SRajan Vaja 1441a2cc220aSRajan Vaja static ssize_t health_status_store(struct device *device, 1442a2cc220aSRajan Vaja struct device_attribute *attr, 1443a2cc220aSRajan Vaja const char *buf, size_t count) 1444a2cc220aSRajan Vaja { 1445a2cc220aSRajan Vaja int ret; 1446a2cc220aSRajan Vaja unsigned int value; 1447a2cc220aSRajan Vaja 1448a2cc220aSRajan Vaja ret = kstrtouint(buf, 10, &value); 1449a2cc220aSRajan Vaja if (ret) 1450a2cc220aSRajan Vaja return ret; 1451a2cc220aSRajan Vaja 1452a2cc220aSRajan Vaja ret = zynqmp_pm_set_boot_health_status(value); 1453a2cc220aSRajan Vaja if (ret) { 1454a2cc220aSRajan Vaja dev_err(device, "unable to set healthy bit value to %u\n", 1455a2cc220aSRajan Vaja value); 1456a2cc220aSRajan Vaja return ret; 1457a2cc220aSRajan Vaja } 1458a2cc220aSRajan Vaja 1459a2cc220aSRajan Vaja return count; 1460a2cc220aSRajan Vaja } 1461a2cc220aSRajan Vaja 1462a2cc220aSRajan Vaja static DEVICE_ATTR_WO(health_status); 1463a2cc220aSRajan Vaja 1464ae5c961dSRajan Vaja static ssize_t ggs_show(struct device *device, 1465ae5c961dSRajan Vaja struct device_attribute *attr, 1466ae5c961dSRajan Vaja char *buf, 1467ae5c961dSRajan Vaja u32 reg) 1468ae5c961dSRajan Vaja { 1469ae5c961dSRajan Vaja int ret; 1470ae5c961dSRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 1471ae5c961dSRajan Vaja 1472ae5c961dSRajan Vaja ret = zynqmp_pm_read_ggs(reg, ret_payload); 1473ae5c961dSRajan Vaja if (ret) 1474ae5c961dSRajan Vaja return ret; 1475ae5c961dSRajan Vaja 1476ae5c961dSRajan Vaja return sprintf(buf, "0x%x\n", ret_payload[1]); 1477ae5c961dSRajan Vaja } 1478ae5c961dSRajan Vaja 1479ae5c961dSRajan Vaja static ssize_t ggs_store(struct device *device, 1480ae5c961dSRajan Vaja struct device_attribute *attr, 1481ae5c961dSRajan Vaja const char *buf, size_t count, 1482ae5c961dSRajan Vaja u32 reg) 1483ae5c961dSRajan Vaja { 1484ae5c961dSRajan Vaja long value; 1485ae5c961dSRajan Vaja int ret; 1486ae5c961dSRajan Vaja 1487ae5c961dSRajan Vaja if (reg >= GSS_NUM_REGS) 1488ae5c961dSRajan Vaja return -EINVAL; 1489ae5c961dSRajan Vaja 1490ae5c961dSRajan Vaja ret = kstrtol(buf, 16, &value); 1491ae5c961dSRajan Vaja if (ret) { 1492ae5c961dSRajan Vaja count = -EFAULT; 1493ae5c961dSRajan Vaja goto err; 1494ae5c961dSRajan Vaja } 1495ae5c961dSRajan Vaja 1496ae5c961dSRajan Vaja ret = zynqmp_pm_write_ggs(reg, value); 1497ae5c961dSRajan Vaja if (ret) 1498ae5c961dSRajan Vaja count = -EFAULT; 1499ae5c961dSRajan Vaja err: 1500ae5c961dSRajan Vaja return count; 1501ae5c961dSRajan Vaja } 1502ae5c961dSRajan Vaja 1503ae5c961dSRajan Vaja /* GGS register show functions */ 1504ae5c961dSRajan Vaja #define GGS0_SHOW(N) \ 1505ae5c961dSRajan Vaja ssize_t ggs##N##_show(struct device *device, \ 1506ae5c961dSRajan Vaja struct device_attribute *attr, \ 1507ae5c961dSRajan Vaja char *buf) \ 1508ae5c961dSRajan Vaja { \ 1509ae5c961dSRajan Vaja return ggs_show(device, attr, buf, N); \ 1510ae5c961dSRajan Vaja } 1511ae5c961dSRajan Vaja 1512ae5c961dSRajan Vaja static GGS0_SHOW(0); 1513ae5c961dSRajan Vaja static GGS0_SHOW(1); 1514ae5c961dSRajan Vaja static GGS0_SHOW(2); 1515ae5c961dSRajan Vaja static GGS0_SHOW(3); 1516ae5c961dSRajan Vaja 1517ae5c961dSRajan Vaja /* GGS register store function */ 1518ae5c961dSRajan Vaja #define GGS0_STORE(N) \ 1519ae5c961dSRajan Vaja ssize_t ggs##N##_store(struct device *device, \ 1520ae5c961dSRajan Vaja struct device_attribute *attr, \ 1521ae5c961dSRajan Vaja const char *buf, \ 1522ae5c961dSRajan Vaja size_t count) \ 1523ae5c961dSRajan Vaja { \ 1524ae5c961dSRajan Vaja return ggs_store(device, attr, buf, count, N); \ 1525ae5c961dSRajan Vaja } 1526ae5c961dSRajan Vaja 1527ae5c961dSRajan Vaja static GGS0_STORE(0); 1528ae5c961dSRajan Vaja static GGS0_STORE(1); 1529ae5c961dSRajan Vaja static GGS0_STORE(2); 1530ae5c961dSRajan Vaja static GGS0_STORE(3); 1531ae5c961dSRajan Vaja 1532ae5c961dSRajan Vaja static ssize_t pggs_show(struct device *device, 1533ae5c961dSRajan Vaja struct device_attribute *attr, 1534ae5c961dSRajan Vaja char *buf, 1535ae5c961dSRajan Vaja u32 reg) 1536ae5c961dSRajan Vaja { 1537ae5c961dSRajan Vaja int ret; 1538ae5c961dSRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 1539ae5c961dSRajan Vaja 1540ae5c961dSRajan Vaja ret = zynqmp_pm_read_pggs(reg, ret_payload); 1541ae5c961dSRajan Vaja if (ret) 1542ae5c961dSRajan Vaja return ret; 1543ae5c961dSRajan Vaja 1544ae5c961dSRajan Vaja return sprintf(buf, "0x%x\n", ret_payload[1]); 1545ae5c961dSRajan Vaja } 1546ae5c961dSRajan Vaja 1547ae5c961dSRajan Vaja static ssize_t pggs_store(struct device *device, 1548ae5c961dSRajan Vaja struct device_attribute *attr, 1549ae5c961dSRajan Vaja const char *buf, size_t count, 1550ae5c961dSRajan Vaja u32 reg) 1551ae5c961dSRajan Vaja { 1552ae5c961dSRajan Vaja long value; 1553ae5c961dSRajan Vaja int ret; 1554ae5c961dSRajan Vaja 1555ae5c961dSRajan Vaja if (reg >= GSS_NUM_REGS) 1556ae5c961dSRajan Vaja return -EINVAL; 1557ae5c961dSRajan Vaja 1558ae5c961dSRajan Vaja ret = kstrtol(buf, 16, &value); 1559ae5c961dSRajan Vaja if (ret) { 1560ae5c961dSRajan Vaja count = -EFAULT; 1561ae5c961dSRajan Vaja goto err; 1562ae5c961dSRajan Vaja } 1563ae5c961dSRajan Vaja 1564ae5c961dSRajan Vaja ret = zynqmp_pm_write_pggs(reg, value); 1565ae5c961dSRajan Vaja if (ret) 1566ae5c961dSRajan Vaja count = -EFAULT; 1567ae5c961dSRajan Vaja 1568ae5c961dSRajan Vaja err: 1569ae5c961dSRajan Vaja return count; 1570ae5c961dSRajan Vaja } 1571ae5c961dSRajan Vaja 1572ae5c961dSRajan Vaja #define PGGS0_SHOW(N) \ 1573ae5c961dSRajan Vaja ssize_t pggs##N##_show(struct device *device, \ 1574ae5c961dSRajan Vaja struct device_attribute *attr, \ 1575ae5c961dSRajan Vaja char *buf) \ 1576ae5c961dSRajan Vaja { \ 1577ae5c961dSRajan Vaja return pggs_show(device, attr, buf, N); \ 1578ae5c961dSRajan Vaja } 1579ae5c961dSRajan Vaja 1580ae5c961dSRajan Vaja #define PGGS0_STORE(N) \ 1581ae5c961dSRajan Vaja ssize_t pggs##N##_store(struct device *device, \ 1582ae5c961dSRajan Vaja struct device_attribute *attr, \ 1583ae5c961dSRajan Vaja const char *buf, \ 1584ae5c961dSRajan Vaja size_t count) \ 1585ae5c961dSRajan Vaja { \ 1586ae5c961dSRajan Vaja return pggs_store(device, attr, buf, count, N); \ 1587ae5c961dSRajan Vaja } 1588ae5c961dSRajan Vaja 1589ae5c961dSRajan Vaja /* PGGS register show functions */ 1590ae5c961dSRajan Vaja static PGGS0_SHOW(0); 1591ae5c961dSRajan Vaja static PGGS0_SHOW(1); 1592ae5c961dSRajan Vaja static PGGS0_SHOW(2); 1593ae5c961dSRajan Vaja static PGGS0_SHOW(3); 1594ae5c961dSRajan Vaja 1595ae5c961dSRajan Vaja /* PGGS register store functions */ 1596ae5c961dSRajan Vaja static PGGS0_STORE(0); 1597ae5c961dSRajan Vaja static PGGS0_STORE(1); 1598ae5c961dSRajan Vaja static PGGS0_STORE(2); 1599ae5c961dSRajan Vaja static PGGS0_STORE(3); 1600ae5c961dSRajan Vaja 1601ae5c961dSRajan Vaja /* GGS register attributes */ 1602ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs0); 1603ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs1); 1604ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs2); 1605ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs3); 1606ae5c961dSRajan Vaja 1607ae5c961dSRajan Vaja /* PGGS register attributes */ 1608ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs0); 1609ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs1); 1610ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs2); 1611ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs3); 1612ae5c961dSRajan Vaja 16132c5d8f7cSRonak Jain static ssize_t feature_config_id_show(struct device *device, 16142c5d8f7cSRonak Jain struct device_attribute *attr, 16152c5d8f7cSRonak Jain char *buf) 16162c5d8f7cSRonak Jain { 16172c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device); 16182c5d8f7cSRonak Jain 16192c5d8f7cSRonak Jain return sysfs_emit(buf, "%d\n", devinfo->feature_conf_id); 16202c5d8f7cSRonak Jain } 16212c5d8f7cSRonak Jain 16222c5d8f7cSRonak Jain static ssize_t feature_config_id_store(struct device *device, 16232c5d8f7cSRonak Jain struct device_attribute *attr, 16242c5d8f7cSRonak Jain const char *buf, size_t count) 16252c5d8f7cSRonak Jain { 16262c5d8f7cSRonak Jain u32 config_id; 16272c5d8f7cSRonak Jain int ret; 16282c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device); 16292c5d8f7cSRonak Jain 16302c5d8f7cSRonak Jain if (!buf) 16312c5d8f7cSRonak Jain return -EINVAL; 16322c5d8f7cSRonak Jain 16332c5d8f7cSRonak Jain ret = kstrtou32(buf, 10, &config_id); 16342c5d8f7cSRonak Jain if (ret) 16352c5d8f7cSRonak Jain return ret; 16362c5d8f7cSRonak Jain 16372c5d8f7cSRonak Jain devinfo->feature_conf_id = config_id; 16382c5d8f7cSRonak Jain 16392c5d8f7cSRonak Jain return count; 16402c5d8f7cSRonak Jain } 16412c5d8f7cSRonak Jain 16422c5d8f7cSRonak Jain static DEVICE_ATTR_RW(feature_config_id); 16432c5d8f7cSRonak Jain 16442c5d8f7cSRonak Jain static ssize_t feature_config_value_show(struct device *device, 16452c5d8f7cSRonak Jain struct device_attribute *attr, 16462c5d8f7cSRonak Jain char *buf) 16472c5d8f7cSRonak Jain { 16482c5d8f7cSRonak Jain int ret; 16492c5d8f7cSRonak Jain u32 ret_payload[PAYLOAD_ARG_CNT]; 16502c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device); 16512c5d8f7cSRonak Jain 16522c5d8f7cSRonak Jain ret = zynqmp_pm_get_feature_config(devinfo->feature_conf_id, 16532c5d8f7cSRonak Jain ret_payload); 16542c5d8f7cSRonak Jain if (ret) 16552c5d8f7cSRonak Jain return ret; 16562c5d8f7cSRonak Jain 16572c5d8f7cSRonak Jain return sysfs_emit(buf, "%d\n", ret_payload[1]); 16582c5d8f7cSRonak Jain } 16592c5d8f7cSRonak Jain 16602c5d8f7cSRonak Jain static ssize_t feature_config_value_store(struct device *device, 16612c5d8f7cSRonak Jain struct device_attribute *attr, 16622c5d8f7cSRonak Jain const char *buf, size_t count) 16632c5d8f7cSRonak Jain { 16642c5d8f7cSRonak Jain u32 value; 16652c5d8f7cSRonak Jain int ret; 16662c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device); 16672c5d8f7cSRonak Jain 16682c5d8f7cSRonak Jain if (!buf) 16692c5d8f7cSRonak Jain return -EINVAL; 16702c5d8f7cSRonak Jain 16712c5d8f7cSRonak Jain ret = kstrtou32(buf, 10, &value); 16722c5d8f7cSRonak Jain if (ret) 16732c5d8f7cSRonak Jain return ret; 16742c5d8f7cSRonak Jain 16752c5d8f7cSRonak Jain ret = zynqmp_pm_set_feature_config(devinfo->feature_conf_id, 16762c5d8f7cSRonak Jain value); 16772c5d8f7cSRonak Jain if (ret) 16782c5d8f7cSRonak Jain return ret; 16792c5d8f7cSRonak Jain 16802c5d8f7cSRonak Jain return count; 16812c5d8f7cSRonak Jain } 16822c5d8f7cSRonak Jain 16832c5d8f7cSRonak Jain static DEVICE_ATTR_RW(feature_config_value); 16842c5d8f7cSRonak Jain 1685ae5c961dSRajan Vaja static struct attribute *zynqmp_firmware_attrs[] = { 1686ae5c961dSRajan Vaja &dev_attr_ggs0.attr, 1687ae5c961dSRajan Vaja &dev_attr_ggs1.attr, 1688ae5c961dSRajan Vaja &dev_attr_ggs2.attr, 1689ae5c961dSRajan Vaja &dev_attr_ggs3.attr, 1690ae5c961dSRajan Vaja &dev_attr_pggs0.attr, 1691ae5c961dSRajan Vaja &dev_attr_pggs1.attr, 1692ae5c961dSRajan Vaja &dev_attr_pggs2.attr, 1693ae5c961dSRajan Vaja &dev_attr_pggs3.attr, 1694b3ae24c4SRajan Vaja &dev_attr_shutdown_scope.attr, 1695a2cc220aSRajan Vaja &dev_attr_health_status.attr, 16962c5d8f7cSRonak Jain &dev_attr_feature_config_id.attr, 16972c5d8f7cSRonak Jain &dev_attr_feature_config_value.attr, 1698ae5c961dSRajan Vaja NULL, 1699ae5c961dSRajan Vaja }; 1700ae5c961dSRajan Vaja 1701ae5c961dSRajan Vaja ATTRIBUTE_GROUPS(zynqmp_firmware); 1702ae5c961dSRajan Vaja 170376582671SRajan Vaja static int zynqmp_firmware_probe(struct platform_device *pdev) 170476582671SRajan Vaja { 170576582671SRajan Vaja struct device *dev = &pdev->dev; 170676582671SRajan Vaja struct device_node *np; 17072c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo; 170876582671SRajan Vaja int ret; 170976582671SRajan Vaja 1710e5052becSRonak Jain ret = get_set_conduit_method(dev->of_node); 1711e5052becSRonak Jain if (ret) 1712e5052becSRonak Jain return ret; 1713e5052becSRonak Jain 171476582671SRajan Vaja np = of_find_compatible_node(NULL, NULL, "xlnx,zynqmp"); 1715af3f1afaSJolly Shah if (!np) { 1716af3f1afaSJolly Shah np = of_find_compatible_node(NULL, NULL, "xlnx,versal"); 171776582671SRajan Vaja if (!np) 171876582671SRajan Vaja return 0; 1719461011b1SRavi Patel 1720461011b1SRavi Patel feature_check_enabled = true; 1721af3f1afaSJolly Shah } 172276582671SRajan Vaja 1723e5052becSRonak Jain if (!feature_check_enabled) { 1724e5052becSRonak Jain ret = do_feature_check_call(PM_FEATURE_CHECK); 1725e5052becSRonak Jain if (ret >= 0) 1726e5052becSRonak Jain feature_check_enabled = true; 1727e5052becSRonak Jain } 1728e5052becSRonak Jain 1729e5052becSRonak Jain of_node_put(np); 173076582671SRajan Vaja 17312c5d8f7cSRonak Jain devinfo = devm_kzalloc(dev, sizeof(*devinfo), GFP_KERNEL); 17322c5d8f7cSRonak Jain if (!devinfo) 17332c5d8f7cSRonak Jain return -ENOMEM; 17342c5d8f7cSRonak Jain 17352c5d8f7cSRonak Jain devinfo->dev = dev; 17362c5d8f7cSRonak Jain 17372c5d8f7cSRonak Jain platform_set_drvdata(pdev, devinfo); 17382c5d8f7cSRonak Jain 173976582671SRajan Vaja /* Check PM API version number */ 1740168e05c1SRajan Vaja ret = zynqmp_pm_get_api_version(&pm_api_version); 1741168e05c1SRajan Vaja if (ret) 1742168e05c1SRajan Vaja return ret; 1743168e05c1SRajan Vaja 174476582671SRajan Vaja if (pm_api_version < ZYNQMP_PM_VERSION) { 174576582671SRajan Vaja panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n", 174676582671SRajan Vaja __func__, 174776582671SRajan Vaja ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR, 174876582671SRajan Vaja pm_api_version >> 16, pm_api_version & 0xFFFF); 174976582671SRajan Vaja } 175076582671SRajan Vaja 175176582671SRajan Vaja pr_info("%s Platform Management API v%d.%d\n", __func__, 175276582671SRajan Vaja pm_api_version >> 16, pm_api_version & 0xFFFF); 175376582671SRajan Vaja 175476582671SRajan Vaja /* Check trustzone version number */ 175576582671SRajan Vaja ret = zynqmp_pm_get_trustzone_version(&pm_tz_version); 175676582671SRajan Vaja if (ret) 175776582671SRajan Vaja panic("Legacy trustzone found without version support\n"); 175876582671SRajan Vaja 175976582671SRajan Vaja if (pm_tz_version < ZYNQMP_TZ_VERSION) 176076582671SRajan Vaja panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n", 176176582671SRajan Vaja __func__, 176276582671SRajan Vaja ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR, 176376582671SRajan Vaja pm_tz_version >> 16, pm_tz_version & 0xFFFF); 176476582671SRajan Vaja 176576582671SRajan Vaja pr_info("%s Trustzone version v%d.%d\n", __func__, 176676582671SRajan Vaja pm_tz_version >> 16, pm_tz_version & 0xFFFF); 176776582671SRajan Vaja 1768e23d9c6dSJolly Shah ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs, 1769e23d9c6dSJolly Shah ARRAY_SIZE(firmware_devs), NULL, 0, NULL); 1770e23d9c6dSJolly Shah if (ret) { 1771e23d9c6dSJolly Shah dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret); 1772e23d9c6dSJolly Shah return ret; 1773e23d9c6dSJolly Shah } 1774e23d9c6dSJolly Shah 177565f0539bSChristophe JAILLET zynqmp_pm_api_debugfs_init(); 177665f0539bSChristophe JAILLET 1777a515814eSAbhyuday Godhasara np = of_find_compatible_node(NULL, NULL, "xlnx,versal"); 1778a515814eSAbhyuday Godhasara if (np) { 1779a515814eSAbhyuday Godhasara em_dev = platform_device_register_data(&pdev->dev, "xlnx_event_manager", 1780a515814eSAbhyuday Godhasara -1, NULL, 0); 1781a515814eSAbhyuday Godhasara if (IS_ERR(em_dev)) 1782a515814eSAbhyuday Godhasara dev_err_probe(&pdev->dev, PTR_ERR(em_dev), "EM register fail with error\n"); 1783a515814eSAbhyuday Godhasara } 1784a515814eSAbhyuday Godhasara of_node_put(np); 1785a515814eSAbhyuday Godhasara 178676582671SRajan Vaja return of_platform_populate(dev->of_node, NULL, NULL, dev); 178776582671SRajan Vaja } 178876582671SRajan Vaja 178976582671SRajan Vaja static int zynqmp_firmware_remove(struct platform_device *pdev) 179076582671SRajan Vaja { 1791acfdd185SAmit Sunil Dhamne struct pm_api_feature_data *feature_data; 1792f1f21becSTejas Patel struct hlist_node *tmp; 1793acfdd185SAmit Sunil Dhamne int i; 1794acfdd185SAmit Sunil Dhamne 1795e23d9c6dSJolly Shah mfd_remove_devices(&pdev->dev); 1796b3217252SRajan Vaja zynqmp_pm_api_debugfs_exit(); 1797b3217252SRajan Vaja 1798f1f21becSTejas Patel hash_for_each_safe(pm_api_features_map, i, tmp, feature_data, hentry) { 1799acfdd185SAmit Sunil Dhamne hash_del(&feature_data->hentry); 1800acfdd185SAmit Sunil Dhamne kfree(feature_data); 1801acfdd185SAmit Sunil Dhamne } 1802acfdd185SAmit Sunil Dhamne 1803a515814eSAbhyuday Godhasara platform_device_unregister(em_dev); 1804a515814eSAbhyuday Godhasara 180576582671SRajan Vaja return 0; 180676582671SRajan Vaja } 180776582671SRajan Vaja 180876582671SRajan Vaja static const struct of_device_id zynqmp_firmware_of_match[] = { 180976582671SRajan Vaja {.compatible = "xlnx,zynqmp-firmware"}, 1810af3f1afaSJolly Shah {.compatible = "xlnx,versal-firmware"}, 181176582671SRajan Vaja {}, 181276582671SRajan Vaja }; 181376582671SRajan Vaja MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match); 181476582671SRajan Vaja 181576582671SRajan Vaja static struct platform_driver zynqmp_firmware_driver = { 181676582671SRajan Vaja .driver = { 181776582671SRajan Vaja .name = "zynqmp_firmware", 181876582671SRajan Vaja .of_match_table = zynqmp_firmware_of_match, 1819ae5c961dSRajan Vaja .dev_groups = zynqmp_firmware_groups, 182076582671SRajan Vaja }, 182176582671SRajan Vaja .probe = zynqmp_firmware_probe, 182276582671SRajan Vaja .remove = zynqmp_firmware_remove, 182376582671SRajan Vaja }; 182476582671SRajan Vaja module_platform_driver(zynqmp_firmware_driver); 1825