Loading Documentation/devicetree/bindings/regulator/cpr3-hmss-regulator.txt +22 −4 Original line number Diff line number Diff line Loading @@ -79,6 +79,12 @@ HMSS specific properties: which may be used as the ceiling for the corner. If this property is not specified, then a value of 0 is assumed. - qcom,system-supply-max-voltage Usage: required if qcom,vdd-threadN-ldo-supply is specified for any CPR3 regulator managed by any CPR3 thread of this controller. Value type: <u32> Definition: Maximum voltage setpoint for the system-supply regulator. - qcom,cpr-up-down-delay-time Usage: required Value type: <u32> Loading Loading @@ -174,7 +180,7 @@ HMSS specific properties: given regulator type. For HMSS the maximum supported value is 2. - qcom,ldo-headroom-voltage - qcom,ldo-min-headroom-voltage Usage: required if qcom,vdd-threadN-ldo-supply is specified for the CPR3 thread containing this CPR3 regulator and this CPR3 regulator needs to manage the cluster LDO state. Loading @@ -182,6 +188,15 @@ HMSS specific properties: Definition: Voltage in microvolts required between the VDD_APCC voltage and the LDO output in order for the LDO to be operational. - qcom,ldo-max-headroom-voltage Usage: required if qcom,vdd-threadN-ldo-supply is specified for the CPR3 thread containing this CPR3 regulator and this CPR3 regulator needs to manage the cluster LDO state. Value type: <u32> Definition: Maximum voltage difference in microvolts between the vdd-supply voltage and the LDO output voltage in order for active LDO mode to be operational. - qcom,ldo-adjust-voltage Usage: optional Value type: <u32> Loading @@ -189,7 +204,7 @@ HMSS specific properties: output and CPU. - qcom,ldo-max-voltage Usage: required if qcom,ldo-headroom-voltage is specified for this Usage: required if qcom,ldo-min-headroom-voltage is specified for this CPR3 regulator. Value type: <u32> Definition: Voltage in microvolts which represents the maximum Loading Loading @@ -248,6 +263,7 @@ apcc_cpr: cpr3-ctrl@99e8000 { qcom,apm-ctrl = <&apc_apm>; qcom,apm-threshold-voltage = <850000>; qcom,apm-hysteresis-voltage = <5000>; qcom,system-supply-max-voltage = <1015000>; vdd-supply = <&pm8994_s11>; qcom,voltage-step = <5000>; Loading Loading @@ -280,7 +296,8 @@ apcc_cpr: cpr3-ctrl@99e8000 { qcom,cpr-fuse-combos = <1>; qcom,cpr-corners = <19>; qcom,ldo-headroom-voltage = <150000>; qcom,ldo-min-headroom-voltage = <150000>; qcom,ldo-max-headroom-voltage = <470000>; qcom,ldo-max-voltage = <805000>; qcom,cpr-corner-fmax-map = <1 2 6 11 19>; Loading Loading @@ -408,7 +425,8 @@ apcc_cpr: cpr3-ctrl@99e8000 { qcom,cpr-fuse-combos = <1>; qcom,cpr-corners = <18>; qcom,ldo-headroom-voltage = <150000>; qcom,ldo-min-headroom-voltage = <150000>; qcom,ldo-max-headroom-voltage = <470000>; qcom,ldo-max-voltage = <805000>; qcom,cpr-corner-fmax-map = <1 3 5 11 18>; Loading arch/arm/boot/dts/qcom/msm8996-regulator.dtsi +5 −2 Original line number Diff line number Diff line Loading @@ -574,6 +574,7 @@ qcom,apm-ctrl = <&apc_apm>; qcom,apm-threshold-voltage = <850000>; qcom,apm-hysteresis-voltage = <5000>; qcom,system-supply-max-voltage = <1015000>; vdd-supply = <&pm8994_s11>; qcom,voltage-step = <5000>; Loading Loading @@ -612,7 +613,8 @@ /* Speed bin 1 */ <13 13 13 13 13 13 13 13>; qcom,ldo-headroom-voltage = <150000>; qcom,ldo-min-headroom-voltage = <150000>; qcom,ldo-max-headroom-voltage = <470000>; qcom,ldo-max-voltage = <890000>; qcom,cpr-corner-fmax-map = Loading Loading @@ -947,7 +949,8 @@ /* Speed bin 1 */ <21 21 21 21 21 21 21 21>; qcom,ldo-headroom-voltage = <150000>; qcom,ldo-min-headroom-voltage = <150000>; qcom,ldo-max-headroom-voltage = <470000>; qcom,ldo-max-voltage = <890000>; qcom,cpr-corner-fmax-map = Loading arch/arm/boot/dts/qcom/msm8996-v2.dtsi +0 −2 Original line number Diff line number Diff line Loading @@ -109,7 +109,6 @@ qcom,cpr-fuse-combos = <4>; qcom,cpr-corners = <19>; qcom,ldo-headroom-voltage = <150000>; qcom,ldo-max-voltage = <805000>; qcom,cpr-corner-fmax-map = <1 2 6 11 19>; Loading Loading @@ -227,7 +226,6 @@ qcom,cpr-fuse-combos = <4>; qcom,cpr-corners = <18>; qcom,ldo-headroom-voltage = <150000>; qcom,ldo-max-voltage = <805000>; qcom,cpr-corner-fmax-map = <1 3 5 11 18>; Loading drivers/regulator/cpr3-hmss-regulator.c +26 −6 Original line number Diff line number Diff line Loading @@ -1279,7 +1279,7 @@ static int cpr3_hmss_kvreg_init(struct cpr3_regulator *vreg) if (!of_find_property(ctrl->dev->of_node, kvreg_name_buf , NULL)) return 0; else if (!of_find_property(node, "qcom,ldo-headroom-voltage", NULL)) else if (!of_find_property(node, "qcom,ldo-min-headroom-voltage", NULL)) return 0; scnprintf(kvreg_name_buf, MAX_KVREG_NAME_SIZE, "vdd-thread%d-ldo", id); Loading Loading @@ -1307,10 +1307,23 @@ static int cpr3_hmss_kvreg_init(struct cpr3_regulator *vreg) return rc; } rc = of_property_read_u32(node, "qcom,ldo-headroom-voltage", &vreg->ldo_headroom_volt); if (!ctrl->system_supply_max_volt) { cpr3_err(ctrl, "system-supply max voltage must be specified\n"); return -EINVAL; } rc = of_property_read_u32(node, "qcom,ldo-min-headroom-voltage", &vreg->ldo_min_headroom_volt); if (rc) { cpr3_err(vreg, "error reading qcom,ldo-headroom-voltage, rc=%d\n", cpr3_err(vreg, "error reading qcom,ldo-min-headroom-voltage, rc=%d\n", rc); return rc; } rc = of_property_read_u32(node, "qcom,ldo-max-headroom-voltage", &vreg->ldo_max_headroom_volt); if (rc) { cpr3_err(vreg, "error reading qcom,ldo-max-headroom-voltage, rc=%d\n", rc); return rc; } Loading Loading @@ -1343,8 +1356,9 @@ static int cpr3_hmss_kvreg_init(struct cpr3_regulator *vreg) vreg->ldo_mode_allowed = !of_property_read_bool(node, "qcom,ldo-disable"); cpr3_info(vreg, "LDO headroom=%d uV, LDO adj=%d uV, LDO mode=%s, LDO retention=%d uV\n", vreg->ldo_headroom_volt, cpr3_info(vreg, "LDO min headroom=%d uV, LDO max headroom=%d uV, LDO adj=%d uV, LDO mode=%s, LDO retention=%d uV\n", vreg->ldo_min_headroom_volt, vreg->ldo_max_headroom_volt, vreg->ldo_adjust_volt, vreg->ldo_mode_allowed ? "allowed" : "disallowed", vreg->ldo_ret_volt); Loading Loading @@ -1598,6 +1612,12 @@ static int cpr3_hmss_init_controller(struct cpr3_controller *ctrl) return rc; } /* No error check since this is an optional property. */ of_property_read_u32(ctrl->dev->of_node, "qcom,system-supply-max-voltage", &ctrl->system_supply_max_volt); /* No error check since this is an optional property. */ of_property_read_u32(ctrl->dev->of_node, "qcom,cpr-clock-throttling", &ctrl->proc_clock_throttle); Loading drivers/regulator/cpr3-regulator.c +133 −29 Original line number Diff line number Diff line Loading @@ -782,7 +782,7 @@ static int cpr3_regulator_config_ldo_retention(struct cpr3_regulator *vreg, } mode = floor_volt >= retention_volt + vreg->ldo_headroom_volt mode = floor_volt >= retention_volt + vreg->ldo_min_headroom_volt ? LDO_MODE : BHS_MODE; rc = regulator_allow_bypass(ldo_ret_reg, mode); Loading Loading @@ -811,7 +811,7 @@ static int cpr3_regulator_set_bhs_mode(struct cpr3_regulator *vreg, struct regulator *ldo_reg = vreg->ldo_regulator; int bhs_volt, rc; bhs_volt = vdd_volt - vreg->ldo_headroom_volt; bhs_volt = vdd_volt - vreg->ldo_min_headroom_volt; if (bhs_volt > vreg->ldo_max_volt) { cpr3_debug(vreg, "limited to LDO output of %d uV when switching to BHS mode\n", vreg->ldo_max_volt); Loading Loading @@ -839,13 +839,18 @@ static int cpr3_regulator_set_bhs_mode(struct cpr3_regulator *vreg, /** * cpr3_regulator_config_vreg_ldo() - configure the voltage and bypass state for * the LDO regulator associated with a single CPR3 regulator * the LDO regulator associated with a single CPR3 regulator. * * @vreg: Pointer to the CPR3 regulator * @vdd_floor_volt: Last known aggregated floor voltage in microvolts for * the VDD supply * @vdd_ceiling_volt: Last known aggregated ceiling voltage in microvolts for * the VDD supply * @vdd_volt: Last known voltage in microvolts for the VDD supply * @last_volt: Last known voltage in microvolts for the VDD supply * @apm_crossing: Flag indicating if an APM reconfiguration is taking * place as a result of a VDD voltage scale request and * the VDD supply is at the crossover voltage * @new_volt: New voltage in microvolts that VDD needs to end up at * * This function performs all relevant LDO or BHS configurations if an LDO * regulator is specified. Loading @@ -854,10 +859,53 @@ static int cpr3_regulator_set_bhs_mode(struct cpr3_regulator *vreg, */ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, int vdd_floor_volt, int vdd_ceiling_volt, int vdd_volt) int last_volt, bool apm_crossing, int new_volt) { struct cpr3_controller *ctrl = vreg->thread->ctrl; struct regulator *ldo_reg = vreg->ldo_regulator; int rc, ldo_volt, bhs_volt, max_volt; struct cpr3_corner *current_corner; enum msm_apm_supply apm_mode; int rc, ldo_volt, final_ldo_volt, bhs_volt, max_volt, safe_volt; if (apm_crossing) { if (!vreg->vreg_enabled || vreg->current_corner == CPR3_REGULATOR_CORNER_INVALID) return 0; /* * Guarantee LDO maximum headroom is not * violated when the APM is switched to the * system-supply source. */ current_corner = &vreg->corner[vreg->current_corner]; if (vreg->ldo_regulator_bypass == LDO_MODE) { apm_mode = msm_apm_get_supply(ctrl->apm); if (apm_mode < 0) { cpr3_err(ctrl, "APM get supply failed, rc=%d\n", apm_mode); return apm_mode; } if (apm_mode == ctrl->apm_high_supply && new_volt < ctrl->apm_threshold_volt) { safe_volt = max(current_corner->open_loop_volt - vreg->ldo_adjust_volt, ctrl->system_supply_max_volt - vreg->ldo_max_headroom_volt); max_volt = min(ctrl->system_supply_max_volt, vreg->ldo_max_volt); rc = regulator_set_voltage(ldo_reg, safe_volt, max_volt); if (rc) { cpr3_err(vreg, "regulator_set_voltage(ldo) == %d failed, rc=%d\n", safe_volt, rc); return rc; } } } return 0; } rc = cpr3_regulator_config_ldo_retention(vreg, vdd_floor_volt); if (rc) Loading @@ -867,34 +915,55 @@ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, == CPR3_REGULATOR_CORNER_INVALID) return 0; ldo_volt = vreg->corner[vreg->current_corner].open_loop_volt current_corner = &vreg->corner[vreg->current_corner]; ldo_volt = current_corner->open_loop_volt - vreg->ldo_adjust_volt; bhs_volt = last_volt - vreg->ldo_min_headroom_volt; max_volt = min(vdd_ceiling_volt, vreg->ldo_max_volt); if (vdd_floor_volt >= ldo_volt + vreg->ldo_headroom_volt) { if (vdd_floor_volt >= ldo_volt + vreg->ldo_min_headroom_volt && ldo_volt >= ctrl->system_supply_max_volt - vreg->ldo_max_headroom_volt && bhs_volt >= ctrl->system_supply_max_volt - vreg->ldo_max_headroom_volt) { /* LDO minimum and maximum headrooms satisfied */ apm_mode = msm_apm_get_supply(ctrl->apm); if (apm_mode < 0) { cpr3_err(ctrl, "APM get supply failed, rc=%d\n", apm_mode); return apm_mode; } if (vreg->ldo_regulator_bypass == BHS_MODE) { if (ldo_volt > vreg->ldo_max_volt) { cpr3_debug(vreg, "cannot support LDO mode with ldo_volt=%d uV\n", ldo_volt); return 0; } /* * BHS to LDO transition. Configure LDO output * to min(max LDO output, VDD - LDO headroom) * voltage then switch the regulator mode. */ bhs_volt = vdd_volt - vreg->ldo_headroom_volt; if (bhs_volt > vreg->ldo_max_volt) { cpr3_debug(vreg, "limiting bhs_volt=%d uV to %d uV\n", bhs_volt, vreg->ldo_max_volt); bhs_volt = vreg->ldo_max_volt; } * voltage if APM is on high supply source or * min(max(system-supply ceiling - LDO max headroom, * VDD - LDO headroom), max LDO output) if * APM is on low supply source, then switch * regulator mode. */ if (apm_mode == ctrl->apm_high_supply) safe_volt = min(vreg->ldo_max_volt, bhs_volt); else safe_volt = min(max(ctrl->system_supply_max_volt - vreg->ldo_max_headroom_volt, bhs_volt), vreg->ldo_max_volt); rc = regulator_set_voltage(ldo_reg, bhs_volt, max_volt); rc = regulator_set_voltage(ldo_reg, safe_volt, max_volt); if (rc) { cpr3_err(vreg, "regulator_set_voltage(ldo) == %d failed, rc=%d\n", bhs_volt, rc); safe_volt, rc); return rc; } Loading @@ -908,15 +977,22 @@ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, } /* Configure final LDO output voltage */ rc = regulator_set_voltage(ldo_reg, ldo_volt, max_volt); if (apm_mode == ctrl->apm_high_supply) final_ldo_volt = max(ldo_volt, vdd_ceiling_volt - vreg->ldo_max_headroom_volt); else final_ldo_volt = ldo_volt; rc = regulator_set_voltage(ldo_reg, final_ldo_volt, max_volt); if (rc) { cpr3_err(vreg, "regulator_set_voltage(ldo) == %d failed, rc=%d\n", ldo_volt, rc); final_ldo_volt, rc); return rc; } } else { if (vreg->ldo_regulator_bypass == LDO_MODE) { rc = cpr3_regulator_set_bhs_mode(vreg, vdd_volt, rc = cpr3_regulator_set_bhs_mode(vreg, last_volt, vdd_ceiling_volt); if (rc) return rc; Loading @@ -935,13 +1011,17 @@ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, * the VDD supply * @vdd_ceiling_volt: Last known aggregated ceiling voltage in microvolts for * the VDD supply * @vdd_volt: Last known voltage in microvolts for the VDD supply * @last_volt: Last known voltage in microvolts for the VDD supply * @apm_crossing: Flag indicating if an APM reconfiguration is taking * place as a result of a VDD voltage scale request and * the VDD supply is at the crossover voltage * @new_volt: New voltage in microvolts that VDD needs to end up at * * Return: 0 on success, errno on failure */ static int cpr3_regulator_config_ldo(struct cpr3_controller *ctrl, int vdd_floor_volt, int vdd_ceiling_volt, int vdd_volt) int last_volt, bool apm_crossing, int new_volt) { struct cpr3_regulator *vreg; int i, j, rc; Loading @@ -954,7 +1034,8 @@ static int cpr3_regulator_config_ldo(struct cpr3_controller *ctrl, continue; rc = cpr3_regulator_config_vreg_ldo(vreg, vdd_floor_volt, vdd_ceiling_volt, vdd_volt); vdd_floor_volt, vdd_ceiling_volt, last_volt, apm_crossing, new_volt); if (rc) return rc; } Loading Loading @@ -999,6 +1080,18 @@ static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl, apm_crossing = true; if (apm_crossing) { if (new_volt < last_volt) { /* Decreasing VDD voltage */ rc = cpr3_regulator_config_ldo(ctrl, apm_volt, last_max_volt, last_volt, false, apm_volt); if (rc) { cpr3_err(ctrl, "unable to configure LDO state, rc=%d\n", rc); return rc; } } rc = regulator_set_voltage(vdd, apm_volt, apm_volt); if (rc) { cpr3_err(ctrl, "regulator_set_voltage(vdd) == %d failed, rc=%d\n", Loading @@ -1006,6 +1099,15 @@ static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl, return rc; } rc = cpr3_regulator_config_ldo(ctrl, aggr_corner->floor_volt, last_max_volt, apm_volt, true, new_volt); if (rc) { cpr3_err(ctrl, "unable to configure LDO state, rc=%d\n", rc); return rc; } rc = msm_apm_set_supply(ctrl->apm, new_volt >= apm_volt ? ctrl->apm_high_supply : ctrl->apm_low_supply); if (rc) { Loading @@ -1020,7 +1122,8 @@ static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl, /* Decreasing VDD voltage */ rc = cpr3_regulator_config_ldo(ctrl, aggr_corner->floor_volt, last_max_volt, apm_crossing ? apm_volt : last_volt); apm_volt : last_volt, false, new_volt); if (rc) { cpr3_err(ctrl, "unable to configure LDO state, rc=%d\n", rc); Loading Loading @@ -1056,7 +1159,8 @@ static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl, if (new_volt >= last_volt) { /* Increasing VDD voltage */ rc = cpr3_regulator_config_ldo(ctrl, aggr_corner->floor_volt, max_volt, new_volt); max_volt, new_volt, false, new_volt); if (rc) { cpr3_err(ctrl, "unable to configure LDO state, rc=%d\n", rc); Loading Loading
Documentation/devicetree/bindings/regulator/cpr3-hmss-regulator.txt +22 −4 Original line number Diff line number Diff line Loading @@ -79,6 +79,12 @@ HMSS specific properties: which may be used as the ceiling for the corner. If this property is not specified, then a value of 0 is assumed. - qcom,system-supply-max-voltage Usage: required if qcom,vdd-threadN-ldo-supply is specified for any CPR3 regulator managed by any CPR3 thread of this controller. Value type: <u32> Definition: Maximum voltage setpoint for the system-supply regulator. - qcom,cpr-up-down-delay-time Usage: required Value type: <u32> Loading Loading @@ -174,7 +180,7 @@ HMSS specific properties: given regulator type. For HMSS the maximum supported value is 2. - qcom,ldo-headroom-voltage - qcom,ldo-min-headroom-voltage Usage: required if qcom,vdd-threadN-ldo-supply is specified for the CPR3 thread containing this CPR3 regulator and this CPR3 regulator needs to manage the cluster LDO state. Loading @@ -182,6 +188,15 @@ HMSS specific properties: Definition: Voltage in microvolts required between the VDD_APCC voltage and the LDO output in order for the LDO to be operational. - qcom,ldo-max-headroom-voltage Usage: required if qcom,vdd-threadN-ldo-supply is specified for the CPR3 thread containing this CPR3 regulator and this CPR3 regulator needs to manage the cluster LDO state. Value type: <u32> Definition: Maximum voltage difference in microvolts between the vdd-supply voltage and the LDO output voltage in order for active LDO mode to be operational. - qcom,ldo-adjust-voltage Usage: optional Value type: <u32> Loading @@ -189,7 +204,7 @@ HMSS specific properties: output and CPU. - qcom,ldo-max-voltage Usage: required if qcom,ldo-headroom-voltage is specified for this Usage: required if qcom,ldo-min-headroom-voltage is specified for this CPR3 regulator. Value type: <u32> Definition: Voltage in microvolts which represents the maximum Loading Loading @@ -248,6 +263,7 @@ apcc_cpr: cpr3-ctrl@99e8000 { qcom,apm-ctrl = <&apc_apm>; qcom,apm-threshold-voltage = <850000>; qcom,apm-hysteresis-voltage = <5000>; qcom,system-supply-max-voltage = <1015000>; vdd-supply = <&pm8994_s11>; qcom,voltage-step = <5000>; Loading Loading @@ -280,7 +296,8 @@ apcc_cpr: cpr3-ctrl@99e8000 { qcom,cpr-fuse-combos = <1>; qcom,cpr-corners = <19>; qcom,ldo-headroom-voltage = <150000>; qcom,ldo-min-headroom-voltage = <150000>; qcom,ldo-max-headroom-voltage = <470000>; qcom,ldo-max-voltage = <805000>; qcom,cpr-corner-fmax-map = <1 2 6 11 19>; Loading Loading @@ -408,7 +425,8 @@ apcc_cpr: cpr3-ctrl@99e8000 { qcom,cpr-fuse-combos = <1>; qcom,cpr-corners = <18>; qcom,ldo-headroom-voltage = <150000>; qcom,ldo-min-headroom-voltage = <150000>; qcom,ldo-max-headroom-voltage = <470000>; qcom,ldo-max-voltage = <805000>; qcom,cpr-corner-fmax-map = <1 3 5 11 18>; Loading
arch/arm/boot/dts/qcom/msm8996-regulator.dtsi +5 −2 Original line number Diff line number Diff line Loading @@ -574,6 +574,7 @@ qcom,apm-ctrl = <&apc_apm>; qcom,apm-threshold-voltage = <850000>; qcom,apm-hysteresis-voltage = <5000>; qcom,system-supply-max-voltage = <1015000>; vdd-supply = <&pm8994_s11>; qcom,voltage-step = <5000>; Loading Loading @@ -612,7 +613,8 @@ /* Speed bin 1 */ <13 13 13 13 13 13 13 13>; qcom,ldo-headroom-voltage = <150000>; qcom,ldo-min-headroom-voltage = <150000>; qcom,ldo-max-headroom-voltage = <470000>; qcom,ldo-max-voltage = <890000>; qcom,cpr-corner-fmax-map = Loading Loading @@ -947,7 +949,8 @@ /* Speed bin 1 */ <21 21 21 21 21 21 21 21>; qcom,ldo-headroom-voltage = <150000>; qcom,ldo-min-headroom-voltage = <150000>; qcom,ldo-max-headroom-voltage = <470000>; qcom,ldo-max-voltage = <890000>; qcom,cpr-corner-fmax-map = Loading
arch/arm/boot/dts/qcom/msm8996-v2.dtsi +0 −2 Original line number Diff line number Diff line Loading @@ -109,7 +109,6 @@ qcom,cpr-fuse-combos = <4>; qcom,cpr-corners = <19>; qcom,ldo-headroom-voltage = <150000>; qcom,ldo-max-voltage = <805000>; qcom,cpr-corner-fmax-map = <1 2 6 11 19>; Loading Loading @@ -227,7 +226,6 @@ qcom,cpr-fuse-combos = <4>; qcom,cpr-corners = <18>; qcom,ldo-headroom-voltage = <150000>; qcom,ldo-max-voltage = <805000>; qcom,cpr-corner-fmax-map = <1 3 5 11 18>; Loading
drivers/regulator/cpr3-hmss-regulator.c +26 −6 Original line number Diff line number Diff line Loading @@ -1279,7 +1279,7 @@ static int cpr3_hmss_kvreg_init(struct cpr3_regulator *vreg) if (!of_find_property(ctrl->dev->of_node, kvreg_name_buf , NULL)) return 0; else if (!of_find_property(node, "qcom,ldo-headroom-voltage", NULL)) else if (!of_find_property(node, "qcom,ldo-min-headroom-voltage", NULL)) return 0; scnprintf(kvreg_name_buf, MAX_KVREG_NAME_SIZE, "vdd-thread%d-ldo", id); Loading Loading @@ -1307,10 +1307,23 @@ static int cpr3_hmss_kvreg_init(struct cpr3_regulator *vreg) return rc; } rc = of_property_read_u32(node, "qcom,ldo-headroom-voltage", &vreg->ldo_headroom_volt); if (!ctrl->system_supply_max_volt) { cpr3_err(ctrl, "system-supply max voltage must be specified\n"); return -EINVAL; } rc = of_property_read_u32(node, "qcom,ldo-min-headroom-voltage", &vreg->ldo_min_headroom_volt); if (rc) { cpr3_err(vreg, "error reading qcom,ldo-headroom-voltage, rc=%d\n", cpr3_err(vreg, "error reading qcom,ldo-min-headroom-voltage, rc=%d\n", rc); return rc; } rc = of_property_read_u32(node, "qcom,ldo-max-headroom-voltage", &vreg->ldo_max_headroom_volt); if (rc) { cpr3_err(vreg, "error reading qcom,ldo-max-headroom-voltage, rc=%d\n", rc); return rc; } Loading Loading @@ -1343,8 +1356,9 @@ static int cpr3_hmss_kvreg_init(struct cpr3_regulator *vreg) vreg->ldo_mode_allowed = !of_property_read_bool(node, "qcom,ldo-disable"); cpr3_info(vreg, "LDO headroom=%d uV, LDO adj=%d uV, LDO mode=%s, LDO retention=%d uV\n", vreg->ldo_headroom_volt, cpr3_info(vreg, "LDO min headroom=%d uV, LDO max headroom=%d uV, LDO adj=%d uV, LDO mode=%s, LDO retention=%d uV\n", vreg->ldo_min_headroom_volt, vreg->ldo_max_headroom_volt, vreg->ldo_adjust_volt, vreg->ldo_mode_allowed ? "allowed" : "disallowed", vreg->ldo_ret_volt); Loading Loading @@ -1598,6 +1612,12 @@ static int cpr3_hmss_init_controller(struct cpr3_controller *ctrl) return rc; } /* No error check since this is an optional property. */ of_property_read_u32(ctrl->dev->of_node, "qcom,system-supply-max-voltage", &ctrl->system_supply_max_volt); /* No error check since this is an optional property. */ of_property_read_u32(ctrl->dev->of_node, "qcom,cpr-clock-throttling", &ctrl->proc_clock_throttle); Loading
drivers/regulator/cpr3-regulator.c +133 −29 Original line number Diff line number Diff line Loading @@ -782,7 +782,7 @@ static int cpr3_regulator_config_ldo_retention(struct cpr3_regulator *vreg, } mode = floor_volt >= retention_volt + vreg->ldo_headroom_volt mode = floor_volt >= retention_volt + vreg->ldo_min_headroom_volt ? LDO_MODE : BHS_MODE; rc = regulator_allow_bypass(ldo_ret_reg, mode); Loading Loading @@ -811,7 +811,7 @@ static int cpr3_regulator_set_bhs_mode(struct cpr3_regulator *vreg, struct regulator *ldo_reg = vreg->ldo_regulator; int bhs_volt, rc; bhs_volt = vdd_volt - vreg->ldo_headroom_volt; bhs_volt = vdd_volt - vreg->ldo_min_headroom_volt; if (bhs_volt > vreg->ldo_max_volt) { cpr3_debug(vreg, "limited to LDO output of %d uV when switching to BHS mode\n", vreg->ldo_max_volt); Loading Loading @@ -839,13 +839,18 @@ static int cpr3_regulator_set_bhs_mode(struct cpr3_regulator *vreg, /** * cpr3_regulator_config_vreg_ldo() - configure the voltage and bypass state for * the LDO regulator associated with a single CPR3 regulator * the LDO regulator associated with a single CPR3 regulator. * * @vreg: Pointer to the CPR3 regulator * @vdd_floor_volt: Last known aggregated floor voltage in microvolts for * the VDD supply * @vdd_ceiling_volt: Last known aggregated ceiling voltage in microvolts for * the VDD supply * @vdd_volt: Last known voltage in microvolts for the VDD supply * @last_volt: Last known voltage in microvolts for the VDD supply * @apm_crossing: Flag indicating if an APM reconfiguration is taking * place as a result of a VDD voltage scale request and * the VDD supply is at the crossover voltage * @new_volt: New voltage in microvolts that VDD needs to end up at * * This function performs all relevant LDO or BHS configurations if an LDO * regulator is specified. Loading @@ -854,10 +859,53 @@ static int cpr3_regulator_set_bhs_mode(struct cpr3_regulator *vreg, */ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, int vdd_floor_volt, int vdd_ceiling_volt, int vdd_volt) int last_volt, bool apm_crossing, int new_volt) { struct cpr3_controller *ctrl = vreg->thread->ctrl; struct regulator *ldo_reg = vreg->ldo_regulator; int rc, ldo_volt, bhs_volt, max_volt; struct cpr3_corner *current_corner; enum msm_apm_supply apm_mode; int rc, ldo_volt, final_ldo_volt, bhs_volt, max_volt, safe_volt; if (apm_crossing) { if (!vreg->vreg_enabled || vreg->current_corner == CPR3_REGULATOR_CORNER_INVALID) return 0; /* * Guarantee LDO maximum headroom is not * violated when the APM is switched to the * system-supply source. */ current_corner = &vreg->corner[vreg->current_corner]; if (vreg->ldo_regulator_bypass == LDO_MODE) { apm_mode = msm_apm_get_supply(ctrl->apm); if (apm_mode < 0) { cpr3_err(ctrl, "APM get supply failed, rc=%d\n", apm_mode); return apm_mode; } if (apm_mode == ctrl->apm_high_supply && new_volt < ctrl->apm_threshold_volt) { safe_volt = max(current_corner->open_loop_volt - vreg->ldo_adjust_volt, ctrl->system_supply_max_volt - vreg->ldo_max_headroom_volt); max_volt = min(ctrl->system_supply_max_volt, vreg->ldo_max_volt); rc = regulator_set_voltage(ldo_reg, safe_volt, max_volt); if (rc) { cpr3_err(vreg, "regulator_set_voltage(ldo) == %d failed, rc=%d\n", safe_volt, rc); return rc; } } } return 0; } rc = cpr3_regulator_config_ldo_retention(vreg, vdd_floor_volt); if (rc) Loading @@ -867,34 +915,55 @@ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, == CPR3_REGULATOR_CORNER_INVALID) return 0; ldo_volt = vreg->corner[vreg->current_corner].open_loop_volt current_corner = &vreg->corner[vreg->current_corner]; ldo_volt = current_corner->open_loop_volt - vreg->ldo_adjust_volt; bhs_volt = last_volt - vreg->ldo_min_headroom_volt; max_volt = min(vdd_ceiling_volt, vreg->ldo_max_volt); if (vdd_floor_volt >= ldo_volt + vreg->ldo_headroom_volt) { if (vdd_floor_volt >= ldo_volt + vreg->ldo_min_headroom_volt && ldo_volt >= ctrl->system_supply_max_volt - vreg->ldo_max_headroom_volt && bhs_volt >= ctrl->system_supply_max_volt - vreg->ldo_max_headroom_volt) { /* LDO minimum and maximum headrooms satisfied */ apm_mode = msm_apm_get_supply(ctrl->apm); if (apm_mode < 0) { cpr3_err(ctrl, "APM get supply failed, rc=%d\n", apm_mode); return apm_mode; } if (vreg->ldo_regulator_bypass == BHS_MODE) { if (ldo_volt > vreg->ldo_max_volt) { cpr3_debug(vreg, "cannot support LDO mode with ldo_volt=%d uV\n", ldo_volt); return 0; } /* * BHS to LDO transition. Configure LDO output * to min(max LDO output, VDD - LDO headroom) * voltage then switch the regulator mode. */ bhs_volt = vdd_volt - vreg->ldo_headroom_volt; if (bhs_volt > vreg->ldo_max_volt) { cpr3_debug(vreg, "limiting bhs_volt=%d uV to %d uV\n", bhs_volt, vreg->ldo_max_volt); bhs_volt = vreg->ldo_max_volt; } * voltage if APM is on high supply source or * min(max(system-supply ceiling - LDO max headroom, * VDD - LDO headroom), max LDO output) if * APM is on low supply source, then switch * regulator mode. */ if (apm_mode == ctrl->apm_high_supply) safe_volt = min(vreg->ldo_max_volt, bhs_volt); else safe_volt = min(max(ctrl->system_supply_max_volt - vreg->ldo_max_headroom_volt, bhs_volt), vreg->ldo_max_volt); rc = regulator_set_voltage(ldo_reg, bhs_volt, max_volt); rc = regulator_set_voltage(ldo_reg, safe_volt, max_volt); if (rc) { cpr3_err(vreg, "regulator_set_voltage(ldo) == %d failed, rc=%d\n", bhs_volt, rc); safe_volt, rc); return rc; } Loading @@ -908,15 +977,22 @@ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, } /* Configure final LDO output voltage */ rc = regulator_set_voltage(ldo_reg, ldo_volt, max_volt); if (apm_mode == ctrl->apm_high_supply) final_ldo_volt = max(ldo_volt, vdd_ceiling_volt - vreg->ldo_max_headroom_volt); else final_ldo_volt = ldo_volt; rc = regulator_set_voltage(ldo_reg, final_ldo_volt, max_volt); if (rc) { cpr3_err(vreg, "regulator_set_voltage(ldo) == %d failed, rc=%d\n", ldo_volt, rc); final_ldo_volt, rc); return rc; } } else { if (vreg->ldo_regulator_bypass == LDO_MODE) { rc = cpr3_regulator_set_bhs_mode(vreg, vdd_volt, rc = cpr3_regulator_set_bhs_mode(vreg, last_volt, vdd_ceiling_volt); if (rc) return rc; Loading @@ -935,13 +1011,17 @@ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, * the VDD supply * @vdd_ceiling_volt: Last known aggregated ceiling voltage in microvolts for * the VDD supply * @vdd_volt: Last known voltage in microvolts for the VDD supply * @last_volt: Last known voltage in microvolts for the VDD supply * @apm_crossing: Flag indicating if an APM reconfiguration is taking * place as a result of a VDD voltage scale request and * the VDD supply is at the crossover voltage * @new_volt: New voltage in microvolts that VDD needs to end up at * * Return: 0 on success, errno on failure */ static int cpr3_regulator_config_ldo(struct cpr3_controller *ctrl, int vdd_floor_volt, int vdd_ceiling_volt, int vdd_volt) int last_volt, bool apm_crossing, int new_volt) { struct cpr3_regulator *vreg; int i, j, rc; Loading @@ -954,7 +1034,8 @@ static int cpr3_regulator_config_ldo(struct cpr3_controller *ctrl, continue; rc = cpr3_regulator_config_vreg_ldo(vreg, vdd_floor_volt, vdd_ceiling_volt, vdd_volt); vdd_floor_volt, vdd_ceiling_volt, last_volt, apm_crossing, new_volt); if (rc) return rc; } Loading Loading @@ -999,6 +1080,18 @@ static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl, apm_crossing = true; if (apm_crossing) { if (new_volt < last_volt) { /* Decreasing VDD voltage */ rc = cpr3_regulator_config_ldo(ctrl, apm_volt, last_max_volt, last_volt, false, apm_volt); if (rc) { cpr3_err(ctrl, "unable to configure LDO state, rc=%d\n", rc); return rc; } } rc = regulator_set_voltage(vdd, apm_volt, apm_volt); if (rc) { cpr3_err(ctrl, "regulator_set_voltage(vdd) == %d failed, rc=%d\n", Loading @@ -1006,6 +1099,15 @@ static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl, return rc; } rc = cpr3_regulator_config_ldo(ctrl, aggr_corner->floor_volt, last_max_volt, apm_volt, true, new_volt); if (rc) { cpr3_err(ctrl, "unable to configure LDO state, rc=%d\n", rc); return rc; } rc = msm_apm_set_supply(ctrl->apm, new_volt >= apm_volt ? ctrl->apm_high_supply : ctrl->apm_low_supply); if (rc) { Loading @@ -1020,7 +1122,8 @@ static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl, /* Decreasing VDD voltage */ rc = cpr3_regulator_config_ldo(ctrl, aggr_corner->floor_volt, last_max_volt, apm_crossing ? apm_volt : last_volt); apm_volt : last_volt, false, new_volt); if (rc) { cpr3_err(ctrl, "unable to configure LDO state, rc=%d\n", rc); Loading Loading @@ -1056,7 +1159,8 @@ static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl, if (new_volt >= last_volt) { /* Increasing VDD voltage */ rc = cpr3_regulator_config_ldo(ctrl, aggr_corner->floor_volt, max_volt, new_volt); max_volt, new_volt, false, new_volt); if (rc) { cpr3_err(ctrl, "unable to configure LDO state, rc=%d\n", rc); Loading