diff options
-rw-r--r-- | drivers/clk/qcom/clk-cpu-osm.c | 66 |
1 files changed, 56 insertions, 10 deletions
diff --git a/drivers/clk/qcom/clk-cpu-osm.c b/drivers/clk/qcom/clk-cpu-osm.c index d3914ab5f47c..8bf45f572c5e 100644 --- a/drivers/clk/qcom/clk-cpu-osm.c +++ b/drivers/clk/qcom/clk-cpu-osm.c @@ -84,12 +84,14 @@ enum clk_osm_trace_packet_id { #define VERSION_REG 0x0 #define OSM_TABLE_SIZE 40 +#define MAX_VIRTUAL_CORNER (OSM_TABLE_SIZE - 1) #define MAX_CLUSTER_CNT 2 #define LLM_SW_OVERRIDE_CNT 3 #define CORE_COUNT_VAL(val) ((val & GENMASK(18, 16)) >> 16) #define SINGLE_CORE 1 #define MAX_CORE_COUNT 4 #define DEBUG_REG_NUM 3 +#define OSM_SEQ_MINUS_ONE 0xff #define ENABLE_REG 0x1004 #define INDEX_REG 0x1150 @@ -353,8 +355,10 @@ struct clk_osm { u32 cluster_num; u32 irq; u32 apm_crossover_vc; + u32 apm_threshold_pre_vc; u32 apm_threshold_vc; u32 mem_acc_crossover_vc; + u32 mem_acc_threshold_pre_vc; u32 mem_acc_threshold_vc; u32 cycle_counter_reads; u32 cycle_counter_delay; @@ -1622,10 +1626,26 @@ static int clk_osm_resolve_crossover_corners(struct clk_osm *c, if (corner_volt >= apm_threshold) { c->apm_threshold_vc = c->osm_table[i].virtual_corner; + /* + * Handle case where VC 0 has open-loop + * greater than or equal to APM threshold voltage. + */ + c->apm_threshold_pre_vc = c->apm_threshold_vc ? + c->apm_threshold_vc - 1 : OSM_SEQ_MINUS_ONE; break; } } + /* + * This assumes the OSM table uses corners + * 0 to MAX_VIRTUAL_CORNER - 1. + */ + if (!c->apm_threshold_vc && + c->apm_threshold_pre_vc != OSM_SEQ_MINUS_ONE) { + c->apm_threshold_vc = MAX_VIRTUAL_CORNER; + c->apm_threshold_pre_vc = c->apm_threshold_vc - 1; + } + /* Determine MEM ACC threshold virtual corner */ if (mem_acc_threshold) { for (i = 0; i < OSM_TABLE_SIZE; i++) { @@ -1636,9 +1656,30 @@ static int clk_osm_resolve_crossover_corners(struct clk_osm *c, if (corner_volt >= mem_acc_threshold) { c->mem_acc_threshold_vc = c->osm_table[i].virtual_corner; + /* + * Handle case where VC 0 has open-loop + * greater than or equal to MEM-ACC threshold + * voltage. + */ + c->mem_acc_threshold_pre_vc = + c->mem_acc_threshold_vc ? + c->mem_acc_threshold_vc - 1 : + OSM_SEQ_MINUS_ONE; break; } } + + /* + * This assumes the OSM table uses corners + * 0 to MAX_VIRTUAL_CORNER - 1. + */ + if (!c->mem_acc_threshold_vc && c->mem_acc_threshold_pre_vc + != OSM_SEQ_MINUS_ONE) { + c->mem_acc_threshold_vc = + MAX_VIRTUAL_CORNER; + c->mem_acc_threshold_pre_vc = + c->mem_acc_threshold_vc - 1; + } } return 0; @@ -1989,13 +2030,20 @@ static void clk_osm_program_mem_acc_regs(struct clk_osm *c) * highest MEM ACC threshold if it is specified instead of the * fixed mapping in the LUT. */ - if (c->mem_acc_threshold_vc) { - threshold_vc[2] = c->mem_acc_threshold_vc - 1; + if (c->mem_acc_threshold_vc || c->mem_acc_threshold_pre_vc + == OSM_SEQ_MINUS_ONE) { + threshold_vc[2] = c->mem_acc_threshold_pre_vc; threshold_vc[3] = c->mem_acc_threshold_vc; - if (threshold_vc[1] >= threshold_vc[2]) - threshold_vc[1] = threshold_vc[2] - 1; - if (threshold_vc[0] >= threshold_vc[1]) - threshold_vc[0] = threshold_vc[1] - 1; + + if (c->mem_acc_threshold_pre_vc == OSM_SEQ_MINUS_ONE) { + threshold_vc[1] = threshold_vc[0] = + c->mem_acc_threshold_pre_vc; + } else { + if (threshold_vc[1] >= threshold_vc[2]) + threshold_vc[1] = threshold_vc[2] - 1; + if (threshold_vc[0] >= threshold_vc[1]) + threshold_vc[0] = threshold_vc[1] - 1; + } } scm_io_write(c->pbases[OSM_BASE] + SEQ_REG(55), @@ -2249,8 +2297,7 @@ static void clk_osm_apm_vc_setup(struct clk_osm *c) clk_osm_write_reg(c, c->pbases[OSM_BASE] + SEQ_REG(1), SEQ_REG(8)); clk_osm_write_reg(c, c->apm_threshold_vc, SEQ_REG(15)); - clk_osm_write_reg(c, c->apm_threshold_vc != 0 ? - c->apm_threshold_vc - 1 : 0xff, + clk_osm_write_reg(c, c->apm_threshold_pre_vc, SEQ_REG(31)); clk_osm_write_reg(c, 0x3b | c->apm_threshold_vc << 6, SEQ_REG(73)); @@ -2268,8 +2315,7 @@ static void clk_osm_apm_vc_setup(struct clk_osm *c) scm_io_write(c->pbases[OSM_BASE] + SEQ_REG(15), c->apm_threshold_vc); scm_io_write(c->pbases[OSM_BASE] + SEQ_REG(31), - c->apm_threshold_vc != 0 ? - c->apm_threshold_vc - 1 : 0xff); + c->apm_threshold_pre_vc); scm_io_write(c->pbases[OSM_BASE] + SEQ_REG(76), 0x39 | c->apm_threshold_vc << 6); } |