lkml.org 
[lkml]   [2018]   [Jun]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [PATCH v11 04/10] drivers: qcom: rpmh: add RPMH helper functions
On Mon, Jun 18 2018 at 07:37 -0600, Raju P L S S S N wrote:
>From: Lina Iyer <ilina@codeaurora.org>
>
>Sending RPMH requests and waiting for response from the controller
>through a callback is common functionality across all platform drivers.
>To simplify drivers, add a library functions to create RPMH client and
>send resource state requests.
>
>rpmh_write() is a synchronous blocking call that can be used to send
>active state requests.
>
>Signed-off-by: Lina Iyer <ilina@codeaurora.org>
>Signed-off-by: Raju P.L.S.S.S.N <rplsssn@codeaurora.org>
>---
>Changes in v11:
> - move rpmh_request to rpmh-internal.h
> - Associate rpmh_ctrl to rsc_drv
> - Remove EXPORT_SYMBOL for rpmh_tx_done
>
>Changes in v10:
> - Remove rsc_drv_list
> - Add EXPORT_SYMBOL
>
>Changes in v9:
> - Remove EXPORT_SYMBOL
> - add WARN_ON if response fails
>
>Changes in v7:
> - Optimization and locking fixes
>
>Changes in v6:
> - replace rpmh_client with device
> - inline wait_for_tx_done()
>
>Changes in v4:
> - use const struct tcs_cmd in API
> - remove wait count from this patch
> - changed -EFAULT to -EINVAL
>---
> drivers/soc/qcom/Makefile | 4 +-
> drivers/soc/qcom/rpmh-internal.h | 31 ++++++++++-
> drivers/soc/qcom/rpmh-rsc.c | 4 ++
> drivers/soc/qcom/rpmh.c | 116 +++++++++++++++++++++++++++++++++++++++
> include/soc/qcom/rpmh.h | 25 +++++++++
> 5 files changed, 178 insertions(+), 2 deletions(-)
> create mode 100644 drivers/soc/qcom/rpmh.c
> create mode 100644 include/soc/qcom/rpmh.h
>
>diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
>index cb6300f..bb395c3 100644
>--- a/drivers/soc/qcom/Makefile
>+++ b/drivers/soc/qcom/Makefile
>@@ -7,7 +7,9 @@ obj-$(CONFIG_QCOM_PM) += spm.o
> obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o
> qmi_helpers-y += qmi_encdec.o qmi_interface.o
> obj-$(CONFIG_QCOM_RMTFS_MEM) += rmtfs_mem.o
>-obj-$(CONFIG_QCOM_RPMH) += rpmh-rsc.o
>+obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o
>+qcom_rpmh-y += rpmh-rsc.o
>+qcom_rpmh-y += rpmh.o
> obj-$(CONFIG_QCOM_SMD_RPM) += smd-rpm.o
> obj-$(CONFIG_QCOM_SMEM) += smem.o
> obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
>diff --git a/drivers/soc/qcom/rpmh-internal.h b/drivers/soc/qcom/rpmh-internal.h
>index cc29176..f8e0f2a 100644
>--- a/drivers/soc/qcom/rpmh-internal.h
>+++ b/drivers/soc/qcom/rpmh-internal.h
>@@ -42,6 +42,32 @@ struct tcs_group {
> };
>
> /**
>+ * struct rpmh_request: the message to be sent to rpmh-rsc
>+ *
>+ * @msg: the request
>+ * @cmd: the payload that will be part of the @msg
>+ * @completion: triggered when request is done
>+ * @dev: the device making the request
>+ * @err: err return from the controller
>+ */
>+struct rpmh_request {
>+ struct tcs_request msg;
>+ struct tcs_cmd cmd[MAX_RPMH_PAYLOAD];
>+ struct completion *completion;
>+ const struct device *dev;
>+ int err;
>+};
>+
>+/**
>+ * struct rpmh_ctrlr: our representation of the controller
>+ *
>+ * @drv: the controller instance
>+ */
>+struct rpmh_ctrlr {
>+ struct rsc_drv *drv;
>+};
>+
>+/**
> * struct rsc_drv: the Direct Resource Voter (DRV) of the
> * Resource State Coordinator controller (RSC)
> *
>@@ -52,6 +78,7 @@ struct tcs_group {
> * @tcs: TCS groups
> * @tcs_in_use: s/w state of the TCS
> * @lock: synchronize state of the controller
>+ * @ctrl: controller to handle cases like batch requests
This is not only for batch requests.
This is handle to the DRV's client. @client might be a better name than
@ctrlr.

Thanks,
Lina

> */
> struct rsc_drv {
> const char *name;
>@@ -61,9 +88,11 @@ struct rsc_drv {
> struct tcs_group tcs[TCS_TYPE_NR];
> DECLARE_BITMAP(tcs_in_use, MAX_TCS_NR);
> spinlock_t lock;
>+ struct rpmh_ctrlr ctrlr;
> };
>
>-
> int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg);
>
>+void rpmh_tx_done(const struct tcs_request *msg, int r);
>+
> #endif /* __RPM_INTERNAL_H__ */
>diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
>index 89d41cd..59fa41f 100644
>--- a/drivers/soc/qcom/rpmh-rsc.c
>+++ b/drivers/soc/qcom/rpmh-rsc.c
>@@ -175,6 +175,8 @@ static irqreturn_t tcs_tx_done(int irq, void *p)
> spin_lock(&drv->lock);
> clear_bit(i, drv->tcs_in_use);
> spin_unlock(&drv->lock);
>+ if (req)
>+ rpmh_tx_done(req, err);
> }
>
> return IRQ_HANDLED;
>@@ -467,6 +469,8 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
> /* Enable the active TCS to send requests immediately */
> write_tcs_reg(drv, RSC_DRV_IRQ_ENABLE, 0, drv->tcs[ACTIVE_TCS].mask);
>
>+ dev_set_drvdata(&pdev->dev, drv);
>+
> return devm_of_platform_populate(&pdev->dev);
> }
>
>diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
>new file mode 100644
>index 0000000..969f1d5
>--- /dev/null
>+++ b/drivers/soc/qcom/rpmh.c
>@@ -0,0 +1,116 @@
>+// SPDX-License-Identifier: GPL-2.0
>+/*
>+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
>+ */
>+
>+#include <linux/atomic.h>
>+#include <linux/bug.h>
>+#include <linux/interrupt.h>
>+#include <linux/jiffies.h>
>+#include <linux/kernel.h>
>+#include <linux/module.h>
>+#include <linux/of.h>
>+#include <linux/platform_device.h>
>+#include <linux/slab.h>
>+#include <linux/types.h>
>+#include <linux/wait.h>
>+
>+#include <soc/qcom/rpmh.h>
>+
>+#include "rpmh-internal.h"
>+
>+#define RPMH_TIMEOUT_MS msecs_to_jiffies(10000)
>+
>+#define DEFINE_RPMH_MSG_ONSTACK(dev, s, q, name) \
>+ struct rpmh_request name = { \
>+ .msg = { \
>+ .state = s, \
>+ .cmds = name.cmd, \
>+ .num_cmds = 0, \
>+ .wait_for_compl = true, \
>+ }, \
>+ .cmd = { { 0 } }, \
>+ .completion = q, \
>+ .dev = dev, \
>+ }
>+
>+#define ctrlr_to_drv(ctrlr) container_of(ctrlr, struct rsc_drv, ctrlr)
>+
>+static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct device *dev)
>+{
>+ struct rsc_drv *drv = dev_get_drvdata(dev->parent);
>+
>+ return &drv->ctrlr;
>+}
>+
>+void rpmh_tx_done(const struct tcs_request *msg, int r)
>+{
>+ struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request,
>+ msg);
>+ struct completion *compl = rpm_msg->completion;
>+
>+ rpm_msg->err = r;
>+
>+ if (r)
>+ dev_err(rpm_msg->dev, "RPMH TX fail in msg addr=%#x, err=%d\n",
>+ rpm_msg->msg.cmds[0].addr, r);
>+
>+ /* Signal the blocking thread we are done */
>+ if (compl)
>+ complete(compl);
>+}
>+
>+/**
>+ * __rpmh_write: send the RPMH request
>+ *
>+ * @dev: The device making the request
>+ * @state: Active/Sleep request type
>+ * @rpm_msg: The data that needs to be sent (cmds).
>+ */
>+static int __rpmh_write(const struct device *dev, enum rpmh_state state,
>+ struct rpmh_request *rpm_msg)
>+{
>+ struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
>+
>+ rpm_msg->msg.state = state;
>+
>+ if (state != RPMH_ACTIVE_ONLY_STATE)
>+ return -EINVAL;
>+
>+ WARN_ON(irqs_disabled());
>+
>+ return rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msg->msg);
>+}
>+
>+/**
>+ * rpmh_write: Write a set of RPMH commands and block until response
>+ *
>+ * @rc: The RPMH handle got from rpmh_get_client
>+ * @state: Active/sleep set
>+ * @cmd: The payload data
>+ * @n: The number of elements in @cmd
>+ *
>+ * May sleep. Do not call from atomic contexts.
>+ */
>+int rpmh_write(const struct device *dev, enum rpmh_state state,
>+ const struct tcs_cmd *cmd, u32 n)
>+{
>+ DECLARE_COMPLETION_ONSTACK(compl);
>+ DEFINE_RPMH_MSG_ONSTACK(dev, state, &compl, rpm_msg);
>+ int ret;
>+
>+ if (!cmd || !n || n > MAX_RPMH_PAYLOAD)
>+ return -EINVAL;
>+
>+ memcpy(rpm_msg.cmd, cmd, n * sizeof(*cmd));
>+ rpm_msg.msg.num_cmds = n;
>+
>+ ret = __rpmh_write(dev, state, &rpm_msg);
>+ if (ret)
>+ return ret;
>+
>+ ret = wait_for_completion_timeout(&compl, RPMH_TIMEOUT_MS);
>+ WARN_ON(!ret);
>+ return (ret > 0) ? 0 : -ETIMEDOUT;
>+}
>+EXPORT_SYMBOL(rpmh_write);
>diff --git a/include/soc/qcom/rpmh.h b/include/soc/qcom/rpmh.h
>new file mode 100644
>index 0000000..c1d0f90
>--- /dev/null
>+++ b/include/soc/qcom/rpmh.h
>@@ -0,0 +1,25 @@
>+/* SPDX-License-Identifier: GPL-2.0 */
>+/*
>+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
>+ */
>+
>+#ifndef __SOC_QCOM_RPMH_H__
>+#define __SOC_QCOM_RPMH_H__
>+
>+#include <soc/qcom/tcs.h>
>+#include <linux/platform_device.h>
>+
>+
>+#if IS_ENABLED(CONFIG_QCOM_RPMH)
>+int rpmh_write(const struct device *dev, enum rpmh_state state,
>+ const struct tcs_cmd *cmd, u32 n);
>+
>+#else
>+
>+static inline int rpmh_write(const struct device *dev, enum rpmh_state state,
>+ const struct tcs_cmd *cmd, u32 n)
>+{ return -ENODEV; }
>+
>+#endif /* CONFIG_QCOM_RPMH */
>+
>+#endif /* __SOC_QCOM_RPMH_H__ */
>--
>The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project
>

\
 
 \ /
  Last update: 2018-06-18 18:41    [W:0.121 / U:0.428 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site