drivers: firmware: arm_scmi: Add qcom vendor protocol
Add Qcom vendor consolidated protocol. This change adds client and vendor driver for Qcom SCMI consolidated protocol. Change-Id: I8100d9487fd5da706004f6090a25a271a482b2fe Signed-off-by: Shivnandan Kumar <quic_kshivnan@quicinc.com>
This commit is contained in:
parent
93288c2477
commit
1db77b7094
7 changed files with 269 additions and 2 deletions
|
|
@ -143,7 +143,18 @@ config QTI_SCMI_PMU_PROTOCOL
|
|||
This protocol provides interface to communicate with micro controller
|
||||
which maintains the PMU configuration for multiple clients.
|
||||
|
||||
This driver defines the comands or message ID's used for this
|
||||
This driver defines the commands or message ID's used for this
|
||||
communication and also exposes the ops used by clients.
|
||||
|
||||
config QTI_SCMI_VENDOR_PROTOCOL
|
||||
tristate "Qualcomm Technologies, Inc. Qcom SCMI vendor Protocol"
|
||||
depends on ARM || ARM64 || COMPILE_TEST
|
||||
depends on ARM_SCMI_PROTOCOL && QCOM_CPUCP
|
||||
help
|
||||
System Control and Management Interface (SCMI) Qcom vendor protocol.
|
||||
This protocol provides interface to communicate with micro controller.
|
||||
|
||||
This driver defines the commands or message ID's used for this
|
||||
communication and also exposes the ops used by clients.
|
||||
|
||||
config QTI_SCMI_C1DCVS_PROTOCOL
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ obj-$(CONFIG_ARM_SCMI_POWER_CONTROL) += scmi_power_control.o
|
|||
obj-$(CONFIG_QTI_SCMI_PMU_PROTOCOL) += pmu_vendor.o
|
||||
obj-$(CONFIG_QTI_SCMI_C1DCVS_PROTOCOL) += c1dcvs_vendor.o
|
||||
obj-$(CONFIG_QTI_SCMI_MEMLAT_PROTOCOL) += memlat_vendor.o
|
||||
obj-$(CONFIG_QTI_SCMI_VENDOR_PROTOCOL) += qcom_scmi_vendor.o
|
||||
|
||||
ifeq ($(CONFIG_THUMB2_KERNEL)$(CONFIG_CC_IS_CLANG),yy)
|
||||
# The use of R7 in the SMCCC conflicts with the compiler's use of R7 as a frame
|
||||
|
|
|
|||
148
drivers/firmware/arm_scmi/qcom_scmi_vendor.c
Normal file
148
drivers/firmware/arm_scmi/qcom_scmi_vendor.c
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include <linux/qcom_scmi_vendor.h>
|
||||
|
||||
#define EXTENDED_MSG_ID 0
|
||||
#define SCMI_MAX_TX_RX_SIZE 128
|
||||
#define PROTOCOL_PAYLOAD_SIZE 16
|
||||
#define SET_PARAM 0x10
|
||||
#define GET_PARAM 0x11
|
||||
#define START_ACTIVITY 0x12
|
||||
#define STOP_ACTIVITY 0x13
|
||||
|
||||
static int qcom_scmi_set_param(const struct scmi_protocol_handle *ph, void *buf, u64 algo_str,
|
||||
u32 param_id, size_t size)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct scmi_xfer *t;
|
||||
uint32_t *msg;
|
||||
|
||||
if (!ph || !ph->xops)
|
||||
return ret;
|
||||
ret = ph->xops->xfer_get_init(ph, SET_PARAM, size + PROTOCOL_PAYLOAD_SIZE,
|
||||
SCMI_MAX_TX_RX_SIZE, &t);
|
||||
if (ret)
|
||||
return ret;
|
||||
msg = t->tx.buf;
|
||||
*msg++ = cpu_to_le32(EXTENDED_MSG_ID);
|
||||
*msg++ = cpu_to_le32(algo_str & GENMASK(31, 0));
|
||||
*msg++ = cpu_to_le32((algo_str & GENMASK(63, 32)) >> 32);
|
||||
*msg++ = cpu_to_le32(param_id);
|
||||
memcpy(msg, buf, size);
|
||||
ret = ph->xops->do_xfer(ph, t);
|
||||
ph->xops->xfer_put(ph, t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_scmi_get_param(const struct scmi_protocol_handle *ph, void *buf, u64 algo_str,
|
||||
u32 param_id, size_t tx_size, size_t rx_size)
|
||||
{
|
||||
|
||||
int ret = -EINVAL;
|
||||
struct scmi_xfer *t;
|
||||
uint32_t *msg;
|
||||
|
||||
if (!ph || !ph->xops || !buf)
|
||||
return ret;
|
||||
ret = ph->xops->xfer_get_init(ph, GET_PARAM, tx_size + PROTOCOL_PAYLOAD_SIZE,
|
||||
SCMI_MAX_TX_RX_SIZE, &t);
|
||||
if (ret)
|
||||
return ret;
|
||||
msg = t->tx.buf;
|
||||
*msg++ = cpu_to_le32(EXTENDED_MSG_ID);
|
||||
*msg++ = cpu_to_le32(algo_str & GENMASK(31, 0));
|
||||
*msg++ = cpu_to_le32((algo_str & GENMASK(63, 32)) >> 32);
|
||||
*msg++ = cpu_to_le32(param_id);
|
||||
memcpy(msg, buf, tx_size);
|
||||
ret = ph->xops->do_xfer(ph, t);
|
||||
if (t->rx.len > rx_size) {
|
||||
pr_err("SCMI received buffer size %d is more than expected size %d\n",
|
||||
t->rx.len, rx_size);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
memcpy(buf, t->rx.buf, t->rx.len);
|
||||
ph->xops->xfer_put(ph, t);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_scmi_start_activity(const struct scmi_protocol_handle *ph,
|
||||
void *buf, u64 algo_str, u32 param_id, size_t size)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct scmi_xfer *t;
|
||||
uint32_t *msg;
|
||||
|
||||
if (!ph || !ph->xops)
|
||||
return ret;
|
||||
ret = ph->xops->xfer_get_init(ph, START_ACTIVITY, size + PROTOCOL_PAYLOAD_SIZE,
|
||||
SCMI_MAX_TX_RX_SIZE, &t);
|
||||
if (ret)
|
||||
return ret;
|
||||
msg = t->tx.buf;
|
||||
*msg++ = cpu_to_le32(EXTENDED_MSG_ID);
|
||||
*msg++ = cpu_to_le32(algo_str & GENMASK(31, 0));
|
||||
*msg++ = cpu_to_le32((algo_str & GENMASK(63, 32)) >> 32);
|
||||
*msg++ = cpu_to_le32(param_id);
|
||||
memcpy(msg, buf, size);
|
||||
ret = ph->xops->do_xfer(ph, t);
|
||||
ph->xops->xfer_put(ph, t);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_scmi_stop_activity(const struct scmi_protocol_handle *ph, void *buf, u64 algo_str,
|
||||
u32 param_id, size_t size)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct scmi_xfer *t;
|
||||
uint32_t *msg;
|
||||
|
||||
if (!ph || !ph->xops)
|
||||
return ret;
|
||||
ret = ph->xops->xfer_get_init(ph, STOP_ACTIVITY, size + PROTOCOL_PAYLOAD_SIZE,
|
||||
SCMI_MAX_TX_RX_SIZE, &t);
|
||||
if (ret)
|
||||
return ret;
|
||||
msg = t->tx.buf;
|
||||
*msg++ = cpu_to_le32(EXTENDED_MSG_ID);
|
||||
*msg++ = cpu_to_le32(algo_str & GENMASK(31, 0));
|
||||
*msg++ = cpu_to_le32((algo_str & GENMASK(63, 32)) >> 32);
|
||||
*msg++ = cpu_to_le32(param_id);
|
||||
memcpy(msg, buf, size);
|
||||
ret = ph->xops->do_xfer(ph, t);
|
||||
ph->xops->xfer_put(ph, t);
|
||||
return ret;
|
||||
}
|
||||
static struct qcom_scmi_vendor_ops qcom_proto_ops = {
|
||||
.set_param = qcom_scmi_set_param,
|
||||
.get_param = qcom_scmi_get_param,
|
||||
.start_activity = qcom_scmi_start_activity,
|
||||
.stop_activity = qcom_scmi_stop_activity,
|
||||
};
|
||||
|
||||
static int qcom_scmi_vendor_protocol_init(const struct scmi_protocol_handle *ph)
|
||||
{
|
||||
u32 version;
|
||||
|
||||
ph->xops->version_get(ph, &version);
|
||||
|
||||
dev_dbg(ph->dev, "qcom scmi version %d.%d\n",
|
||||
PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct scmi_protocol qcom_scmi_vendor = {
|
||||
.id = QCOM_SCMI_VENDOR_PROTOCOL,
|
||||
.owner = THIS_MODULE,
|
||||
.instance_init = &qcom_scmi_vendor_protocol_init,
|
||||
.ops = &qcom_proto_ops,
|
||||
};
|
||||
module_scmi_protocol(qcom_scmi_vendor);
|
||||
|
||||
MODULE_DESCRIPTION("qcom scmi vendor Protocol");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -76,7 +76,18 @@ config QTI_PMU_SCMI_CLIENT
|
|||
|
||||
This driver delivers the pmu vendor protocol handle to interface
|
||||
driver, and interface driver will use this handle to communicate with
|
||||
rimps.
|
||||
cpucp.
|
||||
|
||||
config QTI_QCOM_SCMI_CLIENT
|
||||
tristate "Qualcomm Technologies Inc. SCMI client driver"
|
||||
depends on QTI_SCMI_VENDOR_PROTOCOL
|
||||
default n
|
||||
help
|
||||
SCMI client driver registers for Qcom vendor protocol.
|
||||
|
||||
This driver delivers the qcom vendor protocol handle to interface
|
||||
driver, and interface driver will use this handle to communicate with
|
||||
cpucp.
|
||||
|
||||
config QTI_C1DCVS_SCMI_CLIENT
|
||||
tristate "Qualcomm Technologies Inc. SCMI client driver for cpudcvs"
|
||||
|
|
|
|||
|
|
@ -9,3 +9,4 @@ obj-$(CONFIG_QCOM_BWMON) += bwmon.o
|
|||
obj-$(CONFIG_QTI_PMU_SCMI_CLIENT) += pmu_scmi.o
|
||||
obj-$(CONFIG_QTI_C1DCVS_SCMI_CLIENT) += c1dcvs_scmi.o
|
||||
obj-$(CONFIG_QTI_HW_MEMLAT_SCMI_CLIENT) += memlat_scmi.o
|
||||
obj-$(CONFIG_QTI_QCOM_SCMI_CLIENT) += qcom_scmi_client.o
|
||||
|
|
|
|||
57
drivers/soc/qcom/dcvs/qcom_scmi_client.c
Normal file
57
drivers/soc/qcom/dcvs/qcom_scmi_client.c
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/scmi_protocol.h>
|
||||
#include <linux/qcom_scmi_vendor.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
struct scmi_device *scmi_dev;
|
||||
static int scmi_client_inited;
|
||||
|
||||
struct scmi_device *get_qcom_scmi_device(void)
|
||||
{
|
||||
if (!scmi_client_inited)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
if (!scmi_dev || !scmi_dev->handle)
|
||||
return ERR_PTR(-ENODEV);
|
||||
return scmi_dev;
|
||||
}
|
||||
EXPORT_SYMBOL(get_qcom_scmi_device);
|
||||
|
||||
static int scmi_client_probe(struct scmi_device *sdev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
scmi_dev = sdev;
|
||||
if (!sdev)
|
||||
ret = -ENODEV;
|
||||
scmi_client_inited = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct scmi_device_id scmi_id_table[] = {
|
||||
{ .protocol_id = QCOM_SCMI_VENDOR_PROTOCOL, .name = "qcom_scmi_vendor_protocol" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(scmi, scmi_id_table);
|
||||
|
||||
static struct scmi_driver qcom_scmi_client_drv = {
|
||||
.name = "qcom-scmi-driver",
|
||||
.probe = scmi_client_probe,
|
||||
.id_table = scmi_id_table,
|
||||
};
|
||||
module_scmi_driver(qcom_scmi_client_drv);
|
||||
|
||||
MODULE_SOFTDEP("pre: qcom_scmi_vendor");
|
||||
MODULE_DESCRIPTION("QCOM SCMI client driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
||||
38
include/linux/qcom_scmi_vendor.h
Normal file
38
include/linux/qcom_scmi_vendor.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Qcom scmi vendor protocol's header
|
||||
*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _QCOM_SCMI_VENDOR_H
|
||||
#define _QCOM_SCMI_VENDOR_H
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define QCOM_SCMI_VENDOR_PROTOCOL 0x80
|
||||
|
||||
struct scmi_protocol_handle;
|
||||
extern struct scmi_device *get_qcom_scmi_device(void);
|
||||
|
||||
|
||||
/**
|
||||
* struct qcom_scmi_vendor_ops - represents the various operations provided
|
||||
* by qcom scmi vendor protocol
|
||||
*/
|
||||
struct qcom_scmi_vendor_ops {
|
||||
int (*set_param)(const struct scmi_protocol_handle *ph, void *buf, u64 algo_str,
|
||||
u32 param_id, size_t size);
|
||||
int (*get_param)(const struct scmi_protocol_handle *ph, void *buf, u64 algo_str,
|
||||
u32 param_id, size_t tx_size, size_t rx_size);
|
||||
int (*start_activity)(const struct scmi_protocol_handle *ph, void *buf, u64 algo_str,
|
||||
u32 param_id, size_t size);
|
||||
int (*stop_activity)(const struct scmi_protocol_handle *ph, void *buf, u64 algo_str,
|
||||
u32 param_id, size_t size);
|
||||
};
|
||||
|
||||
|
||||
#endif /* _QCOM_SCMI_VENDOR_H */
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue