Loading Documentation/devicetree/bindings/regulator/cprh-kbss-regulator.txt +2 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,8 @@ KBSS specific properties: "qcom,cprh-msm8998-v1-kbss-regulator", "qcom,cprh-msm8998-v2-kbss-regulator", "qcom,cprh-msm8998-kbss-regulator", "qcom,cprh-sdm660-kbss-regulator". "qcom,cprh-sdm660-kbss-regulator", "qcom,cprh-sdm630-kbss-regulator". If the SoC revision is not specified, then it is assumed to be the most recent revision of MSM8998, i.e. v2. Loading arch/arm/boot/dts/qcom/sdm630-regulator.dtsi +203 −0 Original line number Diff line number Diff line Loading @@ -633,4 +633,207 @@ }; }; }; /* APC0 CPR Controller node for Silver cluster */ apc0_cpr: cprh-ctrl@179c8000 { compatible = "qcom,cprh-sdm630-kbss-regulator"; reg = <0x179c8000 0x4000>, <0x00784000 0x1000>; reg-names = "cpr_ctrl", "fuse_base"; clocks = <&clock_gcc GCC_HMSS_RBCPR_CLK>; clock-names = "core_clk"; qcom,cpr-ctrl-name = "apc0"; qcom,cpr-controller-id = <0>; qcom,cpr-sensor-time = <1000>; qcom,cpr-loop-time = <5000000>; qcom,cpr-idle-cycles = <15>; qcom,cpr-up-down-delay-time = <3000>; qcom,cpr-step-quot-init-min = <12>; qcom,cpr-step-quot-init-max = <14>; qcom,cpr-count-mode = <0>; /* All at once */ qcom,cpr-count-repeat = <14>; qcom,cpr-down-error-step-limit = <1>; qcom,cpr-up-error-step-limit = <1>; qcom,cpr-corner-switch-delay-time = <1042>; qcom,cpr-voltage-settling-time = <1760>; qcom,apm-threshold-voltage = <872000>; qcom,apm-crossover-voltage = <872000>; qcom,apm-hysteresis-voltage = <20000>; qcom,voltage-step = <4000>; qcom,voltage-base = <400000>; qcom,cpr-saw-use-unit-mV; qcom,cpr-panic-reg-addr-list = <0x179cbaa4 0x17912c18>; qcom,cpr-panic-reg-name-list = "PWR_CPRH_STATUS", "APCLUS0_L2_SAW4_PMIC_STS"; thread@0 { qcom,cpr-thread-id = <0>; qcom,cpr-consecutive-up = <0>; qcom,cpr-consecutive-down = <2>; qcom,cpr-up-threshold = <2>; qcom,cpr-down-threshold = <2>; apc0_pwrcl_vreg: regulator { regulator-name = "apc0_pwrcl_corner"; regulator-min-microvolt = <1>; regulator-max-microvolt = <8>; qcom,cpr-fuse-corners = <4>; qcom,cpr-fuse-combos = <24>; qcom,cpr-speed-bins = <3>; qcom,cpr-speed-bin-corners = <8 8 8>; qcom,cpr-corners = <8>; qcom,cpr-corner-fmax-map = <2 4 5 8>; qcom,cpr-voltage-ceiling = <724000 724000 724000 788000 868000 924000 988000 1068000>; qcom,cpr-voltage-floor = <588000 588000 596000 652000 712000 744000 784000 844000>; qcom,corner-frequencies = <300000000 614400000 883200000 1094400000 1382400000 1536000000 1728000000 1843200000>; qcom,allow-voltage-interpolation; qcom,allow-quotient-interpolation; qcom,cpr-scaled-open-loop-voltage-as-ceiling; }; }; }; /* APC1 CPR Controller node for Gold cluster */ apc1_cpr: cprh-ctrl@179c4000 { compatible = "qcom,cprh-sdm630-kbss-regulator"; reg = <0x179c4000 0x4000>, <0x00784000 0x1000>; reg-names = "cpr_ctrl", "fuse_base"; clocks = <&clock_gcc GCC_HMSS_RBCPR_CLK>; clock-names = "core_clk"; qcom,cpr-ctrl-name = "apc1"; qcom,cpr-controller-id = <1>; qcom,cpr-sensor-time = <1000>; qcom,cpr-loop-time = <5000000>; qcom,cpr-idle-cycles = <15>; qcom,cpr-up-down-delay-time = <3000>; qcom,cpr-step-quot-init-min = <12>; qcom,cpr-step-quot-init-max = <14>; qcom,cpr-count-mode = <0>; /* All at once */ qcom,cpr-count-repeat = <14>; qcom,cpr-down-error-step-limit = <1>; qcom,cpr-up-error-step-limit = <1>; qcom,cpr-corner-switch-delay-time = <1042>; qcom,cpr-voltage-settling-time = <1760>; qcom,apm-threshold-voltage = <872000>; qcom,apm-crossover-voltage = <872000>; qcom,apm-hysteresis-voltage = <20000>; qcom,voltage-step = <4000>; qcom,voltage-base = <400000>; qcom,cpr-saw-use-unit-mV; qcom,cpr-panic-reg-addr-list = <0x179c7aa4 0x17812c18>; qcom,cpr-panic-reg-name-list = "PERF_CPRH_STATUS", "APCLUS1_L2_SAW4_PMIC_STS"; thread@0 { qcom,cpr-thread-id = <0>; qcom,cpr-consecutive-up = <0>; qcom,cpr-consecutive-down = <2>; qcom,cpr-up-threshold = <2>; qcom,cpr-down-threshold = <2>; apc1_perfcl_vreg: regulator { regulator-name = "apc1_perfcl_corner"; regulator-min-microvolt = <1>; regulator-max-microvolt = <11>; qcom,cpr-fuse-corners = <4>; qcom,cpr-fuse-combos = <24>; qcom,cpr-speed-bins = <3>; qcom,cpr-speed-bin-corners = <10 10 11>; qcom,cpr-corners = /* Speed bin 0 */ <10 10 10 10 10 10 10 10>, /* Speed bin 1 */ <10 10 10 10 10 10 10 10>, /* Speed bin 2 */ <11 11 11 11 11 11 11 11>; qcom,cpr-corner-fmax-map = /* Speed bin 0 */ <2 4 6 10>, /* Speed bin 1 */ <2 4 6 10>, /* Speed bin 2 */ <2 4 6 11>; qcom,cpr-voltage-ceiling = /* Speed bin 0 */ <724000 724000 724000 788000 868000 868000 924000 988000 988000 1068000>, /* Speed bin 1 */ <724000 724000 724000 788000 868000 868000 924000 988000 988000 1068000>, /* Speed bin 2 */ <724000 724000 724000 788000 868000 868000 924000 988000 988000 1068000 1140000>; qcom,cpr-voltage-floor = /* Speed bin 0 */ <588000 588000 596000 652000 712000 712000 744000 784000 784000 844000>, /* Speed bin 1 */ <588000 588000 596000 652000 712000 712000 744000 784000 784000 844000>, /* Speed bin 2 */ <588000 588000 596000 652000 712000 712000 744000 784000 784000 844000 900000>; qcom,corner-frequencies = /* Speed bin 0 */ <300000000 787200000 1113600000 1344000000 1516800000 1670400000 1881600000 2016000000 2150400000 2380800000>, /* Speed bin 1 */ <300000000 787200000 1113600000 1344000000 1516800000 1670400000 1881600000 2016000000 2150400000 2208000000>, /* Speed bin 2 */ <300000000 787200000 1113600000 1344000000 1516800000 1670400000 1881600000 2016000000 2150400000 2208000000 2515200000>; qcom,allow-voltage-interpolation; qcom,allow-quotient-interpolation; qcom,cpr-scaled-open-loop-voltage-as-ceiling; }; }; }; }; drivers/regulator/cprh-kbss-regulator.c +243 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ #define MSM8998_KBSS_FUSE_CORNERS 4 #define SDM660_KBSS_FUSE_CORNERS 5 #define SDM630_KBSS_FUSE_CORNERS 4 /** * struct cprh_kbss_fuses - KBSS specific fuse data Loading Loading @@ -79,6 +80,7 @@ struct cprh_kbss_fuses { */ #define CPRH_MSM8998_KBSS_FUSE_COMBO_COUNT 32 #define CPRH_SDM660_KBSS_FUSE_COMBO_COUNT 16 #define CPRH_SDM630_KBSS_FUSE_COMBO_COUNT 24 /* * Constants which define the name of each fuse corner. Loading Loading @@ -129,6 +131,20 @@ static const char * const cprh_sdm660_perf_kbss_fuse_corner_name[] = { [CPRH_SDM660_PERF_KBSS_FUSE_CORNER_TURBO_L2] = "TURBO_L2", }; enum cprh_sdm630_kbss_fuse_corner { CPRH_SDM630_KBSS_FUSE_CORNER_LOWSVS = 0, CPRH_SDM630_KBSS_FUSE_CORNER_SVSPLUS = 1, CPRH_SDM630_KBSS_FUSE_CORNER_NOM = 2, CPRH_SDM630_KBSS_FUSE_CORNER_TURBO_L1 = 3, }; static const char * const cprh_sdm630_kbss_fuse_corner_name[] = { [CPRH_SDM630_KBSS_FUSE_CORNER_LOWSVS] = "LowSVS", [CPRH_SDM630_KBSS_FUSE_CORNER_SVSPLUS] = "SVSPLUS", [CPRH_SDM630_KBSS_FUSE_CORNER_NOM] = "NOM", [CPRH_SDM630_KBSS_FUSE_CORNER_TURBO_L1] = "TURBO_L1", }; /* KBSS cluster IDs */ #define CPRH_KBSS_POWER_CLUSTER_ID 0 #define CPRH_KBSS_PERFORMANCE_CLUSTER_ID 1 Loading Loading @@ -185,6 +201,22 @@ sdm660_kbss_ro_sel_param[2][SDM660_KBSS_FUSE_CORNERS][3] = { }, }; static const struct cpr3_fuse_param sdm630_kbss_ro_sel_param[2][SDM630_KBSS_FUSE_CORNERS][3] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { {{67, 12, 15}, {} }, {{65, 56, 59}, {} }, {{67, 4, 7}, {} }, {{67, 0, 3}, {} }, }, [CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = { {{68, 61, 63}, {69, 0, 0} }, {{69, 1, 4}, {} }, {{68, 57, 60}, {} }, {{66, 14, 17}, {} }, }, }; static const struct cpr3_fuse_param msm8998_kbss_init_voltage_param[2][MSM8998_KBSS_FUSE_CORNERS][2] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { Loading Loading @@ -219,6 +251,22 @@ sdm660_kbss_init_voltage_param[2][SDM660_KBSS_FUSE_CORNERS][2] = { }, }; static const struct cpr3_fuse_param sdm630_kbss_init_voltage_param[2][SDM630_KBSS_FUSE_CORNERS][2] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { {{67, 34, 39}, {} }, {{71, 3, 8}, {} }, {{67, 22, 27}, {} }, {{67, 16, 21}, {} }, }, [CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = { {{69, 17, 22}, {} }, {{69, 23, 28}, {} }, {{69, 11, 16}, {} }, {{70, 42, 47}, {} }, }, }; static const struct cpr3_fuse_param msm8998_kbss_target_quot_param[2][MSM8998_KBSS_FUSE_CORNERS][3] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { Loading Loading @@ -253,6 +301,22 @@ sdm660_kbss_target_quot_param[2][SDM660_KBSS_FUSE_CORNERS][3] = { }, }; static const struct cpr3_fuse_param sdm630_kbss_target_quot_param[2][SDM630_KBSS_FUSE_CORNERS][3] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { {{68, 12, 23}, {} }, {{71, 9, 20}, {} }, {{67, 52, 63}, {} }, {{67, 40, 51}, {} }, }, [CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = { {{69, 53, 63}, {70, 0, 0}, {} }, {{70, 1, 12}, {} }, {{69, 41, 52}, {} }, {{70, 48, 59}, {} }, }, }; static const struct cpr3_fuse_param msm8998_kbss_quot_offset_param[2][MSM8998_KBSS_FUSE_CORNERS][3] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { Loading Loading @@ -287,6 +351,22 @@ sdm660_kbss_quot_offset_param[2][SDM660_KBSS_FUSE_CORNERS][3] = { }, }; static const struct cpr3_fuse_param sdm630_kbss_quot_offset_param[2][SDM630_KBSS_FUSE_CORNERS][3] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { {{} }, {{71, 21, 27}, {} }, {{68, 31, 37}, {} }, {{68, 24, 30}, {} }, }, [CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = { {{} }, {{70, 27, 33}, {} }, {{70, 20, 26}, {} }, {{70, 60, 63}, {71, 0, 2}, {} }, }, }; static const struct cpr3_fuse_param msm8998_cpr_fusing_rev_param[] = { {39, 51, 53}, {}, Loading @@ -297,6 +377,11 @@ static const struct cpr3_fuse_param sdm660_cpr_fusing_rev_param[] = { {}, }; static const struct cpr3_fuse_param sdm630_cpr_fusing_rev_param[] = { {71, 28, 30}, {}, }; static const struct cpr3_fuse_param kbss_speed_bin_param[] = { {38, 29, 31}, {}, Loading Loading @@ -332,6 +417,18 @@ sdm660_kbss_aging_init_quot_diff_param[2][2] = { }, }; static const struct cpr3_fuse_param sdm630_kbss_aging_init_quot_diff_param[2][2] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { {68, 45, 52}, {}, }, [CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = { {70, 34, 41}, {}, }, }; /* * Open loop voltage fuse reference voltages in microvolts for MSM8998 v1 */ Loading Loading @@ -383,6 +480,25 @@ sdm660_kbss_fuse_ref_volt[2][SDM660_KBSS_FUSE_CORNERS] = { }, }; /* * Open loop voltage fuse reference voltages in microvolts for SDM630 */ static const int sdm630_kbss_fuse_ref_volt[SDM630_KBSS_FUSE_CORNERS] = { 644000, 788000, 868000, 1068000, }; static const int sdm630_kbss_speed_bin_2_fuse_ref_volt[SDM630_KBSS_FUSE_CORNERS] = { 644000, 788000, 868000, 1140000, }; #define CPRH_KBSS_FUSE_STEP_VOLT 10000 #define CPRH_KBSS_VOLTAGE_FUSE_SIZE 6 #define CPRH_KBSS_QUOT_OFFSET_SCALE 5 Loading Loading @@ -432,6 +548,12 @@ sdm660_kbss_fuse_ref_volt[2][SDM660_KBSS_FUSE_CORNERS] = { #define SDM660_KBSS_PERFORMANCE_AGING_SENSOR_ID 0 #define SDM660_KBSS_PERFORMANCE_AGING_BYPASS_MASK0 0 /* * sdm630 configuration */ #define SDM630_KBSS_POWER_CPR_SENSOR_COUNT 6 #define SDM630_KBSS_PERFORMANCE_CPR_SENSOR_COUNT 9 /* * SOC IDs */ Loading @@ -439,6 +561,7 @@ enum soc_id { MSM8998_V1_SOC_ID = 1, MSM8998_V2_SOC_ID = 2, SDM660_SOC_ID = 3, SDM630_SOC_ID = 4, }; /** Loading Loading @@ -622,6 +745,90 @@ static int cprh_sdm660_kbss_read_fuse_data(struct cpr3_regulator *vreg, return rc; }; /** * cprh_sdm630_kbss_read_fuse_data() - load SDM630 KBSS specific fuse parameter * values * @vreg: Pointer to the CPR3 regulator * @fuse: KBSS specific fuse data * * This function fills cprh_kbss_fuses struct with values read out of hardware * fuses. * * Return: 0 on success, errno on failure */ static int cprh_sdm630_kbss_read_fuse_data(struct cpr3_regulator *vreg, struct cprh_kbss_fuses *fuse) { void __iomem *base = vreg->thread->ctrl->fuse_base; int i, id, rc; rc = cpr3_read_fuse_param(base, sdm630_cpr_fusing_rev_param, &fuse->cpr_fusing_rev); if (rc) { cpr3_err(vreg, "Unable to read CPR fusing revision fuse, rc=%d\n", rc); return rc; } cpr3_info(vreg, "CPR fusing revision = %llu\n", fuse->cpr_fusing_rev); id = vreg->thread->ctrl->ctrl_id; for (i = 0; i < SDM630_KBSS_FUSE_CORNERS; i++) { rc = cpr3_read_fuse_param(base, sdm630_kbss_init_voltage_param[id][i], &fuse->init_voltage[i]); if (rc) { cpr3_err(vreg, "Unable to read fuse-corner %d initial voltage fuse, rc=%d\n", i, rc); return rc; } rc = cpr3_read_fuse_param(base, sdm630_kbss_target_quot_param[id][i], &fuse->target_quot[i]); if (rc) { cpr3_err(vreg, "Unable to read fuse-corner %d target quotient fuse, rc=%d\n", i, rc); return rc; } rc = cpr3_read_fuse_param(base, sdm630_kbss_ro_sel_param[id][i], &fuse->ro_sel[i]); if (rc) { cpr3_err(vreg, "Unable to read fuse-corner %d RO select fuse, rc=%d\n", i, rc); return rc; } rc = cpr3_read_fuse_param(base, sdm630_kbss_quot_offset_param[id][i], &fuse->quot_offset[i]); if (rc) { cpr3_err(vreg, "Unable to read fuse-corner %d quotient offset fuse, rc=%d\n", i, rc); return rc; } } rc = cpr3_read_fuse_param(base, sdm630_kbss_aging_init_quot_diff_param[id], &fuse->aging_init_quot_diff); if (rc) { cpr3_err(vreg, "Unable to read aging initial quotient difference fuse, rc=%d\n", rc); return rc; } vreg->fuse_combo = fuse->cpr_fusing_rev + 8 * fuse->speed_bin; if (vreg->fuse_combo >= CPRH_SDM630_KBSS_FUSE_COMBO_COUNT) { cpr3_err(vreg, "invalid CPR fuse combo = %d found\n", vreg->fuse_combo); return -EINVAL; } return rc; }; /** * cprh_kbss_read_fuse_data() - load KBSS specific fuse parameter values * @vreg: Pointer to the CPR3 regulator Loading @@ -648,6 +855,9 @@ static int cprh_kbss_read_fuse_data(struct cpr3_regulator *vreg) case SDM660_SOC_ID: fuse_corners = SDM660_KBSS_FUSE_CORNERS; break; case SDM630_SOC_ID: fuse_corners = SDM630_KBSS_FUSE_CORNERS; break; case MSM8998_V1_SOC_ID: case MSM8998_V2_SOC_ID: fuse_corners = MSM8998_KBSS_FUSE_CORNERS; Loading Loading @@ -686,6 +896,14 @@ static int cprh_kbss_read_fuse_data(struct cpr3_regulator *vreg) return rc; } break; case SDM630_SOC_ID: rc = cprh_sdm630_kbss_read_fuse_data(vreg, fuse); if (rc) { cpr3_err(vreg, "sdm630 kbss fuse data read failed, rc=%d\n", rc); return rc; } break; case MSM8998_V1_SOC_ID: case MSM8998_V2_SOC_ID: rc = cprh_msm8998_kbss_read_fuse_data(vreg, fuse); Loading Loading @@ -789,6 +1007,12 @@ static int cprh_kbss_calculate_open_loop_voltages(struct cpr3_regulator *vreg) else corner_name = cprh_sdm660_perf_kbss_fuse_corner_name; break; case SDM630_SOC_ID: ref_volt = sdm630_kbss_fuse_ref_volt; if (vreg->speed_bin_fuse == 2) ref_volt = sdm630_kbss_speed_bin_2_fuse_ref_volt; corner_name = cprh_sdm630_kbss_fuse_corner_name; break; case MSM8998_V1_SOC_ID: ref_volt = msm8998_v1_kbss_fuse_ref_volt; corner_name = cprh_msm8998_kbss_fuse_corner_name; Loading Loading @@ -1356,6 +1580,13 @@ static int cprh_kbss_calculate_target_quotients(struct cpr3_regulator *vreg) CPRH_SDM660_PERF_KBSS_FUSE_CORNER_TURBO_L2; } break; case SDM630_SOC_ID: corner_name = cprh_sdm630_kbss_fuse_corner_name; lowest_fuse_corner = CPRH_SDM630_KBSS_FUSE_CORNER_LOWSVS; highest_fuse_corner = CPRH_SDM630_KBSS_FUSE_CORNER_TURBO_L1; break; case MSM8998_V1_SOC_ID: case MSM8998_V2_SOC_ID: corner_name = cprh_msm8998_kbss_fuse_corner_name; Loading Loading @@ -1923,6 +2154,14 @@ static int cprh_kbss_init_controller(struct cpr3_controller *ctrl) ctrl->sensor_count = SDM660_KBSS_PERFORMANCE_CPR_SENSOR_COUNT; break; case SDM630_SOC_ID: if (ctrl->ctrl_id == CPRH_KBSS_POWER_CLUSTER_ID) ctrl->sensor_count = SDM630_KBSS_POWER_CPR_SENSOR_COUNT; else ctrl->sensor_count = SDM630_KBSS_PERFORMANCE_CPR_SENSOR_COUNT; break; case MSM8998_V1_SOC_ID: case MSM8998_V2_SOC_ID: if (ctrl->ctrl_id == CPRH_KBSS_POWER_CLUSTER_ID) Loading Loading @@ -2024,6 +2263,10 @@ static const struct of_device_id cprh_regulator_match_table[] = { .compatible = "qcom,cprh-sdm660-kbss-regulator", .data = (void *)(uintptr_t)SDM660_SOC_ID, }, { .compatible = "qcom,cprh-sdm630-kbss-regulator", .data = (void *)(uintptr_t)SDM630_SOC_ID, }, {} }; Loading Loading
Documentation/devicetree/bindings/regulator/cprh-kbss-regulator.txt +2 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,8 @@ KBSS specific properties: "qcom,cprh-msm8998-v1-kbss-regulator", "qcom,cprh-msm8998-v2-kbss-regulator", "qcom,cprh-msm8998-kbss-regulator", "qcom,cprh-sdm660-kbss-regulator". "qcom,cprh-sdm660-kbss-regulator", "qcom,cprh-sdm630-kbss-regulator". If the SoC revision is not specified, then it is assumed to be the most recent revision of MSM8998, i.e. v2. Loading
arch/arm/boot/dts/qcom/sdm630-regulator.dtsi +203 −0 Original line number Diff line number Diff line Loading @@ -633,4 +633,207 @@ }; }; }; /* APC0 CPR Controller node for Silver cluster */ apc0_cpr: cprh-ctrl@179c8000 { compatible = "qcom,cprh-sdm630-kbss-regulator"; reg = <0x179c8000 0x4000>, <0x00784000 0x1000>; reg-names = "cpr_ctrl", "fuse_base"; clocks = <&clock_gcc GCC_HMSS_RBCPR_CLK>; clock-names = "core_clk"; qcom,cpr-ctrl-name = "apc0"; qcom,cpr-controller-id = <0>; qcom,cpr-sensor-time = <1000>; qcom,cpr-loop-time = <5000000>; qcom,cpr-idle-cycles = <15>; qcom,cpr-up-down-delay-time = <3000>; qcom,cpr-step-quot-init-min = <12>; qcom,cpr-step-quot-init-max = <14>; qcom,cpr-count-mode = <0>; /* All at once */ qcom,cpr-count-repeat = <14>; qcom,cpr-down-error-step-limit = <1>; qcom,cpr-up-error-step-limit = <1>; qcom,cpr-corner-switch-delay-time = <1042>; qcom,cpr-voltage-settling-time = <1760>; qcom,apm-threshold-voltage = <872000>; qcom,apm-crossover-voltage = <872000>; qcom,apm-hysteresis-voltage = <20000>; qcom,voltage-step = <4000>; qcom,voltage-base = <400000>; qcom,cpr-saw-use-unit-mV; qcom,cpr-panic-reg-addr-list = <0x179cbaa4 0x17912c18>; qcom,cpr-panic-reg-name-list = "PWR_CPRH_STATUS", "APCLUS0_L2_SAW4_PMIC_STS"; thread@0 { qcom,cpr-thread-id = <0>; qcom,cpr-consecutive-up = <0>; qcom,cpr-consecutive-down = <2>; qcom,cpr-up-threshold = <2>; qcom,cpr-down-threshold = <2>; apc0_pwrcl_vreg: regulator { regulator-name = "apc0_pwrcl_corner"; regulator-min-microvolt = <1>; regulator-max-microvolt = <8>; qcom,cpr-fuse-corners = <4>; qcom,cpr-fuse-combos = <24>; qcom,cpr-speed-bins = <3>; qcom,cpr-speed-bin-corners = <8 8 8>; qcom,cpr-corners = <8>; qcom,cpr-corner-fmax-map = <2 4 5 8>; qcom,cpr-voltage-ceiling = <724000 724000 724000 788000 868000 924000 988000 1068000>; qcom,cpr-voltage-floor = <588000 588000 596000 652000 712000 744000 784000 844000>; qcom,corner-frequencies = <300000000 614400000 883200000 1094400000 1382400000 1536000000 1728000000 1843200000>; qcom,allow-voltage-interpolation; qcom,allow-quotient-interpolation; qcom,cpr-scaled-open-loop-voltage-as-ceiling; }; }; }; /* APC1 CPR Controller node for Gold cluster */ apc1_cpr: cprh-ctrl@179c4000 { compatible = "qcom,cprh-sdm630-kbss-regulator"; reg = <0x179c4000 0x4000>, <0x00784000 0x1000>; reg-names = "cpr_ctrl", "fuse_base"; clocks = <&clock_gcc GCC_HMSS_RBCPR_CLK>; clock-names = "core_clk"; qcom,cpr-ctrl-name = "apc1"; qcom,cpr-controller-id = <1>; qcom,cpr-sensor-time = <1000>; qcom,cpr-loop-time = <5000000>; qcom,cpr-idle-cycles = <15>; qcom,cpr-up-down-delay-time = <3000>; qcom,cpr-step-quot-init-min = <12>; qcom,cpr-step-quot-init-max = <14>; qcom,cpr-count-mode = <0>; /* All at once */ qcom,cpr-count-repeat = <14>; qcom,cpr-down-error-step-limit = <1>; qcom,cpr-up-error-step-limit = <1>; qcom,cpr-corner-switch-delay-time = <1042>; qcom,cpr-voltage-settling-time = <1760>; qcom,apm-threshold-voltage = <872000>; qcom,apm-crossover-voltage = <872000>; qcom,apm-hysteresis-voltage = <20000>; qcom,voltage-step = <4000>; qcom,voltage-base = <400000>; qcom,cpr-saw-use-unit-mV; qcom,cpr-panic-reg-addr-list = <0x179c7aa4 0x17812c18>; qcom,cpr-panic-reg-name-list = "PERF_CPRH_STATUS", "APCLUS1_L2_SAW4_PMIC_STS"; thread@0 { qcom,cpr-thread-id = <0>; qcom,cpr-consecutive-up = <0>; qcom,cpr-consecutive-down = <2>; qcom,cpr-up-threshold = <2>; qcom,cpr-down-threshold = <2>; apc1_perfcl_vreg: regulator { regulator-name = "apc1_perfcl_corner"; regulator-min-microvolt = <1>; regulator-max-microvolt = <11>; qcom,cpr-fuse-corners = <4>; qcom,cpr-fuse-combos = <24>; qcom,cpr-speed-bins = <3>; qcom,cpr-speed-bin-corners = <10 10 11>; qcom,cpr-corners = /* Speed bin 0 */ <10 10 10 10 10 10 10 10>, /* Speed bin 1 */ <10 10 10 10 10 10 10 10>, /* Speed bin 2 */ <11 11 11 11 11 11 11 11>; qcom,cpr-corner-fmax-map = /* Speed bin 0 */ <2 4 6 10>, /* Speed bin 1 */ <2 4 6 10>, /* Speed bin 2 */ <2 4 6 11>; qcom,cpr-voltage-ceiling = /* Speed bin 0 */ <724000 724000 724000 788000 868000 868000 924000 988000 988000 1068000>, /* Speed bin 1 */ <724000 724000 724000 788000 868000 868000 924000 988000 988000 1068000>, /* Speed bin 2 */ <724000 724000 724000 788000 868000 868000 924000 988000 988000 1068000 1140000>; qcom,cpr-voltage-floor = /* Speed bin 0 */ <588000 588000 596000 652000 712000 712000 744000 784000 784000 844000>, /* Speed bin 1 */ <588000 588000 596000 652000 712000 712000 744000 784000 784000 844000>, /* Speed bin 2 */ <588000 588000 596000 652000 712000 712000 744000 784000 784000 844000 900000>; qcom,corner-frequencies = /* Speed bin 0 */ <300000000 787200000 1113600000 1344000000 1516800000 1670400000 1881600000 2016000000 2150400000 2380800000>, /* Speed bin 1 */ <300000000 787200000 1113600000 1344000000 1516800000 1670400000 1881600000 2016000000 2150400000 2208000000>, /* Speed bin 2 */ <300000000 787200000 1113600000 1344000000 1516800000 1670400000 1881600000 2016000000 2150400000 2208000000 2515200000>; qcom,allow-voltage-interpolation; qcom,allow-quotient-interpolation; qcom,cpr-scaled-open-loop-voltage-as-ceiling; }; }; }; };
drivers/regulator/cprh-kbss-regulator.c +243 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ #define MSM8998_KBSS_FUSE_CORNERS 4 #define SDM660_KBSS_FUSE_CORNERS 5 #define SDM630_KBSS_FUSE_CORNERS 4 /** * struct cprh_kbss_fuses - KBSS specific fuse data Loading Loading @@ -79,6 +80,7 @@ struct cprh_kbss_fuses { */ #define CPRH_MSM8998_KBSS_FUSE_COMBO_COUNT 32 #define CPRH_SDM660_KBSS_FUSE_COMBO_COUNT 16 #define CPRH_SDM630_KBSS_FUSE_COMBO_COUNT 24 /* * Constants which define the name of each fuse corner. Loading Loading @@ -129,6 +131,20 @@ static const char * const cprh_sdm660_perf_kbss_fuse_corner_name[] = { [CPRH_SDM660_PERF_KBSS_FUSE_CORNER_TURBO_L2] = "TURBO_L2", }; enum cprh_sdm630_kbss_fuse_corner { CPRH_SDM630_KBSS_FUSE_CORNER_LOWSVS = 0, CPRH_SDM630_KBSS_FUSE_CORNER_SVSPLUS = 1, CPRH_SDM630_KBSS_FUSE_CORNER_NOM = 2, CPRH_SDM630_KBSS_FUSE_CORNER_TURBO_L1 = 3, }; static const char * const cprh_sdm630_kbss_fuse_corner_name[] = { [CPRH_SDM630_KBSS_FUSE_CORNER_LOWSVS] = "LowSVS", [CPRH_SDM630_KBSS_FUSE_CORNER_SVSPLUS] = "SVSPLUS", [CPRH_SDM630_KBSS_FUSE_CORNER_NOM] = "NOM", [CPRH_SDM630_KBSS_FUSE_CORNER_TURBO_L1] = "TURBO_L1", }; /* KBSS cluster IDs */ #define CPRH_KBSS_POWER_CLUSTER_ID 0 #define CPRH_KBSS_PERFORMANCE_CLUSTER_ID 1 Loading Loading @@ -185,6 +201,22 @@ sdm660_kbss_ro_sel_param[2][SDM660_KBSS_FUSE_CORNERS][3] = { }, }; static const struct cpr3_fuse_param sdm630_kbss_ro_sel_param[2][SDM630_KBSS_FUSE_CORNERS][3] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { {{67, 12, 15}, {} }, {{65, 56, 59}, {} }, {{67, 4, 7}, {} }, {{67, 0, 3}, {} }, }, [CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = { {{68, 61, 63}, {69, 0, 0} }, {{69, 1, 4}, {} }, {{68, 57, 60}, {} }, {{66, 14, 17}, {} }, }, }; static const struct cpr3_fuse_param msm8998_kbss_init_voltage_param[2][MSM8998_KBSS_FUSE_CORNERS][2] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { Loading Loading @@ -219,6 +251,22 @@ sdm660_kbss_init_voltage_param[2][SDM660_KBSS_FUSE_CORNERS][2] = { }, }; static const struct cpr3_fuse_param sdm630_kbss_init_voltage_param[2][SDM630_KBSS_FUSE_CORNERS][2] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { {{67, 34, 39}, {} }, {{71, 3, 8}, {} }, {{67, 22, 27}, {} }, {{67, 16, 21}, {} }, }, [CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = { {{69, 17, 22}, {} }, {{69, 23, 28}, {} }, {{69, 11, 16}, {} }, {{70, 42, 47}, {} }, }, }; static const struct cpr3_fuse_param msm8998_kbss_target_quot_param[2][MSM8998_KBSS_FUSE_CORNERS][3] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { Loading Loading @@ -253,6 +301,22 @@ sdm660_kbss_target_quot_param[2][SDM660_KBSS_FUSE_CORNERS][3] = { }, }; static const struct cpr3_fuse_param sdm630_kbss_target_quot_param[2][SDM630_KBSS_FUSE_CORNERS][3] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { {{68, 12, 23}, {} }, {{71, 9, 20}, {} }, {{67, 52, 63}, {} }, {{67, 40, 51}, {} }, }, [CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = { {{69, 53, 63}, {70, 0, 0}, {} }, {{70, 1, 12}, {} }, {{69, 41, 52}, {} }, {{70, 48, 59}, {} }, }, }; static const struct cpr3_fuse_param msm8998_kbss_quot_offset_param[2][MSM8998_KBSS_FUSE_CORNERS][3] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { Loading Loading @@ -287,6 +351,22 @@ sdm660_kbss_quot_offset_param[2][SDM660_KBSS_FUSE_CORNERS][3] = { }, }; static const struct cpr3_fuse_param sdm630_kbss_quot_offset_param[2][SDM630_KBSS_FUSE_CORNERS][3] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { {{} }, {{71, 21, 27}, {} }, {{68, 31, 37}, {} }, {{68, 24, 30}, {} }, }, [CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = { {{} }, {{70, 27, 33}, {} }, {{70, 20, 26}, {} }, {{70, 60, 63}, {71, 0, 2}, {} }, }, }; static const struct cpr3_fuse_param msm8998_cpr_fusing_rev_param[] = { {39, 51, 53}, {}, Loading @@ -297,6 +377,11 @@ static const struct cpr3_fuse_param sdm660_cpr_fusing_rev_param[] = { {}, }; static const struct cpr3_fuse_param sdm630_cpr_fusing_rev_param[] = { {71, 28, 30}, {}, }; static const struct cpr3_fuse_param kbss_speed_bin_param[] = { {38, 29, 31}, {}, Loading Loading @@ -332,6 +417,18 @@ sdm660_kbss_aging_init_quot_diff_param[2][2] = { }, }; static const struct cpr3_fuse_param sdm630_kbss_aging_init_quot_diff_param[2][2] = { [CPRH_KBSS_POWER_CLUSTER_ID] = { {68, 45, 52}, {}, }, [CPRH_KBSS_PERFORMANCE_CLUSTER_ID] = { {70, 34, 41}, {}, }, }; /* * Open loop voltage fuse reference voltages in microvolts for MSM8998 v1 */ Loading Loading @@ -383,6 +480,25 @@ sdm660_kbss_fuse_ref_volt[2][SDM660_KBSS_FUSE_CORNERS] = { }, }; /* * Open loop voltage fuse reference voltages in microvolts for SDM630 */ static const int sdm630_kbss_fuse_ref_volt[SDM630_KBSS_FUSE_CORNERS] = { 644000, 788000, 868000, 1068000, }; static const int sdm630_kbss_speed_bin_2_fuse_ref_volt[SDM630_KBSS_FUSE_CORNERS] = { 644000, 788000, 868000, 1140000, }; #define CPRH_KBSS_FUSE_STEP_VOLT 10000 #define CPRH_KBSS_VOLTAGE_FUSE_SIZE 6 #define CPRH_KBSS_QUOT_OFFSET_SCALE 5 Loading Loading @@ -432,6 +548,12 @@ sdm660_kbss_fuse_ref_volt[2][SDM660_KBSS_FUSE_CORNERS] = { #define SDM660_KBSS_PERFORMANCE_AGING_SENSOR_ID 0 #define SDM660_KBSS_PERFORMANCE_AGING_BYPASS_MASK0 0 /* * sdm630 configuration */ #define SDM630_KBSS_POWER_CPR_SENSOR_COUNT 6 #define SDM630_KBSS_PERFORMANCE_CPR_SENSOR_COUNT 9 /* * SOC IDs */ Loading @@ -439,6 +561,7 @@ enum soc_id { MSM8998_V1_SOC_ID = 1, MSM8998_V2_SOC_ID = 2, SDM660_SOC_ID = 3, SDM630_SOC_ID = 4, }; /** Loading Loading @@ -622,6 +745,90 @@ static int cprh_sdm660_kbss_read_fuse_data(struct cpr3_regulator *vreg, return rc; }; /** * cprh_sdm630_kbss_read_fuse_data() - load SDM630 KBSS specific fuse parameter * values * @vreg: Pointer to the CPR3 regulator * @fuse: KBSS specific fuse data * * This function fills cprh_kbss_fuses struct with values read out of hardware * fuses. * * Return: 0 on success, errno on failure */ static int cprh_sdm630_kbss_read_fuse_data(struct cpr3_regulator *vreg, struct cprh_kbss_fuses *fuse) { void __iomem *base = vreg->thread->ctrl->fuse_base; int i, id, rc; rc = cpr3_read_fuse_param(base, sdm630_cpr_fusing_rev_param, &fuse->cpr_fusing_rev); if (rc) { cpr3_err(vreg, "Unable to read CPR fusing revision fuse, rc=%d\n", rc); return rc; } cpr3_info(vreg, "CPR fusing revision = %llu\n", fuse->cpr_fusing_rev); id = vreg->thread->ctrl->ctrl_id; for (i = 0; i < SDM630_KBSS_FUSE_CORNERS; i++) { rc = cpr3_read_fuse_param(base, sdm630_kbss_init_voltage_param[id][i], &fuse->init_voltage[i]); if (rc) { cpr3_err(vreg, "Unable to read fuse-corner %d initial voltage fuse, rc=%d\n", i, rc); return rc; } rc = cpr3_read_fuse_param(base, sdm630_kbss_target_quot_param[id][i], &fuse->target_quot[i]); if (rc) { cpr3_err(vreg, "Unable to read fuse-corner %d target quotient fuse, rc=%d\n", i, rc); return rc; } rc = cpr3_read_fuse_param(base, sdm630_kbss_ro_sel_param[id][i], &fuse->ro_sel[i]); if (rc) { cpr3_err(vreg, "Unable to read fuse-corner %d RO select fuse, rc=%d\n", i, rc); return rc; } rc = cpr3_read_fuse_param(base, sdm630_kbss_quot_offset_param[id][i], &fuse->quot_offset[i]); if (rc) { cpr3_err(vreg, "Unable to read fuse-corner %d quotient offset fuse, rc=%d\n", i, rc); return rc; } } rc = cpr3_read_fuse_param(base, sdm630_kbss_aging_init_quot_diff_param[id], &fuse->aging_init_quot_diff); if (rc) { cpr3_err(vreg, "Unable to read aging initial quotient difference fuse, rc=%d\n", rc); return rc; } vreg->fuse_combo = fuse->cpr_fusing_rev + 8 * fuse->speed_bin; if (vreg->fuse_combo >= CPRH_SDM630_KBSS_FUSE_COMBO_COUNT) { cpr3_err(vreg, "invalid CPR fuse combo = %d found\n", vreg->fuse_combo); return -EINVAL; } return rc; }; /** * cprh_kbss_read_fuse_data() - load KBSS specific fuse parameter values * @vreg: Pointer to the CPR3 regulator Loading @@ -648,6 +855,9 @@ static int cprh_kbss_read_fuse_data(struct cpr3_regulator *vreg) case SDM660_SOC_ID: fuse_corners = SDM660_KBSS_FUSE_CORNERS; break; case SDM630_SOC_ID: fuse_corners = SDM630_KBSS_FUSE_CORNERS; break; case MSM8998_V1_SOC_ID: case MSM8998_V2_SOC_ID: fuse_corners = MSM8998_KBSS_FUSE_CORNERS; Loading Loading @@ -686,6 +896,14 @@ static int cprh_kbss_read_fuse_data(struct cpr3_regulator *vreg) return rc; } break; case SDM630_SOC_ID: rc = cprh_sdm630_kbss_read_fuse_data(vreg, fuse); if (rc) { cpr3_err(vreg, "sdm630 kbss fuse data read failed, rc=%d\n", rc); return rc; } break; case MSM8998_V1_SOC_ID: case MSM8998_V2_SOC_ID: rc = cprh_msm8998_kbss_read_fuse_data(vreg, fuse); Loading Loading @@ -789,6 +1007,12 @@ static int cprh_kbss_calculate_open_loop_voltages(struct cpr3_regulator *vreg) else corner_name = cprh_sdm660_perf_kbss_fuse_corner_name; break; case SDM630_SOC_ID: ref_volt = sdm630_kbss_fuse_ref_volt; if (vreg->speed_bin_fuse == 2) ref_volt = sdm630_kbss_speed_bin_2_fuse_ref_volt; corner_name = cprh_sdm630_kbss_fuse_corner_name; break; case MSM8998_V1_SOC_ID: ref_volt = msm8998_v1_kbss_fuse_ref_volt; corner_name = cprh_msm8998_kbss_fuse_corner_name; Loading Loading @@ -1356,6 +1580,13 @@ static int cprh_kbss_calculate_target_quotients(struct cpr3_regulator *vreg) CPRH_SDM660_PERF_KBSS_FUSE_CORNER_TURBO_L2; } break; case SDM630_SOC_ID: corner_name = cprh_sdm630_kbss_fuse_corner_name; lowest_fuse_corner = CPRH_SDM630_KBSS_FUSE_CORNER_LOWSVS; highest_fuse_corner = CPRH_SDM630_KBSS_FUSE_CORNER_TURBO_L1; break; case MSM8998_V1_SOC_ID: case MSM8998_V2_SOC_ID: corner_name = cprh_msm8998_kbss_fuse_corner_name; Loading Loading @@ -1923,6 +2154,14 @@ static int cprh_kbss_init_controller(struct cpr3_controller *ctrl) ctrl->sensor_count = SDM660_KBSS_PERFORMANCE_CPR_SENSOR_COUNT; break; case SDM630_SOC_ID: if (ctrl->ctrl_id == CPRH_KBSS_POWER_CLUSTER_ID) ctrl->sensor_count = SDM630_KBSS_POWER_CPR_SENSOR_COUNT; else ctrl->sensor_count = SDM630_KBSS_PERFORMANCE_CPR_SENSOR_COUNT; break; case MSM8998_V1_SOC_ID: case MSM8998_V2_SOC_ID: if (ctrl->ctrl_id == CPRH_KBSS_POWER_CLUSTER_ID) Loading Loading @@ -2024,6 +2263,10 @@ static const struct of_device_id cprh_regulator_match_table[] = { .compatible = "qcom,cprh-sdm660-kbss-regulator", .data = (void *)(uintptr_t)SDM660_SOC_ID, }, { .compatible = "qcom,cprh-sdm630-kbss-regulator", .data = (void *)(uintptr_t)SDM630_SOC_ID, }, {} }; Loading