176582671SRajan Vaja // SPDX-License-Identifier: GPL-2.0 276582671SRajan Vaja /* 376582671SRajan Vaja * Xilinx Zynq MPSoC Firmware layer 476582671SRajan Vaja * 5ae5c961dSRajan Vaja * Copyright (C) 2014-2020 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> 2376582671SRajan Vaja 2476582671SRajan Vaja #include <linux/firmware/xlnx-zynqmp.h> 25b3217252SRajan Vaja #include "zynqmp-debug.h" 2676582671SRajan Vaja 27461011b1SRavi Patel static bool feature_check_enabled; 28461011b1SRavi Patel static u32 zynqmp_pm_features[PM_API_MAX]; 29461011b1SRavi Patel 30e23d9c6dSJolly Shah static const struct mfd_cell firmware_devs[] = { 31e23d9c6dSJolly Shah { 32e23d9c6dSJolly Shah .name = "zynqmp_power_controller", 33e23d9c6dSJolly Shah }, 34e23d9c6dSJolly Shah }; 35e23d9c6dSJolly Shah 3676582671SRajan Vaja /** 3776582671SRajan Vaja * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes 3876582671SRajan Vaja * @ret_status: PMUFW return code 3976582671SRajan Vaja * 4076582671SRajan Vaja * Return: corresponding Linux error code 4176582671SRajan Vaja */ 4276582671SRajan Vaja static int zynqmp_pm_ret_code(u32 ret_status) 4376582671SRajan Vaja { 4476582671SRajan Vaja switch (ret_status) { 4576582671SRajan Vaja case XST_PM_SUCCESS: 4676582671SRajan Vaja case XST_PM_DOUBLE_REQ: 4776582671SRajan Vaja return 0; 48461011b1SRavi Patel case XST_PM_NO_FEATURE: 49461011b1SRavi Patel return -ENOTSUPP; 5076582671SRajan Vaja case XST_PM_NO_ACCESS: 5176582671SRajan Vaja return -EACCES; 5276582671SRajan Vaja case XST_PM_ABORT_SUSPEND: 5376582671SRajan Vaja return -ECANCELED; 54df2a4d94SRajan Vaja case XST_PM_MULT_USER: 55df2a4d94SRajan Vaja return -EUSERS; 5676582671SRajan Vaja case XST_PM_INTERNAL: 5776582671SRajan Vaja case XST_PM_CONFLICT: 5876582671SRajan Vaja case XST_PM_INVALID_NODE: 5976582671SRajan Vaja default: 6076582671SRajan Vaja return -EINVAL; 6176582671SRajan Vaja } 6276582671SRajan Vaja } 6376582671SRajan Vaja 6476582671SRajan Vaja static noinline int do_fw_call_fail(u64 arg0, u64 arg1, u64 arg2, 6576582671SRajan Vaja u32 *ret_payload) 6676582671SRajan Vaja { 6776582671SRajan Vaja return -ENODEV; 6876582671SRajan Vaja } 6976582671SRajan Vaja 7076582671SRajan Vaja /* 7176582671SRajan Vaja * PM function call wrapper 7276582671SRajan Vaja * Invoke do_fw_call_smc or do_fw_call_hvc, depending on the configuration 7376582671SRajan Vaja */ 7476582671SRajan Vaja static int (*do_fw_call)(u64, u64, u64, u32 *ret_payload) = do_fw_call_fail; 7576582671SRajan Vaja 7676582671SRajan Vaja /** 7776582671SRajan Vaja * do_fw_call_smc() - Call system-level platform management layer (SMC) 7876582671SRajan Vaja * @arg0: Argument 0 to SMC call 7976582671SRajan Vaja * @arg1: Argument 1 to SMC call 8076582671SRajan Vaja * @arg2: Argument 2 to SMC call 8176582671SRajan Vaja * @ret_payload: Returned value array 8276582671SRajan Vaja * 8376582671SRajan Vaja * Invoke platform management function via SMC call (no hypervisor present). 8476582671SRajan Vaja * 8576582671SRajan Vaja * Return: Returns status, either success or error+reason 8676582671SRajan Vaja */ 8776582671SRajan Vaja static noinline int do_fw_call_smc(u64 arg0, u64 arg1, u64 arg2, 8876582671SRajan Vaja u32 *ret_payload) 8976582671SRajan Vaja { 9076582671SRajan Vaja struct arm_smccc_res res; 9176582671SRajan Vaja 9276582671SRajan Vaja arm_smccc_smc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res); 9376582671SRajan Vaja 9476582671SRajan Vaja if (ret_payload) { 9576582671SRajan Vaja ret_payload[0] = lower_32_bits(res.a0); 9676582671SRajan Vaja ret_payload[1] = upper_32_bits(res.a0); 9776582671SRajan Vaja ret_payload[2] = lower_32_bits(res.a1); 9876582671SRajan Vaja ret_payload[3] = upper_32_bits(res.a1); 9976582671SRajan Vaja } 10076582671SRajan Vaja 10176582671SRajan Vaja return zynqmp_pm_ret_code((enum pm_ret_status)res.a0); 10276582671SRajan Vaja } 10376582671SRajan Vaja 10476582671SRajan Vaja /** 10576582671SRajan Vaja * do_fw_call_hvc() - Call system-level platform management layer (HVC) 10676582671SRajan Vaja * @arg0: Argument 0 to HVC call 10776582671SRajan Vaja * @arg1: Argument 1 to HVC call 10876582671SRajan Vaja * @arg2: Argument 2 to HVC call 10976582671SRajan Vaja * @ret_payload: Returned value array 11076582671SRajan Vaja * 11176582671SRajan Vaja * Invoke platform management function via HVC 11276582671SRajan Vaja * HVC-based for communication through hypervisor 11376582671SRajan Vaja * (no direct communication with ATF). 11476582671SRajan Vaja * 11576582671SRajan Vaja * Return: Returns status, either success or error+reason 11676582671SRajan Vaja */ 11776582671SRajan Vaja static noinline int do_fw_call_hvc(u64 arg0, u64 arg1, u64 arg2, 11876582671SRajan Vaja u32 *ret_payload) 11976582671SRajan Vaja { 12076582671SRajan Vaja struct arm_smccc_res res; 12176582671SRajan Vaja 12276582671SRajan Vaja arm_smccc_hvc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res); 12376582671SRajan Vaja 12476582671SRajan Vaja if (ret_payload) { 12576582671SRajan Vaja ret_payload[0] = lower_32_bits(res.a0); 12676582671SRajan Vaja ret_payload[1] = upper_32_bits(res.a0); 12776582671SRajan Vaja ret_payload[2] = lower_32_bits(res.a1); 12876582671SRajan Vaja ret_payload[3] = upper_32_bits(res.a1); 12976582671SRajan Vaja } 13076582671SRajan Vaja 13176582671SRajan Vaja return zynqmp_pm_ret_code((enum pm_ret_status)res.a0); 13276582671SRajan Vaja } 13376582671SRajan Vaja 13476582671SRajan Vaja /** 135461011b1SRavi Patel * zynqmp_pm_feature() - Check weather given feature is supported or not 136461011b1SRavi Patel * @api_id: API ID to check 137461011b1SRavi Patel * 138461011b1SRavi Patel * Return: Returns status, either success or error+reason 139461011b1SRavi Patel */ 140461011b1SRavi Patel static int zynqmp_pm_feature(u32 api_id) 141461011b1SRavi Patel { 142461011b1SRavi Patel int ret; 143461011b1SRavi Patel u32 ret_payload[PAYLOAD_ARG_CNT]; 144461011b1SRavi Patel u64 smc_arg[2]; 145461011b1SRavi Patel 146461011b1SRavi Patel if (!feature_check_enabled) 147461011b1SRavi Patel return 0; 148461011b1SRavi Patel 149461011b1SRavi Patel /* Return value if feature is already checked */ 150f3217d6fSArnd Bergmann if (api_id > ARRAY_SIZE(zynqmp_pm_features)) 151f3217d6fSArnd Bergmann return PM_FEATURE_INVALID; 152f3217d6fSArnd Bergmann 153461011b1SRavi Patel if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED) 154461011b1SRavi Patel return zynqmp_pm_features[api_id]; 155461011b1SRavi Patel 156461011b1SRavi Patel smc_arg[0] = PM_SIP_SVC | PM_FEATURE_CHECK; 157461011b1SRavi Patel smc_arg[1] = api_id; 158461011b1SRavi Patel 159461011b1SRavi Patel ret = do_fw_call(smc_arg[0], smc_arg[1], 0, ret_payload); 160461011b1SRavi Patel if (ret) { 161461011b1SRavi Patel zynqmp_pm_features[api_id] = PM_FEATURE_INVALID; 162461011b1SRavi Patel return PM_FEATURE_INVALID; 163461011b1SRavi Patel } 164461011b1SRavi Patel 165461011b1SRavi Patel zynqmp_pm_features[api_id] = ret_payload[1]; 166461011b1SRavi Patel 167461011b1SRavi Patel return zynqmp_pm_features[api_id]; 168461011b1SRavi Patel } 169461011b1SRavi Patel 170461011b1SRavi Patel /** 17176582671SRajan Vaja * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer 17276582671SRajan Vaja * caller function depending on the configuration 17376582671SRajan Vaja * @pm_api_id: Requested PM-API call 17476582671SRajan Vaja * @arg0: Argument 0 to requested PM-API call 17576582671SRajan Vaja * @arg1: Argument 1 to requested PM-API call 17676582671SRajan Vaja * @arg2: Argument 2 to requested PM-API call 17776582671SRajan Vaja * @arg3: Argument 3 to requested PM-API call 17876582671SRajan Vaja * @ret_payload: Returned value array 17976582671SRajan Vaja * 18076582671SRajan Vaja * Invoke platform management function for SMC or HVC call, depending on 18176582671SRajan Vaja * configuration. 18276582671SRajan Vaja * Following SMC Calling Convention (SMCCC) for SMC64: 18376582671SRajan Vaja * Pm Function Identifier, 18476582671SRajan Vaja * PM_SIP_SVC + PM_API_ID = 18576582671SRajan Vaja * ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) 18676582671SRajan Vaja * ((SMC_64) << FUNCID_CC_SHIFT) 18776582671SRajan Vaja * ((SIP_START) << FUNCID_OEN_SHIFT) 18876582671SRajan Vaja * ((PM_API_ID) & FUNCID_NUM_MASK)) 18976582671SRajan Vaja * 19076582671SRajan Vaja * PM_SIP_SVC - Registered ZynqMP SIP Service Call. 19176582671SRajan Vaja * PM_API_ID - Platform Management API ID. 19276582671SRajan Vaja * 19376582671SRajan Vaja * Return: Returns status, either success or error+reason 19476582671SRajan Vaja */ 19576582671SRajan Vaja int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1, 19676582671SRajan Vaja u32 arg2, u32 arg3, u32 *ret_payload) 19776582671SRajan Vaja { 19876582671SRajan Vaja /* 19976582671SRajan Vaja * Added SIP service call Function Identifier 20076582671SRajan Vaja * Make sure to stay in x0 register 20176582671SRajan Vaja */ 20276582671SRajan Vaja u64 smc_arg[4]; 20376582671SRajan Vaja 204461011b1SRavi Patel if (zynqmp_pm_feature(pm_api_id) == PM_FEATURE_INVALID) 205461011b1SRavi Patel return -ENOTSUPP; 206461011b1SRavi Patel 20776582671SRajan Vaja smc_arg[0] = PM_SIP_SVC | pm_api_id; 20876582671SRajan Vaja smc_arg[1] = ((u64)arg1 << 32) | arg0; 20976582671SRajan Vaja smc_arg[2] = ((u64)arg3 << 32) | arg2; 21076582671SRajan Vaja 21176582671SRajan Vaja return do_fw_call(smc_arg[0], smc_arg[1], smc_arg[2], ret_payload); 21276582671SRajan Vaja } 21376582671SRajan Vaja 21476582671SRajan Vaja static u32 pm_api_version; 21576582671SRajan Vaja static u32 pm_tz_version; 21676582671SRajan Vaja 21776582671SRajan Vaja /** 21876582671SRajan Vaja * zynqmp_pm_get_api_version() - Get version number of PMU PM firmware 21976582671SRajan Vaja * @version: Returned version value 22076582671SRajan Vaja * 22176582671SRajan Vaja * Return: Returns status, either success or error+reason 22276582671SRajan Vaja */ 223b9b3a8beSRajan Vaja int zynqmp_pm_get_api_version(u32 *version) 22476582671SRajan Vaja { 22576582671SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 22676582671SRajan Vaja int ret; 22776582671SRajan Vaja 22876582671SRajan Vaja if (!version) 22976582671SRajan Vaja return -EINVAL; 23076582671SRajan Vaja 23176582671SRajan Vaja /* Check is PM API version already verified */ 23276582671SRajan Vaja if (pm_api_version > 0) { 23376582671SRajan Vaja *version = pm_api_version; 23476582671SRajan Vaja return 0; 23576582671SRajan Vaja } 23676582671SRajan Vaja ret = zynqmp_pm_invoke_fn(PM_GET_API_VERSION, 0, 0, 0, 0, ret_payload); 23776582671SRajan Vaja *version = ret_payload[1]; 23876582671SRajan Vaja 23976582671SRajan Vaja return ret; 24076582671SRajan Vaja } 241b9b3a8beSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_api_version); 24276582671SRajan Vaja 24376582671SRajan Vaja /** 244fe6f42cfSNava kishore Manne * zynqmp_pm_get_chipid - Get silicon ID registers 245fe6f42cfSNava kishore Manne * @idcode: IDCODE register 246fe6f42cfSNava kishore Manne * @version: version register 247fe6f42cfSNava kishore Manne * 248fe6f42cfSNava kishore Manne * Return: Returns the status of the operation and the idcode and version 249fe6f42cfSNava kishore Manne * registers in @idcode and @version. 250fe6f42cfSNava kishore Manne */ 25121cd93baSRajan Vaja int zynqmp_pm_get_chipid(u32 *idcode, u32 *version) 252fe6f42cfSNava kishore Manne { 253fe6f42cfSNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT]; 254fe6f42cfSNava kishore Manne int ret; 255fe6f42cfSNava kishore Manne 256fe6f42cfSNava kishore Manne if (!idcode || !version) 257fe6f42cfSNava kishore Manne return -EINVAL; 258fe6f42cfSNava kishore Manne 259fe6f42cfSNava kishore Manne ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload); 260fe6f42cfSNava kishore Manne *idcode = ret_payload[1]; 261fe6f42cfSNava kishore Manne *version = ret_payload[2]; 262fe6f42cfSNava kishore Manne 263fe6f42cfSNava kishore Manne return ret; 264fe6f42cfSNava kishore Manne } 26521cd93baSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_chipid); 266fe6f42cfSNava kishore Manne 267fe6f42cfSNava kishore Manne /** 26876582671SRajan Vaja * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version 26976582671SRajan Vaja * @version: Returned version value 27076582671SRajan Vaja * 27176582671SRajan Vaja * Return: Returns status, either success or error+reason 27276582671SRajan Vaja */ 27376582671SRajan Vaja static int zynqmp_pm_get_trustzone_version(u32 *version) 27476582671SRajan Vaja { 27576582671SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 27676582671SRajan Vaja int ret; 27776582671SRajan Vaja 27876582671SRajan Vaja if (!version) 27976582671SRajan Vaja return -EINVAL; 28076582671SRajan Vaja 28176582671SRajan Vaja /* Check is PM trustzone version already verified */ 28276582671SRajan Vaja if (pm_tz_version > 0) { 28376582671SRajan Vaja *version = pm_tz_version; 28476582671SRajan Vaja return 0; 28576582671SRajan Vaja } 28676582671SRajan Vaja ret = zynqmp_pm_invoke_fn(PM_GET_TRUSTZONE_VERSION, 0, 0, 28776582671SRajan Vaja 0, 0, ret_payload); 28876582671SRajan Vaja *version = ret_payload[1]; 28976582671SRajan Vaja 29076582671SRajan Vaja return ret; 29176582671SRajan Vaja } 29276582671SRajan Vaja 29376582671SRajan Vaja /** 29476582671SRajan Vaja * get_set_conduit_method() - Choose SMC or HVC based communication 29576582671SRajan Vaja * @np: Pointer to the device_node structure 29676582671SRajan Vaja * 29776582671SRajan Vaja * Use SMC or HVC-based functions to communicate with EL2/EL3. 29876582671SRajan Vaja * 29976582671SRajan Vaja * Return: Returns 0 on success or error code 30076582671SRajan Vaja */ 30176582671SRajan Vaja static int get_set_conduit_method(struct device_node *np) 30276582671SRajan Vaja { 30376582671SRajan Vaja const char *method; 30476582671SRajan Vaja 30576582671SRajan Vaja if (of_property_read_string(np, "method", &method)) { 30676582671SRajan Vaja pr_warn("%s missing \"method\" property\n", __func__); 30776582671SRajan Vaja return -ENXIO; 30876582671SRajan Vaja } 30976582671SRajan Vaja 31076582671SRajan Vaja if (!strcmp("hvc", method)) { 31176582671SRajan Vaja do_fw_call = do_fw_call_hvc; 31276582671SRajan Vaja } else if (!strcmp("smc", method)) { 31376582671SRajan Vaja do_fw_call = do_fw_call_smc; 31476582671SRajan Vaja } else { 31576582671SRajan Vaja pr_warn("%s Invalid \"method\" property: %s\n", 31676582671SRajan Vaja __func__, method); 31776582671SRajan Vaja return -EINVAL; 31876582671SRajan Vaja } 31976582671SRajan Vaja 32076582671SRajan Vaja return 0; 32176582671SRajan Vaja } 32276582671SRajan Vaja 32359ecdd77SRajan Vaja /** 32459ecdd77SRajan Vaja * zynqmp_pm_query_data() - Get query data from firmware 32559ecdd77SRajan Vaja * @qdata: Variable to the zynqmp_pm_query_data structure 32659ecdd77SRajan Vaja * @out: Returned output value 32759ecdd77SRajan Vaja * 32859ecdd77SRajan Vaja * Return: Returns status, either success or error+reason 32959ecdd77SRajan Vaja */ 3306366c1baSRajan Vaja int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out) 33159ecdd77SRajan Vaja { 332f9627312SRajan Vaja int ret; 333f9627312SRajan Vaja 334f9627312SRajan Vaja ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, qdata.qid, qdata.arg1, 33559ecdd77SRajan Vaja qdata.arg2, qdata.arg3, out); 336f9627312SRajan Vaja 337f9627312SRajan Vaja /* 338f9627312SRajan Vaja * For clock name query, all bytes in SMC response are clock name 339f9627312SRajan Vaja * characters and return code is always success. For invalid clocks, 340f9627312SRajan Vaja * clock name bytes would be zeros. 341f9627312SRajan Vaja */ 342f9627312SRajan Vaja return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret; 343f9627312SRajan Vaja } 3446366c1baSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_query_data); 345f9627312SRajan Vaja 346f9627312SRajan Vaja /** 347f9627312SRajan Vaja * zynqmp_pm_clock_enable() - Enable the clock for given id 348f9627312SRajan Vaja * @clock_id: ID of the clock to be enabled 349f9627312SRajan Vaja * 350f9627312SRajan Vaja * This function is used by master to enable the clock 351f9627312SRajan Vaja * including peripherals and PLL clocks. 352f9627312SRajan Vaja * 353f9627312SRajan Vaja * Return: Returns status, either success or error+reason 354f9627312SRajan Vaja */ 3553637e84cSRajan Vaja int zynqmp_pm_clock_enable(u32 clock_id) 356f9627312SRajan Vaja { 357f9627312SRajan Vaja return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL); 358f9627312SRajan Vaja } 3593637e84cSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_enable); 360f9627312SRajan Vaja 361f9627312SRajan Vaja /** 362f9627312SRajan Vaja * zynqmp_pm_clock_disable() - Disable the clock for given id 363f9627312SRajan Vaja * @clock_id: ID of the clock to be disable 364f9627312SRajan Vaja * 365f9627312SRajan Vaja * This function is used by master to disable the clock 366f9627312SRajan Vaja * including peripherals and PLL clocks. 367f9627312SRajan Vaja * 368f9627312SRajan Vaja * Return: Returns status, either success or error+reason 369f9627312SRajan Vaja */ 370f5ccd54bSRajan Vaja int zynqmp_pm_clock_disable(u32 clock_id) 371f9627312SRajan Vaja { 372f9627312SRajan Vaja return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL); 373f9627312SRajan Vaja } 374f5ccd54bSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_disable); 375f9627312SRajan Vaja 376f9627312SRajan Vaja /** 377f9627312SRajan Vaja * zynqmp_pm_clock_getstate() - Get the clock state for given id 378f9627312SRajan Vaja * @clock_id: ID of the clock to be queried 379f9627312SRajan Vaja * @state: 1/0 (Enabled/Disabled) 380f9627312SRajan Vaja * 381f9627312SRajan Vaja * This function is used by master to get the state of clock 382f9627312SRajan Vaja * including peripherals and PLL clocks. 383f9627312SRajan Vaja * 384f9627312SRajan Vaja * Return: Returns status, either success or error+reason 385f9627312SRajan Vaja */ 3865e76731dSRajan Vaja int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state) 387f9627312SRajan Vaja { 388f9627312SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 389f9627312SRajan Vaja int ret; 390f9627312SRajan Vaja 391f9627312SRajan Vaja ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, clock_id, 0, 392f9627312SRajan Vaja 0, 0, ret_payload); 393f9627312SRajan Vaja *state = ret_payload[1]; 394f9627312SRajan Vaja 395f9627312SRajan Vaja return ret; 396f9627312SRajan Vaja } 3975e76731dSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getstate); 398f9627312SRajan Vaja 399f9627312SRajan Vaja /** 400f9627312SRajan Vaja * zynqmp_pm_clock_setdivider() - Set the clock divider for given id 401f9627312SRajan Vaja * @clock_id: ID of the clock 402f9627312SRajan Vaja * @divider: divider value 403f9627312SRajan Vaja * 404f9627312SRajan Vaja * This function is used by master to set divider for any clock 405f9627312SRajan Vaja * to achieve desired rate. 406f9627312SRajan Vaja * 407f9627312SRajan Vaja * Return: Returns status, either success or error+reason 408f9627312SRajan Vaja */ 409fc9fb8fbSRajan Vaja int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider) 410f9627312SRajan Vaja { 411f9627312SRajan Vaja return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, clock_id, divider, 412f9627312SRajan Vaja 0, 0, NULL); 413f9627312SRajan Vaja } 414fc9fb8fbSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setdivider); 415f9627312SRajan Vaja 416f9627312SRajan Vaja /** 417f9627312SRajan Vaja * zynqmp_pm_clock_getdivider() - Get the clock divider for given id 418f9627312SRajan Vaja * @clock_id: ID of the clock 419f9627312SRajan Vaja * @divider: divider value 420f9627312SRajan Vaja * 421f9627312SRajan Vaja * This function is used by master to get divider values 422f9627312SRajan Vaja * for any clock. 423f9627312SRajan Vaja * 424f9627312SRajan Vaja * Return: Returns status, either success or error+reason 425f9627312SRajan Vaja */ 4260667a8d1SRajan Vaja int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider) 427f9627312SRajan Vaja { 428f9627312SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 429f9627312SRajan Vaja int ret; 430f9627312SRajan Vaja 431f9627312SRajan Vaja ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, clock_id, 0, 432f9627312SRajan Vaja 0, 0, ret_payload); 433f9627312SRajan Vaja *divider = ret_payload[1]; 434f9627312SRajan Vaja 435f9627312SRajan Vaja return ret; 436f9627312SRajan Vaja } 4370667a8d1SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getdivider); 438f9627312SRajan Vaja 439f9627312SRajan Vaja /** 440f9627312SRajan Vaja * zynqmp_pm_clock_setrate() - Set the clock rate for given id 441f9627312SRajan Vaja * @clock_id: ID of the clock 442f9627312SRajan Vaja * @rate: rate value in hz 443f9627312SRajan Vaja * 444f9627312SRajan Vaja * This function is used by master to set rate for any clock. 445f9627312SRajan Vaja * 446f9627312SRajan Vaja * Return: Returns status, either success or error+reason 447f9627312SRajan Vaja */ 4487a1e1062SRajan Vaja int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate) 449f9627312SRajan Vaja { 450f9627312SRajan Vaja return zynqmp_pm_invoke_fn(PM_CLOCK_SETRATE, clock_id, 451f9627312SRajan Vaja lower_32_bits(rate), 452f9627312SRajan Vaja upper_32_bits(rate), 453f9627312SRajan Vaja 0, NULL); 454f9627312SRajan Vaja } 4557a1e1062SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setrate); 456f9627312SRajan Vaja 457f9627312SRajan Vaja /** 458f9627312SRajan Vaja * zynqmp_pm_clock_getrate() - Get the clock rate for given id 459f9627312SRajan Vaja * @clock_id: ID of the clock 460f9627312SRajan Vaja * @rate: rate value in hz 461f9627312SRajan Vaja * 462f9627312SRajan Vaja * This function is used by master to get rate 463f9627312SRajan Vaja * for any clock. 464f9627312SRajan Vaja * 465f9627312SRajan Vaja * Return: Returns status, either success or error+reason 466f9627312SRajan Vaja */ 4677a1e1062SRajan Vaja int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate) 468f9627312SRajan Vaja { 469f9627312SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 470f9627312SRajan Vaja int ret; 471f9627312SRajan Vaja 472f9627312SRajan Vaja ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETRATE, clock_id, 0, 473f9627312SRajan Vaja 0, 0, ret_payload); 474f9627312SRajan Vaja *rate = ((u64)ret_payload[2] << 32) | ret_payload[1]; 475f9627312SRajan Vaja 476f9627312SRajan Vaja return ret; 477f9627312SRajan Vaja } 4787a1e1062SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getrate); 479f9627312SRajan Vaja 480f9627312SRajan Vaja /** 481f9627312SRajan Vaja * zynqmp_pm_clock_setparent() - Set the clock parent for given id 482f9627312SRajan Vaja * @clock_id: ID of the clock 483f9627312SRajan Vaja * @parent_id: parent id 484f9627312SRajan Vaja * 485f9627312SRajan Vaja * This function is used by master to set parent for any clock. 486f9627312SRajan Vaja * 487f9627312SRajan Vaja * Return: Returns status, either success or error+reason 488f9627312SRajan Vaja */ 48970c0d364SRajan Vaja int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id) 490f9627312SRajan Vaja { 491f9627312SRajan Vaja return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, clock_id, 492f9627312SRajan Vaja parent_id, 0, 0, NULL); 493f9627312SRajan Vaja } 49470c0d364SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setparent); 495f9627312SRajan Vaja 496f9627312SRajan Vaja /** 497f9627312SRajan Vaja * zynqmp_pm_clock_getparent() - Get the clock parent for given id 498f9627312SRajan Vaja * @clock_id: ID of the clock 499f9627312SRajan Vaja * @parent_id: parent id 500f9627312SRajan Vaja * 501f9627312SRajan Vaja * This function is used by master to get parent index 502f9627312SRajan Vaja * for any clock. 503f9627312SRajan Vaja * 504f9627312SRajan Vaja * Return: Returns status, either success or error+reason 505f9627312SRajan Vaja */ 50670c0d364SRajan Vaja int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id) 507f9627312SRajan Vaja { 508f9627312SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 509f9627312SRajan Vaja int ret; 510f9627312SRajan Vaja 511f9627312SRajan Vaja ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, clock_id, 0, 512f9627312SRajan Vaja 0, 0, ret_payload); 513f9627312SRajan Vaja *parent_id = ret_payload[1]; 514f9627312SRajan Vaja 515f9627312SRajan Vaja return ret; 51659ecdd77SRajan Vaja } 51770c0d364SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getparent); 51859ecdd77SRajan Vaja 5193b0296b8SRajan Vaja /** 520426c8d85SRajan Vaja * zynqmp_pm_set_pll_frac_mode() - PM API for set PLL mode 5213b0296b8SRajan Vaja * 522426c8d85SRajan Vaja * @clk_id: PLL clock ID 523426c8d85SRajan Vaja * @mode: PLL mode (PLL_MODE_FRAC/PLL_MODE_INT) 5243b0296b8SRajan Vaja * 525426c8d85SRajan Vaja * This function sets PLL mode 5263b0296b8SRajan Vaja * 5273b0296b8SRajan Vaja * Return: Returns status, either success or error+reason 5283b0296b8SRajan Vaja */ 529426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_mode(u32 clk_id, u32 mode) 5303b0296b8SRajan Vaja { 531426c8d85SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_MODE, 532426c8d85SRajan Vaja clk_id, mode, NULL); 5333b0296b8SRajan Vaja } 534426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_mode); 535426c8d85SRajan Vaja 536426c8d85SRajan Vaja /** 537426c8d85SRajan Vaja * zynqmp_pm_get_pll_frac_mode() - PM API for get PLL mode 538426c8d85SRajan Vaja * 539426c8d85SRajan Vaja * @clk_id: PLL clock ID 540426c8d85SRajan Vaja * @mode: PLL mode 541426c8d85SRajan Vaja * 542426c8d85SRajan Vaja * This function return current PLL mode 543426c8d85SRajan Vaja * 544426c8d85SRajan Vaja * Return: Returns status, either success or error+reason 545426c8d85SRajan Vaja */ 546426c8d85SRajan Vaja int zynqmp_pm_get_pll_frac_mode(u32 clk_id, u32 *mode) 547426c8d85SRajan Vaja { 548426c8d85SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_MODE, 549426c8d85SRajan Vaja clk_id, 0, mode); 550426c8d85SRajan Vaja } 551426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_mode); 552426c8d85SRajan Vaja 553426c8d85SRajan Vaja /** 554426c8d85SRajan Vaja * zynqmp_pm_set_pll_frac_data() - PM API for setting pll fraction data 555426c8d85SRajan Vaja * 556426c8d85SRajan Vaja * @clk_id: PLL clock ID 557426c8d85SRajan Vaja * @data: fraction data 558426c8d85SRajan Vaja * 559426c8d85SRajan Vaja * This function sets fraction data. 560426c8d85SRajan Vaja * It is valid for fraction mode only. 561426c8d85SRajan Vaja * 562426c8d85SRajan Vaja * Return: Returns status, either success or error+reason 563426c8d85SRajan Vaja */ 564426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_data(u32 clk_id, u32 data) 565426c8d85SRajan Vaja { 566426c8d85SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_DATA, 567426c8d85SRajan Vaja clk_id, data, NULL); 568426c8d85SRajan Vaja } 569426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_data); 570426c8d85SRajan Vaja 571426c8d85SRajan Vaja /** 572426c8d85SRajan Vaja * zynqmp_pm_get_pll_frac_data() - PM API for getting pll fraction data 573426c8d85SRajan Vaja * 574426c8d85SRajan Vaja * @clk_id: PLL clock ID 575426c8d85SRajan Vaja * @data: fraction data 576426c8d85SRajan Vaja * 577426c8d85SRajan Vaja * This function returns fraction data value. 578426c8d85SRajan Vaja * 579426c8d85SRajan Vaja * Return: Returns status, either success or error+reason 580426c8d85SRajan Vaja */ 581426c8d85SRajan Vaja int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data) 582426c8d85SRajan Vaja { 583426c8d85SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_DATA, 584426c8d85SRajan Vaja clk_id, 0, data); 585426c8d85SRajan Vaja } 586426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data); 587426c8d85SRajan Vaja 588426c8d85SRajan Vaja /** 589426c8d85SRajan Vaja * zynqmp_pm_set_sd_tapdelay() - Set tap delay for the SD device 590426c8d85SRajan Vaja * 591426c8d85SRajan Vaja * @node_id Node ID of the device 592426c8d85SRajan Vaja * @type Type of tap delay to set (input/output) 593426c8d85SRajan Vaja * @value Value to set fot the tap delay 594426c8d85SRajan Vaja * 595426c8d85SRajan Vaja * This function sets input/output tap delay for the SD device. 596426c8d85SRajan Vaja * 597426c8d85SRajan Vaja * @return Returns status, either success or error+reason 598426c8d85SRajan Vaja */ 599426c8d85SRajan Vaja int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value) 600426c8d85SRajan Vaja { 601426c8d85SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY, 602426c8d85SRajan Vaja type, value, NULL); 603426c8d85SRajan Vaja } 604426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay); 605426c8d85SRajan Vaja 606426c8d85SRajan Vaja /** 607426c8d85SRajan Vaja * zynqmp_pm_sd_dll_reset() - Reset DLL logic 608426c8d85SRajan Vaja * 609426c8d85SRajan Vaja * @node_id Node ID of the device 610426c8d85SRajan Vaja * @type Reset type 611426c8d85SRajan Vaja * 612426c8d85SRajan Vaja * This function resets DLL logic for the SD device. 613426c8d85SRajan Vaja * 614426c8d85SRajan Vaja * @return Returns status, either success or error+reason 615426c8d85SRajan Vaja */ 616426c8d85SRajan Vaja int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type) 617426c8d85SRajan Vaja { 618f4426311SManish Narani return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SD_DLL_RESET, 619426c8d85SRajan Vaja type, 0, NULL); 620426c8d85SRajan Vaja } 621426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset); 6223b0296b8SRajan Vaja 623bc3843d4SNava kishore Manne /** 6244f680b72SRajan Vaja * zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs) 6254f680b72SRajan Vaja * @index GGS register index 6264f680b72SRajan Vaja * @value Register value to be written 6274f680b72SRajan Vaja * 6284f680b72SRajan Vaja * This function writes value to GGS register. 6294f680b72SRajan Vaja * 6304f680b72SRajan Vaja * @return Returns status, either success or error+reason 6314f680b72SRajan Vaja */ 6324f680b72SRajan Vaja int zynqmp_pm_write_ggs(u32 index, u32 value) 6334f680b72SRajan Vaja { 6344f680b72SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_GGS, 6354f680b72SRajan Vaja index, value, NULL); 6364f680b72SRajan Vaja } 6374f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs); 6384f680b72SRajan Vaja 6394f680b72SRajan Vaja /** 6404f680b72SRajan Vaja * zynqmp_pm_write_ggs() - PM API for reading global general storage (ggs) 6414f680b72SRajan Vaja * @index GGS register index 6424f680b72SRajan Vaja * @value Register value to be written 6434f680b72SRajan Vaja * 6444f680b72SRajan Vaja * This function returns GGS register value. 6454f680b72SRajan Vaja * 6464f680b72SRajan Vaja * @return Returns status, either success or error+reason 6474f680b72SRajan Vaja */ 6484f680b72SRajan Vaja int zynqmp_pm_read_ggs(u32 index, u32 *value) 6494f680b72SRajan Vaja { 6504f680b72SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_GGS, 6514f680b72SRajan Vaja index, 0, value); 6524f680b72SRajan Vaja } 6534f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs); 6544f680b72SRajan Vaja 6554f680b72SRajan Vaja /** 6564f680b72SRajan Vaja * zynqmp_pm_write_pggs() - PM API for writing persistent global general 6574f680b72SRajan Vaja * storage (pggs) 6584f680b72SRajan Vaja * @index PGGS register index 6594f680b72SRajan Vaja * @value Register value to be written 6604f680b72SRajan Vaja * 6614f680b72SRajan Vaja * This function writes value to PGGS register. 6624f680b72SRajan Vaja * 6634f680b72SRajan Vaja * @return Returns status, either success or error+reason 6644f680b72SRajan Vaja */ 6654f680b72SRajan Vaja int zynqmp_pm_write_pggs(u32 index, u32 value) 6664f680b72SRajan Vaja { 6674f680b72SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_PGGS, index, value, 6684f680b72SRajan Vaja NULL); 6694f680b72SRajan Vaja } 6704f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs); 6714f680b72SRajan Vaja 6724f680b72SRajan Vaja /** 6734f680b72SRajan Vaja * zynqmp_pm_write_pggs() - PM API for reading persistent global general 6744f680b72SRajan Vaja * storage (pggs) 6754f680b72SRajan Vaja * @index PGGS register index 6764f680b72SRajan Vaja * @value Register value to be written 6774f680b72SRajan Vaja * 6784f680b72SRajan Vaja * This function returns PGGS register value. 6794f680b72SRajan Vaja * 6804f680b72SRajan Vaja * @return Returns status, either success or error+reason 6814f680b72SRajan Vaja */ 6824f680b72SRajan Vaja int zynqmp_pm_read_pggs(u32 index, u32 *value) 6834f680b72SRajan Vaja { 6844f680b72SRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_PGGS, index, 0, 6854f680b72SRajan Vaja value); 6864f680b72SRajan Vaja } 6874f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs); 6884f680b72SRajan Vaja 6894f680b72SRajan Vaja /** 690a2cc220aSRajan Vaja * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status 691a2cc220aSRajan Vaja * @value Status value to be written 692a2cc220aSRajan Vaja * 693a2cc220aSRajan Vaja * This function sets healthy bit value to indicate boot health status 694a2cc220aSRajan Vaja * to firmware. 695a2cc220aSRajan Vaja * 696a2cc220aSRajan Vaja * @return Returns status, either success or error+reason 697a2cc220aSRajan Vaja */ 698a2cc220aSRajan Vaja int zynqmp_pm_set_boot_health_status(u32 value) 699a2cc220aSRajan Vaja { 700a2cc220aSRajan Vaja return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_BOOT_HEALTH_STATUS, 701a2cc220aSRajan Vaja value, 0, NULL); 702a2cc220aSRajan Vaja } 703a2cc220aSRajan Vaja 704a2cc220aSRajan Vaja /** 705bc3843d4SNava kishore Manne * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release) 706bc3843d4SNava kishore Manne * @reset: Reset to be configured 707bc3843d4SNava kishore Manne * @assert_flag: Flag stating should reset be asserted (1) or 708bc3843d4SNava kishore Manne * released (0) 709bc3843d4SNava kishore Manne * 710bc3843d4SNava kishore Manne * Return: Returns status, either success or error+reason 711bc3843d4SNava kishore Manne */ 712cf23ec35SRajan Vaja int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset, 713bc3843d4SNava kishore Manne const enum zynqmp_pm_reset_action assert_flag) 714bc3843d4SNava kishore Manne { 715bc3843d4SNava kishore Manne return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag, 716bc3843d4SNava kishore Manne 0, 0, NULL); 717bc3843d4SNava kishore Manne } 718cf23ec35SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert); 719bc3843d4SNava kishore Manne 720bc3843d4SNava kishore Manne /** 721bc3843d4SNava kishore Manne * zynqmp_pm_reset_get_status - Get status of the reset 722bc3843d4SNava kishore Manne * @reset: Reset whose status should be returned 723bc3843d4SNava kishore Manne * @status: Returned status 724bc3843d4SNava kishore Manne * 725bc3843d4SNava kishore Manne * Return: Returns status, either success or error+reason 726bc3843d4SNava kishore Manne */ 7271b413581SRajan Vaja int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status) 728bc3843d4SNava kishore Manne { 729bc3843d4SNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT]; 730bc3843d4SNava kishore Manne int ret; 731bc3843d4SNava kishore Manne 732bc3843d4SNava kishore Manne if (!status) 733bc3843d4SNava kishore Manne return -EINVAL; 734bc3843d4SNava kishore Manne 735bc3843d4SNava kishore Manne ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0, 736bc3843d4SNava kishore Manne 0, 0, ret_payload); 737bc3843d4SNava kishore Manne *status = ret_payload[1]; 738bc3843d4SNava kishore Manne 739bc3843d4SNava kishore Manne return ret; 740bc3843d4SNava kishore Manne } 7411b413581SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status); 742bc3843d4SNava kishore Manne 743e178df31SJolly Shah /** 744e840deccSNava kishore Manne * zynqmp_pm_fpga_load - Perform the fpga load 745e840deccSNava kishore Manne * @address: Address to write to 746e840deccSNava kishore Manne * @size: pl bitstream size 747e840deccSNava kishore Manne * @flags: Bitstream type 748e840deccSNava kishore Manne * -XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration 749e840deccSNava kishore Manne * -XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration 750e840deccSNava kishore Manne * 751e840deccSNava kishore Manne * This function provides access to pmufw. To transfer 752e840deccSNava kishore Manne * the required bitstream into PL. 753e840deccSNava kishore Manne * 754e840deccSNava kishore Manne * Return: Returns status, either success or error+reason 755e840deccSNava kishore Manne */ 7564db8180fSRajan Vaja int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags) 757e840deccSNava kishore Manne { 758e840deccSNava kishore Manne return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address), 759e840deccSNava kishore Manne upper_32_bits(address), size, flags, NULL); 760e840deccSNava kishore Manne } 76156a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load); 762e840deccSNava kishore Manne 763e840deccSNava kishore Manne /** 764e840deccSNava kishore Manne * zynqmp_pm_fpga_get_status - Read value from PCAP status register 765e840deccSNava kishore Manne * @value: Value to read 766e840deccSNava kishore Manne * 767e840deccSNava kishore Manne * This function provides access to the pmufw to get the PCAP 768e840deccSNava kishore Manne * status 769e840deccSNava kishore Manne * 770e840deccSNava kishore Manne * Return: Returns status, either success or error+reason 771e840deccSNava kishore Manne */ 7724db8180fSRajan Vaja int zynqmp_pm_fpga_get_status(u32 *value) 773e840deccSNava kishore Manne { 774e840deccSNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT]; 775e840deccSNava kishore Manne int ret; 776e840deccSNava kishore Manne 777e840deccSNava kishore Manne if (!value) 778e840deccSNava kishore Manne return -EINVAL; 779e840deccSNava kishore Manne 780e840deccSNava kishore Manne ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload); 781e840deccSNava kishore Manne *value = ret_payload[1]; 782e840deccSNava kishore Manne 783e840deccSNava kishore Manne return ret; 784e840deccSNava kishore Manne } 78556a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status); 786e840deccSNava kishore Manne 787e840deccSNava kishore Manne /** 788e178df31SJolly Shah * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller 789e178df31SJolly Shah * master has initialized its own power management 790e178df31SJolly Shah * 791e178df31SJolly Shah * This API function is to be used for notify the power management controller 792e178df31SJolly Shah * about the completed power management initialization. 793e178df31SJolly Shah * 794e178df31SJolly Shah * Return: Returns status, either success or error+reason 795e178df31SJolly Shah */ 7969474da95SRajan Vaja int zynqmp_pm_init_finalize(void) 797e178df31SJolly Shah { 798e178df31SJolly Shah return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL); 799e178df31SJolly Shah } 8009474da95SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_init_finalize); 801e178df31SJolly Shah 802e178df31SJolly Shah /** 803e178df31SJolly Shah * zynqmp_pm_set_suspend_mode() - Set system suspend mode 804e178df31SJolly Shah * @mode: Mode to set for system suspend 805e178df31SJolly Shah * 806e178df31SJolly Shah * This API function is used to set mode of system suspend. 807e178df31SJolly Shah * 808e178df31SJolly Shah * Return: Returns status, either success or error+reason 809e178df31SJolly Shah */ 810951d0a97SRajan Vaja int zynqmp_pm_set_suspend_mode(u32 mode) 811e178df31SJolly Shah { 812e178df31SJolly Shah return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL); 813e178df31SJolly Shah } 814951d0a97SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode); 815e178df31SJolly Shah 816c1986ac3SRajan Vaja /** 817c1986ac3SRajan Vaja * zynqmp_pm_request_node() - Request a node with specific capabilities 818c1986ac3SRajan Vaja * @node: Node ID of the slave 819c1986ac3SRajan Vaja * @capabilities: Requested capabilities of the slave 820c1986ac3SRajan Vaja * @qos: Quality of service (not supported) 821c1986ac3SRajan Vaja * @ack: Flag to specify whether acknowledge is requested 822c1986ac3SRajan Vaja * 823c1986ac3SRajan Vaja * This function is used by master to request particular node from firmware. 824c1986ac3SRajan Vaja * Every master must request node before using it. 825c1986ac3SRajan Vaja * 826c1986ac3SRajan Vaja * Return: Returns status, either success or error+reason 827c1986ac3SRajan Vaja */ 828bf8b27edSRajan Vaja int zynqmp_pm_request_node(const u32 node, const u32 capabilities, 829bf8b27edSRajan Vaja const u32 qos, const enum zynqmp_pm_request_ack ack) 830c1986ac3SRajan Vaja { 831c1986ac3SRajan Vaja return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities, 832c1986ac3SRajan Vaja qos, ack, NULL); 833c1986ac3SRajan Vaja } 834bf8b27edSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_request_node); 835c1986ac3SRajan Vaja 836c1986ac3SRajan Vaja /** 837c1986ac3SRajan Vaja * zynqmp_pm_release_node() - Release a node 838c1986ac3SRajan Vaja * @node: Node ID of the slave 839c1986ac3SRajan Vaja * 840c1986ac3SRajan Vaja * This function is used by master to inform firmware that master 841c1986ac3SRajan Vaja * has released node. Once released, master must not use that node 842c1986ac3SRajan Vaja * without re-request. 843c1986ac3SRajan Vaja * 844c1986ac3SRajan Vaja * Return: Returns status, either success or error+reason 845c1986ac3SRajan Vaja */ 84607fb1a46SRajan Vaja int zynqmp_pm_release_node(const u32 node) 847c1986ac3SRajan Vaja { 848c1986ac3SRajan Vaja return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL); 849c1986ac3SRajan Vaja } 85007fb1a46SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_release_node); 851c1986ac3SRajan Vaja 852c1986ac3SRajan Vaja /** 853c1986ac3SRajan Vaja * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves 854c1986ac3SRajan Vaja * @node: Node ID of the slave 855c1986ac3SRajan Vaja * @capabilities: Requested capabilities of the slave 856c1986ac3SRajan Vaja * @qos: Quality of service (not supported) 857c1986ac3SRajan Vaja * @ack: Flag to specify whether acknowledge is requested 858c1986ac3SRajan Vaja * 859c1986ac3SRajan Vaja * This API function is to be used for slaves a PU already has requested 860c1986ac3SRajan Vaja * to change its capabilities. 861c1986ac3SRajan Vaja * 862c1986ac3SRajan Vaja * Return: Returns status, either success or error+reason 863c1986ac3SRajan Vaja */ 864cbbbda71SRajan Vaja int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities, 865c1986ac3SRajan Vaja const u32 qos, 866c1986ac3SRajan Vaja const enum zynqmp_pm_request_ack ack) 867c1986ac3SRajan Vaja { 868c1986ac3SRajan Vaja return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities, 869c1986ac3SRajan Vaja qos, ack, NULL); 870c1986ac3SRajan Vaja } 871cbbbda71SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement); 872c1986ac3SRajan Vaja 873057a0fb6SKalyani Akula /** 874057a0fb6SKalyani Akula * zynqmp_pm_aes - Access AES hardware to encrypt/decrypt the data using 875057a0fb6SKalyani Akula * AES-GCM core. 876057a0fb6SKalyani Akula * @address: Address of the AesParams structure. 877057a0fb6SKalyani Akula * @out: Returned output value 878057a0fb6SKalyani Akula * 879057a0fb6SKalyani Akula * Return: Returns status, either success or error code. 880057a0fb6SKalyani Akula */ 881bc86f9c5SRajan Vaja int zynqmp_pm_aes_engine(const u64 address, u32 *out) 882057a0fb6SKalyani Akula { 883057a0fb6SKalyani Akula u32 ret_payload[PAYLOAD_ARG_CNT]; 884057a0fb6SKalyani Akula int ret; 885057a0fb6SKalyani Akula 886057a0fb6SKalyani Akula if (!out) 887057a0fb6SKalyani Akula return -EINVAL; 888057a0fb6SKalyani Akula 889057a0fb6SKalyani Akula ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, upper_32_bits(address), 890057a0fb6SKalyani Akula lower_32_bits(address), 891057a0fb6SKalyani Akula 0, 0, ret_payload); 892057a0fb6SKalyani Akula *out = ret_payload[1]; 893057a0fb6SKalyani Akula 894057a0fb6SKalyani Akula return ret; 895057a0fb6SKalyani Akula } 896bc86f9c5SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine); 897057a0fb6SKalyani Akula 898fdd2ed88SRajan Vaja /** 899fdd2ed88SRajan Vaja * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart 900fdd2ed88SRajan Vaja * @type: Shutdown or restart? 0 for shutdown, 1 for restart 901fdd2ed88SRajan Vaja * @subtype: Specifies which system should be restarted or shut down 902fdd2ed88SRajan Vaja * 903fdd2ed88SRajan Vaja * Return: Returns status, either success or error+reason 904fdd2ed88SRajan Vaja */ 905fdd2ed88SRajan Vaja int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype) 906fdd2ed88SRajan Vaja { 907fdd2ed88SRajan Vaja return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype, 908fdd2ed88SRajan Vaja 0, 0, NULL); 909fdd2ed88SRajan Vaja } 910fdd2ed88SRajan Vaja 911b3ae24c4SRajan Vaja /** 912b3ae24c4SRajan Vaja * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope 913b3ae24c4SRajan Vaja * @subtype: Shutdown subtype 914b3ae24c4SRajan Vaja * @name: Matching string for scope argument 915b3ae24c4SRajan Vaja * 916b3ae24c4SRajan Vaja * This struct encapsulates mapping between shutdown scope ID and string. 917b3ae24c4SRajan Vaja */ 918b3ae24c4SRajan Vaja struct zynqmp_pm_shutdown_scope { 919b3ae24c4SRajan Vaja const enum zynqmp_pm_shutdown_subtype subtype; 920b3ae24c4SRajan Vaja const char *name; 921b3ae24c4SRajan Vaja }; 922b3ae24c4SRajan Vaja 923b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = { 924b3ae24c4SRajan Vaja [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = { 925b3ae24c4SRajan Vaja .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM, 926b3ae24c4SRajan Vaja .name = "subsystem", 927b3ae24c4SRajan Vaja }, 928b3ae24c4SRajan Vaja [ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = { 929b3ae24c4SRajan Vaja .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY, 930b3ae24c4SRajan Vaja .name = "ps_only", 931b3ae24c4SRajan Vaja }, 932b3ae24c4SRajan Vaja [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = { 933b3ae24c4SRajan Vaja .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM, 934b3ae24c4SRajan Vaja .name = "system", 935b3ae24c4SRajan Vaja }, 936b3ae24c4SRajan Vaja }; 937b3ae24c4SRajan Vaja 938b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope *selected_scope = 939b3ae24c4SRajan Vaja &shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM]; 940b3ae24c4SRajan Vaja 941b3ae24c4SRajan Vaja /** 942b3ae24c4SRajan Vaja * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid 943b3ae24c4SRajan Vaja * @scope_string: Shutdown scope string 944b3ae24c4SRajan Vaja * 945b3ae24c4SRajan Vaja * Return: Return pointer to matching shutdown scope struct from 946b3ae24c4SRajan Vaja * array of available options in system if string is valid, 947b3ae24c4SRajan Vaja * otherwise returns NULL. 948b3ae24c4SRajan Vaja */ 949b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope* 950b3ae24c4SRajan Vaja zynqmp_pm_is_shutdown_scope_valid(const char *scope_string) 951b3ae24c4SRajan Vaja { 952b3ae24c4SRajan Vaja int count; 953b3ae24c4SRajan Vaja 954b3ae24c4SRajan Vaja for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++) 955b3ae24c4SRajan Vaja if (sysfs_streq(scope_string, shutdown_scopes[count].name)) 956b3ae24c4SRajan Vaja return &shutdown_scopes[count]; 957b3ae24c4SRajan Vaja 958b3ae24c4SRajan Vaja return NULL; 959b3ae24c4SRajan Vaja } 960b3ae24c4SRajan Vaja 961b3ae24c4SRajan Vaja static ssize_t shutdown_scope_show(struct device *device, 962b3ae24c4SRajan Vaja struct device_attribute *attr, 963b3ae24c4SRajan Vaja char *buf) 964b3ae24c4SRajan Vaja { 965b3ae24c4SRajan Vaja int i; 966b3ae24c4SRajan Vaja 967b3ae24c4SRajan Vaja for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) { 968b3ae24c4SRajan Vaja if (&shutdown_scopes[i] == selected_scope) { 969b3ae24c4SRajan Vaja strcat(buf, "["); 970b3ae24c4SRajan Vaja strcat(buf, shutdown_scopes[i].name); 971b3ae24c4SRajan Vaja strcat(buf, "]"); 972b3ae24c4SRajan Vaja } else { 973b3ae24c4SRajan Vaja strcat(buf, shutdown_scopes[i].name); 974b3ae24c4SRajan Vaja } 975b3ae24c4SRajan Vaja strcat(buf, " "); 976b3ae24c4SRajan Vaja } 977b3ae24c4SRajan Vaja strcat(buf, "\n"); 978b3ae24c4SRajan Vaja 979b3ae24c4SRajan Vaja return strlen(buf); 980b3ae24c4SRajan Vaja } 981b3ae24c4SRajan Vaja 982b3ae24c4SRajan Vaja static ssize_t shutdown_scope_store(struct device *device, 983b3ae24c4SRajan Vaja struct device_attribute *attr, 984b3ae24c4SRajan Vaja const char *buf, size_t count) 985b3ae24c4SRajan Vaja { 986b3ae24c4SRajan Vaja int ret; 987b3ae24c4SRajan Vaja struct zynqmp_pm_shutdown_scope *scope; 988b3ae24c4SRajan Vaja 989b3ae24c4SRajan Vaja scope = zynqmp_pm_is_shutdown_scope_valid(buf); 990b3ae24c4SRajan Vaja if (!scope) 991b3ae24c4SRajan Vaja return -EINVAL; 992b3ae24c4SRajan Vaja 993b3ae24c4SRajan Vaja ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY, 994b3ae24c4SRajan Vaja scope->subtype); 995b3ae24c4SRajan Vaja if (ret) { 996b3ae24c4SRajan Vaja pr_err("unable to set shutdown scope %s\n", buf); 997b3ae24c4SRajan Vaja return ret; 998b3ae24c4SRajan Vaja } 999b3ae24c4SRajan Vaja 1000b3ae24c4SRajan Vaja selected_scope = scope; 1001b3ae24c4SRajan Vaja 1002b3ae24c4SRajan Vaja return count; 1003b3ae24c4SRajan Vaja } 1004b3ae24c4SRajan Vaja 1005b3ae24c4SRajan Vaja static DEVICE_ATTR_RW(shutdown_scope); 1006b3ae24c4SRajan Vaja 1007a2cc220aSRajan Vaja static ssize_t health_status_store(struct device *device, 1008a2cc220aSRajan Vaja struct device_attribute *attr, 1009a2cc220aSRajan Vaja const char *buf, size_t count) 1010a2cc220aSRajan Vaja { 1011a2cc220aSRajan Vaja int ret; 1012a2cc220aSRajan Vaja unsigned int value; 1013a2cc220aSRajan Vaja 1014a2cc220aSRajan Vaja ret = kstrtouint(buf, 10, &value); 1015a2cc220aSRajan Vaja if (ret) 1016a2cc220aSRajan Vaja return ret; 1017a2cc220aSRajan Vaja 1018a2cc220aSRajan Vaja ret = zynqmp_pm_set_boot_health_status(value); 1019a2cc220aSRajan Vaja if (ret) { 1020a2cc220aSRajan Vaja dev_err(device, "unable to set healthy bit value to %u\n", 1021a2cc220aSRajan Vaja value); 1022a2cc220aSRajan Vaja return ret; 1023a2cc220aSRajan Vaja } 1024a2cc220aSRajan Vaja 1025a2cc220aSRajan Vaja return count; 1026a2cc220aSRajan Vaja } 1027a2cc220aSRajan Vaja 1028a2cc220aSRajan Vaja static DEVICE_ATTR_WO(health_status); 1029a2cc220aSRajan Vaja 1030ae5c961dSRajan Vaja static ssize_t ggs_show(struct device *device, 1031ae5c961dSRajan Vaja struct device_attribute *attr, 1032ae5c961dSRajan Vaja char *buf, 1033ae5c961dSRajan Vaja u32 reg) 1034ae5c961dSRajan Vaja { 1035ae5c961dSRajan Vaja int ret; 1036ae5c961dSRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 1037ae5c961dSRajan Vaja 1038ae5c961dSRajan Vaja ret = zynqmp_pm_read_ggs(reg, ret_payload); 1039ae5c961dSRajan Vaja if (ret) 1040ae5c961dSRajan Vaja return ret; 1041ae5c961dSRajan Vaja 1042ae5c961dSRajan Vaja return sprintf(buf, "0x%x\n", ret_payload[1]); 1043ae5c961dSRajan Vaja } 1044ae5c961dSRajan Vaja 1045ae5c961dSRajan Vaja static ssize_t ggs_store(struct device *device, 1046ae5c961dSRajan Vaja struct device_attribute *attr, 1047ae5c961dSRajan Vaja const char *buf, size_t count, 1048ae5c961dSRajan Vaja u32 reg) 1049ae5c961dSRajan Vaja { 1050ae5c961dSRajan Vaja long value; 1051ae5c961dSRajan Vaja int ret; 1052ae5c961dSRajan Vaja 1053ae5c961dSRajan Vaja if (reg >= GSS_NUM_REGS) 1054ae5c961dSRajan Vaja return -EINVAL; 1055ae5c961dSRajan Vaja 1056ae5c961dSRajan Vaja ret = kstrtol(buf, 16, &value); 1057ae5c961dSRajan Vaja if (ret) { 1058ae5c961dSRajan Vaja count = -EFAULT; 1059ae5c961dSRajan Vaja goto err; 1060ae5c961dSRajan Vaja } 1061ae5c961dSRajan Vaja 1062ae5c961dSRajan Vaja ret = zynqmp_pm_write_ggs(reg, value); 1063ae5c961dSRajan Vaja if (ret) 1064ae5c961dSRajan Vaja count = -EFAULT; 1065ae5c961dSRajan Vaja err: 1066ae5c961dSRajan Vaja return count; 1067ae5c961dSRajan Vaja } 1068ae5c961dSRajan Vaja 1069ae5c961dSRajan Vaja /* GGS register show functions */ 1070ae5c961dSRajan Vaja #define GGS0_SHOW(N) \ 1071ae5c961dSRajan Vaja ssize_t ggs##N##_show(struct device *device, \ 1072ae5c961dSRajan Vaja struct device_attribute *attr, \ 1073ae5c961dSRajan Vaja char *buf) \ 1074ae5c961dSRajan Vaja { \ 1075ae5c961dSRajan Vaja return ggs_show(device, attr, buf, N); \ 1076ae5c961dSRajan Vaja } 1077ae5c961dSRajan Vaja 1078ae5c961dSRajan Vaja static GGS0_SHOW(0); 1079ae5c961dSRajan Vaja static GGS0_SHOW(1); 1080ae5c961dSRajan Vaja static GGS0_SHOW(2); 1081ae5c961dSRajan Vaja static GGS0_SHOW(3); 1082ae5c961dSRajan Vaja 1083ae5c961dSRajan Vaja /* GGS register store function */ 1084ae5c961dSRajan Vaja #define GGS0_STORE(N) \ 1085ae5c961dSRajan Vaja ssize_t ggs##N##_store(struct device *device, \ 1086ae5c961dSRajan Vaja struct device_attribute *attr, \ 1087ae5c961dSRajan Vaja const char *buf, \ 1088ae5c961dSRajan Vaja size_t count) \ 1089ae5c961dSRajan Vaja { \ 1090ae5c961dSRajan Vaja return ggs_store(device, attr, buf, count, N); \ 1091ae5c961dSRajan Vaja } 1092ae5c961dSRajan Vaja 1093ae5c961dSRajan Vaja static GGS0_STORE(0); 1094ae5c961dSRajan Vaja static GGS0_STORE(1); 1095ae5c961dSRajan Vaja static GGS0_STORE(2); 1096ae5c961dSRajan Vaja static GGS0_STORE(3); 1097ae5c961dSRajan Vaja 1098ae5c961dSRajan Vaja static ssize_t pggs_show(struct device *device, 1099ae5c961dSRajan Vaja struct device_attribute *attr, 1100ae5c961dSRajan Vaja char *buf, 1101ae5c961dSRajan Vaja u32 reg) 1102ae5c961dSRajan Vaja { 1103ae5c961dSRajan Vaja int ret; 1104ae5c961dSRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT]; 1105ae5c961dSRajan Vaja 1106ae5c961dSRajan Vaja ret = zynqmp_pm_read_pggs(reg, ret_payload); 1107ae5c961dSRajan Vaja if (ret) 1108ae5c961dSRajan Vaja return ret; 1109ae5c961dSRajan Vaja 1110ae5c961dSRajan Vaja return sprintf(buf, "0x%x\n", ret_payload[1]); 1111ae5c961dSRajan Vaja } 1112ae5c961dSRajan Vaja 1113ae5c961dSRajan Vaja static ssize_t pggs_store(struct device *device, 1114ae5c961dSRajan Vaja struct device_attribute *attr, 1115ae5c961dSRajan Vaja const char *buf, size_t count, 1116ae5c961dSRajan Vaja u32 reg) 1117ae5c961dSRajan Vaja { 1118ae5c961dSRajan Vaja long value; 1119ae5c961dSRajan Vaja int ret; 1120ae5c961dSRajan Vaja 1121ae5c961dSRajan Vaja if (reg >= GSS_NUM_REGS) 1122ae5c961dSRajan Vaja return -EINVAL; 1123ae5c961dSRajan Vaja 1124ae5c961dSRajan Vaja ret = kstrtol(buf, 16, &value); 1125ae5c961dSRajan Vaja if (ret) { 1126ae5c961dSRajan Vaja count = -EFAULT; 1127ae5c961dSRajan Vaja goto err; 1128ae5c961dSRajan Vaja } 1129ae5c961dSRajan Vaja 1130ae5c961dSRajan Vaja ret = zynqmp_pm_write_pggs(reg, value); 1131ae5c961dSRajan Vaja if (ret) 1132ae5c961dSRajan Vaja count = -EFAULT; 1133ae5c961dSRajan Vaja 1134ae5c961dSRajan Vaja err: 1135ae5c961dSRajan Vaja return count; 1136ae5c961dSRajan Vaja } 1137ae5c961dSRajan Vaja 1138ae5c961dSRajan Vaja #define PGGS0_SHOW(N) \ 1139ae5c961dSRajan Vaja ssize_t pggs##N##_show(struct device *device, \ 1140ae5c961dSRajan Vaja struct device_attribute *attr, \ 1141ae5c961dSRajan Vaja char *buf) \ 1142ae5c961dSRajan Vaja { \ 1143ae5c961dSRajan Vaja return pggs_show(device, attr, buf, N); \ 1144ae5c961dSRajan Vaja } 1145ae5c961dSRajan Vaja 1146ae5c961dSRajan Vaja #define PGGS0_STORE(N) \ 1147ae5c961dSRajan Vaja ssize_t pggs##N##_store(struct device *device, \ 1148ae5c961dSRajan Vaja struct device_attribute *attr, \ 1149ae5c961dSRajan Vaja const char *buf, \ 1150ae5c961dSRajan Vaja size_t count) \ 1151ae5c961dSRajan Vaja { \ 1152ae5c961dSRajan Vaja return pggs_store(device, attr, buf, count, N); \ 1153ae5c961dSRajan Vaja } 1154ae5c961dSRajan Vaja 1155ae5c961dSRajan Vaja /* PGGS register show functions */ 1156ae5c961dSRajan Vaja static PGGS0_SHOW(0); 1157ae5c961dSRajan Vaja static PGGS0_SHOW(1); 1158ae5c961dSRajan Vaja static PGGS0_SHOW(2); 1159ae5c961dSRajan Vaja static PGGS0_SHOW(3); 1160ae5c961dSRajan Vaja 1161ae5c961dSRajan Vaja /* PGGS register store functions */ 1162ae5c961dSRajan Vaja static PGGS0_STORE(0); 1163ae5c961dSRajan Vaja static PGGS0_STORE(1); 1164ae5c961dSRajan Vaja static PGGS0_STORE(2); 1165ae5c961dSRajan Vaja static PGGS0_STORE(3); 1166ae5c961dSRajan Vaja 1167ae5c961dSRajan Vaja /* GGS register attributes */ 1168ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs0); 1169ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs1); 1170ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs2); 1171ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs3); 1172ae5c961dSRajan Vaja 1173ae5c961dSRajan Vaja /* PGGS register attributes */ 1174ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs0); 1175ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs1); 1176ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs2); 1177ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs3); 1178ae5c961dSRajan Vaja 1179ae5c961dSRajan Vaja static struct attribute *zynqmp_firmware_attrs[] = { 1180ae5c961dSRajan Vaja &dev_attr_ggs0.attr, 1181ae5c961dSRajan Vaja &dev_attr_ggs1.attr, 1182ae5c961dSRajan Vaja &dev_attr_ggs2.attr, 1183ae5c961dSRajan Vaja &dev_attr_ggs3.attr, 1184ae5c961dSRajan Vaja &dev_attr_pggs0.attr, 1185ae5c961dSRajan Vaja &dev_attr_pggs1.attr, 1186ae5c961dSRajan Vaja &dev_attr_pggs2.attr, 1187ae5c961dSRajan Vaja &dev_attr_pggs3.attr, 1188b3ae24c4SRajan Vaja &dev_attr_shutdown_scope.attr, 1189a2cc220aSRajan Vaja &dev_attr_health_status.attr, 1190ae5c961dSRajan Vaja NULL, 1191ae5c961dSRajan Vaja }; 1192ae5c961dSRajan Vaja 1193ae5c961dSRajan Vaja ATTRIBUTE_GROUPS(zynqmp_firmware); 1194ae5c961dSRajan Vaja 119576582671SRajan Vaja static int zynqmp_firmware_probe(struct platform_device *pdev) 119676582671SRajan Vaja { 119776582671SRajan Vaja struct device *dev = &pdev->dev; 119876582671SRajan Vaja struct device_node *np; 119976582671SRajan Vaja int ret; 120076582671SRajan Vaja 120176582671SRajan Vaja np = of_find_compatible_node(NULL, NULL, "xlnx,zynqmp"); 1202af3f1afaSJolly Shah if (!np) { 1203af3f1afaSJolly Shah np = of_find_compatible_node(NULL, NULL, "xlnx,versal"); 120476582671SRajan Vaja if (!np) 120576582671SRajan Vaja return 0; 1206461011b1SRavi Patel 1207461011b1SRavi Patel feature_check_enabled = true; 1208af3f1afaSJolly Shah } 120976582671SRajan Vaja of_node_put(np); 121076582671SRajan Vaja 121176582671SRajan Vaja ret = get_set_conduit_method(dev->of_node); 121276582671SRajan Vaja if (ret) 121376582671SRajan Vaja return ret; 121476582671SRajan Vaja 121576582671SRajan Vaja /* Check PM API version number */ 121676582671SRajan Vaja zynqmp_pm_get_api_version(&pm_api_version); 121776582671SRajan Vaja if (pm_api_version < ZYNQMP_PM_VERSION) { 121876582671SRajan Vaja panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n", 121976582671SRajan Vaja __func__, 122076582671SRajan Vaja ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR, 122176582671SRajan Vaja pm_api_version >> 16, pm_api_version & 0xFFFF); 122276582671SRajan Vaja } 122376582671SRajan Vaja 122476582671SRajan Vaja pr_info("%s Platform Management API v%d.%d\n", __func__, 122576582671SRajan Vaja pm_api_version >> 16, pm_api_version & 0xFFFF); 122676582671SRajan Vaja 122776582671SRajan Vaja /* Check trustzone version number */ 122876582671SRajan Vaja ret = zynqmp_pm_get_trustzone_version(&pm_tz_version); 122976582671SRajan Vaja if (ret) 123076582671SRajan Vaja panic("Legacy trustzone found without version support\n"); 123176582671SRajan Vaja 123276582671SRajan Vaja if (pm_tz_version < ZYNQMP_TZ_VERSION) 123376582671SRajan Vaja panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n", 123476582671SRajan Vaja __func__, 123576582671SRajan Vaja ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR, 123676582671SRajan Vaja pm_tz_version >> 16, pm_tz_version & 0xFFFF); 123776582671SRajan Vaja 123876582671SRajan Vaja pr_info("%s Trustzone version v%d.%d\n", __func__, 123976582671SRajan Vaja pm_tz_version >> 16, pm_tz_version & 0xFFFF); 124076582671SRajan Vaja 1241e23d9c6dSJolly Shah ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs, 1242e23d9c6dSJolly Shah ARRAY_SIZE(firmware_devs), NULL, 0, NULL); 1243e23d9c6dSJolly Shah if (ret) { 1244e23d9c6dSJolly Shah dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret); 1245e23d9c6dSJolly Shah return ret; 1246e23d9c6dSJolly Shah } 1247e23d9c6dSJolly Shah 124865f0539bSChristophe JAILLET zynqmp_pm_api_debugfs_init(); 124965f0539bSChristophe JAILLET 125076582671SRajan Vaja return of_platform_populate(dev->of_node, NULL, NULL, dev); 125176582671SRajan Vaja } 125276582671SRajan Vaja 125376582671SRajan Vaja static int zynqmp_firmware_remove(struct platform_device *pdev) 125476582671SRajan Vaja { 1255e23d9c6dSJolly Shah mfd_remove_devices(&pdev->dev); 1256b3217252SRajan Vaja zynqmp_pm_api_debugfs_exit(); 1257b3217252SRajan Vaja 125876582671SRajan Vaja return 0; 125976582671SRajan Vaja } 126076582671SRajan Vaja 126176582671SRajan Vaja static const struct of_device_id zynqmp_firmware_of_match[] = { 126276582671SRajan Vaja {.compatible = "xlnx,zynqmp-firmware"}, 1263af3f1afaSJolly Shah {.compatible = "xlnx,versal-firmware"}, 126476582671SRajan Vaja {}, 126576582671SRajan Vaja }; 126676582671SRajan Vaja MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match); 126776582671SRajan Vaja 126876582671SRajan Vaja static struct platform_driver zynqmp_firmware_driver = { 126976582671SRajan Vaja .driver = { 127076582671SRajan Vaja .name = "zynqmp_firmware", 127176582671SRajan Vaja .of_match_table = zynqmp_firmware_of_match, 1272ae5c961dSRajan Vaja .dev_groups = zynqmp_firmware_groups, 127376582671SRajan Vaja }, 127476582671SRajan Vaja .probe = zynqmp_firmware_probe, 127576582671SRajan Vaja .remove = zynqmp_firmware_remove, 127676582671SRajan Vaja }; 127776582671SRajan Vaja module_platform_driver(zynqmp_firmware_driver); 1278