clk: msm: osm: support programming LMh SW override values in set_rate()

To ensure stable operation, it is necessary to place LMh SW override
votes when setting the new rate of the power and performance
CPU clocks. Add support for parsing these values from Device Tree
and programming them in clk_set_rate().

Change-Id: I60d90d546f155edb6c13c46e6c59c75e95848d6c
CRs-Fixed: 1009097
Signed-off-by: Osvaldo Banuelos <osvaldob@codeaurora.org>
This commit is contained in:
Osvaldo Banuelos 2016-04-26 17:48:47 -07:00 committed by Jeevan Shriram
parent 75f9319b67
commit cf381d203a
2 changed files with 37 additions and 1 deletions

View file

@ -196,6 +196,13 @@ Properties:
controller status register for each of the two clusters
managed by the OSM controller.
- qcom,llm-sw-overr
Usage: optional
Value type: <prop-encoded-array>
Definition: Array of tuples which defines the three non-zero LLM SW
override values to write to the OSM controller for each
of the two clusters. Each tuple must contain three elements.
- qcom,pwrcl-apcs-mem-acc-cfg
Usage: required if qcom,osm-no-tz is specified
Value type: <prop-encoded-array>

View file

@ -80,6 +80,7 @@ enum clk_osm_trace_packet_id {
#define OSM_TABLE_SIZE 40
#define MAX_CLUSTER_CNT 2
#define MAX_CONFIG 4
#define LLM_SW_OVERRIDE_CNT 3
#define ENABLE_REG 0x1004
#define INDEX_REG 0x1150
@ -142,6 +143,7 @@ enum clk_osm_trace_packet_id {
#define PLL_POST_DIV1 0x1F
#define PLL_POST_DIV2 0x11F
#define LLM_SW_OVERRIDE_REG 0x1038
#define VMIN_REDUC_ENABLE_REG 0x103C
#define VMIN_REDUC_TIMER_REG 0x1040
#define PDN_FSM_CTRL_REG 0x1070
@ -300,6 +302,7 @@ struct clk_osm {
u32 apcs_pll_user_ctl;
u32 apcs_mem_acc_cfg[MAX_MEM_ACC_VAL_PER_LEVEL];
u32 apcs_mem_acc_val[MAX_MEM_ACC_VALUES];
u32 llm_sw_overr[LLM_SW_OVERRIDE_CNT];
u32 apm_mode_ctl;
u32 apm_ctrl_status;
u32 osm_clk_rate;
@ -413,9 +416,23 @@ static int clk_osm_set_rate(struct clk *c, unsigned long rate)
}
pr_debug("rate: %lu --> index %d\n", rate, index);
if (cpuclk->llm_sw_overr) {
clk_osm_write_reg(cpuclk, cpuclk->llm_sw_overr[0],
LLM_SW_OVERRIDE_REG);
clk_osm_write_reg(cpuclk, cpuclk->llm_sw_overr[1],
LLM_SW_OVERRIDE_REG);
udelay(1);
}
/* Choose index and send request to OSM hardware */
clk_osm_write_reg(cpuclk, index, DCVS_PERF_STATE_DESIRED_REG);
if (cpuclk->llm_sw_overr) {
udelay(1);
clk_osm_write_reg(cpuclk, cpuclk->llm_sw_overr[2],
LLM_SW_OVERRIDE_REG);
}
/* Make sure the write goes through before proceeding */
mb();
@ -603,7 +620,7 @@ static int clk_osm_parse_dt_configs(struct platform_device *pdev)
{
struct device_node *of = pdev->dev.of_node;
u32 *array;
int rc = 0;
int i, rc = 0;
array = devm_kzalloc(&pdev->dev, MAX_CLUSTER_CNT * sizeof(u32),
GFP_KERNEL);
@ -687,6 +704,18 @@ static int clk_osm_parse_dt_configs(struct platform_device *pdev)
pwrcl_clk.apm_ctrl_status = array[pwrcl_clk.cluster_num];
perfcl_clk.apm_ctrl_status = array[perfcl_clk.cluster_num];
for (i = 0; i < LLM_SW_OVERRIDE_CNT; i++)
of_property_read_u32_index(of, "qcom,llm-sw-overr",
pwrcl_clk.cluster_num *
LLM_SW_OVERRIDE_CNT + i,
&pwrcl_clk.llm_sw_overr[i]);
for (i = 0; i < LLM_SW_OVERRIDE_CNT; i++)
of_property_read_u32_index(of, "qcom,llm-sw-overr",
perfcl_clk.cluster_num *
LLM_SW_OVERRIDE_CNT + i,
&perfcl_clk.llm_sw_overr[i]);
rc = of_property_read_u32(of, "qcom,xo-clk-rate",
&pwrcl_clk.xo_clk_rate);
if (rc) {