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

Commit 5cdf3db9 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: spss_utils: add spss events support"

parents abd758ba d19250c9
Loading
Loading
Loading
Loading
+112 −8
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
 */

/*
@@ -33,6 +33,7 @@
#include <linux/notifier.h>
#include <linux/sizes.h>    /* SZ_4K */
#include <linux/uaccess.h>  /* copy_from_user() */
#include <linux/completion.h>	/* wait_for_completion_timeout() */

#include <soc/qcom/subsystem_notif.h>
#include <soc/qcom/subsystem_restart.h>
@@ -91,6 +92,9 @@ static phys_addr_t cmac_mem_addr;
#define SPU_EMULATUION (BIT(0) | BIT(1))
#define SPU_PRESENT_IN_EMULATION BIT(2)

/* Events notification */
struct completion spss_events[SPSS_NUM_EVENTS];

/**
 * struct device state
 */
@@ -376,15 +380,84 @@ static int spss_create_sysfs(struct device *dev)
/*==========================================================================*/
/*  IOCTL */
/*==========================================================================*/
static int spss_wait_for_event(struct spss_ioc_wait_for_event *req)
{
	int ret;
	uint32_t event_id;
	uint32_t timeout_sec;
	long timeleft = 1;

	event_id = req->event_id;
	timeout_sec = req->timeout_sec;

	if (event_id >= SPSS_NUM_EVENTS) {
		pr_err("event_id [%d] invalid\n", event_id);
		return -EINVAL;
	}

	pr_debug("wait for event [%d], timeout_sec [%d]\n",
		event_id, timeout_sec);

	if (timeout_sec) {
		unsigned long jiffies = 0;

		jiffies = msecs_to_jiffies(timeout_sec*1000);
		timeleft = wait_for_completion_interruptible_timeout(
			&spss_events[event_id], jiffies);
		ret = timeleft;
	} else {
		ret = wait_for_completion_interruptible(
			&spss_events[event_id]);
	}

	if (timeleft == 0) {
		pr_err("wait for event [%d] timeout [%d] sec expired\n",
			event_id, timeout_sec);
		req->status = EVENT_STATUS_TIMEOUT;
	} else if (ret < 0) {
		pr_err("wait for event [%d] interrupted. ret [%d]\n",
			event_id, ret);
		req->status = EVENT_STATUS_ABORTED;
	} else {
		pr_debug("wait for event [%d] completed.\n", event_id);
		req->status = EVENT_STATUS_SIGNALED;
	}

	return 0;
}

static int spss_signal_event(struct spss_ioc_signal_event *req)
{
	uint32_t event_id;

	event_id = req->event_id;

	if (event_id >= SPSS_NUM_EVENTS) {
		pr_err("event_id [%d] invalid\n", event_id);
		return -EINVAL;
	}

	pr_debug("signal event [%d]\n", event_id);
	complete_all(&spss_events[event_id]);
	req->status = EVENT_STATUS_SIGNALED;

	return 0;
}

