Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73820753 authored by Odelu Kukatla's avatar Odelu Kukatla Committed by Gerrit - the friendly Code Review server
Browse files

devfreq: spdm: Add snapshot of devfreq-spdm driver



This is a snapshot of the devfreq-spdm driver as of msm-3.18
'commit fa156811a90f ("ASoC: msm: enable group config for both
tx and rx").

Change-Id: I11fbcbfbca8b9bc30b9b43d08557fd5774e1444d
Signed-off-by: default avatarOdelu Kukatla <okukatla@codeaurora.org>
parent 098abe14
Loading
Loading
Loading
Loading
+84 −0
Original line number Diff line number Diff line
MSM SPDM bandwidth monitor device

devfreq-spdm is a device that represents a device that is monitored by the SPDM
hardware to measure the traffic status of configured master ports on the bus.


Required properties:
-compatible:			Must be "qcom,devfreq_spdm"
-clock-names:			Clocks used to measure current bus frequency.
				Expected names are "cci_clk"
-clocks:			References to named clocks
-qcom,spdm-client:		Client id of the port being monitored
-qcom,bw-upstep:		Initial up vote size in MB/s
-qcom,bw-dwnstep:		Initial down vote size in MB/s
-qcom,max-vote:			Vote ceiling in MB/s
-qcom,ports:			SPDM ports used by this device
-qcom,alpha-up:			SPDM filter up alpha value
-qcom,alpha-down:		SPDM filter down alpha value
-qcom,bucket-size:		SPDM filter bucket size
-qcom,pl-freqs:			The driver supports different filter values at
				three different performance levels.  This value
				defines the cut-over frequenices
-qcom,reject-rate:		Desired rejection rate used to calculate
				SPDM threshold
-qcom,response-time-us:	Desired response time used to calculate
				SPDM threshold
-qcom,cci-response-time-us:	Desired response time used to calculate
				SPDM threshold when CCI is under heavy load
-qcom,max-cci-freq:		CCI frequency at which cci_response_time_us
				is used
-qcom,up-step-multp:		used to increase rate of growth on up votes
-qcom,spdm-interval:		down-vote polling interval

Example:
devfreq_spdm_cpu {
	compatible = "qcom,devfreq_spdm";
	qcom,msm-bus,name = "devfreq_spdm";
	qcom,msm-bus,num-cases = <2>;
	qcom,msm-bus,num-paths = <1>;
	qcom,msm-bus,vectors-KBps =
			<1 512 0 0>,
			<1 512 0 0>;
	qcom,spdm-client = <0>;

	clock-names = "cci_clk";
	clocks = <&clock_cpu clk_cci_clk>;

	qcom,bw-upstep = <100>;
	qcom,bw-dwnstep = <100>;
	qcom,max-vote = <10000>;
	qcom,up-step-multp = <2>;
	qcom,spdm-interval = <100>;

	qcom,ports = <16>;
	qcom,alpha-up = <7>;
	qcom,alpha-down = <15>;
	qcom,bucket-size = <8>;

	/*max pl1 freq, max pl2 freq*/
	qcom,pl-freqs = <149999999 150000000>;

	/* pl1 low, pl1 high, pl2 low, pl2 high, pl3 low, pl3 high */
	qcom,reject-rate = <5000 5000 5000 5000 5000 5000>;
	/* pl1 low, pl1 high, pl2 low, pl2 high, pl3 low, pl3 high */
	qcom,response-time-us = <220 220 2000 2000 900 900>;
	/* pl1 low, pl1 high, pl2 low, pl2 high, pl3 low, pl3 high */
	qcom,cci-response-time-us = <50 50 30 30 20 20>;
	qcom,max-cci-freq = <600000000>;
};

This device is always used with the SPDM governor which requires a device tree
entry to know what IRQ to respond to.

Required properties:
-compatible			Must be "qcom,gov_spdm_hyp"
-interrupt-names		SPDM irq to handle.  Name should be "spdm-irq"
-interrupts			The interrupt number the SPDM hw is assigned

Example:
devfreq_spdm_gov {
	compatible = "qcom,gov_spdm_hyp";
	interrupt-names = "spdm-irq";
	interrupts = <0 192 0>;
};
+27 −0
Original line number Diff line number Diff line
@@ -135,6 +135,15 @@ config DEVFREQ_GOV_QCOM_CACHE_HWMON
	  it can conflict with existing profiling tools. This governor is
	  unlikely to be useful for other devices.

