Skip to content

Commit

Permalink
soc: qcom: geni: Support for ICC voting
Browse files Browse the repository at this point in the history
Add necessary macros and structure variables to support ICC BW
voting from individual SE drivers.

Signed-off-by: Akash Asthana <akashast@codeaurora.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Link: https://lore.kernel.org/r/1592908737-7068-2-git-send-email-akashast@codeaurora.org
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
  • Loading branch information
Akash Asthana authored and Bjorn Andersson committed Jun 25, 2020
1 parent be24c6a commit 58ffbba
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 0 deletions.
82 changes: 82 additions & 0 deletions drivers/soc/qcom/qcom-geni-se.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ struct geni_wrapper {
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

/* Common SE registers */
Expand Down Expand Up @@ -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);

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)
{
struct device *dev = &pdev->dev;
Expand Down
38 changes: 38 additions & 0 deletions include/linux/qcom-geni-se.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#ifndef _LINUX_QCOM_GENI_SE
#define _LINUX_QCOM_GENI_SE

#include <linux/interconnect.h>

/* Transfer mode supported by GENI Serial Engines */
enum geni_se_xfer_mode {
GENI_SE_INVALID,
Expand All @@ -25,6 +27,17 @@ enum geni_se_protocol_type {
struct geni_wrapper;
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
* @base: Base Address of the Serial Engine's register block
Expand All @@ -33,6 +46,7 @@ struct clk;
* @clk: Handle to the core serial engine clock
* @num_clk_levels: Number of valid clock levels in clk_perf_tbl
* @clk_perf_tbl: Table of clock frequency input to serial engine clock
* @icc_paths: Array of ICC paths for SE
*/
struct geni_se {
void __iomem *base;
Expand All @@ -41,6 +55,7 @@ struct geni_se {
struct clk *clk;
unsigned int num_clk_levels;
unsigned long *clk_perf_tbl;
struct geni_icc_path icc_paths[3];
};

/* Common SE registers */
Expand Down Expand Up @@ -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_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)

u32 geni_se_get_qup_hw_version(struct geni_se *se);
Expand Down Expand Up @@ -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_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

0 comments on commit 58ffbba

Please sign in to comment.