Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Xilinx Zynq MPSoC Firmware layer
0004  *
0005  *  Copyright (C) 2014-2022 Xilinx, Inc.
0006  *
0007  *  Michal Simek <michal.simek@xilinx.com>
0008  *  Davorin Mista <davorin.mista@aggios.com>
0009  *  Jolly Shah <jollys@xilinx.com>
0010  *  Rajan Vaja <rajanv@xilinx.com>
0011  */
0012 
0013 #include <linux/arm-smccc.h>
0014 #include <linux/compiler.h>
0015 #include <linux/device.h>
0016 #include <linux/init.h>
0017 #include <linux/mfd/core.h>
0018 #include <linux/module.h>
0019 #include <linux/of.h>
0020 #include <linux/of_platform.h>
0021 #include <linux/slab.h>
0022 #include <linux/uaccess.h>
0023 #include <linux/hashtable.h>
0024 
0025 #include <linux/firmware/xlnx-zynqmp.h>
0026 #include <linux/firmware/xlnx-event-manager.h>
0027 #include "zynqmp-debug.h"
0028 
0029 /* Max HashMap Order for PM API feature check (1<<7 = 128) */
0030 #define PM_API_FEATURE_CHECK_MAX_ORDER  7
0031 
0032 /* CRL registers and bitfields */
0033 #define CRL_APB_BASE            0xFF5E0000U
0034 /* BOOT_PIN_CTRL- Used to control the mode pins after boot */
0035 #define CRL_APB_BOOT_PIN_CTRL       (CRL_APB_BASE + (0x250U))
0036 /* BOOT_PIN_CTRL_MASK- out_val[11:8], out_en[3:0] */
0037 #define CRL_APB_BOOTPIN_CTRL_MASK   0xF0FU
0038 
0039 /* IOCTL/QUERY feature payload size */
0040 #define FEATURE_PAYLOAD_SIZE        2
0041 
0042 /* Firmware feature check version mask */
0043 #define FIRMWARE_VERSION_MASK       GENMASK(15, 0)
0044 
0045 static bool feature_check_enabled;
0046 static DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER);
0047 static u32 ioctl_features[FEATURE_PAYLOAD_SIZE];
0048 static u32 query_features[FEATURE_PAYLOAD_SIZE];
0049 
0050 static struct platform_device *em_dev;
0051 
0052 /**
0053  * struct zynqmp_devinfo - Structure for Zynqmp device instance
0054  * @dev:        Device Pointer
0055  * @feature_conf_id:    Feature conf id
0056  */
0057 struct zynqmp_devinfo {
0058     struct device *dev;
0059     u32 feature_conf_id;
0060 };
0061 
0062 /**
0063  * struct pm_api_feature_data - PM API Feature data
0064  * @pm_api_id:      PM API Id, used as key to index into hashmap
0065  * @feature_status: status of PM API feature: valid, invalid
0066  * @hentry:     hlist_node that hooks this entry into hashtable
0067  */
0068 struct pm_api_feature_data {
0069     u32 pm_api_id;
0070     int feature_status;
0071     struct hlist_node hentry;
0072 };
0073 
0074 static const struct mfd_cell firmware_devs[] = {
0075     {
0076         .name = "zynqmp_power_controller",
0077     },
0078 };
0079 
0080 /**
0081  * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes
0082  * @ret_status:     PMUFW return code
0083  *
0084  * Return: corresponding Linux error code
0085  */
0086 static int zynqmp_pm_ret_code(u32 ret_status)
0087 {
0088     switch (ret_status) {
0089     case XST_PM_SUCCESS:
0090     case XST_PM_DOUBLE_REQ:
0091         return 0;
0092     case XST_PM_NO_FEATURE:
0093         return -ENOTSUPP;
0094     case XST_PM_NO_ACCESS:
0095         return -EACCES;
0096     case XST_PM_ABORT_SUSPEND:
0097         return -ECANCELED;
0098     case XST_PM_MULT_USER:
0099         return -EUSERS;
0100     case XST_PM_INTERNAL:
0101     case XST_PM_CONFLICT:
0102     case XST_PM_INVALID_NODE:
0103     default:
0104         return -EINVAL;
0105     }
0106 }
0107 
0108 static noinline int do_fw_call_fail(u64 arg0, u64 arg1, u64 arg2,
0109                     u32 *ret_payload)
0110 {
0111     return -ENODEV;
0112 }
0113 
0114 /*
0115  * PM function call wrapper
0116  * Invoke do_fw_call_smc or do_fw_call_hvc, depending on the configuration
0117  */
0118 static int (*do_fw_call)(u64, u64, u64, u32 *ret_payload) = do_fw_call_fail;
0119 
0120 /**
0121  * do_fw_call_smc() - Call system-level platform management layer (SMC)
0122  * @arg0:       Argument 0 to SMC call
0123  * @arg1:       Argument 1 to SMC call
0124  * @arg2:       Argument 2 to SMC call
0125  * @ret_payload:    Returned value array
0126  *
0127  * Invoke platform management function via SMC call (no hypervisor present).
0128  *
0129  * Return: Returns status, either success or error+reason
0130  */
0131 static noinline int do_fw_call_smc(u64 arg0, u64 arg1, u64 arg2,
0132                    u32 *ret_payload)
0133 {
0134     struct arm_smccc_res res;
0135 
0136     arm_smccc_smc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
0137 
0138     if (ret_payload) {
0139         ret_payload[0] = lower_32_bits(res.a0);
0140         ret_payload[1] = upper_32_bits(res.a0);
0141         ret_payload[2] = lower_32_bits(res.a1);
0142         ret_payload[3] = upper_32_bits(res.a1);
0143     }
0144 
0145     return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
0146 }
0147 
0148 /**
0149  * do_fw_call_hvc() - Call system-level platform management layer (HVC)
0150  * @arg0:       Argument 0 to HVC call
0151  * @arg1:       Argument 1 to HVC call
0152  * @arg2:       Argument 2 to HVC call
0153  * @ret_payload:    Returned value array
0154  *
0155  * Invoke platform management function via HVC
0156  * HVC-based for communication through hypervisor
0157  * (no direct communication with ATF).
0158  *
0159  * Return: Returns status, either success or error+reason
0160  */
0161 static noinline int do_fw_call_hvc(u64 arg0, u64 arg1, u64 arg2,
0162                    u32 *ret_payload)
0163 {
0164     struct arm_smccc_res res;
0165 
0166     arm_smccc_hvc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
0167 
0168     if (ret_payload) {
0169         ret_payload[0] = lower_32_bits(res.a0);
0170         ret_payload[1] = upper_32_bits(res.a0);
0171         ret_payload[2] = lower_32_bits(res.a1);
0172         ret_payload[3] = upper_32_bits(res.a1);
0173     }
0174 
0175     return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
0176 }
0177 
0178 static int __do_feature_check_call(const u32 api_id, u32 *ret_payload)
0179 {
0180     int ret;
0181     u64 smc_arg[2];
0182 
0183     smc_arg[0] = PM_SIP_SVC | PM_FEATURE_CHECK;
0184     smc_arg[1] = api_id;
0185 
0186     ret = do_fw_call(smc_arg[0], smc_arg[1], 0, ret_payload);
0187     if (ret)
0188         ret = -EOPNOTSUPP;
0189     else
0190         ret = ret_payload[1];
0191 
0192     return ret;
0193 }
0194 
0195 static int do_feature_check_call(const u32 api_id)
0196 {
0197     int ret;
0198     u32 ret_payload[PAYLOAD_ARG_CNT];
0199     struct pm_api_feature_data *feature_data;
0200 
0201     /* Check for existing entry in hash table for given api */
0202     hash_for_each_possible(pm_api_features_map, feature_data, hentry,
0203                    api_id) {
0204         if (feature_data->pm_api_id == api_id)
0205             return feature_data->feature_status;
0206     }
0207 
0208     /* Add new entry if not present */
0209     feature_data = kmalloc(sizeof(*feature_data), GFP_KERNEL);
0210     if (!feature_data)
0211         return -ENOMEM;
0212 
0213     feature_data->pm_api_id = api_id;
0214     ret = __do_feature_check_call(api_id, ret_payload);
0215 
0216     feature_data->feature_status = ret;
0217     hash_add(pm_api_features_map, &feature_data->hentry, api_id);
0218 
0219     if (api_id == PM_IOCTL)
0220         /* Store supported IOCTL IDs mask */
0221         memcpy(ioctl_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4);
0222     else if (api_id == PM_QUERY_DATA)
0223         /* Store supported QUERY IDs mask */
0224         memcpy(query_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4);
0225 
0226     return ret;
0227 }
0228 EXPORT_SYMBOL_GPL(zynqmp_pm_feature);
0229 
0230 /**
0231  * zynqmp_pm_feature() - Check whether given feature is supported or not and
0232  *           store supported IOCTL/QUERY ID mask
0233  * @api_id:     API ID to check
0234  *
0235  * Return: Returns status, either success or error+reason
0236  */
0237 int zynqmp_pm_feature(const u32 api_id)
0238 {
0239     int ret;
0240 
0241     if (!feature_check_enabled)
0242         return 0;
0243 
0244     ret = do_feature_check_call(api_id);
0245 
0246     return ret;
0247 }
0248 
0249 /**
0250  * zynqmp_pm_is_function_supported() - Check whether given IOCTL/QUERY function
0251  *                     is supported or not
0252  * @api_id:     PM_IOCTL or PM_QUERY_DATA
0253  * @id:         IOCTL or QUERY function IDs
0254  *
0255  * Return: Returns status, either success or error+reason
0256  */
0257 int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
0258 {
0259     int ret;
0260     u32 *bit_mask;
0261 
0262     /* Input arguments validation */
0263     if (id >= 64 || (api_id != PM_IOCTL && api_id != PM_QUERY_DATA))
0264         return -EINVAL;
0265 
0266     /* Check feature check API version */
0267     ret = do_feature_check_call(PM_FEATURE_CHECK);
0268     if (ret < 0)
0269         return ret;
0270 
0271     /* Check if feature check version 2 is supported or not */
0272     if ((ret & FIRMWARE_VERSION_MASK) == PM_API_VERSION_2) {
0273         /*
0274          * Call feature check for IOCTL/QUERY API to get IOCTL ID or
0275          * QUERY ID feature status.
0276          */
0277         ret = do_feature_check_call(api_id);
0278         if (ret < 0)
0279             return ret;
0280 
0281         bit_mask = (api_id == PM_IOCTL) ? ioctl_features : query_features;
0282 
0283         if ((bit_mask[(id / 32)] & BIT((id % 32))) == 0U)
0284             return -EOPNOTSUPP;
0285     } else {
0286         return -ENODATA;
0287     }
0288 
0289     return 0;
0290 }
0291 EXPORT_SYMBOL_GPL(zynqmp_pm_is_function_supported);
0292 
0293 /**
0294  * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer
0295  *             caller function depending on the configuration
0296  * @pm_api_id:      Requested PM-API call
0297  * @arg0:       Argument 0 to requested PM-API call
0298  * @arg1:       Argument 1 to requested PM-API call
0299  * @arg2:       Argument 2 to requested PM-API call
0300  * @arg3:       Argument 3 to requested PM-API call
0301  * @ret_payload:    Returned value array
0302  *
0303  * Invoke platform management function for SMC or HVC call, depending on
0304  * configuration.
0305  * Following SMC Calling Convention (SMCCC) for SMC64:
0306  * Pm Function Identifier,
0307  * PM_SIP_SVC + PM_API_ID =
0308  *  ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)
0309  *  ((SMC_64) << FUNCID_CC_SHIFT)
0310  *  ((SIP_START) << FUNCID_OEN_SHIFT)
0311  *  ((PM_API_ID) & FUNCID_NUM_MASK))
0312  *
0313  * PM_SIP_SVC   - Registered ZynqMP SIP Service Call.
0314  * PM_API_ID    - Platform Management API ID.
0315  *
0316  * Return: Returns status, either success or error+reason
0317  */
0318 int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1,
0319             u32 arg2, u32 arg3, u32 *ret_payload)
0320 {
0321     /*
0322      * Added SIP service call Function Identifier
0323      * Make sure to stay in x0 register
0324      */
0325     u64 smc_arg[4];
0326     int ret;
0327 
0328     /* Check if feature is supported or not */
0329     ret = zynqmp_pm_feature(pm_api_id);
0330     if (ret < 0)
0331         return ret;
0332 
0333     smc_arg[0] = PM_SIP_SVC | pm_api_id;
0334     smc_arg[1] = ((u64)arg1 << 32) | arg0;
0335     smc_arg[2] = ((u64)arg3 << 32) | arg2;
0336 
0337     return do_fw_call(smc_arg[0], smc_arg[1], smc_arg[2], ret_payload);
0338 }
0339 
0340 static u32 pm_api_version;
0341 static u32 pm_tz_version;
0342 
0343 int zynqmp_pm_register_sgi(u32 sgi_num, u32 reset)
0344 {
0345     int ret;
0346 
0347     ret = zynqmp_pm_invoke_fn(TF_A_PM_REGISTER_SGI, sgi_num, reset, 0, 0,
0348                   NULL);
0349     if (!ret)
0350         return ret;
0351 
0352     /* try old implementation as fallback strategy if above fails */
0353     return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_REGISTER_SGI, sgi_num,
0354                    reset, NULL);
0355 }
0356 
0357 /**
0358  * zynqmp_pm_get_api_version() - Get version number of PMU PM firmware
0359  * @version:    Returned version value
0360  *
0361  * Return: Returns status, either success or error+reason
0362  */
0363 int zynqmp_pm_get_api_version(u32 *version)
0364 {
0365     u32 ret_payload[PAYLOAD_ARG_CNT];
0366     int ret;
0367 
0368     if (!version)
0369         return -EINVAL;
0370 
0371     /* Check is PM API version already verified */
0372     if (pm_api_version > 0) {
0373         *version = pm_api_version;
0374         return 0;
0375     }
0376     ret = zynqmp_pm_invoke_fn(PM_GET_API_VERSION, 0, 0, 0, 0, ret_payload);
0377     *version = ret_payload[1];
0378 
0379     return ret;
0380 }
0381 EXPORT_SYMBOL_GPL(zynqmp_pm_get_api_version);
0382 
0383 /**
0384  * zynqmp_pm_get_chipid - Get silicon ID registers
0385  * @idcode:     IDCODE register
0386  * @version:    version register
0387  *
0388  * Return:      Returns the status of the operation and the idcode and version
0389  *              registers in @idcode and @version.
0390  */
0391 int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
0392 {
0393     u32 ret_payload[PAYLOAD_ARG_CNT];
0394     int ret;
0395 
0396     if (!idcode || !version)
0397         return -EINVAL;
0398 
0399     ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
0400     *idcode = ret_payload[1];
0401     *version = ret_payload[2];
0402 
0403     return ret;
0404 }
0405 EXPORT_SYMBOL_GPL(zynqmp_pm_get_chipid);
0406 
0407 /**
0408  * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
0409  * @version:    Returned version value
0410  *
0411  * Return: Returns status, either success or error+reason
0412  */
0413 static int zynqmp_pm_get_trustzone_version(u32 *version)
0414 {
0415     u32 ret_payload[PAYLOAD_ARG_CNT];
0416     int ret;
0417 
0418     if (!version)
0419         return -EINVAL;
0420 
0421     /* Check is PM trustzone version already verified */
0422     if (pm_tz_version > 0) {
0423         *version = pm_tz_version;
0424         return 0;
0425     }
0426     ret = zynqmp_pm_invoke_fn(PM_GET_TRUSTZONE_VERSION, 0, 0,
0427                   0, 0, ret_payload);
0428     *version = ret_payload[1];
0429 
0430     return ret;
0431 }
0432 
0433 /**
0434  * get_set_conduit_method() - Choose SMC or HVC based communication
0435  * @np:     Pointer to the device_node structure
0436  *
0437  * Use SMC or HVC-based functions to communicate with EL2/EL3.
0438  *
0439  * Return: Returns 0 on success or error code
0440  */
0441 static int get_set_conduit_method(struct device_node *np)
0442 {
0443     const char *method;
0444 
0445     if (of_property_read_string(np, "method", &method)) {
0446         pr_warn("%s missing \"method\" property\n", __func__);
0447         return -ENXIO;
0448     }
0449 
0450     if (!strcmp("hvc", method)) {
0451         do_fw_call = do_fw_call_hvc;
0452     } else if (!strcmp("smc", method)) {
0453         do_fw_call = do_fw_call_smc;
0454     } else {
0455         pr_warn("%s Invalid \"method\" property: %s\n",
0456             __func__, method);
0457         return -EINVAL;
0458     }
0459 
0460     return 0;
0461 }
0462 
0463 /**
0464  * zynqmp_pm_query_data() - Get query data from firmware
0465  * @qdata:  Variable to the zynqmp_pm_query_data structure
0466  * @out:    Returned output value
0467  *
0468  * Return: Returns status, either success or error+reason
0469  */
0470 int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
0471 {
0472     int ret;
0473 
0474     ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, qdata.qid, qdata.arg1,
0475                   qdata.arg2, qdata.arg3, out);
0476 
0477     /*
0478      * For clock name query, all bytes in SMC response are clock name
0479      * characters and return code is always success. For invalid clocks,
0480      * clock name bytes would be zeros.
0481      */
0482     return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret;
0483 }
0484 EXPORT_SYMBOL_GPL(zynqmp_pm_query_data);
0485 
0486 /**
0487  * zynqmp_pm_clock_enable() - Enable the clock for given id
0488  * @clock_id:   ID of the clock to be enabled
0489  *
0490  * This function is used by master to enable the clock
0491  * including peripherals and PLL clocks.
0492  *
0493  * Return: Returns status, either success or error+reason
0494  */
0495 int zynqmp_pm_clock_enable(u32 clock_id)
0496 {
0497     return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL);
0498 }
0499 EXPORT_SYMBOL_GPL(zynqmp_pm_clock_enable);
0500 
0501 /**
0502  * zynqmp_pm_clock_disable() - Disable the clock for given id
0503  * @clock_id:   ID of the clock to be disable
0504  *
0505  * This function is used by master to disable the clock
0506  * including peripherals and PLL clocks.
0507  *
0508  * Return: Returns status, either success or error+reason
0509  */
0510 int zynqmp_pm_clock_disable(u32 clock_id)
0511 {
0512     return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL);
0513 }
0514 EXPORT_SYMBOL_GPL(zynqmp_pm_clock_disable);
0515 
0516 /**
0517  * zynqmp_pm_clock_getstate() - Get the clock state for given id
0518  * @clock_id:   ID of the clock to be queried
0519  * @state:  1/0 (Enabled/Disabled)
0520  *
0521  * This function is used by master to get the state of clock
0522  * including peripherals and PLL clocks.
0523  *
0524  * Return: Returns status, either success or error+reason
0525  */
0526 int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
0527 {
0528     u32 ret_payload[PAYLOAD_ARG_CNT];
0529     int ret;
0530 
0531     ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, clock_id, 0,
0532                   0, 0, ret_payload);
0533     *state = ret_payload[1];
0534 
0535     return ret;
0536 }
0537 EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getstate);
0538 
0539 /**
0540  * zynqmp_pm_clock_setdivider() - Set the clock divider for given id
0541  * @clock_id:   ID of the clock
0542  * @divider:    divider value
0543  *
0544  * This function is used by master to set divider for any clock
0545  * to achieve desired rate.
0546  *
0547  * Return: Returns status, either success or error+reason
0548  */
0549 int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider)
0550 {
0551     return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, clock_id, divider,
0552                    0, 0, NULL);
0553 }
0554 EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setdivider);
0555 
0556 /**
0557  * zynqmp_pm_clock_getdivider() - Get the clock divider for given id
0558  * @clock_id:   ID of the clock
0559  * @divider:    divider value
0560  *
0561  * This function is used by master to get divider values
0562  * for any clock.
0563  *
0564  * Return: Returns status, either success or error+reason
0565  */
0566 int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
0567 {
0568     u32 ret_payload[PAYLOAD_ARG_CNT];
0569     int ret;
0570 
0571     ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, clock_id, 0,
0572                   0, 0, ret_payload);
0573     *divider = ret_payload[1];
0574 
0575     return ret;
0576 }
0577 EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getdivider);
0578 
0579 /**
0580  * zynqmp_pm_clock_setrate() - Set the clock rate for given id
0581  * @clock_id:   ID of the clock
0582  * @rate:   rate value in hz
0583  *
0584  * This function is used by master to set rate for any clock.
0585  *
0586  * Return: Returns status, either success or error+reason
0587  */
0588 int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate)
0589 {
0590     return zynqmp_pm_invoke_fn(PM_CLOCK_SETRATE, clock_id,
0591                    lower_32_bits(rate),
0592                    upper_32_bits(rate),
0593                    0, NULL);
0594 }
0595 EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setrate);
0596 
0597 /**
0598  * zynqmp_pm_clock_getrate() - Get the clock rate for given id
0599  * @clock_id:   ID of the clock
0600  * @rate:   rate value in hz
0601  *
0602  * This function is used by master to get rate
0603  * for any clock.
0604  *
0605  * Return: Returns status, either success or error+reason
0606  */
0607 int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate)
0608 {
0609     u32 ret_payload[PAYLOAD_ARG_CNT];
0610     int ret;
0611 
0612     ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETRATE, clock_id, 0,
0613                   0, 0, ret_payload);
0614     *rate = ((u64)ret_payload[2] << 32) | ret_payload[1];
0615 
0616     return ret;
0617 }
0618 EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getrate);
0619 
0620 /**
0621  * zynqmp_pm_clock_setparent() - Set the clock parent for given id
0622  * @clock_id:   ID of the clock
0623  * @parent_id:  parent id
0624  *
0625  * This function is used by master to set parent for any clock.
0626  *
0627  * Return: Returns status, either success or error+reason
0628  */
0629 int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id)
0630 {
0631     return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, clock_id,
0632                    parent_id, 0, 0, NULL);
0633 }
0634 EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setparent);
0635 
0636 /**
0637  * zynqmp_pm_clock_getparent() - Get the clock parent for given id
0638  * @clock_id:   ID of the clock
0639  * @parent_id:  parent id
0640  *
0641  * This function is used by master to get parent index
0642  * for any clock.
0643  *
0644  * Return: Returns status, either success or error+reason
0645  */
0646 int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)
0647 {
0648     u32 ret_payload[PAYLOAD_ARG_CNT];
0649     int ret;
0650 
0651     ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, clock_id, 0,
0652                   0, 0, ret_payload);
0653     *parent_id = ret_payload[1];
0654 
0655     return ret;
0656 }
0657 EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getparent);
0658 
0659 /**
0660  * zynqmp_pm_set_pll_frac_mode() - PM API for set PLL mode
0661  *
0662  * @clk_id: PLL clock ID
0663  * @mode:   PLL mode (PLL_MODE_FRAC/PLL_MODE_INT)
0664  *
0665  * This function sets PLL mode
0666  *
0667  * Return: Returns status, either success or error+reason
0668  */
0669 int zynqmp_pm_set_pll_frac_mode(u32 clk_id, u32 mode)
0670 {
0671     return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_MODE,
0672                    clk_id, mode, NULL);
0673 }
0674 EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_mode);
0675 
0676 /**
0677  * zynqmp_pm_get_pll_frac_mode() - PM API for get PLL mode
0678  *
0679  * @clk_id: PLL clock ID
0680  * @mode:   PLL mode
0681  *
0682  * This function return current PLL mode
0683  *
0684  * Return: Returns status, either success or error+reason
0685  */
0686 int zynqmp_pm_get_pll_frac_mode(u32 clk_id, u32 *mode)
0687 {
0688     return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_MODE,
0689                    clk_id, 0, mode);
0690 }
0691 EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_mode);
0692 
0693 /**
0694  * zynqmp_pm_set_pll_frac_data() - PM API for setting pll fraction data
0695  *
0696  * @clk_id: PLL clock ID
0697  * @data:   fraction data
0698  *
0699  * This function sets fraction data.
0700  * It is valid for fraction mode only.
0701  *
0702  * Return: Returns status, either success or error+reason
0703  */
0704 int zynqmp_pm_set_pll_frac_data(u32 clk_id, u32 data)
0705 {
0706     return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_DATA,
0707                    clk_id, data, NULL);
0708 }
0709 EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_data);
0710 
0711 /**
0712  * zynqmp_pm_get_pll_frac_data() - PM API for getting pll fraction data
0713  *
0714  * @clk_id: PLL clock ID
0715  * @data:   fraction data
0716  *
0717  * This function returns fraction data value.
0718  *
0719  * Return: Returns status, either success or error+reason
0720  */
0721 int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data)
0722 {
0723     return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_DATA,
0724                    clk_id, 0, data);
0725 }
0726 EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data);
0727 
0728 /**
0729  * zynqmp_pm_set_sd_tapdelay() -  Set tap delay for the SD device
0730  *
0731  * @node_id:    Node ID of the device
0732  * @type:   Type of tap delay to set (input/output)
0733  * @value:  Value to set fot the tap delay
0734  *
0735  * This function sets input/output tap delay for the SD device.
0736  *
0737  * Return:  Returns status, either success or error+reason
0738  */
0739 int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value)
0740 {
0741     return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY,
0742                    type, value, NULL);
0743 }
0744 EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay);
0745 
0746 /**
0747  * zynqmp_pm_sd_dll_reset() - Reset DLL logic
0748  *
0749  * @node_id:    Node ID of the device
0750  * @type:   Reset type
0751  *
0752  * This function resets DLL logic for the SD device.
0753  *
0754  * Return:  Returns status, either success or error+reason
0755  */
0756 int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type)
0757 {
0758     return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SD_DLL_RESET,
0759                    type, 0, NULL);
0760 }
0761 EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset);
0762 
0763 /**
0764  * zynqmp_pm_ospi_mux_select() - OSPI Mux selection
0765  *
0766  * @dev_id: Device Id of the OSPI device.
0767  * @select: OSPI Mux select value.
0768  *
0769  * This function select the OSPI Mux.
0770  *
0771  * Return:  Returns status, either success or error+reason
0772  */
0773 int zynqmp_pm_ospi_mux_select(u32 dev_id, u32 select)
0774 {
0775     return zynqmp_pm_invoke_fn(PM_IOCTL, dev_id, IOCTL_OSPI_MUX_SELECT,
0776                    select, 0, NULL);
0777 }
0778 EXPORT_SYMBOL_GPL(zynqmp_pm_ospi_mux_select);
0779 
0780 /**
0781  * zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs)
0782  * @index:  GGS register index
0783  * @value:  Register value to be written
0784  *
0785  * This function writes value to GGS register.
0786  *
0787  * Return:      Returns status, either success or error+reason
0788  */
0789 int zynqmp_pm_write_ggs(u32 index, u32 value)
0790 {
0791     return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_GGS,
0792                    index, value, NULL);
0793 }
0794 EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs);
0795 
0796 /**
0797  * zynqmp_pm_read_ggs() - PM API for reading global general storage (ggs)
0798  * @index:  GGS register index
0799  * @value:  Register value to be written
0800  *
0801  * This function returns GGS register value.
0802  *
0803  * Return:  Returns status, either success or error+reason
0804  */
0805 int zynqmp_pm_read_ggs(u32 index, u32 *value)
0806 {
0807     return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_GGS,
0808                    index, 0, value);
0809 }
0810 EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs);
0811 
0812 /**
0813  * zynqmp_pm_write_pggs() - PM API for writing persistent global general
0814  *               storage (pggs)
0815  * @index:  PGGS register index
0816  * @value:  Register value to be written
0817  *
0818  * This function writes value to PGGS register.
0819  *
0820  * Return:  Returns status, either success or error+reason
0821  */
0822 int zynqmp_pm_write_pggs(u32 index, u32 value)
0823 {
0824     return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_PGGS, index, value,
0825                    NULL);
0826 }
0827 EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs);
0828 
0829 /**
0830  * zynqmp_pm_read_pggs() - PM API for reading persistent global general
0831  *               storage (pggs)
0832  * @index:  PGGS register index
0833  * @value:  Register value to be written
0834  *
0835  * This function returns PGGS register value.
0836  *
0837  * Return:  Returns status, either success or error+reason
0838  */
0839 int zynqmp_pm_read_pggs(u32 index, u32 *value)
0840 {
0841     return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_PGGS, index, 0,
0842                    value);
0843 }
0844 EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs);
0845 
0846 /**
0847  * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status
0848  * @value:  Status value to be written
0849  *
0850  * This function sets healthy bit value to indicate boot health status
0851  * to firmware.
0852  *
0853  * Return:  Returns status, either success or error+reason
0854  */
0855 int zynqmp_pm_set_boot_health_status(u32 value)
0856 {
0857     return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_BOOT_HEALTH_STATUS,
0858                    value, 0, NULL);
0859 }
0860 
0861 /**
0862  * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release)
0863  * @reset:      Reset to be configured
0864  * @assert_flag:    Flag stating should reset be asserted (1) or
0865  *          released (0)
0866  *
0867  * Return: Returns status, either success or error+reason
0868  */
0869 int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
0870                const enum zynqmp_pm_reset_action assert_flag)
0871 {
0872     return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag,
0873                    0, 0, NULL);
0874 }
0875 EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert);
0876 
0877 /**
0878  * zynqmp_pm_reset_get_status - Get status of the reset
0879  * @reset:      Reset whose status should be returned
0880  * @status:     Returned status
0881  *
0882  * Return: Returns status, either success or error+reason
0883  */
0884 int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status)
0885 {
0886     u32 ret_payload[PAYLOAD_ARG_CNT];
0887     int ret;
0888 
0889     if (!status)
0890         return -EINVAL;
0891 
0892     ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0,
0893                   0, 0, ret_payload);
0894     *status = ret_payload[1];
0895 
0896     return ret;
0897 }
0898 EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status);
0899 
0900 /**
0901  * zynqmp_pm_fpga_load - Perform the fpga load
0902  * @address:    Address to write to
0903  * @size:   pl bitstream size
0904  * @flags:  Bitstream type
0905  *  -XILINX_ZYNQMP_PM_FPGA_FULL:  FPGA full reconfiguration
0906  *  -XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration
0907  *
0908  * This function provides access to pmufw. To transfer
0909  * the required bitstream into PL.
0910  *
0911  * Return: Returns status, either success or error+reason
0912  */
0913 int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags)
0914 {
0915     return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
0916                    upper_32_bits(address), size, flags, NULL);
0917 }
0918 EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load);
0919 
0920 /**
0921  * zynqmp_pm_fpga_get_status - Read value from PCAP status register
0922  * @value: Value to read
0923  *
0924  * This function provides access to the pmufw to get the PCAP
0925  * status
0926  *
0927  * Return: Returns status, either success or error+reason
0928  */
0929 int zynqmp_pm_fpga_get_status(u32 *value)
0930 {
0931     u32 ret_payload[PAYLOAD_ARG_CNT];
0932     int ret;
0933 
0934     if (!value)
0935         return -EINVAL;
0936 
0937     ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload);
0938     *value = ret_payload[1];
0939 
0940     return ret;
0941 }
0942 EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status);
0943 
0944 /**
0945  * zynqmp_pm_pinctrl_request - Request Pin from firmware
0946  * @pin: Pin number to request
0947  *
0948  * This function requests pin from firmware.
0949  *
0950  * Return: Returns status, either success or error+reason.
0951  */
0952 int zynqmp_pm_pinctrl_request(const u32 pin)
0953 {
0954     return zynqmp_pm_invoke_fn(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL);
0955 }
0956 EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_request);
0957 
0958 /**
0959  * zynqmp_pm_pinctrl_release - Inform firmware that Pin control is released
0960  * @pin: Pin number to release
0961  *
0962  * This function release pin from firmware.
0963  *
0964  * Return: Returns status, either success or error+reason.
0965  */
0966 int zynqmp_pm_pinctrl_release(const u32 pin)
0967 {
0968     return zynqmp_pm_invoke_fn(PM_PINCTRL_RELEASE, pin, 0, 0, 0, NULL);
0969 }
0970 EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_release);
0971 
0972 /**
0973  * zynqmp_pm_pinctrl_get_function - Read function id set for the given pin
0974  * @pin: Pin number
0975  * @id: Buffer to store function ID
0976  *
0977  * This function provides the function currently set for the given pin.
0978  *
0979  * Return: Returns status, either success or error+reason
0980  */
0981 int zynqmp_pm_pinctrl_get_function(const u32 pin, u32 *id)
0982 {
0983     u32 ret_payload[PAYLOAD_ARG_CNT];
0984     int ret;
0985 
0986     if (!id)
0987         return -EINVAL;
0988 
0989     ret = zynqmp_pm_invoke_fn(PM_PINCTRL_GET_FUNCTION, pin, 0,
0990                   0, 0, ret_payload);
0991     *id = ret_payload[1];
0992 
0993     return ret;
0994 }
0995 EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_function);
0996 
0997 /**
0998  * zynqmp_pm_pinctrl_set_function - Set requested function for the pin
0999  * @pin: Pin number
1000  * @id: Function ID to set
1001  *
1002  * This function sets requested function for the given pin.
1003  *
1004  * Return: Returns status, either success or error+reason.
1005  */
1006 int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id)
1007 {
1008     return zynqmp_pm_invoke_fn(PM_PINCTRL_SET_FUNCTION, pin, id,
1009                    0, 0, NULL);
1010 }
1011 EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_function);
1012 
1013 /**
1014  * zynqmp_pm_pinctrl_get_config - Get configuration parameter for the pin
1015  * @pin: Pin number
1016  * @param: Parameter to get
1017  * @value: Buffer to store parameter value
1018  *
1019  * This function gets requested configuration parameter for the given pin.
1020  *
1021  * Return: Returns status, either success or error+reason.
1022  */
1023 int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param,
1024                  u32 *value)
1025 {
1026     u32 ret_payload[PAYLOAD_ARG_CNT];
1027     int ret;
1028 
1029     if (!value)
1030         return -EINVAL;
1031 
1032     ret = zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_GET, pin, param,
1033                   0, 0, ret_payload);
1034     *value = ret_payload[1];
1035 
1036     return ret;
1037 }
1038 EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_config);
1039 
1040 /**
1041  * zynqmp_pm_pinctrl_set_config - Set configuration parameter for the pin
1042  * @pin: Pin number
1043  * @param: Parameter to set
1044  * @value: Parameter value to set
1045  *
1046  * This function sets requested configuration parameter for the given pin.
1047  *
1048  * Return: Returns status, either success or error+reason.
1049  */
1050 int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param,
1051                  u32 value)
1052 {
1053     return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, pin,
1054                    param, value, 0, NULL);
1055 }
1056 EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_config);
1057 
1058 /**
1059  * zynqmp_pm_bootmode_read() - PM Config API for read bootpin status
1060  * @ps_mode: Returned output value of ps_mode
1061  *
1062  * This API function is to be used for notify the power management controller
1063  * to read bootpin status.
1064  *
1065  * Return: status, either success or error+reason
1066  */
1067 unsigned int zynqmp_pm_bootmode_read(u32 *ps_mode)
1068 {
1069     unsigned int ret;
1070     u32 ret_payload[PAYLOAD_ARG_CNT];
1071 
1072     ret = zynqmp_pm_invoke_fn(PM_MMIO_READ, CRL_APB_BOOT_PIN_CTRL, 0,
1073                   0, 0, ret_payload);
1074 
1075     *ps_mode = ret_payload[1];
1076 
1077     return ret;
1078 }
1079 EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_read);
1080 
1081 /**
1082  * zynqmp_pm_bootmode_write() - PM Config API for Configure bootpin
1083  * @ps_mode: Value to be written to the bootpin ctrl register
1084  *
1085  * This API function is to be used for notify the power management controller
1086  * to configure bootpin.
1087  *
1088  * Return: Returns status, either success or error+reason
1089  */
1090 int zynqmp_pm_bootmode_write(u32 ps_mode)
1091 {
1092     return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, CRL_APB_BOOT_PIN_CTRL,
1093                    CRL_APB_BOOTPIN_CTRL_MASK, ps_mode, 0, NULL);
1094 }
1095 EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_write);
1096 
1097 /**
1098  * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
1099  *                 master has initialized its own power management
1100  *
1101  * Return: Returns status, either success or error+reason
1102  *
1103  * This API function is to be used for notify the power management controller
1104  * about the completed power management initialization.
1105  */
1106 int zynqmp_pm_init_finalize(void)
1107 {
1108     return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL);
1109 }
1110 EXPORT_SYMBOL_GPL(zynqmp_pm_init_finalize);
1111 
1112 /**
1113  * zynqmp_pm_set_suspend_mode() - Set system suspend mode
1114  * @mode:   Mode to set for system suspend
1115  *
1116  * This API function is used to set mode of system suspend.
1117  *
1118  * Return: Returns status, either success or error+reason
1119  */
1120 int zynqmp_pm_set_suspend_mode(u32 mode)
1121 {
1122     return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL);
1123 }
1124 EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode);
1125 
1126 /**
1127  * zynqmp_pm_request_node() - Request a node with specific capabilities
1128  * @node:       Node ID of the slave
1129  * @capabilities:   Requested capabilities of the slave
1130  * @qos:        Quality of service (not supported)
1131  * @ack:        Flag to specify whether acknowledge is requested
1132  *
1133  * This function is used by master to request particular node from firmware.
1134  * Every master must request node before using it.
1135  *
1136  * Return: Returns status, either success or error+reason
1137  */
1138 int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
1139                const u32 qos, const enum zynqmp_pm_request_ack ack)
1140 {
1141     return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities,
1142                    qos, ack, NULL);
1143 }
1144 EXPORT_SYMBOL_GPL(zynqmp_pm_request_node);
1145 
1146 /**
1147  * zynqmp_pm_release_node() - Release a node
1148  * @node:   Node ID of the slave
1149  *
1150  * This function is used by master to inform firmware that master
1151  * has released node. Once released, master must not use that node
1152  * without re-request.
1153  *
1154  * Return: Returns status, either success or error+reason
1155  */
1156 int zynqmp_pm_release_node(const u32 node)
1157 {
1158     return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL);
1159 }
1160 EXPORT_SYMBOL_GPL(zynqmp_pm_release_node);
1161 
1162 /**
1163  * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
1164  * @node:       Node ID of the slave
1165  * @capabilities:   Requested capabilities of the slave
1166  * @qos:        Quality of service (not supported)
1167  * @ack:        Flag to specify whether acknowledge is requested
1168  *
1169  * This API function is to be used for slaves a PU already has requested
1170  * to change its capabilities.
1171  *
1172  * Return: Returns status, either success or error+reason
1173  */
1174 int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
1175                   const u32 qos,
1176                   const enum zynqmp_pm_request_ack ack)
1177 {
1178     return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities,
1179                    qos, ack, NULL);
1180 }
1181 EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement);
1182 
1183 /**
1184  * zynqmp_pm_load_pdi - Load and process PDI
1185  * @src:       Source device where PDI is located
1186  * @address:   PDI src address
1187  *
1188  * This function provides support to load PDI from linux
1189  *
1190  * Return: Returns status, either success or error+reason
1191  */
1192 int zynqmp_pm_load_pdi(const u32 src, const u64 address)
1193 {
1194     return zynqmp_pm_invoke_fn(PM_LOAD_PDI, src,
1195                    lower_32_bits(address),
1196                    upper_32_bits(address), 0, NULL);
1197 }
1198 EXPORT_SYMBOL_GPL(zynqmp_pm_load_pdi);
1199 
1200 /**
1201  * zynqmp_pm_aes_engine - Access AES hardware to encrypt/decrypt the data using
1202  * AES-GCM core.
1203  * @address:    Address of the AesParams structure.
1204  * @out:    Returned output value
1205  *
1206  * Return:  Returns status, either success or error code.
1207  */
1208 int zynqmp_pm_aes_engine(const u64 address, u32 *out)
1209 {
1210     u32 ret_payload[PAYLOAD_ARG_CNT];
1211     int ret;
1212 
1213     if (!out)
1214         return -EINVAL;
1215 
1216     ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, upper_32_bits(address),
1217                   lower_32_bits(address),
1218                   0, 0, ret_payload);
1219     *out = ret_payload[1];
1220 
1221     return ret;
1222 }
1223 EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);
1224 
1225 /**
1226  * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash
1227  * @address:    Address of the data/ Address of output buffer where
1228  *      hash should be stored.
1229  * @size:   Size of the data.
1230  * @flags:
1231  *  BIT(0) - for initializing csudma driver and SHA3(Here address
1232  *       and size inputs can be NULL).
1233  *  BIT(1) - to call Sha3_Update API which can be called multiple
1234  *       times when data is not contiguous.
1235  *  BIT(2) - to get final hash of the whole updated data.
1236  *       Hash will be overwritten at provided address with
1237  *       48 bytes.
1238  *
1239  * Return:  Returns status, either success or error code.
1240  */
1241 int zynqmp_pm_sha_hash(const u64 address, const u32 size, const u32 flags)
1242 {
1243     u32 lower_addr = lower_32_bits(address);
1244     u32 upper_addr = upper_32_bits(address);
1245 
1246     return zynqmp_pm_invoke_fn(PM_SECURE_SHA, upper_addr, lower_addr,
1247                    size, flags, NULL);
1248 }
1249 EXPORT_SYMBOL_GPL(zynqmp_pm_sha_hash);
1250 
1251 /**
1252  * zynqmp_pm_register_notifier() - PM API for register a subsystem
1253  *                                to be notified about specific
1254  *                                event/error.
1255  * @node:   Node ID to which the event is related.
1256  * @event:  Event Mask of Error events for which wants to get notified.
1257  * @wake:   Wake subsystem upon capturing the event if value 1
1258  * @enable: Enable the registration for value 1, disable for value 0
1259  *
1260  * This function is used to register/un-register for particular node-event
1261  * combination in firmware.
1262  *
1263  * Return: Returns status, either success or error+reason
1264  */
1265 
1266 int zynqmp_pm_register_notifier(const u32 node, const u32 event,
1267                 const u32 wake, const u32 enable)
1268 {
1269     return zynqmp_pm_invoke_fn(PM_REGISTER_NOTIFIER, node, event,
1270                    wake, enable, NULL);
1271 }
1272 EXPORT_SYMBOL_GPL(zynqmp_pm_register_notifier);
1273 
1274 /**
1275  * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart
1276  * @type:   Shutdown or restart? 0 for shutdown, 1 for restart
1277  * @subtype:    Specifies which system should be restarted or shut down
1278  *
1279  * Return:  Returns status, either success or error+reason
1280  */
1281 int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype)
1282 {
1283     return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype,
1284                    0, 0, NULL);
1285 }
1286 
1287 /**
1288  * zynqmp_pm_set_feature_config - PM call to request IOCTL for feature config
1289  * @id:         The config ID of the feature to be configured
1290  * @value:      The config value of the feature to be configured
1291  *
1292  * Return:      Returns 0 on success or error value on failure.
1293  */
1294 int zynqmp_pm_set_feature_config(enum pm_feature_config_id id, u32 value)
1295 {
1296     return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_FEATURE_CONFIG,
1297                    id, value, NULL);
1298 }
1299 
1300 /**
1301  * zynqmp_pm_get_feature_config - PM call to get value of configured feature
1302  * @id:         The config id of the feature to be queried
1303  * @payload:    Returned value array
1304  *
1305  * Return:      Returns 0 on success or error value on failure.
1306  */
1307 int zynqmp_pm_get_feature_config(enum pm_feature_config_id id,
1308                  u32 *payload)
1309 {
1310     return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_FEATURE_CONFIG,
1311                    id, 0, payload);
1312 }
1313 
1314 /**
1315  * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope
1316  * @subtype:    Shutdown subtype
1317  * @name:   Matching string for scope argument
1318  *
1319  * This struct encapsulates mapping between shutdown scope ID and string.
1320  */
1321 struct zynqmp_pm_shutdown_scope {
1322     const enum zynqmp_pm_shutdown_subtype subtype;
1323     const char *name;
1324 };
1325 
1326 static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = {
1327     [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = {
1328         .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM,
1329         .name = "subsystem",
1330     },
1331     [ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = {
1332         .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY,
1333         .name = "ps_only",
1334     },
1335     [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = {
1336         .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM,
1337         .name = "system",
1338     },
1339 };
1340 
1341 static struct zynqmp_pm_shutdown_scope *selected_scope =
1342         &shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM];
1343 
1344 /**
1345  * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid
1346  * @scope_string:   Shutdown scope string
1347  *
1348  * Return:      Return pointer to matching shutdown scope struct from
1349  *          array of available options in system if string is valid,
1350  *          otherwise returns NULL.
1351  */
1352 static struct zynqmp_pm_shutdown_scope*
1353         zynqmp_pm_is_shutdown_scope_valid(const char *scope_string)
1354 {
1355     int count;
1356 
1357     for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++)
1358         if (sysfs_streq(scope_string, shutdown_scopes[count].name))
1359             return &shutdown_scopes[count];
1360 
1361     return NULL;
1362 }
1363 
1364 static ssize_t shutdown_scope_show(struct device *device,
1365                    struct device_attribute *attr,
1366                    char *buf)
1367 {
1368     int i;
1369 
1370     for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) {
1371         if (&shutdown_scopes[i] == selected_scope) {
1372             strcat(buf, "[");
1373             strcat(buf, shutdown_scopes[i].name);
1374             strcat(buf, "]");
1375         } else {
1376             strcat(buf, shutdown_scopes[i].name);
1377         }
1378         strcat(buf, " ");
1379     }
1380     strcat(buf, "\n");
1381 
1382     return strlen(buf);
1383 }
1384 
1385 static ssize_t shutdown_scope_store(struct device *device,
1386                     struct device_attribute *attr,
1387                     const char *buf, size_t count)
1388 {
1389     int ret;
1390     struct zynqmp_pm_shutdown_scope *scope;
1391 
1392     scope = zynqmp_pm_is_shutdown_scope_valid(buf);
1393     if (!scope)
1394         return -EINVAL;
1395 
1396     ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY,
1397                     scope->subtype);
1398     if (ret) {
1399         pr_err("unable to set shutdown scope %s\n", buf);
1400         return ret;
1401     }
1402 
1403     selected_scope = scope;
1404 
1405     return count;
1406 }
1407 
1408 static DEVICE_ATTR_RW(shutdown_scope);
1409 
1410 static ssize_t health_status_store(struct device *device,
1411                    struct device_attribute *attr,
1412                    const char *buf, size_t count)
1413 {
1414     int ret;
1415     unsigned int value;
1416 
1417     ret = kstrtouint(buf, 10, &value);
1418     if (ret)
1419         return ret;
1420 
1421     ret = zynqmp_pm_set_boot_health_status(value);
1422     if (ret) {
1423         dev_err(device, "unable to set healthy bit value to %u\n",
1424             value);
1425         return ret;
1426     }
1427 
1428     return count;
1429 }
1430 
1431 static DEVICE_ATTR_WO(health_status);
1432 
1433 static ssize_t ggs_show(struct device *device,
1434             struct device_attribute *attr,
1435             char *buf,
1436             u32 reg)
1437 {
1438     int ret;
1439     u32 ret_payload[PAYLOAD_ARG_CNT];
1440 
1441     ret = zynqmp_pm_read_ggs(reg, ret_payload);
1442     if (ret)
1443         return ret;
1444 
1445     return sprintf(buf, "0x%x\n", ret_payload[1]);
1446 }
1447 
1448 static ssize_t ggs_store(struct device *device,
1449              struct device_attribute *attr,
1450              const char *buf, size_t count,
1451              u32 reg)
1452 {
1453     long value;
1454     int ret;
1455 
1456     if (reg >= GSS_NUM_REGS)
1457         return -EINVAL;
1458 
1459     ret = kstrtol(buf, 16, &value);
1460     if (ret) {
1461         count = -EFAULT;
1462         goto err;
1463     }
1464 
1465     ret = zynqmp_pm_write_ggs(reg, value);
1466     if (ret)
1467         count = -EFAULT;
1468 err:
1469     return count;
1470 }
1471 
1472 /* GGS register show functions */
1473 #define GGS0_SHOW(N)                        \
1474     ssize_t ggs##N##_show(struct device *device,        \
1475                   struct device_attribute *attr,    \
1476                   char *buf)            \
1477     {                           \
1478         return ggs_show(device, attr, buf, N);      \
1479     }
1480 
1481 static GGS0_SHOW(0);
1482 static GGS0_SHOW(1);
1483 static GGS0_SHOW(2);
1484 static GGS0_SHOW(3);
1485 
1486 /* GGS register store function */
1487 #define GGS0_STORE(N)                       \
1488     ssize_t ggs##N##_store(struct device *device,       \
1489                    struct device_attribute *attr,   \
1490                    const char *buf,         \
1491                    size_t count)            \
1492     {                           \
1493         return ggs_store(device, attr, buf, count, N);  \
1494     }
1495 
1496 static GGS0_STORE(0);
1497 static GGS0_STORE(1);
1498 static GGS0_STORE(2);
1499 static GGS0_STORE(3);
1500 
1501 static ssize_t pggs_show(struct device *device,
1502              struct device_attribute *attr,
1503              char *buf,
1504              u32 reg)
1505 {
1506     int ret;
1507     u32 ret_payload[PAYLOAD_ARG_CNT];
1508 
1509     ret = zynqmp_pm_read_pggs(reg, ret_payload);
1510     if (ret)
1511         return ret;
1512 
1513     return sprintf(buf, "0x%x\n", ret_payload[1]);
1514 }
1515 
1516 static ssize_t pggs_store(struct device *device,
1517               struct device_attribute *attr,
1518               const char *buf, size_t count,
1519               u32 reg)
1520 {
1521     long value;
1522     int ret;
1523 
1524     if (reg >= GSS_NUM_REGS)
1525         return -EINVAL;
1526 
1527     ret = kstrtol(buf, 16, &value);
1528     if (ret) {
1529         count = -EFAULT;
1530         goto err;
1531     }
1532 
1533     ret = zynqmp_pm_write_pggs(reg, value);
1534     if (ret)
1535         count = -EFAULT;
1536 
1537 err:
1538     return count;
1539 }
1540 
1541 #define PGGS0_SHOW(N)                       \
1542     ssize_t pggs##N##_show(struct device *device,       \
1543                    struct device_attribute *attr,   \
1544                    char *buf)           \
1545     {                           \
1546         return pggs_show(device, attr, buf, N);     \
1547     }
1548 
1549 #define PGGS0_STORE(N)                      \
1550     ssize_t pggs##N##_store(struct device *device,      \
1551                 struct device_attribute *attr,  \
1552                 const char *buf,        \
1553                 size_t count)           \
1554     {                           \
1555         return pggs_store(device, attr, buf, count, N); \
1556     }
1557 
1558 /* PGGS register show functions */
1559 static PGGS0_SHOW(0);
1560 static PGGS0_SHOW(1);
1561 static PGGS0_SHOW(2);
1562 static PGGS0_SHOW(3);
1563 
1564 /* PGGS register store functions */
1565 static PGGS0_STORE(0);
1566 static PGGS0_STORE(1);
1567 static PGGS0_STORE(2);
1568 static PGGS0_STORE(3);
1569 
1570 /* GGS register attributes */
1571 static DEVICE_ATTR_RW(ggs0);
1572 static DEVICE_ATTR_RW(ggs1);
1573 static DEVICE_ATTR_RW(ggs2);
1574 static DEVICE_ATTR_RW(ggs3);
1575 
1576 /* PGGS register attributes */
1577 static DEVICE_ATTR_RW(pggs0);
1578 static DEVICE_ATTR_RW(pggs1);
1579 static DEVICE_ATTR_RW(pggs2);
1580 static DEVICE_ATTR_RW(pggs3);
1581 
1582 static ssize_t feature_config_id_show(struct device *device,
1583                       struct device_attribute *attr,
1584                       char *buf)
1585 {
1586     struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
1587 
1588     return sysfs_emit(buf, "%d\n", devinfo->feature_conf_id);
1589 }
1590 
1591 static ssize_t feature_config_id_store(struct device *device,
1592                        struct device_attribute *attr,
1593                        const char *buf, size_t count)
1594 {
1595     u32 config_id;
1596     int ret;
1597     struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
1598 
1599     if (!buf)
1600         return -EINVAL;
1601 
1602     ret = kstrtou32(buf, 10, &config_id);
1603     if (ret)
1604         return ret;
1605 
1606     devinfo->feature_conf_id = config_id;
1607 
1608     return count;
1609 }
1610 
1611 static DEVICE_ATTR_RW(feature_config_id);
1612 
1613 static ssize_t feature_config_value_show(struct device *device,
1614                      struct device_attribute *attr,
1615                      char *buf)
1616 {
1617     int ret;
1618     u32 ret_payload[PAYLOAD_ARG_CNT];
1619     struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
1620 
1621     ret = zynqmp_pm_get_feature_config(devinfo->feature_conf_id,
1622                        ret_payload);
1623     if (ret)
1624         return ret;
1625 
1626     return sysfs_emit(buf, "%d\n", ret_payload[1]);
1627 }
1628 
1629 static ssize_t feature_config_value_store(struct device *device,
1630                       struct device_attribute *attr,
1631                       const char *buf, size_t count)
1632 {
1633     u32 value;
1634     int ret;
1635     struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
1636 
1637     if (!buf)
1638         return -EINVAL;
1639 
1640     ret = kstrtou32(buf, 10, &value);
1641     if (ret)
1642         return ret;
1643 
1644     ret = zynqmp_pm_set_feature_config(devinfo->feature_conf_id,
1645                        value);
1646     if (ret)
1647         return ret;
1648 
1649     return count;
1650 }
1651 
1652 static DEVICE_ATTR_RW(feature_config_value);
1653 
1654 static struct attribute *zynqmp_firmware_attrs[] = {
1655     &dev_attr_ggs0.attr,
1656     &dev_attr_ggs1.attr,
1657     &dev_attr_ggs2.attr,
1658     &dev_attr_ggs3.attr,
1659     &dev_attr_pggs0.attr,
1660     &dev_attr_pggs1.attr,
1661     &dev_attr_pggs2.attr,
1662     &dev_attr_pggs3.attr,
1663     &dev_attr_shutdown_scope.attr,
1664     &dev_attr_health_status.attr,
1665     &dev_attr_feature_config_id.attr,
1666     &dev_attr_feature_config_value.attr,
1667     NULL,
1668 };
1669 
1670 ATTRIBUTE_GROUPS(zynqmp_firmware);
1671 
1672 static int zynqmp_firmware_probe(struct platform_device *pdev)
1673 {
1674     struct device *dev = &pdev->dev;
1675     struct device_node *np;
1676     struct zynqmp_devinfo *devinfo;
1677     int ret;
1678 
1679     ret = get_set_conduit_method(dev->of_node);
1680     if (ret)
1681         return ret;
1682 
1683     np = of_find_compatible_node(NULL, NULL, "xlnx,zynqmp");
1684     if (!np) {
1685         np = of_find_compatible_node(NULL, NULL, "xlnx,versal");
1686         if (!np)
1687             return 0;
1688 
1689         feature_check_enabled = true;
1690     }
1691 
1692     if (!feature_check_enabled) {
1693         ret = do_feature_check_call(PM_FEATURE_CHECK);
1694         if (ret >= 0)
1695             feature_check_enabled = true;
1696     }
1697 
1698     of_node_put(np);
1699 
1700     devinfo = devm_kzalloc(dev, sizeof(*devinfo), GFP_KERNEL);
1701     if (!devinfo)
1702         return -ENOMEM;
1703 
1704     devinfo->dev = dev;
1705 
1706     platform_set_drvdata(pdev, devinfo);
1707 
1708     /* Check PM API version number */
1709     ret = zynqmp_pm_get_api_version(&pm_api_version);
1710     if (ret)
1711         return ret;
1712 
1713     if (pm_api_version < ZYNQMP_PM_VERSION) {
1714         panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n",
1715               __func__,
1716               ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR,
1717               pm_api_version >> 16, pm_api_version & 0xFFFF);
1718     }
1719 
1720     pr_info("%s Platform Management API v%d.%d\n", __func__,
1721         pm_api_version >> 16, pm_api_version & 0xFFFF);
1722 
1723     /* Check trustzone version number */
1724     ret = zynqmp_pm_get_trustzone_version(&pm_tz_version);
1725     if (ret)
1726         panic("Legacy trustzone found without version support\n");
1727 
1728     if (pm_tz_version < ZYNQMP_TZ_VERSION)
1729         panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n",
1730               __func__,
1731               ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR,
1732               pm_tz_version >> 16, pm_tz_version & 0xFFFF);
1733 
1734     pr_info("%s Trustzone version v%d.%d\n", __func__,
1735         pm_tz_version >> 16, pm_tz_version & 0xFFFF);
1736 
1737     ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
1738                   ARRAY_SIZE(firmware_devs), NULL, 0, NULL);
1739     if (ret) {
1740         dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret);
1741         return ret;
1742     }
1743 
1744     zynqmp_pm_api_debugfs_init();
1745 
1746     np = of_find_compatible_node(NULL, NULL, "xlnx,versal");
1747     if (np) {
1748         em_dev = platform_device_register_data(&pdev->dev, "xlnx_event_manager",
1749                                -1, NULL, 0);
1750         if (IS_ERR(em_dev))
1751             dev_err_probe(&pdev->dev, PTR_ERR(em_dev), "EM register fail with error\n");
1752     }
1753     of_node_put(np);
1754 
1755     return of_platform_populate(dev->of_node, NULL, NULL, dev);
1756 }
1757 
1758 static int zynqmp_firmware_remove(struct platform_device *pdev)
1759 {
1760     struct pm_api_feature_data *feature_data;
1761     struct hlist_node *tmp;
1762     int i;
1763 
1764     mfd_remove_devices(&pdev->dev);
1765     zynqmp_pm_api_debugfs_exit();
1766 
1767     hash_for_each_safe(pm_api_features_map, i, tmp, feature_data, hentry) {
1768         hash_del(&feature_data->hentry);
1769         kfree(feature_data);
1770     }
1771 
1772     platform_device_unregister(em_dev);
1773 
1774     return 0;
1775 }
1776 
1777 static const struct of_device_id zynqmp_firmware_of_match[] = {
1778     {.compatible = "xlnx,zynqmp-firmware"},
1779     {.compatible = "xlnx,versal-firmware"},
1780     {},
1781 };
1782 MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match);
1783 
1784 static struct platform_driver zynqmp_firmware_driver = {
1785     .driver = {
1786         .name = "zynqmp_firmware",
1787         .of_match_table = zynqmp_firmware_of_match,
1788         .dev_groups = zynqmp_firmware_groups,
1789     },
1790     .probe = zynqmp_firmware_probe,
1791     .remove = zynqmp_firmware_remove,
1792 };
1793 module_platform_driver(zynqmp_firmware_driver);