config DEVFREQ_GOV_SPDM_HYP
	bool "QTI SPDM Hypervisor Governor"
	depends on ARCH_QCOM
	help
	  Hypervisor based governor for CPU bandwidth voting
	  for QTI chipsets.
	  Sets the frequency using a "on-demand" algorithm.
	  This governor is unlikely to be useful for other devices.

config DEVFREQ_GOV_MEMLAT
	tristate "HW monitor based governor for device BW"
	depends on ARM_MEMLAT_MON
@@ -227,6 +236,24 @@ config QCOM_DEVFREQ_DEVBW
	  agnostic interface to so that some of the devfreq governors can be
	  shared across SoCs.

config SPDM_SCM
	bool "QTI SPDM SCM based call support"
	depends on DEVFREQ_SPDM
	help
	  SPDM driver support the dcvs algorithm logic being accessed via
	  scm or hvc calls. This adds the support for SPDM interaction to
          tz via SCM based call. If not selected then Hypervior interaction
          will be activated.

config DEVFREQ_SPDM
	bool "QTI SPDM based bandwidth voting"
	depends on ARCH_QCOM
	select DEVFREQ_GOV_SPDM_HYP
	help
	  This adds the support for SPDM based bandwidth voting on QTI chipsets.
	  This driver allows any SPDM based client to vote for bandwidth.
	  Used with the QTI SPDM Hypervisor Governor.

source "drivers/devfreq/event/Kconfig"

endif # PM_DEVFREQ
+2 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ obj-$(CONFIG_QCOMCCI_HWMON) += msmcci-hwmon.o
obj-$(CONFIG_QCOM_M4M_HWMON)		+= m4m-hwmon.o
obj-$(CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON)	+= governor_bw_hwmon.o
obj-$(CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON)	+= governor_cache_hwmon.o
obj-$(CONFIG_DEVFREQ_GOV_SPDM_HYP)	+= governor_spdm_bw_hyp.o
obj-$(CONFIG_DEVFREQ_GOV_MEMLAT)       += governor_memlat.o

# DEVFREQ Drivers
@@ -23,6 +24,7 @@ obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o
obj-$(CONFIG_ARM_TEGRA_DEVFREQ)		+= tegra-devfreq.o
obj-$(CONFIG_QCOM_DEVFREQ_DEVBW)		+= devfreq_devbw.o
obj-$(CONFIG_DEVFREQ_SIMPLE_DEV)	+= devfreq_simple_dev.o
obj-$(CONFIG_DEVFREQ_SPDM)		+= devfreq_spdm.o devfreq_spdm_debugfs.o

# DEVFREQ Event Drivers
obj-$(CONFIG_PM_DEVFREQ_EVENT)		+= event/
+444 −0
Original line number Diff line number Diff line
/*
 *Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved.
 *
 *This program is free software; you can redistribute it and/or modify
 *it under the terms of the GNU General Public License version 2 and
 *only version 2 as published by the Free Software Foundation.
 *
 *This program is distributed in the hope that it will be useful,
 *but WITHOUT ANY WARRANTY; without even the implied warranty of
 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *GNU General Public License for more details.
 */
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/devfreq.h>
#include <linux/init.h>
#include <linux/ipc_logging.h>
#include <linux/gfp.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/msm-bus.h>
#include <linux/of.h>
#include <linux/platform_device.h>

#include "governor.h"
#include "devfreq_spdm.h"

static void *spdm_ipc_log_ctxt;
#define DEVFREQ_SPDM_DEFAULT_WINDOW_MS 100
#define SPDM_IPC_LOG_PAGES	5

#define SPDM_IPC_LOG(x...)	do { \
	pr_debug(x); \
	if (spdm_ipc_log_ctxt) \
		ipc_log_string(spdm_ipc_log_ctxt, x); \
} while (0)

#define COPY_SIZE(x, y) ((x) <= (y) ? (x) : (y))

