From nobody Tue Sep 29 05:35:47 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BE1BC345EBF; Tue, 11 Aug 2026 20:35:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786480516; cv=none; b=bL9RoRPV7VwTe7MdBEK8jI2OGSDtbAAX4HAZUVcgmOWzpYByTsyYBaJCMzlLWW9ifjWahVNWg0dddr7xamz1gw/rrnu4rPbkigKbflYnXEDMhoGnq534diwqOZ+D1OrRUzxSFUceVR6q14tsMVcRXOvyO5QkU4xInHHK2+j+ZBI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786480516; c=relaxed/simple; bh=/q6sFHhFLpno9qM7ZXdnG4oRJRbNjKO9vu4PxKxhL2s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=iMXoh2XbqpQnAV0y1GIU+xa/+lDEq3efOsXExg++eoA7W2+vKfyuDp/d/CsWYJvBjINN+xYiqUxAJSqdaDB7S5BclDFUlGyqlDMCAdfsFF9HTrwMg7bRKgivWJ8aQspFfeQICBjP2M5ZTY4hj892Nl5dsjJKlWu8csxhQu2ca54= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=u7bv3/LF; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="u7bv3/LF" Received: by smtp.kernel.org (Postfix) with ESMTPS id 647C9C2BCF4; Tue, 11 Aug 2026 20:35:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786480516; bh=/q6sFHhFLpno9qM7ZXdnG4oRJRbNjKO9vu4PxKxhL2s=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=u7bv3/LFW9rSc2+VDX4Qq62ueW+/6GEy5MSDQGvDd6D2CDrI55u/mfuKx41p/9Uqg iv3zWTupR3ucIzf5bK4l5edCA92MXPX4FJUdh34LsroCC6dQAXAEJHj7wjokxXqGim fuoH4pcrAjX2UaJY8LutVAEJTFLHJNO3nh9Ej48uMC53XR2klAqig5hth6vp7umJuo TKCnZ+kwrcpi/k3JU0lozN8gO6FX97tFz65EePXaewQjpc0ltyLap6nmL0shcvOZld rIAfUglQ2IsLvLszLFXZcvGFewEq3XuA4VHxLfEwWz6dpYWVCV/5VUEJK6Eln03Z+h ptw/TIj77GwxA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 414D3C5AC67; Tue, 11 Aug 2026 20:35:16 +0000 (UTC) From: Robin Snyders via B4 Relay Date: Tue, 11 Aug 2026 22:35:04 +0200 Subject: [PATCH 1/3] dt-bindings: power: supply: qcom,pmi8998-charger: add SMB5 PMICs Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260811-submit-qcom-smbx-send-v1-v1-1-feec6cfa123a@snyders.xyz> References: <20260811-submit-qcom-smbx-send-v1-v1-0-feec6cfa123a@snyders.xyz> In-Reply-To: <20260811-submit-qcom-smbx-send-v1-v1-0-feec6cfa123a@snyders.xyz> To: Casey Connolly , Sebastian Reichel , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-arm-msm@vger.kernel.org, linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Robin Snyders X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786480511; l=939; i=robin@snyders.xyz; s=default; h=from:subject:message-id; bh=EYGMyPfkRuuk1QHQrRSaTrAt/JZBY5TFPUfwjprLJoo=; b=2zjhn0rcir35V690AgI3vmDGAQrUmO7XzcAqZ+hVyAZytBBhtfX27vBplyTSo98tY/LqROTKm yfITkTgkAncCRUOYpk9JJD3BerrASJ/Qgk3rQA2AMeerhPIc46udQEt X-Developer-Key: i=robin@snyders.xyz; a=ed25519; pk=Mdk5dNn+Tkcy7BWexDxBLR/s1BNz8WdqDPnr3qtYBIU= X-Endpoint-Received: by B4 Relay for robin@snyders.xyz/default with auth_id=938 X-Original-From: Robin Snyders Reply-To: robin@snyders.xyz From: Casey Connolly Add compatible strings for PM7250B and PM8150B, which contain the SMB5 generation of the Qualcomm switch-mode battery charger. Signed-off-by: Casey Connolly Signed-off-by: Robin Snyders --- .../devicetree/bindings/power/supply/qcom,pmi8998-charger.yaml | = 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/power/supply/qcom,pmi8998-ch= arger.yaml b/Documentation/devicetree/bindings/power/supply/qcom,pmi8998-ch= arger.yaml index 70f5cd6eaeab..9e200ba3f3a8 100644 --- a/Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.y= aml +++ b/Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.y= aml @@ -12,6 +12,8 @@ maintainers: properties: compatible: enum: + - qcom,pm7250b-charger + - qcom,pm8150b-charger - qcom,pmi8998-charger - qcom,pm660-charger =20 --=20 2.54.0 From nobody Tue Sep 29 05:35:47 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BE29F35DA6E; Tue, 11 Aug 2026 20:35:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786480516; cv=none; b=eHyo+/vxj+HKLNH6yAUbKF/twUgTNmzam2rFsz7/0PiKKOZ2Hr6a+cRs1UwHqW7HmPI005zJ3yuTgkwgid1QATf+NBK0Xc8jCOU5jt4TH2GmwD/fYOChvd70NdFg/Ia30btnPwx5Yo2dLqkNhDxWcBt1ks1pycIZgZmdwr1iJjg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786480516; c=relaxed/simple; bh=PwXbpBtywcEYKD9MOtc5jNQb8oT5o7KPkPQUZgP64Mo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=amOrdO1ZbRP0wmcBBtajf3D7ffy+2nM0D6Ts0w8g34vW8tDbaqXhQp0QGtIjxTqKQ1ZeLW8MXlx8jaDtxokxQGFSSzmEGu+SGYlLzl6s7yP4vQAERGYoaAqZRUEXzKImmJUxiWfpq0993xLiyUarAg8ge8umoHUaDXqzJ/PbjDc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LRwZEKu9; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LRwZEKu9" Received: by smtp.kernel.org (Postfix) with ESMTPS id 70369C2BCF6; Tue, 11 Aug 2026 20:35:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786480516; bh=PwXbpBtywcEYKD9MOtc5jNQb8oT5o7KPkPQUZgP64Mo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=LRwZEKu9Eb+9wqNpxLolrJ3WiBkkrn6fhJCbJXfWpPHMpDap+pg6ZqorP6EG9Qdtd 59RWNOt41IMSL839zOqRUCR9mYxgPCRv/VOjvwW+c7ihrn6sTF8Immf/A+eEb33KX3 DnFzozNQ/97C89gxMa9qh7+ryvbg7WPAcO9eETCO3dIdV3j+iRragfv8kHcMai4AHR 6NMUhjZJXgtWYsY4VYdgkabZN4e0GFdEj+o4IEiz6or8uyB2AmyeJXz70eqrnHcVfp aYPoK7UT/fTFMi3BEGyt7C1ZqrSo0xReGOFSKr3YCpxmefh0roE6LNOQHqgeUaMzP7 o+nsJgLqMuqnA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5014BC5B56A; Tue, 11 Aug 2026 20:35:16 +0000 (UTC) From: Robin Snyders via B4 Relay Date: Tue, 11 Aug 2026 22:35:05 +0200 Subject: [PATCH 2/3] power: supply: qcom_smbx: add SMB5 support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260811-submit-qcom-smbx-send-v1-v1-2-feec6cfa123a@snyders.xyz> References: <20260811-submit-qcom-smbx-send-v1-v1-0-feec6cfa123a@snyders.xyz> In-Reply-To: <20260811-submit-qcom-smbx-send-v1-v1-0-feec6cfa123a@snyders.xyz> To: Casey Connolly , Sebastian Reichel , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-arm-msm@vger.kernel.org, linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Robin Snyders , Joel Selvaraj X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786480511; l=28665; i=robin@snyders.xyz; s=default; h=from:subject:message-id; bh=p4yLBqyL9oTJyxri1sQr3FrYoXGVU+5DUUBVLcaVWss=; b=6BE4WdAC2lIyQxJluqaX29nkEpSsksoLaN4zn1t3sIAo5pFGOl95d18cSd1OoZhreobwtkG92 miP9ArY6zLMBiJDe7EiTFW/wsD+1KuL1AtBfLqTchxcfqtA74WRhEdy X-Developer-Key: i=robin@snyders.xyz; a=ed25519; pk=Mdk5dNn+Tkcy7BWexDxBLR/s1BNz8WdqDPnr3qtYBIU= X-Endpoint-Received: by B4 Relay for robin@snyders.xyz/default with auth_id=938 X-Original-From: Robin Snyders Reply-To: robin@snyders.xyz From: Casey Connolly Introduce support for the SMB5 charger found on PM8150B and other modern Qualcomm PMICs. SMB5 is largely similar to SMB2, with differences in the register layout, Type-C block and charger status fields. Select the register layout and the voltage, fast-charge-current and input-current ranges from per-PMIC match data. Suspend USB input and charging before initialization, program the battery limits and interrupts, and only then enable charging and input. Start PM8150B with conservative 4.40 V, 1.50 A and 500 mA limits. Also read overvoltage state from the returned register value rather than the register address. On a OnePlus 7T Pro, register reads confirmed the programmed limits. A 180-second guarded charging trace and a subsequent 600-second runtime trace completed without crossing the voltage guard. Signed-off-by: Casey Connolly Co-developed-by: Joel Selvaraj Signed-off-by: Joel Selvaraj Co-developed-by: Robin Snyders Signed-off-by: Robin Snyders --- drivers/power/supply/qcom_smbx.c | 512 ++++++++++++++++++++++++++++++++++-= ---- 1 file changed, 446 insertions(+), 66 deletions(-) diff --git a/drivers/power/supply/qcom_smbx.c b/drivers/power/supply/qcom_s= mbx.c index 67fdb4335338..09d9e0f95cb5 100644 --- a/drivers/power/supply/qcom_smbx.c +++ b/drivers/power/supply/qcom_smbx.c @@ -23,6 +23,13 @@ #include #include =20 +enum smb_generation { + SMB2, + SMB5, +}; + +#define SMB_REG_OFFSET(smb) ((smb)->gen =3D=3D SMB2 ? 0x600 : 0x100) + /* clang-format off */ #define BATTERY_CHARGER_STATUS_1 0x06 #define BVR_INITIAL_RAMP_BIT BIT(7) @@ -34,14 +41,20 @@ #define BATTERY_CHARGER_STATUS_2 0x07 #define INPUT_CURRENT_LIMITED_BIT BIT(7) #define CHARGER_ERROR_STATUS_SFT_EXPIRE_BIT BIT(6) -#define CHARGER_ERROR_STATUS_BAT_OV_BIT BIT(5) +#define SMB2_CHARGER_ERROR_STATUS_BAT_OV_BIT BIT(5) #define CHARGER_ERROR_STATUS_BAT_TERM_MISSING_BIT BIT(4) #define BAT_TEMP_STATUS_MASK GENMASK(3, 0) #define BAT_TEMP_STATUS_SOFT_LIMIT_MASK GENMASK(3, 2) -#define BAT_TEMP_STATUS_HOT_SOFT_LIMIT_BIT BIT(3) -#define BAT_TEMP_STATUS_COLD_SOFT_LIMIT_BIT BIT(2) -#define BAT_TEMP_STATUS_TOO_HOT_BIT BIT(1) -#define BAT_TEMP_STATUS_TOO_COLD_BIT BIT(0) +#define SMB2_BAT_TEMP_STATUS_HOT_SOFT_LIMIT_BIT BIT(3) +#define SMB2_BAT_TEMP_STATUS_COLD_SOFT_LIMIT_BIT BIT(2) +#define SMB2_BAT_TEMP_STATUS_TOO_HOT_BIT BIT(1) +#define SMB2_BAT_TEMP_STATUS_TOO_COLD_BIT BIT(0) + +#define SMB5_CHARGER_ERROR_STATUS_BAT_OV_BIT BIT(1) +#define SMB5_BAT_TEMP_STATUS_HOT_SOFT_BIT BIT(5) +#define SMB5_BAT_TEMP_STATUS_COLD_SOFT_BIT BIT(4) +#define SMB5_BAT_TEMP_STATUS_TOO_HOT_BIT BIT(3) +#define SMB5_BAT_TEMP_STATUS_TOO_COLD_BIT BIT(2) =20 #define BATTERY_CHARGER_STATUS_4 0x0A #define CHARGE_CURRENT_POST_JEITA_MASK GENMASK(7, 0) @@ -78,12 +91,15 @@ #define FLOAT_VOLTAGE_CFG 0x70 #define FLOAT_VOLTAGE_SETTING_MASK GENMASK(7, 0) =20 -#define FG_UPDATE_CFG_2_SEL 0x7D +#define SMB2_FG_UPDATE_CFG_2_SEL 0x7D #define SOC_LT_OTG_THRESH_SEL_BIT BIT(3) -#define SOC_LT_CHG_RECHARGE_THRESH_SEL_BIT BIT(2) -#define VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT BIT(1) +#define SMB2_SOC_LT_CHG_RECHARGE_THRESH_SEL_BIT BIT(2) +#define SMB2_VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT BIT(1) #define IBT_LT_CHG_TERM_THRESH_SEL_BIT BIT(0) =20 +#define SMB5_CHARGE_RCHG_SOC_THRESHOLD_CFG_REG 0x7D +#define SMB5_CHARGE_RCHG_SOC_THRESHOLD_CFG_MASK GENMASK(7, 0) + #define JEITA_EN_CFG 0x90 #define JEITA_EN_HARDLIMIT_BIT BIT(4) #define JEITA_EN_HOT_SL_FCV_BIT BIT(3) @@ -189,9 +205,11 @@ #define TYPEC_TRYSINK_DETECT_STATUS_BIT BIT(0) =20 #define CMD_APSD 0x341 -#define ICL_OVERRIDE_BIT BIT(1) #define APSD_RERUN_BIT BIT(0) =20 +#define CMD_ICL_OVERRIDE 0x342 +#define ICL_OVERRIDE_BIT BIT(0) + #define TYPE_C_CFG 0x358 #define APSD_START_ON_CC_BIT BIT(7) #define WAIT_FOR_APSD_BIT BIT(6) @@ -260,7 +278,7 @@ #define EXIT_SNK_BASED_ON_CC_BIT BIT(7) #define VCONN_EN_ORIENTATION_BIT BIT(6) #define TYPEC_VCONN_OVERCURR_INT_EN_BIT BIT(5) -#define VCONN_EN_SRC_BIT BIT(4) +#define SMB2_VCONN_EN_SRC_BIT BIT(4) #define VCONN_EN_VALUE_BIT BIT(3) #define TYPEC_POWER_ROLE_CMD_MASK GENMASK(2, 0) #define UFP_EN_CMD_BIT BIT(2) @@ -274,7 +292,7 @@ #define SUSPEND_ON_COLLAPSE_USBIN_BIT BIT(7) #define USBIN_AICL_HDC_EN_BIT BIT(6) #define USBIN_AICL_START_AT_MAX_BIT BIT(5) -#define USBIN_AICL_RERUN_EN_BIT BIT(4) +#define USBIN_AICL_PERIODIC_RERUN_EN_BIT BIT(4) #define USBIN_AICL_ADC_EN_BIT BIT(3) #define USBIN_AICL_EN_BIT BIT(2) #define USBIN_HV_COLLAPSE_RESPONSE_BIT BIT(1) @@ -303,10 +321,10 @@ #define AICL_SWITCH_ENABLE_BIT BIT(1) #define ZIN_ICL_ENABLE_BIT BIT(0) =20 -#define ICL_STATUS 0x607 +#define ICL_STATUS(smb) (SMB_REG_OFFSET(smb) + 0x07) #define INPUT_CURRENT_LIMIT_MASK GENMASK(7, 0) =20 -#define POWER_PATH_STATUS 0x60B +#define POWER_PATH_STATUS(smb) (SMB_REG_OFFSET(smb) + 0x0B) #define P_PATH_INPUT_SS_DONE_BIT BIT(7) #define P_PATH_USBIN_SUSPEND_STS_BIT BIT(6) #define P_PATH_DCIN_SUSPEND_STS_BIT BIT(5) @@ -315,6 +333,27 @@ #define P_PATH_POWER_PATH_MASK GENMASK(2, 1) #define P_PATH_VALID_INPUT_POWER_SOURCE_STS_BIT BIT(0) =20 +/* 0x5xx region is available on the SMB5 Type-C block. */ +#define SMB5_TYPE_C_MODE_CFG 0x544 +#define SMB5_EN_TRY_SNK_BIT BIT(4) +#define SMB5_EN_SNK_ONLY_BIT BIT(1) + +#define SMB5_TYPEC_TYPE_C_VCONN_CONTROL 0x546 +#define SMB5_VCONN_EN_ORIENTATION_BIT BIT(2) +#define SMB5_VCONN_EN_VALUE_BIT BIT(1) +#define SMB5_VCONN_EN_SRC_BIT BIT(0) + +#define SMB5_TYPE_C_DEBUG_ACCESS_SINK 0x54a +#define SMB5_TYPEC_DEBUG_ACCESS_SINK_MASK GENMASK(4, 0) + +#define SMB5_DEBUG_ACCESS_SRC_CFG 0x54c +#define SMB5_EN_UNORIENTED_DEBUG_ACCESS_SRC_BIT BIT(0) + +#define SMB5_TYPE_C_EXIT_STATE_CFG 0x550 +#define SMB5_BYPASS_VSAFE0V_DURING_ROLE_SWAP_BIT BIT(3) +#define SMB5_SEL_SRC_UPPER_REF_BIT BIT(2) +#define SMB5_EXIT_SNK_BASED_ON_CC_BIT BIT(0) + #define BARK_BITE_WDOG_PET 0x643 #define BARK_BITE_WDOG_PET_BIT BIT(0) =20 @@ -350,8 +389,8 @@ #define DCP_CURRENT_UA 1500000 #define CURRENT_MAX_UA DCP_CURRENT_UA =20 -/* pmi8998 registers represent current in increments of 1/40th of an amp */ -#define CURRENT_SCALE_FACTOR 25000 +/* PMI8998 registers represent current in increments of 1/40th of an amp. = */ +#define SMB2_CURRENT_STEP_UA 25000 /* clang-format on */ =20 enum charger_status { @@ -378,6 +417,9 @@ struct smb_init_register { * @base: Base address for smb registers * @regmap: Register map * @batt_info: Battery data from DT + * @gen: Charger hardware generation + * @icl_max_ua: Maximum programmable USB input current + * @icl_step_ua: USB input current register step * @status_change_work: Worker to handle plug/unplug events * @cable_irq: USB plugin IRQ * @wakeup_enabled: If the cable IRQ will cause a wakeup @@ -391,6 +433,9 @@ struct smb_chip { unsigned int base; struct regmap *regmap; struct power_supply_battery_info *batt_info; + enum smb_generation gen; + unsigned int icl_max_ua; + unsigned int icl_step_ua; =20 struct delayed_work status_change_work; int cable_irq; @@ -402,6 +447,20 @@ struct smb_chip { struct power_supply *chg_psy; }; =20 +struct smb_match_data { + const char *name; + enum smb_generation gen; + size_t init_seq_len; + unsigned int fv_min_uv; + unsigned int fv_max_uv; + unsigned int fv_step_uv; + unsigned int fcc_max_ua; + unsigned int fcc_step_ua; + unsigned int icl_max_ua; + unsigned int icl_step_ua; + const struct smb_init_register *init_seq; +}; + static enum power_supply_property smb_properties[] =3D { POWER_SUPPLY_PROP_MANUFACTURER, POWER_SUPPLY_PROP_MODEL_NAME, @@ -419,7 +478,7 @@ static int smb_get_prop_usb_online(struct smb_chip *chi= p, int *val) unsigned int stat; int rc; =20 - rc =3D regmap_read(chip->regmap, chip->base + POWER_PATH_STATUS, &stat); + rc =3D regmap_read(chip->regmap, chip->base + POWER_PATH_STATUS(chip), &s= tat); if (rc < 0) { dev_err(chip->dev, "Couldn't read power path status: %d\n", rc); return rc; @@ -474,9 +533,35 @@ static int smb_apsd_get_charger_type(struct smb_chip *= chip, int *val) return 0; } =20 +/* Return 1 when in overvoltage state, else 0 or -errno */ +static int smbx_ov_status(struct smb_chip *chip) +{ + u16 reg; + u8 mask; + int rc; + u32 val; + + switch (chip->gen) { + case SMB2: + reg =3D BATTERY_CHARGER_STATUS_2; + mask =3D SMB2_CHARGER_ERROR_STATUS_BAT_OV_BIT; + break; + case SMB5: + reg =3D BATTERY_CHARGER_STATUS_7; + mask =3D SMB5_CHARGER_ERROR_STATUS_BAT_OV_BIT; + break; + } + + rc =3D regmap_read(chip->regmap, chip->base + reg, &val); + if (rc) + return rc; + + return !!(val & mask); +} + static int smb_get_prop_status(struct smb_chip *chip, int *val) { - unsigned char stat[2]; + u32 stat; int usb_online =3D 0; int rc; =20 @@ -486,22 +571,27 @@ static int smb_get_prop_status(struct smb_chip *chip,= int *val) return rc; } =20 - rc =3D regmap_bulk_read(chip->regmap, - chip->base + BATTERY_CHARGER_STATUS_1, &stat, 2); + rc =3D regmap_read(chip->regmap, + chip->base + BATTERY_CHARGER_STATUS_1, &stat); if (rc < 0) { dev_err(chip->dev, "Failed to read charging status ret=3D%d\n", rc); return rc; } =20 - if (stat[1] & CHARGER_ERROR_STATUS_BAT_OV_BIT) { + rc =3D smbx_ov_status(chip); + if (rc < 0) + return rc; + + /* In overvoltage state */ + if (rc =3D=3D 1) { *val =3D POWER_SUPPLY_STATUS_NOT_CHARGING; return 0; } =20 - stat[0] =3D stat[0] & BATTERY_CHARGER_STATUS_MASK; + stat =3D stat & BATTERY_CHARGER_STATUS_MASK; =20 - switch (stat[0]) { + switch (stat) { case TRICKLE_CHARGE: case PRE_CHARGE: case FAST_CHARGE: @@ -525,10 +615,10 @@ static int smb_get_prop_status(struct smb_chip *chip,= int *val) static inline int smb_get_current_limit(struct smb_chip *chip, unsigned int *val) { - int rc =3D regmap_read(chip->regmap, chip->base + ICL_STATUS, val); + int rc =3D regmap_read(chip->regmap, chip->base + ICL_STATUS(chip), val); =20 if (rc >=3D 0) - *val *=3D CURRENT_SCALE_FACTOR; + *val *=3D chip->icl_step_ua; return rc; } =20 @@ -536,12 +626,13 @@ static int smb_set_current_limit(struct smb_chip *chi= p, unsigned int val) { unsigned char val_raw; =20 - if (val > 4800000) { + if (val > chip->icl_max_ua) { dev_err(chip->dev, - "Can't set current limit higher than 4800000uA"); + "Can't set current limit higher than %uuA", + chip->icl_max_ua); return -EINVAL; } - val_raw =3D val / CURRENT_SCALE_FACTOR; + val_raw =3D val / chip->icl_step_ua; =20 return regmap_write(chip->regmap, chip->base + USBIN_CURRENT_LIMIT_CFG, val_raw); @@ -620,7 +711,44 @@ static int smb_get_iio_chan(struct smb_chip *chip, str= uct iio_channel *chan, return iio_read_channel_processed(chan, val); } =20 -static int smb_get_prop_health(struct smb_chip *chip, int *val) +static int smb5_get_prop_health(struct smb_chip *chip, int *val) +{ + int rc; + unsigned int stat; + + rc =3D smbx_ov_status(chip); + + /* Treat any error as if we are in the overvoltage state */ + if (rc < 0) + dev_err(chip->dev, "Couldn't determine overvoltage status!"); + if (rc) { + dev_err(chip->dev, "battery over-voltage"); + *val =3D POWER_SUPPLY_HEALTH_OVERVOLTAGE; + return 0; + } + + rc =3D regmap_read(chip->regmap, chip->base + BATTERY_CHARGER_STATUS_7, + &stat); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read charger status 7 rc=3D%d\n", rc); + return rc; + } + + if (stat & SMB5_BAT_TEMP_STATUS_TOO_COLD_BIT) + *val =3D POWER_SUPPLY_HEALTH_COLD; + else if (stat & SMB5_BAT_TEMP_STATUS_TOO_HOT_BIT) + *val =3D POWER_SUPPLY_HEALTH_OVERHEAT; + else if (stat & SMB5_BAT_TEMP_STATUS_COLD_SOFT_BIT) + *val =3D POWER_SUPPLY_HEALTH_COOL; + else if (stat & SMB5_BAT_TEMP_STATUS_HOT_SOFT_BIT) + *val =3D POWER_SUPPLY_HEALTH_WARM; + else + *val =3D POWER_SUPPLY_HEALTH_GOOD; + + return 0; +} + +static int smb2_get_prop_health(struct smb_chip *chip, int *val) { int rc; unsigned int stat; @@ -633,19 +761,19 @@ static int smb_get_prop_health(struct smb_chip *chip,= int *val) } =20 switch (stat) { - case CHARGER_ERROR_STATUS_BAT_OV_BIT: + case SMB2_CHARGER_ERROR_STATUS_BAT_OV_BIT: *val =3D POWER_SUPPLY_HEALTH_OVERVOLTAGE; return 0; - case BAT_TEMP_STATUS_TOO_COLD_BIT: + case SMB2_BAT_TEMP_STATUS_TOO_COLD_BIT: *val =3D POWER_SUPPLY_HEALTH_COLD; return 0; - case BAT_TEMP_STATUS_TOO_HOT_BIT: + case SMB2_BAT_TEMP_STATUS_TOO_HOT_BIT: *val =3D POWER_SUPPLY_HEALTH_OVERHEAT; return 0; - case BAT_TEMP_STATUS_COLD_SOFT_LIMIT_BIT: + case SMB2_BAT_TEMP_STATUS_COLD_SOFT_LIMIT_BIT: *val =3D POWER_SUPPLY_HEALTH_COOL; return 0; - case BAT_TEMP_STATUS_HOT_SOFT_LIMIT_BIT: + case SMB2_BAT_TEMP_STATUS_HOT_SOFT_LIMIT_BIT: *val =3D POWER_SUPPLY_HEALTH_WARM; return 0; default: @@ -654,11 +782,25 @@ static int smb_get_prop_health(struct smb_chip *chip,= int *val) } } =20 +static int smb_get_prop_health(struct smb_chip *chip, int *val) +{ + switch (chip->gen) { + case SMB2: + return smb2_get_prop_health(chip, val); + case SMB5: + return smb5_get_prop_health(chip, val); + default: + dev_err(chip->dev, "unsupported SMB chip generation\n"); + return -EINVAL; + } +} + static int smb_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { struct smb_chip *chip =3D power_supply_get_drvdata(psy); + int ret; =20 switch (psp) { case POWER_SUPPLY_PROP_MANUFACTURER: @@ -673,8 +815,13 @@ static int smb_get_property(struct power_supply *psy, return smb_get_iio_chan(chip, chip->usb_in_i_chan, &val->intval); case POWER_SUPPLY_PROP_VOLTAGE_NOW: - return smb_get_iio_chan(chip, chip->usb_in_v_chan, - &val->intval); + ret =3D smb_get_iio_chan(chip, chip->usb_in_v_chan, + &val->intval); + if (!ret) { + if (chip->gen =3D=3D SMB5) + val->intval *=3D 16; + } + return ret; case POWER_SUPPLY_PROP_ONLINE: return smb_get_prop_usb_online(chip, &val->intval); case POWER_SUPPLY_PROP_STATUS: @@ -722,12 +869,8 @@ static int smb_property_is_writable(struct power_suppl= y *psy, static irqreturn_t smb_handle_batt_overvoltage(int irq, void *data) { struct smb_chip *chip =3D data; - unsigned int status; - - regmap_read(chip->regmap, chip->base + BATTERY_CHARGER_STATUS_2, - &status); =20 - if (status & CHARGER_ERROR_STATUS_BAT_OV_BIT) { + if (smbx_ov_status(chip) =3D=3D 1) { /* The hardware stops charging automatically */ dev_err(chip->dev, "battery overvoltage detected\n"); power_supply_changed(chip->chg_psy); @@ -773,7 +916,7 @@ static irqreturn_t smb_handle_wdog_bark(int irq, void *= data) } =20 static const struct power_supply_desc smb_psy_desc =3D { - .name =3D "pmi8998_charger", + .name =3D "SMB2_charger", .type =3D POWER_SUPPLY_TYPE_USB, .usb_types =3D BIT(POWER_SUPPLY_USB_TYPE_SDP) | BIT(POWER_SUPPLY_USB_TYPE_CDP) | @@ -787,16 +930,84 @@ static const struct power_supply_desc smb_psy_desc = =3D { }; =20 /* Init sequence derived from vendor downstream driver */ -static const struct smb_init_register smb_init_seq[] =3D { - { .addr =3D AICL_RERUN_TIME_CFG, .mask =3D AICL_RERUN_TIME_MASK, .val =3D= 0 }, +static const struct smb_init_register smb5_init_seq[] =3D { + /* + * By default configure us as an upstream facing port + * FIXME: This will be handled by the type-c driver + */ + { .addr =3D SMB5_TYPE_C_MODE_CFG, + .mask =3D SMB5_EN_TRY_SNK_BIT | SMB5_EN_SNK_ONLY_BIT, + .val =3D SMB5_EN_TRY_SNK_BIT }, + { .addr =3D SMB5_TYPEC_TYPE_C_VCONN_CONTROL, + .mask =3D SMB5_VCONN_EN_ORIENTATION_BIT | SMB5_VCONN_EN_SRC_BIT | + SMB5_VCONN_EN_VALUE_BIT, + .val =3D SMB5_VCONN_EN_SRC_BIT }, + { .addr =3D SMB5_DEBUG_ACCESS_SRC_CFG, + .mask =3D SMB5_EN_UNORIENTED_DEBUG_ACCESS_SRC_BIT, + .val =3D SMB5_EN_UNORIENTED_DEBUG_ACCESS_SRC_BIT }, + { .addr =3D SMB5_TYPE_C_EXIT_STATE_CFG, + .mask =3D SMB5_SEL_SRC_UPPER_REF_BIT, + .val =3D SMB5_SEL_SRC_UPPER_REF_BIT }, + /* + * Disable Type-C factory mode and stay in Attached.SRC state when VCONN + * over-current happens + */ + { .addr =3D TYPE_C_CFG, + .mask =3D APSD_START_ON_CC_BIT, + .val =3D 0 }, + { .addr =3D SMB5_TYPE_C_DEBUG_ACCESS_SINK, + .mask =3D SMB5_TYPEC_DEBUG_ACCESS_SINK_MASK, + .val =3D 0x17 }, + /* Configure VBUS for software control */ + { .addr =3D OTG_CFG, .mask =3D OTG_EN_SRC_CFG_BIT, .val =3D 0 }, + /* + * Recharge when State Of Charge drops below 98%. + */ + { .addr =3D SMB5_CHARGE_RCHG_SOC_THRESHOLD_CFG_REG, + .mask =3D SMB5_CHARGE_RCHG_SOC_THRESHOLD_CFG_MASK, + .val =3D 250 }, + /* Enable BC1P2 auto Src detect */ + { .addr =3D USBIN_OPTIONS_1_CFG, + .mask =3D AUTO_SRC_DETECT_BIT, + .val =3D AUTO_SRC_DETECT_BIT }, + /* Set the default SDP charger type to a 500ma USB 2.0 port */ + { .addr =3D USBIN_ICL_OPTIONS, + .mask =3D USBIN_MODE_CHG_BIT, + .val =3D USBIN_MODE_CHG_BIT }, + { .addr =3D CMD_ICL_OVERRIDE, + .mask =3D ICL_OVERRIDE_BIT, + .val =3D 0 }, + { .addr =3D USBIN_LOAD_CFG, + .mask =3D ICL_OVERRIDE_AFTER_APSD_BIT, + .val =3D 0 }, + /* Disable watchdog */ + { .addr =3D SNARL_BARK_BITE_WD_CFG, .mask =3D 0xff, .val =3D 0 }, + { .addr =3D WD_CFG, + .mask =3D WATCHDOG_TRIGGER_AFP_EN_BIT | WDOG_TIMER_EN_ON_PLUGIN_BIT | + BARK_WDOG_INT_EN_BIT, + .val =3D 0 }, + /* + * Enable Automatic Input Current Limit, this will slowly ramp up the cur= rent + * When connected to a wall charger, and automatically stop when it detec= ts + * the charger current limit (voltage drop?) or it reaches the programmed= limit. + */ + { .addr =3D USBIN_AICL_OPTIONS_CFG, + .mask =3D USBIN_AICL_PERIODIC_RERUN_EN_BIT | USBIN_AICL_ADC_EN_BIT + | USBIN_AICL_EN_BIT | SUSPEND_ON_COLLAPSE_USBIN_BIT, + .val =3D USBIN_AICL_PERIODIC_RERUN_EN_BIT | USBIN_AICL_ADC_EN_BIT + | USBIN_AICL_EN_BIT | SUSPEND_ON_COLLAPSE_USBIN_BIT }, +}; + +/* Init sequence derived from vendor downstream driver */ +static const struct smb_init_register smb2_init_seq[] =3D { /* * By default configure us as an upstream facing port * FIXME: This will be handled by the type-c driver */ { .addr =3D TYPE_C_INTRPT_ENB_SOFTWARE_CTRL, - .mask =3D TYPEC_POWER_ROLE_CMD_MASK | VCONN_EN_SRC_BIT | + .mask =3D TYPEC_POWER_ROLE_CMD_MASK | SMB2_VCONN_EN_SRC_BIT | VCONN_EN_VALUE_BIT, - .val =3D VCONN_EN_SRC_BIT }, + .val =3D SMB2_VCONN_EN_SRC_BIT }, /* * Disable Type-C factory mode and stay in Attached.SRC state when VCONN * over-current happens @@ -810,10 +1021,10 @@ static const struct smb_init_register smb_init_seq[]= =3D { * Use VBAT to determine the recharge threshold when battery is full * rather than the state of charge. */ - { .addr =3D FG_UPDATE_CFG_2_SEL, - .mask =3D SOC_LT_CHG_RECHARGE_THRESH_SEL_BIT | - VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT, - .val =3D VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT }, + { .addr =3D SMB2_FG_UPDATE_CFG_2_SEL, + .mask =3D SMB2_SOC_LT_CHG_RECHARGE_THRESH_SEL_BIT | + SMB2_VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT, + .val =3D SMB2_VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT }, /* Enable charging */ { .addr =3D USBIN_OPTIONS_1_CFG, .mask =3D HVDCP_EN_BIT, .val =3D 0 }, { .addr =3D CHARGING_ENABLE_CMD, @@ -878,7 +1089,7 @@ static const struct smb_init_register smb_init_seq[] = =3D { */ { .addr =3D PRE_CHARGE_CURRENT_CFG, .mask =3D PRE_CHARGE_CURRENT_SETTING_MASK, - .val =3D 500000 / CURRENT_SCALE_FACTOR }, + .val =3D 500000 / SMB2_CURRENT_STEP_UA }, /* * This overrides all of the current limit options exposed to userspace * and prevents the device from pulling more than ~1A. This is done @@ -886,20 +1097,76 @@ static const struct smb_init_register smb_init_seq[]= =3D { */ { .addr =3D FAST_CHARGE_CURRENT_CFG, .mask =3D FAST_CHARGE_CURRENT_SETTING_MASK, - .val =3D 1000000 / CURRENT_SCALE_FACTOR }, + .val =3D 1000000 / SMB2_CURRENT_STEP_UA }, +}; + +static const struct smb_match_data pmi8998_match_data =3D { + .init_seq =3D smb2_init_seq, + .init_seq_len =3D ARRAY_SIZE(smb2_init_seq), + .name =3D "pmi8998", + .gen =3D SMB2, + .fv_min_uv =3D 3487500, + .fv_max_uv =3D 4920000, + .fv_step_uv =3D 7500, + .fcc_max_ua =3D 4500000, + .fcc_step_ua =3D 25000, + .icl_max_ua =3D 4800000, + .icl_step_ua =3D 25000, +}; + +static const struct smb_match_data pm660_match_data =3D { + .init_seq =3D smb2_init_seq, + .init_seq_len =3D ARRAY_SIZE(smb2_init_seq), + .name =3D "pm660", + .gen =3D SMB2, + .fv_min_uv =3D 3487500, + .fv_max_uv =3D 4920000, + .fv_step_uv =3D 7500, + .fcc_max_ua =3D 4500000, + .fcc_step_ua =3D 25000, + .icl_max_ua =3D 4800000, + .icl_step_ua =3D 25000, +}; + +static const struct smb_match_data pm8150b_match_data =3D { + .init_seq =3D smb5_init_seq, + .init_seq_len =3D ARRAY_SIZE(smb5_init_seq), + .name =3D "pm8150b", + .gen =3D SMB5, + .fv_min_uv =3D 3600000, + .fv_max_uv =3D 4790000, + .fv_step_uv =3D 10000, + .fcc_max_ua =3D 8000000, + .fcc_step_ua =3D 50000, + .icl_max_ua =3D 5000000, + .icl_step_ua =3D 50000, }; =20 -static int smb_init_hw(struct smb_chip *chip) +static const struct smb_match_data pm7250b_match_data =3D { + .init_seq =3D smb5_init_seq, + .init_seq_len =3D ARRAY_SIZE(smb5_init_seq), + .name =3D "pm7250b", + .gen =3D SMB5, + .fv_min_uv =3D 3600000, + .fv_max_uv =3D 4800000, + .fv_step_uv =3D 10000, + .fcc_max_ua =3D 3000000, + .fcc_step_ua =3D 50000, + .icl_max_ua =3D 3000000, + .icl_step_ua =3D 50000, +}; + +static int smb_init_hw(struct smb_chip *chip, const struct smb_init_regist= er *init_seq, size_t len) { int rc, i; =20 - for (i =3D 0; i < ARRAY_SIZE(smb_init_seq); i++) { + for (i =3D 0; i < len; i++) { dev_dbg(chip->dev, "%d: Writing 0x%02x to 0x%02x\n", i, - smb_init_seq[i].val, smb_init_seq[i].addr); + init_seq[i].val, init_seq[i].addr); rc =3D regmap_update_bits(chip->regmap, - chip->base + smb_init_seq[i].addr, - smb_init_seq[i].mask, - smb_init_seq[i].val); + chip->base + init_seq[i].addr, + init_seq[i].mask, + init_seq[i].val); if (rc < 0) return dev_err_probe(chip->dev, rc, "%s: init command %d failed\n", @@ -935,6 +1202,11 @@ static int smb_probe(struct platform_device *pdev) struct power_supply_config supply_config =3D {}; struct power_supply_desc *desc; struct smb_chip *chip; + const struct smb_match_data *match_data; + unsigned int fast_charge_current_sel; + unsigned int float_voltage_sel; + int fast_charge_current_ua; + int float_voltage_uv; int rc, irq; =20 chip =3D devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); @@ -965,7 +1237,34 @@ static int smb_probe(struct platform_device *pdev) "Couldn't get usbin_i IIO channel\n"); } =20 - rc =3D smb_init_hw(chip); + match_data =3D device_get_match_data(chip->dev); + if (!match_data) + return dev_err_probe(chip->dev, -ENODEV, + "missing match data\n"); + + chip->gen =3D match_data->gen; + chip->icl_max_ua =3D match_data->icl_max_ua; + chip->icl_step_ua =3D match_data->icl_step_ua; + + dev_info(chip->dev, "Generation %s\n", chip->gen =3D=3D SMB2 ? "SMB2" : "= SMB5"); + if (chip->gen =3D=3D SMB5) { + /* Do not use bootloader charge limits while configuring SMB5. */ + rc =3D regmap_update_bits(chip->regmap, + chip->base + USBIN_CMD_IL, + USBIN_SUSPEND_BIT, USBIN_SUSPEND_BIT); + if (rc < 0) + return dev_err_probe(chip->dev, rc, + "could not suspend USB input\n"); + + rc =3D regmap_update_bits(chip->regmap, + chip->base + CHARGING_ENABLE_CMD, + CHARGING_ENABLE_CMD_BIT, 0); + if (rc < 0) + return dev_err_probe(chip->dev, rc, + "could not disable charging\n"); + } + + rc =3D smb_init_hw(chip, match_data->init_seq, match_data->init_seq_len); if (rc < 0) return rc; =20 @@ -978,7 +1277,7 @@ static int smb_probe(struct platform_device *pdev) memcpy(desc, &smb_psy_desc, sizeof(smb_psy_desc)); desc->name =3D devm_kasprintf(chip->dev, GFP_KERNEL, "%s-charger", - (const char *)device_get_match_data(chip->dev)); + match_data->name); if (!desc->name) return -ENOMEM; =20 @@ -999,11 +1298,66 @@ static int smb_probe(struct platform_device *pdev) return dev_err_probe(chip->dev, rc, "Failed to init status change work\n"); =20 - rc =3D (chip->batt_info->voltage_max_design_uv - 3487500) / 7500 + 1; - rc =3D regmap_update_bits(chip->regmap, chip->base + FLOAT_VOLTAGE_CFG, - FLOAT_VOLTAGE_SETTING_MASK, rc); - if (rc < 0) - return dev_err_probe(chip->dev, rc, "Couldn't set vbat max\n"); + if (chip->gen =3D=3D SMB5) { + float_voltage_uv =3D + chip->batt_info->constant_charge_voltage_max_uv; + if (float_voltage_uv <=3D 0) + float_voltage_uv =3D chip->batt_info->voltage_max_design_uv; + + if (float_voltage_uv < match_data->fv_min_uv || + float_voltage_uv > match_data->fv_max_uv) + return dev_err_probe(chip->dev, -EINVAL, + "float voltage %d uV outside %u-%u uV\n", + float_voltage_uv, + match_data->fv_min_uv, + match_data->fv_max_uv); + + float_voltage_sel =3D + (float_voltage_uv - match_data->fv_min_uv) / + match_data->fv_step_uv; + rc =3D regmap_update_bits(chip->regmap, + chip->base + FLOAT_VOLTAGE_CFG, + FLOAT_VOLTAGE_SETTING_MASK, + float_voltage_sel); + if (rc < 0) + return dev_err_probe(chip->dev, rc, + "could not set float voltage\n"); + + fast_charge_current_ua =3D + chip->batt_info->constant_charge_current_max_ua; + if (fast_charge_current_ua <=3D 0) + fast_charge_current_ua =3D DCP_CURRENT_UA; + + if (fast_charge_current_ua > match_data->fcc_max_ua) + return dev_err_probe(chip->dev, -EINVAL, + "fast charge current %d uA exceeds %u uA\n", + fast_charge_current_ua, + match_data->fcc_max_ua); + + fast_charge_current_sel =3D fast_charge_current_ua / + match_data->fcc_step_ua; + rc =3D regmap_update_bits(chip->regmap, + chip->base + FAST_CHARGE_CURRENT_CFG, + FAST_CHARGE_CURRENT_SETTING_MASK, + fast_charge_current_sel); + if (rc < 0) + return dev_err_probe(chip->dev, rc, + "could not set fast charge current\n"); + + rc =3D smb_set_current_limit(chip, SDP_CURRENT_UA); + if (rc < 0) + return dev_err_probe(chip->dev, rc, + "could not set USB input current\n"); + } else { + rc =3D (chip->batt_info->voltage_max_design_uv - + match_data->fv_min_uv) / match_data->fv_step_uv + 1; + rc =3D regmap_update_bits(chip->regmap, + chip->base + FLOAT_VOLTAGE_CFG, + FLOAT_VOLTAGE_SETTING_MASK, rc); + if (rc < 0) + return dev_err_probe(chip->dev, rc, + "could not set vbat max\n"); + } =20 rc =3D smb_init_irq(chip, &irq, "bat-ov", smb_handle_batt_overvoltage); if (rc < 0) @@ -1030,6 +1384,30 @@ static int smb_probe(struct platform_device *pdev) =20 platform_set_drvdata(pdev, chip); =20 + if (chip->gen =3D=3D SMB5) { + rc =3D regmap_update_bits(chip->regmap, + chip->base + CHARGING_ENABLE_CMD, + CHARGING_ENABLE_CMD_BIT, + CHARGING_ENABLE_CMD_BIT); + if (rc < 0) + return dev_err_probe(chip->dev, rc, + "could not enable charging\n"); + + rc =3D regmap_update_bits(chip->regmap, + chip->base + USBIN_CMD_IL, + USBIN_SUSPEND_BIT, 0); + if (rc < 0) + return dev_err_probe(chip->dev, rc, + "could not enable USB input\n"); + + dev_info(chip->dev, + "charge limits: float=3D%u uV fast=3D%u uA input=3D%u uA\n", + match_data->fv_min_uv + + float_voltage_sel * match_data->fv_step_uv, + fast_charge_current_sel * match_data->fcc_step_ua, + SDP_CURRENT_UA); + } + /* Initialise charger state */ schedule_delayed_work(&chip->status_change_work, 0); =20 @@ -1037,8 +1415,10 @@ static int smb_probe(struct platform_device *pdev) } =20 static const struct of_device_id smb_match_id_table[] =3D { - { .compatible =3D "qcom,pmi8998-charger", .data =3D "pmi8998" }, - { .compatible =3D "qcom,pm660-charger", .data =3D "pm660" }, + { .compatible =3D "qcom,pmi8998-charger", .data =3D &pmi8998_match_data }, + { .compatible =3D "qcom,pm660-charger", .data =3D &pm660_match_data }, + { .compatible =3D "qcom,pm7250b-charger", .data =3D &pm7250b_match_data }, + { .compatible =3D "qcom,pm8150b-charger", .data =3D &pm8150b_match_data }, { /* sentinal */ } }; MODULE_DEVICE_TABLE(of, smb_match_id_table); --=20 2.54.0 From nobody Tue Sep 29 05:35:47 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C51313FE640; Tue, 11 Aug 2026 20:35:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786480516; cv=none; b=fhgog3aFHcwHS19SJPPo4A3gAbLu6I03tgCyb/7gs/G1b6cFZFkE+U/3TEjmIfJk4hTNDa9AFoejTaHY+jBkrsnSFrBwtAhuXs+bzs9O9e1c2EeSMBvFOlNSPROsYTaiXquJj6OxhPnTl7pz1c+/BrqYmK6vPtbwCUMN4aOPyMg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786480516; c=relaxed/simple; bh=uFM1obCRazEZ5yLSAJ1dVuTgdYFgMqkX05MVuYYS3K0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=H9GzHYh32nFOQGgPpAe01yerVEiXmsMkuvBsYv3z00n3TAJ342MdTdwbATsZP2Itv0gvgrrlmBvU/8bPvqqJF+pRJOUkfC1+EkgNnhnQ9SkUzJM6ssOjzR5Wn+MiJSaIAXiLueNOxk+OZqiB7KqNwlpQFQ8vC8ejPrZoXUpCnDk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=OEUejYcI; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="OEUejYcI" Received: by smtp.kernel.org (Postfix) with ESMTPS id 83B4CC4AF0B; Tue, 11 Aug 2026 20:35:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786480516; bh=uFM1obCRazEZ5yLSAJ1dVuTgdYFgMqkX05MVuYYS3K0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=OEUejYcID5k/IM8xxJ5LWP6VgbLMw+rkmu/LO4GT47lSNnhbZGv2FZQS/lxwYLDnc NQT9+1N9h/PGrUqr3zMzSukFcxfI+ygn7B1mB/q6rB+1v7mlbf2UwVE4WPNyLJGFJ7 hmgc29/Vuy2mnrPGD8nGwPwWbt3jqqViFxwk8RaCdroGFcEUKjufC+ZFxcoJoKIQo9 dCJa5DmSd2anO5l/x2MaE83qtUTPbJbMETaNGlDCoXgYgKuN5315Nk6PIs1Q/thwvN kNGNrfwgn6YYjsIRWg9JJyC1/rvkEsPmtZZ90Fa27b4eRVNsO0hIyot5n5bZ81Vtxn avC5hXJcmcGTA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5DDFDC5CFE7; Tue, 11 Aug 2026 20:35:16 +0000 (UTC) From: Robin Snyders via B4 Relay Date: Tue, 11 Aug 2026 22:35:06 +0200 Subject: [PATCH 3/3] power: supply: qcom_smbx: program AICL rerun time Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260811-submit-qcom-smbx-send-v1-v1-3-feec6cfa123a@snyders.xyz> References: <20260811-submit-qcom-smbx-send-v1-v1-0-feec6cfa123a@snyders.xyz> In-Reply-To: <20260811-submit-qcom-smbx-send-v1-v1-0-feec6cfa123a@snyders.xyz> To: Casey Connolly , Sebastian Reichel , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-arm-msm@vger.kernel.org, linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Robin Snyders X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786480511; l=1368; i=robin@snyders.xyz; s=default; h=from:subject:message-id; bh=KqL6fkAKus1VfXlFaQFE4bSn/EnAURWbYSu61RmyM78=; b=O/bMHtYUWLUrjPRkO7HCQ0p5EH47F5WETJrS8QTvN+SIi3L34vlRH8pxEuNWoTDO+iNNtikJH GLuD8HZHzDOAo/OQ6e7nNYpywWBvPpvkeoVoFDmSIBNCIz7rJO3pVt5 X-Developer-Key: i=robin@snyders.xyz; a=ed25519; pk=Mdk5dNn+Tkcy7BWexDxBLR/s1BNz8WdqDPnr3qtYBIU= X-Endpoint-Received: by B4 Relay for robin@snyders.xyz/default with auth_id=938 X-Original-From: Robin Snyders Reply-To: robin@snyders.xyz From: Casey Connolly The bootloader-provided automatic input current limit rerun interval is not a stable software interface. Program a consistent three-second interval during probe. This is required at least on SMB5 hardware. Signed-off-by: Casey Connolly Signed-off-by: Robin Snyders --- drivers/power/supply/qcom_smbx.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/power/supply/qcom_smbx.c b/drivers/power/supply/qcom_s= mbx.c index 09d9e0f95cb5..9e3e240b6813 100644 --- a/drivers/power/supply/qcom_smbx.c +++ b/drivers/power/supply/qcom_smbx.c @@ -374,6 +374,7 @@ enum smb_generation { =20 #define AICL_RERUN_TIME_CFG 0x661 #define AICL_RERUN_TIME_MASK GENMASK(1, 0) +#define AICL_RERUN_TIME_3_SECS 0 =20 #define STAT_CFG 0x690 #define STAT_SW_OVERRIDE_VALUE_BIT BIT(7) @@ -1384,6 +1385,14 @@ static int smb_probe(struct platform_device *pdev) =20 platform_set_drvdata(pdev, chip); =20 + rc =3D regmap_write_bits(chip->regmap, + chip->base + AICL_RERUN_TIME_CFG, + AICL_RERUN_TIME_MASK, + AICL_RERUN_TIME_3_SECS); + if (rc < 0) + return dev_err_probe(chip->dev, rc, + "could not set AICL rerun time\n"); + if (chip->gen =3D=3D SMB5) { rc =3D regmap_update_bits(chip->regmap, chip->base + CHARGING_ENABLE_CMD, --=20 2.54.0