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

Commit 348d7803 authored by Elliot Berman's avatar Elliot Berman
Browse files

firmware: qcom_scm: Add calls for pfk_ice



Add variant of qcom_scm_call which disables EBUSY retry mechanism.
Add SCM calls for pfk_ice to initialize keys.

Change-Id: Ib785cd0bf4df5b81d73bad96c2a6f56ae961b55d
Signed-off-by: default avatarElliot Berman <eberman@codeaurora.org>
parent 5317ce31
Loading
Loading
Loading
Loading
+71 −2
Original line number Diff line number Diff line
@@ -21,6 +21,9 @@
#define MAX_QCOM_SCM_ARGS 10
#define MAX_QCOM_SCM_RETS 3

#define QCOM_SCM_ATOMIC		BIT(0)
#define QCOM_SCM_NORETRY	BIT(1)

enum qcom_scm_arg_types {
	QCOM_SCM_VAL,
	QCOM_SCM_RO,
@@ -181,11 +184,12 @@ static void __qcom_scm_call_do_quirk(const struct arm_smccc_args *smc,
}

static int qcom_scm_call_smccc(struct device *dev,
				  struct qcom_scm_desc *desc, bool atomic)
				  struct qcom_scm_desc *desc, const u32 options)
{
	int arglen = desc->arginfo & 0xf;
	int i, ret;
	size_t alloc_len;
	const bool atomic = options & QCOM_SCM_ATOMIC;
	gfp_t flag = atomic ? GFP_ATOMIC : GFP_NOIO;
	u32 smccc_call_type = atomic ? ARM_SMCCC_FAST_CALL : ARM_SMCCC_STD_CALL;
	u32 qcom_smccc_convention =
@@ -262,7 +266,8 @@ static int qcom_scm_call_smccc(struct device *dev,
			mutex_unlock(&qcom_scm_lock);

			if (res.a0 == QCOM_SCM_V2_EBUSY) {
				if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY)
				if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY ||
				    (options & QCOM_SCM_NORETRY))
					break;
				msleep(QCOM_SCM_EBUSY_WAIT_MS);
			}
@@ -543,6 +548,31 @@ static int qcom_scm_call_atomic(struct device *dev, struct qcom_scm_desc *desc)
	}
}

/**
 * qcom_scm_call_noretry() - Invoke a syscall in the secure world
 * @dev:	device
 * @svc_id:	service identifier
 * @cmd_id:	command identifier
 * @desc:	Descriptor structure containing arguments and return values
 *
 * Sends a command to the SCM and waits for the command to finish processing.
 * This should *only* be called in pre-emptible context.
 */
static int qcom_scm_call_noretry(struct device *dev, struct qcom_scm_desc *desc)
{
	might_sleep();
	switch (__get_convention()) {
	case SMC_CONVENTION_ARM_32:
	case SMC_CONVENTION_ARM_64:
		return qcom_scm_call_smccc(dev, desc, QCOM_SCM_NORETRY);
	case SMC_CONVENTION_LEGACY:
		return qcom_scm_call_legacy(dev, desc);
	default:
		pr_err("Unknown current SCM calling convention.\n");
		return -EINVAL;
	}
}