static int change_bw(struct device *dev, unsigned long *freq, u32 flags)
{
	struct spdm_data *data = 0;
	int i;
	int next_idx;
	int ret = 0;
	struct spdm_args desc = { { 0 } };
	int ext_status = 0;

	if (!dev || !freq)
		return -EINVAL;

	data = dev_get_drvdata(dev);
	if (!data)
		return -EINVAL;

	if (data->devfreq->previous_freq == *freq)
		goto update_thresholds;

	next_idx = data->cur_idx + 1;
	next_idx = next_idx % 2;

	for (i = 0; i < data->pdata->usecase[next_idx].num_paths; i++)
		data->pdata->usecase[next_idx].vectors[i].ab = (*freq) << 6;

	data->cur_idx = next_idx;
	ret = msm_bus_scale_client_update_request(data->bus_scale_client_id,
						  data->cur_idx);

update_thresholds:
	desc.arg[0] = SPDM_CMD_ENABLE;
	desc.arg[1] = data->spdm_client;
	desc.arg[2] = (clk_get_rate(data->cci_clk)) / 1000;
	ext_status = spdm_ext_call(&desc, 3);
	if (ext_status)
		pr_err("External command %u failed with error %u",
			(int)desc.arg[0], ext_status);
	return ret;
}

static int get_cur_bw(struct device *dev, unsigned long *freq)
{
	struct spdm_data *data = 0;

	if (!dev || !freq)
		return -EINVAL;

	data = dev_get_drvdata(dev);
	if (!data)
		return -EINVAL;

	*freq = data->pdata->usecase[data->cur_idx].vectors[0].ab >> 6;

	return 0;
}

static int get_dev_status(struct device *dev, struct devfreq_dev_status *status)
{
	struct spdm_data *data = 0;
	int ret;

	if (!dev || !status)
		return -EINVAL;

	data = dev_get_drvdata(dev);
	if (!data)
		return -EINVAL;

	/*
	 * determine if we want to go up or down based on the notification.
	 */
	if (data->action == SPDM_UP)
		status->busy_time = 255;
	else
		status->busy_time = 0;
	status->total_time = 255;
	ret = get_cur_bw(dev, &status->current_frequency);
	if (ret)
		return ret;

	return 0;

}

static int populate_config_data(struct spdm_data *data,
				struct platform_device *pdev)
{
	int ret = -EINVAL;
	struct device_node *node = pdev->dev.of_node;
	struct property *prop = 0;

	ret = of_property_read_u32(node, "qcom,max-vote",
				   &data->config_data.max_vote);
	if (ret)
		return ret;

	ret = of_property_read_u32(node, "qcom,bw-upstep",
				   &data->config_data.upstep);
	if (ret)
		return ret;

	ret = of_property_read_u32(node, "qcom,bw-dwnstep",
				   &data->config_data.downstep);
	if (ret)
		return ret;

	ret = of_property_read_u32(node, "qcom,alpha-up",
				   &data->config_data.aup);
	if (ret)
		return ret;

	ret = of_property_read_u32(node, "qcom,alpha-down",
				   &data->config_data.adown);
	if (ret)
		return ret;

	ret = of_property_read_u32(node, "qcom,bucket-size",
				   &data->config_data.bucket_size);
	if (ret)
		return ret;

	ret = of_property_read_u32_array(node, "qcom,pl-freqs",
					 data->config_data.pl_freqs,
					 SPDM_PL_COUNT - 1);
	if (ret)
		return ret;

	ret = of_property_read_u32_array(node, "qcom,reject-rate",
					 data->config_data.reject_rate,
					 SPDM_PL_COUNT * 2);
	if (ret)
		return ret;

	ret = of_property_read_u32_array(node, "qcom,response-time-us",
					 data->config_data.response_time_us,
					 SPDM_PL_COUNT * 2);
	if (ret)
		return ret;

	ret = of_property_read_u32_array(node, "qcom,cci-response-time-us",
					 data->config_data.cci_response_time_us,
					 SPDM_PL_COUNT * 2);
	if (ret)
		return ret;

	ret = of_property_read_u32(node, "qcom,max-cci-freq",
				   &data->config_data.max_cci_freq);
	if (ret)
		return ret;
	ret = of_property_read_u32(node, "qcom,up-step-multp",
				   &data->config_data.up_step_multp);
	if (ret)
		return ret;

