Commit 58ffbba6 authored by Akash Asthana's avatar Akash Asthana Committed by Bjorn Andersson

soc: qcom: geni: Support for ICC voting

Add necessary macros and structure variables to support ICC BW
voting from individual SE drivers.
Signed-off-by: default avatarAkash Asthana <akashast@codeaurora.org>
Reviewed-by: default avatarMatthias Kaehlcke <mka@chromium.org>
Link: https://lore.kernel.org/r/1592908737-7068-2-git-send-email-akashast@codeaurora.orgSigned-off-by: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
parent be24c6a7
...@@ -92,6 +92,9 @@ struct geni_wrapper { ...@@ -92,6 +92,9 @@ struct geni_wrapper {
struct clk_bulk_data ahb_clks[NUM_AHB_CLKS]; struct clk_bulk_data ahb_clks[NUM_AHB_CLKS];
}; };
static const char * const icc_path_names[] = {"qup-core", "qup-config",
"qup-memory"};
#define QUP_HW_VER_REG 0x4 #define QUP_HW_VER_REG 0x4
/* Common SE registers */ /* Common SE registers */
...@@ -720,6 +723,85 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len) ...@@ -720,6 +723,85 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
} }
EXPORT_SYMBOL(geni_se_rx_dma_unprep); EXPORT_SYMBOL(geni_se_rx_dma_unprep);
int geni_icc_get(struct geni_se *se, const char *icc_ddr)
{
int i, err;
const char *icc_names[] = {"qup-core", "qup-config", icc_ddr};
for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
if (!icc_names[i])
continue;
se->icc_paths[i].path = devm_of_icc_get(se->dev, icc_names[i]);
if (IS_ERR(se->icc_paths[i].path))
goto err;
}
return 0;
err:
err = PTR_ERR(se->icc_paths[i].path);
if (err != -EPROBE_DEFER)
dev_err_ratelimited(se->dev, "Failed to get ICC path '%s': %d\n",
icc_names[i], err);
return err;
}
EXPORT_SYMBOL(geni_icc_get);
int geni_icc_set_bw(struct geni_se *se)
{
int i, ret;
for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
ret = icc_set_bw(se->icc_paths[i].path,
se->icc_paths[i].avg_bw, se->icc_paths[i].avg_bw);
if (ret) {
dev_err_ratelimited(se->dev, "ICC BW voting failed on path '%s': %d\n",
icc_path_names[i], ret);
return ret;
}
}
return 0;
}
EXPORT_SYMBOL(geni_icc_set_bw);
/* To do: Replace this by icc_bulk_enable once it's implemented in ICC core */
int geni_icc_enable(struct geni_se *se)
{
int i, ret;
for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
ret = icc_enable(se->icc_paths[i].path);
if (ret) {
dev_err_ratelimited(se->dev, "ICC enable failed on path '%s': %d\n",
icc_path_names[i], ret);
return ret;
}
}
return 0;
}
EXPORT_SYMBOL(geni_icc_enable);
int geni_icc_disable(struct geni_se *se)
{
int i, ret;
for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
ret = icc_disable(se->icc_paths[i].path);
if (ret) {
dev_err_ratelimited(se->dev, "ICC disable failed on path '%s': %d\n",
icc_path_names[i], ret);
return ret;
}
}
return 0;
}
EXPORT_SYMBOL(geni_icc_disable);
static int geni_se_probe(struct platform_device *pdev) static int geni_se_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#ifndef _LINUX_QCOM_GENI_SE #ifndef _LINUX_QCOM_GENI_SE
#define _LINUX_QCOM_GENI_SE #define _LINUX_QCOM_GENI_SE
#include <linux/interconnect.h>
/* Transfer mode supported by GENI Serial Engines */ /* Transfer mode supported by GENI Serial Engines */
enum geni_se_xfer_mode { enum geni_se_xfer_mode {
GENI_SE_INVALID, GENI_SE_INVALID,
...@@ -25,6 +27,17 @@ enum geni_se_protocol_type { ...@@ -25,6 +27,17 @@ enum geni_se_protocol_type {
struct geni_wrapper; struct geni_wrapper;
struct clk; struct clk;
enum geni_icc_path_index {
GENI_TO_CORE,
CPU_TO_GENI,
GENI_TO_DDR
};
struct geni_icc_path {
struct icc_path *path;
unsigned int avg_bw;
};
/** /**
* struct geni_se - GENI Serial Engine * struct geni_se - GENI Serial Engine
* @base: Base Address of the Serial Engine's register block * @base: Base Address of the Serial Engine's register block
...@@ -33,6 +46,7 @@ struct clk; ...@@ -33,6 +46,7 @@ struct clk;
* @clk: Handle to the core serial engine clock * @clk: Handle to the core serial engine clock
* @num_clk_levels: Number of valid clock levels in clk_perf_tbl * @num_clk_levels: Number of valid clock levels in clk_perf_tbl
* @clk_perf_tbl: Table of clock frequency input to serial engine clock * @clk_perf_tbl: Table of clock frequency input to serial engine clock
* @icc_paths: Array of ICC paths for SE
*/ */
struct geni_se { struct geni_se {
void __iomem *base; void __iomem *base;
...@@ -41,6 +55,7 @@ struct geni_se { ...@@ -41,6 +55,7 @@ struct geni_se {
struct clk *clk; struct clk *clk;
unsigned int num_clk_levels; unsigned int num_clk_levels;
unsigned long *clk_perf_tbl; unsigned long *clk_perf_tbl;
struct geni_icc_path icc_paths[3];
}; };
/* Common SE registers */ /* Common SE registers */
...@@ -229,6 +244,21 @@ struct geni_se { ...@@ -229,6 +244,21 @@ struct geni_se {
#define GENI_SE_VERSION_MINOR(ver) ((ver & HW_VER_MINOR_MASK) >> HW_VER_MINOR_SHFT) #define GENI_SE_VERSION_MINOR(ver) ((ver & HW_VER_MINOR_MASK) >> HW_VER_MINOR_SHFT)
#define GENI_SE_VERSION_STEP(ver) (ver & HW_VER_STEP_MASK) #define GENI_SE_VERSION_STEP(ver) (ver & HW_VER_STEP_MASK)
/*
* Define bandwidth thresholds that cause the underlying Core 2X interconnect
* clock to run at the named frequency. These baseline values are recommended
* by the hardware team, and are not dynamically scaled with GENI bandwidth
* beyond basic on/off.
*/
#define CORE_2X_19_2_MHZ 960
#define CORE_2X_50_MHZ 2500
#define CORE_2X_100_MHZ 5000
#define CORE_2X_150_MHZ 7500
#define CORE_2X_200_MHZ 10000
#define CORE_2X_236_MHZ 16383
#define GENI_DEFAULT_BW Bps_to_icc(1000)
#if IS_ENABLED(CONFIG_QCOM_GENI_SE) #if IS_ENABLED(CONFIG_QCOM_GENI_SE)
u32 geni_se_get_qup_hw_version(struct geni_se *se); u32 geni_se_get_qup_hw_version(struct geni_se *se);
...@@ -416,5 +446,13 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len, ...@@ -416,5 +446,13 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
void geni_se_tx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len); void geni_se_tx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len);
void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len); void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len);
int geni_icc_get(struct geni_se *se, const char *icc_ddr);
int geni_icc_set_bw(struct geni_se *se);
int geni_icc_enable(struct geni_se *se);
int geni_icc_disable(struct geni_se *se);
#endif #endif
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment