Loading Documentation/devicetree/bindings/arm/msm/qcom,osm.txt +1 −23 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ Properties: - compatible Usage: required Value type: <string> Definition: must be "qcom,clk-cpu-osm". Definition: must be "qcom,clk-cpu-osm" or "qcom,clk-cpu-osm-v2". - reg Usage: required Loading Loading @@ -85,24 +85,6 @@ Properties: by the OSM hardware for each supported DCVS setpoint of the Performance cluster. - qcom,l3-min-cpr-vc-binX Usage: required Value type: <u32> Definition: First virtual corner which does not use PLL post-divider for the L3 clock domain. - qcom,pwrcl-min-cpr-vc-binX Usage: required Value type: <u32> Definition: First virtual corner which does not use PLL post-divider for the power cluster. - qcom,perfcl-min-cpr-vc-binX Usage: required Value type: <u32> Definition: First virtual corner which does not use PLL post-divider for the performance cluster. - qcom,osm-no-tz Usage: optional Value type: <empty> Loading Loading @@ -501,10 +483,6 @@ Example: < 1881600000 0x404c1462 0x00004e4e 0x2 21 >, < 1958400000 0x404c1566 0x00005252 0x3 22 >; qcom,l3-min-cpr-vc-bin0 = <7>; qcom,pwrcl-min-cpr-vc-bin0 = <6>; qcom,perfcl-min-cpr-vc-bin0 = <7>; qcom,up-timer = <1000 1000 1000>; qcom,down-timer = Loading drivers/clk/qcom/clk-cpu-osm.c +59 −77 Original line number Diff line number Diff line Loading @@ -150,12 +150,17 @@ #define DATA_MEM(n) (0x400 + (n) * 4) #define DCVS_PERF_STATE_DESIRED_REG_0 0x780 #define DCVS_PERF_STATE_DESIRED_REG(n) (DCVS_PERF_STATE_DESIRED_REG_0 + \ (4 * n)) #define OSM_CYCLE_COUNTER_STATUS_REG_0 0x7d0 #define OSM_CYCLE_COUNTER_STATUS_REG(n) (OSM_CYCLE_COUNTER_STATUS_REG_0 + \ (4 * n)) #define DCVS_PERF_STATE_DESIRED_REG_0_V1 0x780 #define DCVS_PERF_STATE_DESIRED_REG_0_V2 0x920 #define DCVS_PERF_STATE_DESIRED_REG(n, v2) \ (((v2) ? DCVS_PERF_STATE_DESIRED_REG_0_V2 \ : DCVS_PERF_STATE_DESIRED_REG_0_V1) + 4 * (n)) #define OSM_CYCLE_COUNTER_STATUS_REG_0_V1 0x7d0 #define OSM_CYCLE_COUNTER_STATUS_REG_0_V2 0x9c0 #define OSM_CYCLE_COUNTER_STATUS_REG(n, v2) \ (((v2) ? OSM_CYCLE_COUNTER_STATUS_REG_0_V2 \ : OSM_CYCLE_COUNTER_STATUS_REG_0_V1) + 4 * (n)) /* ACD registers */ #define ACD_HW_VERSION 0x0 Loading Loading @@ -444,6 +449,8 @@ static int clk_osm_acd_auto_local_write_reg(struct clk_osm *c, u32 mask) return 0; } static bool is_v2; static inline struct clk_osm *to_clk_osm(struct clk_hw *_hw) { return container_of(_hw, struct clk_osm, hw); Loading Loading @@ -604,7 +611,7 @@ static int l3_clk_set_rate(struct clk_hw *hw, unsigned long rate, } pr_debug("rate: %lu --> index %d\n", rate, index); clk_osm_write_reg(cpuclk, index, DCVS_PERF_STATE_DESIRED_REG_0, clk_osm_write_reg(cpuclk, index, DCVS_PERF_STATE_DESIRED_REG(0, is_v2), OSM_BASE); /* Make sure the write goes through before proceeding */ Loading @@ -622,7 +629,7 @@ static unsigned long l3_clk_recalc_rate(struct clk_hw *hw, if (!cpuclk) return -EINVAL; index = clk_osm_read_reg(cpuclk, DCVS_PERF_STATE_DESIRED_REG_0); index = clk_osm_read_reg(cpuclk, DCVS_PERF_STATE_DESIRED_REG(0, is_v2)); pr_debug("%s: Index %d, freq %ld\n", __func__, index, cpuclk->osm_table[index].frequency); Loading Loading @@ -890,7 +897,8 @@ static struct clk_osm *osm_configure_policy(struct cpufreq_policy *policy) static void osm_set_index(struct clk_osm *c, unsigned int index, unsigned int num) { clk_osm_write_reg(c, index, DCVS_PERF_STATE_DESIRED_REG(num), OSM_BASE); clk_osm_write_reg(c, index, DCVS_PERF_STATE_DESIRED_REG(num, is_v2), OSM_BASE); /* Make sure the write goes through before proceeding */ clk_osm_mb(c, OSM_BASE); Loading @@ -915,8 +923,8 @@ static unsigned int osm_cpufreq_get(unsigned int cpu) return 0; c = policy->driver_data; index = clk_osm_read_reg(c, DCVS_PERF_STATE_DESIRED_REG(c->core_num)); index = clk_osm_read_reg(c, DCVS_PERF_STATE_DESIRED_REG(c->core_num, is_v2)); return policy->freq_table[index].frequency; } Loading Loading @@ -1872,6 +1880,7 @@ static void populate_opp_table(struct platform_device *pdev) static u64 clk_osm_get_cpu_cycle_counter(int cpu) { u32 val; int core_num; unsigned long flags; struct clk_osm *parent, *c = logical_cpu_to_clk(cpu); Loading @@ -1887,12 +1896,9 @@ static u64 clk_osm_get_cpu_cycle_counter(int cpu) * Use core 0's copy as proxy for the whole cluster when per * core DCVS is disabled. */ if (parent->per_core_dcvs) val = clk_osm_read_reg_no_log(parent, OSM_CYCLE_COUNTER_STATUS_REG(c->core_num)); else core_num = parent->per_core_dcvs ? c->core_num : 0; val = clk_osm_read_reg_no_log(parent, OSM_CYCLE_COUNTER_STATUS_REG(0)); OSM_CYCLE_COUNTER_STATUS_REG(core_num, is_v2)); if (val < c->prev_cycle_counter) { /* Handle counter overflow */ Loading Loading @@ -2061,6 +2067,10 @@ static int clk_osm_get_lut(struct platform_device *pdev, c->osm_table[j].override_data, c->osm_table[j].mem_acc_level); data = (array[i + FREQ_DATA] & GENMASK(29, 28)) >> 28; if (j && !c->min_cpr_vc && !data) c->min_cpr_vc = c->osm_table[j].virtual_corner; data = (array[i + FREQ_DATA] & GENMASK(18, 16)) >> 16; if (!last_entry && data == MAX_CORE_COUNT) { fmax_temp[k] = array[i]; Loading Loading @@ -2243,9 +2253,6 @@ static int clk_osm_parse_dt_configs(struct platform_device *pdev) u32 *array; int rc = 0; struct resource *res; char l3_min_cpr_vc_str[] = "qcom,l3-min-cpr-vc-bin0"; char pwrcl_min_cpr_vc_str[] = "qcom,pwrcl-min-cpr-vc-bin0"; char perfcl_min_cpr_vc_str[] = "qcom,perfcl-min-cpr-vc-bin0"; array = devm_kzalloc(&pdev->dev, MAX_CLUSTER_CNT * sizeof(u32), GFP_KERNEL); Loading Loading @@ -2463,35 +2470,6 @@ static int clk_osm_parse_dt_configs(struct platform_device *pdev) return -ENOMEM; } snprintf(l3_min_cpr_vc_str, ARRAY_SIZE(l3_min_cpr_vc_str), "qcom,l3-min-cpr-vc-bin%d", l3_clk.speedbin); rc = of_property_read_u32(of, l3_min_cpr_vc_str, &l3_clk.min_cpr_vc); if (rc) { dev_err(&pdev->dev, "unable to find %s property, rc=%d\n", l3_min_cpr_vc_str, rc); return -EINVAL; } snprintf(pwrcl_min_cpr_vc_str, ARRAY_SIZE(pwrcl_min_cpr_vc_str), "qcom,pwrcl-min-cpr-vc-bin%d", pwrcl_clk.speedbin); rc = of_property_read_u32(of, pwrcl_min_cpr_vc_str, &pwrcl_clk.min_cpr_vc); if (rc) { dev_err(&pdev->dev, "unable to find %s property, rc=%d\n", pwrcl_min_cpr_vc_str, rc); return -EINVAL; } snprintf(perfcl_min_cpr_vc_str, ARRAY_SIZE(perfcl_min_cpr_vc_str), "qcom,perfcl-min-cpr-vc-bin%d", perfcl_clk.speedbin); rc = of_property_read_u32(of, perfcl_min_cpr_vc_str, &perfcl_clk.min_cpr_vc); if (rc) { dev_err(&pdev->dev, "unable to find %s property, rc=%d\n", perfcl_min_cpr_vc_str, rc); return -EINVAL; } l3_clk.secure_init = perfcl_clk.secure_init = pwrcl_clk.secure_init = of_property_read_bool(pdev->dev.of_node, "qcom,osm-no-tz"); Loading Loading @@ -3025,6 +3003,9 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev) return PTR_ERR(ext_xo_clk); } is_v2 = of_device_is_compatible(pdev->dev.of_node, "qcom,clk-cpu-osm-v2"); clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data), GFP_KERNEL); if (!clk_data) Loading @@ -3037,33 +3018,6 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev) clk_data->clk_num = num_clks; rc = clk_osm_parse_dt_configs(pdev); if (rc) { dev_err(&pdev->dev, "Unable to parse OSM device tree configurations\n"); return rc; } rc = clk_osm_parse_acd_dt_configs(pdev); if (rc) { dev_err(&pdev->dev, "Unable to parse ACD device tree configurations\n"); return rc; } rc = clk_osm_resources_init(pdev); if (rc) { if (rc != -EPROBE_DEFER) dev_err(&pdev->dev, "OSM resources init failed, rc=%d\n", rc); return rc; } rc = clk_osm_acd_resources_init(pdev); if (rc) { dev_err(&pdev->dev, "ACD resources init failed, rc=%d\n", rc); return rc; } if (l3_clk.vbases[EFUSE_BASE]) { /* Multiple speed-bins are supported */ pte_efuse = readl_relaxed(l3_clk.vbases[EFUSE_BASE]); Loading Loading @@ -3123,6 +3077,33 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev) return rc; } rc = clk_osm_parse_dt_configs(pdev); if (rc) { dev_err(&pdev->dev, "Unable to parse OSM device tree configurations\n"); return rc; } rc = clk_osm_parse_acd_dt_configs(pdev); if (rc) { dev_err(&pdev->dev, "Unable to parse ACD device tree configurations\n"); return rc; } rc = clk_osm_resources_init(pdev); if (rc) { if (rc != -EPROBE_DEFER) dev_err(&pdev->dev, "OSM resources init failed, rc=%d\n", rc); return rc; } rc = clk_osm_acd_resources_init(pdev); if (rc) { dev_err(&pdev->dev, "ACD resources init failed, rc=%d\n", rc); return rc; } rc = clk_osm_resolve_open_loop_voltages(&l3_clk); if (rc) { if (rc == -EPROBE_DEFER) Loading Loading @@ -3352,6 +3333,7 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev) static const struct of_device_id match_table[] = { { .compatible = "qcom,clk-cpu-osm" }, { .compatible = "qcom,clk-cpu-osm-v2" }, {} }; Loading Loading
Documentation/devicetree/bindings/arm/msm/qcom,osm.txt +1 −23 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ Properties: - compatible Usage: required Value type: <string> Definition: must be "qcom,clk-cpu-osm". Definition: must be "qcom,clk-cpu-osm" or "qcom,clk-cpu-osm-v2". - reg Usage: required Loading Loading @@ -85,24 +85,6 @@ Properties: by the OSM hardware for each supported DCVS setpoint of the Performance cluster. - qcom,l3-min-cpr-vc-binX Usage: required Value type: <u32> Definition: First virtual corner which does not use PLL post-divider for the L3 clock domain. - qcom,pwrcl-min-cpr-vc-binX Usage: required Value type: <u32> Definition: First virtual corner which does not use PLL post-divider for the power cluster. - qcom,perfcl-min-cpr-vc-binX Usage: required Value type: <u32> Definition: First virtual corner which does not use PLL post-divider for the performance cluster. - qcom,osm-no-tz Usage: optional Value type: <empty> Loading Loading @@ -501,10 +483,6 @@ Example: < 1881600000 0x404c1462 0x00004e4e 0x2 21 >, < 1958400000 0x404c1566 0x00005252 0x3 22 >; qcom,l3-min-cpr-vc-bin0 = <7>; qcom,pwrcl-min-cpr-vc-bin0 = <6>; qcom,perfcl-min-cpr-vc-bin0 = <7>; qcom,up-timer = <1000 1000 1000>; qcom,down-timer = Loading
drivers/clk/qcom/clk-cpu-osm.c +59 −77 Original line number Diff line number Diff line Loading @@ -150,12 +150,17 @@ #define DATA_MEM(n) (0x400 + (n) * 4) #define DCVS_PERF_STATE_DESIRED_REG_0 0x780 #define DCVS_PERF_STATE_DESIRED_REG(n) (DCVS_PERF_STATE_DESIRED_REG_0 + \ (4 * n)) #define OSM_CYCLE_COUNTER_STATUS_REG_0 0x7d0 #define OSM_CYCLE_COUNTER_STATUS_REG(n) (OSM_CYCLE_COUNTER_STATUS_REG_0 + \ (4 * n)) #define DCVS_PERF_STATE_DESIRED_REG_0_V1 0x780 #define DCVS_PERF_STATE_DESIRED_REG_0_V2 0x920 #define DCVS_PERF_STATE_DESIRED_REG(n, v2) \ (((v2) ? DCVS_PERF_STATE_DESIRED_REG_0_V2 \ : DCVS_PERF_STATE_DESIRED_REG_0_V1) + 4 * (n)) #define OSM_CYCLE_COUNTER_STATUS_REG_0_V1 0x7d0 #define OSM_CYCLE_COUNTER_STATUS_REG_0_V2 0x9c0 #define OSM_CYCLE_COUNTER_STATUS_REG(n, v2) \ (((v2) ? OSM_CYCLE_COUNTER_STATUS_REG_0_V2 \ : OSM_CYCLE_COUNTER_STATUS_REG_0_V1) + 4 * (n)) /* ACD registers */ #define ACD_HW_VERSION 0x0 Loading Loading @@ -444,6 +449,8 @@ static int clk_osm_acd_auto_local_write_reg(struct clk_osm *c, u32 mask) return 0; } static bool is_v2; static inline struct clk_osm *to_clk_osm(struct clk_hw *_hw) { return container_of(_hw, struct clk_osm, hw); Loading Loading @@ -604,7 +611,7 @@ static int l3_clk_set_rate(struct clk_hw *hw, unsigned long rate, } pr_debug("rate: %lu --> index %d\n", rate, index); clk_osm_write_reg(cpuclk, index, DCVS_PERF_STATE_DESIRED_REG_0, clk_osm_write_reg(cpuclk, index, DCVS_PERF_STATE_DESIRED_REG(0, is_v2), OSM_BASE); /* Make sure the write goes through before proceeding */ Loading @@ -622,7 +629,7 @@ static unsigned long l3_clk_recalc_rate(struct clk_hw *hw, if (!cpuclk) return -EINVAL; index = clk_osm_read_reg(cpuclk, DCVS_PERF_STATE_DESIRED_REG_0); index = clk_osm_read_reg(cpuclk, DCVS_PERF_STATE_DESIRED_REG(0, is_v2)); pr_debug("%s: Index %d, freq %ld\n", __func__, index, cpuclk->osm_table[index].frequency); Loading Loading @@ -890,7 +897,8 @@ static struct clk_osm *osm_configure_policy(struct cpufreq_policy *policy) static void osm_set_index(struct clk_osm *c, unsigned int index, unsigned int num) { clk_osm_write_reg(c, index, DCVS_PERF_STATE_DESIRED_REG(num), OSM_BASE); clk_osm_write_reg(c, index, DCVS_PERF_STATE_DESIRED_REG(num, is_v2), OSM_BASE); /* Make sure the write goes through before proceeding */ clk_osm_mb(c, OSM_BASE); Loading @@ -915,8 +923,8 @@ static unsigned int osm_cpufreq_get(unsigned int cpu) return 0; c = policy->driver_data; index = clk_osm_read_reg(c, DCVS_PERF_STATE_DESIRED_REG(c->core_num)); index = clk_osm_read_reg(c, DCVS_PERF_STATE_DESIRED_REG(c->core_num, is_v2)); return policy->freq_table[index].frequency; } Loading Loading @@ -1872,6 +1880,7 @@ static void populate_opp_table(struct platform_device *pdev) static u64 clk_osm_get_cpu_cycle_counter(int cpu) { u32 val; int core_num; unsigned long flags; struct clk_osm *parent, *c = logical_cpu_to_clk(cpu); Loading @@ -1887,12 +1896,9 @@ static u64 clk_osm_get_cpu_cycle_counter(int cpu) * Use core 0's copy as proxy for the whole cluster when per * core DCVS is disabled. */ if (parent->per_core_dcvs) val = clk_osm_read_reg_no_log(parent, OSM_CYCLE_COUNTER_STATUS_REG(c->core_num)); else core_num = parent->per_core_dcvs ? c->core_num : 0; val = clk_osm_read_reg_no_log(parent, OSM_CYCLE_COUNTER_STATUS_REG(0)); OSM_CYCLE_COUNTER_STATUS_REG(core_num, is_v2)); if (val < c->prev_cycle_counter) { /* Handle counter overflow */ Loading Loading @@ -2061,6 +2067,10 @@ static int clk_osm_get_lut(struct platform_device *pdev, c->osm_table[j].override_data, c->osm_table[j].mem_acc_level); data = (array[i + FREQ_DATA] & GENMASK(29, 28)) >> 28; if (j && !c->min_cpr_vc && !data) c->min_cpr_vc = c->osm_table[j].virtual_corner; data = (array[i + FREQ_DATA] & GENMASK(18, 16)) >> 16; if (!last_entry && data == MAX_CORE_COUNT) { fmax_temp[k] = array[i]; Loading Loading @@ -2243,9 +2253,6 @@ static int clk_osm_parse_dt_configs(struct platform_device *pdev) u32 *array; int rc = 0; struct resource *res; char l3_min_cpr_vc_str[] = "qcom,l3-min-cpr-vc-bin0"; char pwrcl_min_cpr_vc_str[] = "qcom,pwrcl-min-cpr-vc-bin0"; char perfcl_min_cpr_vc_str[] = "qcom,perfcl-min-cpr-vc-bin0"; array = devm_kzalloc(&pdev->dev, MAX_CLUSTER_CNT * sizeof(u32), GFP_KERNEL); Loading Loading @@ -2463,35 +2470,6 @@ static int clk_osm_parse_dt_configs(struct platform_device *pdev) return -ENOMEM; } snprintf(l3_min_cpr_vc_str, ARRAY_SIZE(l3_min_cpr_vc_str), "qcom,l3-min-cpr-vc-bin%d", l3_clk.speedbin); rc = of_property_read_u32(of, l3_min_cpr_vc_str, &l3_clk.min_cpr_vc); if (rc) { dev_err(&pdev->dev, "unable to find %s property, rc=%d\n", l3_min_cpr_vc_str, rc); return -EINVAL; } snprintf(pwrcl_min_cpr_vc_str, ARRAY_SIZE(pwrcl_min_cpr_vc_str), "qcom,pwrcl-min-cpr-vc-bin%d", pwrcl_clk.speedbin); rc = of_property_read_u32(of, pwrcl_min_cpr_vc_str, &pwrcl_clk.min_cpr_vc); if (rc) { dev_err(&pdev->dev, "unable to find %s property, rc=%d\n", pwrcl_min_cpr_vc_str, rc); return -EINVAL; } snprintf(perfcl_min_cpr_vc_str, ARRAY_SIZE(perfcl_min_cpr_vc_str), "qcom,perfcl-min-cpr-vc-bin%d", perfcl_clk.speedbin); rc = of_property_read_u32(of, perfcl_min_cpr_vc_str, &perfcl_clk.min_cpr_vc); if (rc) { dev_err(&pdev->dev, "unable to find %s property, rc=%d\n", perfcl_min_cpr_vc_str, rc); return -EINVAL; } l3_clk.secure_init = perfcl_clk.secure_init = pwrcl_clk.secure_init = of_property_read_bool(pdev->dev.of_node, "qcom,osm-no-tz"); Loading Loading @@ -3025,6 +3003,9 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev) return PTR_ERR(ext_xo_clk); } is_v2 = of_device_is_compatible(pdev->dev.of_node, "qcom,clk-cpu-osm-v2"); clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data), GFP_KERNEL); if (!clk_data) Loading @@ -3037,33 +3018,6 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev) clk_data->clk_num = num_clks; rc = clk_osm_parse_dt_configs(pdev); if (rc) { dev_err(&pdev->dev, "Unable to parse OSM device tree configurations\n"); return rc; } rc = clk_osm_parse_acd_dt_configs(pdev); if (rc) { dev_err(&pdev->dev, "Unable to parse ACD device tree configurations\n"); return rc; } rc = clk_osm_resources_init(pdev); if (rc) { if (rc != -EPROBE_DEFER) dev_err(&pdev->dev, "OSM resources init failed, rc=%d\n", rc); return rc; } rc = clk_osm_acd_resources_init(pdev); if (rc) { dev_err(&pdev->dev, "ACD resources init failed, rc=%d\n", rc); return rc; } if (l3_clk.vbases[EFUSE_BASE]) { /* Multiple speed-bins are supported */ pte_efuse = readl_relaxed(l3_clk.vbases[EFUSE_BASE]); Loading Loading @@ -3123,6 +3077,33 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev) return rc; } rc = clk_osm_parse_dt_configs(pdev); if (rc) { dev_err(&pdev->dev, "Unable to parse OSM device tree configurations\n"); return rc; } rc = clk_osm_parse_acd_dt_configs(pdev); if (rc) { dev_err(&pdev->dev, "Unable to parse ACD device tree configurations\n"); return rc; } rc = clk_osm_resources_init(pdev); if (rc) { if (rc != -EPROBE_DEFER) dev_err(&pdev->dev, "OSM resources init failed, rc=%d\n", rc); return rc; } rc = clk_osm_acd_resources_init(pdev); if (rc) { dev_err(&pdev->dev, "ACD resources init failed, rc=%d\n", rc); return rc; } rc = clk_osm_resolve_open_loop_voltages(&l3_clk); if (rc) { if (rc == -EPROBE_DEFER) Loading Loading @@ -3352,6 +3333,7 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev) static const struct of_device_id match_table[] = { { .compatible = "qcom,clk-cpu-osm" }, { .compatible = "qcom,clk-cpu-osm-v2" }, {} }; Loading