	prop = of_find_property(node, "qcom,ports", 0);
	if (!prop)
		return -EINVAL;
	data->config_data.num_ports = prop->length / sizeof(u32);
	data->config_data.ports =
	    devm_kzalloc(&pdev->dev, prop->length, GFP_KERNEL);
	if (!data->config_data.ports)
		return -ENOMEM;
	ret = of_property_read_u32_array(node, "qcom,ports",
					 data->config_data.ports,
					 data->config_data.num_ports);
	if (ret) {
		devm_kfree(&pdev->dev, data->config_data.ports);
		data->config_data.ports = NULL;
		return ret;
	}

	return 0;
}

static int populate_spdm_data(struct spdm_data *data,
			      struct platform_device *pdev)
{
	int ret = -EINVAL;
	struct device_node *node = pdev->dev.of_node;

	ret = populate_config_data(data, pdev);
	if (ret)
		return ret;

	ret =
	    of_property_read_u32(node, "qcom,spdm-client", &data->spdm_client);
	if (ret)
		goto no_client;

	ret = of_property_read_u32(node, "qcom,spdm-interval", &data->window);
	if (ret)
		data->window = DEVFREQ_SPDM_DEFAULT_WINDOW_MS;

	data->pdata = msm_bus_cl_get_pdata(pdev);
	if (!data->pdata) {
		ret = -EINVAL;
		goto no_pdata;
	}

	return 0;

no_client:
no_pdata:
	devm_kfree(&pdev->dev, data->config_data.ports);
	data->config_data.ports = NULL;
	return ret;
}

#ifdef CONFIG_MSM_HVC
int __spdm_hyp_call(struct spdm_args *args, int num_args)
{
	struct hvc_desc desc = { { 0 } };
	int status;

	memcpy(desc.arg, args->arg,
		COPY_SIZE(sizeof(desc.arg), sizeof(args->arg)));
	SPDM_IPC_LOG("hvc call fn:0x%x, cmd:%llu, num_args:%d\n",
		HVC_FN_SIP(SPDM_HYP_FNID), desc.arg[0], num_args);

	status = hvc(HVC_FN_SIP(SPDM_HYP_FNID), &desc);

	memcpy(args->ret, desc.ret,
		COPY_SIZE(sizeof(args->ret), sizeof(desc.ret)));
	SPDM_IPC_LOG("hvc return fn:0x%x cmd:%llu Ret[0]:%llu Ret[1]:%llu\n",
			HVC_FN_SIP(SPDM_HYP_FNID), desc.arg[0],
			desc.ret[0], desc.ret[1]);
	return status;
}
#endif

int __spdm_scm_call(struct spdm_args *args, int num_args)
{
	int status = 0;

	SPDM_IPC_LOG("%s:svc_id:%d,cmd_id:%d,cmd:%llu,num_args:%d\n",
		__func__, SPDM_SCM_SVC_ID, SPDM_SCM_CMD_ID,
		args->arg[0], num_args);

	if (!is_scm_armv8()) {
		status = scm_call(SPDM_SCM_SVC_ID, SPDM_SCM_CMD_ID, args->arg,
				sizeof(args->arg), args->ret,
				sizeof(args->ret));
	} else {
		struct scm_desc desc = {0};
		/*
		 * Need to hard code this, this is a requirement from TZ syscall
		 * interface.
		 */
		desc.arginfo = SCM_ARGS(6);
		memcpy(desc.args, args->arg,
			COPY_SIZE(sizeof(desc.args), sizeof(args->arg)));

		status = scm_call2(SCM_SIP_FNID(SPDM_SCM_SVC_ID,
				SPDM_SCM_CMD_ID), &desc);

		memcpy(args->ret, desc.ret,
			COPY_SIZE(sizeof(args->ret), sizeof(desc.ret)));
	}
	SPDM_IPC_LOG("%s:svc_id:%d,cmd_id:%d,cmd:%llu,Ret[0]:%llu,Ret[1]:%llu\n"
		, __func__, SPDM_SCM_SVC_ID, SPDM_SCM_CMD_ID, args->arg[0],
		args->ret[0], args->ret[1]);
	return status;
}

