slatecom: add rpmsg glink support for slatecom_interface

Add rpmsg support for slatecom interface driver to
send msm state transition commands to slate.

Add Opcodes to be received on slate-ctrl channel from hal.
Send TWM_ENTER, DEEP SLEEP ENTER & EXIT to slate.

Mot-CRs-fixed: (CR)
CVE-Fixed: CVE-2023-33085
CRs-Fixed: 3512209
Change-Id: Ic29b116da7b90e1a1d71a14b970a2a53b1b3c20f
Signed-off-by: Praveen koya <pkoya@codeaurora.org>
Signed-off-by: Ashutosh Verma <ashverma@motorola.com>
Reviewed-on: https://gerrit.mot.com/2762749
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Xiangpo Zhao <zhaoxp3@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
Praveen koya 2021-07-20 15:39:21 +05:30 • committed by Xiaojun Ji
commit 32ac22edb4
7 changed files with 345 additions and 1 deletions

View file

@ -1483,6 +1483,15 @@ config MSM_SLATECOM_INTERFACE
from hardware. Hardware will provide access to read
registers and read/write AHB memory in the device.
config MSM_SLATECOM_RPMSG
tristate "Provide support for slate GLINK channel"
depends on MSM_SLATECOM_INTERFACE
help
MSM_SLATECOM_RPMSG informs SLATECOM_INTERFACE driver if GLINK channel
has been opened by remote processor. It doesn't maintain state machine
and is probed when Slate opens channel and removed when the channel is
closed by remote processor.
config QCOM_AOP_SET_DDR
tristate "Sysfs to communicate with AOP using QMP protocol"
help

View file

@ -119,6 +119,7 @@ obj-$(CONFIG_RENAME_BLOCK_DEVICE) += rename_block_device.o
obj-$(CONFIG_QCOM_ADSP_MANUAL_VOTE) += adsp_vote_qmi.o adsp_lpm_voting_v01.o
obj-$(CONFIG_MSM_SLATECOM) += slatecom_spi.o
obj-$(CONFIG_MSM_SLATECOM_INTERFACE) += slatecom_interface.o
obj-$(CONFIG_MSM_SLATECOM_RPMSG) += slatecom_rpmsg.o
obj-$(CONFIG_QCOM_AOP_SET_DDR) += aop-set-ddr.o
obj-$(CONFIG_CPU_V7) += idle-v7.o
obj-$(CONFIG_DUMP_XBL_LOG) += dump_boot_log.o

View file