static long spss_utils_ioctl(struct file *file,
	unsigned int cmd, unsigned long arg)
{
	int ret;
	void *buf = (void *) arg;
	unsigned char data[64] = {0};
	size_t size = 0;
	u32 i = 0;
	/* Saved cmacs of spu firmware and UEFI loaded spu apps */
	u32 fw_and_apps_cmacs[FW_AND_APPS_CMAC_SIZE];
	struct spss_ioc_wait_for_event *wait_req =
		(struct spss_ioc_wait_for_event *) data;
	struct spss_ioc_signal_event *signal_req =
		(struct spss_ioc_signal_event *) data;

	if (buf == NULL) {
		pr_err("invalid ioctl arg\n");
@@ -429,7 +502,7 @@ static long spss_utils_ioctl(struct file *file,

		/*
		 * SPSS is loaded now by UEFI,
		 * so IAR callback is not being called on powerup by PIL.
		 * so IAR callback is not being called on power-up by PIL.
		 * therefore read the spu pbl fw cmac and apps cmac from ioctl.
		 * The callback shall be called on spss SSR.
		 */
@@ -439,6 +512,30 @@ static long spss_utils_ioctl(struct file *file,
		spss_get_saved_uefi_apps_cmac();
		break;

	case SPSS_IOC_WAIT_FOR_EVENT:
		/* check input params */
		if (size != sizeof(struct spss_ioc_wait_for_event)) {
			pr_err("cmd [0x%x] invalid size [0x%x]\n", cmd, size);
			return -EINVAL;
		}
		ret = spss_wait_for_event(wait_req);
		if (ret < 0)
			return ret;
		copy_to_user((void __user *)arg, data, size);
		break;

	case SPSS_IOC_SIGNAL_EVENT:
		/* check input params */
		if (size != sizeof(struct spss_ioc_signal_event)) {
			pr_err("cmd [0x%x] invalid size [0x%x]\n", cmd, size);
			return -EINVAL;
		}
		ret = spss_signal_event(signal_req);
		if (ret < 0)
			return ret;
		copy_to_user((void __user *)arg, data, size);
		break;

	default:
		pr_err("invalid ioctl cmd [0x%x]\n", cmd);
		return -EINVAL;
@@ -772,7 +869,7 @@ static int spss_parse_dt(struct device_node *node)

	iar_state = val1;

	pr_info("iar_state [%d]\n", iar_state);
	pr_debug("iar_state [%d]\n", iar_state);

	return 0;
}
@@ -909,13 +1006,11 @@ static int spss_set_saved_uefi_apps_cmac(void)
	return 0;
}

static int spss_utils_iar_callback(struct notifier_block *nb,
static int spss_utils_pil_callback(struct notifier_block *nb,
				  unsigned long code,
				  void *data)
{
	/* do nothing if IAR is not active */
	if (!is_iar_active)
		return NOTIFY_OK;
	int i;

	switch (code) {
	case SUBSYS_BEFORE_SHUTDOWN:
@@ -926,11 +1021,16 @@ static int spss_utils_iar_callback(struct notifier_block *nb,
		break;
	case SUBSYS_BEFORE_POWERUP:
		pr_debug("[SUBSYS_BEFORE_POWERUP] event.\n");
		for (i = 0 ; i < SPSS_NUM_EVENTS; i++)
			reinit_completion(&spss_events[i]);
		break;
	case SUBSYS_AFTER_POWERUP:
		pr_debug("[SUBSYS_AFTER_POWERUP] event.\n");
		break;
	case SUBSYS_BEFORE_AUTH_AND_RESET:
		/* do nothing if IAR is not active */
		if (!is_iar_active)
			return NOTIFY_OK;
		pr_debug("[SUBSYS_BEFORE_AUTH_AND_RESET] event.\n");
		/* Called on SSR as spss firmware is loaded by UEFI */
		spss_set_fw_cmac(cmac_buf, sizeof(cmac_buf));
@@ -951,6 +1051,7 @@ static int spss_utils_iar_callback(struct notifier_block *nb,
static int spss_probe(struct platform_device *pdev)
{
	int ret = 0;
	int i;
	struct device_node *np = NULL;
	struct device *dev = NULL;

@@ -1023,7 +1124,7 @@ static int spss_probe(struct platform_device *pdev)
	if (!iar_nb)
		return -ENOMEM;

	iar_nb->notifier_call = spss_utils_iar_callback;
	iar_nb->notifier_call = spss_utils_pil_callback;

	iar_notif_handle = subsys_notif_register_notifier("spss", iar_nb);
	if (IS_ERR_OR_NULL(iar_notif_handle)) {
@@ -1031,6 +1132,9 @@ static int spss_probe(struct platform_device *pdev)
		kfree(iar_nb);
	}

	for (i = 0 ; i < SPSS_NUM_EVENTS; i++)
		init_completion(&spss_events[i]);

	return 0;
}

+28 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
 * Copyright (c) 2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
 */

#ifndef _UAPI_SPSS_UTILS_H_
@@ -17,6 +17,8 @@
 */

#define SPSS_IOC_MAGIC  'S'

/* ---------- set fw cmac --------------------------------- */
#define NUM_SPU_UEFI_APPS   3

struct spss_ioc_set_fw_cmac {
@@ -27,4 +29,29 @@ struct spss_ioc_set_fw_cmac {
#define SPSS_IOC_SET_FW_CMAC \
	_IOWR(SPSS_IOC_MAGIC, 1, struct spss_ioc_set_fw_cmac)

/* ---------- wait for event ------------------------------ */
#define SPSS_NUM_EVENTS   8

#define EVENT_STATUS_SIGNALED   0xAAAA
#define EVENT_STATUS_TIMEOUT    0xEEE1
#define EVENT_STATUS_ABORTED    0xEEE2

struct spss_ioc_wait_for_event {
	uint32_t event_id;      /* input */
	uint32_t timeout_sec;   /* input */
	uint32_t status;        /* output */
} __packed;

#define SPSS_IOC_WAIT_FOR_EVENT \
	_IOWR(SPSS_IOC_MAGIC, 2, struct spss_ioc_wait_for_event)

/* ---------- signal event ------------------------------ */
struct spss_ioc_signal_event {
	uint32_t event_id;      /* input */
	uint32_t status;        /* output */
} __packed;

#define SPSS_IOC_SIGNAL_EVENT \
	_IOWR(SPSS_IOC_MAGIC, 3, struct spss_ioc_signal_event)

#endif /* _UAPI_SPSS_UTILS_H_ */