From nobody Thu Oct 2 10:53:02 2025 Received: from mail.andi.de1.cc (mail.andi.de1.cc [178.238.236.174]) (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 664012FF66E; Wed, 17 Sep 2025 17:48:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.238.236.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758131323; cv=none; b=DE/cuDhwt2MDB5UGyVXOWLKZfVbXYDPZxwk3WEjL1tTrxiZMktn2eKU2R1t3C2HRnUs3c7I1gaaxsoASbRUH9CZRv1mdGiZdWCmXQ4A5o5s2NzlvHSgkn+dkD9nlD3/sZAbO6ememKYeEJYcFu8Qes9jPrO+Y353oxqbrUxm6lE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758131323; c=relaxed/simple; bh=T8jSP/nM6p52WCx230tHmxgQZTrIyhdphnlgliU2MrA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Od3LfP+gAWXxJrNp8ZEsqg7MBRbTaewAr+d0KA0vTjk5F1LNK7e8kioo+WDEDjbU4Uzw7N/jqnaGAZsumj+V1cObWqOVRCICT3JZ5Q52MsI5VzvIr4bvPW1sa0Bm9fEPdfE7BfYT9+3uIclJbswYKNfL7wZjZ2plW93gJXOZ1cc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=kemnade.info; spf=pass smtp.mailfrom=kemnade.info; dkim=pass (2048-bit key) header.d=kemnade.info header.i=@kemnade.info header.b=9W9AciBv; arc=none smtp.client-ip=178.238.236.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=kemnade.info Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=kemnade.info Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kemnade.info header.i=@kemnade.info header.b="9W9AciBv" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=kemnade.info; s=20220719; h=Cc:In-Reply-To:References:From:Sender:Reply-To: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID; bh=H1DU/m8mr++CuW8Z72z0QsfexEFDp7sdws2HKxbjT+0=; b=9W9AciBv5QQHD8CE6VCsXkMzNc dkhwMQfPTniz0PFxqS7NDTcDtC4P5choULZ0YuBQo5Cfw0cFArx6Rien07KbP/MI+OOS3XXtCj+jV 3cRpUpEdDk+dTNrIq9ocCdZRoJZMP0CvzsCfjKe1tgDeRJDt/odhT6fRfdnMJbn8Yjbn7i3Ele3xK 28CSWbnlurEi26w/xFOsYfQBZyUq5aFWeiamkL5z5Kr5/NBljKQ6jKyju/K66cCgPjBcdLAefoPoc difsHaYm/MargVmdjCunw9W0MM/Lh4pS14Kk6Eyh47WuYN4ZRVrDbcGbN/OG+IETo0wfWCvw93aui lDCpiWBQ==; From: Andreas Kemnade Date: Wed, 17 Sep 2025 19:48:02 +0200 Subject: [PATCH v4 1/3] mfd: bd71828, bd71815 prepare for power-supply 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: <20250917-bd71828-charger-v4-1-fbc85a910499@kemnade.info> References: <20250917-bd71828-charger-v4-0-fbc85a910499@kemnade.info> In-Reply-To: <20250917-bd71828-charger-v4-0-fbc85a910499@kemnade.info> To: Matti Vaittinen , Lee Jones , Sebastian Reichel Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, Krzysztof Kozlowski , Andreas Kemnade , Matti Vaittinen X-Mailer: b4 0.15-dev-50721 X-Developer-Signature: v=1; a=openpgp-sha256; l=7379; i=andreas@kemnade.info; h=from:subject:message-id; bh=dmgYEkH3Jz6Tq+5u+8yD7jG3DYrR4sIck3blNGqHI8g=; b=owGbwMvMwCUm/rzkS6lq2x3G02pJDBmnvmSdv/rxa9byu2u/TFWyO/blgfnu4ticyXyL7mX7n VZaJz+vsqOUhUGMi0FWTJHll7WC2yeVZ7nBUyPsYeawMoEMYeDiFICJ+FUzMlzuPj9vzmff7/4n 6zbxOKxI5pinxDHxQP85ScmpN+U/2cozMtxj05OpM1ZtenRMWOTzjA6hvbemzos+rsg0374nt+7 0JUYA X-Developer-Key: i=andreas@kemnade.info; a=openpgp; fpr=EEC0DB858E66C0DA70620AC07DBD6AC74DE29324 From: Matti Vaittinen Add core support for ROHM BD718(15/28/78) PMIC's charger blocks. Signed-off-by: Matti Vaittinen Signed-off-by: Andreas Kemnade --- drivers/mfd/rohm-bd71828.c | 44 ++++++++++++++++++++++------ include/linux/mfd/rohm-bd71828.h | 63 ++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 98 insertions(+), 9 deletions(-) diff --git a/drivers/mfd/rohm-bd71828.c b/drivers/mfd/rohm-bd71828.c index a14b7aa69c3c6..84a64c3b9c9f5 100644 --- a/drivers/mfd/rohm-bd71828.c +++ b/drivers/mfd/rohm-bd71828.c @@ -45,8 +45,8 @@ static const struct resource bd71828_rtc_irqs[] =3D { =20 static const struct resource bd71815_power_irqs[] =3D { DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_RMV, "bd71815-dcin-rmv"), - DEFINE_RES_IRQ_NAMED(BD71815_INT_CLPS_OUT, "bd71815-clps-out"), - DEFINE_RES_IRQ_NAMED(BD71815_INT_CLPS_IN, "bd71815-clps-in"), + DEFINE_RES_IRQ_NAMED(BD71815_INT_CLPS_OUT, "bd71815-dcin-clps-out"), + DEFINE_RES_IRQ_NAMED(BD71815_INT_CLPS_IN, "bd71815-dcin-clps-in"), DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_OVP_RES, "bd71815-dcin-ovp-res"), DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_OVP_DET, "bd71815-dcin-ovp-det"), DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_MON_RES, "bd71815-dcin-mon-res"), @@ -56,7 +56,7 @@ static const struct resource bd71815_power_irqs[] =3D { DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_LOW_RES, "bd71815-vsys-low-res"), DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_LOW_DET, "bd71815-vsys-low-det"), DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_MON_RES, "bd71815-vsys-mon-res"), - DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_MON_RES, "bd71815-vsys-mon-det"), + DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_MON_DET, "bd71815-vsys-mon-det"), DEFINE_RES_IRQ_NAMED(BD71815_INT_CHG_WDG_TEMP, "bd71815-chg-wdg-temp"), DEFINE_RES_IRQ_NAMED(BD71815_INT_CHG_WDG_TIME, "bd71815-chg-wdg"), DEFINE_RES_IRQ_NAMED(BD71815_INT_CHG_RECHARGE_RES, "bd71815-rechg-res"), @@ -87,10 +87,10 @@ static const struct resource bd71815_power_irqs[] =3D { DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_CURR_2_DET, "bd71815-bat-oc2-de= t"), DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_CURR_3_RES, "bd71815-bat-oc3-re= s"), DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_CURR_3_DET, "bd71815-bat-oc3-de= t"), - DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_LOW_RES, "bd71815-bat-low-res"), - DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_LOW_DET, "bd71815-bat-low-det"), - DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_HI_RES, "bd71815-bat-hi-res"), - DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_HI_DET, "bd71815-bat-hi-det"), + DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_LOW_RES, "bd71815-temp-bat-low-= res"), + DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_LOW_DET, "bd71815-temp-bat-low-= det"), + DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_HI_RES, "bd71815-temp-bat-hi-re= s"), + DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_HI_DET, "bd71815-temp-bat-hi-de= t"), }; =20 static const struct mfd_cell bd71815_mfd_cells[] =3D { @@ -109,7 +109,30 @@ static const struct mfd_cell bd71815_mfd_cells[] =3D { }, }; =20 -static const struct mfd_cell bd71828_mfd_cells[] =3D { +static const struct resource bd71828_power_irqs[] =3D { + DEFINE_RES_IRQ_NAMED(BD71828_INT_CHG_TOPOFF_TO_DONE, + "bd71828-chg-done"), + DEFINE_RES_IRQ_NAMED(BD71828_INT_DCIN_DET, "bd71828-pwr-dcin-in"), + DEFINE_RES_IRQ_NAMED(BD71828_INT_DCIN_RMV, "bd71828-pwr-dcin-out"), + DEFINE_RES_IRQ_NAMED(BD71828_INT_BAT_LOW_VOLT_RES, + "bd71828-vbat-normal"), + DEFINE_RES_IRQ_NAMED(BD71828_INT_BAT_LOW_VOLT_DET, "bd71828-vbat-low"), + DEFINE_RES_IRQ_NAMED(BD71828_INT_TEMP_BAT_HI_DET, "bd71828-btemp-hi"), + DEFINE_RES_IRQ_NAMED(BD71828_INT_TEMP_BAT_HI_RES, "bd71828-btemp-cool"), + DEFINE_RES_IRQ_NAMED(BD71828_INT_TEMP_BAT_LOW_DET, "bd71828-btemp-lo"), + DEFINE_RES_IRQ_NAMED(BD71828_INT_TEMP_BAT_LOW_RES, + "bd71828-btemp-warm"), + DEFINE_RES_IRQ_NAMED(BD71828_INT_TEMP_CHIP_OVER_VF_DET, + "bd71828-temp-hi"), + DEFINE_RES_IRQ_NAMED(BD71828_INT_TEMP_CHIP_OVER_VF_RES, + "bd71828-temp-norm"), + DEFINE_RES_IRQ_NAMED(BD71828_INT_TEMP_CHIP_OVER_125_DET, + "bd71828-temp-125-over"), + DEFINE_RES_IRQ_NAMED(BD71828_INT_TEMP_CHIP_OVER_125_RES, + "bd71828-temp-125-under"), +}; + +static struct mfd_cell bd71828_mfd_cells[] =3D { { .name =3D "bd71828-pmic", }, { .name =3D "bd71828-gpio", }, { .name =3D "bd71828-led", .of_compatible =3D "rohm,bd71828-leds" }, @@ -118,8 +141,11 @@ static const struct mfd_cell bd71828_mfd_cells[] =3D { * BD70528 clock gate are the register address and mask. */ { .name =3D "bd71828-clk", }, - { .name =3D "bd71827-power", }, { + .name =3D "bd71828-power", + .resources =3D bd71828_power_irqs, + .num_resources =3D ARRAY_SIZE(bd71828_power_irqs), + }, { .name =3D "bd71828-rtc", .resources =3D bd71828_rtc_irqs, .num_resources =3D ARRAY_SIZE(bd71828_rtc_irqs), diff --git a/include/linux/mfd/rohm-bd71828.h b/include/linux/mfd/rohm-bd71= 828.h index ce786c96404a3..73a71ef691525 100644 --- a/include/linux/mfd/rohm-bd71828.h +++ b/include/linux/mfd/rohm-bd71828.h @@ -189,6 +189,69 @@ enum { /* Charger/Battey */ #define BD71828_REG_CHG_STATE 0x65 #define BD71828_REG_CHG_FULL 0xd2 +#define BD71828_REG_CHG_EN 0x6F +#define BD71828_REG_DCIN_STAT 0x68 +#define BD71828_MASK_DCIN_DET 0x01 +#define BD71828_REG_VDCIN_U 0x9c +#define BD71828_MASK_CHG_EN 0x01 +#define BD71828_CHG_MASK_DCIN_U 0x0f +#define BD71828_REG_BAT_STAT 0x67 +#define BD71828_REG_BAT_TEMP 0x6c +#define BD71828_MASK_BAT_TEMP 0x07 +#define BD71828_BAT_TEMP_OPEN 0x07 +#define BD71828_MASK_BAT_DET 0x20 +#define BD71828_MASK_BAT_DET_DONE 0x10 +#define BD71828_REG_CHG_STATE 0x65 +#define BD71828_REG_VBAT_U 0x8c +#define BD71828_MASK_VBAT_U 0x0f +#define BD71828_REG_VBAT_REX_AVG_U 0x92 + +#define BD71828_REG_OCV_PWRON_U 0x8A + +#define BD71828_REG_VBAT_MIN_AVG_U 0x8e +#define BD71828_REG_VBAT_MIN_AVG_L 0x8f + +#define BD71828_REG_CC_CNT3 0xb5 +#define BD71828_REG_CC_CNT2 0xb6 +#define BD71828_REG_CC_CNT1 0xb7 +#define BD71828_REG_CC_CNT0 0xb8 +#define BD71828_REG_CC_CURCD_AVG_U 0xb2 +#define BD71828_MASK_CC_CURCD_AVG_U 0x3f +#define BD71828_MASK_CC_CUR_DIR 0x80 +#define BD71828_REG_VM_BTMP_U 0xa1 +#define BD71828_REG_VM_BTMP_L 0xa2 +#define BD71828_MASK_VM_BTMP_U 0x0f +#define BD71828_REG_COULOMB_CTRL 0xc4 +#define BD71828_REG_COULOMB_CTRL2 0xd2 +#define BD71828_MASK_REX_CC_CLR 0x01 +#define BD71828_MASK_FULL_CC_CLR 0x10 +#define BD71828_REG_CC_CNT_FULL3 0xbd +#define BD71828_REG_CC_CNT_CHG3 0xc1 + +#define BD71828_REG_VBAT_INITIAL1_U 0x86 +#define BD71828_REG_VBAT_INITIAL1_L 0x87 + +#define BD71828_REG_VBAT_INITIAL2_U 0x88 +#define BD71828_REG_VBAT_INITIAL2_L 0x89 + +#define BD71828_REG_IBAT_U 0xb0 +#define BD71828_REG_IBAT_L 0xb1 + +#define BD71828_REG_IBAT_AVG_U 0xb2 +#define BD71828_REG_IBAT_AVG_L 0xb3 + +#define BD71828_REG_VSYS_AVG_U 0x96 +#define BD71828_REG_VSYS_AVG_L 0x97 +#define BD71828_REG_VSYS_MIN_AVG_U 0x98 +#define BD71828_REG_VSYS_MIN_AVG_L 0x99 +#define BD71828_REG_CHG_SET1 0x75 +#define BD71828_REG_ALM_VBAT_LIMIT_U 0xaa +#define BD71828_REG_BATCAP_MON_LIMIT_U 0xcc +#define BD71828_REG_CONF 0x64 + +#define BD71828_REG_DCIN_CLPS 0x71 + +#define BD71828_REG_MEAS_CLEAR 0xaf =20 /* LEDs */ #define BD71828_REG_LED_CTRL 0x4A --=20 2.47.3 From nobody Thu Oct 2 10:53:02 2025 Received: from mail.andi.de1.cc (mail.andi.de1.cc [178.238.236.174]) (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 327082FE599; Wed, 17 Sep 2025 17:48:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.238.236.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758131323; cv=none; b=pkhU3DusErsB2v0oW0BpHcSjcVf77JCakIHy3g07uknqKeQCjKzFPo4m3b7W+gbePMTpKdISVXmzEoGkMYl2W1WQfniXP8TjYt0XzQAkk7KREAD8SC19UEaiVuW1ZOZfaJqvD/7Nj6aCj3ktvV4GYr4pEap/f3dTyQ1FnpFTIFM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758131323; c=relaxed/simple; bh=crvHxNcUb8owIapDfnOmuaHxpOIzMenhccUmBOpAh84=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LLy/sL50FhfwtuyVwRNGKmBKADCc47hvpCJrOrjGgO8p6KsOJBvssjxJ24D5u0tvKjmRJgjpvorJ0CA13hIdc9vZAtVWs6ZtK/F4455kHuOYderE38JnA1jL4GtFNur7kDEBbWAevirDAJSPD3QLnYLWbbnRiDI94wfMUDTusyc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=kemnade.info; spf=pass smtp.mailfrom=kemnade.info; dkim=pass (2048-bit key) header.d=kemnade.info header.i=@kemnade.info header.b=pV1kttWv; arc=none smtp.client-ip=178.238.236.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=kemnade.info Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=kemnade.info Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kemnade.info header.i=@kemnade.info header.b="pV1kttWv" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=kemnade.info; s=20220719; h=Cc:In-Reply-To:References:From:Sender:Reply-To: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID; bh=2f6TxJgfgD6i4sMZL2s6ohkTCg8GTeGjwxrYK8JdMvc=; b=pV1kttWvyWFJz+frONuhua8ssl 6IQNZiCm+XvXUpyILzwUJi0m4+F1lKGbqUY02UaiK5cbrDK19jF3hmF13uDBtYJzo/XTt94QpDk3d Ijt36oGkNuYjpwhROnlpfZiyDV0Isgbytpg2foM3yY4ZW/7TYcOp5tez1Mjhzd6JDHslYgqPoPtKp sRFcrMrWefa03SMyfJRg9adze2342YBIBB9rKEhjC4pvb+GFS71NWFDB8weGx8qkqzwu0//xyfRh4 yb7maEtmv71M6h7Ytd+Ty1hGmDjfzcuN2RPxOLXdH5JvE423G2jUeniwxkfOUsqJmgPANia24ZQcq GJ2TB15A==; From: Andreas Kemnade Date: Wed, 17 Sep 2025 19:48:03 +0200 Subject: [PATCH v4 2/3] power: supply: Add bd718(15/28/78) charger driver 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: <20250917-bd71828-charger-v4-2-fbc85a910499@kemnade.info> References: <20250917-bd71828-charger-v4-0-fbc85a910499@kemnade.info> In-Reply-To: <20250917-bd71828-charger-v4-0-fbc85a910499@kemnade.info> To: Matti Vaittinen , Lee Jones , Sebastian Reichel Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, Krzysztof Kozlowski , Andreas Kemnade X-Mailer: b4 0.15-dev-50721 X-Developer-Signature: v=1; a=openpgp-sha256; l=32435; i=andreas@kemnade.info; h=from:subject:message-id; bh=crvHxNcUb8owIapDfnOmuaHxpOIzMenhccUmBOpAh84=; b=owGbwMvMwCUm/rzkS6lq2x3G02pJDBmnvmRNW3Hq0pyAqPkeJ7b+V755dIla1Hxj5Z8TBJhWb 9l/rXZtfUcpC4MYF4OsmCLLL2sFt08qz3KDp0bYw8xhZQIZwsDFKQATKTrB8M+qpFi8Y8JFroUf vjf+jdxSb7Jlw8zbBTtWv97C7d/II2vJ8N/daY+p3oTps9i0zjTNnfdY9VHUlCoVWd7dobf6Lwb +NeQFAA== X-Developer-Key: i=andreas@kemnade.info; a=openpgp; fpr=EEC0DB858E66C0DA70620AC07DBD6AC74DE29324 Add charger driver for ROHM BD718(15/28/78) PMIC charger block. It is a stripped down version of the driver here: https://lore.kernel.org/lkml/dbd97c1b0d715aa35a8b4d79741e433d97c562aa.16370= 61794.git.matti.vaittinen@fi.rohmeurope.com/ For the ease of review and to do a step-by-step approach remove all the coloumb counter related stuff and do not sneak in BD71827 support. That also avoids non-trivial rebasing of the above series. Changes besides that: Replace the custom property by a standard one and do not use megaohms for the current sense resistor. Signed-off-by: Andreas Kemnade Reviewed-by: Matti Vaittinen Acked-by: Sebastian Reichel --- drivers/power/supply/Kconfig | 9 + drivers/power/supply/Makefile | 1 + drivers/power/supply/bd71828-power.c | 1051 ++++++++++++++++++++++++++++++= ++++ 3 files changed, 1061 insertions(+) diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 79ddb006e2dad..16dddb2355d9b 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -974,6 +974,15 @@ config CHARGER_UCS1002 Say Y to enable support for Microchip UCS1002 Programmable USB Port Power Controller with Charger Emulation. =20 +config CHARGER_BD71828 + tristate "Power-supply driver for ROHM BD71828 and BD71815 PMIC" + depends on MFD_ROHM_BD71828 + help + Say Y here to enable support for charger and battery + in ROHM BD71815, BD71817, ROHM BD71828 power management + ICs. This driver gets various bits of information about battery + and charger states. + config CHARGER_BD99954 tristate "ROHM bd99954 charger driver" depends on I2C diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index f943c9150b326..c6520a11f021c 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -113,6 +113,7 @@ obj-$(CONFIG_CHARGER_SC2731) +=3D sc2731_charger.o obj-$(CONFIG_FUEL_GAUGE_SC27XX) +=3D sc27xx_fuel_gauge.o obj-$(CONFIG_FUEL_GAUGE_STC3117) +=3D stc3117_fuel_gauge.o obj-$(CONFIG_CHARGER_UCS1002) +=3D ucs1002_power.o +obj-$(CONFIG_CHARGER_BD71828) +=3D bd71828-power.o obj-$(CONFIG_CHARGER_BD99954) +=3D bd99954-charger.o obj-$(CONFIG_CHARGER_WILCO) +=3D wilco-charger.o obj-$(CONFIG_RN5T618_POWER) +=3D rn5t618_power.o diff --git a/drivers/power/supply/bd71828-power.c b/drivers/power/supply/bd= 71828-power.c new file mode 100644 index 0000000000000..fdd03159dc7bc --- /dev/null +++ b/drivers/power/supply/bd71828-power.c @@ -0,0 +1,1051 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* ROHM BD71815, BD71828 and BD71878 Charger driver */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* common defines */ +#define BD7182x_MASK_VBAT_U 0x1f +#define BD7182x_MASK_VDCIN_U 0x0f +#define BD7182x_MASK_IBAT_U 0x3f +#define BD7182x_MASK_CURDIR_DISCHG 0x80 +#define BD7182x_MASK_CHG_STATE 0x7f +#define BD7182x_MASK_BAT_TEMP 0x07 +#define BD7182x_MASK_DCIN_DET BIT(0) +#define BD7182x_MASK_CONF_PON BIT(0) +#define BD71815_MASK_CONF_XSTB BIT(1) +#define BD7182x_MASK_BAT_STAT 0x3f +#define BD7182x_MASK_DCIN_STAT 0x07 + +#define BD7182x_MASK_WDT_AUTO 0x40 +#define BD7182x_MASK_VBAT_ALM_LIMIT_U 0x01 +#define BD7182x_MASK_CHG_EN 0x01 + +#define BD7182x_DCIN_COLLAPSE_DEFAULT 0x36 + +#define MAX_CURRENT_DEFAULT 890000 /* uA */ +#define AC_NAME "bd71828_ac" +#define BAT_NAME "bd71828_bat" + +#define BAT_OPEN 0x7 + +/* + * VBAT Low voltage detection Threshold + * 0x00D4*16mV =3D 212*0.016 =3D 3.392v + */ +#define VBAT_LOW_TH 0x00D4 + +struct pwr_regs { + u8 vbat_avg; + u8 ibat; + u8 ibat_avg; + u8 btemp_vth; + u8 chg_state; + u8 bat_temp; + u8 dcin_stat; + u8 dcin_collapse_limit; + u8 chg_set1; + u8 chg_en; + u8 vbat_alm_limit_u; + u8 conf; + u8 vdcin; +}; + +static const struct pwr_regs pwr_regs_bd71828 =3D { + .vbat_avg =3D BD71828_REG_VBAT_U, + .ibat =3D BD71828_REG_IBAT_U, + .ibat_avg =3D BD71828_REG_IBAT_AVG_U, + .btemp_vth =3D BD71828_REG_VM_BTMP_U, + .chg_state =3D BD71828_REG_CHG_STATE, + .bat_temp =3D BD71828_REG_BAT_TEMP, + .dcin_stat =3D BD71828_REG_DCIN_STAT, + .dcin_collapse_limit =3D BD71828_REG_DCIN_CLPS, + .chg_set1 =3D BD71828_REG_CHG_SET1, + .chg_en =3D BD71828_REG_CHG_EN, + .vbat_alm_limit_u =3D BD71828_REG_ALM_VBAT_LIMIT_U, + .conf =3D BD71828_REG_CONF, + .vdcin =3D BD71828_REG_VDCIN_U, +}; + +static const struct pwr_regs pwr_regs_bd71815 =3D { + .vbat_avg =3D BD71815_REG_VM_SA_VBAT_U, + /* BD71815 does not have separate current and current avg */ + .ibat =3D BD71815_REG_CC_CURCD_U, + .ibat_avg =3D BD71815_REG_CC_CURCD_U, + + .btemp_vth =3D BD71815_REG_VM_BTMP, + .chg_state =3D BD71815_REG_CHG_STATE, + .bat_temp =3D BD71815_REG_BAT_TEMP, + .dcin_stat =3D BD71815_REG_DCIN_STAT, + .dcin_collapse_limit =3D BD71815_REG_DCIN_CLPS, + .chg_set1 =3D BD71815_REG_CHG_SET1, + .chg_en =3D BD71815_REG_CHG_SET1, + .vbat_alm_limit_u =3D BD71815_REG_ALM_VBAT_TH_U, + .conf =3D BD71815_REG_CONF, + + .vdcin =3D BD71815_REG_VM_DCIN_U, +}; + +struct bd71828_power { + struct regmap *regmap; + enum rohm_chip_type chip_type; + struct device *dev; + struct power_supply *ac; + struct power_supply *bat; + + const struct pwr_regs *regs; + /* Reg val to uA */ + int curr_factor; + int rsens; + int (*get_temp)(struct bd71828_power *pwr, int *temp); + int (*bat_inserted)(struct bd71828_power *pwr); +}; + +static int bd7182x_write16(struct bd71828_power *pwr, int reg, u16 val) +{ + __be16 tmp; + + tmp =3D cpu_to_be16(val); + + return regmap_bulk_write(pwr->regmap, reg, &tmp, sizeof(tmp)); +} + +static int bd7182x_read16_himask(struct bd71828_power *pwr, int reg, int h= imask, + u16 *val) +{ + struct regmap *regmap =3D pwr->regmap; + int ret; + __be16 rvals; + u8 *tmp =3D (u8 *)&rvals; + + ret =3D regmap_bulk_read(regmap, reg, &rvals, sizeof(*val)); + if (!ret) { + *tmp &=3D himask; + *val =3D be16_to_cpu(rvals); + } + + return ret; +} + +static int bd71828_get_vbat(struct bd71828_power *pwr, int *vcell) +{ + u16 tmp_vcell; + int ret; + + ret =3D bd7182x_read16_himask(pwr, pwr->regs->vbat_avg, + BD7182x_MASK_VBAT_U, &tmp_vcell); + if (ret) + dev_err(pwr->dev, "Failed to read battery average voltage\n"); + else + *vcell =3D ((int)tmp_vcell) * 1000; + + return ret; +} + +static int bd71828_get_current_ds_adc(struct bd71828_power *pwr, int *curr= , int *curr_avg) +{ + __be16 tmp_curr; + char *tmp =3D (char *)&tmp_curr; + int dir =3D 1; + int regs[] =3D { pwr->regs->ibat, pwr->regs->ibat_avg }; + int *vals[] =3D { curr, curr_avg }; + int ret, i; + + for (dir =3D 1, i =3D 0; i < ARRAY_SIZE(regs); i++) { + ret =3D regmap_bulk_read(pwr->regmap, regs[i], &tmp_curr, + sizeof(tmp_curr)); + if (ret) + break; + + if (*tmp & BD7182x_MASK_CURDIR_DISCHG) + dir =3D -1; + + *tmp &=3D BD7182x_MASK_IBAT_U; + + *vals[i] =3D dir * ((int)be16_to_cpu(tmp_curr)) * pwr->curr_factor; + } + + return ret; +} + +/* Unit is tenths of degree C */ +static int bd71815_get_temp(struct bd71828_power *pwr, int *temp) +{ + struct regmap *regmap =3D pwr->regmap; + int ret; + int t; + + ret =3D regmap_read(regmap, pwr->regs->btemp_vth, &t); + if (ret) + return ret; + + t =3D 200 - t; + + if (t > 200) { + dev_err(pwr->dev, "Failed to read battery temperature\n"); + return -ENODATA; + } + + return 0; +} + +/* Unit is tenths of degree C */ +static int bd71828_get_temp(struct bd71828_power *pwr, int *temp) +{ + u16 t; + int ret; + int tmp =3D 200 * 10000; + + ret =3D bd7182x_read16_himask(pwr, pwr->regs->btemp_vth, + BD71828_MASK_VM_BTMP_U, &t); + if (ret) + return ret; + + if (t > 3200) { + dev_err(pwr->dev, + "Failed to read battery temperature\n"); + return -ENODATA; + } + + tmp -=3D 625ULL * (unsigned int)t; + *temp =3D tmp / 1000; + + return ret; +} + +static int bd71828_charge_status(struct bd71828_power *pwr, + int *s, int *h) +{ + unsigned int state; + int status, health; + int ret =3D 1; + + ret =3D regmap_read(pwr->regmap, pwr->regs->chg_state, &state); + if (ret) { + dev_err(pwr->dev, "charger status reading failed (%d)\n", ret); + return ret; + } + + state &=3D BD7182x_MASK_CHG_STATE; + + dev_dbg(pwr->dev, "CHG_STATE %d\n", state); + + switch (state) { + case 0x00: + status =3D POWER_SUPPLY_STATUS_DISCHARGING; + health =3D POWER_SUPPLY_HEALTH_GOOD; + break; + case 0x01: + case 0x02: + case 0x03: + case 0x0E: + status =3D POWER_SUPPLY_STATUS_CHARGING; + health =3D POWER_SUPPLY_HEALTH_GOOD; + break; + case 0x0F: + status =3D POWER_SUPPLY_STATUS_FULL; + health =3D POWER_SUPPLY_HEALTH_GOOD; + break; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + status =3D POWER_SUPPLY_STATUS_NOT_CHARGING; + health =3D POWER_SUPPLY_HEALTH_OVERHEAT; + break; + case 0x30: + case 0x31: + case 0x32: + case 0x40: + status =3D POWER_SUPPLY_STATUS_DISCHARGING; + health =3D POWER_SUPPLY_HEALTH_GOOD; + break; + case 0x7f: + default: + status =3D POWER_SUPPLY_STATUS_NOT_CHARGING; + health =3D POWER_SUPPLY_HEALTH_DEAD; + break; + } + + if (s) + *s =3D status; + if (h) + *h =3D health; + + return ret; +} + +static int get_chg_online(struct bd71828_power *pwr, int *chg_online) +{ + int r, ret; + + ret =3D regmap_read(pwr->regmap, pwr->regs->dcin_stat, &r); + if (ret) { + dev_err(pwr->dev, "Failed to read DCIN status\n"); + return ret; + } + *chg_online =3D ((r & BD7182x_MASK_DCIN_DET) !=3D 0); + + return 0; +} + +static int get_bat_online(struct bd71828_power *pwr, int *bat_online) +{ + int r, ret; + + ret =3D regmap_read(pwr->regmap, pwr->regs->bat_temp, &r); + if (ret) { + dev_err(pwr->dev, "Failed to read battery temperature\n"); + return ret; + } + *bat_online =3D ((r & BD7182x_MASK_BAT_TEMP) !=3D BAT_OPEN); + + return 0; +} + +static int bd71828_bat_inserted(struct bd71828_power *pwr) +{ + int ret, val; + + ret =3D regmap_read(pwr->regmap, pwr->regs->conf, &val); + if (ret) { + dev_err(pwr->dev, "Failed to read CONF register\n"); + return 0; + } + ret =3D val & BD7182x_MASK_CONF_PON; + + if (ret) + regmap_update_bits(pwr->regmap, pwr->regs->conf, + BD7182x_MASK_CONF_PON, 0); + + return ret; +} + +static int bd71815_bat_inserted(struct bd71828_power *pwr) +{ + int ret, val; + + ret =3D regmap_read(pwr->regmap, pwr->regs->conf, &val); + if (ret) { + dev_err(pwr->dev, "Failed to read CONF register\n"); + return ret; + } + + ret =3D !(val & BD71815_MASK_CONF_XSTB); + if (ret) + regmap_write(pwr->regmap, pwr->regs->conf, val | + BD71815_MASK_CONF_XSTB); + + return ret; +} + +static int bd71828_init_hardware(struct bd71828_power *pwr) +{ + int ret; + + /* TODO: Collapse limit should come from device-tree ? */ + ret =3D regmap_write(pwr->regmap, pwr->regs->dcin_collapse_limit, + BD7182x_DCIN_COLLAPSE_DEFAULT); + if (ret) { + dev_err(pwr->dev, "Failed to write DCIN collapse limit\n"); + return ret; + } + + ret =3D pwr->bat_inserted(pwr); + if (ret < 0) + return ret; + + if (ret) { + /* WDT_FST auto set */ + ret =3D regmap_update_bits(pwr->regmap, pwr->regs->chg_set1, + BD7182x_MASK_WDT_AUTO, + BD7182x_MASK_WDT_AUTO); + if (ret) + return ret; + + ret =3D bd7182x_write16(pwr, pwr->regs->vbat_alm_limit_u, + VBAT_LOW_TH); + if (ret) + return ret; + + /* + * On BD71815 "we mask the power-state" from relax detection. + * I am unsure what the impact of the power-state would be if + * we didn't - but this is what the vendor driver did - and + * that driver has been used in few projects so I just assume + * this is needed. + */ + if (pwr->chip_type =3D=3D ROHM_CHIP_TYPE_BD71815) { + ret =3D regmap_set_bits(pwr->regmap, + BD71815_REG_REX_CTRL_1, + REX_PMU_STATE_MASK); + if (ret) + return ret; + } + } + + return 0; +} + +static int bd71828_charger_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct bd71828_power *pwr =3D dev_get_drvdata(psy->dev.parent); + u32 vot; + u16 tmp; + int online; + int ret; + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + ret =3D get_chg_online(pwr, &online); + if (!ret) + val->intval =3D online; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + ret =3D bd7182x_read16_himask(pwr, pwr->regs->vdcin, + BD7182x_MASK_VDCIN_U, &tmp); + if (ret) + return ret; + + vot =3D tmp; + /* 5 milli volt steps */ + val->intval =3D 5000 * vot; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int bd71828_battery_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct bd71828_power *pwr =3D dev_get_drvdata(psy->dev.parent); + int ret =3D 0; + int status, health, tmp, curr, curr_avg, chg_en; + + if (psp =3D=3D POWER_SUPPLY_PROP_STATUS || + psp =3D=3D POWER_SUPPLY_PROP_HEALTH || + psp =3D=3D POWER_SUPPLY_PROP_CHARGE_TYPE) + ret =3D bd71828_charge_status(pwr, &status, &health); + else if (psp =3D=3D POWER_SUPPLY_PROP_CURRENT_AVG || + psp =3D=3D POWER_SUPPLY_PROP_CURRENT_NOW) + ret =3D bd71828_get_current_ds_adc(pwr, &curr, &curr_avg); + if (ret) + return ret; + + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + val->intval =3D status; + break; + case POWER_SUPPLY_PROP_HEALTH: + val->intval =3D health; + break; + case POWER_SUPPLY_PROP_PRESENT: + ret =3D get_bat_online(pwr, &tmp); + if (!ret) + val->intval =3D tmp; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + ret =3D bd71828_get_vbat(pwr, &tmp); + val->intval =3D tmp; + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval =3D POWER_SUPPLY_TECHNOLOGY_LION; + break; + case POWER_SUPPLY_PROP_CURRENT_AVG: + val->intval =3D curr_avg; + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval =3D curr; + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + val->intval =3D MAX_CURRENT_DEFAULT; + break; + case POWER_SUPPLY_PROP_TEMP: + ret =3D pwr->get_temp(pwr, &val->intval); + break; + case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR: + ret =3D regmap_read(pwr->regmap, pwr->regs->chg_en, &chg_en); + if (ret) + return ret; + + val->intval =3D (chg_en & BD7182x_MASK_CHG_EN) ? + POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO : + POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE; + break; + default: + ret =3D -EINVAL; + break; + } + + return ret; +} + +static int bd71828_battery_set_property(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct bd71828_power *pwr =3D dev_get_drvdata(psy->dev.parent); + int ret =3D 0; + + switch (psp) { + case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR: + if (val->intval =3D=3D POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO) + ret =3D regmap_update_bits(pwr->regmap, pwr->regs->chg_en, + BD7182x_MASK_CHG_EN, + BD7182x_MASK_CHG_EN); + else + ret =3D regmap_update_bits(pwr->regmap, pwr->regs->chg_en, + BD7182x_MASK_CHG_EN, + 0); + break; + default: + return -EINVAL; + } + + return ret; +} + +static int bd71828_battery_property_is_writeable(struct power_supply *psy, + enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR: + return true; + default: + return false; + } +} + +/** @brief ac properties */ +static const enum power_supply_property bd71828_charger_props[] =3D { + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_VOLTAGE_NOW, +}; + +static const enum power_supply_property bd71828_battery_props[] =3D { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_CURRENT_AVG, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CURRENT_MAX, + POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR, +}; + +/** @brief powers supplied by bd71828_ac */ +static char *bd71828_ac_supplied_to[] =3D { + BAT_NAME, +}; + +static const struct power_supply_desc bd71828_ac_desc =3D { + .name =3D AC_NAME, + .type =3D POWER_SUPPLY_TYPE_MAINS, + .properties =3D bd71828_charger_props, + .num_properties =3D ARRAY_SIZE(bd71828_charger_props), + .get_property =3D bd71828_charger_get_property, +}; + +static const struct power_supply_desc bd71828_bat_desc =3D { + .name =3D BAT_NAME, + .type =3D POWER_SUPPLY_TYPE_BATTERY, + .charge_behaviours =3D BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO) | + BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE), + .properties =3D bd71828_battery_props, + .num_properties =3D ARRAY_SIZE(bd71828_battery_props), + .get_property =3D bd71828_battery_get_property, + .set_property =3D bd71828_battery_set_property, + .property_is_writeable =3D bd71828_battery_property_is_writeable, +}; + +#define RSENS_CURR 10000000LLU + +#define BD_ISR_NAME(name) \ +bd7181x_##name##_isr + +#define BD_ISR_BAT(name, print, run_gauge) \ +static irqreturn_t BD_ISR_NAME(name)(int irq, void *data) \ +{ \ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; \ + \ + dev_dbg(pwr->dev, "%s\n", print); \ + power_supply_changed(pwr->bat); \ + \ + return IRQ_HANDLED; \ +} + +#define BD_ISR_AC(name, print, run_gauge) \ +static irqreturn_t BD_ISR_NAME(name)(int irq, void *data) \ +{ \ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; \ + \ + power_supply_changed(pwr->ac); \ + dev_dbg(pwr->dev, "%s\n", print); \ + power_supply_changed(pwr->bat); \ + \ + return IRQ_HANDLED; \ +} + +#define BD_ISR_DUMMY(name, print) \ +static irqreturn_t BD_ISR_NAME(name)(int irq, void *data) \ +{ \ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; \ + \ + dev_dbg(pwr->dev, "%s\n", print); \ + \ + return IRQ_HANDLED; \ +} + +BD_ISR_BAT(chg_state_changed, "CHG state changed", true) +/* DCIN voltage changes */ +BD_ISR_AC(dcin_removed, "DCIN removed", true) +BD_ISR_AC(clps_out, "DCIN voltage back to normal", true) +BD_ISR_AC(clps_in, "DCIN voltage collapsed", false) +BD_ISR_AC(dcin_ovp_res, "DCIN voltage normal", true) +BD_ISR_AC(dcin_ovp_det, "DCIN OVER VOLTAGE", true) + +BD_ISR_DUMMY(dcin_mon_det, "DCIN voltage below threshold") +BD_ISR_DUMMY(dcin_mon_res, "DCIN voltage above threshold") + +BD_ISR_DUMMY(vsys_uv_res, "VSYS under-voltage cleared") +BD_ISR_DUMMY(vsys_uv_det, "VSYS under-voltage") +BD_ISR_DUMMY(vsys_low_res, "'VSYS low' cleared") +BD_ISR_DUMMY(vsys_low_det, "VSYS low") +BD_ISR_DUMMY(vsys_mon_res, "VSYS mon - resumed") +BD_ISR_DUMMY(vsys_mon_det, "VSYS mon - detected") +BD_ISR_BAT(chg_wdg_temp, "charger temperature watchdog triggered", true) +BD_ISR_BAT(chg_wdg, "charging watchdog triggered", true) +BD_ISR_BAT(bat_removed, "Battery removed", true) +BD_ISR_BAT(bat_det, "Battery detected", true) +/* TODO: Verify the meaning of these interrupts */ +BD_ISR_BAT(rechg_det, "Recharging", true) +BD_ISR_BAT(rechg_res, "Recharge ending", true) +BD_ISR_DUMMY(temp_transit, "Temperature transition") +BD_ISR_BAT(therm_rmv, "bd71815-therm-rmv", false) +BD_ISR_BAT(therm_det, "bd71815-therm-det", true) +BD_ISR_BAT(bat_dead, "bd71815-bat-dead", false) +BD_ISR_BAT(bat_short_res, "bd71815-bat-short-res", true) +BD_ISR_BAT(bat_short, "bd71815-bat-short-det", false) +BD_ISR_BAT(bat_low_res, "bd71815-bat-low-res", true) +BD_ISR_BAT(bat_low, "bd71815-bat-low-det", true) +BD_ISR_BAT(bat_ov_res, "bd71815-bat-over-res", true) +/* What should we do here? */ +BD_ISR_BAT(bat_ov, "bd71815-bat-over-det", false) +BD_ISR_BAT(bat_mon_res, "bd71815-bat-mon-res", true) +BD_ISR_BAT(bat_mon, "bd71815-bat-mon-det", true) +BD_ISR_BAT(bat_cc_mon, "bd71815-bat-cc-mon2", false) +BD_ISR_BAT(bat_oc1_res, "bd71815-bat-oc1-res", true) +BD_ISR_BAT(bat_oc1, "bd71815-bat-oc1-det", false) +BD_ISR_BAT(bat_oc2_res, "bd71815-bat-oc2-res", true) +BD_ISR_BAT(bat_oc2, "bd71815-bat-oc2-det", false) +BD_ISR_BAT(bat_oc3_res, "bd71815-bat-oc3-res", true) +BD_ISR_BAT(bat_oc3, "bd71815-bat-oc3-det", false) +BD_ISR_BAT(temp_bat_low_res, "bd71815-temp-bat-low-res", true) +BD_ISR_BAT(temp_bat_low, "bd71815-temp-bat-low-det", true) +BD_ISR_BAT(temp_bat_hi_res, "bd71815-temp-bat-hi-res", true) +BD_ISR_BAT(temp_bat_hi, "bd71815-temp-bat-hi-det", true) + +static irqreturn_t bd7182x_dcin_removed(int irq, void *data) +{ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; + + power_supply_changed(pwr->ac); + dev_dbg(pwr->dev, "DCIN removed\n"); + + return IRQ_HANDLED; +} + +static irqreturn_t bd718x7_chg_done(int irq, void *data) +{ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; + + power_supply_changed(pwr->bat); + + return IRQ_HANDLED; +} + +static irqreturn_t bd7182x_dcin_detected(int irq, void *data) +{ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; + + dev_dbg(pwr->dev, "DCIN inserted\n"); + power_supply_changed(pwr->ac); + + return IRQ_HANDLED; +} + +static irqreturn_t bd71828_vbat_low_res(int irq, void *data) +{ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; + + dev_dbg(pwr->dev, "VBAT LOW Resumed\n"); + + return IRQ_HANDLED; +} + +static irqreturn_t bd71828_vbat_low_det(int irq, void *data) +{ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; + + dev_dbg(pwr->dev, "VBAT LOW Detected\n"); + + return IRQ_HANDLED; +} + +static irqreturn_t bd71828_temp_bat_hi_det(int irq, void *data) +{ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; + + dev_warn(pwr->dev, "Overtemp Detected\n"); + power_supply_changed(pwr->bat); + + return IRQ_HANDLED; +} + +static irqreturn_t bd71828_temp_bat_hi_res(int irq, void *data) +{ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; + + dev_dbg(pwr->dev, "Overtemp Resumed\n"); + power_supply_changed(pwr->bat); + + return IRQ_HANDLED; +} + +static irqreturn_t bd71828_temp_bat_low_det(int irq, void *data) +{ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; + + dev_dbg(pwr->dev, "Lowtemp Detected\n"); + power_supply_changed(pwr->bat); + + return IRQ_HANDLED; +} + +static irqreturn_t bd71828_temp_bat_low_res(int irq, void *data) +{ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; + + dev_dbg(pwr->dev, "Lowtemp Resumed\n"); + power_supply_changed(pwr->bat); + + return IRQ_HANDLED; +} + +static irqreturn_t bd71828_temp_vf_det(int irq, void *data) +{ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; + + dev_dbg(pwr->dev, "VF Detected\n"); + power_supply_changed(pwr->bat); + + return IRQ_HANDLED; +} + +static irqreturn_t bd71828_temp_vf_res(int irq, void *data) +{ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; + + dev_dbg(pwr->dev, "VF Resumed\n"); + power_supply_changed(pwr->bat); + + return IRQ_HANDLED; +} + +static irqreturn_t bd71828_temp_vf125_det(int irq, void *data) +{ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; + + dev_dbg(pwr->dev, "VF125 Detected\n"); + power_supply_changed(pwr->bat); + + return IRQ_HANDLED; +} + +static irqreturn_t bd71828_temp_vf125_res(int irq, void *data) +{ + struct bd71828_power *pwr =3D (struct bd71828_power *)data; + + dev_dbg(pwr->dev, "VF125 Resumed\n"); + power_supply_changed(pwr->bat); + + return IRQ_HANDLED; +} + +struct bd7182x_irq_res { + const char *name; + irq_handler_t handler; +}; + +#define BDIRQ(na, hn) { .name =3D (na), .handler =3D (hn) } + +static int bd7182x_get_irqs(struct platform_device *pdev, + struct bd71828_power *pwr) +{ + int i, irq, ret; + static const struct bd7182x_irq_res bd71815_irqs[] =3D { + BDIRQ("bd71815-dcin-rmv", BD_ISR_NAME(dcin_removed)), + BDIRQ("bd71815-dcin-clps-out", BD_ISR_NAME(clps_out)), + BDIRQ("bd71815-dcin-clps-in", BD_ISR_NAME(clps_in)), + BDIRQ("bd71815-dcin-ovp-res", BD_ISR_NAME(dcin_ovp_res)), + BDIRQ("bd71815-dcin-ovp-det", BD_ISR_NAME(dcin_ovp_det)), + BDIRQ("bd71815-dcin-mon-res", BD_ISR_NAME(dcin_mon_res)), + BDIRQ("bd71815-dcin-mon-det", BD_ISR_NAME(dcin_mon_det)), + + BDIRQ("bd71815-vsys-uv-res", BD_ISR_NAME(vsys_uv_res)), + BDIRQ("bd71815-vsys-uv-det", BD_ISR_NAME(vsys_uv_det)), + BDIRQ("bd71815-vsys-low-res", BD_ISR_NAME(vsys_low_res)), + BDIRQ("bd71815-vsys-low-det", BD_ISR_NAME(vsys_low_det)), + BDIRQ("bd71815-vsys-mon-res", BD_ISR_NAME(vsys_mon_res)), + BDIRQ("bd71815-vsys-mon-det", BD_ISR_NAME(vsys_mon_det)), + BDIRQ("bd71815-chg-wdg-temp", BD_ISR_NAME(chg_wdg_temp)), + BDIRQ("bd71815-chg-wdg", BD_ISR_NAME(chg_wdg)), + BDIRQ("bd71815-rechg-det", BD_ISR_NAME(rechg_det)), + BDIRQ("bd71815-rechg-res", BD_ISR_NAME(rechg_res)), + BDIRQ("bd71815-ranged-temp-transit", BD_ISR_NAME(temp_transit)), + BDIRQ("bd71815-chg-state-change", BD_ISR_NAME(chg_state_changed)), + BDIRQ("bd71815-bat-temp-normal", bd71828_temp_bat_hi_res), + BDIRQ("bd71815-bat-temp-erange", bd71828_temp_bat_hi_det), + BDIRQ("bd71815-bat-rmv", BD_ISR_NAME(bat_removed)), + BDIRQ("bd71815-bat-det", BD_ISR_NAME(bat_det)), + + /* Add ISRs for these */ + BDIRQ("bd71815-therm-rmv", BD_ISR_NAME(therm_rmv)), + BDIRQ("bd71815-therm-det", BD_ISR_NAME(therm_det)), + BDIRQ("bd71815-bat-dead", BD_ISR_NAME(bat_dead)), + BDIRQ("bd71815-bat-short-res", BD_ISR_NAME(bat_short_res)), + BDIRQ("bd71815-bat-short-det", BD_ISR_NAME(bat_short)), + BDIRQ("bd71815-bat-low-res", BD_ISR_NAME(bat_low_res)), + BDIRQ("bd71815-bat-low-det", BD_ISR_NAME(bat_low)), + BDIRQ("bd71815-bat-over-res", BD_ISR_NAME(bat_ov_res)), + BDIRQ("bd71815-bat-over-det", BD_ISR_NAME(bat_ov)), + BDIRQ("bd71815-bat-mon-res", BD_ISR_NAME(bat_mon_res)), + BDIRQ("bd71815-bat-mon-det", BD_ISR_NAME(bat_mon)), + /* cc-mon 1 & 3 ? */ + BDIRQ("bd71815-bat-cc-mon2", BD_ISR_NAME(bat_cc_mon)), + BDIRQ("bd71815-bat-oc1-res", BD_ISR_NAME(bat_oc1_res)), + BDIRQ("bd71815-bat-oc1-det", BD_ISR_NAME(bat_oc1)), + BDIRQ("bd71815-bat-oc2-res", BD_ISR_NAME(bat_oc2_res)), + BDIRQ("bd71815-bat-oc2-det", BD_ISR_NAME(bat_oc2)), + BDIRQ("bd71815-bat-oc3-res", BD_ISR_NAME(bat_oc3_res)), + BDIRQ("bd71815-bat-oc3-det", BD_ISR_NAME(bat_oc3)), + BDIRQ("bd71815-temp-bat-low-res", BD_ISR_NAME(temp_bat_low_res)), + BDIRQ("bd71815-temp-bat-low-det", BD_ISR_NAME(temp_bat_low)), + BDIRQ("bd71815-temp-bat-hi-res", BD_ISR_NAME(temp_bat_hi_res)), + BDIRQ("bd71815-temp-bat-hi-det", BD_ISR_NAME(temp_bat_hi)), + /* + * TODO: add rest of the IRQs and re-check the handling. + * Check the bd71815-bat-cc-mon1, bd71815-bat-cc-mon3, + * bd71815-bat-low-res, bd71815-bat-low-det, + * bd71815-bat-hi-res, bd71815-bat-hi-det. + */ + }; + static const struct bd7182x_irq_res bd71828_irqs[] =3D { + BDIRQ("bd71828-chg-done", bd718x7_chg_done), + BDIRQ("bd71828-pwr-dcin-in", bd7182x_dcin_detected), + BDIRQ("bd71828-pwr-dcin-out", bd7182x_dcin_removed), + BDIRQ("bd71828-vbat-normal", bd71828_vbat_low_res), + BDIRQ("bd71828-vbat-low", bd71828_vbat_low_det), + BDIRQ("bd71828-btemp-hi", bd71828_temp_bat_hi_det), + BDIRQ("bd71828-btemp-cool", bd71828_temp_bat_hi_res), + BDIRQ("bd71828-btemp-lo", bd71828_temp_bat_low_det), + BDIRQ("bd71828-btemp-warm", bd71828_temp_bat_low_res), + BDIRQ("bd71828-temp-hi", bd71828_temp_vf_det), + BDIRQ("bd71828-temp-norm", bd71828_temp_vf_res), + BDIRQ("bd71828-temp-125-over", bd71828_temp_vf125_det), + BDIRQ("bd71828-temp-125-under", bd71828_temp_vf125_res), + }; + int num_irqs; + const struct bd7182x_irq_res *irqs; + + switch (pwr->chip_type) { + case ROHM_CHIP_TYPE_BD71828: + irqs =3D &bd71828_irqs[0]; + num_irqs =3D ARRAY_SIZE(bd71828_irqs); + break; + case ROHM_CHIP_TYPE_BD71815: + irqs =3D &bd71815_irqs[0]; + num_irqs =3D ARRAY_SIZE(bd71815_irqs); + break; + default: + return -EINVAL; + } + + for (i =3D 0; i < num_irqs; i++) { + irq =3D platform_get_irq_byname(pdev, irqs[i].name); + + ret =3D devm_request_threaded_irq(&pdev->dev, irq, NULL, + irqs[i].handler, 0, + irqs[i].name, pwr); + if (ret) + break; + } + + return ret; +} + +#define RSENS_DEFAULT_30MOHM 30000 /* 30 mOhm in uOhms*/ + +static int bd7182x_get_rsens(struct bd71828_power *pwr) +{ + u64 tmp =3D RSENS_CURR; + int rsens_ohm =3D RSENS_DEFAULT_30MOHM; + struct fwnode_handle *node =3D NULL; + + if (pwr->dev->parent) + node =3D dev_fwnode(pwr->dev->parent); + + if (node) { + int ret; + u32 rs; + + ret =3D fwnode_property_read_u32(node, + "rohm,charger-sense-resistor-micro-ohms", + &rs); + if (ret) { + if (ret =3D=3D -EINVAL) { + rs =3D RSENS_DEFAULT_30MOHM; + } else { + dev_err(pwr->dev, "Bad RSENS dt property\n"); + return ret; + } + } + if (!rs) { + dev_err(pwr->dev, "Bad RSENS value\n"); + return -EINVAL; + } + + rsens_ohm =3D (int)rs; + } + + /* Reg val to uA */ + do_div(tmp, rsens_ohm); + + pwr->curr_factor =3D tmp; + pwr->rsens =3D rsens_ohm; + dev_dbg(pwr->dev, "Setting rsens to %u micro ohm\n", pwr->rsens); + dev_dbg(pwr->dev, "Setting curr-factor to %u\n", pwr->curr_factor); + + return 0; +} + +static int bd71828_power_probe(struct platform_device *pdev) +{ + struct bd71828_power *pwr; + struct power_supply_config ac_cfg =3D {}; + struct power_supply_config bat_cfg =3D {}; + int ret; + struct regmap *regmap; + + regmap =3D dev_get_regmap(pdev->dev.parent, NULL); + if (!regmap) { + dev_err(&pdev->dev, "No parent regmap\n"); + return -EINVAL; + } + + pwr =3D devm_kzalloc(&pdev->dev, sizeof(*pwr), GFP_KERNEL); + if (!pwr) + return -ENOMEM; + + pwr->regmap =3D regmap; + pwr->dev =3D &pdev->dev; + pwr->chip_type =3D platform_get_device_id(pdev)->driver_data; + + switch (pwr->chip_type) { + case ROHM_CHIP_TYPE_BD71828: + pwr->bat_inserted =3D bd71828_bat_inserted; + pwr->get_temp =3D bd71828_get_temp; + pwr->regs =3D &pwr_regs_bd71828; + break; + case ROHM_CHIP_TYPE_BD71815: + pwr->bat_inserted =3D bd71815_bat_inserted; + pwr->get_temp =3D bd71815_get_temp; + pwr->regs =3D &pwr_regs_bd71815; + break; + default: + dev_err(pwr->dev, "Unknown PMIC\n"); + return -EINVAL; + } + + ret =3D bd7182x_get_rsens(pwr); + if (ret) + return dev_err_probe(&pdev->dev, ret, "sense resistor missing\n"); + + dev_set_drvdata(&pdev->dev, pwr); + bd71828_init_hardware(pwr); + + bat_cfg.drv_data =3D pwr; + bat_cfg.fwnode =3D dev_fwnode(&pdev->dev); + + ac_cfg.supplied_to =3D bd71828_ac_supplied_to; + ac_cfg.num_supplicants =3D ARRAY_SIZE(bd71828_ac_supplied_to); + ac_cfg.drv_data =3D pwr; + + pwr->ac =3D devm_power_supply_register(&pdev->dev, &bd71828_ac_desc, + &ac_cfg); + if (IS_ERR(pwr->ac)) + return dev_err_probe(&pdev->dev, PTR_ERR(pwr->ac), + "failed to register ac\n"); + + pwr->bat =3D devm_power_supply_register(&pdev->dev, &bd71828_bat_desc, + &bat_cfg); + if (IS_ERR(pwr->bat)) + return dev_err_probe(&pdev->dev, PTR_ERR(pwr->bat), + "failed to register bat\n"); + + ret =3D bd7182x_get_irqs(pdev, pwr); + if (ret) + return dev_err_probe(&pdev->dev, ret, "failed to request IRQs"); + + /* Configure wakeup capable */ + device_set_wakeup_capable(pwr->dev, 1); + device_set_wakeup_enable(pwr->dev, 1); + + return 0; +} + +static const struct platform_device_id bd71828_charger_id[] =3D { + { "bd71815-power", ROHM_CHIP_TYPE_BD71815 }, + { "bd71828-power", ROHM_CHIP_TYPE_BD71828 }, + { }, +}; +MODULE_DEVICE_TABLE(platform, bd71828_charger_id); + +static struct platform_driver bd71828_power_driver =3D { + .driver =3D { + .name =3D "bd718xx-power", + }, + .probe =3D bd71828_power_probe, + .id_table =3D bd71828_charger_id, +}; + +module_platform_driver(bd71828_power_driver); + +MODULE_AUTHOR("Cong Pham "); +MODULE_DESCRIPTION("ROHM BD718(15/28/78) PMIC Battery Charger driver"); +MODULE_LICENSE("GPL"); --=20 2.47.3 From nobody Thu Oct 2 10:53:02 2025 Received: from mail.andi.de1.cc (mail.andi.de1.cc [178.238.236.174]) (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 76B9D2FF16B; Wed, 17 Sep 2025 17:48:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.238.236.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758131321; cv=none; b=Eylruk6XsmWkbRDYViArxFPDwb4lA/Zc625bAbz4SNYzLarjpZVqLU9SFLg8VbNOXkmTIFKubRK46qvzsNLjbExtA83KlWuxM2o1x0+TBcEjNvNxljJZP4YQGdwEpY+rp5WGFdXVcpfcRICtqnjuhVXAwlxEltpqocfFxVGLFNI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758131321; c=relaxed/simple; bh=/tS5VN8wqJ0W6f79Uht7zyfEMcAvhg6Jn1SC8qgkuXk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=UFpZ2JqLqU1v9ExRR9RwJbtgSBNsT9lY2u7i6JTURZPwl2XH/YdsuHO/pKWqIhvgQjouLqABEuC+MBg7ySk9hb6g72l6Iq91nm7CT3FErQC9ivqIy8T+6WM/IeER9epih7v9suy9ekVwFiFKmvdN/YRujAjh7EmPfNgUvqxxF/I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=kemnade.info; spf=pass smtp.mailfrom=kemnade.info; dkim=pass (2048-bit key) header.d=kemnade.info header.i=@kemnade.info header.b=lmGhiiIt; arc=none smtp.client-ip=178.238.236.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=kemnade.info Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=kemnade.info Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kemnade.info header.i=@kemnade.info header.b="lmGhiiIt" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=kemnade.info; s=20220719; h=Cc:In-Reply-To:References:From:Sender:Reply-To: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID; bh=3q5kiib1kd62l3L+MK1D9QnKWb3L2UjvT/k4OiP6KHs=; b=lmGhiiItEIEn4oHqn9ygwJ2xTy p3yRTkwf/diZ/RkOkOFIij3iPe7/Is1o2vW3k3imaDonJYd0Bn36PUoIb/DpRbfN9jP2JdJTDG4TE umakduLqcB7QFk7k6idX3t8/GFVrJ2nPeQYWD0xFCyBO+94uMEkUFqPSZ4Sa2mrOWBiZYptxEBrhZ 9RFucdZT1SmlQwT4eqxuesEr6dpQ1QA/0Y63APO36ZDkyYwMFaOLE92u1id0BGfr7gxai7fKBp6W+ EtujfNVwHJbyWqL7H3dHq/6GcRmfuJEN1FNoArCuCdiRad9Co8/QIfbnYlbCSftt1qhs1tSYR5KyI wSPrSAkw==; From: Andreas Kemnade Date: Wed, 17 Sep 2025 19:48:04 +0200 Subject: [PATCH v4 3/3] MAINTAINERS: Add entry for BD71828 charger 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: <20250917-bd71828-charger-v4-3-fbc85a910499@kemnade.info> References: <20250917-bd71828-charger-v4-0-fbc85a910499@kemnade.info> In-Reply-To: <20250917-bd71828-charger-v4-0-fbc85a910499@kemnade.info> To: Matti Vaittinen , Lee Jones , Sebastian Reichel Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, Krzysztof Kozlowski , Andreas Kemnade X-Mailer: b4 0.15-dev-50721 X-Developer-Signature: v=1; a=openpgp-sha256; l=782; i=andreas@kemnade.info; h=from:subject:message-id; bh=/tS5VN8wqJ0W6f79Uht7zyfEMcAvhg6Jn1SC8qgkuXk=; b=owGbwMvMwCUm/rzkS6lq2x3G02pJDBmnvmRJ2/T7mJxfkTn/YuAv0ZbG29mHNK7fdt9aJj+za kboMhGNjlIWBjEuBlkxRZZf1gpun1Se5QZPjbCHmcPKBDKEgYtTACaS3crwV7p+qd3qBbdqBT9a /Tq38av1Bu2ivcciGjgjBWTfOe09KsPwT/EOm7HHDf7DJZ12n0u/hu157XZQWjQ77sqGUDFVa31 RHgA= X-Developer-Key: i=andreas@kemnade.info; a=openpgp; fpr=EEC0DB858E66C0DA70620AC07DBD6AC74DE29324 Add an entry for BD71828 charger driver. Signed-off-by: Andreas Kemnade Suggested-by: Matti Vaittinen Reviewed-by: Matti Vaittinen --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index fe168477caa45..044eb41ba4797 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21848,6 +21848,12 @@ L: linux-serial@vger.kernel.org S: Odd Fixes F: drivers/tty/serial/rp2.* =20 +ROHM BD71828 CHARGER +M: Andreas Kemnade +M: Matti Vaittinen +S: Maintained +F: drivers/power/supply/bd71828-charger.c + ROHM BD79703 DAC M: Matti Vaittinen S: Supported --=20 2.47.3