qcom-charger: set optimal buck switching frequency

Reduce the power dissipation impact by choosing the optimal
switching frequency per input voltage.

The optimal switching frequences are chosen as follow,
	5V only = 600kHz
	6-8V QC3 = 800kHz
	9V QC2 or vanilla PD = 1.0MHz
	12V QC2 or PD adapter = 1.2MHz

CRs-Fixed: 1048242
Change-Id: I2ef9f3e122b39682a743334668fcd0aeb085e147
Signed-off-by: Harry Yang <harryy@codeaurora.org>
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
This commit is contained in:
Harry Yang 2016-10-04 17:03:56 -07:00
parent 46aa49c118
commit b6d0253492
3 changed files with 121 additions and 8 deletions

View file

@ -203,6 +203,13 @@ static struct smb_params v1_params = {
.get_proc = smblib_mapping_cc_delta_to_field_value,
.set_proc = smblib_mapping_cc_delta_from_field_value,
},
.freq_buck = {
.name = "buck switching frequency",
.reg = CFG_BUCKBOOST_FREQ_SELECT_BUCK_REG,
.min_u = 600,
.max_u = 2000,
.step_u = 200,
},
};
#define STEP_CHARGING_MAX_STEPS 5

View file

@ -220,6 +220,34 @@ int smblib_get_usb_suspend(struct smb_charger *chg, int *suspend)
return rc;
}
#define FSW_600HZ_FOR_5V 600
#define FSW_800HZ_FOR_6V_8V 800
#define FSW_1MHZ_FOR_REMOVAL 1000
#define FSW_1MHZ_FOR_9V 1000
#define FSW_1P2MHZ_FOR_12V 1200
static int smblib_set_opt_freq_buck(struct smb_charger *chg, int fsw_khz)
{
union power_supply_propval pval = {0, };
int rc = 0;
rc = smblib_set_charge_param(chg, &chg->param.freq_buck, fsw_khz);
if (rc < 0)
dev_err(chg->dev, "Error in setting freq_buck rc=%d\n", rc);
if (chg->mode == PARALLEL_MASTER && chg->pl.psy) {
pval.intval = fsw_khz;
rc = power_supply_set_property(chg->pl.psy,
POWER_SUPPLY_PROP_BUCK_FREQ, &pval);
if (rc < 0) {
dev_err(chg->dev,
"Could not set parallel buck_freq rc=%d\n", rc);
return rc;
}
}
return rc;
}
struct apsd_result {
const char * const name;
const u8 bit;
@ -416,10 +444,13 @@ static int smblib_set_usb_pd_allowed_voltage(struct smb_charger *chg,
if (min_allowed_uv == MICRO_5V && max_allowed_uv == MICRO_5V) {
allowed_voltage = USBIN_ADAPTER_ALLOW_5V;
smblib_set_opt_freq_buck(chg, FSW_600HZ_FOR_5V);
} else if (min_allowed_uv == MICRO_9V && max_allowed_uv == MICRO_9V) {
allowed_voltage = USBIN_ADAPTER_ALLOW_9V;
smblib_set_opt_freq_buck(chg, FSW_1MHZ_FOR_9V);
} else if (min_allowed_uv == MICRO_12V && max_allowed_uv == MICRO_12V) {
allowed_voltage = USBIN_ADAPTER_ALLOW_12V;
smblib_set_opt_freq_buck(chg, FSW_1P2MHZ_FOR_12V);
} else if (min_allowed_uv < MICRO_9V && max_allowed_uv <= MICRO_9V) {
allowed_voltage = USBIN_ADAPTER_ALLOW_5V_TO_9V;
} else if (min_allowed_uv < MICRO_9V && max_allowed_uv <= MICRO_12V) {
@ -2167,6 +2198,16 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
int rc;
u8 stat;
rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
if (rc < 0) {
dev_err(chg->dev, "Couldn't read USB_INT_RT_STS rc=%d\n", rc);
return IRQ_HANDLED;
}
chg->vbus_present = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT);
smblib_set_opt_freq_buck(chg,
chg->vbus_present ? FSW_600HZ_FOR_5V : FSW_1MHZ_FOR_REMOVAL);
/* fetch the DPDM regulator */
if (!chg->dpdm_reg && of_get_property(chg->dev->of_node,
"dpdm-supply", NULL)) {
@ -2181,14 +2222,6 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
if (!chg->dpdm_reg)
goto skip_dpdm_float;
rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
if (rc < 0) {
smblib_err(chg, "Couldn't read USB_INT_RT_STS rc=%d\n", rc);
return IRQ_HANDLED;
}
chg->vbus_present = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT);
if (chg->vbus_present) {
if (!regulator_is_enabled(chg->dpdm_reg)) {
smblib_dbg(chg, PR_MISC, "enabling DPDM regulator\n");
@ -2260,6 +2293,60 @@ static void smblib_handle_sdp_enumeration_done(struct smb_charger *chg,
rising ? "rising" : "falling");
}
#define QC3_PULSES_FOR_6V 5
#define QC3_PULSES_FOR_9V 20
#define QC3_PULSES_FOR_12V 35
static void smblib_hvdcp_adaptive_voltage_change(struct smb_charger *chg)
{
int rc;
u8 stat;
int pulses;
if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_HVDCP) {
rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat);
if (rc < 0) {
smblib_err(chg,
"Couldn't read QC_CHANGE_STATUS rc=%d\n", rc);
return;
}
switch (stat & QC_2P0_STATUS_MASK) {
case QC_5V_BIT:
smblib_set_opt_freq_buck(chg, FSW_600HZ_FOR_5V);
break;
case QC_9V_BIT:
smblib_set_opt_freq_buck(chg, FSW_1MHZ_FOR_9V);
break;
case QC_12V_BIT:
smblib_set_opt_freq_buck(chg, FSW_1P2MHZ_FOR_12V);
break;
default:
smblib_set_opt_freq_buck(chg, FSW_1MHZ_FOR_REMOVAL);
break;
}
}
if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_HVDCP_3) {
rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, &stat);
if (rc < 0) {
smblib_err(chg,
"Couldn't read QC_PULSE_COUNT rc=%d\n", rc);
return;
}
pulses = (stat & QC_PULSE_COUNT_MASK);
if (pulses < QC3_PULSES_FOR_6V)
smblib_set_opt_freq_buck(chg, FSW_600HZ_FOR_5V);
else if (pulses < QC3_PULSES_FOR_9V)
smblib_set_opt_freq_buck(chg, FSW_800HZ_FOR_6V_8V);
else if (pulses < QC3_PULSES_FOR_12V)
smblib_set_opt_freq_buck(chg, FSW_1MHZ_FOR_9V);
else
smblib_set_opt_freq_buck(chg, FSW_1P2MHZ_FOR_12V);
}
}
static void smblib_handle_adaptive_voltage_done(struct smb_charger *chg,
bool rising)
{
@ -2272,10 +2359,20 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg,
bool rising)
{
const struct apsd_result *apsd_result;
int rc;
if (!rising)
return;
/*
* Disable AUTH_IRQ_EN_CFG_BIT to receive adapter voltage
* change interrupt.
*/
rc = smblib_masked_write(chg, USBIN_SOURCE_CHANGE_INTRPT_ENB_REG,
AUTH_IRQ_EN_CFG_BIT, 0);
if (rc < 0)
smblib_err(chg, "Couldn't enable QC auth setting rc=%d\n", rc);
if (chg->mode == PARALLEL_MASTER)
vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, true, 0);
@ -2381,6 +2478,8 @@ irqreturn_t smblib_handle_usb_source_change(int irq, void *data)
smblib_handle_slow_plugin_timeout(chg,
(bool)(stat & SLOW_PLUGIN_TIMEOUT_BIT));
smblib_hvdcp_adaptive_voltage_change(chg);
power_supply_changed(chg->usb_psy);
return IRQ_HANDLED;
@ -2399,6 +2498,12 @@ static void typec_source_removal(struct smb_charger *chg)
cancel_delayed_work_sync(&chg->hvdcp_detect_work);
/* reset AUTH_IRQ_EN_CFG_BIT */
rc = smblib_masked_write(chg, USBIN_SOURCE_CHANGE_INTRPT_ENB_REG,
AUTH_IRQ_EN_CFG_BIT, AUTH_IRQ_EN_CFG_BIT);
if (rc < 0)
smblib_err(chg, "Couldn't enable QC auth setting rc=%d\n", rc);
/* reconfigure allowed voltage for HVDCP */
rc = smblib_write(chg, USBIN_ADAPTER_ALLOW_CFG_REG,
USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V);

View file

@ -428,6 +428,7 @@ enum {
#define USBIN_5V_TO_12V_BIT BIT(2)
#define USBIN_5V_TO_9V_BIT BIT(1)
#define USBIN_5V_BIT BIT(0)
#define QC_2P0_STATUS_MASK GENMASK(2, 0)
#define APSD_STATUS_REG (USBIN_BASE + 0x07)
#define APSD_STATUS_7_BIT BIT(7)