diff --git a/Documentation/devicetree/bindings/power/qcom-charger/smb138x-charger.txt b/Documentation/devicetree/bindings/power/qcom-charger/smb138x-charger.txt index d41ffcaa4cae..0549c439460c 100644 --- a/Documentation/devicetree/bindings/power/qcom-charger/smb138x-charger.txt +++ b/Documentation/devicetree/bindings/power/qcom-charger/smb138x-charger.txt @@ -24,6 +24,13 @@ Charger specific properties: Standalone/Parallel Master - "qcom,smb138x-charger" Parallel Slave - "qcom,smb138x-parallel-slave" +- qcom,pmic-revid + Usage: required + Value type: phandle + Definition: Should specify the phandle of SMB's + revid module. This is used to identify + the SMB subtype. + - qcom,suspend-input Usage: optional Value type: diff --git a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi index ba25d2f07736..b84f63ecbd1e 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi @@ -370,8 +370,14 @@ #interrupt-cells = <3>; qcom,periph-map = <0x10 0x11 0x12 0x13 0x14 0x16 0x36>; + smb138x_revid: qcom,revid@100 { + compatible = "qcom,qpnp-revid"; + reg = <0x100 0x100>; + }; + smb138x_parallel_slave: qcom,smb138x-parallel-slave@1000 { compatible = "qcom,smb138x-parallel-slave"; + qcom,pmic-revid = <&smb138x_revid>; reg = <0x1000 0x700>; }; }; diff --git a/drivers/power/qcom-charger/smb138x-charger.c b/drivers/power/qcom-charger/smb138x-charger.c index e9006cfc0b9e..329ee7210c1f 100644 --- a/drivers/power/qcom-charger/smb138x-charger.c +++ b/drivers/power/qcom-charger/smb138x-charger.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "smb-reg.h" #include "smb-lib.h" #include "pmic-voter.h" @@ -29,6 +30,14 @@ #define SMB138X_DEFAULT_FCC_UA 1000000 #define SMB138X_DEFAULT_ICL_UA 1500000 +/* Registers that are not common to be mentioned in smb-reg.h */ +#define SMB2CHG_MISC_ENG_SDCDC_CFG2 (MISC_BASE + 0xC1) +#define ENG_SDCDC_SEL_OOB_VTH_BIT BIT(0) + +enum { + OOB_COMP_WA_BIT = BIT(0), +}; + static struct smb_params v1_params = { .fcc = { .name = "fast charge current", @@ -68,6 +77,7 @@ struct smb_dt_props { }; struct smb138x { + u32 wa_flags; struct smb_charger chg; struct smb_dt_props dt; struct power_supply *parallel_psy; @@ -625,9 +635,56 @@ static int smb138x_init_hw(struct smb138x *chip) return rc; } + if (chip->wa_flags & OOB_COMP_WA_BIT) { + rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG2, + ENG_SDCDC_SEL_OOB_VTH_BIT, + ENG_SDCDC_SEL_OOB_VTH_BIT); + if (rc < 0) { + dev_err(chg->dev, + "Couldn't configure the oob comp threh rc = %d\n", rc); + return rc; + } + } + return rc; } +static int smb138x_setup_wa_flags(struct smb138x *chip) +{ + struct pmic_revid_data *pmic_rev_id; + struct device_node *revid_dev_node; + + revid_dev_node = of_parse_phandle(chip->chg.dev->of_node, + "qcom,pmic-revid", 0); + if (!revid_dev_node) { + pr_err("Missing qcom,pmic-revid property\n"); + return -EINVAL; + } + + pmic_rev_id = get_revid_data(revid_dev_node); + if (IS_ERR_OR_NULL(pmic_rev_id)) { + /* + * the revid peripheral must be registered, any failure + * here only indicates that the rev-id module has not + * probed yet. + */ + return -EPROBE_DEFER; + } + + switch (pmic_rev_id->pmic_subtype) { + case SMB1381_SUBTYPE: + if (pmic_rev_id->rev4 < 2) /* SMB1381 rev 1.0 */ + chip->wa_flags |= OOB_COMP_WA_BIT; + break; + default: + pr_err("PMIC subtype %d not supported\n", + pmic_rev_id->pmic_subtype); + return -EINVAL; + } + + return 0; +} + /**************************** * DETERMINE INITIAL STATUS * ****************************/ @@ -857,6 +914,17 @@ static int smb138x_slave_probe(struct smb138x *chip) return rc; } + if (chip->wa_flags & OOB_COMP_WA_BIT) { + rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG2, + ENG_SDCDC_SEL_OOB_VTH_BIT, + ENG_SDCDC_SEL_OOB_VTH_BIT); + if (rc < 0) { + dev_err(chg->dev, + "Couldn't configure the oob comp threh rc = %d\n", rc); + return rc; + } + } + /* suspend usb input */ rc = smblib_set_usb_suspend(chg, true); if (rc < 0) { @@ -938,6 +1006,13 @@ static int smb138x_probe(struct platform_device *pdev) platform_set_drvdata(pdev, chip); + rc = smb138x_setup_wa_flags(chip); + if (rc < 0) { + if (rc != -EPROBE_DEFER) + pr_err("Couldn't setup wa flags rc = %d\n", rc); + return rc; + } + chip->chg.mode = (enum smb_mode) id->data; switch (chip->chg.mode) { case PARALLEL_MASTER: diff --git a/include/linux/qpnp/qpnp-revid.h b/include/linux/qpnp/qpnp-revid.h index 388296c53460..b13ebe50c3d6 100644 --- a/include/linux/qpnp/qpnp-revid.h +++ b/include/linux/qpnp/qpnp-revid.h @@ -201,6 +201,9 @@ /* PMI8937 */ #define PMI8937_SUBTYPE 0x37 +/* SMB1381 */ +#define SMB1381_SUBTYPE 0x17 + struct pmic_revid_data { u8 rev1; u8 rev2;