static int probe(struct platform_device *pdev)
{
	struct spdm_data *data = 0;
	int ret = -EINVAL;
	struct spdm_args desc = { { 0 } };
	int ext_status = 0;

	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	data->action = SPDM_DOWN;

	platform_set_drvdata(pdev, data);

	ret = populate_spdm_data(data, pdev);
	if (ret)
		goto bad_of;

	desc.arg[0] = SPDM_CMD_GET_VERSION;
	ext_status = spdm_ext_call(&desc, 1);
	if (ext_status) {
		pr_err("%s:External command %u failed with error %u\n",
			__func__, (int)desc.arg[0], ext_status);
		goto bad_of;
	}

	if (desc.ret[0] < SPDM_TZ_VERSION) {
		pr_err("%s: Version mismatch expected 0x%x got 0x%x", __func__,
			SPDM_TZ_VERSION, (int)desc.arg[0]);
		goto bad_of;
	}

	data->bus_scale_client_id = msm_bus_scale_register_client(data->pdata);
	if (!data->bus_scale_client_id) {
		ret = -EINVAL;
		goto no_bus_scaling;
	}

	data->cci_clk = clk_get(&pdev->dev, "cci_clk");
	if (IS_ERR(data->cci_clk)) {
		ret = PTR_ERR(data->cci_clk);
		goto no_clock;
	}

	data->profile =
	    devm_kzalloc(&pdev->dev, sizeof(*(data->profile)), GFP_KERNEL);
	if (!data->profile) {
		ret = -ENOMEM;
		goto no_profile;
	}
	data->profile->target = change_bw;
	data->profile->get_dev_status = get_dev_status;
	data->profile->get_cur_freq = get_cur_bw;
	data->profile->polling_ms = data->window;

	data->devfreq =
	    devfreq_add_device(&pdev->dev, data->profile, "spdm_bw_hyp", data);
	if (IS_ERR(data->devfreq)) {
		ret = PTR_ERR(data->devfreq);
		goto no_spdm_device;
	}

	spdm_init_debugfs(&pdev->dev);
	spdm_ipc_log_ctxt = ipc_log_context_create(SPDM_IPC_LOG_PAGES,
							"devfreq_spdm", 0);

	if (IS_ERR_OR_NULL(spdm_ipc_log_ctxt)) {
		pr_err("%s: Failed to create IPC log context\n", __func__);
		spdm_ipc_log_ctxt = NULL;
	}


	return 0;

no_spdm_device:
	devm_kfree(&pdev->dev, data->profile);
no_profile:
no_clock:
	msm_bus_scale_unregister_client(data->bus_scale_client_id);
no_bus_scaling:
	devm_kfree(&pdev->dev, data->config_data.ports);
bad_of:
	devm_kfree(&pdev->dev, data);
	platform_set_drvdata(pdev, NULL);
	return ret;
}

static int remove(struct platform_device *pdev)
{
	struct spdm_data *data = 0;

	data = platform_get_drvdata(pdev);

	spdm_remove_debugfs(data);

	if (data->devfreq)
		devfreq_remove_device(data->devfreq);

	if (data->profile)
		devm_kfree(&pdev->dev, data->profile);

	if (data->bus_scale_client_id)
		msm_bus_scale_unregister_client(data->bus_scale_client_id);

	if (data->config_data.ports)
		devm_kfree(&pdev->dev, data->config_data.ports);

	devm_kfree(&pdev->dev, data);
	platform_set_drvdata(pdev, NULL);

	if (spdm_ipc_log_ctxt)
		ipc_log_context_destroy(spdm_ipc_log_ctxt);

	return 0;
}

static const struct of_device_id devfreq_spdm_match[] = {
	{.compatible = "qcom,devfreq_spdm"},
	{}
};

static struct platform_driver devfreq_spdm_drvr = {
	.driver = {
		   .name = "devfreq_spdm",
		   .owner = THIS_MODULE,
		   .of_match_table = devfreq_spdm_match,
		   },
	.probe = probe,
	.remove = remove,
};

static int __init devfreq_spdm_init(void)
{
	return platform_driver_register(&devfreq_spdm_drvr);
}

module_init(devfreq_spdm_init);

MODULE_LICENSE("GPL v2");
+131 −0
Original line number Diff line number Diff line
/*
 *Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved.
 *
 *This program is free software; you can redistribute it and/or modify
 *it under the terms of the GNU General Public License version 2 and
 *only version 2 as published by the Free Software Foundation.
 *
 *This program is distributed in the hope that it will be useful,
 *but WITHOUT ANY WARRANTY; without even the implied warranty of
 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *GNU General Public License for more details.
 */

