From 658628e7ef78e875cfe13064387c1a7a287d6338 Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Wed, 20 Jun 2018 18:56:58 +0530 Subject: drivers: qcom: rpmh-rsc: add RPMH controller for QCOM SoCs Add controller driver for QCOM SoCs that have hardware based shared resource management. The hardware IP known as RSC (Resource State Coordinator) houses multiple Direct Resource Voter (DRV) for different execution levels. A DRV is a unique voter on the state of a shared resource. A Trigger Control Set (TCS) is a bunch of slots that can house multiple resource state requests, that when triggered will issue those requests through an internal bus to the Resource Power Manager Hardened (RPMH) blocks. These hardware blocks are capable of adjusting clocks, voltages, etc. The resource state request from a DRV are aggregated along with state requests from other processors in the SoC and the aggregate value is applied on the resource. Some important aspects of the RPMH communication - - Requests are with some header information - Multiple requests (upto 16) may be sent through a TCS, at a time - Requests in a TCS are sent in sequence - Requests may be fire-n-forget or completion (response expected) - Multiple TCS from the same DRV may be triggered simultaneously - Cannot send a request if another request for the same addr is in progress from the same DRV - When all the requests from a TCS are complete, an IRQ is raised - The IRQ handler needs to clear the TCS before it is available for reuse - TCS configuration is specific to a DRV - Platform drivers may use DRV from different RSCs to make requests Resource state requests made when CPUs are active are called 'active' state requests. Requests made when all the CPUs are powered down (idle state) are called 'sleep' state requests. They are matched by a corresponding 'wake' state requests which puts the resources back in to previously requested active state before resuming any CPU. TCSes are dedicated for each type of requests. Active mode TCSes (AMC) are used to send requests immediately to the resource, while control TCS are used to provide specific information to the controller. Sleep and Wake TCS send sleep and wake requests, after and before the system halt respectively. Signed-off-by: Lina Iyer Signed-off-by: Raju P.L.S.S.S.N Signed-off-by: Andy Gross --- include/soc/qcom/tcs.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 include/soc/qcom/tcs.h (limited to 'include/soc') diff --git a/include/soc/qcom/tcs.h b/include/soc/qcom/tcs.h new file mode 100644 index 000000000000..262876a59e86 --- /dev/null +++ b/include/soc/qcom/tcs.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef __SOC_QCOM_TCS_H__ +#define __SOC_QCOM_TCS_H__ + +#define MAX_RPMH_PAYLOAD 16 + +/** + * rpmh_state: state for the request + * + * RPMH_SLEEP_STATE: State of the resource when the processor subsystem + * is powered down. There is no client using the + * resource actively. + * RPMH_WAKE_ONLY_STATE: Resume resource state to the value previously + * requested before the processor was powered down. + * RPMH_ACTIVE_ONLY_STATE: Active or AMC mode requests. Resource state + * is aggregated immediately. + */ +enum rpmh_state { + RPMH_SLEEP_STATE, + RPMH_WAKE_ONLY_STATE, + RPMH_ACTIVE_ONLY_STATE, +}; + +/** + * struct tcs_cmd: an individual request to RPMH. + * + * @addr: the address of the resource slv_id:18:16 | offset:0:15 + * @data: the resource state request + * @wait: wait for this request to be complete before sending the next + */ +struct tcs_cmd { + u32 addr; + u32 data; + u32 wait; +}; + +/** + * struct tcs_request: A set of tcs_cmds sent together in a TCS + * + * @state: state for the request. + * @wait_for_compl: wait until we get a response from the h/w accelerator + * @num_cmds: the number of @cmds in this request + * @cmds: an array of tcs_cmds + */ +struct tcs_request { + enum rpmh_state state; + u32 wait_for_compl; + u32 num_cmds; + struct tcs_cmd *cmds; +}; + +#endif /* __SOC_QCOM_TCS_H__ */ -- cgit v1.2.3 From c1038456b02b86cc4445441a8d33c5aca0ac103e Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Wed, 20 Jun 2018 18:57:01 +0530 Subject: drivers: qcom: rpmh: add RPMH helper functions 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 Signed-off-by: Raju P.L.S.S.S.N Signed-off-by: Andy Gross --- include/soc/qcom/rpmh.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 include/soc/qcom/rpmh.h (limited to 'include/soc') diff --git a/include/soc/qcom/rpmh.h b/include/soc/qcom/rpmh.h new file mode 100644 index 000000000000..c1d0f902bd71 --- /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 +#include + + +#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__ */ -- cgit v1.2.3 From 600513dfeef33cb05c694d1b13d319b9e8cde536 Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Wed, 20 Jun 2018 18:57:04 +0530 Subject: drivers: qcom: rpmh: cache sleep/wake state requests Active state requests are sent immediately to the RSC controller, while sleep and wake state requests are cached in this driver to avoid taxing the RSC controller repeatedly. The cached values will be sent to the controller when the rpmh_flush() is called. Generally, flushing is a system PM activity and may be called from the system PM drivers when the system is entering suspend or deeper sleep modes during cpuidle. Also allow invalidating the cached requests, so they may be re-populated again. Signed-off-by: Lina Iyer [rplsssn: remove unneeded semicolon, address line over 80chars error] Signed-off-by: Raju P.L.S.S.S.N Reviewed-by: Evan Green Reviewed-by: Matthias Kaehlcke Signed-off-by: Andy Gross --- include/soc/qcom/rpmh.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'include/soc') diff --git a/include/soc/qcom/rpmh.h b/include/soc/qcom/rpmh.h index c1d0f902bd71..42e62a0d26d8 100644 --- a/include/soc/qcom/rpmh.h +++ b/include/soc/qcom/rpmh.h @@ -14,12 +14,23 @@ int rpmh_write(const struct device *dev, enum rpmh_state state, const struct tcs_cmd *cmd, u32 n); +int rpmh_flush(const struct device *dev); + +int rpmh_invalidate(const struct device *dev); + #else static inline int rpmh_write(const struct device *dev, enum rpmh_state state, const struct tcs_cmd *cmd, u32 n) { return -ENODEV; } + +static inline int rpmh_flush(const struct device *dev) +{ return -ENODEV; } + +static inline int rpmh_invalidate(const struct device *dev) +{ return -ENODEV; } + #endif /* CONFIG_QCOM_RPMH */ #endif /* __SOC_QCOM_RPMH_H__ */ -- cgit v1.2.3 From 564b5e24ccd4c840a7f84dfd952e5715dd9b3966 Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Wed, 20 Jun 2018 18:57:05 +0530 Subject: drivers: qcom: rpmh: allow requests to be sent asynchronously Platform drivers that want to send a request but do not want to block until the RPMH request completes have now a new API - rpmh_write_async(). The API allocates memory and send the requests and returns the control back to the platform driver. The tx_done callback from the controller is handled in the context of the controller's thread and frees the allocated memory. This API allows RPMH requests from atomic contexts as well. Signed-off-by: Lina Iyer Signed-off-by: Raju P.L.S.S.S.N Signed-off-by: Andy Gross --- include/soc/qcom/rpmh.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/soc') diff --git a/include/soc/qcom/rpmh.h b/include/soc/qcom/rpmh.h index 42e62a0d26d8..1161a5c77e75 100644 --- a/include/soc/qcom/rpmh.h +++ b/include/soc/qcom/rpmh.h @@ -14,6 +14,9 @@ int rpmh_write(const struct device *dev, enum rpmh_state state, const struct tcs_cmd *cmd, u32 n); +int rpmh_write_async(const struct device *dev, enum rpmh_state state, + const struct tcs_cmd *cmd, u32 n); + int rpmh_flush(const struct device *dev); int rpmh_invalidate(const struct device *dev); @@ -24,6 +27,10 @@ static inline int rpmh_write(const struct device *dev, enum rpmh_state state, const struct tcs_cmd *cmd, u32 n) { return -ENODEV; } +static inline int rpmh_write_async(const struct device *dev, + enum rpmh_state state, + const struct tcs_cmd *cmd, u32 n) +{ return -ENODEV; } static inline int rpmh_flush(const struct device *dev) { return -ENODEV; } -- cgit v1.2.3 From c8790cb6da58d3fa09dfa707aa486fe6769c23bc Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Wed, 20 Jun 2018 18:57:06 +0530 Subject: drivers: qcom: rpmh: add support for batch RPMH request Platform drivers need make a lot of resource state requests at the same time, say, at the start or end of an usecase. It can be quite inefficient to send each request separately. Instead they can give the RPMH library a batch of requests to be sent and wait on the whole transaction to be complete. rpmh_write_batch() is a blocking call that can be used to send multiple RPMH command sets. Each RPMH command set is set asynchronously and the API blocks until all the command sets are complete and receive their tx_done callbacks. Signed-off-by: Lina Iyer Signed-off-by: Raju P.L.S.S.S.N Reviewed-by: Matthias Kaehlcke Signed-off-by: Andy Gross --- include/soc/qcom/rpmh.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include/soc') diff --git a/include/soc/qcom/rpmh.h b/include/soc/qcom/rpmh.h index 1161a5c77e75..619e07c75da9 100644 --- a/include/soc/qcom/rpmh.h +++ b/include/soc/qcom/rpmh.h @@ -17,6 +17,9 @@ int rpmh_write(const struct device *dev, enum rpmh_state state, int rpmh_write_async(const struct device *dev, enum rpmh_state state, const struct tcs_cmd *cmd, u32 n); +int rpmh_write_batch(const struct device *dev, enum rpmh_state state, + const struct tcs_cmd *cmd, u32 *n); + int rpmh_flush(const struct device *dev); int rpmh_invalidate(const struct device *dev); @@ -32,6 +35,11 @@ static inline int rpmh_write_async(const struct device *dev, const struct tcs_cmd *cmd, u32 n) { return -ENODEV; } +static inline int rpmh_write_batch(const struct device *dev, + enum rpmh_state state, + const struct tcs_cmd *cmd, u32 *n) +{ return -ENODEV; } + static inline int rpmh_flush(const struct device *dev) { return -ENODEV; } -- cgit v1.2.3