cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

zynqmp.c (46333B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Xilinx Zynq MPSoC Firmware layer
      4 *
      5 *  Copyright (C) 2014-2021 Xilinx, Inc.
      6 *
      7 *  Michal Simek <michal.simek@xilinx.com>
      8 *  Davorin Mista <davorin.mista@aggios.com>
      9 *  Jolly Shah <jollys@xilinx.com>
     10 *  Rajan Vaja <rajanv@xilinx.com>
     11 */
     12
     13#include <linux/arm-smccc.h>
     14#include <linux/compiler.h>
     15#include <linux/device.h>
     16#include <linux/init.h>
     17#include <linux/mfd/core.h>
     18#include <linux/module.h>
     19#include <linux/of.h>
     20#include <linux/of_platform.h>
     21#include <linux/slab.h>
     22#include <linux/uaccess.h>
     23#include <linux/hashtable.h>
     24
     25#include <linux/firmware/xlnx-zynqmp.h>
     26#include <linux/firmware/xlnx-event-manager.h>
     27#include "zynqmp-debug.h"
     28
     29/* Max HashMap Order for PM API feature check (1<<7 = 128) */
     30#define PM_API_FEATURE_CHECK_MAX_ORDER  7
     31
     32/* CRL registers and bitfields */
     33#define CRL_APB_BASE			0xFF5E0000U
     34/* BOOT_PIN_CTRL- Used to control the mode pins after boot */
     35#define CRL_APB_BOOT_PIN_CTRL		(CRL_APB_BASE + (0x250U))
     36/* BOOT_PIN_CTRL_MASK- out_val[11:8], out_en[3:0] */
     37#define CRL_APB_BOOTPIN_CTRL_MASK	0xF0FU
     38
     39/* IOCTL/QUERY feature payload size */
     40#define FEATURE_PAYLOAD_SIZE		2
     41
     42/* Firmware feature check version mask */
     43#define FIRMWARE_VERSION_MASK		GENMASK(15, 0)
     44
     45static bool feature_check_enabled;
     46static DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER);
     47static u32 ioctl_features[FEATURE_PAYLOAD_SIZE];
     48static u32 query_features[FEATURE_PAYLOAD_SIZE];
     49
     50static struct platform_device *em_dev;
     51
     52/**
     53 * struct zynqmp_devinfo - Structure for Zynqmp device instance
     54 * @dev:		Device Pointer
     55 * @feature_conf_id:	Feature conf id
     56 */
     57struct zynqmp_devinfo {
     58	struct device *dev;
     59	u32 feature_conf_id;
     60};
     61
     62/**
     63 * struct pm_api_feature_data - PM API Feature data
     64 * @pm_api_id:		PM API Id, used as key to index into hashmap
     65 * @feature_status:	status of PM API feature: valid, invalid
     66 * @hentry:		hlist_node that hooks this entry into hashtable
     67 */
     68struct pm_api_feature_data {
     69	u32 pm_api_id;
     70	int feature_status;
     71	struct hlist_node hentry;
     72};
     73
     74static const struct mfd_cell firmware_devs[] = {
     75	{
     76		.name = "zynqmp_power_controller",
     77	},
     78};
     79
     80/**
     81 * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes
     82 * @ret_status:		PMUFW return code
     83 *
     84 * Return: corresponding Linux error code
     85 */
     86static int zynqmp_pm_ret_code(u32 ret_status)
     87{
     88	switch (ret_status) {
     89	case XST_PM_SUCCESS:
     90	case XST_PM_DOUBLE_REQ:
     91		return 0;
     92	case XST_PM_NO_FEATURE:
     93		return -ENOTSUPP;
     94	case XST_PM_NO_ACCESS:
     95		return -EACCES;
     96	case XST_PM_ABORT_SUSPEND:
     97		return -ECANCELED;
     98	case XST_PM_MULT_USER:
     99		return -EUSERS;
    100	case XST_PM_INTERNAL:
    101	case XST_PM_CONFLICT:
    102	case XST_PM_INVALID_NODE:
    103	default:
    104		return -EINVAL;
    105	}
    106}
    107
    108static noinline int do_fw_call_fail(u64 arg0, u64 arg1, u64 arg2,
    109				    u32 *ret_payload)
    110{
    111	return -ENODEV;
    112}
    113
    114/*
    115 * PM function call wrapper
    116 * Invoke do_fw_call_smc or do_fw_call_hvc, depending on the configuration
    117 */
    118static int (*do_fw_call)(u64, u64, u64, u32 *ret_payload) = do_fw_call_fail;
    119
    120/**
    121 * do_fw_call_smc() - Call system-level platform management layer (SMC)
    122 * @arg0:		Argument 0 to SMC call
    123 * @arg1:		Argument 1 to SMC call
    124 * @arg2:		Argument 2 to SMC call
    125 * @ret_payload:	Returned value array
    126 *
    127 * Invoke platform management function via SMC call (no hypervisor present).
    128 *
    129 * Return: Returns status, either success or error+reason
    130 */
    131static noinline int do_fw_call_smc(u64 arg0, u64 arg1, u64 arg2,
    132				   u32 *ret_payload)
    133{
    134	struct arm_smccc_res res;
    135
    136	arm_smccc_smc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
    137
    138	if (ret_payload) {
    139		ret_payload[0] = lower_32_bits(res.a0);
    140		ret_payload[1] = upper_32_bits(res.a0);
    141		ret_payload[2] = lower_32_bits(res.a1);
    142		ret_payload[3] = upper_32_bits(res.a1);
    143	}
    144
    145	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
    146}
    147
    148/**
    149 * do_fw_call_hvc() - Call system-level platform management layer (HVC)
    150 * @arg0:		Argument 0 to HVC call
    151 * @arg1:		Argument 1 to HVC call
    152 * @arg2:		Argument 2 to HVC call
    153 * @ret_payload:	Returned value array
    154 *
    155 * Invoke platform management function via HVC
    156 * HVC-based for communication through hypervisor
    157 * (no direct communication with ATF).
    158 *
    159 * Return: Returns status, either success or error+reason
    160 */
    161static noinline int do_fw_call_hvc(u64 arg0, u64 arg1, u64 arg2,
    162				   u32 *ret_payload)
    163{
    164	struct arm_smccc_res res;
    165
    166	arm_smccc_hvc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
    167
    168	if (ret_payload) {
    169		ret_payload[0] = lower_32_bits(res.a0);
    170		ret_payload[1] = upper_32_bits(res.a0);
    171		ret_payload[2] = lower_32_bits(res.a1);
    172		ret_payload[3] = upper_32_bits(res.a1);
    173	}
    174
    175	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
    176}
    177
    178static int __do_feature_check_call(const u32 api_id, u32 *ret_payload)
    179{
    180	int ret;
    181	u64 smc_arg[2];
    182
    183	smc_arg[0] = PM_SIP_SVC | PM_FEATURE_CHECK;
    184	smc_arg[1] = api_id;
    185
    186	ret = do_fw_call(smc_arg[0], smc_arg[1], 0, ret_payload);
    187	if (ret)
    188		ret = -EOPNOTSUPP;
    189	else
    190		ret = ret_payload[1];
    191
    192	return ret;
    193}
    194
    195static int do_feature_check_call(const u32 api_id)
    196{
    197	int ret;
    198	u32 ret_payload[PAYLOAD_ARG_CNT];
    199	struct pm_api_feature_data *feature_data;
    200
    201	/* Check for existing entry in hash table for given api */
    202	hash_for_each_possible(pm_api_features_map, feature_data, hentry,
    203			       api_id) {
    204		if (feature_data->pm_api_id == api_id)
    205			return feature_data->feature_status;
    206	}
    207
    208	/* Add new entry if not present */
    209	feature_data = kmalloc(sizeof(*feature_data), GFP_KERNEL);
    210	if (!feature_data)
    211		return -ENOMEM;
    212
    213	feature_data->pm_api_id = api_id;
    214	ret = __do_feature_check_call(api_id, ret_payload);
    215
    216	feature_data->feature_status = ret;
    217	hash_add(pm_api_features_map, &feature_data->hentry, api_id);
    218
    219	if (api_id == PM_IOCTL)
    220		/* Store supported IOCTL IDs mask */
    221		memcpy(ioctl_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4);
    222	else if (api_id == PM_QUERY_DATA)
    223		/* Store supported QUERY IDs mask */
    224		memcpy(query_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4);
    225
    226	return ret;
    227}
    228EXPORT_SYMBOL_GPL(zynqmp_pm_feature);
    229
    230/**
    231 * zynqmp_pm_feature() - Check whether given feature is supported or not and
    232 *			 store supported IOCTL/QUERY ID mask
    233 * @api_id:		API ID to check
    234 *
    235 * Return: Returns status, either success or error+reason
    236 */
    237int zynqmp_pm_feature(const u32 api_id)
    238{
    239	int ret;
    240
    241	if (!feature_check_enabled)
    242		return 0;
    243
    244	ret = do_feature_check_call(api_id);
    245
    246	return ret;
    247}
    248
    249/**
    250 * zynqmp_pm_is_function_supported() - Check whether given IOCTL/QUERY function
    251 *				       is supported or not
    252 * @api_id:		PM_IOCTL or PM_QUERY_DATA
    253 * @id:			IOCTL or QUERY function IDs
    254 *
    255 * Return: Returns status, either success or error+reason
    256 */
    257int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
    258{
    259	int ret;
    260	u32 *bit_mask;
    261
    262	/* Input arguments validation */
    263	if (id >= 64 || (api_id != PM_IOCTL && api_id != PM_QUERY_DATA))
    264		return -EINVAL;
    265
    266	/* Check feature check API version */
    267	ret = do_feature_check_call(PM_FEATURE_CHECK);
    268	if (ret < 0)
    269		return ret;
    270
    271	/* Check if feature check version 2 is supported or not */
    272	if ((ret & FIRMWARE_VERSION_MASK) == PM_API_VERSION_2) {
    273		/*
    274		 * Call feature check for IOCTL/QUERY API to get IOCTL ID or
    275		 * QUERY ID feature status.
    276		 */
    277		ret = do_feature_check_call(api_id);
    278		if (ret < 0)
    279			return ret;
    280
    281		bit_mask = (api_id == PM_IOCTL) ? ioctl_features : query_features;
    282
    283		if ((bit_mask[(id / 32)] & BIT((id % 32))) == 0U)
    284			return -EOPNOTSUPP;
    285	} else {
    286		return -ENODATA;
    287	}
    288
    289	return 0;
    290}
    291EXPORT_SYMBOL_GPL(zynqmp_pm_is_function_supported);
    292
    293/**
    294 * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer
    295 *			   caller function depending on the configuration
    296 * @pm_api_id:		Requested PM-API call
    297 * @arg0:		Argument 0 to requested PM-API call
    298 * @arg1:		Argument 1 to requested PM-API call
    299 * @arg2:		Argument 2 to requested PM-API call
    300 * @arg3:		Argument 3 to requested PM-API call
    301 * @ret_payload:	Returned value array
    302 *
    303 * Invoke platform management function for SMC or HVC call, depending on
    304 * configuration.
    305 * Following SMC Calling Convention (SMCCC) for SMC64:
    306 * Pm Function Identifier,
    307 * PM_SIP_SVC + PM_API_ID =
    308 *	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)
    309 *	((SMC_64) << FUNCID_CC_SHIFT)
    310 *	((SIP_START) << FUNCID_OEN_SHIFT)
    311 *	((PM_API_ID) & FUNCID_NUM_MASK))
    312 *
    313 * PM_SIP_SVC	- Registered ZynqMP SIP Service Call.
    314 * PM_API_ID	- Platform Management API ID.
    315 *
    316 * Return: Returns status, either success or error+reason
    317 */
    318int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1,
    319			u32 arg2, u32 arg3, u32 *ret_payload)
    320{
    321	/*
    322	 * Added SIP service call Function Identifier
    323	 * Make sure to stay in x0 register
    324	 */
    325	u64 smc_arg[4];
    326	int ret;
    327
    328	/* Check if feature is supported or not */
    329	ret = zynqmp_pm_feature(pm_api_id);
    330	if (ret < 0)
    331		return ret;
    332
    333	smc_arg[0] = PM_SIP_SVC | pm_api_id;
    334	smc_arg[1] = ((u64)arg1 << 32) | arg0;
    335	smc_arg[2] = ((u64)arg3 << 32) | arg2;
    336
    337	return do_fw_call(smc_arg[0], smc_arg[1], smc_arg[2], ret_payload);
    338}
    339
    340static u32 pm_api_version;
    341static u32 pm_tz_version;
    342
    343/**
    344 * zynqmp_pm_get_api_version() - Get version number of PMU PM firmware
    345 * @version:	Returned version value
    346 *
    347 * Return: Returns status, either success or error+reason
    348 */
    349int zynqmp_pm_get_api_version(u32 *version)
    350{
    351	u32 ret_payload[PAYLOAD_ARG_CNT];
    352	int ret;
    353
    354	if (!version)
    355		return -EINVAL;
    356
    357	/* Check is PM API version already verified */
    358	if (pm_api_version > 0) {
    359		*version = pm_api_version;
    360		return 0;
    361	}
    362	ret = zynqmp_pm_invoke_fn(PM_GET_API_VERSION, 0, 0, 0, 0, ret_payload);
    363	*version = ret_payload[1];
    364
    365	return ret;
    366}
    367EXPORT_SYMBOL_GPL(zynqmp_pm_get_api_version);
    368
    369/**
    370 * zynqmp_pm_get_chipid - Get silicon ID registers
    371 * @idcode:     IDCODE register
    372 * @version:    version register
    373 *
    374 * Return:      Returns the status of the operation and the idcode and version
    375 *              registers in @idcode and @version.
    376 */
    377int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
    378{
    379	u32 ret_payload[PAYLOAD_ARG_CNT];
    380	int ret;
    381
    382	if (!idcode || !version)
    383		return -EINVAL;
    384
    385	ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
    386	*idcode = ret_payload[1];
    387	*version = ret_payload[2];
    388
    389	return ret;
    390}
    391EXPORT_SYMBOL_GPL(zynqmp_pm_get_chipid);
    392
    393/**
    394 * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
    395 * @version:	Returned version value
    396 *
    397 * Return: Returns status, either success or error+reason
    398 */
    399static int zynqmp_pm_get_trustzone_version(u32 *version)
    400{
    401	u32 ret_payload[PAYLOAD_ARG_CNT];
    402	int ret;
    403
    404	if (!version)
    405		return -EINVAL;
    406
    407	/* Check is PM trustzone version already verified */
    408	if (pm_tz_version > 0) {
    409		*version = pm_tz_version;
    410		return 0;
    411	}
    412	ret = zynqmp_pm_invoke_fn(PM_GET_TRUSTZONE_VERSION, 0, 0,
    413				  0, 0, ret_payload);
    414	*version = ret_payload[1];
    415
    416	return ret;
    417}
    418
    419/**
    420 * get_set_conduit_method() - Choose SMC or HVC based communication
    421 * @np:		Pointer to the device_node structure
    422 *
    423 * Use SMC or HVC-based functions to communicate with EL2/EL3.
    424 *
    425 * Return: Returns 0 on success or error code
    426 */
    427static int get_set_conduit_method(struct device_node *np)
    428{
    429	const char *method;
    430
    431	if (of_property_read_string(np, "method", &method)) {
    432		pr_warn("%s missing \"method\" property\n", __func__);
    433		return -ENXIO;
    434	}
    435
    436	if (!strcmp("hvc", method)) {
    437		do_fw_call = do_fw_call_hvc;
    438	} else if (!strcmp("smc", method)) {
    439		do_fw_call = do_fw_call_smc;
    440	} else {
    441		pr_warn("%s Invalid \"method\" property: %s\n",
    442			__func__, method);
    443		return -EINVAL;
    444	}
    445
    446	return 0;
    447}
    448
    449/**
    450 * zynqmp_pm_query_data() - Get query data from firmware
    451 * @qdata:	Variable to the zynqmp_pm_query_data structure
    452 * @out:	Returned output value
    453 *
    454 * Return: Returns status, either success or error+reason
    455 */
    456int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
    457{
    458	int ret;
    459
    460	ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, qdata.qid, qdata.arg1,
    461				  qdata.arg2, qdata.arg3, out);
    462
    463	/*
    464	 * For clock name query, all bytes in SMC response are clock name
    465	 * characters and return code is always success. For invalid clocks,
    466	 * clock name bytes would be zeros.
    467	 */
    468	return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret;
    469}
    470EXPORT_SYMBOL_GPL(zynqmp_pm_query_data);
    471
    472/**
    473 * zynqmp_pm_clock_enable() - Enable the clock for given id
    474 * @clock_id:	ID of the clock to be enabled
    475 *
    476 * This function is used by master to enable the clock
    477 * including peripherals and PLL clocks.
    478 *
    479 * Return: Returns status, either success or error+reason
    480 */
    481int zynqmp_pm_clock_enable(u32 clock_id)
    482{
    483	return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL);
    484}
    485EXPORT_SYMBOL_GPL(zynqmp_pm_clock_enable);
    486
    487/**
    488 * zynqmp_pm_clock_disable() - Disable the clock for given id
    489 * @clock_id:	ID of the clock to be disable
    490 *
    491 * This function is used by master to disable the clock
    492 * including peripherals and PLL clocks.
    493 *
    494 * Return: Returns status, either success or error+reason
    495 */
    496int zynqmp_pm_clock_disable(u32 clock_id)
    497{
    498	return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL);
    499}
    500EXPORT_SYMBOL_GPL(zynqmp_pm_clock_disable);
    501
    502/**
    503 * zynqmp_pm_clock_getstate() - Get the clock state for given id
    504 * @clock_id:	ID of the clock to be queried
    505 * @state:	1/0 (Enabled/Disabled)
    506 *
    507 * This function is used by master to get the state of clock
    508 * including peripherals and PLL clocks.
    509 *
    510 * Return: Returns status, either success or error+reason
    511 */
    512int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
    513{
    514	u32 ret_payload[PAYLOAD_ARG_CNT];
    515	int ret;
    516
    517	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, clock_id, 0,
    518				  0, 0, ret_payload);
    519	*state = ret_payload[1];
    520
    521	return ret;
    522}
    523EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getstate);
    524
    525/**
    526 * zynqmp_pm_clock_setdivider() - Set the clock divider for given id
    527 * @clock_id:	ID of the clock
    528 * @divider:	divider value
    529 *
    530 * This function is used by master to set divider for any clock
    531 * to achieve desired rate.
    532 *
    533 * Return: Returns status, either success or error+reason
    534 */
    535int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider)
    536{
    537	return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, clock_id, divider,
    538				   0, 0, NULL);
    539}
    540EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setdivider);
    541
    542/**
    543 * zynqmp_pm_clock_getdivider() - Get the clock divider for given id
    544 * @clock_id:	ID of the clock
    545 * @divider:	divider value
    546 *
    547 * This function is used by master to get divider values
    548 * for any clock.
    549 *
    550 * Return: Returns status, either success or error+reason
    551 */
    552int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
    553{
    554	u32 ret_payload[PAYLOAD_ARG_CNT];
    555	int ret;
    556
    557	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, clock_id, 0,
    558				  0, 0, ret_payload);
    559	*divider = ret_payload[1];
    560
    561	return ret;
    562}
    563EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getdivider);
    564
    565/**
    566 * zynqmp_pm_clock_setrate() - Set the clock rate for given id
    567 * @clock_id:	ID of the clock
    568 * @rate:	rate value in hz
    569 *
    570 * This function is used by master to set rate for any clock.
    571 *
    572 * Return: Returns status, either success or error+reason
    573 */
    574int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate)
    575{
    576	return zynqmp_pm_invoke_fn(PM_CLOCK_SETRATE, clock_id,
    577				   lower_32_bits(rate),
    578				   upper_32_bits(rate),
    579				   0, NULL);
    580}
    581EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setrate);
    582
    583/**
    584 * zynqmp_pm_clock_getrate() - Get the clock rate for given id
    585 * @clock_id:	ID of the clock
    586 * @rate:	rate value in hz
    587 *
    588 * This function is used by master to get rate
    589 * for any clock.
    590 *
    591 * Return: Returns status, either success or error+reason
    592 */
    593int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate)
    594{
    595	u32 ret_payload[PAYLOAD_ARG_CNT];
    596	int ret;
    597
    598	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETRATE, clock_id, 0,
    599				  0, 0, ret_payload);
    600	*rate = ((u64)ret_payload[2] << 32) | ret_payload[1];
    601
    602	return ret;
    603}
    604EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getrate);
    605
    606/**
    607 * zynqmp_pm_clock_setparent() - Set the clock parent for given id
    608 * @clock_id:	ID of the clock
    609 * @parent_id:	parent id
    610 *
    611 * This function is used by master to set parent for any clock.
    612 *
    613 * Return: Returns status, either success or error+reason
    614 */
    615int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id)
    616{
    617	return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, clock_id,
    618				   parent_id, 0, 0, NULL);
    619}
    620EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setparent);
    621
    622/**
    623 * zynqmp_pm_clock_getparent() - Get the clock parent for given id
    624 * @clock_id:	ID of the clock
    625 * @parent_id:	parent id
    626 *
    627 * This function is used by master to get parent index
    628 * for any clock.
    629 *
    630 * Return: Returns status, either success or error+reason
    631 */
    632int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)
    633{
    634	u32 ret_payload[PAYLOAD_ARG_CNT];
    635	int ret;
    636
    637	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, clock_id, 0,
    638				  0, 0, ret_payload);
    639	*parent_id = ret_payload[1];
    640
    641	return ret;
    642}
    643EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getparent);
    644
    645/**
    646 * zynqmp_pm_set_pll_frac_mode() - PM API for set PLL mode
    647 *
    648 * @clk_id:	PLL clock ID
    649 * @mode:	PLL mode (PLL_MODE_FRAC/PLL_MODE_INT)
    650 *
    651 * This function sets PLL mode
    652 *
    653 * Return: Returns status, either success or error+reason
    654 */
    655int zynqmp_pm_set_pll_frac_mode(u32 clk_id, u32 mode)
    656{
    657	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_MODE,
    658				   clk_id, mode, NULL);
    659}
    660EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_mode);
    661
    662/**
    663 * zynqmp_pm_get_pll_frac_mode() - PM API for get PLL mode
    664 *
    665 * @clk_id:	PLL clock ID
    666 * @mode:	PLL mode
    667 *
    668 * This function return current PLL mode
    669 *
    670 * Return: Returns status, either success or error+reason
    671 */
    672int zynqmp_pm_get_pll_frac_mode(u32 clk_id, u32 *mode)
    673{
    674	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_MODE,
    675				   clk_id, 0, mode);
    676}
    677EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_mode);
    678
    679/**
    680 * zynqmp_pm_set_pll_frac_data() - PM API for setting pll fraction data
    681 *
    682 * @clk_id:	PLL clock ID
    683 * @data:	fraction data
    684 *
    685 * This function sets fraction data.
    686 * It is valid for fraction mode only.
    687 *
    688 * Return: Returns status, either success or error+reason
    689 */
    690int zynqmp_pm_set_pll_frac_data(u32 clk_id, u32 data)
    691{
    692	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_DATA,
    693				   clk_id, data, NULL);
    694}
    695EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_data);
    696
    697/**
    698 * zynqmp_pm_get_pll_frac_data() - PM API for getting pll fraction data
    699 *
    700 * @clk_id:	PLL clock ID
    701 * @data:	fraction data
    702 *
    703 * This function returns fraction data value.
    704 *
    705 * Return: Returns status, either success or error+reason
    706 */
    707int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data)
    708{
    709	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_DATA,
    710				   clk_id, 0, data);
    711}
    712EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data);
    713
    714/**
    715 * zynqmp_pm_set_sd_tapdelay() -  Set tap delay for the SD device
    716 *
    717 * @node_id:	Node ID of the device
    718 * @type:	Type of tap delay to set (input/output)
    719 * @value:	Value to set fot the tap delay
    720 *
    721 * This function sets input/output tap delay for the SD device.
    722 *
    723 * Return:	Returns status, either success or error+reason
    724 */
    725int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value)
    726{
    727	return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY,
    728				   type, value, NULL);
    729}
    730EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay);
    731
    732/**
    733 * zynqmp_pm_sd_dll_reset() - Reset DLL logic
    734 *
    735 * @node_id:	Node ID of the device
    736 * @type:	Reset type
    737 *
    738 * This function resets DLL logic for the SD device.
    739 *
    740 * Return:	Returns status, either success or error+reason
    741 */
    742int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type)
    743{
    744	return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SD_DLL_RESET,
    745				   type, 0, NULL);
    746}
    747EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset);
    748
    749/**
    750 * zynqmp_pm_ospi_mux_select() - OSPI Mux selection
    751 *
    752 * @dev_id:	Device Id of the OSPI device.
    753 * @select:	OSPI Mux select value.
    754 *
    755 * This function select the OSPI Mux.
    756 *
    757 * Return:	Returns status, either success or error+reason
    758 */
    759int zynqmp_pm_ospi_mux_select(u32 dev_id, u32 select)
    760{
    761	return zynqmp_pm_invoke_fn(PM_IOCTL, dev_id, IOCTL_OSPI_MUX_SELECT,
    762				   select, 0, NULL);
    763}
    764EXPORT_SYMBOL_GPL(zynqmp_pm_ospi_mux_select);
    765
    766/**
    767 * zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs)
    768 * @index:	GGS register index
    769 * @value:	Register value to be written
    770 *
    771 * This function writes value to GGS register.
    772 *
    773 * Return:      Returns status, either success or error+reason
    774 */
    775int zynqmp_pm_write_ggs(u32 index, u32 value)
    776{
    777	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_GGS,
    778				   index, value, NULL);
    779}
    780EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs);
    781
    782/**
    783 * zynqmp_pm_read_ggs() - PM API for reading global general storage (ggs)
    784 * @index:	GGS register index
    785 * @value:	Register value to be written
    786 *
    787 * This function returns GGS register value.
    788 *
    789 * Return:	Returns status, either success or error+reason
    790 */
    791int zynqmp_pm_read_ggs(u32 index, u32 *value)
    792{
    793	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_GGS,
    794				   index, 0, value);
    795}
    796EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs);
    797
    798/**
    799 * zynqmp_pm_write_pggs() - PM API for writing persistent global general
    800 *			     storage (pggs)
    801 * @index:	PGGS register index
    802 * @value:	Register value to be written
    803 *
    804 * This function writes value to PGGS register.
    805 *
    806 * Return:	Returns status, either success or error+reason
    807 */
    808int zynqmp_pm_write_pggs(u32 index, u32 value)
    809{
    810	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_PGGS, index, value,
    811				   NULL);
    812}
    813EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs);
    814
    815/**
    816 * zynqmp_pm_read_pggs() - PM API for reading persistent global general
    817 *			     storage (pggs)
    818 * @index:	PGGS register index
    819 * @value:	Register value to be written
    820 *
    821 * This function returns PGGS register value.
    822 *
    823 * Return:	Returns status, either success or error+reason
    824 */
    825int zynqmp_pm_read_pggs(u32 index, u32 *value)
    826{
    827	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_PGGS, index, 0,
    828				   value);
    829}
    830EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs);
    831
    832/**
    833 * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status
    834 * @value:	Status value to be written
    835 *
    836 * This function sets healthy bit value to indicate boot health status
    837 * to firmware.
    838 *
    839 * Return:	Returns status, either success or error+reason
    840 */
    841int zynqmp_pm_set_boot_health_status(u32 value)
    842{
    843	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_BOOT_HEALTH_STATUS,
    844				   value, 0, NULL);
    845}
    846
    847/**
    848 * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release)
    849 * @reset:		Reset to be configured
    850 * @assert_flag:	Flag stating should reset be asserted (1) or
    851 *			released (0)
    852 *
    853 * Return: Returns status, either success or error+reason
    854 */
    855int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
    856			   const enum zynqmp_pm_reset_action assert_flag)
    857{
    858	return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag,
    859				   0, 0, NULL);
    860}
    861EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert);
    862
    863/**
    864 * zynqmp_pm_reset_get_status - Get status of the reset
    865 * @reset:      Reset whose status should be returned
    866 * @status:     Returned status
    867 *
    868 * Return: Returns status, either success or error+reason
    869 */
    870int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status)
    871{
    872	u32 ret_payload[PAYLOAD_ARG_CNT];
    873	int ret;
    874
    875	if (!status)
    876		return -EINVAL;
    877
    878	ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0,
    879				  0, 0, ret_payload);
    880	*status = ret_payload[1];
    881
    882	return ret;
    883}
    884EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status);
    885
    886/**
    887 * zynqmp_pm_fpga_load - Perform the fpga load
    888 * @address:	Address to write to
    889 * @size:	pl bitstream size
    890 * @flags:	Bitstream type
    891 *	-XILINX_ZYNQMP_PM_FPGA_FULL:  FPGA full reconfiguration
    892 *	-XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration
    893 *
    894 * This function provides access to pmufw. To transfer
    895 * the required bitstream into PL.
    896 *
    897 * Return: Returns status, either success or error+reason
    898 */
    899int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags)
    900{
    901	return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
    902				   upper_32_bits(address), size, flags, NULL);
    903}
    904EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load);
    905
    906/**
    907 * zynqmp_pm_fpga_get_status - Read value from PCAP status register
    908 * @value: Value to read
    909 *
    910 * This function provides access to the pmufw to get the PCAP
    911 * status
    912 *
    913 * Return: Returns status, either success or error+reason
    914 */
    915int zynqmp_pm_fpga_get_status(u32 *value)
    916{
    917	u32 ret_payload[PAYLOAD_ARG_CNT];
    918	int ret;
    919
    920	if (!value)
    921		return -EINVAL;
    922
    923	ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload);
    924	*value = ret_payload[1];
    925
    926	return ret;
    927}
    928EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status);
    929
    930/**
    931 * zynqmp_pm_pinctrl_request - Request Pin from firmware
    932 * @pin: Pin number to request
    933 *
    934 * This function requests pin from firmware.
    935 *
    936 * Return: Returns status, either success or error+reason.
    937 */
    938int zynqmp_pm_pinctrl_request(const u32 pin)
    939{
    940	return zynqmp_pm_invoke_fn(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL);
    941}
    942EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_request);
    943
    944/**
    945 * zynqmp_pm_pinctrl_release - Inform firmware that Pin control is released
    946 * @pin: Pin number to release
    947 *
    948 * This function release pin from firmware.
    949 *
    950 * Return: Returns status, either success or error+reason.
    951 */
    952int zynqmp_pm_pinctrl_release(const u32 pin)
    953{
    954	return zynqmp_pm_invoke_fn(PM_PINCTRL_RELEASE, pin, 0, 0, 0, NULL);
    955}
    956EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_release);
    957
    958/**
    959 * zynqmp_pm_pinctrl_get_function - Read function id set for the given pin
    960 * @pin: Pin number
    961 * @id: Buffer to store function ID
    962 *
    963 * This function provides the function currently set for the given pin.
    964 *
    965 * Return: Returns status, either success or error+reason
    966 */
    967int zynqmp_pm_pinctrl_get_function(const u32 pin, u32 *id)
    968{
    969	u32 ret_payload[PAYLOAD_ARG_CNT];
    970	int ret;
    971
    972	if (!id)
    973		return -EINVAL;
    974
    975	ret = zynqmp_pm_invoke_fn(PM_PINCTRL_GET_FUNCTION, pin, 0,
    976				  0, 0, ret_payload);
    977	*id = ret_payload[1];
    978
    979	return ret;
    980}
    981EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_function);
    982
    983/**
    984 * zynqmp_pm_pinctrl_set_function - Set requested function for the pin
    985 * @pin: Pin number
    986 * @id: Function ID to set
    987 *
    988 * This function sets requested function for the given pin.
    989 *
    990 * Return: Returns status, either success or error+reason.
    991 */
    992int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id)
    993{
    994	return zynqmp_pm_invoke_fn(PM_PINCTRL_SET_FUNCTION, pin, id,
    995				   0, 0, NULL);
    996}
    997EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_function);
    998
    999/**
   1000 * zynqmp_pm_pinctrl_get_config - Get configuration parameter for the pin
   1001 * @pin: Pin number
   1002 * @param: Parameter to get
   1003 * @value: Buffer to store parameter value
   1004 *
   1005 * This function gets requested configuration parameter for the given pin.
   1006 *
   1007 * Return: Returns status, either success or error+reason.
   1008 */
   1009int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param,
   1010				 u32 *value)
   1011{
   1012	u32 ret_payload[PAYLOAD_ARG_CNT];
   1013	int ret;
   1014
   1015	if (!value)
   1016		return -EINVAL;
   1017
   1018	ret = zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_GET, pin, param,
   1019				  0, 0, ret_payload);
   1020	*value = ret_payload[1];
   1021
   1022	return ret;
   1023}
   1024EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_config);
   1025
   1026/**
   1027 * zynqmp_pm_pinctrl_set_config - Set configuration parameter for the pin
   1028 * @pin: Pin number
   1029 * @param: Parameter to set
   1030 * @value: Parameter value to set
   1031 *
   1032 * This function sets requested configuration parameter for the given pin.
   1033 *
   1034 * Return: Returns status, either success or error+reason.
   1035 */
   1036int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param,
   1037				 u32 value)
   1038{
   1039	return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, pin,
   1040				   param, value, 0, NULL);
   1041}
   1042EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_config);
   1043
   1044/**
   1045 * zynqmp_pm_bootmode_read() - PM Config API for read bootpin status
   1046 * @ps_mode: Returned output value of ps_mode
   1047 *
   1048 * This API function is to be used for notify the power management controller
   1049 * to read bootpin status.
   1050 *
   1051 * Return: status, either success or error+reason
   1052 */
   1053unsigned int zynqmp_pm_bootmode_read(u32 *ps_mode)
   1054{
   1055	unsigned int ret;
   1056	u32 ret_payload[PAYLOAD_ARG_CNT];
   1057
   1058	ret = zynqmp_pm_invoke_fn(PM_MMIO_READ, CRL_APB_BOOT_PIN_CTRL, 0,
   1059				  0, 0, ret_payload);
   1060
   1061	*ps_mode = ret_payload[1];
   1062
   1063	return ret;
   1064}
   1065EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_read);
   1066
   1067/**
   1068 * zynqmp_pm_bootmode_write() - PM Config API for Configure bootpin
   1069 * @ps_mode: Value to be written to the bootpin ctrl register
   1070 *
   1071 * This API function is to be used for notify the power management controller
   1072 * to configure bootpin.
   1073 *
   1074 * Return: Returns status, either success or error+reason
   1075 */
   1076int zynqmp_pm_bootmode_write(u32 ps_mode)
   1077{
   1078	return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, CRL_APB_BOOT_PIN_CTRL,
   1079				   CRL_APB_BOOTPIN_CTRL_MASK, ps_mode, 0, NULL);
   1080}
   1081EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_write);
   1082
   1083/**
   1084 * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
   1085 *			       master has initialized its own power management
   1086 *
   1087 * Return: Returns status, either success or error+reason
   1088 *
   1089 * This API function is to be used for notify the power management controller
   1090 * about the completed power management initialization.
   1091 */
   1092int zynqmp_pm_init_finalize(void)
   1093{
   1094	return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL);
   1095}
   1096EXPORT_SYMBOL_GPL(zynqmp_pm_init_finalize);
   1097
   1098/**
   1099 * zynqmp_pm_set_suspend_mode()	- Set system suspend mode
   1100 * @mode:	Mode to set for system suspend
   1101 *
   1102 * This API function is used to set mode of system suspend.
   1103 *
   1104 * Return: Returns status, either success or error+reason
   1105 */
   1106int zynqmp_pm_set_suspend_mode(u32 mode)
   1107{
   1108	return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL);
   1109}
   1110EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode);
   1111
   1112/**
   1113 * zynqmp_pm_request_node() - Request a node with specific capabilities
   1114 * @node:		Node ID of the slave
   1115 * @capabilities:	Requested capabilities of the slave
   1116 * @qos:		Quality of service (not supported)
   1117 * @ack:		Flag to specify whether acknowledge is requested
   1118 *
   1119 * This function is used by master to request particular node from firmware.
   1120 * Every master must request node before using it.
   1121 *
   1122 * Return: Returns status, either success or error+reason
   1123 */
   1124int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
   1125			   const u32 qos, const enum zynqmp_pm_request_ack ack)
   1126{
   1127	return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities,
   1128				   qos, ack, NULL);
   1129}
   1130EXPORT_SYMBOL_GPL(zynqmp_pm_request_node);
   1131
   1132/**
   1133 * zynqmp_pm_release_node() - Release a node
   1134 * @node:	Node ID of the slave
   1135 *
   1136 * This function is used by master to inform firmware that master
   1137 * has released node. Once released, master must not use that node
   1138 * without re-request.
   1139 *
   1140 * Return: Returns status, either success or error+reason
   1141 */
   1142int zynqmp_pm_release_node(const u32 node)
   1143{
   1144	return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL);
   1145}
   1146EXPORT_SYMBOL_GPL(zynqmp_pm_release_node);
   1147
   1148/**
   1149 * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
   1150 * @node:		Node ID of the slave
   1151 * @capabilities:	Requested capabilities of the slave
   1152 * @qos:		Quality of service (not supported)
   1153 * @ack:		Flag to specify whether acknowledge is requested
   1154 *
   1155 * This API function is to be used for slaves a PU already has requested
   1156 * to change its capabilities.
   1157 *
   1158 * Return: Returns status, either success or error+reason
   1159 */
   1160int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
   1161			      const u32 qos,
   1162			      const enum zynqmp_pm_request_ack ack)
   1163{
   1164	return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities,
   1165				   qos, ack, NULL);
   1166}
   1167EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement);
   1168
   1169/**
   1170 * zynqmp_pm_load_pdi - Load and process PDI
   1171 * @src:       Source device where PDI is located
   1172 * @address:   PDI src address
   1173 *
   1174 * This function provides support to load PDI from linux
   1175 *
   1176 * Return: Returns status, either success or error+reason
   1177 */
   1178int zynqmp_pm_load_pdi(const u32 src, const u64 address)
   1179{
   1180	return zynqmp_pm_invoke_fn(PM_LOAD_PDI, src,
   1181				   lower_32_bits(address),
   1182				   upper_32_bits(address), 0, NULL);
   1183}
   1184EXPORT_SYMBOL_GPL(zynqmp_pm_load_pdi);
   1185
   1186/**
   1187 * zynqmp_pm_aes_engine - Access AES hardware to encrypt/decrypt the data using
   1188 * AES-GCM core.
   1189 * @address:	Address of the AesParams structure.
   1190 * @out:	Returned output value
   1191 *
   1192 * Return:	Returns status, either success or error code.
   1193 */
   1194int zynqmp_pm_aes_engine(const u64 address, u32 *out)
   1195{
   1196	u32 ret_payload[PAYLOAD_ARG_CNT];
   1197	int ret;
   1198
   1199	if (!out)
   1200		return -EINVAL;
   1201
   1202	ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, upper_32_bits(address),
   1203				  lower_32_bits(address),
   1204				  0, 0, ret_payload);
   1205	*out = ret_payload[1];
   1206
   1207	return ret;
   1208}
   1209EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);
   1210
   1211/**
   1212 * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash
   1213 * @address:	Address of the data/ Address of output buffer where
   1214 *		hash should be stored.
   1215 * @size:	Size of the data.
   1216 * @flags:
   1217 *	BIT(0) - for initializing csudma driver and SHA3(Here address
   1218 *		 and size inputs can be NULL).
   1219 *	BIT(1) - to call Sha3_Update API which can be called multiple
   1220 *		 times when data is not contiguous.
   1221 *	BIT(2) - to get final hash of the whole updated data.
   1222 *		 Hash will be overwritten at provided address with
   1223 *		 48 bytes.
   1224 *
   1225 * Return:	Returns status, either success or error code.
   1226 */
   1227int zynqmp_pm_sha_hash(const u64 address, const u32 size, const u32 flags)
   1228{
   1229	u32 lower_addr = lower_32_bits(address);
   1230	u32 upper_addr = upper_32_bits(address);
   1231
   1232	return zynqmp_pm_invoke_fn(PM_SECURE_SHA, upper_addr, lower_addr,
   1233				   size, flags, NULL);
   1234}
   1235EXPORT_SYMBOL_GPL(zynqmp_pm_sha_hash);
   1236
   1237/**
   1238 * zynqmp_pm_register_notifier() - PM API for register a subsystem
   1239 *                                to be notified about specific
   1240 *                                event/error.
   1241 * @node:	Node ID to which the event is related.
   1242 * @event:	Event Mask of Error events for which wants to get notified.
   1243 * @wake:	Wake subsystem upon capturing the event if value 1
   1244 * @enable:	Enable the registration for value 1, disable for value 0
   1245 *
   1246 * This function is used to register/un-register for particular node-event
   1247 * combination in firmware.
   1248 *
   1249 * Return: Returns status, either success or error+reason
   1250 */
   1251
   1252int zynqmp_pm_register_notifier(const u32 node, const u32 event,
   1253				const u32 wake, const u32 enable)
   1254{
   1255	return zynqmp_pm_invoke_fn(PM_REGISTER_NOTIFIER, node, event,
   1256				   wake, enable, NULL);
   1257}
   1258EXPORT_SYMBOL_GPL(zynqmp_pm_register_notifier);
   1259
   1260/**
   1261 * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart
   1262 * @type:	Shutdown or restart? 0 for shutdown, 1 for restart
   1263 * @subtype:	Specifies which system should be restarted or shut down
   1264 *
   1265 * Return:	Returns status, either success or error+reason
   1266 */
   1267int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype)
   1268{
   1269	return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype,
   1270				   0, 0, NULL);
   1271}
   1272
   1273/**
   1274 * zynqmp_pm_set_feature_config - PM call to request IOCTL for feature config
   1275 * @id:         The config ID of the feature to be configured
   1276 * @value:      The config value of the feature to be configured
   1277 *
   1278 * Return:      Returns 0 on success or error value on failure.
   1279 */
   1280int zynqmp_pm_set_feature_config(enum pm_feature_config_id id, u32 value)
   1281{
   1282	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_FEATURE_CONFIG,
   1283				   id, value, NULL);
   1284}
   1285
   1286/**
   1287 * zynqmp_pm_get_feature_config - PM call to get value of configured feature
   1288 * @id:         The config id of the feature to be queried
   1289 * @payload:    Returned value array
   1290 *
   1291 * Return:      Returns 0 on success or error value on failure.
   1292 */
   1293int zynqmp_pm_get_feature_config(enum pm_feature_config_id id,
   1294				 u32 *payload)
   1295{
   1296	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_FEATURE_CONFIG,
   1297				   id, 0, payload);
   1298}
   1299
   1300/**
   1301 * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope
   1302 * @subtype:	Shutdown subtype
   1303 * @name:	Matching string for scope argument
   1304 *
   1305 * This struct encapsulates mapping between shutdown scope ID and string.
   1306 */
   1307struct zynqmp_pm_shutdown_scope {
   1308	const enum zynqmp_pm_shutdown_subtype subtype;
   1309	const char *name;
   1310};
   1311
   1312static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = {
   1313	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = {
   1314		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM,
   1315		.name = "subsystem",
   1316	},
   1317	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = {
   1318		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY,
   1319		.name = "ps_only",
   1320	},
   1321	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = {
   1322		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM,
   1323		.name = "system",
   1324	},
   1325};
   1326
   1327static struct zynqmp_pm_shutdown_scope *selected_scope =
   1328		&shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM];
   1329
   1330/**
   1331 * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid
   1332 * @scope_string:	Shutdown scope string
   1333 *
   1334 * Return:		Return pointer to matching shutdown scope struct from
   1335 *			array of available options in system if string is valid,
   1336 *			otherwise returns NULL.
   1337 */
   1338static struct zynqmp_pm_shutdown_scope*
   1339		zynqmp_pm_is_shutdown_scope_valid(const char *scope_string)
   1340{
   1341	int count;
   1342
   1343	for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++)
   1344		if (sysfs_streq(scope_string, shutdown_scopes[count].name))
   1345			return &shutdown_scopes[count];
   1346
   1347	return NULL;
   1348}
   1349
   1350static ssize_t shutdown_scope_show(struct device *device,
   1351				   struct device_attribute *attr,
   1352				   char *buf)
   1353{
   1354	int i;
   1355
   1356	for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) {
   1357		if (&shutdown_scopes[i] == selected_scope) {
   1358			strcat(buf, "[");
   1359			strcat(buf, shutdown_scopes[i].name);
   1360			strcat(buf, "]");
   1361		} else {
   1362			strcat(buf, shutdown_scopes[i].name);
   1363		}
   1364		strcat(buf, " ");
   1365	}
   1366	strcat(buf, "\n");
   1367
   1368	return strlen(buf);
   1369}
   1370
   1371static ssize_t shutdown_scope_store(struct device *device,
   1372				    struct device_attribute *attr,
   1373				    const char *buf, size_t count)
   1374{
   1375	int ret;
   1376	struct zynqmp_pm_shutdown_scope *scope;
   1377
   1378	scope = zynqmp_pm_is_shutdown_scope_valid(buf);
   1379	if (!scope)
   1380		return -EINVAL;
   1381
   1382	ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY,
   1383					scope->subtype);
   1384	if (ret) {
   1385		pr_err("unable to set shutdown scope %s\n", buf);
   1386		return ret;
   1387	}
   1388
   1389	selected_scope = scope;
   1390
   1391	return count;
   1392}
   1393
   1394static DEVICE_ATTR_RW(shutdown_scope);
   1395
   1396static ssize_t health_status_store(struct device *device,
   1397				   struct device_attribute *attr,
   1398				   const char *buf, size_t count)
   1399{
   1400	int ret;
   1401	unsigned int value;
   1402
   1403	ret = kstrtouint(buf, 10, &value);
   1404	if (ret)
   1405		return ret;
   1406
   1407	ret = zynqmp_pm_set_boot_health_status(value);
   1408	if (ret) {
   1409		dev_err(device, "unable to set healthy bit value to %u\n",
   1410			value);
   1411		return ret;
   1412	}
   1413
   1414	return count;
   1415}
   1416
   1417static DEVICE_ATTR_WO(health_status);
   1418
   1419static ssize_t ggs_show(struct device *device,
   1420			struct device_attribute *attr,
   1421			char *buf,
   1422			u32 reg)
   1423{
   1424	int ret;
   1425	u32 ret_payload[PAYLOAD_ARG_CNT];
   1426
   1427	ret = zynqmp_pm_read_ggs(reg, ret_payload);
   1428	if (ret)
   1429		return ret;
   1430
   1431	return sprintf(buf, "0x%x\n", ret_payload[1]);
   1432}
   1433
   1434static ssize_t ggs_store(struct device *device,
   1435			 struct device_attribute *attr,
   1436			 const char *buf, size_t count,
   1437			 u32 reg)
   1438{
   1439	long value;
   1440	int ret;
   1441
   1442	if (reg >= GSS_NUM_REGS)
   1443		return -EINVAL;
   1444
   1445	ret = kstrtol(buf, 16, &value);
   1446	if (ret) {
   1447		count = -EFAULT;
   1448		goto err;
   1449	}
   1450
   1451	ret = zynqmp_pm_write_ggs(reg, value);
   1452	if (ret)
   1453		count = -EFAULT;
   1454err:
   1455	return count;
   1456}
   1457
   1458/* GGS register show functions */
   1459#define GGS0_SHOW(N)						\
   1460	ssize_t ggs##N##_show(struct device *device,		\
   1461			      struct device_attribute *attr,	\
   1462			      char *buf)			\
   1463	{							\
   1464		return ggs_show(device, attr, buf, N);		\
   1465	}
   1466
   1467static GGS0_SHOW(0);
   1468static GGS0_SHOW(1);
   1469static GGS0_SHOW(2);
   1470static GGS0_SHOW(3);
   1471
   1472/* GGS register store function */
   1473#define GGS0_STORE(N)						\
   1474	ssize_t ggs##N##_store(struct device *device,		\
   1475			       struct device_attribute *attr,	\
   1476			       const char *buf,			\
   1477			       size_t count)			\
   1478	{							\
   1479		return ggs_store(device, attr, buf, count, N);	\
   1480	}
   1481
   1482static GGS0_STORE(0);
   1483static GGS0_STORE(1);
   1484static GGS0_STORE(2);
   1485static GGS0_STORE(3);
   1486
   1487static ssize_t pggs_show(struct device *device,
   1488			 struct device_attribute *attr,
   1489			 char *buf,
   1490			 u32 reg)
   1491{
   1492	int ret;
   1493	u32 ret_payload[PAYLOAD_ARG_CNT];
   1494
   1495	ret = zynqmp_pm_read_pggs(reg, ret_payload);
   1496	if (ret)
   1497		return ret;
   1498
   1499	return sprintf(buf, "0x%x\n", ret_payload[1]);
   1500}
   1501
   1502static ssize_t pggs_store(struct device *device,
   1503			  struct device_attribute *attr,
   1504			  const char *buf, size_t count,
   1505			  u32 reg)
   1506{
   1507	long value;
   1508	int ret;
   1509
   1510	if (reg >= GSS_NUM_REGS)
   1511		return -EINVAL;
   1512
   1513	ret = kstrtol(buf, 16, &value);
   1514	if (ret) {
   1515		count = -EFAULT;
   1516		goto err;
   1517	}
   1518
   1519	ret = zynqmp_pm_write_pggs(reg, value);
   1520	if (ret)
   1521		count = -EFAULT;
   1522
   1523err:
   1524	return count;
   1525}
   1526
   1527#define PGGS0_SHOW(N)						\
   1528	ssize_t pggs##N##_show(struct device *device,		\
   1529			       struct device_attribute *attr,	\
   1530			       char *buf)			\
   1531	{							\
   1532		return pggs_show(device, attr, buf, N);		\
   1533	}
   1534
   1535#define PGGS0_STORE(N)						\
   1536	ssize_t pggs##N##_store(struct device *device,		\
   1537				struct device_attribute *attr,	\
   1538				const char *buf,		\
   1539				size_t count)			\
   1540	{							\
   1541		return pggs_store(device, attr, buf, count, N);	\
   1542	}
   1543
   1544/* PGGS register show functions */
   1545static PGGS0_SHOW(0);
   1546static PGGS0_SHOW(1);
   1547static PGGS0_SHOW(2);
   1548static PGGS0_SHOW(3);
   1549
   1550/* PGGS register store functions */
   1551static PGGS0_STORE(0);
   1552static PGGS0_STORE(1);
   1553static PGGS0_STORE(2);
   1554static PGGS0_STORE(3);
   1555
   1556/* GGS register attributes */
   1557static DEVICE_ATTR_RW(ggs0);
   1558static DEVICE_ATTR_RW(ggs1);
   1559static DEVICE_ATTR_RW(ggs2);
   1560static DEVICE_ATTR_RW(ggs3);
   1561
   1562/* PGGS register attributes */
   1563static DEVICE_ATTR_RW(pggs0);
   1564static DEVICE_ATTR_RW(pggs1);
   1565static DEVICE_ATTR_RW(pggs2);
   1566static DEVICE_ATTR_RW(pggs3);
   1567
   1568static ssize_t feature_config_id_show(struct device *device,
   1569				      struct device_attribute *attr,
   1570				      char *buf)
   1571{
   1572	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
   1573
   1574	return sysfs_emit(buf, "%d\n", devinfo->feature_conf_id);
   1575}
   1576
   1577static ssize_t feature_config_id_store(struct device *device,
   1578				       struct device_attribute *attr,
   1579				       const char *buf, size_t count)
   1580{
   1581	u32 config_id;
   1582	int ret;
   1583	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
   1584
   1585	if (!buf)
   1586		return -EINVAL;
   1587
   1588	ret = kstrtou32(buf, 10, &config_id);
   1589	if (ret)
   1590		return ret;
   1591
   1592	devinfo->feature_conf_id = config_id;
   1593
   1594	return count;
   1595}
   1596
   1597static DEVICE_ATTR_RW(feature_config_id);
   1598
   1599static ssize_t feature_config_value_show(struct device *device,
   1600					 struct device_attribute *attr,
   1601					 char *buf)
   1602{
   1603	int ret;
   1604	u32 ret_payload[PAYLOAD_ARG_CNT];
   1605	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
   1606
   1607	ret = zynqmp_pm_get_feature_config(devinfo->feature_conf_id,
   1608					   ret_payload);
   1609	if (ret)
   1610		return ret;
   1611
   1612	return sysfs_emit(buf, "%d\n", ret_payload[1]);
   1613}
   1614
   1615static ssize_t feature_config_value_store(struct device *device,
   1616					  struct device_attribute *attr,
   1617					  const char *buf, size_t count)
   1618{
   1619	u32 value;
   1620	int ret;
   1621	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
   1622
   1623	if (!buf)
   1624		return -EINVAL;
   1625
   1626	ret = kstrtou32(buf, 10, &value);
   1627	if (ret)
   1628		return ret;
   1629
   1630	ret = zynqmp_pm_set_feature_config(devinfo->feature_conf_id,
   1631					   value);
   1632	if (ret)
   1633		return ret;
   1634
   1635	return count;
   1636}
   1637
   1638static DEVICE_ATTR_RW(feature_config_value);
   1639
   1640static struct attribute *zynqmp_firmware_attrs[] = {
   1641	&dev_attr_ggs0.attr,
   1642	&dev_attr_ggs1.attr,
   1643	&dev_attr_ggs2.attr,
   1644	&dev_attr_ggs3.attr,
   1645	&dev_attr_pggs0.attr,
   1646	&dev_attr_pggs1.attr,
   1647	&dev_attr_pggs2.attr,
   1648	&dev_attr_pggs3.attr,
   1649	&dev_attr_shutdown_scope.attr,
   1650	&dev_attr_health_status.attr,
   1651	&dev_attr_feature_config_id.attr,
   1652	&dev_attr_feature_config_value.attr,
   1653	NULL,
   1654};
   1655
   1656ATTRIBUTE_GROUPS(zynqmp_firmware);
   1657
   1658static int zynqmp_firmware_probe(struct platform_device *pdev)
   1659{
   1660	struct device *dev = &pdev->dev;
   1661	struct device_node *np;
   1662	struct zynqmp_devinfo *devinfo;
   1663	int ret;
   1664
   1665	ret = get_set_conduit_method(dev->of_node);
   1666	if (ret)
   1667		return ret;
   1668
   1669	np = of_find_compatible_node(NULL, NULL, "xlnx,zynqmp");
   1670	if (!np) {
   1671		np = of_find_compatible_node(NULL, NULL, "xlnx,versal");
   1672		if (!np)
   1673			return 0;
   1674
   1675		feature_check_enabled = true;
   1676	}
   1677
   1678	if (!feature_check_enabled) {
   1679		ret = do_feature_check_call(PM_FEATURE_CHECK);
   1680		if (ret >= 0)
   1681			feature_check_enabled = true;
   1682	}
   1683
   1684	of_node_put(np);
   1685
   1686	devinfo = devm_kzalloc(dev, sizeof(*devinfo), GFP_KERNEL);
   1687	if (!devinfo)
   1688		return -ENOMEM;
   1689
   1690	devinfo->dev = dev;
   1691
   1692	platform_set_drvdata(pdev, devinfo);
   1693
   1694	/* Check PM API version number */
   1695	ret = zynqmp_pm_get_api_version(&pm_api_version);
   1696	if (ret)
   1697		return ret;
   1698
   1699	if (pm_api_version < ZYNQMP_PM_VERSION) {
   1700		panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n",
   1701		      __func__,
   1702		      ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR,
   1703		      pm_api_version >> 16, pm_api_version & 0xFFFF);
   1704	}
   1705
   1706	pr_info("%s Platform Management API v%d.%d\n", __func__,
   1707		pm_api_version >> 16, pm_api_version & 0xFFFF);
   1708
   1709	/* Check trustzone version number */
   1710	ret = zynqmp_pm_get_trustzone_version(&pm_tz_version);
   1711	if (ret)
   1712		panic("Legacy trustzone found without version support\n");
   1713
   1714	if (pm_tz_version < ZYNQMP_TZ_VERSION)
   1715		panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n",
   1716		      __func__,
   1717		      ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR,
   1718		      pm_tz_version >> 16, pm_tz_version & 0xFFFF);
   1719
   1720	pr_info("%s Trustzone version v%d.%d\n", __func__,
   1721		pm_tz_version >> 16, pm_tz_version & 0xFFFF);
   1722
   1723	ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
   1724			      ARRAY_SIZE(firmware_devs), NULL, 0, NULL);
   1725	if (ret) {
   1726		dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret);
   1727		return ret;
   1728	}
   1729
   1730	zynqmp_pm_api_debugfs_init();
   1731
   1732	np = of_find_compatible_node(NULL, NULL, "xlnx,versal");
   1733	if (np) {
   1734		em_dev = platform_device_register_data(&pdev->dev, "xlnx_event_manager",
   1735						       -1, NULL, 0);
   1736		if (IS_ERR(em_dev))
   1737			dev_err_probe(&pdev->dev, PTR_ERR(em_dev), "EM register fail with error\n");
   1738	}
   1739	of_node_put(np);
   1740
   1741	return of_platform_populate(dev->of_node, NULL, NULL, dev);
   1742}
   1743
   1744static int zynqmp_firmware_remove(struct platform_device *pdev)
   1745{
   1746	struct pm_api_feature_data *feature_data;
   1747	struct hlist_node *tmp;
   1748	int i;
   1749
   1750	mfd_remove_devices(&pdev->dev);
   1751	zynqmp_pm_api_debugfs_exit();
   1752
   1753	hash_for_each_safe(pm_api_features_map, i, tmp, feature_data, hentry) {
   1754		hash_del(&feature_data->hentry);
   1755		kfree(feature_data);
   1756	}
   1757
   1758	platform_device_unregister(em_dev);
   1759
   1760	return 0;
   1761}
   1762
   1763static const struct of_device_id zynqmp_firmware_of_match[] = {
   1764	{.compatible = "xlnx,zynqmp-firmware"},
   1765	{.compatible = "xlnx,versal-firmware"},
   1766	{},
   1767};
   1768MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match);
   1769
   1770static struct platform_driver zynqmp_firmware_driver = {
   1771	.driver = {
   1772		.name = "zynqmp_firmware",
   1773		.of_match_table = zynqmp_firmware_of_match,
   1774		.dev_groups = zynqmp_firmware_groups,
   1775	},
   1776	.probe = zynqmp_firmware_probe,
   1777	.remove = zynqmp_firmware_remove,
   1778};
   1779module_platform_driver(zynqmp_firmware_driver);