@ -31,7 +31,7 @@
#include "peripheral-loader.h"
#include "../../misc/qseecom_kernel.h"
//#include "pil_slate_intf.h"
#include "slatecom_rpmsg.h"
#define SLATECOM "slate_com_dev"
@ -95,7 +95,14 @@ struct slatedaemon_priv {
unsigned long attrs;
u32 cmd_status;
struct device *platform_dev;
bool slatecom_rpmsg;
bool slate_resp_cmplt;
void *lhndl;
wait_queue_head_t link_state_wait;
char rx_buf[20];
struct mutex glink_mutex;
};
static void *slatecom_intf_drv;
struct slate_event {
enum slate_event_type e_type;
@ -182,6 +189,104 @@ static int send_uevent(struct slate_event *pce)
return kobject_uevent_env(&dev_ret->kobj, KOBJ_CHANGE, envp);
}
void slatecom_intf_notify_glink_channel_state(bool state)
{
struct slatedaemon_priv *dev =
container_of(slatecom_intf_drv, struct slatedaemon_priv, lhndl);
pr_debug("%s: slate_ctrl channel state: %d\n", __func__, state);
dev->slatecom_rpmsg = state;
}
EXPORT_SYMBOL(slatecom_intf_notify_glink_channel_state);
void slatecom_rx_msg(void *data, int len)
{
struct slatedaemon_priv *dev =
container_of(slatecom_intf_drv, struct slatedaemon_priv, lhndl);
dev->slate_resp_cmplt = true;
wake_up(&dev->link_state_wait);
memcpy(dev->rx_buf, data, len);
}
EXPORT_SYMBOL(slatecom_rx_msg);
static int slatecom_tx_msg(struct slatedaemon_priv *dev, void *msg, size_t len)
{
int rc = 0;
uint8_t resp = 0;
mutex_lock(&dev->glink_mutex);
if (!dev->slatecom_rpmsg) {
pr_err("slatecom-rpmsg is not probed yet, waiting for it to be probed\n");
goto err_ret;
}
rc = slatecom_rpmsg_tx_msg(msg, len);
/* wait for sending command to SLATE */
rc = wait_event_timeout(dev->link_state_wait,
(rc == 0), msecs_to_jiffies(TIMEOUT_MS));
if (rc == 0) {
pr_err("failed to send command to SLATE %d\n", rc);
goto err_ret;
}
/* wait for getting response from SLATE */
rc = wait_event_timeout(dev->link_state_wait,
dev->slate_resp_cmplt,
msecs_to_jiffies(TIMEOUT_MS));
if (rc == 0) {
pr_err("failed to get SLATE response %d\n", rc);
goto err_ret;
}
dev->slate_resp_cmplt = false;
/* check SLATE response */
resp = *(uint8_t *)dev->rx_buf;
if (!(resp == 0x01)) {
pr_err("Bad SLATE response\n");
rc = -EINVAL;
goto err_ret;
}
rc = 0;
err_ret:
mutex_unlock(&dev->glink_mutex);
return rc;
}
/**
* send_state_change_cmd send state transition event to Slate
* and wait for the response.
* The response is returned to the caller.
*/
static int send_state_change_cmd(struct slate_ui_data *ui_obj_msg)
{
int ret = 0;
struct wear_header wear_header_t = {0, 0};
struct slatedaemon_priv *dev = container_of(slatecom_intf_drv,
struct slatedaemon_priv,
lhndl);
uint32_t state = ui_obj_msg->cmd;
switch (state) {
case STATE_TWM_ENTER:
wear_header_t.opcode = GMI_WEAR_MGR_ENTER_TWM;
break;
case STATE_DS_ENTER:
wear_header_t.opcode = GMI_WEAR_MGR_ENTER_TRACKER_DS;
break;
case STATE_DS_EXIT:
wear_header_t.opcode = GMI_WEAR_MGR_EXIT_TRACKER_DS;
break;
default:
pr_err("Invalid MSM State transtion cmd\n");
break;
}
ret = slatecom_tx_msg(dev, &wear_header_t.opcode, sizeof(wear_header_t.opcode));
if (ret < 0)
pr_err("MSM State transtion event cmd failed\n");
return ret;
}
static int slatecom_char_open(struct inode *inode, struct file *file)
{
int ret;
@ -382,6 +487,16 @@ static long slate_com_ioctl(struct file *filp,
}
ret = 0;
break;
case DEVICE_STATE_TRANSITION:
if (copy_from_user(&ui_obj_msg, (void __user *)arg,
sizeof(ui_obj_msg))) {
pr_err("The copy from user failed for state transition cmd\n");
ret = -EFAULT;
}
ret = send_state_change_cmd(&ui_obj_msg);
if (ret < 0)
pr_err("device state transition cmd failed\n");
break;
default:
ret = -ENOIOCTLCMD;
break;

View file

@ -36,6 +36,80 @@ void set_slate_dsp_state(bool status);
* Set slate bt state
*/
void set_slate_bt_state(bool status);
void slatecom_intf_notify_glink_channel_state(bool state);
void slatecom_rx_msg(void *data, int len);
/*
* WM header type - generic header structure
*/
struct wear_header {
uint32_t opcode;
uint32_t payload_size;
};
/**
* Opcodes to be received on slate-control channel.
*/
enum WMSlateCtrlChnlOpcode {
/*
* Command to slate to enter TWM mode
*/
GMI_WEAR_MGR_ENTER_TWM = 1,
/*
* Notification to slate about Modem Processor Sub System
* is down due to a subsystem reset.
*/
GMI_WEAR_MGR_SSR_MPSS_DOWN_NOTIFICATION = 2,
/*
* Notification to slate about Modem Processor Sub System
* being brought up after a subsystem reset.
*/
GMI_WEAR_MGR_SSR_MPSS_UP_NOTIFICATION = 3,
/*
* Notification to slate about ADSP Sub System
* is down due to a subsystem reset.
*/
GMI_WEAR_MGR_SSR_ADSP_DOWN_INDICATION = 8,
/*
* Notification to slate about Modem Processor
* Sub System being brought up after a subsystem reset.
*/
GMI_WEAR_MGR_SSR_ADSP_UP_INDICATION = 9,
/*
* Notification to MSM for generic wakeup in tracker mode
*/
GMI_WEAR_MGR_WAKE_UP_NO_REASON = 10,
/*
* Notification to Slate About Entry to Tracker-DS
*/
GMI_WEAR_MGR_ENTER_TRACKER_DS = 11,
/*
* Notification to Slate About Entry to Tracker-DS
*/
GMI_WEAR_MGR_EXIT_TRACKER_DS = 12,
/*
* Notification to Slate About Time-sync update
*/
GMI_WEAR_MGR_TIME_SYNC_UPDATE = 13, /* payload struct: wear_time_sync_t*/
/*
* Notification to Slate About Timeval UTC
*/
GMI_WEAR_MGR_TIMEVAL_UTC = 14, /* payload struct: wear_timeval_utc_t*/
/*
* Notification to Slate About Daylight saving time
*/
GMI_WEAR_MGR_DST = 15, /* payload struct: wear_dst_t*/
};
#endif /* SLATECOM_INTERFACE_H */

View file

@ -0,0 +1,101 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include "slatecom_rpmsg.h"
static struct slatecom_rpmsg_dev *pdev;
int slatecom_rpmsg_tx_msg(void *msg, size_t len)
{
int ret = 0;
if (pdev == NULL || !pdev->chnl_state)
pr_err("pmsg_device is null, channel is closed\n");
pdev->message = msg;
pdev->message_length = len;
if (pdev->message) {
ret = rpmsg_send(pdev->channel, pdev->message, pdev->message_length);
if (ret)
pr_err("rpmsg_send failed: %d\n", ret);
}
return ret;
}
EXPORT_SYMBOL(slatecom_rpmsg_tx_msg);
static int slatecom_rpmsg_probe(struct rpmsg_device *rpdev)
{
int ret = 0;
void *msg = NULL;
pdev = devm_kzalloc(&rpdev->dev, sizeof(*pdev), GFP_KERNEL);
if (!pdev)
return -ENOMEM;
pdev->channel = rpdev->ept;
pdev->dev = &rpdev->dev;
if (pdev->channel == NULL)
return -ENOMEM;
pdev->chnl_state = true;
dev_set_drvdata(&rpdev->dev, pdev);
/* send a callback to slatecom-interface driver*/
slatecom_intf_notify_glink_channel_state(true);
if (pdev->message == NULL)
ret = slatecom_rpmsg_tx_msg(msg, 0);
return 0;
}
static void slatecom_rpmsg_remove(struct rpmsg_device *rpdev)
{
pdev->chnl_state = false;
pdev->message = NULL;
dev_dbg(&rpdev->dev, "rpmsg client driver is removed\n");
slatecom_intf_notify_glink_channel_state(false);
dev_set_drvdata(&rpdev->dev, NULL);
}
static int slatecom_rpmsg_cb(struct rpmsg_device *rpdev,
void *data, int len, void *priv, u32 src)
{
struct slatecom_rpmsg_dev *dev =
dev_get_drvdata(&rpdev->dev);
if (!dev)
return -ENODEV;
slatecom_rx_msg(data, len);
return 0;
}
static const struct rpmsg_device_id rpmsg_driver_slatecom_id_table[] = {
{ "SLATECOM_CTRL" },
{},
};
MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_slatecom_id_table);
static const struct of_device_id rpmsg_driver_slatecom_of_match[] = {
{ .compatible = "qcom,slatecom-rpmsg" },
{},
};
static struct rpmsg_driver rpmsg_slatecom_client = {
.id_table = rpmsg_driver_slatecom_id_table,
.probe = slatecom_rpmsg_probe,
.callback = slatecom_rpmsg_cb,
.remove = slatecom_rpmsg_remove,
.drv = {
.name = "qcom,slatecom_rpmsg",
.of_match_table = rpmsg_driver_slatecom_of_match,
},
};
module_rpmsg_driver(rpmsg_slatecom_client);
MODULE_DESCRIPTION("Interface Driver for SLATECOM and RPMSG");
MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
#ifndef SLATECOMRPMSG_H
#define SLATECOMRPMSG_H
#include <linux/rpmsg.h>
#include "slatecom_interface.h"
#define TIMEOUT_MS 2000
struct slatecom_rpmsg_dev {
struct rpmsg_endpoint *channel;
struct device *dev;
bool chnl_state;
void *message;
size_t message_length;
};
#if IS_ENABLED(CONFIG_MSM_SLATECOM_RPMSG)
int slatecom_rpmsg_tx_msg(void *msg, size_t len);
#else
static inline int slatecom_rpmsg_tx_msg(void *msg, size_t len)
{
return -EIO;
}
#endif
#endif