/**
 * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
 * @entry: Entry point function for the cpus
@@ -1360,6 +1390,45 @@ int __qcom_scm_dcvs_update_ca_v2(struct device *dev, int level, s64 total_time,
	return ret ? : desc.res[0];
}

int __qcom_scm_config_set_ice_key(struct device *dev, uint32_t index,
				  phys_addr_t paddr, size_t size,
				  uint32_t cipher, unsigned int data_unit,
				  unsigned int food)
{
	struct qcom_scm_desc desc = {
		.svc = QCOM_SCM_SVC_ES,
		.cmd = QCOM_SCM_ES_CONFIG_SET_ICE_KEY,
		.owner = ARM_SMCCC_OWNER_SIP
	};

	desc.args[0] = index;
	desc.args[1] = paddr;
	desc.args[2] = size;
	desc.args[3] = cipher;
	desc.args[4] = data_unit;
	desc.args[5] = food;
	desc.arginfo = QCOM_SCM_ARGS(6, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL,
				     QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_VAL);

	return qcom_scm_call_noretry(dev, &desc);
}

int __qcom_scm_clear_ice_key(struct device *dev, uint32_t index,
			     unsigned int food)
{
	struct qcom_scm_desc desc = {
		.svc = QCOM_SCM_SVC_ES,
		.cmd = QCOM_SCM_ES_CLEAR_ICE_KEY,
		.owner = ARM_SMCCC_OWNER_SIP
	};

	desc.args[0] = index;
	desc.args[1] = food;
	desc.arginfo = QCOM_SCM_ARGS(2);

	return qcom_scm_call_noretry(dev, &desc);
}

int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
			u32 req_cnt, u32 *resp)
{
+15 −0
Original line number Diff line number Diff line
@@ -603,6 +603,21 @@ int qcom_scm_dcvs_update_ca_v2(int level, s64 total_time, s64 busy_time,
}
EXPORT_SYMBOL(qcom_scm_dcvs_update_ca_v2);

int qcom_scm_config_set_ice_key(uint32_t index, phys_addr_t paddr, size_t size,
				uint32_t cipher, unsigned int data_unit,
				unsigned int food)
{
	return __qcom_scm_config_set_ice_key(__scm->dev, index, paddr, size,
					     cipher, data_unit, food);
}
EXPORT_SYMBOL(qcom_scm_config_set_ice_key);

int qcom_scm_clear_ice_key(uint32_t index,  unsigned int food)
{
	return __qcom_scm_clear_ice_key(__scm->dev, index, food);
}
EXPORT_SYMBOL(qcom_scm_clear_ice_key);

/**
 * qcom_scm_hdcp_available() - Check if secure environment supports HDCP.
 *
+11 −0
Original line number Diff line number Diff line
@@ -136,6 +136,17 @@ extern int __qcom_scm_dcvs_update_ca_v2(struct device *dev, int level,
					s64 total_time, s64 busy_time,
					int context_count);

#define QCOM_SCM_SVC_ES				0x10
#define QCOM_SCM_ES_CONFIG_SET_ICE_KEY		0x05
#define QCOM_SCM_ES_CLEAR_ICE_KEY		0x06
extern int __qcom_scm_config_set_ice_key(struct device *dev, uint32_t index,
					 phys_addr_t paddr, size_t size,
					 uint32_t cipher,
					 unsigned int data_unit,
					 unsigned int food);
extern int __qcom_scm_clear_ice_key(struct device *dev, uint32_t index,
				    unsigned int food);

#define QCOM_SCM_SVC_HDCP			0x11
#define QCOM_SCM_HDCP_INVOKE			0x01
extern int __qcom_scm_hdcp_req(struct device *dev,
+10 −0
Original line number Diff line number Diff line
@@ -82,6 +82,11 @@ extern int qcom_scm_dcvs_update(int level, s64 total_time, s64 busy_time);
extern int qcom_scm_dcvs_update_v2(int level, s64 total_time, s64 busy_time);
extern int qcom_scm_dcvs_update_ca_v2(int level, s64 total_time, s64 busy_time,
				      int context_count);
extern int qcom_scm_config_set_ice_key(uint32_t index, phys_addr_t paddr,
				       size_t size, uint32_t cipher,
				       unsigned int data_unit,
				       unsigned int food);
extern int qcom_scm_clear_ice_key(uint32_t index, unsigned int food);
extern bool qcom_scm_hdcp_available(void);
extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
			     u32 *resp);
@@ -165,6 +170,11 @@ static inline int qcom_scm_dcvs_update_v2(int level, s64 total_time,
		s64 busy_time) { return -ENODEV; }
static inline int qcom_scm_dcvs_update_ca_v2(int level, s64 total_time,
		s64 busy_time, int context_count) { return -ENODEV; }
static inline int qcom_scm_config_set_ice_key(uint32_t index, phys_addr_t paddr,
		size_t size, uint32_t cipher, unsigned int data_unit,
		unsigned int food) { return -ENODEV; }
static inline int qcom_scm_clear_ice_key(uint32_t index, unsigned int food)
		{ return -ENODEV; }
static inline bool qcom_scm_hdcp_available(void) { return false; }
static inline int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
				    u32 *resp) { return -ENODEV; }