Loading drivers/regulator/cpr3-hmss-regulator.c +1 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> #include <linux/regulator/kryo-regulator.h> #include <linux/regulator/msm-ldo-regulator.h> #include "cpr3-regulator.h" Loading drivers/regulator/cpr3-regulator.c +186 −38 Original line number Diff line number Diff line Loading @@ -35,7 +35,7 @@ #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> #include <linux/regulator/kryo-regulator.h> #include <linux/regulator/msm-ldo-regulator.h> #include <soc/qcom/spm.h> Loading Loading @@ -1761,7 +1761,12 @@ static int cpr3_regulator_config_ldo_retention(struct cpr3_regulator *vreg, { struct regulator *ldo_ret_reg = vreg->ldo_ret_regulator; int retention_volt, rc; enum kryo_supply_mode mode; enum msm_ldo_supply_mode mode; if (!ldo_ret_reg) { /* LDO retention regulator is not defined */ return 0; } retention_volt = regulator_get_voltage(ldo_ret_reg); if (retention_volt < 0) { Loading @@ -1783,8 +1788,8 @@ static int cpr3_regulator_config_ldo_retention(struct cpr3_regulator *vreg, } /** * cpr3_regulator_config_ldo_mem_acc() - configure the mem-acc regulator * corner based upon a future LDO regulator voltage setpoint * cpr3_regulator_config_kryo_ldo_mem_acc() - configure the mem-acc regulator * corner based upon a future Kryo LDO regulator voltage setpoint * @vreg: Pointer to the CPR3 regulator * @new_volt: New voltage in microvolts that the LDO regulator needs * to end up at Loading @@ -1796,7 +1801,7 @@ static int cpr3_regulator_config_ldo_retention(struct cpr3_regulator *vreg, * * Return: 0 on success, errno on failure */ static int cpr3_regulator_config_ldo_mem_acc(struct cpr3_regulator *vreg, static int cpr3_regulator_config_kryo_ldo_mem_acc(struct cpr3_regulator *vreg, int new_volt) { struct cpr3_controller *ctrl = vreg->thread->ctrl; Loading Loading @@ -1858,18 +1863,21 @@ static int cpr3_regulator_config_ldo_mem_acc(struct cpr3_regulator *vreg, } /** * cpr3_regulator_set_bhs_mode() - configure the LDO regulator associated with * a CPR3 regulator to BHS mode * cpr3_regulator_kryo_bhs_prepare() - configure the Kryo LDO regulator * associated with a CPR3 regulator in preparation for BHS * mode switch. * @vreg: Pointer to the CPR3 regulator * @vdd_volt: Last known settled voltage in microvolts for the VDD * supply * @vdd_ceiling_volt: Last known aggregated ceiling voltage in microvolts for * the VDD supply * * This function performs the necessary steps to switch an LDO regulator * to BHS mode (LDO bypassed mode). * This function performs the necessary steps prior to switching a Kryo LDO * regulator to BHS mode (LDO bypassed mode). * * Return: 0 on success, errno on failure */ static int cpr3_regulator_set_bhs_mode(struct cpr3_regulator *vreg, static int cpr3_regulator_kryo_bhs_prepare(struct cpr3_regulator *vreg, int vdd_volt, int vdd_ceiling_volt) { struct regulator *ldo_reg = vreg->ldo_regulator; Loading @@ -1882,7 +1890,7 @@ static int cpr3_regulator_set_bhs_mode(struct cpr3_regulator *vreg, bhs_volt = vreg->ldo_max_volt; } rc = cpr3_regulator_config_ldo_mem_acc(vreg, bhs_volt); rc = cpr3_regulator_config_kryo_ldo_mem_acc(vreg, bhs_volt); if (rc) { cpr3_err(vreg, "failed to configure mem-acc settings\n"); return rc; Loading @@ -1896,9 +1904,40 @@ static int cpr3_regulator_set_bhs_mode(struct cpr3_regulator *vreg, return rc; } return rc; } /** * cpr3_regulator_set_bhs_mode() - configure the LDO regulator associated with * a CPR3 regulator to BHS mode * @vreg: Pointer to the CPR3 regulator * @vdd_volt: Last known settled voltage in microvolts for the VDD * supply * @vdd_ceiling_volt: Last known aggregated ceiling voltage in microvolts for * the VDD supply * * This function performs the necessary steps to switch an LDO regulator * to BHS mode (LDO bypassed mode). */ static int cpr3_regulator_set_bhs_mode(struct cpr3_regulator *vreg, int vdd_volt, int vdd_ceiling_volt) { struct regulator *ldo_reg = vreg->ldo_regulator; int rc; if (vreg->ldo_type == CPR3_LDO_KRYO) { rc = cpr3_regulator_kryo_bhs_prepare(vreg, vdd_volt, vdd_ceiling_volt); if (rc) { cpr3_err(vreg, "cpr3 regulator bhs mode prepare failed, rc=%d\n", rc); return rc; } } rc = regulator_allow_bypass(ldo_reg, BHS_MODE); if (rc) { cpr3_err(vreg, "regulator_allow_bypass(ldo) == %s failed, rc=%d\n", cpr3_err(vreg, "regulator_allow_bypass(bhs) == %s failed, rc=%d\n", BHS_MODE ? "true" : "false", rc); return rc; } Loading Loading @@ -2009,44 +2048,34 @@ static int cpr3_regulator_ldo_apm_prepare(struct cpr3_controller *ctrl, } /** * cpr3_regulator_config_vreg_ldo() - configure the voltage and bypass state for * the LDO regulator associated with a single CPR3 regulator. * cpr3_regulator_config_vreg_kryo_ldo() - configure the voltage and bypass * state for the Kryo 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 * @new_volt: New voltage in microvolts that VDD supply needs to * end up at * @ref_volt: Reference voltage in microvolts corresponds either to * the aggregated floor voltage or the next VDD supply * setpoint. * @last_volt: Last known voltage in microvolts for the VDD supply * * This function performs all relevant LDO or BHS configurations if an LDO * This function performs all relevant LDO or BHS configurations if a Kryo LDO * regulator is specified. * * Return: 0 on success, errno on failure */ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, static int cpr3_regulator_config_vreg_kryo_ldo(struct cpr3_regulator *vreg, int vdd_floor_volt, int vdd_ceiling_volt, int new_volt, int last_volt) int ref_volt, int last_volt) { struct cpr3_controller *ctrl = vreg->thread->ctrl; struct regulator *ldo_reg = vreg->ldo_regulator; struct cpr3_corner *current_corner; enum msm_apm_supply apm_mode; int rc, ldo_volt, final_ldo_volt, bhs_volt, max_volt, safe_volt; int ref_volt; ref_volt = ctrl->use_hw_closed_loop ? vdd_floor_volt : new_volt; rc = cpr3_regulator_config_ldo_retention(vreg, ref_volt); if (rc) return rc; if (!vreg->vreg_enabled || vreg->current_corner == CPR3_REGULATOR_CORNER_INVALID) return 0; current_corner = &vreg->corner[vreg->current_corner]; ldo_volt = current_corner->open_loop_volt Loading Loading @@ -2087,7 +2116,7 @@ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, bhs_volt), vreg->ldo_max_volt); rc = cpr3_regulator_config_ldo_mem_acc(vreg, rc = cpr3_regulator_config_kryo_ldo_mem_acc(vreg, safe_volt); if (rc) { cpr3_err(vreg, "failed to configure mem-acc settings\n"); Loading Loading @@ -2119,7 +2148,7 @@ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, else final_ldo_volt = ldo_volt; rc = cpr3_regulator_config_ldo_mem_acc(vreg, rc = cpr3_regulator_config_kryo_ldo_mem_acc(vreg, final_ldo_volt); if (rc) { cpr3_err(vreg, "failed to configure mem-acc settings\n"); Loading @@ -2145,6 +2174,115 @@ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, return 0; } /** * cpr3_regulator_config_vreg_ldo300() - configure the voltage and bypass state * for the LDO300 regulator associated with a single CPR3 * regulator. * * @vreg: Pointer to the CPR3 regulator * @new_volt: New voltage in microvolts that VDD supply needs to * end up at * @vdd_ceiling_volt: Last known aggregated ceiling voltage in microvolts for * the VDD supply * * This function performs all relevant LDO or BHS configurations for an LDO300 * type regulator. * * Return: 0 on success, errno on failure */ static int cpr3_regulator_config_vreg_ldo300(struct cpr3_regulator *vreg, int new_volt, int vdd_ceiling_volt) { struct regulator *ldo_reg = vreg->ldo_regulator; struct cpr3_corner *corner; bool mode; int rc = 0; corner = &vreg->corner[vreg->current_corner]; mode = corner->ldo_mode_allowed ? LDO_MODE : BHS_MODE; if (mode == LDO_MODE) { rc = regulator_set_voltage(ldo_reg, new_volt, vdd_ceiling_volt); if (rc) { cpr3_err(vreg, "regulator_set_voltage(ldo) == %d failed, rc=%d\n", new_volt, rc); return rc; } } if (vreg->ldo_regulator_bypass != mode) { rc = regulator_allow_bypass(ldo_reg, mode); if (rc) { cpr3_err(vreg, "regulator_allow_bypass(%s) is failed, rc=%d\n", mode == LDO_MODE ? "ldo" : "bhs", rc); return rc; } vreg->ldo_regulator_bypass = mode; } return rc; } /** * cpr3_regulator_config_vreg_ldo() - configure the voltage and bypass state for * 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 * @new_volt: New voltage in microvolts that VDD supply needs to * end up at * @last_volt: Last known voltage in microvolts for the VDD supply * * This function identifies the type of LDO regulator associated with a CPR3 * regulator and invokes the LDO specific configuration functions. * * Return: 0 on success, errno on failure */ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, int vdd_floor_volt, int vdd_ceiling_volt, int new_volt, int last_volt) { struct cpr3_controller *ctrl = vreg->thread->ctrl; int ref_volt, rc; ref_volt = ctrl->use_hw_closed_loop ? vdd_floor_volt : new_volt; rc = cpr3_regulator_config_ldo_retention(vreg, ref_volt); if (rc) return rc; if (!vreg->vreg_enabled || vreg->current_corner == CPR3_REGULATOR_CORNER_INVALID) return 0; switch (vreg->ldo_type) { case CPR3_LDO_KRYO: rc = cpr3_regulator_config_vreg_kryo_ldo(vreg, vdd_floor_volt, vdd_ceiling_volt, ref_volt, last_volt); if (rc) cpr3_err(vreg, "kryo ldo regulator config failed, rc=%d\n", rc); break; case CPR3_LDO300: rc = cpr3_regulator_config_vreg_ldo300(vreg, new_volt, vdd_ceiling_volt); if (rc) cpr3_err(vreg, "ldo300 regulator config failed, rc=%d\n", rc); break; default: cpr3_err(vreg, "invalid ldo regulator type = %d\n", vreg->ldo_type); rc = -EINVAL; } return rc; } /** * cpr3_regulator_config_ldo() - configure the voltage and bypass state for the * LDO regulator associated with each CPR3 regulator of a CPR3 Loading Loading @@ -2529,6 +2667,12 @@ static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl, int rc; if (new_volt < last_volt) { if (ctrl->support_ldo300_vreg) { rc = cpr3_regulator_config_mem_acc(ctrl, aggr_corner); if (rc) return rc; } /* Decreasing VDD voltage */ rc = cpr3_regulator_config_ldo(ctrl, aggr_corner->floor_volt, ctrl->aggr_corner.ceiling_volt, Loading @@ -2539,10 +2683,11 @@ static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl, return rc; } if (!ctrl->support_ldo300_vreg) { rc = cpr3_regulator_config_mem_acc(ctrl, aggr_corner); if (rc) return rc; } } else { /* Increasing VDD voltage */ if (ctrl->system_regulator) { Loading Loading @@ -2903,6 +3048,8 @@ static void cpr3_regulator_aggregate_corners(struct cpr3_corner *aggr_corner, aggr_corner->mem_acc_volt = max(aggr_corner->mem_acc_volt, corner->mem_acc_volt); aggr_corner->irq_en |= corner->irq_en; aggr_corner->use_open_loop |= corner->use_open_loop; aggr_corner->ldo_mode_allowed |= corner->ldo_mode_allowed; if (aggr_quot) { aggr_corner->ro_mask &= corner->ro_mask; Loading Loading @@ -3281,7 +3428,8 @@ static int _cpr3_regulator_update_ctrl_state(struct cpr3_controller *ctrl) * Only enable the CPR controller if it is possible to set more than * one vdd-supply voltage. */ if (aggr_corner.ceiling_volt > aggr_corner.floor_volt) if (aggr_corner.ceiling_volt > aggr_corner.floor_volt && !aggr_corner.use_open_loop) cpr3_ctrl_loop_enable(ctrl); ctrl->last_corner_was_closed_loop = ctrl->cpr_enabled; Loading drivers/regulator/cpr3-regulator.h +21 −0 Original line number Diff line number Diff line Loading @@ -141,6 +141,9 @@ struct cpr4_sdelta { * @use_open_loop: Boolean indicating that open-loop (i.e CPR disabled) as * opposed to closed-loop operation must be used for this * corner on CPRh controllers. * @ldo_mode_allowed: Boolean which indicates if LDO mode is allowed for this * corner. This field is applicable for CPR4 controllers * that manage LDO300 supply regulator. * @sdelta: The CPR4 controller specific data for this corner. This * field is applicable for CPR4 controllers. * Loading Loading @@ -174,6 +177,7 @@ struct cpr3_corner { u32 irq_en; int aging_derate; bool use_open_loop; bool ldo_mode_allowed; struct cpr4_sdelta *sdelta; }; Loading @@ -192,6 +196,18 @@ struct cprh_corner_band { struct cpr4_sdelta *sdelta; }; /** * enum cpr3_ldo_type - Constants which define the LDO supply regulator * types used to manage the subsystem component rail voltage. * %CPR3_LDO_KRYO: Kryo LDO regulator used to sub-regulate the HMSS * per-cluster voltage. * %CPR3_LDO300: LDO regulator used to sub-regulate the GFX voltage. */ enum cpr3_ldo_type { CPR3_LDO_KRYO = 0, CPR3_LDO300 = 1, }; /** * struct cpr3_regulator - CPR3 logical regulator instance associated with a * given CPR3 hardware thread Loading Loading @@ -275,6 +291,7 @@ struct cprh_corner_band { * participated in the last aggregation event * @debug_corner: Index identifying voltage corner used for displaying * corner configuration values in debugfs * @ldo_type: LDO regulator type. * @ldo_min_headroom_volt: Minimum voltage difference in microvolts required * between the VDD supply voltage and the LDO output in * order for the LDO operate Loading Loading @@ -358,6 +375,7 @@ struct cpr3_regulator { int last_closed_loop_corner; bool aggregated; int debug_corner; enum cpr3_ldo_type ldo_type; int ldo_min_headroom_volt; int ldo_max_headroom_volt; int ldo_adjust_volt; Loading Loading @@ -715,6 +733,8 @@ struct cpr3_panic_regs_info { * @panic_regs_info: Array of panic registers information which provides the * list of registers to dump when the device crashes. * @panic_notifier: Notifier block registered to global panic notifier list. * @support_ldo300_vreg: Boolean value which indicates that this CPR controller * manages an underlying LDO regulator of type LDO300. * * This structure contains both configuration and runtime state data. The * elements cpr_allowed_sw, use_hw_closed_loop, aggr_corner, cpr_enabled, Loading Loading @@ -815,6 +835,7 @@ struct cpr3_controller { u32 voltage_settling_time; struct cpr3_panic_regs_info *panic_regs_info; struct notifier_block panic_notifier; bool support_ldo300_vreg; }; /* Used for rounding voltages to the closest physically available set point. */ Loading drivers/regulator/kryo-regulator.c +5 −5 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> #include <linux/regulator/kryo-regulator.h> #include <linux/regulator/msm-ldo-regulator.h> #include <soc/qcom/spm.h> Loading Loading @@ -89,9 +89,9 @@ struct kryo_regulator { struct regulator_dev *retention_rdev; struct regulator_desc retention_desc; const char *name; enum kryo_supply_mode mode; enum kryo_supply_mode retention_mode; enum kryo_supply_mode pre_lpm_state_mode; enum msm_ldo_supply_mode mode; enum msm_ldo_supply_mode retention_mode; enum msm_ldo_supply_mode pre_lpm_state_mode; void __iomem *reg_base; void __iomem *pm_apcc_base; struct dentry *debugfs; Loading Loading @@ -248,7 +248,7 @@ static int kryo_set_ldo_volt(struct kryo_regulator *kvreg, int volt) /* Locks must be held by the caller */ static int kryo_configure_mode(struct kryo_regulator *kvreg, enum kryo_supply_mode mode) enum msm_ldo_supply_mode mode) { u32 reg; int timeout = PWR_GATE_SWITCH_TIMEOUT_US; Loading include/linux/regulator/kryo-regulator.h→include/linux/regulator/msm-ldo-regulator.h +7 −7 Original line number Diff line number Diff line /* * Copyright (c) 2015, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -11,22 +11,22 @@ * GNU General Public License for more details. */ #ifndef __KRYO_REGULATOR_H__ #define __KRYO_REGULATOR_H__ #ifndef __MSM_LDO_REGULATOR_H__ #define __MSM_LDO_REGULATOR_H__ /** * enum kryo_supply_mode - supported operating modes by this regulator type. * enum msm_ldo_supply_mode - supported operating modes by this regulator type. * Use negative logic to ensure BHS mode is treated as the safe default by the * the regulator framework. This is necessary since LDO mode can only be enabled * when several constraints are satisfied. Consumers of this regulator are * expected to request changes in operating modes through the use of * regulator_allow_bypass() passing in the desired Kryo supply mode. * regulator_allow_bypass() passing in the desired LDO supply mode. * %BHS_MODE: to select BHS as operating mode * %LDO_MODE: to select LDO as operating mode */ enum kryo_supply_mode { enum msm_ldo_supply_mode { BHS_MODE = false, LDO_MODE = true, }; #endif /* __KRYO_REGULATOR_H__ */ #endif /* __MSM_LDO_REGULATOR_H__ */ Loading
drivers/regulator/cpr3-hmss-regulator.c +1 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> #include <linux/regulator/kryo-regulator.h> #include <linux/regulator/msm-ldo-regulator.h> #include "cpr3-regulator.h" Loading
drivers/regulator/cpr3-regulator.c +186 −38 Original line number Diff line number Diff line Loading @@ -35,7 +35,7 @@ #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> #include <linux/regulator/kryo-regulator.h> #include <linux/regulator/msm-ldo-regulator.h> #include <soc/qcom/spm.h> Loading Loading @@ -1761,7 +1761,12 @@ static int cpr3_regulator_config_ldo_retention(struct cpr3_regulator *vreg, { struct regulator *ldo_ret_reg = vreg->ldo_ret_regulator; int retention_volt, rc; enum kryo_supply_mode mode; enum msm_ldo_supply_mode mode; if (!ldo_ret_reg) { /* LDO retention regulator is not defined */ return 0; } retention_volt = regulator_get_voltage(ldo_ret_reg); if (retention_volt < 0) { Loading @@ -1783,8 +1788,8 @@ static int cpr3_regulator_config_ldo_retention(struct cpr3_regulator *vreg, } /** * cpr3_regulator_config_ldo_mem_acc() - configure the mem-acc regulator * corner based upon a future LDO regulator voltage setpoint * cpr3_regulator_config_kryo_ldo_mem_acc() - configure the mem-acc regulator * corner based upon a future Kryo LDO regulator voltage setpoint * @vreg: Pointer to the CPR3 regulator * @new_volt: New voltage in microvolts that the LDO regulator needs * to end up at Loading @@ -1796,7 +1801,7 @@ static int cpr3_regulator_config_ldo_retention(struct cpr3_regulator *vreg, * * Return: 0 on success, errno on failure */ static int cpr3_regulator_config_ldo_mem_acc(struct cpr3_regulator *vreg, static int cpr3_regulator_config_kryo_ldo_mem_acc(struct cpr3_regulator *vreg, int new_volt) { struct cpr3_controller *ctrl = vreg->thread->ctrl; Loading Loading @@ -1858,18 +1863,21 @@ static int cpr3_regulator_config_ldo_mem_acc(struct cpr3_regulator *vreg, } /** * cpr3_regulator_set_bhs_mode() - configure the LDO regulator associated with * a CPR3 regulator to BHS mode * cpr3_regulator_kryo_bhs_prepare() - configure the Kryo LDO regulator * associated with a CPR3 regulator in preparation for BHS * mode switch. * @vreg: Pointer to the CPR3 regulator * @vdd_volt: Last known settled voltage in microvolts for the VDD * supply * @vdd_ceiling_volt: Last known aggregated ceiling voltage in microvolts for * the VDD supply * * This function performs the necessary steps to switch an LDO regulator * to BHS mode (LDO bypassed mode). * This function performs the necessary steps prior to switching a Kryo LDO * regulator to BHS mode (LDO bypassed mode). * * Return: 0 on success, errno on failure */ static int cpr3_regulator_set_bhs_mode(struct cpr3_regulator *vreg, static int cpr3_regulator_kryo_bhs_prepare(struct cpr3_regulator *vreg, int vdd_volt, int vdd_ceiling_volt) { struct regulator *ldo_reg = vreg->ldo_regulator; Loading @@ -1882,7 +1890,7 @@ static int cpr3_regulator_set_bhs_mode(struct cpr3_regulator *vreg, bhs_volt = vreg->ldo_max_volt; } rc = cpr3_regulator_config_ldo_mem_acc(vreg, bhs_volt); rc = cpr3_regulator_config_kryo_ldo_mem_acc(vreg, bhs_volt); if (rc) { cpr3_err(vreg, "failed to configure mem-acc settings\n"); return rc; Loading @@ -1896,9 +1904,40 @@ static int cpr3_regulator_set_bhs_mode(struct cpr3_regulator *vreg, return rc; } return rc; } /** * cpr3_regulator_set_bhs_mode() - configure the LDO regulator associated with * a CPR3 regulator to BHS mode * @vreg: Pointer to the CPR3 regulator * @vdd_volt: Last known settled voltage in microvolts for the VDD * supply * @vdd_ceiling_volt: Last known aggregated ceiling voltage in microvolts for * the VDD supply * * This function performs the necessary steps to switch an LDO regulator * to BHS mode (LDO bypassed mode). */ static int cpr3_regulator_set_bhs_mode(struct cpr3_regulator *vreg, int vdd_volt, int vdd_ceiling_volt) { struct regulator *ldo_reg = vreg->ldo_regulator; int rc; if (vreg->ldo_type == CPR3_LDO_KRYO) { rc = cpr3_regulator_kryo_bhs_prepare(vreg, vdd_volt, vdd_ceiling_volt); if (rc) { cpr3_err(vreg, "cpr3 regulator bhs mode prepare failed, rc=%d\n", rc); return rc; } } rc = regulator_allow_bypass(ldo_reg, BHS_MODE); if (rc) { cpr3_err(vreg, "regulator_allow_bypass(ldo) == %s failed, rc=%d\n", cpr3_err(vreg, "regulator_allow_bypass(bhs) == %s failed, rc=%d\n", BHS_MODE ? "true" : "false", rc); return rc; } Loading Loading @@ -2009,44 +2048,34 @@ static int cpr3_regulator_ldo_apm_prepare(struct cpr3_controller *ctrl, } /** * cpr3_regulator_config_vreg_ldo() - configure the voltage and bypass state for * the LDO regulator associated with a single CPR3 regulator. * cpr3_regulator_config_vreg_kryo_ldo() - configure the voltage and bypass * state for the Kryo 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 * @new_volt: New voltage in microvolts that VDD supply needs to * end up at * @ref_volt: Reference voltage in microvolts corresponds either to * the aggregated floor voltage or the next VDD supply * setpoint. * @last_volt: Last known voltage in microvolts for the VDD supply * * This function performs all relevant LDO or BHS configurations if an LDO * This function performs all relevant LDO or BHS configurations if a Kryo LDO * regulator is specified. * * Return: 0 on success, errno on failure */ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, static int cpr3_regulator_config_vreg_kryo_ldo(struct cpr3_regulator *vreg, int vdd_floor_volt, int vdd_ceiling_volt, int new_volt, int last_volt) int ref_volt, int last_volt) { struct cpr3_controller *ctrl = vreg->thread->ctrl; struct regulator *ldo_reg = vreg->ldo_regulator; struct cpr3_corner *current_corner; enum msm_apm_supply apm_mode; int rc, ldo_volt, final_ldo_volt, bhs_volt, max_volt, safe_volt; int ref_volt; ref_volt = ctrl->use_hw_closed_loop ? vdd_floor_volt : new_volt; rc = cpr3_regulator_config_ldo_retention(vreg, ref_volt); if (rc) return rc; if (!vreg->vreg_enabled || vreg->current_corner == CPR3_REGULATOR_CORNER_INVALID) return 0; current_corner = &vreg->corner[vreg->current_corner]; ldo_volt = current_corner->open_loop_volt Loading Loading @@ -2087,7 +2116,7 @@ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, bhs_volt), vreg->ldo_max_volt); rc = cpr3_regulator_config_ldo_mem_acc(vreg, rc = cpr3_regulator_config_kryo_ldo_mem_acc(vreg, safe_volt); if (rc) { cpr3_err(vreg, "failed to configure mem-acc settings\n"); Loading Loading @@ -2119,7 +2148,7 @@ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, else final_ldo_volt = ldo_volt; rc = cpr3_regulator_config_ldo_mem_acc(vreg, rc = cpr3_regulator_config_kryo_ldo_mem_acc(vreg, final_ldo_volt); if (rc) { cpr3_err(vreg, "failed to configure mem-acc settings\n"); Loading @@ -2145,6 +2174,115 @@ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, return 0; } /** * cpr3_regulator_config_vreg_ldo300() - configure the voltage and bypass state * for the LDO300 regulator associated with a single CPR3 * regulator. * * @vreg: Pointer to the CPR3 regulator * @new_volt: New voltage in microvolts that VDD supply needs to * end up at * @vdd_ceiling_volt: Last known aggregated ceiling voltage in microvolts for * the VDD supply * * This function performs all relevant LDO or BHS configurations for an LDO300 * type regulator. * * Return: 0 on success, errno on failure */ static int cpr3_regulator_config_vreg_ldo300(struct cpr3_regulator *vreg, int new_volt, int vdd_ceiling_volt) { struct regulator *ldo_reg = vreg->ldo_regulator; struct cpr3_corner *corner; bool mode; int rc = 0; corner = &vreg->corner[vreg->current_corner]; mode = corner->ldo_mode_allowed ? LDO_MODE : BHS_MODE; if (mode == LDO_MODE) { rc = regulator_set_voltage(ldo_reg, new_volt, vdd_ceiling_volt); if (rc) { cpr3_err(vreg, "regulator_set_voltage(ldo) == %d failed, rc=%d\n", new_volt, rc); return rc; } } if (vreg->ldo_regulator_bypass != mode) { rc = regulator_allow_bypass(ldo_reg, mode); if (rc) { cpr3_err(vreg, "regulator_allow_bypass(%s) is failed, rc=%d\n", mode == LDO_MODE ? "ldo" : "bhs", rc); return rc; } vreg->ldo_regulator_bypass = mode; } return rc; } /** * cpr3_regulator_config_vreg_ldo() - configure the voltage and bypass state for * 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 * @new_volt: New voltage in microvolts that VDD supply needs to * end up at * @last_volt: Last known voltage in microvolts for the VDD supply * * This function identifies the type of LDO regulator associated with a CPR3 * regulator and invokes the LDO specific configuration functions. * * Return: 0 on success, errno on failure */ static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg, int vdd_floor_volt, int vdd_ceiling_volt, int new_volt, int last_volt) { struct cpr3_controller *ctrl = vreg->thread->ctrl; int ref_volt, rc; ref_volt = ctrl->use_hw_closed_loop ? vdd_floor_volt : new_volt; rc = cpr3_regulator_config_ldo_retention(vreg, ref_volt); if (rc) return rc; if (!vreg->vreg_enabled || vreg->current_corner == CPR3_REGULATOR_CORNER_INVALID) return 0; switch (vreg->ldo_type) { case CPR3_LDO_KRYO: rc = cpr3_regulator_config_vreg_kryo_ldo(vreg, vdd_floor_volt, vdd_ceiling_volt, ref_volt, last_volt); if (rc) cpr3_err(vreg, "kryo ldo regulator config failed, rc=%d\n", rc); break; case CPR3_LDO300: rc = cpr3_regulator_config_vreg_ldo300(vreg, new_volt, vdd_ceiling_volt); if (rc) cpr3_err(vreg, "ldo300 regulator config failed, rc=%d\n", rc); break; default: cpr3_err(vreg, "invalid ldo regulator type = %d\n", vreg->ldo_type); rc = -EINVAL; } return rc; } /** * cpr3_regulator_config_ldo() - configure the voltage and bypass state for the * LDO regulator associated with each CPR3 regulator of a CPR3 Loading Loading @@ -2529,6 +2667,12 @@ static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl, int rc; if (new_volt < last_volt) { if (ctrl->support_ldo300_vreg) { rc = cpr3_regulator_config_mem_acc(ctrl, aggr_corner); if (rc) return rc; } /* Decreasing VDD voltage */ rc = cpr3_regulator_config_ldo(ctrl, aggr_corner->floor_volt, ctrl->aggr_corner.ceiling_volt, Loading @@ -2539,10 +2683,11 @@ static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl, return rc; } if (!ctrl->support_ldo300_vreg) { rc = cpr3_regulator_config_mem_acc(ctrl, aggr_corner); if (rc) return rc; } } else { /* Increasing VDD voltage */ if (ctrl->system_regulator) { Loading Loading @@ -2903,6 +3048,8 @@ static void cpr3_regulator_aggregate_corners(struct cpr3_corner *aggr_corner, aggr_corner->mem_acc_volt = max(aggr_corner->mem_acc_volt, corner->mem_acc_volt); aggr_corner->irq_en |= corner->irq_en; aggr_corner->use_open_loop |= corner->use_open_loop; aggr_corner->ldo_mode_allowed |= corner->ldo_mode_allowed; if (aggr_quot) { aggr_corner->ro_mask &= corner->ro_mask; Loading Loading @@ -3281,7 +3428,8 @@ static int _cpr3_regulator_update_ctrl_state(struct cpr3_controller *ctrl) * Only enable the CPR controller if it is possible to set more than * one vdd-supply voltage. */ if (aggr_corner.ceiling_volt > aggr_corner.floor_volt) if (aggr_corner.ceiling_volt > aggr_corner.floor_volt && !aggr_corner.use_open_loop) cpr3_ctrl_loop_enable(ctrl); ctrl->last_corner_was_closed_loop = ctrl->cpr_enabled; Loading
drivers/regulator/cpr3-regulator.h +21 −0 Original line number Diff line number Diff line Loading @@ -141,6 +141,9 @@ struct cpr4_sdelta { * @use_open_loop: Boolean indicating that open-loop (i.e CPR disabled) as * opposed to closed-loop operation must be used for this * corner on CPRh controllers. * @ldo_mode_allowed: Boolean which indicates if LDO mode is allowed for this * corner. This field is applicable for CPR4 controllers * that manage LDO300 supply regulator. * @sdelta: The CPR4 controller specific data for this corner. This * field is applicable for CPR4 controllers. * Loading Loading @@ -174,6 +177,7 @@ struct cpr3_corner { u32 irq_en; int aging_derate; bool use_open_loop; bool ldo_mode_allowed; struct cpr4_sdelta *sdelta; }; Loading @@ -192,6 +196,18 @@ struct cprh_corner_band { struct cpr4_sdelta *sdelta; }; /** * enum cpr3_ldo_type - Constants which define the LDO supply regulator * types used to manage the subsystem component rail voltage. * %CPR3_LDO_KRYO: Kryo LDO regulator used to sub-regulate the HMSS * per-cluster voltage. * %CPR3_LDO300: LDO regulator used to sub-regulate the GFX voltage. */ enum cpr3_ldo_type { CPR3_LDO_KRYO = 0, CPR3_LDO300 = 1, }; /** * struct cpr3_regulator - CPR3 logical regulator instance associated with a * given CPR3 hardware thread Loading Loading @@ -275,6 +291,7 @@ struct cprh_corner_band { * participated in the last aggregation event * @debug_corner: Index identifying voltage corner used for displaying * corner configuration values in debugfs * @ldo_type: LDO regulator type. * @ldo_min_headroom_volt: Minimum voltage difference in microvolts required * between the VDD supply voltage and the LDO output in * order for the LDO operate Loading Loading @@ -358,6 +375,7 @@ struct cpr3_regulator { int last_closed_loop_corner; bool aggregated; int debug_corner; enum cpr3_ldo_type ldo_type; int ldo_min_headroom_volt; int ldo_max_headroom_volt; int ldo_adjust_volt; Loading Loading @@ -715,6 +733,8 @@ struct cpr3_panic_regs_info { * @panic_regs_info: Array of panic registers information which provides the * list of registers to dump when the device crashes. * @panic_notifier: Notifier block registered to global panic notifier list. * @support_ldo300_vreg: Boolean value which indicates that this CPR controller * manages an underlying LDO regulator of type LDO300. * * This structure contains both configuration and runtime state data. The * elements cpr_allowed_sw, use_hw_closed_loop, aggr_corner, cpr_enabled, Loading Loading @@ -815,6 +835,7 @@ struct cpr3_controller { u32 voltage_settling_time; struct cpr3_panic_regs_info *panic_regs_info; struct notifier_block panic_notifier; bool support_ldo300_vreg; }; /* Used for rounding voltages to the closest physically available set point. */ Loading
drivers/regulator/kryo-regulator.c +5 −5 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> #include <linux/regulator/kryo-regulator.h> #include <linux/regulator/msm-ldo-regulator.h> #include <soc/qcom/spm.h> Loading Loading @@ -89,9 +89,9 @@ struct kryo_regulator { struct regulator_dev *retention_rdev; struct regulator_desc retention_desc; const char *name; enum kryo_supply_mode mode; enum kryo_supply_mode retention_mode; enum kryo_supply_mode pre_lpm_state_mode; enum msm_ldo_supply_mode mode; enum msm_ldo_supply_mode retention_mode; enum msm_ldo_supply_mode pre_lpm_state_mode; void __iomem *reg_base; void __iomem *pm_apcc_base; struct dentry *debugfs; Loading Loading @@ -248,7 +248,7 @@ static int kryo_set_ldo_volt(struct kryo_regulator *kvreg, int volt) /* Locks must be held by the caller */ static int kryo_configure_mode(struct kryo_regulator *kvreg, enum kryo_supply_mode mode) enum msm_ldo_supply_mode mode) { u32 reg; int timeout = PWR_GATE_SWITCH_TIMEOUT_US; Loading
include/linux/regulator/kryo-regulator.h→include/linux/regulator/msm-ldo-regulator.h +7 −7 Original line number Diff line number Diff line /* * Copyright (c) 2015, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -11,22 +11,22 @@ * GNU General Public License for more details. */ #ifndef __KRYO_REGULATOR_H__ #define __KRYO_REGULATOR_H__ #ifndef __MSM_LDO_REGULATOR_H__ #define __MSM_LDO_REGULATOR_H__ /** * enum kryo_supply_mode - supported operating modes by this regulator type. * enum msm_ldo_supply_mode - supported operating modes by this regulator type. * Use negative logic to ensure BHS mode is treated as the safe default by the * the regulator framework. This is necessary since LDO mode can only be enabled * when several constraints are satisfied. Consumers of this regulator are * expected to request changes in operating modes through the use of * regulator_allow_bypass() passing in the desired Kryo supply mode. * regulator_allow_bypass() passing in the desired LDO supply mode. * %BHS_MODE: to select BHS as operating mode * %LDO_MODE: to select LDO as operating mode */ enum kryo_supply_mode { enum msm_ldo_supply_mode { BHS_MODE = false, LDO_MODE = true, }; #endif /* __KRYO_REGULATOR_H__ */ #endif /* __MSM_LDO_REGULATOR_H__ */