From nobody Fri Oct 3 13:27:17 2025 Received: from mx.olsak.net (mx.olsak.net [37.205.8.231]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 12C1523956A; Sun, 31 Aug 2025 10:33:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=37.205.8.231 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756636422; cv=none; b=ICpBPup/mNZPFvvIihLE5FX7WoE0BDeqm0Jza1zsiW76mYisbHGGvh4KVf9NPnErNN2IA4C7F/d8goOYuRMs3cVPE6SUi+IoZi8CyAqe5apXtA7hDb92ZewfB0vbAGxFUdcWZsLjVuV0HjT/cPRitN+MJFmYTQI13DOE98pbhmE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756636422; c=relaxed/simple; bh=/BWt+gb17rWNwqyQ+PIFgYY2U43Z8AJLgUzQ6kNKN5o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=j7MCVdTw0Tkb4WoIVGbiTTZlG2AhRGlFjtME9iEVAzLtrtoFiX+hbnQL+SDGL1UskhmHgMWR3j92150D3/1KfMDk6H9y/7wyaMPerJ2E8s/93khc6BYR14NyogUgoDKoPVcBns2rpLRQAAabprIFRIBXAoEIvNpRHUGxkZandbE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=dujemihanovic.xyz; spf=pass smtp.mailfrom=dujemihanovic.xyz; dkim=pass (2048-bit key) header.d=dujemihanovic.xyz header.i=@dujemihanovic.xyz header.b=T/QTrKJY; arc=none smtp.client-ip=37.205.8.231 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=dujemihanovic.xyz Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=dujemihanovic.xyz Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=dujemihanovic.xyz header.i=@dujemihanovic.xyz header.b="T/QTrKJY" DKIM-Signature: a=rsa-sha256; bh=SsSfy111NsTTMO5BFJ1Oz+QDDxhQIm8ud+geT3OT/AA=; c=relaxed/relaxed; d=dujemihanovic.xyz; h=Subject:Subject:Sender:To:To:Cc:Cc:From:From:Date:Date:MIME-Version:MIME-Version:Content-Type:Content-Type:Content-Transfer-Encoding:Content-Transfer-Encoding:Reply-To:In-Reply-To:In-Reply-To:Message-Id:Message-Id:References:References:Autocrypt:Openpgp; i=@dujemihanovic.xyz; s=default; t=1756636409; v=1; x=1757068409; b=T/QTrKJYfOALdFVF6aORoM5uQOienY9Si9kEbpzngXkAGzdySQ5Hm+Isb0oLhb+a8T8vaqta GyxtHyyyBUEkiqOCSviY2ztXfT7JkMyxIyhXC1DJ2H/9cl/nGhKDZh23RdKmvu9nIElCC/c7uTq uKmrj4Qn2e6XCuzayvz7OzjlY4enEO/MNdhmKxfoRn7v2eL6U9YdsgnG+/8IzkCUieOiFEO+1Ub fAYXJsK9N2aRgsYx+1ym35ee+fkMotwvrcZJeRhyn1yxK29I4On+jvqTLDupD5nx2raVuI+ogH+ xOQ00DWjQ1F9gCC2rxjkAf4egvIdFSB1npz9bHD8vCMiQ== Received: by mx.olsak.net (envelope-sender ) with ESMTPS id dd0e146c; Sun, 31 Aug 2025 12:33:29 +0200 From: =?utf-8?q?Duje_Mihanovi=C4=87?= Date: Sun, 31 Aug 2025 12:33:04 +0200 Subject: [PATCH v2 1/3] dt-bindings: mfd: 88pm886: Add #io-channel-cells 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: <20250831-88pm886-gpadc-v2-1-759c1e14d95f@dujemihanovic.xyz> References: <20250831-88pm886-gpadc-v2-0-759c1e14d95f@dujemihanovic.xyz> In-Reply-To: <20250831-88pm886-gpadc-v2-0-759c1e14d95f@dujemihanovic.xyz> To: Jonathan Cameron , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko , Karel Balej , Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: David Wronek , phone-devel@vger.kernel.org, ~postmarketos/upstreaming@lists.sr.ht, linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, devicetree@vger.kernel.org, =?utf-8?q?Duje_Mihanovi=C4=87?= X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1144; i=duje@dujemihanovic.xyz; s=20240706; h=from:subject:message-id; bh=/BWt+gb17rWNwqyQ+PIFgYY2U43Z8AJLgUzQ6kNKN5o=; b=owGbwMvMwCW21nBykGv/WmbG02pJDBlbVL7bV0THvVrx+LhFd89MXUv7H0WZjv0fpx7zVuL7s 2BXh0VpRykLgxgXg6yYIkvuf8drvJ9Ftm7PXmYAM4eVCWQIAxenAExE8BYjw5S76Sk2ga6KIi8N A+2dP2x4v+Lhq/naxVMEDruJS6u828PIMOPVwoKvB71yf3xcF7vHZ8nEXq6k64ZzIrWf1NWv0py xmBcA X-Developer-Key: i=duje@dujemihanovic.xyz; a=openpgp; fpr=6DFF41D60DF314B5B76BA630AD319352458FAD03 Add an #io-channel-cells property to the Marvell 88PM886 PMIC binding to allow referencing the IO channels exposed by its GPADC. Signed-off-by: Duje Mihanovi=C4=87 Acked-by: Karel Balej # for the PMIC Acked-by: Krzysztof Kozlowski --- v2: - New patch --- Documentation/devicetree/bindings/mfd/marvell,88pm886-a1.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/mfd/marvell,88pm886-a1.yaml = b/Documentation/devicetree/bindings/mfd/marvell,88pm886-a1.yaml index d6a71c912b76f7d24787d346d4b4cd51919b1cf6..92a72a99fd790805e775727e39d= 457608fa1795d 100644 --- a/Documentation/devicetree/bindings/mfd/marvell,88pm886-a1.yaml +++ b/Documentation/devicetree/bindings/mfd/marvell,88pm886-a1.yaml @@ -35,6 +35,9 @@ properties: description: LDO or buck regulator. unevaluatedProperties: false =20 + '#io-channel-cells': + const: 1 + required: - compatible - reg @@ -53,6 +56,7 @@ examples: reg =3D <0x30>; interrupts =3D <0 4 IRQ_TYPE_LEVEL_HIGH>; interrupt-parent =3D <&gic>; + #io-channel-cells =3D <1>; wakeup-source; =20 regulators { --=20 2.51.0 From nobody Fri Oct 3 13:27:17 2025 Received: from mx.olsak.net (mx.olsak.net [37.205.8.231]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 65B0623ABBF; Sun, 31 Aug 2025 10:33:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=37.205.8.231 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756636422; cv=none; b=E+OOnUhoSxz+aW+TonCgNxCQi8eu83J55sTOVkb3Gg58lj9lF6kcvG4KyuCFo15JRoP+lgvc49eNNXHcr9zA4Bl2Qa9WyaovLJfSpmbnUW8IznA0mg+P4n9Z6aEyXkL9cCEsQr8YR/FiXOIoOFJ+MtIj6hE1Xf9v43tFgPUVWAQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756636422; c=relaxed/simple; bh=aFuYIkR//cUq0RJAwIKx08u39tiL5jBfJxbdUHDyT1Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fHc/QqZ2fmphXN/CSEnI0YsFr/D8olheBk4qkCDvS4Deeq6nkoZwlPlhK8LMFzrN7cyqEGf3Z0r5l/hHPhEzumbLHDwX8LCK4IwE27U1QBaTlvyheK6RaI3lZ29bry+qsrAbM9g+qgeNnEi9rs+VEHuAd/T+JUfBfAJywhhmPMA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=dujemihanovic.xyz; spf=pass smtp.mailfrom=dujemihanovic.xyz; dkim=pass (2048-bit key) header.d=dujemihanovic.xyz header.i=@dujemihanovic.xyz header.b=ceBGeT8Y; arc=none smtp.client-ip=37.205.8.231 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=dujemihanovic.xyz Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=dujemihanovic.xyz Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=dujemihanovic.xyz header.i=@dujemihanovic.xyz header.b="ceBGeT8Y" DKIM-Signature: a=rsa-sha256; bh=0beVqiAHiGGTNrgmpnQZOFk6EzeD3sKNG7jS5aY5Lgo=; c=relaxed/relaxed; d=dujemihanovic.xyz; h=Subject:Subject:Sender:To:To:Cc:Cc:From:From:Date:Date:MIME-Version:MIME-Version:Content-Type:Content-Type:Content-Transfer-Encoding:Content-Transfer-Encoding:Reply-To:In-Reply-To:In-Reply-To:Message-Id:Message-Id:References:References:Autocrypt:Openpgp; i=@dujemihanovic.xyz; s=default; t=1756636410; v=1; x=1757068410; b=ceBGeT8YXT71ppuRngC0QKa5Xrv3oiz0gwAwAHF6YvS4veiAPoOaJF9UENHBQpwV7UTfaquq pqn6Tp0er+X99xgs11mGZsr/6KCj0Mxavhycd1dWmIIel3q+vuPQP+Tn6JEi2bHN0WiwNMKJJNe AfrO7Jegy4mfOH7panh1Xe8iCNa4nf46dV/xf3fv0+FvcbJWKmk0WtKmhlePO/vMsdY14oeOHVG kbn4hamjNRnVAqA1Q5AgOCpyhm6XX46yUZnt7NqE5BszWr++ZtHXzaU6CZqfPL11arggUDVISgF DhNvW6eMPH9NtPjIzit75s5FNBtSna/CDyp0uQaVThLxQ== Received: by mx.olsak.net (envelope-sender ) with ESMTPS id 5d29aea7; Sun, 31 Aug 2025 12:33:30 +0200 From: =?utf-8?q?Duje_Mihanovi=C4=87?= Date: Sun, 31 Aug 2025 12:33:05 +0200 Subject: [PATCH v2 2/3] iio: adc: Add driver for Marvell 88PM886 PMIC ADC 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: <20250831-88pm886-gpadc-v2-2-759c1e14d95f@dujemihanovic.xyz> References: <20250831-88pm886-gpadc-v2-0-759c1e14d95f@dujemihanovic.xyz> In-Reply-To: <20250831-88pm886-gpadc-v2-0-759c1e14d95f@dujemihanovic.xyz> To: Jonathan Cameron , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko , Karel Balej , Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: David Wronek , phone-devel@vger.kernel.org, ~postmarketos/upstreaming@lists.sr.ht, linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, devicetree@vger.kernel.org, =?utf-8?q?Duje_Mihanovi=C4=87?= X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=16589; i=duje@dujemihanovic.xyz; s=20240706; h=from:subject:message-id; bh=aFuYIkR//cUq0RJAwIKx08u39tiL5jBfJxbdUHDyT1Y=; b=owGbwMvMwCW21nBykGv/WmbG02pJDBlbVL7XdaYfOG0frvP4363d5qLeBybHrfWTjX2uts7/t tePissnO0pZGMS4GGTFFFly/zte4/0ssnV79jIDmDmsTCBDGLg4BWAidUqMDPvf1pWLTn8ZOFXl j5Zg5nR9x2sJMpvfVtxc22jw91vkvhKG/0FPourFeJY9ON/KHd2544yc06LPsSu2fcuM5753XyL 6GD8A X-Developer-Key: i=duje@dujemihanovic.xyz; a=openpgp; fpr=6DFF41D60DF314B5B76BA630AD319352458FAD03 Marvell's 88PM886 PMIC has a so-called General Purpose ADC used for monitoring various system voltages and temperatures. Add the relevant register definitions to the MFD header and a driver for the ADC. Signed-off-by: Duje Mihanovi=C4=87 --- v2: - default MFD_88PM886_PMIC - u8[2] -> __be16 - Drop kernel.h include - Add pm886_gpadc struct - Reorder channel enum - Drop GPADC voltage channels - Drop unnecessary masking in gpadc_get_raw() - Extend gpadc_enable_bias() to allow disabling bias - usleep_range() -> fsleep() - PM wrapper for pm886_gpadc_read_raw() - Proper channel info: voltage is RAW | SCALE, temperature is RAW | OFFSET | SCALE, resistance is PROCESSED - Explicitly define channels to en/disable in pm886_gpadc_setup() - Don't explicitly set iio->dev.parent - Miscellaneous style changes --- MAINTAINERS | 5 + drivers/iio/adc/88pm886-gpadc.c | 383 ++++++++++++++++++++++++++++++++++++= ++++ drivers/iio/adc/Kconfig | 13 ++ drivers/iio/adc/Makefile | 1 + include/linux/mfd/88pm886.h | 54 ++++++ 5 files changed, 456 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index fed6cd812d796a08cebc0c1fd540c8901d1bf448..b362d81e9c1532cc7920f9cec65= b1fd1f81471c6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14710,6 +14710,11 @@ F: drivers/regulator/88pm886-regulator.c F: drivers/rtc/rtc-88pm886.c F: include/linux/mfd/88pm886.h =20 +MARVELL 88PM886 PMIC GPADC DRIVER +M: Duje Mihanovi=C4=87 +S: Maintained +F: drivers/iio/adc/88pm886-gpadc.c + MARVELL ARMADA 3700 PHY DRIVERS M: Miquel Raynal S: Maintained diff --git a/drivers/iio/adc/88pm886-gpadc.c b/drivers/iio/adc/88pm886-gpad= c.c new file mode 100644 index 0000000000000000000000000000000000000000..4622d2525e0edeed89c6e6d4333= 6b177590aa885 --- /dev/null +++ b/drivers/iio/adc/88pm886-gpadc.c @@ -0,0 +1,383 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2025, Duje Mihanovi=C4=87 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +struct pm886_gpadc { + struct regmap *map; +}; + +static const int pm886_gpadc_regs[] =3D { + PM886_REG_GPADC_VSC, + PM886_REG_GPADC_VCHG_PWR, + PM886_REG_GPADC_VCF_OUT, + PM886_REG_GPADC_VBAT, + PM886_REG_GPADC_VBAT_SLP, + PM886_REG_GPADC_VBUS, + + PM886_REG_GPADC_GPADC0, + PM886_REG_GPADC_GPADC1, + PM886_REG_GPADC_GPADC2, + PM886_REG_GPADC_GPADC3, + + PM886_REG_GPADC_GND_DET1, + PM886_REG_GPADC_GND_DET2, + PM886_REG_GPADC_MIC_DET, + + PM886_REG_GPADC_TINT, +}; + +/* Must be kept in sync with the table above */ +enum pm886_gpadc_channel { + VSC_CHAN, + VCHG_PWR_CHAN, + VCF_OUT_CHAN, + VBAT_CHAN, + VBAT_SLP_CHAN, + VBUS_CHAN, + + GPADC0_CHAN, + GPADC1_CHAN, + GPADC2_CHAN, + GPADC3_CHAN, + + GND_DET1_CHAN, + GND_DET2_CHAN, + MIC_DET_CHAN, + + TINT_CHAN, +}; + +#define ADC_CHANNEL_VOLTAGE(index, lsb, name) { \ + .type =3D IIO_VOLTAGE, \ + .indexed =3D 1, \ + .channel =3D index, \ + .address =3D lsb, \ + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .datasheet_name =3D name, \ +} + +#define ADC_CHANNEL_RESISTANCE(index, lsb, name) { \ + .type =3D IIO_RESISTANCE, \ + .indexed =3D 1, \ + .channel =3D index, \ + .address =3D lsb, \ + .info_mask_separate =3D BIT(IIO_CHAN_INFO_PROCESSED), \ + .datasheet_name =3D name, \ +} + +#define ADC_CHANNEL_TEMPERATURE(index, lsb, name) { \ + .type =3D IIO_TEMP, \ + .indexed =3D 1, \ + .channel =3D index, \ + .address =3D lsb, \ + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ + .datasheet_name =3D name, \ +} + +static const struct iio_chan_spec pm886_gpadc_channels[] =3D { + ADC_CHANNEL_VOLTAGE(VSC_CHAN, 1367, "vsc"), + ADC_CHANNEL_VOLTAGE(VCHG_PWR_CHAN, 1709, "vchg_pwr"), + ADC_CHANNEL_VOLTAGE(VCF_OUT_CHAN, 1367, "vcf_out"), + ADC_CHANNEL_VOLTAGE(VBAT_CHAN, 1367, "vbat"), + ADC_CHANNEL_VOLTAGE(VBAT_SLP_CHAN, 1367, "vbat_slp"), + ADC_CHANNEL_VOLTAGE(VBUS_CHAN, 1709, "vbus"), + + ADC_CHANNEL_RESISTANCE(GPADC0_CHAN, 342, "gpadc0"), + ADC_CHANNEL_RESISTANCE(GPADC1_CHAN, 342, "gpadc1"), + ADC_CHANNEL_RESISTANCE(GPADC2_CHAN, 342, "gpadc2"), + ADC_CHANNEL_RESISTANCE(GPADC3_CHAN, 342, "gpadc3"), + + ADC_CHANNEL_VOLTAGE(GND_DET1_CHAN, 342, "gnddet1"), + ADC_CHANNEL_VOLTAGE(GND_DET2_CHAN, 342, "gnddet2"), + ADC_CHANNEL_VOLTAGE(MIC_DET_CHAN, 1367, "mic_det"), + + ADC_CHANNEL_TEMPERATURE(TINT_CHAN, 104, "tint"), +}; + +static const struct regmap_config pm886_gpadc_regmap_config =3D { + .reg_bits =3D 8, + .val_bits =3D 8, + .max_register =3D PM886_REG_GPADC_VBAT_SLP + 1, +}; + +static int gpadc_get_raw(struct iio_dev *iio, enum pm886_gpadc_channel cha= n) +{ + struct pm886_gpadc *gpadc =3D iio_priv(iio); + __be16 buf; + int ret; + + ret =3D regmap_bulk_read(gpadc->map, pm886_gpadc_regs[chan], &buf, sizeof= (buf)); + return !ret ? be16_to_cpu(buf) >> 4 : ret; +} + +static int +gpadc_set_bias(struct pm886_gpadc *gpadc, enum pm886_gpadc_channel chan, b= ool on) +{ + unsigned int gpadc_num =3D chan - GPADC0_CHAN; + unsigned int bits =3D BIT(gpadc_num + 4) | BIT(gpadc_num); + + return regmap_assign_bits(gpadc->map, PM886_REG_GPADC_CONFIG(0x14), bits,= on); +} + +static int +gpadc_find_bias_current(struct iio_dev *iio, struct iio_chan_spec const *c= han, + unsigned int *raw_uv, unsigned int *raw_ua) +{ + struct pm886_gpadc *gpadc =3D iio_priv(iio); + unsigned int gpadc_num =3D chan->channel - GPADC0_CHAN; + unsigned int reg =3D PM886_REG_GPADC_CONFIG(0xb + gpadc_num); + unsigned long lsb =3D chan->address; + int ret; + + for (unsigned int i =3D 0; i < PM886_GPADC_BIAS_LEVELS; i++) { + ret =3D regmap_update_bits(gpadc->map, reg, GENMASK(3, 0), i); + if (ret) + return ret; + + fsleep(5000); + + *raw_ua =3D PM886_GPADC_INDEX_TO_BIAS_UA(i); + *raw_uv =3D gpadc_get_raw(iio, chan->channel) * lsb; + + /* + * Vendor kernel errors out above 1.25V, but testing shows that + * the resistance of the battery detection channel (GPADC2 on + * coreprimevelte) reaches about 1.4Mohm when the battery is + * removed, which can't be measured with such a low upper + * limit. Therefore, to be able to detect the battery without + * ugly externs as used in the vendor fuelgauge driver, + * increase this limit a bit. + */ + if (WARN_ON(*raw_uv > 1500 * (MICRO / MILLI))) + return -EIO; + + /* + * Vendor kernel errors out under 300mV, but for the same + * reason as above (except the channel hovers around 3.5kohm + * with battery present) reduce this limit. + */ + if (*raw_uv < 200 * (MICRO / MILLI)) { + dev_dbg(&iio->dev, "bad bias for chan %d: %duA @ %duV\n", chan->channel, + *raw_ua, *raw_uv); + continue; + } + + dev_dbg(&iio->dev, "good bias for chan %d: %duA @ %duV\n", chan->channel, + *raw_ua, *raw_uv); + return 0; + } + + dev_err(&iio->dev, "failed to find good bias for chan %d\n", chan->channe= l); + return -EINVAL; +} + +static int +gpadc_get_resistance_ohm(struct iio_dev *iio, struct iio_chan_spec const *= chan) +{ + struct pm886_gpadc *gpadc =3D iio_priv(iio); + unsigned int raw_uv, raw_ua; + int ret; + + ret =3D gpadc_set_bias(gpadc, chan->channel, true); + if (ret) + goto err; + + ret =3D gpadc_find_bias_current(iio, chan, &raw_uv, &raw_ua); + if (ret) + goto err; + + ret =3D gpadc_set_bias(gpadc, chan->channel, false); + if (ret) + return ret; + + return DIV_ROUND_CLOSEST(raw_uv, raw_ua); +err: + gpadc_set_bias(gpadc, chan->channel, false); + return ret; +} + +static int +__pm886_gpadc_read_raw(struct iio_dev *iio, struct iio_chan_spec const *ch= an, + int *val, int *val2, long mask) +{ + unsigned long lsb =3D chan->address; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + *val =3D gpadc_get_raw(iio, chan->channel); + if (*val < 0) + return *val; + + dev_dbg(&iio->dev, "chan: %d, raw: %d\n", chan->channel, *val); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val =3D lsb; + *val2 =3D (MICRO / MILLI); + return chan->type =3D=3D IIO_VOLTAGE + ? IIO_VAL_FRACTIONAL + : IIO_VAL_INT; + case IIO_CHAN_INFO_OFFSET: + /* Raw value is 104 millikelvin/LSB, convert it to 104 millicelsius/LSB = */ + *val =3D ABSOLUTE_ZERO_MILLICELSIUS; + *val2 =3D lsb; + return IIO_VAL_FRACTIONAL; + case IIO_CHAN_INFO_PROCESSED: + *val =3D gpadc_get_resistance_ohm(iio, chan); + if (*val < 0) + return *val; + + dev_dbg(&iio->dev, "chan: %d, %d Ohm\n", chan->channel, *val); + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int pm886_gpadc_read_raw(struct iio_dev *iio, struct iio_chan_spec = const *chan, + int *val, int *val2, long mask) +{ + struct device *dev =3D iio->dev.parent; + int ret; + + ret =3D pm_runtime_resume_and_get(dev); + if (ret) + return ret; + + ret =3D __pm886_gpadc_read_raw(iio, chan, val, val2, mask); + + pm_runtime_put_autosuspend(dev); + return ret; +} + +static int pm886_gpadc_setup(struct regmap *map, bool enable) +{ + const u8 config[] =3D { + PM886_GPADC_CONFIG1_EN_ALL, + PM886_GPADC_CONFIG2_EN_ALL, + PM886_GPADC_GND_DET2_EN + }; + int ret; + + /* Enable/disable the ADC block */ + ret =3D regmap_assign_bits(map, PM886_REG_GPADC_CONFIG(0x6), BIT(0), enab= le); + if (ret) + return ret; + + if (!enable) + return 0; + + /* If enabling, enable all channels */ + return regmap_bulk_write(map, PM886_REG_GPADC_CONFIG(0x1), config, ARRAY_= SIZE(config)); +} + +static const struct iio_info pm886_gpadc_iio_info =3D { + .read_raw =3D pm886_gpadc_read_raw, +}; + +static int pm886_gpadc_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct pm886_chip *chip =3D dev_get_drvdata(dev->parent); + struct i2c_client *client =3D chip->client; + struct pm886_gpadc *gpadc; + struct i2c_client *page; + struct iio_dev *iio; + int ret; + + iio =3D devm_iio_device_alloc(dev, sizeof(*gpadc)); + if (!iio) + return -ENOMEM; + + gpadc =3D iio_priv(iio); + dev_set_drvdata(dev, iio); + + page =3D devm_i2c_new_dummy_device(dev, client->adapter, + client->addr + PM886_PAGE_OFFSET_GPADC); + if (IS_ERR(page)) + return dev_err_probe(dev, PTR_ERR(page), "Failed to initialize GPADC pag= e\n"); + + gpadc->map =3D devm_regmap_init_i2c(page, &pm886_gpadc_regmap_config); + if (IS_ERR(gpadc->map)) + return dev_err_probe(dev, PTR_ERR(gpadc->map), + "Failed to initialize GPADC regmap\n"); + + iio->name =3D "88pm886-gpadc"; + iio->dev.of_node =3D dev->parent->of_node; + iio->modes =3D INDIO_DIRECT_MODE; + iio->info =3D &pm886_gpadc_iio_info; + iio->channels =3D pm886_gpadc_channels; + iio->num_channels =3D ARRAY_SIZE(pm886_gpadc_channels); + + pm_runtime_set_autosuspend_delay(dev, 50); + pm_runtime_use_autosuspend(dev); + ret =3D devm_pm_runtime_enable(dev); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable runtime PM\n"); + + ret =3D devm_iio_device_register(dev, iio); + if (ret) + return dev_err_probe(dev, ret, "Failed to register ADC\n"); + + return 0; +} + +static int pm886_gpadc_runtime_resume(struct device *dev) +{ + struct iio_dev *iio =3D dev_get_drvdata(dev); + struct pm886_gpadc *gpadc =3D iio_priv(iio); + + return pm886_gpadc_setup(gpadc->map, true); +} + +static int pm886_gpadc_runtime_suspend(struct device *dev) +{ + struct iio_dev *iio =3D dev_get_drvdata(dev); + struct pm886_gpadc *gpadc =3D iio_priv(iio); + + return pm886_gpadc_setup(gpadc->map, false); +} + +static DEFINE_RUNTIME_DEV_PM_OPS(pm886_gpadc_pm_ops, + pm886_gpadc_runtime_suspend, + pm886_gpadc_runtime_resume, NULL); + +static const struct platform_device_id pm886_gpadc_id[] =3D { + { "88pm886-gpadc" }, + { } +}; +MODULE_DEVICE_TABLE(platform, pm886_gpadc_id); + +static struct platform_driver pm886_gpadc_driver =3D { + .driver =3D { + .name =3D "88pm886-gpadc", + .pm =3D pm_ptr(&pm886_gpadc_pm_ops), + }, + .probe =3D pm886_gpadc_probe, + .id_table =3D pm886_gpadc_id, +}; +module_platform_driver(pm886_gpadc_driver); + +MODULE_AUTHOR("Duje Mihanovi=C4=87 "); +MODULE_DESCRIPTION("Marvell 88PM886 GPADC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 24f2572c487ea3db2abec3283ebd93357c08baab..04c8478ff707dd16ec943674ac7= f01f33249acf1 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -9,6 +9,19 @@ menu "Analog to digital converters" config IIO_ADC_HELPER tristate =20 +config 88PM886_GPADC + tristate "Marvell 88PM886 GPADC driver" + depends on MFD_88PM886_PMIC + default MFD_88PM886_PMIC + help + Say Y here to enable support for the GPADC (General Purpose ADC) + found on the Marvell 88PM886 PMIC. The GPADC measures various + internal voltages and temperatures, including (but not limited to) + system, battery and USB Vbus. + + To compile this driver as a module, choose M here: the module will be + called 88pm886-gpadc. + config AB8500_GPADC bool "ST-Ericsson AB8500 GPADC driver" depends on AB8500_CORE && REGULATOR_AB8500 diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 1c6ca5fd4b6db8c4c40a351b231ba0892e8cd70e..64854907bf3bef7da39f95247e4= e502d01232af3 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_IIO_ADC_HELPER) +=3D industrialio-adc.o =20 # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_88PM886_GPADC) +=3D 88pm886-gpadc.o obj-$(CONFIG_AB8500_GPADC) +=3D ab8500-gpadc.o obj-$(CONFIG_AD_SIGMA_DELTA) +=3D ad_sigma_delta.o obj-$(CONFIG_AD4000) +=3D ad4000.o diff --git a/include/linux/mfd/88pm886.h b/include/linux/mfd/88pm886.h index 85eca44f39ab58ba4cb9ec4216118ee9604d021f..85c3c16fb10b7ee6aafdd6e68fd= 9135d8009eef8 100644 --- a/include/linux/mfd/88pm886.h +++ b/include/linux/mfd/88pm886.h @@ -10,6 +10,7 @@ #define PM886_IRQ_ONKEY 0 =20 #define PM886_PAGE_OFFSET_REGULATORS 1 +#define PM886_PAGE_OFFSET_GPADC 2 =20 #define PM886_REG_ID 0x00 =20 @@ -67,6 +68,59 @@ #define PM886_REG_BUCK4_VOUT 0xcf #define PM886_REG_BUCK5_VOUT 0xdd =20 +/* GPADC enable/disable registers */ +#define PM886_REG_GPADC_CONFIG(n) (n) + +/* GPADC channel registers */ +#define PM886_REG_GPADC_VSC 0x40 +#define PM886_REG_GPADC_VCHG_PWR 0x4c +#define PM886_REG_GPADC_VCF_OUT 0x4e +#define PM886_REG_GPADC_TINT 0x50 +#define PM886_REG_GPADC_GPADC0 0x54 +#define PM886_REG_GPADC_GPADC1 0x56 +#define PM886_REG_GPADC_GPADC2 0x58 +#define PM886_REG_GPADC_VBAT 0xa0 +#define PM886_REG_GPADC_GND_DET1 0xa4 +#define PM886_REG_GPADC_GND_DET2 0xa6 +#define PM886_REG_GPADC_VBUS 0xa8 +#define PM886_REG_GPADC_GPADC3 0xaa +#define PM886_REG_GPADC_MIC_DET 0xac +#define PM886_REG_GPADC_VBAT_SLP 0xb0 + +/* GPADC channel enable bits */ +#define PM886_GPADC_VSC_EN BIT(0) +#define PM886_GPADC_VBAT_EN BIT(1) +#define PM886_GPADC_GNDDET1_EN BIT(3) +#define PM886_GPADC_VBUS_EN BIT(4) +#define PM886_GPADC_VCHG_PWR_EN BIT(5) +#define PM886_GPADC_VCF_OUT_EN BIT(6) +#define PM886_GPADC_CONFIG1_EN_ALL (PM886_GPADC_VSC_EN | \ + PM886_GPADC_VBAT_EN | \ + PM886_GPADC_GNDDET1_EN | \ + PM886_GPADC_VBUS_EN | \ + PM886_GPADC_VCHG_PWR_EN | \ + PM886_GPADC_VCF_OUT_EN) + +#define PM886_GPADC_TINT_EN BIT(0) +#define PM886_GPADC_PMODE_EN BIT(1) +#define PM886_GPADC_GPADC0_EN BIT(2) +#define PM886_GPADC_GPADC1_EN BIT(3) +#define PM886_GPADC_GPADC2_EN BIT(4) +#define PM886_GPADC_GPADC3_EN BIT(5) +#define PM886_GPADC_MIC_DET_EN BIT(6) +#define PM886_GPADC_CONFIG2_EN_ALL (PM886_GPADC_TINT_EN | \ + PM886_GPADC_GPADC0_EN | \ + PM886_GPADC_GPADC1_EN | \ + PM886_GPADC_GPADC2_EN | \ + PM886_GPADC_GPADC3_EN | \ + PM886_GPADC_MIC_DET_EN) + +/* No CONFIG3_EN_ALL because this is the only bit there */ +#define PM886_GPADC_GND_DET2_EN BIT(0) + +#define PM886_GPADC_BIAS_LEVELS 16 +#define PM886_GPADC_INDEX_TO_BIAS_UA(i) (1 + (i) * 5) + #define PM886_LDO_VSEL_MASK 0x0f #define PM886_BUCK_VSEL_MASK 0x7f =20 --=20 2.51.0 From nobody Fri Oct 3 13:27:17 2025 Received: from mx.olsak.net (mx.olsak.net [37.205.8.231]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 49BFC245010; Sun, 31 Aug 2025 10:33:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=37.205.8.231 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756636422; cv=none; b=i1Hqgc2tqK3opvwxz4WgK0X3GukzGY5FEHGVamLnaHbKQzNHhphPVYfYDJSrLexgc6/Rq8oqXEf5XpJfSVDYF4lxMunJtA51ZwecuM0Jp4HQEZINb8mssl/Lg3RJ18xMjpOYptm4XwzT7l4AtEA1LeUCWupnKtlWRIBX2ky7kxI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756636422; c=relaxed/simple; bh=9JhG6l9aYXd0tr5rpMP/JH7+4zmVZlrSGb616SvhYjU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Buc7kcXJwvIyC/2RBIlAFlTvfBOOilPn8oSyQ1qlobHtBfQTHUujXtq2HvK06TYDbBgqRMJT9kOY46w2yExz5TZ4wlLFXLjT9N+gScJagCKxUvKrmYtGia3j9nBFNtxQ/Z4O9xbwwoCrz0wap0GXZ6KCnBOETxz0XIDxWHdbHh0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=dujemihanovic.xyz; spf=pass smtp.mailfrom=dujemihanovic.xyz; dkim=pass (2048-bit key) header.d=dujemihanovic.xyz header.i=@dujemihanovic.xyz header.b=E0KbgRZW; arc=none smtp.client-ip=37.205.8.231 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=dujemihanovic.xyz Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=dujemihanovic.xyz Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=dujemihanovic.xyz header.i=@dujemihanovic.xyz header.b="E0KbgRZW" DKIM-Signature: a=rsa-sha256; bh=rlGvPgM9RCjyuzqwy9Jz8R1zuOjSOwFc2U7uSTIgvLY=; c=relaxed/relaxed; d=dujemihanovic.xyz; h=Subject:Subject:Sender:To:To:Cc:Cc:From:From:Date:Date:MIME-Version:MIME-Version:Content-Type:Content-Type:Content-Transfer-Encoding:Content-Transfer-Encoding:Reply-To:In-Reply-To:In-Reply-To:Message-Id:Message-Id:References:References:Autocrypt:Openpgp; i=@dujemihanovic.xyz; s=default; t=1756636411; v=1; x=1757068411; b=E0KbgRZW95vL1xuiXutYVE1TgT8oKdytvqGxh5eWODOhdzxV/KGK9njPALJJIyXqsHgW+80D LuR/IE3zfeYjOOcrgP3S+VX+JunHRiO9EPWEDJ4b+F1uPqW045qm3MnWqHT8C2/US6yKhE4rE5X 9dBztiT32gyHChpQLpdpQ7b+1aYnDSr/3hSyL2scslNPKDCGIt0TOB0RpDpyKOzKhJZHUXvcqH1 r3I+Ob3Yd6HhEUB+Nm8IZSe02/HVaLFXQVEjXS5GoVK4gltsv8vCv7jGD8gWfW/lYmnRWe21r7w Iww+w7BVcFpnriQXmDURH1zBqSGEPqmqt6ng07AlwW1FA== Received: by mx.olsak.net (envelope-sender ) with ESMTPS id 02b68ab0; Sun, 31 Aug 2025 12:33:31 +0200 From: =?utf-8?q?Duje_Mihanovi=C4=87?= Date: Sun, 31 Aug 2025 12:33:06 +0200 Subject: [PATCH v2 3/3] mfd: 88pm886: Add GPADC cell 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: <20250831-88pm886-gpadc-v2-3-759c1e14d95f@dujemihanovic.xyz> References: <20250831-88pm886-gpadc-v2-0-759c1e14d95f@dujemihanovic.xyz> In-Reply-To: <20250831-88pm886-gpadc-v2-0-759c1e14d95f@dujemihanovic.xyz> To: Jonathan Cameron , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko , Karel Balej , Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: David Wronek , phone-devel@vger.kernel.org, ~postmarketos/upstreaming@lists.sr.ht, linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, devicetree@vger.kernel.org, =?utf-8?q?Duje_Mihanovi=C4=87?= X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=797; i=duje@dujemihanovic.xyz; s=20240706; h=from:subject:message-id; bh=9JhG6l9aYXd0tr5rpMP/JH7+4zmVZlrSGb616SvhYjU=; b=owGbwMvMwCW21nBykGv/WmbG02pJDBlbVL5rXCz59eGsemH9ix7/Sk4zgykFW19dnXnl8E6lu 4H7qvcqd5SyMIhxMciKKbLk/ne8xvtZZOv27GUGMHNYmUCGMHBxCsBE/hkx/A8PvZ2nUKkqvFxO 6p+aRfPWeLXbJxp0Jj/5/PzTrHLWRf8ZGV78+MPYEb44e8sDviNvHc1vxb5/udm7/fNzxzl+9qV TOTgB X-Developer-Key: i=duje@dujemihanovic.xyz; a=openpgp; fpr=6DFF41D60DF314B5B76BA630AD319352458FAD03 Add a cell for the PMIC's onboard General Purpose ADC. Acked-by: Karel Balej # for the PMIC Signed-off-by: Duje Mihanovi=C4=87 --- v2: - Sort cell names --- drivers/mfd/88pm886.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/88pm886.c b/drivers/mfd/88pm886.c index 39dd9a818b0f0e1e5839f76768ff54940f4cefa5..e411d8dee55420e10b6d7ad7069= 576c681360de1 100644 --- a/drivers/mfd/88pm886.c +++ b/drivers/mfd/88pm886.c @@ -35,6 +35,7 @@ static const struct resource pm886_onkey_resources[] =3D { }; =20 static const struct mfd_cell pm886_devs[] =3D { + MFD_CELL_NAME("88pm886-gpadc"), MFD_CELL_RES("88pm886-onkey", pm886_onkey_resources), MFD_CELL_NAME("88pm886-regulator"), MFD_CELL_NAME("88pm886-rtc"), --=20 2.51.0