Merge "clk: qcom: clk-cpu-osm: handle corner cases for APM/MEM-ACC switching"

This commit is contained in:
Linux Build Service Account 2017-04-24 06:47:52 -07:00 committed by Gerrit - the friendly Code Review server
commit d4966a38bb

View file

@ -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);
}