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 */ 20938ed310cSRoman Gushchin feature_data = kmalloc(sizeof(*feature_data), GFP_ATOMIC); 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 { 741a4b2e606SMarek Vasut u32 reg = (type == PM_TAPDELAY_INPUT) ? SD_ITAPDLY : SD_OTAPDLYSEL; 742a4b2e606SMarek Vasut u32 mask = (node_id == NODE_SD_0) ? GENMASK(15, 0) : GENMASK(31, 16); 743a4b2e606SMarek Vasut 744a4b2e606SMarek Vasut if (value) { 745a4b2e606SMarek Vasut return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, 746a4b2e606SMarek Vasut IOCTL_SET_SD_TAPDELAY, 747426c8d85SRajan Vaja type, value, NULL); 748426c8d85SRajan Vaja } 749a4b2e606SMarek Vasut 750a4b2e606SMarek Vasut /* 751a4b2e606SMarek Vasut * Work around completely misdesigned firmware API on Xilinx ZynqMP. 752a4b2e606SMarek Vasut * The IOCTL_SET_SD_TAPDELAY firmware call allows the caller to only 753a4b2e606SMarek Vasut * ever set IOU_SLCR SD_ITAPDLY Register SD0_ITAPDLYENA/SD1_ITAPDLYENA 754a4b2e606SMarek Vasut * bits, but there is no matching call to clear those bits. If those 755a4b2e606SMarek Vasut * bits are not cleared, SDMMC tuning may fail. 756a4b2e606SMarek Vasut * 757a4b2e606SMarek Vasut * Luckily, there are PM_MMIO_READ/PM_MMIO_WRITE calls which seem to 758a4b2e606SMarek Vasut * allow complete unrestricted access to all address space, including 759a4b2e606SMarek Vasut * IOU_SLCR SD_ITAPDLY Register and all the other registers, access 760a4b2e606SMarek Vasut * to which was supposed to be protected by the current firmware API. 761a4b2e606SMarek Vasut * 762a4b2e606SMarek Vasut * Use PM_MMIO_READ/PM_MMIO_WRITE to re-implement the missing counter 763a4b2e606SMarek Vasut * part of IOCTL_SET_SD_TAPDELAY which clears SDx_ITAPDLYENA bits. 764a4b2e606SMarek Vasut */ 765a4b2e606SMarek Vasut return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, reg, mask, 0, 0, NULL); 766a4b2e606SMarek Vasut } 767426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay); 768426c8d85SRajan Vaja 769426c8d85SRajan Vaja /** 770426c8d85SRajan Vaja * zynqmp_pm_sd_dll_reset() - Reset DLL logic 771426c8d85SRajan Vaja * 772332bee16SMichal Simek * @node_id: Node ID of the device 773332bee16SMichal Simek * @type: Reset type 774426c8d85SRajan Vaja * 775426c8d85SRajan Vaja * This function resets DLL logic for the SD device. 776426c8d85SRajan Vaja * 777332bee16SMichal Simek * Return: Returns status, either success or error+reason 778426c8d85SRajan Vaja */ 779426c8d85SRajan Vaja int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type) 780426c8d85SRajan Vaja { 781f4426311SManish Narani return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SD_DLL_RESET, 782426c8d85SRajan Vaja type, 0, NULL); 783426c8d85SRajan Vaja } 784426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset); 7853b0296b8SRajan Vaja 786bc3843d4SNava kishore Manne /** 78774e78adcSSai Krishna Potthuri * zynqmp_pm_ospi_mux_select() - OSPI Mux selection 78874e78adcSSai Krishna Potthuri * 78974e78adcSSai Krishna Potthuri * @dev_id: Device Id of the OSPI device. 79074e78adcSSai Krishna Potthuri * @select: OSPI Mux select value. 79174e78adcSSai Krishna Potthuri * 79274e78adcSSai Krishna Potthuri * This function select the OSPI Mux. 79374e78adcSSai Krishna Potthuri * 79474e78adcSSai Krishna Potthuri * Return: Returns status, either success or error+reason 79574e78adcSSai Krishna Potthuri */ 79674e78adcSSai Krishna Potthuri int zynqmp_pm_ospi_mux_select(u32 dev_id, u32 select) 79774e78adcSSai Krishna Potthuri { 79874e78adcSSai Krishna Potthuri return zynqmp_pm_invoke_fn(PM_IOCTL, dev_id, IOCTL_OSPI_MUX_SELECT, 79974e78adcSSai Krishna Potthuri select, 0, NULL); 80074e78adcSSai Krishna Potthuri } 80174e78adcSSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_ospi_mux_select); 80274e78adcSSai Krishna Potthuri 80374e78adcSSai Krishna Potthuri /** 8044f680b72SRajan Vaja * zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs) 805332bee16SMichal Simek * @index: GGS register index 806332bee16SMichal Simek * @value: Register value to be written 8074f680b72SRajan Vaja * 8084f680b72SRajan Vaja * This function writes value to GGS register. 8094f680b72SRajan Vaja * 810332bee16SMichal Simek * Return: Returns status, either success or error+reason 8114f680b72SRajan Vaja */ 8124f680b72SRajan Vaja int zynqmp_pm_write_ggs(u32 index, u32 value) 8134f680b72SRajan Vaja { 8144f680b72SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_GGS, 8154f680b72SRajan Vaja index, value, NULL); 8164f680b72SRajan Vaja } 8174f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs); 8184f680b72SRajan Vaja 8194f680b72SRajan Vaja /** 8202a8faf8dSMichal Simek * zynqmp_pm_read_ggs() - PM API for reading global general storage (ggs) 821332bee16SMichal Simek * @index: GGS register index 822332bee16SMichal Simek * @value: Register value to be written 8234f680b72SRajan Vaja * 8244f680b72SRajan Vaja * This function returns GGS register value. 8254f680b72SRajan Vaja * 826332bee16SMichal Simek * Return: Returns status, either success or error+reason 8274f680b72SRajan Vaja */ 8284f680b72SRajan Vaja int zynqmp_pm_read_ggs(u32 index, u32 *value) 8294f680b72SRajan Vaja { 8304f680b72SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_GGS, 8314f680b72SRajan Vaja index, 0, value); 8324f680b72SRajan Vaja } 8334f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs); 8344f680b72SRajan Vaja 8354f680b72SRajan Vaja /** 8364f680b72SRajan Vaja * zynqmp_pm_write_pggs() - PM API for writing persistent global general 8374f680b72SRajan Vaja * storage (pggs) 838332bee16SMichal Simek * @index: PGGS register index 839332bee16SMichal Simek * @value: Register value to be written 8404f680b72SRajan Vaja * 8414f680b72SRajan Vaja * This function writes value to PGGS register. 8424f680b72SRajan Vaja * 843332bee16SMichal Simek * Return: Returns status, either success or error+reason 8444f680b72SRajan Vaja */ 8454f680b72SRajan Vaja int zynqmp_pm_write_pggs(u32 index, u32 value) 8464f680b72SRajan Vaja { 8474f680b72SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_PGGS, index, value, 8484f680b72SRajan Vaja NULL); 8494f680b72SRajan Vaja } 8504f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs); 8514f680b72SRajan Vaja 8524f680b72SRajan Vaja /** 8532a8faf8dSMichal Simek * zynqmp_pm_read_pggs() - PM API for reading persistent global general 8544f680b72SRajan Vaja * storage (pggs) 855332bee16SMichal Simek * @index: PGGS register index 856332bee16SMichal Simek * @value: Register value to be written 8574f680b72SRajan Vaja * 8584f680b72SRajan Vaja * This function returns PGGS register value. 8594f680b72SRajan Vaja * 860332bee16SMichal Simek * Return: Returns status, either success or error+reason 8614f680b72SRajan Vaja */ 8624f680b72SRajan Vaja int zynqmp_pm_read_pggs(u32 index, u32 *value) 8634f680b72SRajan Vaja { 8644f680b72SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_PGGS, index, 0, 8654f680b72SRajan Vaja value); 8664f680b72SRajan Vaja } 8674f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs); 8684f680b72SRajan Vaja 8691e400cb9SRajan Vaja int zynqmp_pm_set_tapdelay_bypass(u32 index, u32 value) 8701e400cb9SRajan Vaja { 8711e400cb9SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_TAPDELAY_BYPASS, 8721e400cb9SRajan Vaja index, value, NULL); 8731e400cb9SRajan Vaja } 8741e400cb9SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_tapdelay_bypass); 8751e400cb9SRajan Vaja 8764f680b72SRajan Vaja /** 877a2cc220aSRajan Vaja * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status 878332bee16SMichal Simek * @value: Status value to be written 879a2cc220aSRajan Vaja * 880a2cc220aSRajan Vaja * This function sets healthy bit value to indicate boot health status 881a2cc220aSRajan Vaja * to firmware. 882a2cc220aSRajan Vaja * 883332bee16SMichal Simek * Return: Returns status, either success or error+reason 884a2cc220aSRajan Vaja */ 885a2cc220aSRajan Vaja int zynqmp_pm_set_boot_health_status(u32 value) 886a2cc220aSRajan Vaja { 887a2cc220aSRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_BOOT_HEALTH_STATUS, 888a2cc220aSRajan Vaja value, 0, NULL); 889a2cc220aSRajan Vaja } 890a2cc220aSRajan Vaja 891a2cc220aSRajan Vaja /** 892bc3843d4SNava kishore Manne * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release) 893bc3843d4SNava kishore Manne * @reset: Reset to be configured 894bc3843d4SNava kishore Manne * @assert_flag: Flag stating should reset be asserted (1) or 895bc3843d4SNava kishore Manne * released (0) 896bc3843d4SNava kishore Manne * 897bc3843d4SNava kishore Manne * Return: Returns status, either success or error+reason 898bc3843d4SNava kishore Manne */ 899cf23ec35SRajan Vaja int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset, 900bc3843d4SNava kishore Manne const enum zynqmp_pm_reset_action assert_flag) 901bc3843d4SNava kishore Manne { 902bc3843d4SNava kishore Manne return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag, 903bc3843d4SNava kishore Manne 0, 0, NULL); 904bc3843d4SNava kishore Manne } 905cf23ec35SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert); 906bc3843d4SNava kishore Manne 907bc3843d4SNava kishore Manne /** 908bc3843d4SNava kishore Manne * zynqmp_pm_reset_get_status - Get status of the reset 909bc3843d4SNava kishore Manne * @reset: Reset whose status should be returned 910bc3843d4SNava kishore Manne * @status: Returned status 911bc3843d4SNava kishore Manne * 912bc3843d4SNava kishore Manne * Return: Returns status, either success or error+reason 913bc3843d4SNava kishore Manne */ 9141b413581SRajan Vaja int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status) 915bc3843d4SNava kishore Manne { 916bc3843d4SNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT]; 917bc3843d4SNava kishore Manne int ret; 918bc3843d4SNava kishore Manne 919bc3843d4SNava kishore Manne if (!status) 920bc3843d4SNava kishore Manne return -EINVAL; 921bc3843d4SNava kishore Manne 922bc3843d4SNava kishore Manne ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0, 923bc3843d4SNava kishore Manne 0, 0, ret_payload); 924bc3843d4SNava kishore Manne *status = ret_payload[1]; 925bc3843d4SNava kishore Manne 926bc3843d4SNava kishore Manne return ret; 927bc3843d4SNava kishore Manne } 9281b413581SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status); 929bc3843d4SNava kishore Manne 930e178df31SJolly Shah /** 931e840deccSNava kishore Manne * zynqmp_pm_fpga_load - Perform the fpga load 932e840deccSNava kishore Manne * @address: Address to write to 933e840deccSNava kishore Manne * @size: pl bitstream size 934e840deccSNava kishore Manne * @flags: Bitstream type 935e840deccSNava kishore Manne * -XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration 936e840deccSNava kishore Manne * -XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration 937e840deccSNava kishore Manne * 938e840deccSNava kishore Manne * This function provides access to pmufw. To transfer 939e840deccSNava kishore Manne * the required bitstream into PL. 940e840deccSNava kishore Manne * 941e840deccSNava kishore Manne * Return: Returns status, either success or error+reason 942e840deccSNava kishore Manne */ 9434db8180fSRajan Vaja int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags) 944e840deccSNava kishore Manne { 945*e2ebc05dSNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT]; 946*e2ebc05dSNava kishore Manne int ret; 947*e2ebc05dSNava kishore Manne 948*e2ebc05dSNava kishore Manne ret = zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address), 949*e2ebc05dSNava kishore Manne upper_32_bits(address), size, flags, 950*e2ebc05dSNava kishore Manne ret_payload); 951*e2ebc05dSNava kishore Manne if (ret_payload[0]) 952*e2ebc05dSNava kishore Manne return -ret_payload[0]; 953*e2ebc05dSNava kishore Manne 954*e2ebc05dSNava kishore Manne return ret; 955e840deccSNava kishore Manne } 95656a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load); 957e840deccSNava kishore Manne 958e840deccSNava kishore Manne /** 959e840deccSNava kishore Manne * zynqmp_pm_fpga_get_status - Read value from PCAP status register 960e840deccSNava kishore Manne * @value: Value to read 961e840deccSNava kishore Manne * 962e840deccSNava kishore Manne * This function provides access to the pmufw to get the PCAP 963e840deccSNava kishore Manne * status 964e840deccSNava kishore Manne * 965e840deccSNava kishore Manne * Return: Returns status, either success or error+reason 966e840deccSNava kishore Manne */ 9674db8180fSRajan Vaja int zynqmp_pm_fpga_get_status(u32 *value) 968e840deccSNava kishore Manne { 969e840deccSNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT]; 970e840deccSNava kishore Manne int ret; 971e840deccSNava kishore Manne 972e840deccSNava kishore Manne if (!value) 973e840deccSNava kishore Manne return -EINVAL; 974e840deccSNava kishore Manne 975e840deccSNava kishore Manne ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload); 976e840deccSNava kishore Manne *value = ret_payload[1]; 977e840deccSNava kishore Manne 978e840deccSNava kishore Manne return ret; 979e840deccSNava kishore Manne } 98056a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status); 981e840deccSNava kishore Manne 982e840deccSNava kishore Manne /** 9838f118f61SNava kishore Manne * zynqmp_pm_fpga_get_config_status - Get the FPGA configuration status. 9848f118f61SNava kishore Manne * @value: Buffer to store FPGA configuration status. 9858f118f61SNava kishore Manne * 9868f118f61SNava kishore Manne * This function provides access to the pmufw to get the FPGA configuration 9878f118f61SNava kishore Manne * status 9888f118f61SNava kishore Manne * 9898f118f61SNava kishore Manne * Return: 0 on success, a negative value on error 9908f118f61SNava kishore Manne */ 9918f118f61SNava kishore Manne int zynqmp_pm_fpga_get_config_status(u32 *value) 9928f118f61SNava kishore Manne { 9938f118f61SNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT]; 9948f118f61SNava kishore Manne u32 buf, lower_addr, upper_addr; 9958f118f61SNava kishore Manne int ret; 9968f118f61SNava kishore Manne 9978f118f61SNava kishore Manne if (!value) 9988f118f61SNava kishore Manne return -EINVAL; 9998f118f61SNava kishore Manne 10008f118f61SNava kishore Manne lower_addr = lower_32_bits((u64)&buf); 10018f118f61SNava kishore Manne upper_addr = upper_32_bits((u64)&buf); 10028f118f61SNava kishore Manne 10038f118f61SNava kishore Manne ret = zynqmp_pm_invoke_fn(PM_FPGA_READ, 10048f118f61SNava kishore Manne XILINX_ZYNQMP_PM_FPGA_CONFIG_STAT_OFFSET, 10058f118f61SNava kishore Manne lower_addr, upper_addr, 10068f118f61SNava kishore Manne XILINX_ZYNQMP_PM_FPGA_READ_CONFIG_REG, 10078f118f61SNava kishore Manne ret_payload); 10088f118f61SNava kishore Manne 10098f118f61SNava kishore Manne *value = ret_payload[1]; 10108f118f61SNava kishore Manne 10118f118f61SNava kishore Manne return ret; 10128f118f61SNava kishore Manne } 10138f118f61SNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_config_status); 10148f118f61SNava kishore Manne 10158f118f61SNava kishore Manne /** 1016fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_request - Request Pin from firmware 1017fa989ae7SSai Krishna Potthuri * @pin: Pin number to request 1018fa989ae7SSai Krishna Potthuri * 1019fa989ae7SSai Krishna Potthuri * This function requests pin from firmware. 1020fa989ae7SSai Krishna Potthuri * 1021fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason. 1022fa989ae7SSai Krishna Potthuri */ 1023fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_request(const u32 pin) 1024fa989ae7SSai Krishna Potthuri { 1025fa989ae7SSai Krishna Potthuri return zynqmp_pm_invoke_fn(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL); 1026fa989ae7SSai Krishna Potthuri } 1027fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_request); 1028fa989ae7SSai Krishna Potthuri 1029fa989ae7SSai Krishna Potthuri /** 1030fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_release - Inform firmware that Pin control is released 1031fa989ae7SSai Krishna Potthuri * @pin: Pin number to release 1032fa989ae7SSai Krishna Potthuri * 1033fa989ae7SSai Krishna Potthuri * This function release pin from firmware. 1034fa989ae7SSai Krishna Potthuri * 1035fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason. 1036fa989ae7SSai Krishna Potthuri */ 1037fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_release(const u32 pin) 1038fa989ae7SSai Krishna Potthuri { 1039fa989ae7SSai Krishna Potthuri return zynqmp_pm_invoke_fn(PM_PINCTRL_RELEASE, pin, 0, 0, 0, NULL); 1040fa989ae7SSai Krishna Potthuri } 1041fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_release); 1042fa989ae7SSai Krishna Potthuri 1043fa989ae7SSai Krishna Potthuri /** 1044fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_get_function - Read function id set for the given pin 1045fa989ae7SSai Krishna Potthuri * @pin: Pin number 1046fa989ae7SSai Krishna Potthuri * @id: Buffer to store function ID 1047fa989ae7SSai Krishna Potthuri * 1048fa989ae7SSai Krishna Potthuri * This function provides the function currently set for the given pin. 1049fa989ae7SSai Krishna Potthuri * 1050fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason 1051fa989ae7SSai Krishna Potthuri */ 1052fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_get_function(const u32 pin, u32 *id) 1053fa989ae7SSai Krishna Potthuri { 1054fa989ae7SSai Krishna Potthuri u32 ret_payload[PAYLOAD_ARG_CNT]; 1055fa989ae7SSai Krishna Potthuri int ret; 1056fa989ae7SSai Krishna Potthuri 1057fa989ae7SSai Krishna Potthuri if (!id) 1058fa989ae7SSai Krishna Potthuri return -EINVAL; 1059fa989ae7SSai Krishna Potthuri 1060fa989ae7SSai Krishna Potthuri ret = zynqmp_pm_invoke_fn(PM_PINCTRL_GET_FUNCTION, pin, 0, 1061fa989ae7SSai Krishna Potthuri 0, 0, ret_payload); 1062fa989ae7SSai Krishna Potthuri *id = ret_payload[1]; 1063fa989ae7SSai Krishna Potthuri 1064fa989ae7SSai Krishna Potthuri return ret; 1065fa989ae7SSai Krishna Potthuri } 1066fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_function); 1067fa989ae7SSai Krishna Potthuri 1068fa989ae7SSai Krishna Potthuri /** 1069fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_set_function - Set requested function for the pin 1070fa989ae7SSai Krishna Potthuri * @pin: Pin number 1071fa989ae7SSai Krishna Potthuri * @id: Function ID to set 1072fa989ae7SSai Krishna Potthuri * 1073fa989ae7SSai Krishna Potthuri * This function sets requested function for the given pin. 1074fa989ae7SSai Krishna Potthuri * 1075fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason. 1076fa989ae7SSai Krishna Potthuri */ 1077fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id) 1078fa989ae7SSai Krishna Potthuri { 1079fa989ae7SSai Krishna Potthuri return zynqmp_pm_invoke_fn(PM_PINCTRL_SET_FUNCTION, pin, id, 1080fa989ae7SSai Krishna Potthuri 0, 0, NULL); 1081fa989ae7SSai Krishna Potthuri } 1082fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_function); 1083fa989ae7SSai Krishna Potthuri 1084fa989ae7SSai Krishna Potthuri /** 1085fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_get_config - Get configuration parameter for the pin 1086fa989ae7SSai Krishna Potthuri * @pin: Pin number 1087fa989ae7SSai Krishna Potthuri * @param: Parameter to get 1088fa989ae7SSai Krishna Potthuri * @value: Buffer to store parameter value 1089fa989ae7SSai Krishna Potthuri * 1090fa989ae7SSai Krishna Potthuri * This function gets requested configuration parameter for the given pin. 1091fa989ae7SSai Krishna Potthuri * 1092fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason. 1093fa989ae7SSai Krishna Potthuri */ 1094fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param, 1095fa989ae7SSai Krishna Potthuri u32 *value) 1096fa989ae7SSai Krishna Potthuri { 1097fa989ae7SSai Krishna Potthuri u32 ret_payload[PAYLOAD_ARG_CNT]; 1098fa989ae7SSai Krishna Potthuri int ret; 1099fa989ae7SSai Krishna Potthuri 1100fa989ae7SSai Krishna Potthuri if (!value) 1101fa989ae7SSai Krishna Potthuri return -EINVAL; 1102fa989ae7SSai Krishna Potthuri 1103fa989ae7SSai Krishna Potthuri ret = zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_GET, pin, param, 1104fa989ae7SSai Krishna Potthuri 0, 0, ret_payload); 1105fa989ae7SSai Krishna Potthuri *value = ret_payload[1]; 1106fa989ae7SSai Krishna Potthuri 1107fa989ae7SSai Krishna Potthuri return ret; 1108fa989ae7SSai Krishna Potthuri } 1109fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_config); 1110fa989ae7SSai Krishna Potthuri 1111fa989ae7SSai Krishna Potthuri /** 1112fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_set_config - Set configuration parameter for the pin 1113fa989ae7SSai Krishna Potthuri * @pin: Pin number 1114fa989ae7SSai Krishna Potthuri * @param: Parameter to set 1115fa989ae7SSai Krishna Potthuri * @value: Parameter value to set 1116fa989ae7SSai Krishna Potthuri * 1117fa989ae7SSai Krishna Potthuri * This function sets requested configuration parameter for the given pin. 1118fa989ae7SSai Krishna Potthuri * 1119fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason. 1120fa989ae7SSai Krishna Potthuri */ 1121fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param, 1122fa989ae7SSai Krishna Potthuri u32 value) 1123fa989ae7SSai Krishna Potthuri { 1124fa989ae7SSai Krishna Potthuri return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, pin, 1125fa989ae7SSai Krishna Potthuri param, value, 0, NULL); 1126fa989ae7SSai Krishna Potthuri } 1127fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_config); 1128fa989ae7SSai Krishna Potthuri 1129fa989ae7SSai Krishna Potthuri /** 113023c64d76SPiyush Mehta * zynqmp_pm_bootmode_read() - PM Config API for read bootpin status 113123c64d76SPiyush Mehta * @ps_mode: Returned output value of ps_mode 113223c64d76SPiyush Mehta * 113323c64d76SPiyush Mehta * This API function is to be used for notify the power management controller 113423c64d76SPiyush Mehta * to read bootpin status. 113523c64d76SPiyush Mehta * 113623c64d76SPiyush Mehta * Return: status, either success or error+reason 113723c64d76SPiyush Mehta */ 113823c64d76SPiyush Mehta unsigned int zynqmp_pm_bootmode_read(u32 *ps_mode) 113923c64d76SPiyush Mehta { 114023c64d76SPiyush Mehta unsigned int ret; 114123c64d76SPiyush Mehta u32 ret_payload[PAYLOAD_ARG_CNT]; 114223c64d76SPiyush Mehta 114323c64d76SPiyush Mehta ret = zynqmp_pm_invoke_fn(PM_MMIO_READ, CRL_APB_BOOT_PIN_CTRL, 0, 114423c64d76SPiyush Mehta 0, 0, ret_payload); 114523c64d76SPiyush Mehta 114623c64d76SPiyush Mehta *ps_mode = ret_payload[1]; 114723c64d76SPiyush Mehta 114823c64d76SPiyush Mehta return ret; 114923c64d76SPiyush Mehta } 115023c64d76SPiyush Mehta EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_read); 115123c64d76SPiyush Mehta 115223c64d76SPiyush Mehta /** 115323c64d76SPiyush Mehta * zynqmp_pm_bootmode_write() - PM Config API for Configure bootpin 115423c64d76SPiyush Mehta * @ps_mode: Value to be written to the bootpin ctrl register 115523c64d76SPiyush Mehta * 115623c64d76SPiyush Mehta * This API function is to be used for notify the power management controller 115723c64d76SPiyush Mehta * to configure bootpin. 115823c64d76SPiyush Mehta * 115923c64d76SPiyush Mehta * Return: Returns status, either success or error+reason 116023c64d76SPiyush Mehta */ 116123c64d76SPiyush Mehta int zynqmp_pm_bootmode_write(u32 ps_mode) 116223c64d76SPiyush Mehta { 116323c64d76SPiyush Mehta return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, CRL_APB_BOOT_PIN_CTRL, 116423c64d76SPiyush Mehta CRL_APB_BOOTPIN_CTRL_MASK, ps_mode, 0, NULL); 116523c64d76SPiyush Mehta } 116623c64d76SPiyush Mehta EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_write); 116723c64d76SPiyush Mehta 116823c64d76SPiyush Mehta /** 1169e178df31SJolly Shah * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller 1170e178df31SJolly Shah * master has initialized its own power management 1171e178df31SJolly Shah * 1172332bee16SMichal Simek * Return: Returns status, either success or error+reason 1173332bee16SMichal Simek * 1174e178df31SJolly Shah * This API function is to be used for notify the power management controller 1175e178df31SJolly Shah * about the completed power management initialization. 1176e178df31SJolly Shah */ 11779474da95SRajan Vaja int zynqmp_pm_init_finalize(void) 1178e178df31SJolly Shah { 1179e178df31SJolly Shah return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL); 1180e178df31SJolly Shah } 11819474da95SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_init_finalize); 1182e178df31SJolly Shah 1183e178df31SJolly Shah /** 1184e178df31SJolly Shah * zynqmp_pm_set_suspend_mode() - Set system suspend mode 1185e178df31SJolly Shah * @mode: Mode to set for system suspend 1186e178df31SJolly Shah * 1187e178df31SJolly Shah * This API function is used to set mode of system suspend. 1188e178df31SJolly Shah * 1189e178df31SJolly Shah * Return: Returns status, either success or error+reason 1190e178df31SJolly Shah */ 1191951d0a97SRajan Vaja int zynqmp_pm_set_suspend_mode(u32 mode) 1192e178df31SJolly Shah { 1193e178df31SJolly Shah return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL); 1194e178df31SJolly Shah } 1195951d0a97SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode); 1196e178df31SJolly Shah 1197c1986ac3SRajan Vaja /** 1198c1986ac3SRajan Vaja * zynqmp_pm_request_node() - Request a node with specific capabilities 1199c1986ac3SRajan Vaja * @node: Node ID of the slave 1200c1986ac3SRajan Vaja * @capabilities: Requested capabilities of the slave 1201c1986ac3SRajan Vaja * @qos: Quality of service (not supported) 1202c1986ac3SRajan Vaja * @ack: Flag to specify whether acknowledge is requested 1203c1986ac3SRajan Vaja * 1204c1986ac3SRajan Vaja * This function is used by master to request particular node from firmware. 1205c1986ac3SRajan Vaja * Every master must request node before using it. 1206c1986ac3SRajan Vaja * 1207c1986ac3SRajan Vaja * Return: Returns status, either success or error+reason 1208c1986ac3SRajan Vaja */ 1209bf8b27edSRajan Vaja int zynqmp_pm_request_node(const u32 node, const u32 capabilities, 1210bf8b27edSRajan Vaja const u32 qos, const enum zynqmp_pm_request_ack ack) 1211c1986ac3SRajan Vaja { 1212c1986ac3SRajan Vaja return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities, 1213c1986ac3SRajan Vaja qos, ack, NULL); 1214c1986ac3SRajan Vaja } 1215bf8b27edSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_request_node); 1216c1986ac3SRajan Vaja 1217c1986ac3SRajan Vaja /** 1218c1986ac3SRajan Vaja * zynqmp_pm_release_node() - Release a node 1219c1986ac3SRajan Vaja * @node: Node ID of the slave 1220c1986ac3SRajan Vaja * 1221c1986ac3SRajan Vaja * This function is used by master to inform firmware that master 1222c1986ac3SRajan Vaja * has released node. Once released, master must not use that node 1223c1986ac3SRajan Vaja * without re-request. 1224c1986ac3SRajan Vaja * 1225c1986ac3SRajan Vaja * Return: Returns status, either success or error+reason 1226c1986ac3SRajan Vaja */ 122707fb1a46SRajan Vaja int zynqmp_pm_release_node(const u32 node) 1228c1986ac3SRajan Vaja { 1229c1986ac3SRajan Vaja return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL); 1230c1986ac3SRajan Vaja } 123107fb1a46SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_release_node); 1232c1986ac3SRajan Vaja 1233c1986ac3SRajan Vaja /** 1234a5e56980SBen Levinsky * zynqmp_pm_get_rpu_mode() - Get RPU mode 1235a5e56980SBen Levinsky * @node_id: Node ID of the device 1236a5e56980SBen Levinsky * @rpu_mode: return by reference value 1237a5e56980SBen Levinsky * either split or lockstep 1238a5e56980SBen Levinsky * 1239a5e56980SBen Levinsky * Return: return 0 on success or error+reason. 1240a5e56980SBen Levinsky * if success, then rpu_mode will be set 1241a5e56980SBen Levinsky * to current rpu mode. 1242a5e56980SBen Levinsky */ 1243a5e56980SBen Levinsky int zynqmp_pm_get_rpu_mode(u32 node_id, enum rpu_oper_mode *rpu_mode) 1244a5e56980SBen Levinsky { 1245a5e56980SBen Levinsky u32 ret_payload[PAYLOAD_ARG_CNT]; 1246a5e56980SBen Levinsky int ret; 1247a5e56980SBen Levinsky 1248a5e56980SBen Levinsky ret = zynqmp_pm_invoke_fn(PM_IOCTL, node_id, 1249a5e56980SBen Levinsky IOCTL_GET_RPU_OPER_MODE, 0, 0, ret_payload); 1250a5e56980SBen Levinsky 1251a5e56980SBen Levinsky /* only set rpu_mode if no error */ 1252a5e56980SBen Levinsky if (ret == XST_PM_SUCCESS) 1253a5e56980SBen Levinsky *rpu_mode = ret_payload[0]; 1254a5e56980SBen Levinsky 1255a5e56980SBen Levinsky return ret; 1256a5e56980SBen Levinsky } 1257a5e56980SBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_get_rpu_mode); 1258a5e56980SBen Levinsky 1259a5e56980SBen Levinsky /** 1260a5e56980SBen Levinsky * zynqmp_pm_set_rpu_mode() - Set RPU mode 1261a5e56980SBen Levinsky * @node_id: Node ID of the device 1262a5e56980SBen Levinsky * @rpu_mode: Argument 1 to requested IOCTL call. either split or lockstep 1263a5e56980SBen Levinsky * 1264a5e56980SBen Levinsky * This function is used to set RPU mode to split or 1265a5e56980SBen Levinsky * lockstep 1266a5e56980SBen Levinsky * 1267a5e56980SBen Levinsky * Return: Returns status, either success or error+reason 1268a5e56980SBen Levinsky */ 1269a5e56980SBen Levinsky int zynqmp_pm_set_rpu_mode(u32 node_id, enum rpu_oper_mode rpu_mode) 1270a5e56980SBen Levinsky { 1271a5e56980SBen Levinsky return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, 1272a5e56980SBen Levinsky IOCTL_SET_RPU_OPER_MODE, (u32)rpu_mode, 1273a5e56980SBen Levinsky 0, NULL); 1274a5e56980SBen Levinsky } 1275a5e56980SBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_set_rpu_mode); 1276a5e56980SBen Levinsky 1277a5e56980SBen Levinsky /** 1278a5e56980SBen Levinsky * zynqmp_pm_set_tcm_config - configure TCM 1279a5e56980SBen Levinsky * @node_id: Firmware specific TCM subsystem ID 1280a5e56980SBen Levinsky * @tcm_mode: Argument 1 to requested IOCTL call 1281a5e56980SBen Levinsky * either PM_RPU_TCM_COMB or PM_RPU_TCM_SPLIT 1282a5e56980SBen Levinsky * 1283a5e56980SBen Levinsky * This function is used to set RPU mode to split or combined 1284a5e56980SBen Levinsky * 1285a5e56980SBen Levinsky * Return: status: 0 for success, else failure 1286a5e56980SBen Levinsky */ 1287a5e56980SBen Levinsky int zynqmp_pm_set_tcm_config(u32 node_id, enum rpu_tcm_comb tcm_mode) 1288a5e56980SBen Levinsky { 1289a5e56980SBen Levinsky return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, 1290a5e56980SBen Levinsky IOCTL_TCM_COMB_CONFIG, (u32)tcm_mode, 0, 1291a5e56980SBen Levinsky NULL); 1292a5e56980SBen Levinsky } 1293a5e56980SBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_set_tcm_config); 1294a5e56980SBen Levinsky 1295a5e56980SBen Levinsky /** 1296da22a04fSBen Levinsky * zynqmp_pm_force_pwrdwn - PM call to request for another PU or subsystem to 1297da22a04fSBen Levinsky * be powered down forcefully 1298da22a04fSBen Levinsky * @node: Node ID of the targeted PU or subsystem 1299da22a04fSBen Levinsky * @ack: Flag to specify whether acknowledge is requested 1300da22a04fSBen Levinsky * 1301da22a04fSBen Levinsky * Return: status, either success or error+reason 1302da22a04fSBen Levinsky */ 1303da22a04fSBen Levinsky int zynqmp_pm_force_pwrdwn(const u32 node, 1304da22a04fSBen Levinsky const enum zynqmp_pm_request_ack ack) 1305da22a04fSBen Levinsky { 1306da22a04fSBen Levinsky return zynqmp_pm_invoke_fn(PM_FORCE_POWERDOWN, node, ack, 0, 0, NULL); 1307da22a04fSBen Levinsky } 1308da22a04fSBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_force_pwrdwn); 1309da22a04fSBen Levinsky 1310da22a04fSBen Levinsky /** 1311da22a04fSBen Levinsky * zynqmp_pm_request_wake - PM call to wake up selected master or subsystem 1312da22a04fSBen Levinsky * @node: Node ID of the master or subsystem 1313da22a04fSBen Levinsky * @set_addr: Specifies whether the address argument is relevant 1314da22a04fSBen Levinsky * @address: Address from which to resume when woken up 1315da22a04fSBen Levinsky * @ack: Flag to specify whether acknowledge requested 1316da22a04fSBen Levinsky * 1317da22a04fSBen Levinsky * Return: status, either success or error+reason 1318da22a04fSBen Levinsky */ 1319da22a04fSBen Levinsky int zynqmp_pm_request_wake(const u32 node, 1320da22a04fSBen Levinsky const bool set_addr, 1321da22a04fSBen Levinsky const u64 address, 1322da22a04fSBen Levinsky const enum zynqmp_pm_request_ack ack) 1323da22a04fSBen Levinsky { 1324da22a04fSBen Levinsky /* set_addr flag is encoded into 1st bit of address */ 1325da22a04fSBen Levinsky return zynqmp_pm_invoke_fn(PM_REQUEST_WAKEUP, node, address | set_addr, 1326da22a04fSBen Levinsky address >> 32, ack, NULL); 1327da22a04fSBen Levinsky } 1328da22a04fSBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_request_wake); 1329da22a04fSBen Levinsky 1330da22a04fSBen Levinsky /** 1331c1986ac3SRajan Vaja * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves 1332c1986ac3SRajan Vaja * @node: Node ID of the slave 1333c1986ac3SRajan Vaja * @capabilities: Requested capabilities of the slave 1334c1986ac3SRajan Vaja * @qos: Quality of service (not supported) 1335c1986ac3SRajan Vaja * @ack: Flag to specify whether acknowledge is requested 1336c1986ac3SRajan Vaja * 1337c1986ac3SRajan Vaja * This API function is to be used for slaves a PU already has requested 1338c1986ac3SRajan Vaja * to change its capabilities. 1339c1986ac3SRajan Vaja * 1340c1986ac3SRajan Vaja * Return: Returns status, either success or error+reason 1341c1986ac3SRajan Vaja */ 1342cbbbda71SRajan Vaja int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities, 1343c1986ac3SRajan Vaja const u32 qos, 1344c1986ac3SRajan Vaja const enum zynqmp_pm_request_ack ack) 1345c1986ac3SRajan Vaja { 1346c1986ac3SRajan Vaja return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities, 1347c1986ac3SRajan Vaja qos, ack, NULL); 1348c1986ac3SRajan Vaja } 1349cbbbda71SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement); 1350c1986ac3SRajan Vaja 1351057a0fb6SKalyani Akula /** 13522b9fc773SNava kishore Manne * zynqmp_pm_load_pdi - Load and process PDI 13532b9fc773SNava kishore Manne * @src: Source device where PDI is located 13542b9fc773SNava kishore Manne * @address: PDI src address 13552b9fc773SNava kishore Manne * 13562b9fc773SNava kishore Manne * This function provides support to load PDI from linux 13572b9fc773SNava kishore Manne * 13582b9fc773SNava kishore Manne * Return: Returns status, either success or error+reason 13592b9fc773SNava kishore Manne */ 13602b9fc773SNava kishore Manne int zynqmp_pm_load_pdi(const u32 src, const u64 address) 13612b9fc773SNava kishore Manne { 13622b9fc773SNava kishore Manne return zynqmp_pm_invoke_fn(PM_LOAD_PDI, src, 13632b9fc773SNava kishore Manne lower_32_bits(address), 13642b9fc773SNava kishore Manne upper_32_bits(address), 0, NULL); 13652b9fc773SNava kishore Manne } 13662b9fc773SNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_load_pdi); 13672b9fc773SNava kishore Manne 13682b9fc773SNava kishore Manne /** 13692a8faf8dSMichal Simek * zynqmp_pm_aes_engine - Access AES hardware to encrypt/decrypt the data using 1370057a0fb6SKalyani Akula * AES-GCM core. 1371057a0fb6SKalyani Akula * @address: Address of the AesParams structure. 1372057a0fb6SKalyani Akula * @out: Returned output value 1373057a0fb6SKalyani Akula * 1374057a0fb6SKalyani Akula * Return: Returns status, either success or error code. 1375057a0fb6SKalyani Akula */ 1376bc86f9c5SRajan Vaja int zynqmp_pm_aes_engine(const u64 address, u32 *out) 1377057a0fb6SKalyani Akula { 1378057a0fb6SKalyani Akula u32 ret_payload[PAYLOAD_ARG_CNT]; 1379057a0fb6SKalyani Akula int ret; 1380057a0fb6SKalyani Akula 1381057a0fb6SKalyani Akula if (!out) 1382057a0fb6SKalyani Akula return -EINVAL; 1383057a0fb6SKalyani Akula 1384057a0fb6SKalyani Akula ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, upper_32_bits(address), 1385057a0fb6SKalyani Akula lower_32_bits(address), 1386057a0fb6SKalyani Akula 0, 0, ret_payload); 1387057a0fb6SKalyani Akula *out = ret_payload[1]; 1388057a0fb6SKalyani Akula 1389057a0fb6SKalyani Akula return ret; 1390057a0fb6SKalyani Akula } 1391bc86f9c5SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine); 1392057a0fb6SKalyani Akula 1393fdd2ed88SRajan Vaja /** 139480f940efSHarsha * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash 139580f940efSHarsha * @address: Address of the data/ Address of output buffer where 139680f940efSHarsha * hash should be stored. 139780f940efSHarsha * @size: Size of the data. 139880f940efSHarsha * @flags: 139980f940efSHarsha * BIT(0) - for initializing csudma driver and SHA3(Here address 140080f940efSHarsha * and size inputs can be NULL). 140180f940efSHarsha * BIT(1) - to call Sha3_Update API which can be called multiple 140280f940efSHarsha * times when data is not contiguous. 140380f940efSHarsha * BIT(2) - to get final hash of the whole updated data. 140480f940efSHarsha * Hash will be overwritten at provided address with 140580f940efSHarsha * 48 bytes. 140680f940efSHarsha * 140780f940efSHarsha * Return: Returns status, either success or error code. 140880f940efSHarsha */ 140980f940efSHarsha int zynqmp_pm_sha_hash(const u64 address, const u32 size, const u32 flags) 141080f940efSHarsha { 141180f940efSHarsha u32 lower_addr = lower_32_bits(address); 141280f940efSHarsha u32 upper_addr = upper_32_bits(address); 141380f940efSHarsha 141480f940efSHarsha return zynqmp_pm_invoke_fn(PM_SECURE_SHA, upper_addr, lower_addr, 141580f940efSHarsha size, flags, NULL); 141680f940efSHarsha } 141780f940efSHarsha EXPORT_SYMBOL_GPL(zynqmp_pm_sha_hash); 141880f940efSHarsha 141980f940efSHarsha /** 14201881eadbSAbhyuday Godhasara * zynqmp_pm_register_notifier() - PM API for register a subsystem 14211881eadbSAbhyuday Godhasara * to be notified about specific 14221881eadbSAbhyuday Godhasara * event/error. 14231881eadbSAbhyuday Godhasara * @node: Node ID to which the event is related. 14241881eadbSAbhyuday Godhasara * @event: Event Mask of Error events for which wants to get notified. 14251881eadbSAbhyuday Godhasara * @wake: Wake subsystem upon capturing the event if value 1 14261881eadbSAbhyuday Godhasara * @enable: Enable the registration for value 1, disable for value 0 14271881eadbSAbhyuday Godhasara * 14281881eadbSAbhyuday Godhasara * This function is used to register/un-register for particular node-event 14291881eadbSAbhyuday Godhasara * combination in firmware. 14301881eadbSAbhyuday Godhasara * 14311881eadbSAbhyuday Godhasara * Return: Returns status, either success or error+reason 14321881eadbSAbhyuday Godhasara */ 14331881eadbSAbhyuday Godhasara 14341881eadbSAbhyuday Godhasara int zynqmp_pm_register_notifier(const u32 node, const u32 event, 14351881eadbSAbhyuday Godhasara const u32 wake, const u32 enable) 14361881eadbSAbhyuday Godhasara { 14371881eadbSAbhyuday Godhasara return zynqmp_pm_invoke_fn(PM_REGISTER_NOTIFIER, node, event, 14381881eadbSAbhyuday Godhasara wake, enable, NULL); 14391881eadbSAbhyuday Godhasara } 14401881eadbSAbhyuday Godhasara EXPORT_SYMBOL_GPL(zynqmp_pm_register_notifier); 14411881eadbSAbhyuday Godhasara 14421881eadbSAbhyuday Godhasara /** 1443fdd2ed88SRajan Vaja * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart 1444fdd2ed88SRajan Vaja * @type: Shutdown or restart? 0 for shutdown, 1 for restart 1445fdd2ed88SRajan Vaja * @subtype: Specifies which system should be restarted or shut down 1446fdd2ed88SRajan Vaja * 1447fdd2ed88SRajan Vaja * Return: Returns status, either success or error+reason 1448fdd2ed88SRajan Vaja */ 1449fdd2ed88SRajan Vaja int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype) 1450fdd2ed88SRajan Vaja { 1451fdd2ed88SRajan Vaja return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype, 1452fdd2ed88SRajan Vaja 0, 0, NULL); 1453fdd2ed88SRajan Vaja } 1454fdd2ed88SRajan Vaja 1455b3ae24c4SRajan Vaja /** 1456f1d0821bSRonak Jain * zynqmp_pm_set_feature_config - PM call to request IOCTL for feature config 1457f1d0821bSRonak Jain * @id: The config ID of the feature to be configured 1458f1d0821bSRonak Jain * @value: The config value of the feature to be configured 1459f1d0821bSRonak Jain * 1460f1d0821bSRonak Jain * Return: Returns 0 on success or error value on failure. 1461f1d0821bSRonak Jain */ 1462f1d0821bSRonak Jain int zynqmp_pm_set_feature_config(enum pm_feature_config_id id, u32 value) 1463f1d0821bSRonak Jain { 1464f1d0821bSRonak Jain return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_FEATURE_CONFIG, 1465f1d0821bSRonak Jain id, value, NULL); 1466f1d0821bSRonak Jain } 1467f1d0821bSRonak Jain 1468f1d0821bSRonak Jain /** 1469f1d0821bSRonak Jain * zynqmp_pm_get_feature_config - PM call to get value of configured feature 1470f1d0821bSRonak Jain * @id: The config id of the feature to be queried 1471f1d0821bSRonak Jain * @payload: Returned value array 1472f1d0821bSRonak Jain * 1473f1d0821bSRonak Jain * Return: Returns 0 on success or error value on failure. 1474f1d0821bSRonak Jain */ 1475f1d0821bSRonak Jain int zynqmp_pm_get_feature_config(enum pm_feature_config_id id, 1476f1d0821bSRonak Jain u32 *payload) 1477f1d0821bSRonak Jain { 1478f1d0821bSRonak Jain return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_FEATURE_CONFIG, 1479f1d0821bSRonak Jain id, 0, payload); 1480f1d0821bSRonak Jain } 1481f1d0821bSRonak Jain 1482f1d0821bSRonak Jain /** 1483256dea91SRonak Jain * zynqmp_pm_set_sd_config - PM call to set value of SD config registers 1484256dea91SRonak Jain * @node: SD node ID 1485256dea91SRonak Jain * @config: The config type of SD registers 1486256dea91SRonak Jain * @value: Value to be set 1487256dea91SRonak Jain * 1488256dea91SRonak Jain * Return: Returns 0 on success or error value on failure. 1489256dea91SRonak Jain */ 1490256dea91SRonak Jain int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value) 1491256dea91SRonak Jain { 1492256dea91SRonak Jain return zynqmp_pm_invoke_fn(PM_IOCTL, node, IOCTL_SET_SD_CONFIG, 1493256dea91SRonak Jain config, value, NULL); 1494256dea91SRonak Jain } 1495256dea91SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_config); 1496256dea91SRonak Jain 1497256dea91SRonak Jain /** 1498256dea91SRonak Jain * zynqmp_pm_set_gem_config - PM call to set value of GEM config registers 1499256dea91SRonak Jain * @node: GEM node ID 1500256dea91SRonak Jain * @config: The config type of GEM registers 1501256dea91SRonak Jain * @value: Value to be set 1502256dea91SRonak Jain * 1503256dea91SRonak Jain * Return: Returns 0 on success or error value on failure. 1504256dea91SRonak Jain */ 1505256dea91SRonak Jain int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config, 1506256dea91SRonak Jain u32 value) 1507256dea91SRonak Jain { 1508256dea91SRonak Jain return zynqmp_pm_invoke_fn(PM_IOCTL, node, IOCTL_SET_GEM_CONFIG, 1509256dea91SRonak Jain config, value, NULL); 1510256dea91SRonak Jain } 1511256dea91SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_set_gem_config); 1512256dea91SRonak Jain 1513256dea91SRonak Jain /** 1514b3ae24c4SRajan Vaja * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope 1515b3ae24c4SRajan Vaja * @subtype: Shutdown subtype 1516b3ae24c4SRajan Vaja * @name: Matching string for scope argument 1517b3ae24c4SRajan Vaja * 1518b3ae24c4SRajan Vaja * This struct encapsulates mapping between shutdown scope ID and string. 1519b3ae24c4SRajan Vaja */ 1520b3ae24c4SRajan Vaja struct zynqmp_pm_shutdown_scope { 1521b3ae24c4SRajan Vaja const enum zynqmp_pm_shutdown_subtype subtype; 1522b3ae24c4SRajan Vaja const char *name; 1523b3ae24c4SRajan Vaja }; 1524b3ae24c4SRajan Vaja 1525b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = { 1526b3ae24c4SRajan Vaja [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = { 1527b3ae24c4SRajan Vaja .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM, 1528b3ae24c4SRajan Vaja .name = "subsystem", 1529b3ae24c4SRajan Vaja }, 1530b3ae24c4SRajan Vaja [ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = { 1531b3ae24c4SRajan Vaja .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY, 1532b3ae24c4SRajan Vaja .name = "ps_only", 1533b3ae24c4SRajan Vaja }, 1534b3ae24c4SRajan Vaja [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = { 1535b3ae24c4SRajan Vaja .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM, 1536b3ae24c4SRajan Vaja .name = "system", 1537b3ae24c4SRajan Vaja }, 1538b3ae24c4SRajan Vaja }; 1539b3ae24c4SRajan Vaja 1540b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope *selected_scope = 1541b3ae24c4SRajan Vaja &shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM]; 1542b3ae24c4SRajan Vaja 1543b3ae24c4SRajan Vaja /** 1544b3ae24c4SRajan Vaja * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid 1545b3ae24c4SRajan Vaja * @scope_string: Shutdown scope string 1546b3ae24c4SRajan Vaja * 1547b3ae24c4SRajan Vaja * Return: Return pointer to matching shutdown scope struct from 1548b3ae24c4SRajan Vaja * array of available options in system if string is valid, 1549b3ae24c4SRajan Vaja * otherwise returns NULL. 1550b3ae24c4SRajan Vaja */ 1551b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope* 1552b3ae24c4SRajan Vaja zynqmp_pm_is_shutdown_scope_valid(const char *scope_string) 1553b3ae24c4SRajan Vaja { 1554b3ae24c4SRajan Vaja int count; 1555b3ae24c4SRajan Vaja 1556b3ae24c4SRajan Vaja for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++) 1557b3ae24c4SRajan Vaja if (sysfs_streq(scope_string, shutdown_scopes[count].name)) 1558b3ae24c4SRajan Vaja return &shutdown_scopes[count]; 1559b3ae24c4SRajan Vaja 1560b3ae24c4SRajan Vaja return NULL; 1561b3ae24c4SRajan Vaja } 1562b3ae24c4SRajan Vaja 1563b3ae24c4SRajan Vaja static ssize_t shutdown_scope_show(struct device *device, 1564b3ae24c4SRajan Vaja struct device_attribute *attr, 1565b3ae24c4SRajan Vaja char *buf) 1566b3ae24c4SRajan Vaja { 1567b3ae24c4SRajan Vaja int i; 1568b3ae24c4SRajan Vaja 1569b3ae24c4SRajan Vaja for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) { 1570b3ae24c4SRajan Vaja if (&shutdown_scopes[i] == selected_scope) { 1571b3ae24c4SRajan Vaja strcat(buf, "["); 1572b3ae24c4SRajan Vaja strcat(buf, shutdown_scopes[i].name); 1573b3ae24c4SRajan Vaja strcat(buf, "]"); 1574b3ae24c4SRajan Vaja } else { 1575b3ae24c4SRajan Vaja strcat(buf, shutdown_scopes[i].name); 1576b3ae24c4SRajan Vaja } 1577b3ae24c4SRajan Vaja strcat(buf, " "); 1578b3ae24c4SRajan Vaja } 1579b3ae24c4SRajan Vaja strcat(buf, "\n"); 1580b3ae24c4SRajan Vaja 1581b3ae24c4SRajan Vaja return strlen(buf); 1582b3ae24c4SRajan Vaja } 1583b3ae24c4SRajan Vaja 1584b3ae24c4SRajan Vaja static ssize_t shutdown_scope_store(struct device *device, 1585b3ae24c4SRajan Vaja struct device_attribute *attr, 1586b3ae24c4SRajan Vaja const char *buf, size_t count) 1587b3ae24c4SRajan Vaja { 1588b3ae24c4SRajan Vaja int ret; 1589b3ae24c4SRajan Vaja struct zynqmp_pm_shutdown_scope *scope; 1590b3ae24c4SRajan Vaja 1591b3ae24c4SRajan Vaja scope = zynqmp_pm_is_shutdown_scope_valid(buf); 1592b3ae24c4SRajan Vaja if (!scope) 1593b3ae24c4SRajan Vaja return -EINVAL; 1594b3ae24c4SRajan Vaja 1595b3ae24c4SRajan Vaja ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY, 1596b3ae24c4SRajan Vaja scope->subtype); 1597b3ae24c4SRajan Vaja if (ret) { 1598b3ae24c4SRajan Vaja pr_err("unable to set shutdown scope %s\n", buf); 1599b3ae24c4SRajan Vaja return ret; 1600b3ae24c4SRajan Vaja } 1601b3ae24c4SRajan Vaja 1602b3ae24c4SRajan Vaja selected_scope = scope; 1603b3ae24c4SRajan Vaja 1604b3ae24c4SRajan Vaja return count; 1605b3ae24c4SRajan Vaja } 1606b3ae24c4SRajan Vaja 1607b3ae24c4SRajan Vaja static DEVICE_ATTR_RW(shutdown_scope); 1608b3ae24c4SRajan Vaja 1609a2cc220aSRajan Vaja static ssize_t health_status_store(struct device *device, 1610a2cc220aSRajan Vaja struct device_attribute *attr, 1611a2cc220aSRajan Vaja const char *buf, size_t count) 1612a2cc220aSRajan Vaja { 1613a2cc220aSRajan Vaja int ret; 1614a2cc220aSRajan Vaja unsigned int value; 1615a2cc220aSRajan Vaja 1616a2cc220aSRajan Vaja ret = kstrtouint(buf, 10, &value); 1617a2cc220aSRajan Vaja if (ret) 1618a2cc220aSRajan Vaja return ret; 1619a2cc220aSRajan Vaja 1620a2cc220aSRajan Vaja ret = zynqmp_pm_set_boot_health_status(value); 1621a2cc220aSRajan Vaja if (ret) { 1622a2cc220aSRajan Vaja dev_err(device, "unable to set healthy bit value to %u\n", 1623a2cc220aSRajan Vaja value); 1624a2cc220aSRajan Vaja return ret; 1625a2cc220aSRajan Vaja } 1626a2cc220aSRajan Vaja 1627a2cc220aSRajan Vaja return count; 1628a2cc220aSRajan Vaja } 1629a2cc220aSRajan Vaja 1630a2cc220aSRajan Vaja static DEVICE_ATTR_WO(health_status); 1631a2cc220aSRajan Vaja 1632ae5c961dSRajan Vaja static ssize_t ggs_show(struct device *device, 1633ae5c961dSRajan Vaja struct device_attribute *attr, 1634ae5c961dSRajan Vaja char *buf, 1635ae5c961dSRajan Vaja u32 reg) 1636ae5c961dSRajan Vaja { 1637ae5c961dSRajan Vaja int ret; 1638ae5c961dSRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 1639ae5c961dSRajan Vaja 1640ae5c961dSRajan Vaja ret = zynqmp_pm_read_ggs(reg, ret_payload); 1641ae5c961dSRajan Vaja if (ret) 1642ae5c961dSRajan Vaja return ret; 1643ae5c961dSRajan Vaja 1644ae5c961dSRajan Vaja return sprintf(buf, "0x%x\n", ret_payload[1]); 1645ae5c961dSRajan Vaja } 1646ae5c961dSRajan Vaja 1647ae5c961dSRajan Vaja static ssize_t ggs_store(struct device *device, 1648ae5c961dSRajan Vaja struct device_attribute *attr, 1649ae5c961dSRajan Vaja const char *buf, size_t count, 1650ae5c961dSRajan Vaja u32 reg) 1651ae5c961dSRajan Vaja { 1652ae5c961dSRajan Vaja long value; 1653ae5c961dSRajan Vaja int ret; 1654ae5c961dSRajan Vaja 1655ae5c961dSRajan Vaja if (reg >= GSS_NUM_REGS) 1656ae5c961dSRajan Vaja return -EINVAL; 1657ae5c961dSRajan Vaja 1658ae5c961dSRajan Vaja ret = kstrtol(buf, 16, &value); 1659ae5c961dSRajan Vaja if (ret) { 1660ae5c961dSRajan Vaja count = -EFAULT; 1661ae5c961dSRajan Vaja goto err; 1662ae5c961dSRajan Vaja } 1663ae5c961dSRajan Vaja 1664ae5c961dSRajan Vaja ret = zynqmp_pm_write_ggs(reg, value); 1665ae5c961dSRajan Vaja if (ret) 1666ae5c961dSRajan Vaja count = -EFAULT; 1667ae5c961dSRajan Vaja err: 1668ae5c961dSRajan Vaja return count; 1669ae5c961dSRajan Vaja } 1670ae5c961dSRajan Vaja 1671ae5c961dSRajan Vaja /* GGS register show functions */ 1672ae5c961dSRajan Vaja #define GGS0_SHOW(N) \ 1673ae5c961dSRajan Vaja ssize_t ggs##N##_show(struct device *device, \ 1674ae5c961dSRajan Vaja struct device_attribute *attr, \ 1675ae5c961dSRajan Vaja char *buf) \ 1676ae5c961dSRajan Vaja { \ 1677ae5c961dSRajan Vaja return ggs_show(device, attr, buf, N); \ 1678ae5c961dSRajan Vaja } 1679ae5c961dSRajan Vaja 1680ae5c961dSRajan Vaja static GGS0_SHOW(0); 1681ae5c961dSRajan Vaja static GGS0_SHOW(1); 1682ae5c961dSRajan Vaja static GGS0_SHOW(2); 1683ae5c961dSRajan Vaja static GGS0_SHOW(3); 1684ae5c961dSRajan Vaja 1685ae5c961dSRajan Vaja /* GGS register store function */ 1686ae5c961dSRajan Vaja #define GGS0_STORE(N) \ 1687ae5c961dSRajan Vaja ssize_t ggs##N##_store(struct device *device, \ 1688ae5c961dSRajan Vaja struct device_attribute *attr, \ 1689ae5c961dSRajan Vaja const char *buf, \ 1690ae5c961dSRajan Vaja size_t count) \ 1691ae5c961dSRajan Vaja { \ 1692ae5c961dSRajan Vaja return ggs_store(device, attr, buf, count, N); \ 1693ae5c961dSRajan Vaja } 1694ae5c961dSRajan Vaja 1695ae5c961dSRajan Vaja static GGS0_STORE(0); 1696ae5c961dSRajan Vaja static GGS0_STORE(1); 1697ae5c961dSRajan Vaja static GGS0_STORE(2); 1698ae5c961dSRajan Vaja static GGS0_STORE(3); 1699ae5c961dSRajan Vaja 1700ae5c961dSRajan Vaja static ssize_t pggs_show(struct device *device, 1701ae5c961dSRajan Vaja struct device_attribute *attr, 1702ae5c961dSRajan Vaja char *buf, 1703ae5c961dSRajan Vaja u32 reg) 1704ae5c961dSRajan Vaja { 1705ae5c961dSRajan Vaja int ret; 1706ae5c961dSRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 1707ae5c961dSRajan Vaja 1708ae5c961dSRajan Vaja ret = zynqmp_pm_read_pggs(reg, ret_payload); 1709ae5c961dSRajan Vaja if (ret) 1710ae5c961dSRajan Vaja return ret; 1711ae5c961dSRajan Vaja 1712ae5c961dSRajan Vaja return sprintf(buf, "0x%x\n", ret_payload[1]); 1713ae5c961dSRajan Vaja } 1714ae5c961dSRajan Vaja 1715ae5c961dSRajan Vaja static ssize_t pggs_store(struct device *device, 1716ae5c961dSRajan Vaja struct device_attribute *attr, 1717ae5c961dSRajan Vaja const char *buf, size_t count, 1718ae5c961dSRajan Vaja u32 reg) 1719ae5c961dSRajan Vaja { 1720ae5c961dSRajan Vaja long value; 1721ae5c961dSRajan Vaja int ret; 1722ae5c961dSRajan Vaja 1723ae5c961dSRajan Vaja if (reg >= GSS_NUM_REGS) 1724ae5c961dSRajan Vaja return -EINVAL; 1725ae5c961dSRajan Vaja 1726ae5c961dSRajan Vaja ret = kstrtol(buf, 16, &value); 1727ae5c961dSRajan Vaja if (ret) { 1728ae5c961dSRajan Vaja count = -EFAULT; 1729ae5c961dSRajan Vaja goto err; 1730ae5c961dSRajan Vaja } 1731ae5c961dSRajan Vaja 1732ae5c961dSRajan Vaja ret = zynqmp_pm_write_pggs(reg, value); 1733ae5c961dSRajan Vaja if (ret) 1734ae5c961dSRajan Vaja count = -EFAULT; 1735ae5c961dSRajan Vaja 1736ae5c961dSRajan Vaja err: 1737ae5c961dSRajan Vaja return count; 1738ae5c961dSRajan Vaja } 1739ae5c961dSRajan Vaja 1740ae5c961dSRajan Vaja #define PGGS0_SHOW(N) \ 1741ae5c961dSRajan Vaja ssize_t pggs##N##_show(struct device *device, \ 1742ae5c961dSRajan Vaja struct device_attribute *attr, \ 1743ae5c961dSRajan Vaja char *buf) \ 1744ae5c961dSRajan Vaja { \ 1745ae5c961dSRajan Vaja return pggs_show(device, attr, buf, N); \ 1746ae5c961dSRajan Vaja } 1747ae5c961dSRajan Vaja 1748ae5c961dSRajan Vaja #define PGGS0_STORE(N) \ 1749ae5c961dSRajan Vaja ssize_t pggs##N##_store(struct device *device, \ 1750ae5c961dSRajan Vaja struct device_attribute *attr, \ 1751ae5c961dSRajan Vaja const char *buf, \ 1752ae5c961dSRajan Vaja size_t count) \ 1753ae5c961dSRajan Vaja { \ 1754ae5c961dSRajan Vaja return pggs_store(device, attr, buf, count, N); \ 1755ae5c961dSRajan Vaja } 1756ae5c961dSRajan Vaja 1757ae5c961dSRajan Vaja /* PGGS register show functions */ 1758ae5c961dSRajan Vaja static PGGS0_SHOW(0); 1759ae5c961dSRajan Vaja static PGGS0_SHOW(1); 1760ae5c961dSRajan Vaja static PGGS0_SHOW(2); 1761ae5c961dSRajan Vaja static PGGS0_SHOW(3); 1762ae5c961dSRajan Vaja 1763ae5c961dSRajan Vaja /* PGGS register store functions */ 1764ae5c961dSRajan Vaja static PGGS0_STORE(0); 1765ae5c961dSRajan Vaja static PGGS0_STORE(1); 1766ae5c961dSRajan Vaja static PGGS0_STORE(2); 1767ae5c961dSRajan Vaja static PGGS0_STORE(3); 1768ae5c961dSRajan Vaja 1769ae5c961dSRajan Vaja /* GGS register attributes */ 1770ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs0); 1771ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs1); 1772ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs2); 1773ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs3); 1774ae5c961dSRajan Vaja 1775ae5c961dSRajan Vaja /* PGGS register attributes */ 1776ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs0); 1777ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs1); 1778ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs2); 1779ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs3); 1780ae5c961dSRajan Vaja 17812c5d8f7cSRonak Jain static ssize_t feature_config_id_show(struct device *device, 17822c5d8f7cSRonak Jain struct device_attribute *attr, 17832c5d8f7cSRonak Jain char *buf) 17842c5d8f7cSRonak Jain { 17852c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device); 17862c5d8f7cSRonak Jain 17872c5d8f7cSRonak Jain return sysfs_emit(buf, "%d\n", devinfo->feature_conf_id); 17882c5d8f7cSRonak Jain } 17892c5d8f7cSRonak Jain 17902c5d8f7cSRonak Jain static ssize_t feature_config_id_store(struct device *device, 17912c5d8f7cSRonak Jain struct device_attribute *attr, 17922c5d8f7cSRonak Jain const char *buf, size_t count) 17932c5d8f7cSRonak Jain { 17942c5d8f7cSRonak Jain u32 config_id; 17952c5d8f7cSRonak Jain int ret; 17962c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device); 17972c5d8f7cSRonak Jain 17982c5d8f7cSRonak Jain if (!buf) 17992c5d8f7cSRonak Jain return -EINVAL; 18002c5d8f7cSRonak Jain 18012c5d8f7cSRonak Jain ret = kstrtou32(buf, 10, &config_id); 18022c5d8f7cSRonak Jain if (ret) 18032c5d8f7cSRonak Jain return ret; 18042c5d8f7cSRonak Jain 18052c5d8f7cSRonak Jain devinfo->feature_conf_id = config_id; 18062c5d8f7cSRonak Jain 18072c5d8f7cSRonak Jain return count; 18082c5d8f7cSRonak Jain } 18092c5d8f7cSRonak Jain 18102c5d8f7cSRonak Jain static DEVICE_ATTR_RW(feature_config_id); 18112c5d8f7cSRonak Jain 18122c5d8f7cSRonak Jain static ssize_t feature_config_value_show(struct device *device, 18132c5d8f7cSRonak Jain struct device_attribute *attr, 18142c5d8f7cSRonak Jain char *buf) 18152c5d8f7cSRonak Jain { 18162c5d8f7cSRonak Jain int ret; 18172c5d8f7cSRonak Jain u32 ret_payload[PAYLOAD_ARG_CNT]; 18182c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device); 18192c5d8f7cSRonak Jain 18202c5d8f7cSRonak Jain ret = zynqmp_pm_get_feature_config(devinfo->feature_conf_id, 18212c5d8f7cSRonak Jain ret_payload); 18222c5d8f7cSRonak Jain if (ret) 18232c5d8f7cSRonak Jain return ret; 18242c5d8f7cSRonak Jain 18252c5d8f7cSRonak Jain return sysfs_emit(buf, "%d\n", ret_payload[1]); 18262c5d8f7cSRonak Jain } 18272c5d8f7cSRonak Jain 18282c5d8f7cSRonak Jain static ssize_t feature_config_value_store(struct device *device, 18292c5d8f7cSRonak Jain struct device_attribute *attr, 18302c5d8f7cSRonak Jain const char *buf, size_t count) 18312c5d8f7cSRonak Jain { 18322c5d8f7cSRonak Jain u32 value; 18332c5d8f7cSRonak Jain int ret; 18342c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device); 18352c5d8f7cSRonak Jain 18362c5d8f7cSRonak Jain if (!buf) 18372c5d8f7cSRonak Jain return -EINVAL; 18382c5d8f7cSRonak Jain 18392c5d8f7cSRonak Jain ret = kstrtou32(buf, 10, &value); 18402c5d8f7cSRonak Jain if (ret) 18412c5d8f7cSRonak Jain return ret; 18422c5d8f7cSRonak Jain 18432c5d8f7cSRonak Jain ret = zynqmp_pm_set_feature_config(devinfo->feature_conf_id, 18442c5d8f7cSRonak Jain value); 18452c5d8f7cSRonak Jain if (ret) 18462c5d8f7cSRonak Jain return ret; 18472c5d8f7cSRonak Jain 18482c5d8f7cSRonak Jain return count; 18492c5d8f7cSRonak Jain } 18502c5d8f7cSRonak Jain 18512c5d8f7cSRonak Jain static DEVICE_ATTR_RW(feature_config_value); 18522c5d8f7cSRonak Jain 1853ae5c961dSRajan Vaja static struct attribute *zynqmp_firmware_attrs[] = { 1854ae5c961dSRajan Vaja &dev_attr_ggs0.attr, 1855ae5c961dSRajan Vaja &dev_attr_ggs1.attr, 1856ae5c961dSRajan Vaja &dev_attr_ggs2.attr, 1857ae5c961dSRajan Vaja &dev_attr_ggs3.attr, 1858ae5c961dSRajan Vaja &dev_attr_pggs0.attr, 1859ae5c961dSRajan Vaja &dev_attr_pggs1.attr, 1860ae5c961dSRajan Vaja &dev_attr_pggs2.attr, 1861ae5c961dSRajan Vaja &dev_attr_pggs3.attr, 1862b3ae24c4SRajan Vaja &dev_attr_shutdown_scope.attr, 1863a2cc220aSRajan Vaja &dev_attr_health_status.attr, 18642c5d8f7cSRonak Jain &dev_attr_feature_config_id.attr, 18652c5d8f7cSRonak Jain &dev_attr_feature_config_value.attr, 1866ae5c961dSRajan Vaja NULL, 1867ae5c961dSRajan Vaja }; 1868ae5c961dSRajan Vaja 1869ae5c961dSRajan Vaja ATTRIBUTE_GROUPS(zynqmp_firmware); 1870ae5c961dSRajan Vaja 187176582671SRajan Vaja static int zynqmp_firmware_probe(struct platform_device *pdev) 187276582671SRajan Vaja { 187376582671SRajan Vaja struct device *dev = &pdev->dev; 187476582671SRajan Vaja struct device_node *np; 18752c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo; 187676582671SRajan Vaja int ret; 187776582671SRajan Vaja 1878e5052becSRonak Jain ret = get_set_conduit_method(dev->of_node); 1879e5052becSRonak Jain if (ret) 1880e5052becSRonak Jain return ret; 1881e5052becSRonak Jain 188276582671SRajan Vaja np = of_find_compatible_node(NULL, NULL, "xlnx,zynqmp"); 1883af3f1afaSJolly Shah if (!np) { 1884af3f1afaSJolly Shah np = of_find_compatible_node(NULL, NULL, "xlnx,versal"); 188576582671SRajan Vaja if (!np) 188676582671SRajan Vaja return 0; 1887461011b1SRavi Patel 1888461011b1SRavi Patel feature_check_enabled = true; 1889af3f1afaSJolly Shah } 189076582671SRajan Vaja 1891e5052becSRonak Jain if (!feature_check_enabled) { 1892e5052becSRonak Jain ret = do_feature_check_call(PM_FEATURE_CHECK); 1893e5052becSRonak Jain if (ret >= 0) 1894e5052becSRonak Jain feature_check_enabled = true; 1895e5052becSRonak Jain } 1896e5052becSRonak Jain 1897e5052becSRonak Jain of_node_put(np); 189876582671SRajan Vaja 18992c5d8f7cSRonak Jain devinfo = devm_kzalloc(dev, sizeof(*devinfo), GFP_KERNEL); 19002c5d8f7cSRonak Jain if (!devinfo) 19012c5d8f7cSRonak Jain return -ENOMEM; 19022c5d8f7cSRonak Jain 19032c5d8f7cSRonak Jain devinfo->dev = dev; 19042c5d8f7cSRonak Jain 19052c5d8f7cSRonak Jain platform_set_drvdata(pdev, devinfo); 19062c5d8f7cSRonak Jain 190776582671SRajan Vaja /* Check PM API version number */ 1908168e05c1SRajan Vaja ret = zynqmp_pm_get_api_version(&pm_api_version); 1909168e05c1SRajan Vaja if (ret) 1910168e05c1SRajan Vaja return ret; 1911168e05c1SRajan Vaja 191276582671SRajan Vaja if (pm_api_version < ZYNQMP_PM_VERSION) { 191376582671SRajan Vaja panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n", 191476582671SRajan Vaja __func__, 191576582671SRajan Vaja ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR, 191676582671SRajan Vaja pm_api_version >> 16, pm_api_version & 0xFFFF); 191776582671SRajan Vaja } 191876582671SRajan Vaja 191976582671SRajan Vaja pr_info("%s Platform Management API v%d.%d\n", __func__, 192076582671SRajan Vaja pm_api_version >> 16, pm_api_version & 0xFFFF); 192176582671SRajan Vaja 192276582671SRajan Vaja /* Check trustzone version number */ 192376582671SRajan Vaja ret = zynqmp_pm_get_trustzone_version(&pm_tz_version); 192476582671SRajan Vaja if (ret) 192576582671SRajan Vaja panic("Legacy trustzone found without version support\n"); 192676582671SRajan Vaja 192776582671SRajan Vaja if (pm_tz_version < ZYNQMP_TZ_VERSION) 192876582671SRajan Vaja panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n", 192976582671SRajan Vaja __func__, 193076582671SRajan Vaja ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR, 193176582671SRajan Vaja pm_tz_version >> 16, pm_tz_version & 0xFFFF); 193276582671SRajan Vaja 193376582671SRajan Vaja pr_info("%s Trustzone version v%d.%d\n", __func__, 193476582671SRajan Vaja pm_tz_version >> 16, pm_tz_version & 0xFFFF); 193576582671SRajan Vaja 1936e23d9c6dSJolly Shah ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs, 1937e23d9c6dSJolly Shah ARRAY_SIZE(firmware_devs), NULL, 0, NULL); 1938e23d9c6dSJolly Shah if (ret) { 1939e23d9c6dSJolly Shah dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret); 1940e23d9c6dSJolly Shah return ret; 1941e23d9c6dSJolly Shah } 1942e23d9c6dSJolly Shah 194365f0539bSChristophe JAILLET zynqmp_pm_api_debugfs_init(); 194465f0539bSChristophe JAILLET 1945a515814eSAbhyuday Godhasara np = of_find_compatible_node(NULL, NULL, "xlnx,versal"); 1946a515814eSAbhyuday Godhasara if (np) { 1947a515814eSAbhyuday Godhasara em_dev = platform_device_register_data(&pdev->dev, "xlnx_event_manager", 1948a515814eSAbhyuday Godhasara -1, NULL, 0); 1949a515814eSAbhyuday Godhasara if (IS_ERR(em_dev)) 1950a515814eSAbhyuday Godhasara dev_err_probe(&pdev->dev, PTR_ERR(em_dev), "EM register fail with error\n"); 1951a515814eSAbhyuday Godhasara } 1952a515814eSAbhyuday Godhasara of_node_put(np); 1953a515814eSAbhyuday Godhasara 195476582671SRajan Vaja return of_platform_populate(dev->of_node, NULL, NULL, dev); 195576582671SRajan Vaja } 195676582671SRajan Vaja 195776582671SRajan Vaja static int zynqmp_firmware_remove(struct platform_device *pdev) 195876582671SRajan Vaja { 1959acfdd185SAmit Sunil Dhamne struct pm_api_feature_data *feature_data; 1960f1f21becSTejas Patel struct hlist_node *tmp; 1961acfdd185SAmit Sunil Dhamne int i; 1962acfdd185SAmit Sunil Dhamne 1963e23d9c6dSJolly Shah mfd_remove_devices(&pdev->dev); 1964b3217252SRajan Vaja zynqmp_pm_api_debugfs_exit(); 1965b3217252SRajan Vaja 1966f1f21becSTejas Patel hash_for_each_safe(pm_api_features_map, i, tmp, feature_data, hentry) { 1967acfdd185SAmit Sunil Dhamne hash_del(&feature_data->hentry); 1968acfdd185SAmit Sunil Dhamne kfree(feature_data); 1969acfdd185SAmit Sunil Dhamne } 1970acfdd185SAmit Sunil Dhamne 1971a515814eSAbhyuday Godhasara platform_device_unregister(em_dev); 1972a515814eSAbhyuday Godhasara 197376582671SRajan Vaja return 0; 197476582671SRajan Vaja } 197576582671SRajan Vaja 197676582671SRajan Vaja static const struct of_device_id zynqmp_firmware_of_match[] = { 197776582671SRajan Vaja {.compatible = "xlnx,zynqmp-firmware"}, 1978af3f1afaSJolly Shah {.compatible = "xlnx,versal-firmware"}, 197976582671SRajan Vaja {}, 198076582671SRajan Vaja }; 198176582671SRajan Vaja MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match); 198276582671SRajan Vaja 198376582671SRajan Vaja static struct platform_driver zynqmp_firmware_driver = { 198476582671SRajan Vaja .driver = { 198576582671SRajan Vaja .name = "zynqmp_firmware", 198676582671SRajan Vaja .of_match_table = zynqmp_firmware_of_match, 1987ae5c961dSRajan Vaja .dev_groups = zynqmp_firmware_groups, 198876582671SRajan Vaja }, 198976582671SRajan Vaja .probe = zynqmp_firmware_probe, 199076582671SRajan Vaja .remove = zynqmp_firmware_remove, 199176582671SRajan Vaja }; 199276582671SRajan Vaja module_platform_driver(zynqmp_firmware_driver); 1993