From nobody Tue Dec 2 01:08:19 2025 Received: from mail.subdimension.ro (nalicastle.subdimension.ro [172.105.74.154]) (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 131D725F7B9; Sat, 22 Nov 2025 21:51:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=172.105.74.154 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763848306; cv=none; b=OxrlErMDfzk7Hkv6pOArqK2qti8WflOBBNAFCDB2SuEDmZonzWjENtdN6f8USP3Apxwcwbx2qdR3D+h4Ozn+St9+5P8fP30OAM49phPG59DVmwumTAkioqE8h19yPPwKDT5JXRspYdLRfDDwoaPD8BVhVYSGwBmsixtcvSGA9+Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763848306; c=relaxed/simple; bh=5xU2IWwzhWM7yzf85onc43QINVu/jsxmrKUWxnQw1zI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hn0Kr5nxTt4VCKXqbAyNW4J8fcbnKYbLPMELxR7/8IXJP+rPNtR9ZcUXo1PziW66wc/Yu0GC9jTuS0nd0gqSVgXjc1JB0l+lb3wYC1h0Eg3ZkZzE/BHsSHVaNy7+fuiY6Iwv9AgOMoQqOcurqlrqfpDV6MnNrVpVihwYdEq8Ymc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=subdimension.ro; spf=pass smtp.mailfrom=subdimension.ro; dkim=pass (2048-bit key) header.d=subdimension.ro header.i=@subdimension.ro header.b=sDw16Vg2; arc=none smtp.client-ip=172.105.74.154 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=subdimension.ro Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=subdimension.ro Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=subdimension.ro header.i=@subdimension.ro header.b="sDw16Vg2" Received: from sunspire.home.arpa (unknown [IPv6:2a02:2f0e:3e0c:5b00:e2d5:5eff:fed9:f1c4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mail.subdimension.ro (Postfix) with ESMTPSA id 3E3F616020B; Sat, 22 Nov 2025 23:42:57 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=subdimension.ro; s=mail; t=1763847777; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=09fzl5J2t4FmdmuxvWvyKho0RI5ATjDe6PiJTOM89Q4=; b=sDw16Vg2p3ihHBlD0hehnjR0M0FgbpZUZMO/bnkct7B/KnB7S7yfqaiO66bD+sPfeeuBuE 7lhP4gHaBQbjDhklEefK/KSk/XDI438N07mM8iD/ngxkv40Bgkt/Z/KjjkbX/wEVS4USgV UkxbYEurLMILL6dNit1CngbSjkaqqeXxOJQxma42KJAr6wvOgnDrYmmfwsMSXoxonJXDgA zxDB+z2cx2+aGJnZD/FSrnDYIbFzcK2zvSDRs+iniyg5/zjasabxdVLWHZeOFROEZQqYSU yDf2/AKqjY3VERg9CNh61YVO4l/fFL80gKNF/ItfOIPX1UNV0irporEiRAEC8g== From: Petre Rodan Date: Sat, 22 Nov 2025 23:42:45 +0200 Subject: [PATCH 2/2] iio: pressure: add Honeywell ABP2 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: <20251122-honeywell_abp2_driver-v1-2-7a8e265f9627@subdimension.ro> References: <20251122-honeywell_abp2_driver-v1-0-7a8e265f9627@subdimension.ro> In-Reply-To: <20251122-honeywell_abp2_driver-v1-0-7a8e265f9627@subdimension.ro> To: Jonathan Cameron , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Petre Rodan X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=31597; i=petre.rodan@subdimension.ro; h=from:subject:message-id; bh=5xU2IWwzhWM7yzf85onc43QINVu/jsxmrKUWxnQw1zI=; b=LS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tCgpvd0o0bkFGdEFwTDlrQTBEQUFvQmRDc25wM k02U1dNQnl5WmlBR2tpTGw3alBIMWNMNmdJK1lpbVp5QzA0c0QyCkcrODJ6T29nUS9RRE1wUkky alZxYjRrQ013UUFBUW9BSFJZaEJCb2ltQncrRGJ4UXBFNmlkM1FySjZkak9rbGoKQlFKcElpNWV BQW9KRUhRcko2ZGpPa2xqZDVRUC9pejlydjk1Z2IzbzNWNXZWT1ZHUGpyMzJlaDRzdHJLcHhhaQ pNd3lPUEprS3lxcEtRMktnejFEdXhiZVBmOVp3bFhQSkU3cmpSRDh1TjlJMEhhUjhEZXNQTzAyV DdFZWNkTGkvCnc0M1EvN3VheThadEVaR1U3VEUwWmJ6dGNLNHdiVVRlWHkzNzNnWERjdVBKdDND TVptOUM1Y3hoaVEvOGM5aXkKN0NIVjBSMFhwSjBuMnlZTXJwNGhBb2Vrc1VrbXpIMThXSmJPZXR 4QzMzLzZVcCtLTVZreVl4NlEzazBuYWVYeQo3NXlBZjZVSHRzcFFrNldKS0RqZHArdnpFdzBsdU R5dU5lK1UzTTIvTnBub1h1QjNVY1VaRlZXcStVTXdZZ3NnCkovRlU1aEVEZThCQ085YU1GV1dzd UExVzlNL2l5U0p6NWxrckdudmpXbzhXOEgyYklJRnBKR3lIMmN1Wm9RajQKTEVzYTJXUlcyZmU3 U0trODREMnZZNHdhM0lmOUJaSTgvLzA4cHluazBBbUdkYllGSm1NVXl5MGd2RTFsSHJlVApMbm4 ycjFCUnI0R3o5NGVkSXd5Tll3UHJqeERFTjh2ZGVPd2M3WjBPWTZ5UUNtR2M4cFBqWTdxWEFqZn M2VGNFCktEbUxGOG9xS2VhU2RiSnBLZGlGOVRBWFYvcW5JOWZid1k3VEl3ckRvQkN2Zi9zSDdOV Ul3STk0Q2xSbjA1N0YKN2U3YURiVU9oRHcxVFpVbDRibzl2b09xbnVWYlF2NXgrWkxrSU5kZ3Y1 YnE5V3dxQ24yamxudFJEdGk2OFAycwpTbkoxNEVzZkVqUDJmaGVySkxrZjRiQ3l4a0VpVkNLTHV 6NTVtWkFiQVBTT1VFbnBPL3JFTWhteE1IUUxMcm5hCjd2MXZUZW5VM0dJcXBRPT0KPXFIeHQKLS 0tLS1FTkQgUEdQIE1FU1NBR0UtLS0tLQo= X-Developer-Key: i=petre.rodan@subdimension.ro; a=openpgp; fpr=D80A7FC176151935EC3E5FA9CF269999844E7F30 Adds driver for digital Honeywell ABP2 series of board mount pressure and temperature sensors. This driver covers 113 different pressure ranges and units on both i2c and SPI buses. The i2c address is hardcoded and depends on the part number. Optional end of conversion interrupt control is present on the i2c variants of the chips. The EOC gpio can also be defined for the SPI variants if a non-ABP2 but compatible chip is to be driven. Tested on two different sensors. datasheet: https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/p= roducts/sensors/pressure-sensors/board-mount-pressure-sensors/basic-abp2-se= ries/documents/sps-siot-abp2-series-datasheet-32350268-en.pdf Signed-off-by: Petre Rodan --- MAINTAINERS | 1 + drivers/iio/pressure/Kconfig | 24 ++ drivers/iio/pressure/Makefile | 3 + drivers/iio/pressure/abp2030pa.c | 543 +++++++++++++++++++++++++++++++= ++++ drivers/iio/pressure/abp2030pa.h | 79 +++++ drivers/iio/pressure/abp2030pa_i2c.c | 93 ++++++ drivers/iio/pressure/abp2030pa_spi.c | 88 ++++++ 7 files changed, 831 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 15b92300acbc..0aa9cba68137 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11409,6 +11409,7 @@ M: Petre Rodan L: linux-iio@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/iio/pressure/honeywell,abp2030pa.yaml +F: drivers/iio/pressure/abp2030pa* =20 HONEYWELL HSC030PA PRESSURE SENSOR SERIES IIO DRIVER M: Petre Rodan diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index 2fe9dc90cceb..0c2be090e27d 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -16,6 +16,30 @@ config ABP060MG To compile this driver as a module, choose M here: the module will be called abp060mg. =20 +config ABP2030PA + tristate "Honeywell ABP2 pressure sensor series" + depends on (I2C || SPI_MASTER) + select ABP2030PA_I2C if I2C + select ABP2030PA_SPI if SPI_MASTER + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say Y here to build support for the Honeywell ABP2 board mount + pressure and temperature sensor series. + + To compile this driver as a module, choose M here: the module + will be called abp2030pa. + +config ABP2030PA_I2C + tristate + depends on ABP2030PA + depends on I2C + +config ABP2030PA_SPI + tristate + depends on ABP2030PA + depends on SPI_MASTER + config ROHM_BM1390 tristate "ROHM BM1390GLV-Z pressure sensor driver" depends on I2C diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index a21443e992b9..bc0d11a20acc 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile @@ -5,6 +5,9 @@ =20 # When adding new entries keep the list in alphabetical order obj-$(CONFIG_ABP060MG) +=3D abp060mg.o +obj-$(CONFIG_ABP2030PA) +=3D abp2030pa.o +obj-$(CONFIG_ABP2030PA_I2C) +=3D abp2030pa_i2c.o +obj-$(CONFIG_ABP2030PA_SPI) +=3D abp2030pa_spi.o obj-$(CONFIG_ADP810) +=3D adp810.o obj-$(CONFIG_ROHM_BM1390) +=3D rohm-bm1390.o obj-$(CONFIG_BMP280) +=3D bmp280.o diff --git a/drivers/iio/pressure/abp2030pa.c b/drivers/iio/pressure/abp203= 0pa.c new file mode 100644 index 000000000000..32aa11e4cefd --- /dev/null +++ b/drivers/iio/pressure/abp2030pa.c @@ -0,0 +1,543 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Honeywell ABP2 series pressure sensor driver + * + * Copyright (c) 2025 Petre Rodan + * + * Datasheet: https://prod-edam.honeywell.com/content/dam/honeywell-edam/s= ps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensor= s/basic-abp2-series/documents/sps-siot-abp2-series-datasheet-32350268-en.pdf + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "abp2030pa.h" + +/* status byte flags */ +#define ABP2_ST_POWER BIT(6) /* 1 if device is powered */ +#define ABP2_ST_BUSY BIT(5) /* 1 if device is busy */ + +struct abp2_func_spec { + u32 output_min; + u32 output_max; +}; + +/* + * transfer function A: 10% to 90% of 2^24 + */ +static const struct abp2_func_spec abp2_func_spec[] =3D { + [ABP2_FUNCTION_A] =3D { .output_min =3D 1677722, .output_max =3D 15099494= }, +}; + +enum abp2_variants { + ABP2001BA =3D 0x0, ABP21_6BA =3D 0x1, ABP22_5BA =3D 0x2, ABP2004BA =3D 0x= 3, + ABP2006BA =3D 0x4, ABP2008BA =3D 0x5, ABP2010BA =3D 0x6, ABP2012BA =3D 0x= 7, + ABP2001BD =3D 0x8, ABP21_6BD =3D 0x9, ABP22_5BD =3D 0xa, ABP2004BD =3D 0x= b, + ABP2001BG =3D 0xc, ABP21_6BG =3D 0xd, ABP22_5BG =3D 0xe, ABP2004BG =3D 0x= f, + ABP2006BG =3D 0x10, ABP2008BG =3D 0x11, ABP2010BG =3D 0x12, ABP2012BG =3D= 0x13, + ABP2001GG =3D 0x14, ABP21_2GG =3D 0x15, ABP2100KA =3D 0x16, ABP2160KA =3D= 0x17, + ABP2250KA =3D 0x18, ABP2001KD =3D 0x19, ABP21_6KD =3D 0x1a, ABP22_5KD =3D= 0x1b, + ABP2004KD =3D 0x1c, ABP2006KD =3D 0x1d, ABP2010KD =3D 0x1e, ABP2016KD =3D= 0x1f, + ABP2025KD =3D 0x20, ABP2040KD =3D 0x21, ABP2060KD =3D 0x22, ABP2100KD =3D= 0x23, + ABP2160KD =3D 0x24, ABP2250KD =3D 0x25, ABP2400KD =3D 0x26, ABP2001KG =3D= 0x27, + ABP21_6KG =3D 0x28, ABP22_5KG =3D 0x29, ABP2004KG =3D 0x2a, ABP2006KG =3D= 0x2b, + ABP2010KG =3D 0x2c, ABP2016KG =3D 0x2d, ABP2025KG =3D 0x2e, ABP2040KG =3D= 0x2f, + ABP2060KG =3D 0x30, ABP2100KG =3D 0x31, ABP2160KG =3D 0x32, ABP2250KG =3D= 0x33, + ABP2400KG =3D 0x34, ABP2600KG =3D 0x35, ABP2800KG =3D 0x36, ABP2250LD =3D= 0x37, + ABP2600LD =3D 0x38, ABP2600LG =3D 0x39, ABP22_5MD =3D 0x3a, ABP2006MD =3D= 0x3b, + ABP2010MD =3D 0x3c, ABP2016MD =3D 0x3d, ABP2025MD =3D 0x3e, ABP2040MD =3D= 0x3f, + ABP2060MD =3D 0x40, ABP2100MD =3D 0x41, ABP2160MD =3D 0x42, ABP2250MD =3D= 0x43, + ABP2400MD =3D 0x44, ABP2600MD =3D 0x45, ABP2006MG =3D 0x46, ABP2010MG =3D= 0x47, + ABP2016MG =3D 0x48, ABP2025MG =3D 0x49, ABP2040MG =3D 0x4a, ABP2060MG =3D= 0x4b, + ABP2100MG =3D 0x4c, ABP2160MG =3D 0x4d, ABP2250MG =3D 0x4e, ABP2400MG =3D= 0x4f, + ABP2600MG =3D 0x50, ABP2001ND =3D 0x51, ABP2002ND =3D 0x52, ABP2004ND =3D= 0x53, + ABP2005ND =3D 0x54, ABP2010ND =3D 0x55, ABP2020ND =3D 0x56, ABP2030ND =3D= 0x57, + ABP2002NG =3D 0x58, ABP2004NG =3D 0x59, ABP2005NG =3D 0x5a, ABP2010NG =3D= 0x5b, + ABP2020NG =3D 0x5c, ABP2030NG =3D 0x5d, ABP2015PA =3D 0x5e, ABP2030PA =3D= 0x5f, + ABP2060PA =3D 0x60, ABP2100PA =3D 0x61, ABP2150PA =3D 0x62, ABP2175PA =3D= 0x63, + ABP2001PD =3D 0x64, ABP2005PD =3D 0x65, ABP2015PD =3D 0x66, ABP2030PD =3D= 0x67, + ABP2060PD =3D 0x68, ABP2001PG =3D 0x69, ABP2005PG =3D 0x6a, ABP2015PG =3D= 0x6b, + ABP2030PG =3D 0x6c, ABP2060PG =3D 0x6d, ABP2100PG =3D 0x6e, ABP2150PG =3D= 0x6f, + ABP2175PG =3D 0x70, ABP2_VARIANTS_MAX +}; + +static const char * const abp2_triplet_variants[ABP2_VARIANTS_MAX] =3D { + [ABP2001BA] =3D "001BA", [ABP21_6BA] =3D "1.6BA", [ABP22_5BA] =3D "2.5BA", + [ABP2004BA] =3D "004BA", [ABP2006BA] =3D "006BA", [ABP2008BA] =3D "008BA", + [ABP2010BA] =3D "010BA", [ABP2012BA] =3D "012BA", [ABP2001BD] =3D "001BD", + [ABP21_6BD] =3D "1.6BD", [ABP22_5BD] =3D "2.5BD", [ABP2004BD] =3D "004BD", + [ABP2001BG] =3D "001BG", [ABP21_6BG] =3D "1.6BG", [ABP22_5BG] =3D "2.5BG", + [ABP2004BG] =3D "004BG", [ABP2006BG] =3D "006BG", [ABP2008BG] =3D "008BG", + [ABP2010BG] =3D "010BG", [ABP2012BG] =3D "012BG", [ABP2001GG] =3D "001GG", + [ABP21_2GG] =3D "1.2GG", [ABP2100KA] =3D "100KA", [ABP2160KA] =3D "160KA", + [ABP2250KA] =3D "250KA", [ABP2001KD] =3D "001KD", [ABP21_6KD] =3D "1.6KD", + [ABP22_5KD] =3D "2.5KD", [ABP2004KD] =3D "004KD", [ABP2006KD] =3D "006KD", + [ABP2010KD] =3D "010KD", [ABP2016KD] =3D "016KD", [ABP2025KD] =3D "025KD", + [ABP2040KD] =3D "040KD", [ABP2060KD] =3D "060KD", [ABP2100KD] =3D "100KD", + [ABP2160KD] =3D "160KD", [ABP2250KD] =3D "250KD", [ABP2400KD] =3D "400KD", + [ABP2001KG] =3D "001KG", [ABP21_6KG] =3D "1.6KG", [ABP22_5KG] =3D "2.5KG", + [ABP2004KG] =3D "004KG", [ABP2006KG] =3D "006KG", [ABP2010KG] =3D "010KG", + [ABP2016KG] =3D "016KG", [ABP2025KG] =3D "025KG", [ABP2040KG] =3D "040KG", + [ABP2060KG] =3D "060KG", [ABP2100KG] =3D "100KG", [ABP2160KG] =3D "160KG", + [ABP2250KG] =3D "250KG", [ABP2400KG] =3D "400KG", [ABP2600KG] =3D "600KG", + [ABP2800KG] =3D "800KG", [ABP2250LD] =3D "250LD", [ABP2600LD] =3D "600LD", + [ABP2600LG] =3D "600LG", [ABP22_5MD] =3D "2.5MD", [ABP2006MD] =3D "006MD", + [ABP2010MD] =3D "010MD", [ABP2016MD] =3D "016MD", [ABP2025MD] =3D "025MD", + [ABP2040MD] =3D "040MD", [ABP2060MD] =3D "060MD", [ABP2100MD] =3D "100MD", + [ABP2160MD] =3D "160MD", [ABP2250MD] =3D "250MD", [ABP2400MD] =3D "400MD", + [ABP2600MD] =3D "600MD", [ABP2006MG] =3D "006MG", [ABP2010MG] =3D "010MG", + [ABP2016MG] =3D "016MG", [ABP2025MG] =3D "025MG", [ABP2040MG] =3D "040MG", + [ABP2060MG] =3D "060MG", [ABP2100MG] =3D "100MG", [ABP2160MG] =3D "160MG", + [ABP2250MG] =3D "250MG", [ABP2400MG] =3D "400MG", [ABP2600MG] =3D "600MG", + [ABP2001ND] =3D "001ND", [ABP2002ND] =3D "002ND", [ABP2004ND] =3D "004ND", + [ABP2005ND] =3D "005ND", [ABP2010ND] =3D "010ND", [ABP2020ND] =3D "020ND", + [ABP2030ND] =3D "030ND", [ABP2002NG] =3D "002NG", [ABP2004NG] =3D "004NG", + [ABP2005NG] =3D "005NG", [ABP2010NG] =3D "010NG", [ABP2020NG] =3D "020NG", + [ABP2030NG] =3D "030NG", [ABP2015PA] =3D "015PA", [ABP2030PA] =3D "030PA", + [ABP2060PA] =3D "060PA", [ABP2100PA] =3D "100PA", [ABP2150PA] =3D "150PA", + [ABP2175PA] =3D "175PA", [ABP2001PD] =3D "001PD", [ABP2005PD] =3D "005PD", + [ABP2015PD] =3D "015PD", [ABP2030PD] =3D "030PD", [ABP2060PD] =3D "060PD", + [ABP2001PG] =3D "001PG", [ABP2005PG] =3D "005PG", [ABP2015PG] =3D "015PG", + [ABP2030PG] =3D "030PG", [ABP2060PG] =3D "060PG", [ABP2100PG] =3D "100PG", + [ABP2150PG] =3D "150PG", [ABP2175PG] =3D "175PG" +}; + +/** + * struct abp2_range_config - list of pressure ranges based on nomenclature + * @pmin: lowest pressure that can be measured + * @pmax: highest pressure that can be measured + */ +struct abp2_range_config { + const s32 pmin; + const s32 pmax; +}; + +/* All min max limits have been converted to pascals */ +static const struct abp2_range_config abp2_range_config[ABP2_VARIANTS_MAX]= =3D { + [ABP2001BA] =3D { .pmin =3D 0, .pmax =3D 100000 }, + [ABP21_6BA] =3D { .pmin =3D 0, .pmax =3D 160000 }, + [ABP22_5BA] =3D { .pmin =3D 0, .pmax =3D 250000 }, + [ABP2004BA] =3D { .pmin =3D 0, .pmax =3D 400000 }, + [ABP2006BA] =3D { .pmin =3D 0, .pmax =3D 600000 }, + [ABP2008BA] =3D { .pmin =3D 0, .pmax =3D 800000 }, + [ABP2010BA] =3D { .pmin =3D 0, .pmax =3D 1000000 }, + [ABP2012BA] =3D { .pmin =3D 0, .pmax =3D 1200000 }, + [ABP2001BD] =3D { .pmin =3D -100000, .pmax =3D 100000 }, + [ABP21_6BD] =3D { .pmin =3D -160000, .pmax =3D 160000 }, + [ABP22_5BD] =3D { .pmin =3D -250000, .pmax =3D 250000 }, + [ABP2004BD] =3D { .pmin =3D -400000, .pmax =3D 400000 }, + [ABP2001BG] =3D { .pmin =3D 0, .pmax =3D 100000 }, + [ABP21_6BG] =3D { .pmin =3D 0, .pmax =3D 160000 }, + [ABP22_5BG] =3D { .pmin =3D 0, .pmax =3D 250000 }, + [ABP2004BG] =3D { .pmin =3D 0, .pmax =3D 400000 }, + [ABP2006BG] =3D { .pmin =3D 0, .pmax =3D 600000 }, + [ABP2008BG] =3D { .pmin =3D 0, .pmax =3D 800000 }, + [ABP2010BG] =3D { .pmin =3D 0, .pmax =3D 1000000 }, + [ABP2012BG] =3D { .pmin =3D 0, .pmax =3D 1200000 }, + [ABP2001GG] =3D { .pmin =3D 0, .pmax =3D 1000000 }, + [ABP21_2GG] =3D { .pmin =3D 0, .pmax =3D 1200000 }, + [ABP2100KA] =3D { .pmin =3D 0, .pmax =3D 100000 }, + [ABP2160KA] =3D { .pmin =3D 0, .pmax =3D 160000 }, + [ABP2250KA] =3D { .pmin =3D 0, .pmax =3D 250000 }, + [ABP2001KD] =3D { .pmin =3D -1000, .pmax =3D 1000 }, + [ABP21_6KD] =3D { .pmin =3D -1600, .pmax =3D 1600 }, + [ABP22_5KD] =3D { .pmin =3D -2500, .pmax =3D 2500 }, + [ABP2004KD] =3D { .pmin =3D -4000, .pmax =3D 4000 }, + [ABP2006KD] =3D { .pmin =3D -6000, .pmax =3D 6000 }, + [ABP2010KD] =3D { .pmin =3D -10000, .pmax =3D 10000 }, + [ABP2016KD] =3D { .pmin =3D -16000, .pmax =3D 16000 }, + [ABP2025KD] =3D { .pmin =3D -25000, .pmax =3D 25000 }, + [ABP2040KD] =3D { .pmin =3D -40000, .pmax =3D 40000 }, + [ABP2060KD] =3D { .pmin =3D -60000, .pmax =3D 60000 }, + [ABP2100KD] =3D { .pmin =3D -100000, .pmax =3D 100000 }, + [ABP2160KD] =3D { .pmin =3D -160000, .pmax =3D 160000 }, + [ABP2250KD] =3D { .pmin =3D -250000, .pmax =3D 250000 }, + [ABP2400KD] =3D { .pmin =3D -400000, .pmax =3D 400000 }, + [ABP2001KG] =3D { .pmin =3D 0, .pmax =3D 1000 }, + [ABP21_6KG] =3D { .pmin =3D 0, .pmax =3D 1600 }, + [ABP22_5KG] =3D { .pmin =3D 0, .pmax =3D 2500 }, + [ABP2004KG] =3D { .pmin =3D 0, .pmax =3D 4000 }, + [ABP2006KG] =3D { .pmin =3D 0, .pmax =3D 6000 }, + [ABP2010KG] =3D { .pmin =3D 0, .pmax =3D 10000 }, + [ABP2016KG] =3D { .pmin =3D 0, .pmax =3D 16000 }, + [ABP2025KG] =3D { .pmin =3D 0, .pmax =3D 25000 }, + [ABP2040KG] =3D { .pmin =3D 0, .pmax =3D 40000 }, + [ABP2060KG] =3D { .pmin =3D 0, .pmax =3D 60000 }, + [ABP2100KG] =3D { .pmin =3D 0, .pmax =3D 100000 }, + [ABP2160KG] =3D { .pmin =3D 0, .pmax =3D 160000 }, + [ABP2250KG] =3D { .pmin =3D 0, .pmax =3D 250000 }, + [ABP2400KG] =3D { .pmin =3D 0, .pmax =3D 400000 }, + [ABP2600KG] =3D { .pmin =3D 0, .pmax =3D 600000 }, + [ABP2800KG] =3D { .pmin =3D 0, .pmax =3D 800000 }, + [ABP2250LD] =3D { .pmin =3D -250, .pmax =3D 250 }, + [ABP2600LD] =3D { .pmin =3D -600, .pmax =3D 600 }, + [ABP2600LG] =3D { .pmin =3D 0, .pmax =3D 600 }, + [ABP22_5MD] =3D { .pmin =3D -250, .pmax =3D 250 }, + [ABP2006MD] =3D { .pmin =3D -600, .pmax =3D 600 }, + [ABP2010MD] =3D { .pmin =3D -1000, .pmax =3D 1000 }, + [ABP2016MD] =3D { .pmin =3D -1600, .pmax =3D 1600 }, + [ABP2025MD] =3D { .pmin =3D -2500, .pmax =3D 2500 }, + [ABP2040MD] =3D { .pmin =3D -4000, .pmax =3D 4000 }, + [ABP2060MD] =3D { .pmin =3D -6000, .pmax =3D 6000 }, + [ABP2100MD] =3D { .pmin =3D -10000, .pmax =3D 10000 }, + [ABP2160MD] =3D { .pmin =3D -16000, .pmax =3D 16000 }, + [ABP2250MD] =3D { .pmin =3D -25000, .pmax =3D 25000 }, + [ABP2400MD] =3D { .pmin =3D -40000, .pmax =3D 40000 }, + [ABP2600MD] =3D { .pmin =3D -60000, .pmax =3D 60000 }, + [ABP2006MG] =3D { .pmin =3D 0, .pmax =3D 600 }, + [ABP2010MG] =3D { .pmin =3D 0, .pmax =3D 1000 }, + [ABP2016MG] =3D { .pmin =3D 0, .pmax =3D 1600 }, + [ABP2025MG] =3D { .pmin =3D 0, .pmax =3D 2500 }, + [ABP2040MG] =3D { .pmin =3D 0, .pmax =3D 4000 }, + [ABP2060MG] =3D { .pmin =3D 0, .pmax =3D 6000 }, + [ABP2100MG] =3D { .pmin =3D 0, .pmax =3D 10000 }, + [ABP2160MG] =3D { .pmin =3D 0, .pmax =3D 16000 }, + [ABP2250MG] =3D { .pmin =3D 0, .pmax =3D 25000 }, + [ABP2400MG] =3D { .pmin =3D 0, .pmax =3D 40000 }, + [ABP2600MG] =3D { .pmin =3D 0, .pmax =3D 60000 }, + [ABP2001ND] =3D { .pmin =3D -249, .pmax =3D 249 }, + [ABP2002ND] =3D { .pmin =3D -498, .pmax =3D 498 }, + [ABP2004ND] =3D { .pmin =3D -996, .pmax =3D 996 }, + [ABP2005ND] =3D { .pmin =3D -1245, .pmax =3D 1245 }, + [ABP2010ND] =3D { .pmin =3D -2491, .pmax =3D 2491 }, + [ABP2020ND] =3D { .pmin =3D -4982, .pmax =3D 4982 }, + [ABP2030ND] =3D { .pmin =3D -7473, .pmax =3D 7473 }, + [ABP2002NG] =3D { .pmin =3D 0, .pmax =3D 498 }, + [ABP2004NG] =3D { .pmin =3D 0, .pmax =3D 996 }, + [ABP2005NG] =3D { .pmin =3D 0, .pmax =3D 1245 }, + [ABP2010NG] =3D { .pmin =3D 0, .pmax =3D 2491 }, + [ABP2020NG] =3D { .pmin =3D 0, .pmax =3D 4982 }, + [ABP2030NG] =3D { .pmin =3D 0, .pmax =3D 7473 }, + [ABP2015PA] =3D { .pmin =3D 0, .pmax =3D 103421 }, + [ABP2030PA] =3D { .pmin =3D 0, .pmax =3D 206843 }, + [ABP2060PA] =3D { .pmin =3D 0, .pmax =3D 413685 }, + [ABP2100PA] =3D { .pmin =3D 0, .pmax =3D 689476 }, + [ABP2150PA] =3D { .pmin =3D 0, .pmax =3D 1034214 }, + [ABP2175PA] =3D { .pmin =3D 0, .pmax =3D 1206583 }, + [ABP2001PD] =3D { .pmin =3D -6895, .pmax =3D 6895 }, + [ABP2005PD] =3D { .pmin =3D -34474, .pmax =3D 34474 }, + [ABP2015PD] =3D { .pmin =3D -103421, .pmax =3D 103421 }, + [ABP2030PD] =3D { .pmin =3D -206843, .pmax =3D 206843 }, + [ABP2060PD] =3D { .pmin =3D -413685, .pmax =3D 413685 }, + [ABP2001PG] =3D { .pmin =3D 0, .pmax =3D 6895 }, + [ABP2005PG] =3D { .pmin =3D 0, .pmax =3D 34474 }, + [ABP2015PG] =3D { .pmin =3D 0, .pmax =3D 103421 }, + [ABP2030PG] =3D { .pmin =3D 0, .pmax =3D 206843 }, + [ABP2060PG] =3D { .pmin =3D 0, .pmax =3D 413685 }, + [ABP2100PG] =3D { .pmin =3D 0, .pmax =3D 689476 }, + [ABP2150PG] =3D { .pmin =3D 0, .pmax =3D 1034214 }, + [ABP2175PG] =3D { .pmin =3D 0, .pmax =3D 1206583 } +}; + +static int abp2_get_measurement(struct abp2_data *data) +{ + struct device *dev =3D data->dev; + int ret; + + memset(data->buffer, 0, sizeof(data->buffer)); + reinit_completion(&data->completion); + + ret =3D data->ops->write(data, ABP2_CMD_SYNC, ABP2_PKT_SYNC_LEN); + if (ret < 0) + return ret; + + if (data->irq > 0) { + ret =3D wait_for_completion_timeout(&data->completion, HZ); + if (!ret) { + dev_err(dev, "timeout waiting for EOC interrupt\n"); + return -ETIMEDOUT; + } + } else + fsleep(5000); + + ret =3D data->ops->read(data, ABP2_CMD_NOP, ABP2_PKT_NOP_LEN); + if (ret < 0) + return ret; + + /* + * status byte flags + * bit7 SANITY_CHK - must always be 0 + * bit6 ABP2_ST_POWER - 1 if device is powered + * bit5 ABP2_ST_BUSY - 1 if device has no new conversion ready + * bit4 SANITY_CHK - must always be 0 + * bit3 SANITY_CHK - must always be 0 + * bit2 MEMORY_ERR - 1 if integrity test has failed + * bit1 SANITY_CHK - must always be 0 + * bit0 MATH_ERR - 1 during internal math saturation err + */ + + if (data->buffer[0] =3D=3D (ABP2_ST_POWER | ABP2_ST_BUSY)) + return -ETIMEDOUT; + + if (data->buffer[0] !=3D ABP2_ST_POWER) { + dev_err(data->dev, + "unexpected status byte 0x%02x\n", data->buffer[0]); + return -ETIMEDOUT; + } + + return 0; +} + +static irqreturn_t abp2_eoc_handler(int irq, void *private) +{ + struct abp2_data *data =3D private; + + complete(&data->completion); + + return IRQ_HANDLED; +} + +static irqreturn_t abp2_trigger_handler(int irq, void *private) +{ + int ret; + struct iio_poll_func *pf =3D private; + struct iio_dev *indio_dev =3D pf->indio_dev; + struct abp2_data *data =3D iio_priv(indio_dev); + + ret =3D abp2_get_measurement(data); + if (ret < 0) + goto err; + + data->scan.chan[0] =3D get_unaligned_be24(&data->buffer[1]); + data->scan.chan[1] =3D get_unaligned_be24(&data->buffer[4]); + + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + iio_get_time_ns(indio_dev)); + +err: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +/* + * IIO ABI expects + * value =3D (conv + offset) * scale + * + * datasheet provides the following formula for determining the temperature + * temp[C] =3D conv * a + b + * where a =3D 200/16777215; b =3D -50 + * + * temp[C] =3D (conv + (b/a)) * a * (1000) + * =3D> + * scale =3D a * 1000 =3D .0000119209296 * 1000 =3D .01192092966562 + * offset =3D b/a =3D -50 * 16777215 / 200 =3D -4194303.75 + * + * based on the datasheet + * pressure =3D (conv - Omin) * Q + Pmin =3D + * ((conv - Omin) + Pmin/Q) * Q + * =3D> + * scale =3D Q =3D (Pmax - Pmin) / (Omax - Omin) + * offset =3D Pmin/Q - Omin =3D Pmin * (Omax - Omin) / (Pmax - Pmin) - Om= in + */ +static int abp2_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *channel, int *val, + int *val2, long mask) +{ + struct abp2_data *data =3D iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret =3D abp2_get_measurement(data); + if (ret < 0) + return ret; + + switch (channel->type) { + case IIO_PRESSURE: + *val =3D get_unaligned_be24(&data->buffer[1]); + return IIO_VAL_INT; + case IIO_TEMP: + *val =3D get_unaligned_be24(&data->buffer[4]); + return IIO_VAL_INT; + default: + return -EINVAL; + } + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + switch (channel->type) { + case IIO_TEMP: + *val =3D 0; + *val2 =3D 11920929; + return IIO_VAL_INT_PLUS_NANO; + case IIO_PRESSURE: + *val =3D data->p_scale; + *val2 =3D data->p_scale_dec; + return IIO_VAL_INT_PLUS_NANO; + default: + return -EINVAL; + } + + case IIO_CHAN_INFO_OFFSET: + switch (channel->type) { + case IIO_TEMP: + *val =3D -4194304; + return IIO_VAL_INT; + case IIO_PRESSURE: + *val =3D data->p_offset; + return IIO_VAL_INT; + default: + return -EINVAL; + } + + default: + return -EINVAL; + } +} + +static const struct iio_info abp2_info =3D { + .read_raw =3D &abp2_read_raw, +}; + +static const struct iio_chan_spec abp2_channels[] =3D { + { + .type =3D IIO_PRESSURE, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + .scan_index =3D 0, + .scan_type =3D { + .sign =3D 'u', + .realbits =3D 24, + .storagebits =3D 32, + .endianness =3D IIO_CPU, + }, + }, + { + .type =3D IIO_TEMP, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + .scan_index =3D 1, + .scan_type =3D { + .sign =3D 'u', + .realbits =3D 24, + .storagebits =3D 32, + .endianness =3D IIO_CPU, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(2), +}; + + +int abp2_common_probe(struct device *dev, const struct abp2_ops *ops, int = irq) +{ + int ret; + struct abp2_data *data; + struct iio_dev *indio_dev; + const char *triplet; + s64 tmp; + + indio_dev =3D devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data =3D iio_priv(indio_dev); + data->dev =3D dev; + data->ops =3D ops; + data->irq =3D irq; + + init_completion(&data->completion); + + indio_dev->name =3D "abp2030pa"; + indio_dev->info =3D &abp2_info; + indio_dev->channels =3D abp2_channels; + indio_dev->num_channels =3D ARRAY_SIZE(abp2_channels); + indio_dev->modes =3D INDIO_DIRECT_MODE; + + ret =3D devm_regulator_get_enable(dev, "vdd"); + if (ret) + return dev_err_probe(dev, ret, + "can't get and enable vdd supply\n"); + + ret =3D data->ops->init(data->dev); + if (ret) + return ret; + + ret =3D device_property_read_string(dev, "honeywell,pressure-triplet", + &triplet); + if (ret) { + ret =3D device_property_read_u32(dev, "honeywell,pmin-pascal", + &data->pmin); + if (ret) + return dev_err_probe(dev, ret, + "honeywell,pmin-pascal could not be read\n"); + + ret =3D device_property_read_u32(dev, "honeywell,pmax-pascal", + &data->pmax); + if (ret) + return dev_err_probe(dev, ret, + "honeywell,pmax-pascal could not be read\n"); + } else { + ret =3D device_property_match_property_string(dev, + "honeywell,pressure-triplet", + abp2_triplet_variants, + ABP2_VARIANTS_MAX); + if (ret < 0) + return dev_err_probe(dev, -EINVAL, + "honeywell,pressure-triplet is invalid\n"); + + data->pmin =3D abp2_range_config[ret].pmin; + data->pmax =3D abp2_range_config[ret].pmax; + } + + if (data->pmin >=3D data->pmax) + return dev_err_probe(dev, -EINVAL, + "pressure limits are invalid\n"); + + data->outmin =3D abp2_func_spec[data->function].output_min; + data->outmax =3D abp2_func_spec[data->function].output_max; + + tmp =3D div_s64(((s64)(data->pmax - data->pmin)) * NANO, + data->outmax - data->outmin); + data->p_scale =3D div_s64_rem(tmp, NANO, &data->p_scale_dec); + + tmp =3D div_s64((s64)data->pmin * (s64)(data->outmax - data->outmin), + (s64)(data->pmax - data->pmin)) - (s64)(data->outmin); + data->p_offset =3D tmp; + + if (data->irq > 0) { + ret =3D devm_request_irq(dev, data->irq, abp2_eoc_handler, + IRQF_TRIGGER_RISING, + dev_name(dev), + data); + if (ret) + return dev_err_probe(dev, ret, + "request irq %d failed\n", data->irq); + } + + ret =3D devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, + abp2_trigger_handler, NULL); + if (ret) + return dev_err_probe(dev, ret, + "iio triggered buffer setup failed\n"); + + ret =3D devm_iio_device_register(dev, indio_dev); + if (ret) + return dev_err_probe(dev, ret, + "unable to register iio device\n"); + + return 0; +} +EXPORT_SYMBOL_NS(abp2_common_probe, "IIO_HONEYWELL_ABP2030PA"); + +MODULE_AUTHOR("Petre Rodan "); +MODULE_DESCRIPTION("Honeywell ABP2 pressure sensor core driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/pressure/abp2030pa.h b/drivers/iio/pressure/abp203= 0pa.h new file mode 100644 index 000000000000..14f55e9b3869 --- /dev/null +++ b/drivers/iio/pressure/abp2030pa.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Honeywell ABP2 series pressure sensor driver + * + * Copyright (c) 2025 Petre Rodan + */ + +#ifndef _ABP2030PA_H +#define _ABP2030PA_H + +#include + +#include + +#define ABP2_MEASUREMENT_RD_SIZE 7 +#define ABP2_CMD_NOP 0xf0 +#define ABP2_CMD_SYNC 0xaa +#define ABP2_PKT_NOP_LEN ABP2_MEASUREMENT_RD_SIZE +#define ABP2_PKT_SYNC_LEN 3 + +struct completion; +struct device; + +struct iio_chan_spec; +struct iio_dev; + +struct abp2_data; +struct abp2_ops; + +enum abp2_func_id { + ABP2_FUNCTION_A, +}; + +/** + * struct abp2_data + * @dev: current device structure + * @ops: pointers for bus specific read, write and init functions + * @pmin: minimal pressure in pascal + * @pmax: maximal pressure in pascal + * @outmin: minimum raw pressure in counts (based on transfer function) + * @outmax: maximum raw pressure in counts (based on transfer function) + * @function: transfer function + * @p_scale: pressure scale + * @p_scale_dec: pressure scale, decimal number + * @p_offset: pressure offset + * @irq: end of conversion - applies only to the i2c sensor + * @completion: handshake from irq to read + * @scan: channel values for buffered mode + * @buffer: raw data provided by sensor + */ +struct abp2_data { + struct device *dev; + const struct abp2_ops *ops; + s32 pmin; + s32 pmax; + u32 outmin; + u32 outmax; + enum abp2_func_id function; + int p_scale; + int p_scale_dec; + int p_offset; + int irq; + struct completion completion; + struct { + u32 chan[2]; + aligned_s64 timestamp; + } scan; + u8 buffer[ABP2_MEASUREMENT_RD_SIZE] __aligned(IIO_DMA_MINALIGN); +}; + +struct abp2_ops { + int (*init)(struct device *dev); + int (*read)(struct abp2_data *data, const u8 cmd, const u8 cnt); + int (*write)(struct abp2_data *data, const u8 cmd, const u8 cnt); +}; + +int abp2_common_probe(struct device *dev, const struct abp2_ops *ops, int = irq); + +#endif diff --git a/drivers/iio/pressure/abp2030pa_i2c.c b/drivers/iio/pressure/ab= p2030pa_i2c.c new file mode 100644 index 000000000000..34f365f452ef --- /dev/null +++ b/drivers/iio/pressure/abp2030pa_i2c.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Honeywell ABP2 series pressure sensor driver + * + * Copyright (c) 2025 Petre Rodan + */ + +#include +#include +#include +#include +#include +#include + +#include "abp2030pa.h" + +static int abp2_i2c_init(struct device *dev) +{ + return 0; +} + +static int abp2_i2c_read(struct abp2_data *data, const u8 unused, const u8= cnt) +{ + struct i2c_client *client =3D to_i2c_client(data->dev); + int ret; + + if (cnt > ABP2_MEASUREMENT_RD_SIZE) + return -EOVERFLOW; + + ret =3D i2c_master_recv(client, data->buffer, cnt); + if (ret < 0) + return ret; + else if (ret !=3D cnt) + return -EIO; + + return 0; +} + +static int abp2_i2c_write(struct abp2_data *data, const u8 cmd, const u8 u= nused) +{ + struct i2c_client *client =3D to_i2c_client(data->dev); + u8 wdata[ABP2_PKT_SYNC_LEN] =3D { cmd }; + int ret; + + ret =3D i2c_master_send(client, wdata, ABP2_PKT_SYNC_LEN); + if (ret < 0) + return ret; + else if (ret !=3D ABP2_PKT_SYNC_LEN) + return -EIO; + + return 0; +} + +static const struct abp2_ops abp2_i2c_ops =3D { + .init =3D abp2_i2c_init, + .read =3D abp2_i2c_read, + .write =3D abp2_i2c_write, +}; + +static int abp2_i2c_probe(struct i2c_client *client) +{ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -EOPNOTSUPP; + + return abp2_common_probe(&client->dev, &abp2_i2c_ops, client->irq); +} + +static const struct of_device_id abp2_i2c_match[] =3D { + { .compatible =3D "honeywell,abp2030pa" }, + { } +}; +MODULE_DEVICE_TABLE(of, abp2_i2c_match); + +static const struct i2c_device_id abp2_i2c_id[] =3D { + { "abp2030pa" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, abp2_i2c_id); + +static struct i2c_driver abp2_i2c_driver =3D { + .driver =3D { + .name =3D "abp2030pa", + .of_match_table =3D abp2_i2c_match, + }, + .probe =3D abp2_i2c_probe, + .id_table =3D abp2_i2c_id, +}; +module_i2c_driver(abp2_i2c_driver); + +MODULE_AUTHOR("Petre Rodan "); +MODULE_DESCRIPTION("Honeywell ABP2 pressure sensor i2c driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_HONEYWELL_ABP2030PA"); diff --git a/drivers/iio/pressure/abp2030pa_spi.c b/drivers/iio/pressure/ab= p2030pa_spi.c new file mode 100644 index 000000000000..11a26f14d992 --- /dev/null +++ b/drivers/iio/pressure/abp2030pa_spi.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Honeywell ABP2 series pressure sensor driver + * + * Copyright (c) 2025 Petre Rodan + */ + +#include +#include +#include +#include +#include +#include + +#include "abp2030pa.h" + +struct abp2_spi_buf { + u8 tx[ABP2_MEASUREMENT_RD_SIZE] __aligned(IIO_DMA_MINALIGN); +}; + +static int abp2_spi_init(struct device *dev) +{ + struct spi_device *spi =3D to_spi_device(dev); + struct abp2_spi_buf *buf; + + buf =3D devm_kzalloc(dev, sizeof(*buf), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + spi_set_drvdata(spi, buf); + + return 0; +} + +static int abp2_spi_xfer(struct abp2_data *data, const u8 cmd, const u8 pk= t_len) +{ + struct spi_device *spi =3D to_spi_device(data->dev); + struct abp2_spi_buf *buf =3D spi_get_drvdata(spi); + struct spi_transfer xfer; + + if (pkt_len > ABP2_MEASUREMENT_RD_SIZE) + return -EOVERFLOW; + + buf->tx[0] =3D cmd; + xfer.tx_buf =3D buf->tx; + xfer.rx_buf =3D data->buffer; + xfer.len =3D pkt_len; + + return spi_sync_transfer(spi, &xfer, 1); +} + +static const struct abp2_ops abp2_spi_ops =3D { + .init =3D abp2_spi_init, + .read =3D abp2_spi_xfer, + .write =3D abp2_spi_xfer, +}; + +static int abp2_spi_probe(struct spi_device *spi) +{ + return abp2_common_probe(&spi->dev, &abp2_spi_ops, spi->irq); +} + +static const struct of_device_id abp2_spi_match[] =3D { + { .compatible =3D "honeywell,abp2030pa" }, + { } +}; +MODULE_DEVICE_TABLE(of, abp2_spi_match); + +static const struct spi_device_id abp2_spi_id[] =3D { + { "abp2030pa" }, + { } +}; +MODULE_DEVICE_TABLE(spi, abp2_spi_id); + +static struct spi_driver abp2_spi_driver =3D { + .driver =3D { + .name =3D "abp2030pa", + .of_match_table =3D abp2_spi_match, + }, + .probe =3D abp2_spi_probe, + .id_table =3D abp2_spi_id, +}; +module_spi_driver(abp2_spi_driver); + +MODULE_AUTHOR("Petre Rodan "); +MODULE_DESCRIPTION("Honeywell ABP2 pressure sensor spi driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_HONEYWELL_ABP2030PA"); --=20 2.51.0