summaryrefslogtreecommitdiff
path: root/drivers/power
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-02-09 03:11:52 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-02-09 03:11:51 -0800
commit91b231673d5c6ef00469eaefc5f4310ab2e982af (patch)
tree9f7118704cdd639374e7b75993b3eb5bd1f5ffed /drivers/power
parent2d3372a5f8dea7765e04ed7eb4f9c9aa5499f001 (diff)
parent6e1f3205b4356b12948e135d72b559e7a9d6963b (diff)
Merge "qpnp: smb2: Add charger frequency config for PM660"
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c39
-rw-r--r--drivers/power/supply/qcom/smb-lib.c124
-rw-r--r--drivers/power/supply/qcom/smb-lib.h13
-rw-r--r--drivers/power/supply/qcom/smb-reg.h4
4 files changed, 131 insertions, 49 deletions
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index f8171ecc47f3..4e9d2894479a 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -219,6 +219,23 @@ static struct smb_params v1_params = {
},
};
+static struct smb_params pm660_params = {
+ .freq_buck = {
+ .name = "buck switching frequency",
+ .reg = FREQ_CLK_DIV_REG,
+ .min_u = 600,
+ .max_u = 1600,
+ .set_proc = smblib_set_chg_freq,
+ },
+ .freq_boost = {
+ .name = "boost switching frequency",
+ .reg = FREQ_CLK_DIV_REG,
+ .min_u = 600,
+ .max_u = 1600,
+ .set_proc = smblib_set_chg_freq,
+ },
+};
+
#define STEP_CHARGING_MAX_STEPS 5
struct smb_dt_props {
int fcc_ua;
@@ -1530,7 +1547,7 @@ static int smb2_init_hw(struct smb2 *chip)
return rc;
}
-static int smb2_setup_wa_flags(struct smb2 *chip)
+static int smb2_chg_config_init(struct smb2 *chip)
{
struct smb_charger *chg = &chip->chg;
struct pmic_revid_data *pmic_rev_id;
@@ -1560,9 +1577,25 @@ static int smb2_setup_wa_flags(struct smb2 *chip)
chg->wa_flags |= QC_CHARGER_DETECTION_WA_BIT;
if (pmic_rev_id->rev4 == PMI8998_V2P0_REV4) /* PMI rev 2.0 */
chg->wa_flags |= TYPEC_CC2_REMOVAL_WA_BIT;
+ chg->chg_freq.freq_5V = 600;
+ chg->chg_freq.freq_6V_8V = 800;
+ chg->chg_freq.freq_9V = 1000;
+ chg->chg_freq.freq_12V = 1200;
+ chg->chg_freq.freq_removal = 1000;
+ chg->chg_freq.freq_below_otg_threshold = 2000;
+ chg->chg_freq.freq_above_otg_threshold = 800;
break;
case PM660_SUBTYPE:
chip->chg.wa_flags |= BOOST_BACK_WA;
+ chg->param.freq_buck = pm660_params.freq_buck;
+ chg->param.freq_boost = pm660_params.freq_boost;
+ chg->chg_freq.freq_5V = 600;
+ chg->chg_freq.freq_6V_8V = 800;
+ chg->chg_freq.freq_9V = 1050;
+ chg->chg_freq.freq_12V = 1200;
+ chg->chg_freq.freq_removal = 1050;
+ chg->chg_freq.freq_below_otg_threshold = 1600;
+ chg->chg_freq.freq_above_otg_threshold = 800;
break;
default:
pr_err("PMIC subtype %d not supported\n",
@@ -1951,10 +1984,10 @@ static int smb2_probe(struct platform_device *pdev)
return -EINVAL;
}
- rc = smb2_setup_wa_flags(chip);
+ rc = smb2_chg_config_init(chip);
if (rc < 0) {
if (rc != -EPROBE_DEFER)
- pr_err("Couldn't setup wa flags rc=%d\n", rc);
+ pr_err("Couldn't setup chg_config rc=%d\n", rc);
return rc;
}
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index ee5b5a51465b..16edf875de96 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -39,7 +39,7 @@
static bool is_secure(struct smb_charger *chg, int addr)
{
- if (addr == SHIP_MODE_REG)
+ if (addr == SHIP_MODE_REG || addr == FREQ_CLK_DIV_REG)
return true;
/* assume everything above 0xA0 is secure */
return (bool)((addr & 0xFF) >= 0xA0);
@@ -193,34 +193,6 @@ 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;
@@ -325,6 +297,58 @@ static const struct apsd_result *smblib_get_apsd_result(struct smb_charger *chg)
* REGISTER SETTERS *
********************/
+static int chg_freq_list[] = {
+ 9600, 9600, 6400, 4800, 3800, 3200, 2700, 2400, 2100, 1900, 1700,
+ 1600, 1500, 1400, 1300, 1200,
+};
+
+int smblib_set_chg_freq(struct smb_chg_param *param,
+ int val_u, u8 *val_raw)
+{
+ u8 i;
+
+ if (val_u > param->max_u || val_u < param->min_u)
+ return -EINVAL;
+
+ /* Charger FSW is the configured freqency / 2 */
+ val_u *= 2;
+ for (i = 0; i < ARRAY_SIZE(chg_freq_list); i++) {
+ if (chg_freq_list[i] == val_u)
+ break;
+ }
+ if (i == ARRAY_SIZE(chg_freq_list)) {
+ pr_err("Invalid frequency %d Hz\n", val_u / 2);
+ return -EINVAL;
+ }
+
+ *val_raw = i;
+
+ return 0;
+}
+
+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;
+}
+
int smblib_set_charge_param(struct smb_charger *chg,
struct smb_chg_param *param, int val_u)
{
@@ -417,13 +441,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);
+ smblib_set_opt_freq_buck(chg, chg->chg_freq.freq_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);
+ smblib_set_opt_freq_buck(chg, chg->chg_freq.freq_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);
+ smblib_set_opt_freq_buck(chg, chg->chg_freq.freq_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) {
@@ -1981,8 +2005,6 @@ int smblib_set_prop_usb_current_max(struct smb_charger *chg,
return rc;
}
-#define FSW_2MHZ 2000
-#define FSW_800KHZ_RESET 800
int smblib_set_prop_boost_current(struct smb_charger *chg,
const union power_supply_propval *val)
{
@@ -1990,7 +2012,8 @@ int smblib_set_prop_boost_current(struct smb_charger *chg,
rc = smblib_set_charge_param(chg, &chg->param.freq_boost,
val->intval <= chg->boost_threshold_ua ?
- FSW_2MHZ : FSW_800KHZ_RESET);
+ chg->chg_freq.freq_below_otg_threshold :
+ chg->chg_freq.freq_above_otg_threshold);
if (rc < 0) {
dev_err(chg->dev, "Error in setting freq_boost rc=%d\n", rc);
return rc;
@@ -2581,7 +2604,8 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
vbus_rising = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT);
smblib_set_opt_freq_buck(chg,
- vbus_rising ? FSW_600HZ_FOR_5V : FSW_1MHZ_FOR_REMOVAL);
+ vbus_rising ? chg->chg_freq.freq_5V :
+ chg->chg_freq.freq_removal);
/* fetch the DPDM regulator */
if (!chg->dpdm_reg && of_get_property(chg->dev->of_node,
@@ -2687,16 +2711,20 @@ static void smblib_hvdcp_adaptive_voltage_change(struct smb_charger *chg)
switch (stat & QC_2P0_STATUS_MASK) {
case QC_5V_BIT:
- smblib_set_opt_freq_buck(chg, FSW_600HZ_FOR_5V);
+ smblib_set_opt_freq_buck(chg,
+ chg->chg_freq.freq_5V);
break;
case QC_9V_BIT:
- smblib_set_opt_freq_buck(chg, FSW_1MHZ_FOR_9V);
+ smblib_set_opt_freq_buck(chg,
+ chg->chg_freq.freq_9V);
break;
case QC_12V_BIT:
- smblib_set_opt_freq_buck(chg, FSW_1P2MHZ_FOR_12V);
+ smblib_set_opt_freq_buck(chg,
+ chg->chg_freq.freq_12V);
break;
default:
- smblib_set_opt_freq_buck(chg, FSW_1MHZ_FOR_REMOVAL);
+ smblib_set_opt_freq_buck(chg,
+ chg->chg_freq.freq_removal);
break;
}
}
@@ -2711,14 +2739,17 @@ static void smblib_hvdcp_adaptive_voltage_change(struct smb_charger *chg)
pulses = (stat & QC_PULSE_COUNT_MASK);
if (pulses < QC3_PULSES_FOR_6V)
- smblib_set_opt_freq_buck(chg, FSW_600HZ_FOR_5V);
+ smblib_set_opt_freq_buck(chg,
+ chg->chg_freq.freq_5V);
else if (pulses < QC3_PULSES_FOR_9V)
- smblib_set_opt_freq_buck(chg, FSW_800HZ_FOR_6V_8V);
+ smblib_set_opt_freq_buck(chg,
+ chg->chg_freq.freq_6V_8V);
else if (pulses < QC3_PULSES_FOR_12V)
- smblib_set_opt_freq_buck(chg, FSW_1MHZ_FOR_9V);
+ smblib_set_opt_freq_buck(chg,
+ chg->chg_freq.freq_9V);
else
- smblib_set_opt_freq_buck(chg, FSW_1P2MHZ_FOR_12V);
-
+ smblib_set_opt_freq_buck(chg,
+ chg->chg_freq.freq_12V);
}
}
@@ -2915,7 +2946,8 @@ static void typec_sink_insertion(struct smb_charger *chg)
static void typec_sink_removal(struct smb_charger *chg)
{
- smblib_set_charge_param(chg, &chg->param.freq_boost, FSW_800KHZ_RESET);
+ smblib_set_charge_param(chg, &chg->param.freq_boost,
+ chg->chg_freq.freq_above_otg_threshold);
chg->boost_current_ua = 0;
}
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index cda4b80939ec..e341484bc2ec 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -105,6 +105,16 @@ struct smb_chg_param {
u8 *val_raw);
};
+struct smb_chg_freq {
+ unsigned int freq_5V;
+ unsigned int freq_6V_8V;
+ unsigned int freq_9V;
+ unsigned int freq_12V;
+ unsigned int freq_removal;
+ unsigned int freq_below_otg_threshold;
+ unsigned int freq_above_otg_threshold;
+};
+
struct smb_params {
struct smb_chg_param fcc;
struct smb_chg_param fv;
@@ -158,6 +168,7 @@ struct smb_charger {
int *debug_mask;
enum smb_mode mode;
bool external_vconn;
+ struct smb_chg_freq chg_freq;
/* locks */
struct mutex write_lock;
@@ -264,6 +275,8 @@ int smblib_mapping_cc_delta_to_field_value(struct smb_chg_param *param,
u8 val_raw);
int smblib_mapping_cc_delta_from_field_value(struct smb_chg_param *param,
int val_u, u8 *val_raw);
+int smblib_set_chg_freq(struct smb_chg_param *param,
+ int val_u, u8 *val_raw);
int smblib_vbus_regulator_enable(struct regulator_dev *rdev);
int smblib_vbus_regulator_disable(struct regulator_dev *rdev);
diff --git a/drivers/power/supply/qcom/smb-reg.h b/drivers/power/supply/qcom/smb-reg.h
index b5de39de995a..f238b055d271 100644
--- a/drivers/power/supply/qcom/smb-reg.h
+++ b/drivers/power/supply/qcom/smb-reg.h
@@ -21,6 +21,7 @@
#define USBIN_BASE 0x1300
#define DCIN_BASE 0x1400
#define MISC_BASE 0x1600
+#define CHGR_FREQ_BASE 0x1900
#define PERPH_TYPE_OFFSET 0x04
#define TYPE_MASK GENMASK(7, 0)
@@ -1015,4 +1016,7 @@ enum {
#define CFG_BUCKBOOST_FREQ_SELECT_BUCK_REG (MISC_BASE + 0xA0)
#define CFG_BUCKBOOST_FREQ_SELECT_BOOST_REG (MISC_BASE + 0xA1)
+/* CHGR FREQ Peripheral registers */
+#define FREQ_CLK_DIV_REG (CHGR_FREQ_BASE + 0x50)
+
#endif /* __SMB2_CHARGER_REG_H */