#ifndef DEVFREQ_SPDM_H
#define DEVFREQ_SPDM_H

#include <linux/list.h>
#ifdef CONFIG_MSM_HVC
#include <soc/qcom/hvc.h>
#endif
#include <soc/qcom/scm.h>

enum pl_levels { SPDM_PL1, SPDM_PL2, SPDM_PL3, SPDM_PL_COUNT };
enum actions { SPDM_UP, SPDM_DOWN };
enum spdm_client { SPDM_CLIENT_CPU, SPDM_CLIENT_GPU, SPDM_CLIENT_COUNT };

struct spdm_config_data {
	/* in MB/s */
	u32 upstep;
	u32 downstep;
	u32 up_step_multp;

	u32 num_ports;
	u32 *ports;
	u32 aup;
	u32 adown;
	u32 bucket_size;

	/*
	 * If We define n PL levels we need n-1 frequencies to tell
	 * where to change from one pl to another
	 */
	/* hz */
	u32 pl_freqs[SPDM_PL_COUNT - 1];
	/*
	 * We have a low threshold and a high threhold for each pl to support
	 * the two port solution so we need twice as many entries as
	 * performance levels
	 */
	/* in 100th's of a percent */
	u32 reject_rate[SPDM_PL_COUNT * 2];
	u32 response_time_us[SPDM_PL_COUNT * 2];
	u32 cci_response_time_us[SPDM_PL_COUNT * 2];
	/* hz */
	u32 max_cci_freq;
	/* in MB/s */
	u32 max_vote;

};

struct spdm_data {
	/* bus scaling data */
	int cur_idx;
	struct msm_bus_scale_pdata *pdata;
	u32 bus_scale_client_id;
	/* in mb/s */
	u32 new_bw;

	/* devfreq data */
	struct devfreq *devfreq;
	struct devfreq_dev_profile *profile;
	unsigned long action;
	int window;
	struct clk *cci_clk;

	/* spdm hw/gov data */
	struct spdm_config_data config_data;

	enum spdm_client spdm_client;
	/* list used by governor to keep track of spdm devices */
	struct list_head list;

	struct dentry *debugfs_dir;

	bool enabled;
};

extern void spdm_init_debugfs(struct device *dev);
extern void spdm_remove_debugfs(struct spdm_data *data);

#define SPDM_HYP_FNID 5
#define SPDM_SCM_SVC_ID 0x9
#define SPDM_SCM_CMD_ID 0x4
#define SPDM_TZ_VERSION 0x20000 /* TZ SPDM driver version */
/* SPDM CMD ID's for hypervisor/SCM */
#define SPDM_CMD_GET_VERSION 0
#define SPDM_CMD_GET_BW_ALL 1
#define SPDM_CMD_GET_BW_SPECIFIC 2
#define SPDM_CMD_ENABLE 3
#define SPDM_CMD_DISABLE 4
#define SPDM_CMD_CFG_PORTS 5
#define SPDM_CMD_CFG_FLTR 6
#define SPDM_CMD_CFG_PL 7
#define SPDM_CMD_CFG_REJRATE_LOW 8
#define SPDM_CMD_CFG_REJRATE_MED 9
#define SPDM_CMD_CFG_REJRATE_HIGH 10
#define SPDM_CMD_CFG_RESPTIME_LOW 11
#define SPDM_CMD_CFG_RESPTIME_MED 12
#define SPDM_CMD_CFG_RESPTIME_HIGH 13
#define SPDM_CMD_CFG_CCIRESPTIME_LOW 14
#define SPDM_CMD_CFG_CCIRESPTIME_MED 15
#define SPDM_CMD_CFG_CCIRESPTIME_HIGH 16
#define SPDM_CMD_CFG_MAXCCI 17
#define SPDM_CMD_CFG_VOTES 18

#define SPDM_MAX_ARGS 6
#define SPDM_MAX_RETS 3

struct spdm_args {
	u64 arg[SPDM_MAX_ARGS];
	u64 ret[SPDM_MAX_RETS];
};

#ifdef CONFIG_SPDM_SCM
extern int __spdm_scm_call(struct spdm_args *args, int num_args);
#define spdm_ext_call __spdm_scm_call
#else
extern int __spdm_hyp_call(struct spdm_args *args, int num_args);
#define spdm_ext_call __spdm_hyp_call
#endif
#endif
Loading