View file

@ -20,6 +20,7 @@
#define SLATECOM_ADSP_DOWN2_SLATE 10
#define SLATECOM_SLATE_WEAR_LOAD 11
#define SLATECOM_SLATE_WEAR_UNLOAD 12
#define SLATECOM_DEVICE_STATE_TRANSITION 13
#define EXCHANGE_CODE 'V'
struct slate_ui_data {
@ -47,6 +48,15 @@ enum slate_event_type {
SLATE_BT_READY,
};
enum device_state_transition {
STATE_TWM_ENTER = 1,
STATE_TWM_EXIT,
STATE_DS_ENTER,
STATE_DS_EXIT,
STATE_S2D_ENTER,
STATE_S2D_EXIT,
};
#define REG_READ \
_IOWR(EXCHANGE_CODE, SLATECOM_REG_READ, \
struct slate_ui_data)
@ -86,6 +96,9 @@ enum slate_event_type {
#define SLATE_ADSP_DOWN2_SLATE_DONE \
_IOWR(EXCHANGE_CODE, SLATECOM_ADSP_DOWN2_SLATE, \
struct slate_ui_data)
#define DEVICE_STATE_TRANSITION \
_IOWR(EXCHANGE_CODE, SLATECOM_DEVICE_STATE_TRANSITION, \
struct slate_ui_data)
#endif /* LINUX_SLATECOM_INTERFACE_H */