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 846*1e400cb9SRajan Vaja int zynqmp_pm_set_tapdelay_bypass(u32 index, u32 value) 847*1e400cb9SRajan Vaja { 848*1e400cb9SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_TAPDELAY_BYPASS, 849*1e400cb9SRajan Vaja index, value, NULL); 850*1e400cb9SRajan Vaja } 851*1e400cb9SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_tapdelay_bypass); 852*1e400cb9SRajan Vaja 8534f680b72SRajan Vaja /** 854a2cc220aSRajan Vaja * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status 855332bee16SMichal Simek * @value: Status value to be written 856a2cc220aSRajan Vaja * 857a2cc220aSRajan Vaja * This function sets healthy bit value to indicate boot health status 858a2cc220aSRajan Vaja * to firmware. 859a2cc220aSRajan Vaja * 860332bee16SMichal Simek * Return: Returns status, either success or error+reason 861a2cc220aSRajan Vaja */ 862a2cc220aSRajan Vaja int zynqmp_pm_set_boot_health_status(u32 value) 863a2cc220aSRajan Vaja { 864a2cc220aSRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_BOOT_HEALTH_STATUS, 865a2cc220aSRajan Vaja value, 0, NULL); 866a2cc220aSRajan Vaja } 867a2cc220aSRajan Vaja 868a2cc220aSRajan Vaja /** 869bc3843d4SNava kishore Manne * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release) 870bc3843d4SNava kishore Manne * @reset: Reset to be configured 871bc3843d4SNava kishore Manne * @assert_flag: Flag stating should reset be asserted (1) or 872bc3843d4SNava kishore Manne * released (0) 873bc3843d4SNava kishore Manne * 874bc3843d4SNava kishore Manne * Return: Returns status, either success or error+reason 875bc3843d4SNava kishore Manne */ 876cf23ec35SRajan Vaja int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset, 877bc3843d4SNava kishore Manne const enum zynqmp_pm_reset_action assert_flag) 878bc3843d4SNava kishore Manne { 879bc3843d4SNava kishore Manne return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag, 880bc3843d4SNava kishore Manne 0, 0, NULL); 881bc3843d4SNava kishore Manne } 882cf23ec35SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert); 883bc3843d4SNava kishore Manne 884bc3843d4SNava kishore Manne /** 885bc3843d4SNava kishore Manne * zynqmp_pm_reset_get_status - Get status of the reset 886bc3843d4SNava kishore Manne * @reset: Reset whose status should be returned 887bc3843d4SNava kishore Manne * @status: Returned status 888bc3843d4SNava kishore Manne * 889bc3843d4SNava kishore Manne * Return: Returns status, either success or error+reason 890bc3843d4SNava kishore Manne */ 8911b413581SRajan Vaja int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status) 892bc3843d4SNava kishore Manne { 893bc3843d4SNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT]; 894bc3843d4SNava kishore Manne int ret; 895bc3843d4SNava kishore Manne 896bc3843d4SNava kishore Manne if (!status) 897bc3843d4SNava kishore Manne return -EINVAL; 898bc3843d4SNava kishore Manne 899bc3843d4SNava kishore Manne ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0, 900bc3843d4SNava kishore Manne 0, 0, ret_payload); 901bc3843d4SNava kishore Manne *status = ret_payload[1]; 902bc3843d4SNava kishore Manne 903bc3843d4SNava kishore Manne return ret; 904bc3843d4SNava kishore Manne } 9051b413581SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status); 906bc3843d4SNava kishore Manne 907e178df31SJolly Shah /** 908e840deccSNava kishore Manne * zynqmp_pm_fpga_load - Perform the fpga load 909e840deccSNava kishore Manne * @address: Address to write to 910e840deccSNava kishore Manne * @size: pl bitstream size 911e840deccSNava kishore Manne * @flags: Bitstream type 912e840deccSNava kishore Manne * -XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration 913e840deccSNava kishore Manne * -XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration 914e840deccSNava kishore Manne * 915e840deccSNava kishore Manne * This function provides access to pmufw. To transfer 916e840deccSNava kishore Manne * the required bitstream into PL. 917e840deccSNava kishore Manne * 918e840deccSNava kishore Manne * Return: Returns status, either success or error+reason 919e840deccSNava kishore Manne */ 9204db8180fSRajan Vaja int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags) 921e840deccSNava kishore Manne { 922e840deccSNava kishore Manne return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address), 923e840deccSNava kishore Manne upper_32_bits(address), size, flags, NULL); 924e840deccSNava kishore Manne } 92556a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load); 926e840deccSNava kishore Manne 927e840deccSNava kishore Manne /** 928e840deccSNava kishore Manne * zynqmp_pm_fpga_get_status - Read value from PCAP status register 929e840deccSNava kishore Manne * @value: Value to read 930e840deccSNava kishore Manne * 931e840deccSNava kishore Manne * This function provides access to the pmufw to get the PCAP 932e840deccSNava kishore Manne * status 933e840deccSNava kishore Manne * 934e840deccSNava kishore Manne * Return: Returns status, either success or error+reason 935e840deccSNava kishore Manne */ 9364db8180fSRajan Vaja int zynqmp_pm_fpga_get_status(u32 *value) 937e840deccSNava kishore Manne { 938e840deccSNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT]; 939e840deccSNava kishore Manne int ret; 940e840deccSNava kishore Manne 941e840deccSNava kishore Manne if (!value) 942e840deccSNava kishore Manne return -EINVAL; 943e840deccSNava kishore Manne 944e840deccSNava kishore Manne ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload); 945e840deccSNava kishore Manne *value = ret_payload[1]; 946e840deccSNava kishore Manne 947e840deccSNava kishore Manne return ret; 948e840deccSNava kishore Manne } 94956a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status); 950e840deccSNava kishore Manne 951e840deccSNava kishore Manne /** 952fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_request - Request Pin from firmware 953fa989ae7SSai Krishna Potthuri * @pin: Pin number to request 954fa989ae7SSai Krishna Potthuri * 955fa989ae7SSai Krishna Potthuri * This function requests pin from firmware. 956fa989ae7SSai Krishna Potthuri * 957fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason. 958fa989ae7SSai Krishna Potthuri */ 959fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_request(const u32 pin) 960fa989ae7SSai Krishna Potthuri { 961fa989ae7SSai Krishna Potthuri return zynqmp_pm_invoke_fn(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL); 962fa989ae7SSai Krishna Potthuri } 963fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_request); 964fa989ae7SSai Krishna Potthuri 965fa989ae7SSai Krishna Potthuri /** 966fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_release - Inform firmware that Pin control is released 967fa989ae7SSai Krishna Potthuri * @pin: Pin number to release 968fa989ae7SSai Krishna Potthuri * 969fa989ae7SSai Krishna Potthuri * This function release pin from firmware. 970fa989ae7SSai Krishna Potthuri * 971fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason. 972fa989ae7SSai Krishna Potthuri */ 973fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_release(const u32 pin) 974fa989ae7SSai Krishna Potthuri { 975fa989ae7SSai Krishna Potthuri return zynqmp_pm_invoke_fn(PM_PINCTRL_RELEASE, pin, 0, 0, 0, NULL); 976fa989ae7SSai Krishna Potthuri } 977fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_release); 978fa989ae7SSai Krishna Potthuri 979fa989ae7SSai Krishna Potthuri /** 980fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_get_function - Read function id set for the given pin 981fa989ae7SSai Krishna Potthuri * @pin: Pin number 982fa989ae7SSai Krishna Potthuri * @id: Buffer to store function ID 983fa989ae7SSai Krishna Potthuri * 984fa989ae7SSai Krishna Potthuri * This function provides the function currently set for the given pin. 985fa989ae7SSai Krishna Potthuri * 986fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason 987fa989ae7SSai Krishna Potthuri */ 988fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_get_function(const u32 pin, u32 *id) 989fa989ae7SSai Krishna Potthuri { 990fa989ae7SSai Krishna Potthuri u32 ret_payload[PAYLOAD_ARG_CNT]; 991fa989ae7SSai Krishna Potthuri int ret; 992fa989ae7SSai Krishna Potthuri 993fa989ae7SSai Krishna Potthuri if (!id) 994fa989ae7SSai Krishna Potthuri return -EINVAL; 995fa989ae7SSai Krishna Potthuri 996fa989ae7SSai Krishna Potthuri ret = zynqmp_pm_invoke_fn(PM_PINCTRL_GET_FUNCTION, pin, 0, 997fa989ae7SSai Krishna Potthuri 0, 0, ret_payload); 998fa989ae7SSai Krishna Potthuri *id = ret_payload[1]; 999fa989ae7SSai Krishna Potthuri 1000fa989ae7SSai Krishna Potthuri return ret; 1001fa989ae7SSai Krishna Potthuri } 1002fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_function); 1003fa989ae7SSai Krishna Potthuri 1004fa989ae7SSai Krishna Potthuri /** 1005fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_set_function - Set requested function for the pin 1006fa989ae7SSai Krishna Potthuri * @pin: Pin number 1007fa989ae7SSai Krishna Potthuri * @id: Function ID to set 1008fa989ae7SSai Krishna Potthuri * 1009fa989ae7SSai Krishna Potthuri * This function sets requested function for the given pin. 1010fa989ae7SSai Krishna Potthuri * 1011fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason. 1012fa989ae7SSai Krishna Potthuri */ 1013fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id) 1014fa989ae7SSai Krishna Potthuri { 1015fa989ae7SSai Krishna Potthuri return zynqmp_pm_invoke_fn(PM_PINCTRL_SET_FUNCTION, pin, id, 1016fa989ae7SSai Krishna Potthuri 0, 0, NULL); 1017fa989ae7SSai Krishna Potthuri } 1018fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_function); 1019fa989ae7SSai Krishna Potthuri 1020fa989ae7SSai Krishna Potthuri /** 1021fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_get_config - Get configuration parameter for the pin 1022fa989ae7SSai Krishna Potthuri * @pin: Pin number 1023fa989ae7SSai Krishna Potthuri * @param: Parameter to get 1024fa989ae7SSai Krishna Potthuri * @value: Buffer to store parameter value 1025fa989ae7SSai Krishna Potthuri * 1026fa989ae7SSai Krishna Potthuri * This function gets requested configuration parameter for the given pin. 1027fa989ae7SSai Krishna Potthuri * 1028fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason. 1029fa989ae7SSai Krishna Potthuri */ 1030fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param, 1031fa989ae7SSai Krishna Potthuri u32 *value) 1032fa989ae7SSai Krishna Potthuri { 1033fa989ae7SSai Krishna Potthuri u32 ret_payload[PAYLOAD_ARG_CNT]; 1034fa989ae7SSai Krishna Potthuri int ret; 1035fa989ae7SSai Krishna Potthuri 1036fa989ae7SSai Krishna Potthuri if (!value) 1037fa989ae7SSai Krishna Potthuri return -EINVAL; 1038fa989ae7SSai Krishna Potthuri 1039fa989ae7SSai Krishna Potthuri ret = zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_GET, pin, param, 1040fa989ae7SSai Krishna Potthuri 0, 0, ret_payload); 1041fa989ae7SSai Krishna Potthuri *value = ret_payload[1]; 1042fa989ae7SSai Krishna Potthuri 1043fa989ae7SSai Krishna Potthuri return ret; 1044fa989ae7SSai Krishna Potthuri } 1045fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_config); 1046fa989ae7SSai Krishna Potthuri 1047fa989ae7SSai Krishna Potthuri /** 1048fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_set_config - Set configuration parameter for the pin 1049fa989ae7SSai Krishna Potthuri * @pin: Pin number 1050fa989ae7SSai Krishna Potthuri * @param: Parameter to set 1051fa989ae7SSai Krishna Potthuri * @value: Parameter value to set 1052fa989ae7SSai Krishna Potthuri * 1053fa989ae7SSai Krishna Potthuri * This function sets requested configuration parameter for the given pin. 1054fa989ae7SSai Krishna Potthuri * 1055fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason. 1056fa989ae7SSai Krishna Potthuri */ 1057fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param, 1058fa989ae7SSai Krishna Potthuri u32 value) 1059fa989ae7SSai Krishna Potthuri { 1060fa989ae7SSai Krishna Potthuri return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, pin, 1061fa989ae7SSai Krishna Potthuri param, value, 0, NULL); 1062fa989ae7SSai Krishna Potthuri } 1063fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_config); 1064fa989ae7SSai Krishna Potthuri 1065fa989ae7SSai Krishna Potthuri /** 106623c64d76SPiyush Mehta * zynqmp_pm_bootmode_read() - PM Config API for read bootpin status 106723c64d76SPiyush Mehta * @ps_mode: Returned output value of ps_mode 106823c64d76SPiyush Mehta * 106923c64d76SPiyush Mehta * This API function is to be used for notify the power management controller 107023c64d76SPiyush Mehta * to read bootpin status. 107123c64d76SPiyush Mehta * 107223c64d76SPiyush Mehta * Return: status, either success or error+reason 107323c64d76SPiyush Mehta */ 107423c64d76SPiyush Mehta unsigned int zynqmp_pm_bootmode_read(u32 *ps_mode) 107523c64d76SPiyush Mehta { 107623c64d76SPiyush Mehta unsigned int ret; 107723c64d76SPiyush Mehta u32 ret_payload[PAYLOAD_ARG_CNT]; 107823c64d76SPiyush Mehta 107923c64d76SPiyush Mehta ret = zynqmp_pm_invoke_fn(PM_MMIO_READ, CRL_APB_BOOT_PIN_CTRL, 0, 108023c64d76SPiyush Mehta 0, 0, ret_payload); 108123c64d76SPiyush Mehta 108223c64d76SPiyush Mehta *ps_mode = ret_payload[1]; 108323c64d76SPiyush Mehta 108423c64d76SPiyush Mehta return ret; 108523c64d76SPiyush Mehta } 108623c64d76SPiyush Mehta EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_read); 108723c64d76SPiyush Mehta 108823c64d76SPiyush Mehta /** 108923c64d76SPiyush Mehta * zynqmp_pm_bootmode_write() - PM Config API for Configure bootpin 109023c64d76SPiyush Mehta * @ps_mode: Value to be written to the bootpin ctrl register 109123c64d76SPiyush Mehta * 109223c64d76SPiyush Mehta * This API function is to be used for notify the power management controller 109323c64d76SPiyush Mehta * to configure bootpin. 109423c64d76SPiyush Mehta * 109523c64d76SPiyush Mehta * Return: Returns status, either success or error+reason 109623c64d76SPiyush Mehta */ 109723c64d76SPiyush Mehta int zynqmp_pm_bootmode_write(u32 ps_mode) 109823c64d76SPiyush Mehta { 109923c64d76SPiyush Mehta return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, CRL_APB_BOOT_PIN_CTRL, 110023c64d76SPiyush Mehta CRL_APB_BOOTPIN_CTRL_MASK, ps_mode, 0, NULL); 110123c64d76SPiyush Mehta } 110223c64d76SPiyush Mehta EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_write); 110323c64d76SPiyush Mehta 110423c64d76SPiyush Mehta /** 1105e178df31SJolly Shah * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller 1106e178df31SJolly Shah * master has initialized its own power management 1107e178df31SJolly Shah * 1108332bee16SMichal Simek * Return: Returns status, either success or error+reason 1109332bee16SMichal Simek * 1110e178df31SJolly Shah * This API function is to be used for notify the power management controller 1111e178df31SJolly Shah * about the completed power management initialization. 1112e178df31SJolly Shah */ 11139474da95SRajan Vaja int zynqmp_pm_init_finalize(void) 1114e178df31SJolly Shah { 1115e178df31SJolly Shah return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL); 1116e178df31SJolly Shah } 11179474da95SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_init_finalize); 1118e178df31SJolly Shah 1119e178df31SJolly Shah /** 1120e178df31SJolly Shah * zynqmp_pm_set_suspend_mode() - Set system suspend mode 1121e178df31SJolly Shah * @mode: Mode to set for system suspend 1122e178df31SJolly Shah * 1123e178df31SJolly Shah * This API function is used to set mode of system suspend. 1124e178df31SJolly Shah * 1125e178df31SJolly Shah * Return: Returns status, either success or error+reason 1126e178df31SJolly Shah */ 1127951d0a97SRajan Vaja int zynqmp_pm_set_suspend_mode(u32 mode) 1128e178df31SJolly Shah { 1129e178df31SJolly Shah return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL); 1130e178df31SJolly Shah } 1131951d0a97SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode); 1132e178df31SJolly Shah 1133c1986ac3SRajan Vaja /** 1134c1986ac3SRajan Vaja * zynqmp_pm_request_node() - Request a node with specific capabilities 1135c1986ac3SRajan Vaja * @node: Node ID of the slave 1136c1986ac3SRajan Vaja * @capabilities: Requested capabilities of the slave 1137c1986ac3SRajan Vaja * @qos: Quality of service (not supported) 1138c1986ac3SRajan Vaja * @ack: Flag to specify whether acknowledge is requested 1139c1986ac3SRajan Vaja * 1140c1986ac3SRajan Vaja * This function is used by master to request particular node from firmware. 1141c1986ac3SRajan Vaja * Every master must request node before using it. 1142c1986ac3SRajan Vaja * 1143c1986ac3SRajan Vaja * Return: Returns status, either success or error+reason 1144c1986ac3SRajan Vaja */ 1145bf8b27edSRajan Vaja int zynqmp_pm_request_node(const u32 node, const u32 capabilities, 1146bf8b27edSRajan Vaja const u32 qos, const enum zynqmp_pm_request_ack ack) 1147c1986ac3SRajan Vaja { 1148c1986ac3SRajan Vaja return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities, 1149c1986ac3SRajan Vaja qos, ack, NULL); 1150c1986ac3SRajan Vaja } 1151bf8b27edSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_request_node); 1152c1986ac3SRajan Vaja 1153c1986ac3SRajan Vaja /** 1154c1986ac3SRajan Vaja * zynqmp_pm_release_node() - Release a node 1155c1986ac3SRajan Vaja * @node: Node ID of the slave 1156c1986ac3SRajan Vaja * 1157c1986ac3SRajan Vaja * This function is used by master to inform firmware that master 1158c1986ac3SRajan Vaja * has released node. Once released, master must not use that node 1159c1986ac3SRajan Vaja * without re-request. 1160c1986ac3SRajan Vaja * 1161c1986ac3SRajan Vaja * Return: Returns status, either success or error+reason 1162c1986ac3SRajan Vaja */ 116307fb1a46SRajan Vaja int zynqmp_pm_release_node(const u32 node) 1164c1986ac3SRajan Vaja { 1165c1986ac3SRajan Vaja return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL); 1166c1986ac3SRajan Vaja } 116707fb1a46SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_release_node); 1168c1986ac3SRajan Vaja 1169c1986ac3SRajan Vaja /** 1170c1986ac3SRajan Vaja * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves 1171c1986ac3SRajan Vaja * @node: Node ID of the slave 1172c1986ac3SRajan Vaja * @capabilities: Requested capabilities of the slave 1173c1986ac3SRajan Vaja * @qos: Quality of service (not supported) 1174c1986ac3SRajan Vaja * @ack: Flag to specify whether acknowledge is requested 1175c1986ac3SRajan Vaja * 1176c1986ac3SRajan Vaja * This API function is to be used for slaves a PU already has requested 1177c1986ac3SRajan Vaja * to change its capabilities. 1178c1986ac3SRajan Vaja * 1179c1986ac3SRajan Vaja * Return: Returns status, either success or error+reason 1180c1986ac3SRajan Vaja */ 1181cbbbda71SRajan Vaja int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities, 1182c1986ac3SRajan Vaja const u32 qos, 1183c1986ac3SRajan Vaja const enum zynqmp_pm_request_ack ack) 1184c1986ac3SRajan Vaja { 1185c1986ac3SRajan Vaja return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities, 1186c1986ac3SRajan Vaja qos, ack, NULL); 1187c1986ac3SRajan Vaja } 1188cbbbda71SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement); 1189c1986ac3SRajan Vaja 1190057a0fb6SKalyani Akula /** 11912b9fc773SNava kishore Manne * zynqmp_pm_load_pdi - Load and process PDI 11922b9fc773SNava kishore Manne * @src: Source device where PDI is located 11932b9fc773SNava kishore Manne * @address: PDI src address 11942b9fc773SNava kishore Manne * 11952b9fc773SNava kishore Manne * This function provides support to load PDI from linux 11962b9fc773SNava kishore Manne * 11972b9fc773SNava kishore Manne * Return: Returns status, either success or error+reason 11982b9fc773SNava kishore Manne */ 11992b9fc773SNava kishore Manne int zynqmp_pm_load_pdi(const u32 src, const u64 address) 12002b9fc773SNava kishore Manne { 12012b9fc773SNava kishore Manne return zynqmp_pm_invoke_fn(PM_LOAD_PDI, src, 12022b9fc773SNava kishore Manne lower_32_bits(address), 12032b9fc773SNava kishore Manne upper_32_bits(address), 0, NULL); 12042b9fc773SNava kishore Manne } 12052b9fc773SNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_load_pdi); 12062b9fc773SNava kishore Manne 12072b9fc773SNava kishore Manne /** 12082a8faf8dSMichal Simek * zynqmp_pm_aes_engine - Access AES hardware to encrypt/decrypt the data using 1209057a0fb6SKalyani Akula * AES-GCM core. 1210057a0fb6SKalyani Akula * @address: Address of the AesParams structure. 1211057a0fb6SKalyani Akula * @out: Returned output value 1212057a0fb6SKalyani Akula * 1213057a0fb6SKalyani Akula * Return: Returns status, either success or error code. 1214057a0fb6SKalyani Akula */ 1215bc86f9c5SRajan Vaja int zynqmp_pm_aes_engine(const u64 address, u32 *out) 1216057a0fb6SKalyani Akula { 1217057a0fb6SKalyani Akula u32 ret_payload[PAYLOAD_ARG_CNT]; 1218057a0fb6SKalyani Akula int ret; 1219057a0fb6SKalyani Akula 1220057a0fb6SKalyani Akula if (!out) 1221057a0fb6SKalyani Akula return -EINVAL; 1222057a0fb6SKalyani Akula 1223057a0fb6SKalyani Akula ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, upper_32_bits(address), 1224057a0fb6SKalyani Akula lower_32_bits(address), 1225057a0fb6SKalyani Akula 0, 0, ret_payload); 1226057a0fb6SKalyani Akula *out = ret_payload[1]; 1227057a0fb6SKalyani Akula 1228057a0fb6SKalyani Akula return ret; 1229057a0fb6SKalyani Akula } 1230bc86f9c5SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine); 1231057a0fb6SKalyani Akula 1232fdd2ed88SRajan Vaja /** 123380f940efSHarsha * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash 123480f940efSHarsha * @address: Address of the data/ Address of output buffer where 123580f940efSHarsha * hash should be stored. 123680f940efSHarsha * @size: Size of the data. 123780f940efSHarsha * @flags: 123880f940efSHarsha * BIT(0) - for initializing csudma driver and SHA3(Here address 123980f940efSHarsha * and size inputs can be NULL). 124080f940efSHarsha * BIT(1) - to call Sha3_Update API which can be called multiple 124180f940efSHarsha * times when data is not contiguous. 124280f940efSHarsha * BIT(2) - to get final hash of the whole updated data. 124380f940efSHarsha * Hash will be overwritten at provided address with 124480f940efSHarsha * 48 bytes. 124580f940efSHarsha * 124680f940efSHarsha * Return: Returns status, either success or error code. 124780f940efSHarsha */ 124880f940efSHarsha int zynqmp_pm_sha_hash(const u64 address, const u32 size, const u32 flags) 124980f940efSHarsha { 125080f940efSHarsha u32 lower_addr = lower_32_bits(address); 125180f940efSHarsha u32 upper_addr = upper_32_bits(address); 125280f940efSHarsha 125380f940efSHarsha return zynqmp_pm_invoke_fn(PM_SECURE_SHA, upper_addr, lower_addr, 125480f940efSHarsha size, flags, NULL); 125580f940efSHarsha } 125680f940efSHarsha EXPORT_SYMBOL_GPL(zynqmp_pm_sha_hash); 125780f940efSHarsha 125880f940efSHarsha /** 12591881eadbSAbhyuday Godhasara * zynqmp_pm_register_notifier() - PM API for register a subsystem 12601881eadbSAbhyuday Godhasara * to be notified about specific 12611881eadbSAbhyuday Godhasara * event/error. 12621881eadbSAbhyuday Godhasara * @node: Node ID to which the event is related. 12631881eadbSAbhyuday Godhasara * @event: Event Mask of Error events for which wants to get notified. 12641881eadbSAbhyuday Godhasara * @wake: Wake subsystem upon capturing the event if value 1 12651881eadbSAbhyuday Godhasara * @enable: Enable the registration for value 1, disable for value 0 12661881eadbSAbhyuday Godhasara * 12671881eadbSAbhyuday Godhasara * This function is used to register/un-register for particular node-event 12681881eadbSAbhyuday Godhasara * combination in firmware. 12691881eadbSAbhyuday Godhasara * 12701881eadbSAbhyuday Godhasara * Return: Returns status, either success or error+reason 12711881eadbSAbhyuday Godhasara */ 12721881eadbSAbhyuday Godhasara 12731881eadbSAbhyuday Godhasara int zynqmp_pm_register_notifier(const u32 node, const u32 event, 12741881eadbSAbhyuday Godhasara const u32 wake, const u32 enable) 12751881eadbSAbhyuday Godhasara { 12761881eadbSAbhyuday Godhasara return zynqmp_pm_invoke_fn(PM_REGISTER_NOTIFIER, node, event, 12771881eadbSAbhyuday Godhasara wake, enable, NULL); 12781881eadbSAbhyuday Godhasara } 12791881eadbSAbhyuday Godhasara EXPORT_SYMBOL_GPL(zynqmp_pm_register_notifier); 12801881eadbSAbhyuday Godhasara 12811881eadbSAbhyuday Godhasara /** 1282fdd2ed88SRajan Vaja * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart 1283fdd2ed88SRajan Vaja * @type: Shutdown or restart? 0 for shutdown, 1 for restart 1284fdd2ed88SRajan Vaja * @subtype: Specifies which system should be restarted or shut down 1285fdd2ed88SRajan Vaja * 1286fdd2ed88SRajan Vaja * Return: Returns status, either success or error+reason 1287fdd2ed88SRajan Vaja */ 1288fdd2ed88SRajan Vaja int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype) 1289fdd2ed88SRajan Vaja { 1290fdd2ed88SRajan Vaja return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype, 1291fdd2ed88SRajan Vaja 0, 0, NULL); 1292fdd2ed88SRajan Vaja } 1293fdd2ed88SRajan Vaja 1294b3ae24c4SRajan Vaja /** 1295f1d0821bSRonak Jain * zynqmp_pm_set_feature_config - PM call to request IOCTL for feature config 1296f1d0821bSRonak Jain * @id: The config ID of the feature to be configured 1297f1d0821bSRonak Jain * @value: The config value of the feature to be configured 1298f1d0821bSRonak Jain * 1299f1d0821bSRonak Jain * Return: Returns 0 on success or error value on failure. 1300f1d0821bSRonak Jain */ 1301f1d0821bSRonak Jain int zynqmp_pm_set_feature_config(enum pm_feature_config_id id, u32 value) 1302f1d0821bSRonak Jain { 1303f1d0821bSRonak Jain return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_FEATURE_CONFIG, 1304f1d0821bSRonak Jain id, value, NULL); 1305f1d0821bSRonak Jain } 1306f1d0821bSRonak Jain 1307f1d0821bSRonak Jain /** 1308f1d0821bSRonak Jain * zynqmp_pm_get_feature_config - PM call to get value of configured feature 1309f1d0821bSRonak Jain * @id: The config id of the feature to be queried 1310f1d0821bSRonak Jain * @payload: Returned value array 1311f1d0821bSRonak Jain * 1312f1d0821bSRonak Jain * Return: Returns 0 on success or error value on failure. 1313f1d0821bSRonak Jain */ 1314f1d0821bSRonak Jain int zynqmp_pm_get_feature_config(enum pm_feature_config_id id, 1315f1d0821bSRonak Jain u32 *payload) 1316f1d0821bSRonak Jain { 1317f1d0821bSRonak Jain return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_FEATURE_CONFIG, 1318f1d0821bSRonak Jain id, 0, payload); 1319f1d0821bSRonak Jain } 1320f1d0821bSRonak Jain 1321f1d0821bSRonak Jain /** 1322256dea91SRonak Jain * zynqmp_pm_set_sd_config - PM call to set value of SD config registers 1323256dea91SRonak Jain * @node: SD node ID 1324256dea91SRonak Jain * @config: The config type of SD registers 1325256dea91SRonak Jain * @value: Value to be set 1326256dea91SRonak Jain * 1327256dea91SRonak Jain * Return: Returns 0 on success or error value on failure. 1328256dea91SRonak Jain */ 1329256dea91SRonak Jain int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value) 1330256dea91SRonak Jain { 1331256dea91SRonak Jain return zynqmp_pm_invoke_fn(PM_IOCTL, node, IOCTL_SET_SD_CONFIG, 1332256dea91SRonak Jain config, value, NULL); 1333256dea91SRonak Jain } 1334256dea91SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_config); 1335256dea91SRonak Jain 1336256dea91SRonak Jain /** 1337256dea91SRonak Jain * zynqmp_pm_set_gem_config - PM call to set value of GEM config registers 1338256dea91SRonak Jain * @node: GEM node ID 1339256dea91SRonak Jain * @config: The config type of GEM registers 1340256dea91SRonak Jain * @value: Value to be set 1341256dea91SRonak Jain * 1342256dea91SRonak Jain * Return: Returns 0 on success or error value on failure. 1343256dea91SRonak Jain */ 1344256dea91SRonak Jain int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config, 1345256dea91SRonak Jain u32 value) 1346256dea91SRonak Jain { 1347256dea91SRonak Jain return zynqmp_pm_invoke_fn(PM_IOCTL, node, IOCTL_SET_GEM_CONFIG, 1348256dea91SRonak Jain config, value, NULL); 1349256dea91SRonak Jain } 1350256dea91SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_set_gem_config); 1351256dea91SRonak Jain 1352256dea91SRonak Jain /** 1353b3ae24c4SRajan Vaja * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope 1354b3ae24c4SRajan Vaja * @subtype: Shutdown subtype 1355b3ae24c4SRajan Vaja * @name: Matching string for scope argument 1356b3ae24c4SRajan Vaja * 1357b3ae24c4SRajan Vaja * This struct encapsulates mapping between shutdown scope ID and string. 1358b3ae24c4SRajan Vaja */ 1359b3ae24c4SRajan Vaja struct zynqmp_pm_shutdown_scope { 1360b3ae24c4SRajan Vaja const enum zynqmp_pm_shutdown_subtype subtype; 1361b3ae24c4SRajan Vaja const char *name; 1362b3ae24c4SRajan Vaja }; 1363b3ae24c4SRajan Vaja 1364b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = { 1365b3ae24c4SRajan Vaja [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = { 1366b3ae24c4SRajan Vaja .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM, 1367b3ae24c4SRajan Vaja .name = "subsystem", 1368b3ae24c4SRajan Vaja }, 1369b3ae24c4SRajan Vaja [ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = { 1370b3ae24c4SRajan Vaja .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY, 1371b3ae24c4SRajan Vaja .name = "ps_only", 1372b3ae24c4SRajan Vaja }, 1373b3ae24c4SRajan Vaja [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = { 1374b3ae24c4SRajan Vaja .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM, 1375b3ae24c4SRajan Vaja .name = "system", 1376b3ae24c4SRajan Vaja }, 1377b3ae24c4SRajan Vaja }; 1378b3ae24c4SRajan Vaja 1379b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope *selected_scope = 1380b3ae24c4SRajan Vaja &shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM]; 1381b3ae24c4SRajan Vaja 1382b3ae24c4SRajan Vaja /** 1383b3ae24c4SRajan Vaja * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid 1384b3ae24c4SRajan Vaja * @scope_string: Shutdown scope string 1385b3ae24c4SRajan Vaja * 1386b3ae24c4SRajan Vaja * Return: Return pointer to matching shutdown scope struct from 1387b3ae24c4SRajan Vaja * array of available options in system if string is valid, 1388b3ae24c4SRajan Vaja * otherwise returns NULL. 1389b3ae24c4SRajan Vaja */ 1390b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope* 1391b3ae24c4SRajan Vaja zynqmp_pm_is_shutdown_scope_valid(const char *scope_string) 1392b3ae24c4SRajan Vaja { 1393b3ae24c4SRajan Vaja int count; 1394b3ae24c4SRajan Vaja 1395b3ae24c4SRajan Vaja for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++) 1396b3ae24c4SRajan Vaja if (sysfs_streq(scope_string, shutdown_scopes[count].name)) 1397b3ae24c4SRajan Vaja return &shutdown_scopes[count]; 1398b3ae24c4SRajan Vaja 1399b3ae24c4SRajan Vaja return NULL; 1400b3ae24c4SRajan Vaja } 1401b3ae24c4SRajan Vaja 1402b3ae24c4SRajan Vaja static ssize_t shutdown_scope_show(struct device *device, 1403b3ae24c4SRajan Vaja struct device_attribute *attr, 1404b3ae24c4SRajan Vaja char *buf) 1405b3ae24c4SRajan Vaja { 1406b3ae24c4SRajan Vaja int i; 1407b3ae24c4SRajan Vaja 1408b3ae24c4SRajan Vaja for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) { 1409b3ae24c4SRajan Vaja if (&shutdown_scopes[i] == selected_scope) { 1410b3ae24c4SRajan Vaja strcat(buf, "["); 1411b3ae24c4SRajan Vaja strcat(buf, shutdown_scopes[i].name); 1412b3ae24c4SRajan Vaja strcat(buf, "]"); 1413b3ae24c4SRajan Vaja } else { 1414b3ae24c4SRajan Vaja strcat(buf, shutdown_scopes[i].name); 1415b3ae24c4SRajan Vaja } 1416b3ae24c4SRajan Vaja strcat(buf, " "); 1417b3ae24c4SRajan Vaja } 1418b3ae24c4SRajan Vaja strcat(buf, "\n"); 1419b3ae24c4SRajan Vaja 1420b3ae24c4SRajan Vaja return strlen(buf); 1421b3ae24c4SRajan Vaja } 1422b3ae24c4SRajan Vaja 1423b3ae24c4SRajan Vaja static ssize_t shutdown_scope_store(struct device *device, 1424b3ae24c4SRajan Vaja struct device_attribute *attr, 1425b3ae24c4SRajan Vaja const char *buf, size_t count) 1426b3ae24c4SRajan Vaja { 1427b3ae24c4SRajan Vaja int ret; 1428b3ae24c4SRajan Vaja struct zynqmp_pm_shutdown_scope *scope; 1429b3ae24c4SRajan Vaja 1430b3ae24c4SRajan Vaja scope = zynqmp_pm_is_shutdown_scope_valid(buf); 1431b3ae24c4SRajan Vaja if (!scope) 1432b3ae24c4SRajan Vaja return -EINVAL; 1433b3ae24c4SRajan Vaja 1434b3ae24c4SRajan Vaja ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY, 1435b3ae24c4SRajan Vaja scope->subtype); 1436b3ae24c4SRajan Vaja if (ret) { 1437b3ae24c4SRajan Vaja pr_err("unable to set shutdown scope %s\n", buf); 1438b3ae24c4SRajan Vaja return ret; 1439b3ae24c4SRajan Vaja } 1440b3ae24c4SRajan Vaja 1441b3ae24c4SRajan Vaja selected_scope = scope; 1442b3ae24c4SRajan Vaja 1443b3ae24c4SRajan Vaja return count; 1444b3ae24c4SRajan Vaja } 1445b3ae24c4SRajan Vaja 1446b3ae24c4SRajan Vaja static DEVICE_ATTR_RW(shutdown_scope); 1447b3ae24c4SRajan Vaja 1448a2cc220aSRajan Vaja static ssize_t health_status_store(struct device *device, 1449a2cc220aSRajan Vaja struct device_attribute *attr, 1450a2cc220aSRajan Vaja const char *buf, size_t count) 1451a2cc220aSRajan Vaja { 1452a2cc220aSRajan Vaja int ret; 1453a2cc220aSRajan Vaja unsigned int value; 1454a2cc220aSRajan Vaja 1455a2cc220aSRajan Vaja ret = kstrtouint(buf, 10, &value); 1456a2cc220aSRajan Vaja if (ret) 1457a2cc220aSRajan Vaja return ret; 1458a2cc220aSRajan Vaja 1459a2cc220aSRajan Vaja ret = zynqmp_pm_set_boot_health_status(value); 1460a2cc220aSRajan Vaja if (ret) { 1461a2cc220aSRajan Vaja dev_err(device, "unable to set healthy bit value to %u\n", 1462a2cc220aSRajan Vaja value); 1463a2cc220aSRajan Vaja return ret; 1464a2cc220aSRajan Vaja } 1465a2cc220aSRajan Vaja 1466a2cc220aSRajan Vaja return count; 1467a2cc220aSRajan Vaja } 1468a2cc220aSRajan Vaja 1469a2cc220aSRajan Vaja static DEVICE_ATTR_WO(health_status); 1470a2cc220aSRajan Vaja 1471ae5c961dSRajan Vaja static ssize_t ggs_show(struct device *device, 1472ae5c961dSRajan Vaja struct device_attribute *attr, 1473ae5c961dSRajan Vaja char *buf, 1474ae5c961dSRajan Vaja u32 reg) 1475ae5c961dSRajan Vaja { 1476ae5c961dSRajan Vaja int ret; 1477ae5c961dSRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 1478ae5c961dSRajan Vaja 1479ae5c961dSRajan Vaja ret = zynqmp_pm_read_ggs(reg, ret_payload); 1480ae5c961dSRajan Vaja if (ret) 1481ae5c961dSRajan Vaja return ret; 1482ae5c961dSRajan Vaja 1483ae5c961dSRajan Vaja return sprintf(buf, "0x%x\n", ret_payload[1]); 1484ae5c961dSRajan Vaja } 1485ae5c961dSRajan Vaja 1486ae5c961dSRajan Vaja static ssize_t ggs_store(struct device *device, 1487ae5c961dSRajan Vaja struct device_attribute *attr, 1488ae5c961dSRajan Vaja const char *buf, size_t count, 1489ae5c961dSRajan Vaja u32 reg) 1490ae5c961dSRajan Vaja { 1491ae5c961dSRajan Vaja long value; 1492ae5c961dSRajan Vaja int ret; 1493ae5c961dSRajan Vaja 1494ae5c961dSRajan Vaja if (reg >= GSS_NUM_REGS) 1495ae5c961dSRajan Vaja return -EINVAL; 1496ae5c961dSRajan Vaja 1497ae5c961dSRajan Vaja ret = kstrtol(buf, 16, &value); 1498ae5c961dSRajan Vaja if (ret) { 1499ae5c961dSRajan Vaja count = -EFAULT; 1500ae5c961dSRajan Vaja goto err; 1501ae5c961dSRajan Vaja } 1502ae5c961dSRajan Vaja 1503ae5c961dSRajan Vaja ret = zynqmp_pm_write_ggs(reg, value); 1504ae5c961dSRajan Vaja if (ret) 1505ae5c961dSRajan Vaja count = -EFAULT; 1506ae5c961dSRajan Vaja err: 1507ae5c961dSRajan Vaja return count; 1508ae5c961dSRajan Vaja } 1509ae5c961dSRajan Vaja 1510ae5c961dSRajan Vaja /* GGS register show functions */ 1511ae5c961dSRajan Vaja #define GGS0_SHOW(N) \ 1512ae5c961dSRajan Vaja ssize_t ggs##N##_show(struct device *device, \ 1513ae5c961dSRajan Vaja struct device_attribute *attr, \ 1514ae5c961dSRajan Vaja char *buf) \ 1515ae5c961dSRajan Vaja { \ 1516ae5c961dSRajan Vaja return ggs_show(device, attr, buf, N); \ 1517ae5c961dSRajan Vaja } 1518ae5c961dSRajan Vaja 1519ae5c961dSRajan Vaja static GGS0_SHOW(0); 1520ae5c961dSRajan Vaja static GGS0_SHOW(1); 1521ae5c961dSRajan Vaja static GGS0_SHOW(2); 1522ae5c961dSRajan Vaja static GGS0_SHOW(3); 1523ae5c961dSRajan Vaja 1524ae5c961dSRajan Vaja /* GGS register store function */ 1525ae5c961dSRajan Vaja #define GGS0_STORE(N) \ 1526ae5c961dSRajan Vaja ssize_t ggs##N##_store(struct device *device, \ 1527ae5c961dSRajan Vaja struct device_attribute *attr, \ 1528ae5c961dSRajan Vaja const char *buf, \ 1529ae5c961dSRajan Vaja size_t count) \ 1530ae5c961dSRajan Vaja { \ 1531ae5c961dSRajan Vaja return ggs_store(device, attr, buf, count, N); \ 1532ae5c961dSRajan Vaja } 1533ae5c961dSRajan Vaja 1534ae5c961dSRajan Vaja static GGS0_STORE(0); 1535ae5c961dSRajan Vaja static GGS0_STORE(1); 1536ae5c961dSRajan Vaja static GGS0_STORE(2); 1537ae5c961dSRajan Vaja static GGS0_STORE(3); 1538ae5c961dSRajan Vaja 1539ae5c961dSRajan Vaja static ssize_t pggs_show(struct device *device, 1540ae5c961dSRajan Vaja struct device_attribute *attr, 1541ae5c961dSRajan Vaja char *buf, 1542ae5c961dSRajan Vaja u32 reg) 1543ae5c961dSRajan Vaja { 1544ae5c961dSRajan Vaja int ret; 1545ae5c961dSRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 1546ae5c961dSRajan Vaja 1547ae5c961dSRajan Vaja ret = zynqmp_pm_read_pggs(reg, ret_payload); 1548ae5c961dSRajan Vaja if (ret) 1549ae5c961dSRajan Vaja return ret; 1550ae5c961dSRajan Vaja 1551ae5c961dSRajan Vaja return sprintf(buf, "0x%x\n", ret_payload[1]); 1552ae5c961dSRajan Vaja } 1553ae5c961dSRajan Vaja 1554ae5c961dSRajan Vaja static ssize_t pggs_store(struct device *device, 1555ae5c961dSRajan Vaja struct device_attribute *attr, 1556ae5c961dSRajan Vaja const char *buf, size_t count, 1557ae5c961dSRajan Vaja u32 reg) 1558ae5c961dSRajan Vaja { 1559ae5c961dSRajan Vaja long value; 1560ae5c961dSRajan Vaja int ret; 1561ae5c961dSRajan Vaja 1562ae5c961dSRajan Vaja if (reg >= GSS_NUM_REGS) 1563ae5c961dSRajan Vaja return -EINVAL; 1564ae5c961dSRajan Vaja 1565ae5c961dSRajan Vaja ret = kstrtol(buf, 16, &value); 1566ae5c961dSRajan Vaja if (ret) { 1567ae5c961dSRajan Vaja count = -EFAULT; 1568ae5c961dSRajan Vaja goto err; 1569ae5c961dSRajan Vaja } 1570ae5c961dSRajan Vaja 1571ae5c961dSRajan Vaja ret = zynqmp_pm_write_pggs(reg, value); 1572ae5c961dSRajan Vaja if (ret) 1573ae5c961dSRajan Vaja count = -EFAULT; 1574ae5c961dSRajan Vaja 1575ae5c961dSRajan Vaja err: 1576ae5c961dSRajan Vaja return count; 1577ae5c961dSRajan Vaja } 1578ae5c961dSRajan Vaja 1579ae5c961dSRajan Vaja #define PGGS0_SHOW(N) \ 1580ae5c961dSRajan Vaja ssize_t pggs##N##_show(struct device *device, \ 1581ae5c961dSRajan Vaja struct device_attribute *attr, \ 1582ae5c961dSRajan Vaja char *buf) \ 1583ae5c961dSRajan Vaja { \ 1584ae5c961dSRajan Vaja return pggs_show(device, attr, buf, N); \ 1585ae5c961dSRajan Vaja } 1586ae5c961dSRajan Vaja 1587ae5c961dSRajan Vaja #define PGGS0_STORE(N) \ 1588ae5c961dSRajan Vaja ssize_t pggs##N##_store(struct device *device, \ 1589ae5c961dSRajan Vaja struct device_attribute *attr, \ 1590ae5c961dSRajan Vaja const char *buf, \ 1591ae5c961dSRajan Vaja size_t count) \ 1592ae5c961dSRajan Vaja { \ 1593ae5c961dSRajan Vaja return pggs_store(device, attr, buf, count, N); \ 1594ae5c961dSRajan Vaja } 1595ae5c961dSRajan Vaja 1596ae5c961dSRajan Vaja /* PGGS register show functions */ 1597ae5c961dSRajan Vaja static PGGS0_SHOW(0); 1598ae5c961dSRajan Vaja static PGGS0_SHOW(1); 1599ae5c961dSRajan Vaja static PGGS0_SHOW(2); 1600ae5c961dSRajan Vaja static PGGS0_SHOW(3); 1601ae5c961dSRajan Vaja 1602ae5c961dSRajan Vaja /* PGGS register store functions */ 1603ae5c961dSRajan Vaja static PGGS0_STORE(0); 1604ae5c961dSRajan Vaja static PGGS0_STORE(1); 1605ae5c961dSRajan Vaja static PGGS0_STORE(2); 1606ae5c961dSRajan Vaja static PGGS0_STORE(3); 1607ae5c961dSRajan Vaja 1608ae5c961dSRajan Vaja /* GGS register attributes */ 1609ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs0); 1610ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs1); 1611ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs2); 1612ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs3); 1613ae5c961dSRajan Vaja 1614ae5c961dSRajan Vaja /* PGGS register attributes */ 1615ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs0); 1616ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs1); 1617ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs2); 1618ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs3); 1619ae5c961dSRajan Vaja 16202c5d8f7cSRonak Jain static ssize_t feature_config_id_show(struct device *device, 16212c5d8f7cSRonak Jain struct device_attribute *attr, 16222c5d8f7cSRonak Jain char *buf) 16232c5d8f7cSRonak Jain { 16242c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device); 16252c5d8f7cSRonak Jain 16262c5d8f7cSRonak Jain return sysfs_emit(buf, "%d\n", devinfo->feature_conf_id); 16272c5d8f7cSRonak Jain } 16282c5d8f7cSRonak Jain 16292c5d8f7cSRonak Jain static ssize_t feature_config_id_store(struct device *device, 16302c5d8f7cSRonak Jain struct device_attribute *attr, 16312c5d8f7cSRonak Jain const char *buf, size_t count) 16322c5d8f7cSRonak Jain { 16332c5d8f7cSRonak Jain u32 config_id; 16342c5d8f7cSRonak Jain int ret; 16352c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device); 16362c5d8f7cSRonak Jain 16372c5d8f7cSRonak Jain if (!buf) 16382c5d8f7cSRonak Jain return -EINVAL; 16392c5d8f7cSRonak Jain 16402c5d8f7cSRonak Jain ret = kstrtou32(buf, 10, &config_id); 16412c5d8f7cSRonak Jain if (ret) 16422c5d8f7cSRonak Jain return ret; 16432c5d8f7cSRonak Jain 16442c5d8f7cSRonak Jain devinfo->feature_conf_id = config_id; 16452c5d8f7cSRonak Jain 16462c5d8f7cSRonak Jain return count; 16472c5d8f7cSRonak Jain } 16482c5d8f7cSRonak Jain 16492c5d8f7cSRonak Jain static DEVICE_ATTR_RW(feature_config_id); 16502c5d8f7cSRonak Jain 16512c5d8f7cSRonak Jain static ssize_t feature_config_value_show(struct device *device, 16522c5d8f7cSRonak Jain struct device_attribute *attr, 16532c5d8f7cSRonak Jain char *buf) 16542c5d8f7cSRonak Jain { 16552c5d8f7cSRonak Jain int ret; 16562c5d8f7cSRonak Jain u32 ret_payload[PAYLOAD_ARG_CNT]; 16572c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device); 16582c5d8f7cSRonak Jain 16592c5d8f7cSRonak Jain ret = zynqmp_pm_get_feature_config(devinfo->feature_conf_id, 16602c5d8f7cSRonak Jain ret_payload); 16612c5d8f7cSRonak Jain if (ret) 16622c5d8f7cSRonak Jain return ret; 16632c5d8f7cSRonak Jain 16642c5d8f7cSRonak Jain return sysfs_emit(buf, "%d\n", ret_payload[1]); 16652c5d8f7cSRonak Jain } 16662c5d8f7cSRonak Jain 16672c5d8f7cSRonak Jain static ssize_t feature_config_value_store(struct device *device, 16682c5d8f7cSRonak Jain struct device_attribute *attr, 16692c5d8f7cSRonak Jain const char *buf, size_t count) 16702c5d8f7cSRonak Jain { 16712c5d8f7cSRonak Jain u32 value; 16722c5d8f7cSRonak Jain int ret; 16732c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device); 16742c5d8f7cSRonak Jain 16752c5d8f7cSRonak Jain if (!buf) 16762c5d8f7cSRonak Jain return -EINVAL; 16772c5d8f7cSRonak Jain 16782c5d8f7cSRonak Jain ret = kstrtou32(buf, 10, &value); 16792c5d8f7cSRonak Jain if (ret) 16802c5d8f7cSRonak Jain return ret; 16812c5d8f7cSRonak Jain 16822c5d8f7cSRonak Jain ret = zynqmp_pm_set_feature_config(devinfo->feature_conf_id, 16832c5d8f7cSRonak Jain value); 16842c5d8f7cSRonak Jain if (ret) 16852c5d8f7cSRonak Jain return ret; 16862c5d8f7cSRonak Jain 16872c5d8f7cSRonak Jain return count; 16882c5d8f7cSRonak Jain } 16892c5d8f7cSRonak Jain 16902c5d8f7cSRonak Jain static DEVICE_ATTR_RW(feature_config_value); 16912c5d8f7cSRonak Jain 1692ae5c961dSRajan Vaja static struct attribute *zynqmp_firmware_attrs[] = { 1693ae5c961dSRajan Vaja &dev_attr_ggs0.attr, 1694ae5c961dSRajan Vaja &dev_attr_ggs1.attr, 1695ae5c961dSRajan Vaja &dev_attr_ggs2.attr, 1696ae5c961dSRajan Vaja &dev_attr_ggs3.attr, 1697ae5c961dSRajan Vaja &dev_attr_pggs0.attr, 1698ae5c961dSRajan Vaja &dev_attr_pggs1.attr, 1699ae5c961dSRajan Vaja &dev_attr_pggs2.attr, 1700ae5c961dSRajan Vaja &dev_attr_pggs3.attr, 1701b3ae24c4SRajan Vaja &dev_attr_shutdown_scope.attr, 1702a2cc220aSRajan Vaja &dev_attr_health_status.attr, 17032c5d8f7cSRonak Jain &dev_attr_feature_config_id.attr, 17042c5d8f7cSRonak Jain &dev_attr_feature_config_value.attr, 1705ae5c961dSRajan Vaja NULL, 1706ae5c961dSRajan Vaja }; 1707ae5c961dSRajan Vaja 1708ae5c961dSRajan Vaja ATTRIBUTE_GROUPS(zynqmp_firmware); 1709ae5c961dSRajan Vaja 171076582671SRajan Vaja static int zynqmp_firmware_probe(struct platform_device *pdev) 171176582671SRajan Vaja { 171276582671SRajan Vaja struct device *dev = &pdev->dev; 171376582671SRajan Vaja struct device_node *np; 17142c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo; 171576582671SRajan Vaja int ret; 171676582671SRajan Vaja 1717e5052becSRonak Jain ret = get_set_conduit_method(dev->of_node); 1718e5052becSRonak Jain if (ret) 1719e5052becSRonak Jain return ret; 1720e5052becSRonak Jain 172176582671SRajan Vaja np = of_find_compatible_node(NULL, NULL, "xlnx,zynqmp"); 1722af3f1afaSJolly Shah if (!np) { 1723af3f1afaSJolly Shah np = of_find_compatible_node(NULL, NULL, "xlnx,versal"); 172476582671SRajan Vaja if (!np) 172576582671SRajan Vaja return 0; 1726461011b1SRavi Patel 1727461011b1SRavi Patel feature_check_enabled = true; 1728af3f1afaSJolly Shah } 172976582671SRajan Vaja 1730e5052becSRonak Jain if (!feature_check_enabled) { 1731e5052becSRonak Jain ret = do_feature_check_call(PM_FEATURE_CHECK); 1732e5052becSRonak Jain if (ret >= 0) 1733e5052becSRonak Jain feature_check_enabled = true; 1734e5052becSRonak Jain } 1735e5052becSRonak Jain 1736e5052becSRonak Jain of_node_put(np); 173776582671SRajan Vaja 17382c5d8f7cSRonak Jain devinfo = devm_kzalloc(dev, sizeof(*devinfo), GFP_KERNEL); 17392c5d8f7cSRonak Jain if (!devinfo) 17402c5d8f7cSRonak Jain return -ENOMEM; 17412c5d8f7cSRonak Jain 17422c5d8f7cSRonak Jain devinfo->dev = dev; 17432c5d8f7cSRonak Jain 17442c5d8f7cSRonak Jain platform_set_drvdata(pdev, devinfo); 17452c5d8f7cSRonak Jain 174676582671SRajan Vaja /* Check PM API version number */ 1747168e05c1SRajan Vaja ret = zynqmp_pm_get_api_version(&pm_api_version); 1748168e05c1SRajan Vaja if (ret) 1749168e05c1SRajan Vaja return ret; 1750168e05c1SRajan Vaja 175176582671SRajan Vaja if (pm_api_version < ZYNQMP_PM_VERSION) { 175276582671SRajan Vaja panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n", 175376582671SRajan Vaja __func__, 175476582671SRajan Vaja ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR, 175576582671SRajan Vaja pm_api_version >> 16, pm_api_version & 0xFFFF); 175676582671SRajan Vaja } 175776582671SRajan Vaja 175876582671SRajan Vaja pr_info("%s Platform Management API v%d.%d\n", __func__, 175976582671SRajan Vaja pm_api_version >> 16, pm_api_version & 0xFFFF); 176076582671SRajan Vaja 176176582671SRajan Vaja /* Check trustzone version number */ 176276582671SRajan Vaja ret = zynqmp_pm_get_trustzone_version(&pm_tz_version); 176376582671SRajan Vaja if (ret) 176476582671SRajan Vaja panic("Legacy trustzone found without version support\n"); 176576582671SRajan Vaja 176676582671SRajan Vaja if (pm_tz_version < ZYNQMP_TZ_VERSION) 176776582671SRajan Vaja panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n", 176876582671SRajan Vaja __func__, 176976582671SRajan Vaja ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR, 177076582671SRajan Vaja pm_tz_version >> 16, pm_tz_version & 0xFFFF); 177176582671SRajan Vaja 177276582671SRajan Vaja pr_info("%s Trustzone version v%d.%d\n", __func__, 177376582671SRajan Vaja pm_tz_version >> 16, pm_tz_version & 0xFFFF); 177476582671SRajan Vaja 1775e23d9c6dSJolly Shah ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs, 1776e23d9c6dSJolly Shah ARRAY_SIZE(firmware_devs), NULL, 0, NULL); 1777e23d9c6dSJolly Shah if (ret) { 1778e23d9c6dSJolly Shah dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret); 1779e23d9c6dSJolly Shah return ret; 1780e23d9c6dSJolly Shah } 1781e23d9c6dSJolly Shah 178265f0539bSChristophe JAILLET zynqmp_pm_api_debugfs_init(); 178365f0539bSChristophe JAILLET 1784a515814eSAbhyuday Godhasara np = of_find_compatible_node(NULL, NULL, "xlnx,versal"); 1785a515814eSAbhyuday Godhasara if (np) { 1786a515814eSAbhyuday Godhasara em_dev = platform_device_register_data(&pdev->dev, "xlnx_event_manager", 1787a515814eSAbhyuday Godhasara -1, NULL, 0); 1788a515814eSAbhyuday Godhasara if (IS_ERR(em_dev)) 1789a515814eSAbhyuday Godhasara dev_err_probe(&pdev->dev, PTR_ERR(em_dev), "EM register fail with error\n"); 1790a515814eSAbhyuday Godhasara } 1791a515814eSAbhyuday Godhasara of_node_put(np); 1792a515814eSAbhyuday Godhasara 179376582671SRajan Vaja return of_platform_populate(dev->of_node, NULL, NULL, dev); 179476582671SRajan Vaja } 179576582671SRajan Vaja 179676582671SRajan Vaja static int zynqmp_firmware_remove(struct platform_device *pdev) 179776582671SRajan Vaja { 1798acfdd185SAmit Sunil Dhamne struct pm_api_feature_data *feature_data; 1799f1f21becSTejas Patel struct hlist_node *tmp; 1800acfdd185SAmit Sunil Dhamne int i; 1801acfdd185SAmit Sunil Dhamne 1802e23d9c6dSJolly Shah mfd_remove_devices(&pdev->dev); 1803b3217252SRajan Vaja zynqmp_pm_api_debugfs_exit(); 1804b3217252SRajan Vaja 1805f1f21becSTejas Patel hash_for_each_safe(pm_api_features_map, i, tmp, feature_data, hentry) { 1806acfdd185SAmit Sunil Dhamne hash_del(&feature_data->hentry); 1807acfdd185SAmit Sunil Dhamne kfree(feature_data); 1808acfdd185SAmit Sunil Dhamne } 1809acfdd185SAmit Sunil Dhamne 1810a515814eSAbhyuday Godhasara platform_device_unregister(em_dev); 1811a515814eSAbhyuday Godhasara 181276582671SRajan Vaja return 0; 181376582671SRajan Vaja } 181476582671SRajan Vaja 181576582671SRajan Vaja static const struct of_device_id zynqmp_firmware_of_match[] = { 181676582671SRajan Vaja {.compatible = "xlnx,zynqmp-firmware"}, 1817af3f1afaSJolly Shah {.compatible = "xlnx,versal-firmware"}, 181876582671SRajan Vaja {}, 181976582671SRajan Vaja }; 182076582671SRajan Vaja MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match); 182176582671SRajan Vaja 182276582671SRajan Vaja static struct platform_driver zynqmp_firmware_driver = { 182376582671SRajan Vaja .driver = { 182476582671SRajan Vaja .name = "zynqmp_firmware", 182576582671SRajan Vaja .of_match_table = zynqmp_firmware_of_match, 1826ae5c961dSRajan Vaja .dev_groups = zynqmp_firmware_groups, 182776582671SRajan Vaja }, 182876582671SRajan Vaja .probe = zynqmp_firmware_probe, 182976582671SRajan Vaja .remove = zynqmp_firmware_remove, 183076582671SRajan Vaja }; 183176582671SRajan Vaja module_platform_driver(zynqmp_firmware_driver); 1832