From nobody Fri Oct 3 11:22:52 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 D74081AF0BB; Mon, 1 Sep 2025 19:55:08 +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=1756756510; cv=none; b=Qt/XG7CINaA4h447rXGYvsT1JMyPFtbSZ1esaePOWhP5m2dt80gXXInozjgHsedvMDL5fzf1oNzsneBMB4vOr+xYj5+RNfNX5H1kn7BXcrjpAI/tXd2OdS1LprYowXH3kKWHrrec2/8sSnmVffueddUA2mgogDmPx4L/79WEdms= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756756510; c=relaxed/simple; bh=cvbXcOjmrceea2vVvj79DAGDBVMFe6HplK3FUkfUUoQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ntbSteIMkdKGasOS3K9OvdaT37ZNcafuK5hSuouM+rHvJQnVz1fAhHebpyDJaeEUIaj+WnCWVC9eU+/dsM1gWCALK0OPF+7HYditQHFe3znnMxJ/TA3HGd/Psl/MRkxxjworyTooh2MidWKiaExP21HlpslSW+m9nf4E9Gj3h8k= 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=5jWEjWfP; 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="5jWEjWfP" Received: from localhost.localdomain (unknown [IPv6:2a02:2f0e:3503:4a00: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 1E179173BE9; Mon, 01 Sep 2025 22:47:54 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=subdimension.ro; s=mail; t=1756756074; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+3MAwKLb02xFBAnfdcoXq8JKOD808RppgqaRPlq0x6c=; b=5jWEjWfPc8HMBHwH8SVArnr4W83dLtBXSChH2H433txrl4mF4ZVkD+lVBaJMK0I51mLiST B2Wx4vukuX52ZcDLvNXqDl0SjUoH//P9crAPKrqQaB09Rx1izA4ib9IVAAghtm7Sx6Fdon ZfR4gQjcpcEBz4BUIeQkVuOvJxHYcJgSgbrOPcbwMr2+YeIEZ0TCFq7o537Kvuu3wLsdkf ESLvemxIv7HTYp3qCII37Q3krBp9JI2/JxC+xQlbqWiXcOwHutzNNwAuAEai+4oSBsm5EB JGoz7OnsI9Kysd4Lszr7QH1XyEBLIGadYNhKa2/WIqDpPlGIe/ruGNMsj+0Mlg== From: Petre Rodan To: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Petre Rodan , Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko , Rob Herring , Conor Dooley , Krzysztof Kozlowski Subject: [PATCH 01/10] dt-bindings: iio: accel: bosch,BMA220 improvements Date: Mon, 1 Sep 2025 22:47:27 +0300 Message-ID: <20250901194742.11599-2-petre.rodan@subdimension.ro> X-Mailer: git-send-email 2.49.1 In-Reply-To: <20250901194742.11599-1-petre.rodan@subdimension.ro> References: <20250901194742.11599-1-petre.rodan@subdimension.ro> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" - fix title typo - add optional watchdog setting that recovers the sensor from a stuck-low SDA condition - set correct SPI phase and polarity - interrupt on rising edge. the level-based interrupt that is being replaced was not actually implemented in the driver. This set of changes should not negatively affect existing users. Signed-off-by: Petre Rodan --- .../bindings/iio/accel/bosch,bma220.yaml | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/accel/bosch,bma220.yaml = b/Documentation/devicetree/bindings/iio/accel/bosch,bma220.yaml index ec643de031a3..f71b2320b010 100644 --- a/Documentation/devicetree/bindings/iio/accel/bosch,bma220.yaml +++ b/Documentation/devicetree/bindings/iio/accel/bosch,bma220.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/iio/accel/bosch,bma220.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Bosch BMA220 Trixial Acceleration Sensor +title: Bosch BMA220 Triaxial Acceleration Sensor maintainers: - Jonathan Cameron @@ -20,6 +20,20 @@ properties: interrupts: maxItems: 1 + bosch,watchdog: + description: + In order to prevent the built-in I2C slave to lock-up the I2C bus, a + watchdog timer is introduced. The WDT observes internal I2C signals = and + resets the I2C interface if the bus is locked-up by the BMA220. + 0 - off + 1 - 1ms + 2 - 10ms + enum: [0, 1, 2] + $ref: /schemas/types.yaml#/definitions/uint32 + + spi-cpha: true + spi-cpol: true + vdda-supply: true vddd-supply: true vddio-supply: true @@ -44,8 +58,10 @@ examples: compatible =3D "bosch,bma220"; reg =3D <0>; spi-max-frequency =3D <2500000>; + spi-cpol; + spi-cpha; interrupt-parent =3D <&gpio0>; - interrupts =3D <0 IRQ_TYPE_LEVEL_HIGH>; + interrupts =3D <0 IRQ_TYPE_EDGE_RISING>; }; }; ... -- 2.49.1 From nobody Fri Oct 3 11:22:52 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 D7460225402; Mon, 1 Sep 2025 19:55:08 +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=1756756511; cv=none; b=Qau1fsBE4Sw0vrwup1Ehybv2XBF1VfN9W7+BYmNcnvZxy/wVD3YH7lOpDK9IqGx6s24xa6FRjJhYiYr+6hmnB9QE8Qn7s27+O+2dcoJkJ3ZxSzsD4jFBfkA2UplGfd53bQsvKCF8OGveLT6X62hZB0wlDvIR0D5AJafqQ3PW1W0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756756511; c=relaxed/simple; bh=HxLnuwlpIvhxBUkcMu9dmGedl2oDpN1v3IY49t+ADuI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AXE1w9vODtsxvgaKjT5Cshr99GbdJbRXss/irBSDE+FGMn+gfev71FQSUCdrrL5lepPK3eRLMH0S2dLaMpSuHhf5a2ZK7MELUzFKO33ec6V3uXz4EAB1Ze4DNQCFwqPD3ySXvRFQtvEa/YymJwuHJORaddnYMuQXEoCBotLjHc8= 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=s2GmO+iR; 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="s2GmO+iR" Received: from localhost.localdomain (unknown [IPv6:2a02:2f0e:3503:4a00: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 08617173BEA; Mon, 01 Sep 2025 22:47:54 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=subdimension.ro; s=mail; t=1756756075; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZKpdVryC7+viduYUhoamo/u5TejWB2/LQJTHiVSdYAw=; b=s2GmO+iRqL6NRkt6I9Q0ePO+Ffd5qHsTUxoQyADJxFkdpLDyrnCJod1Bg7NFwBNWyQuHnR 3MjZjZfyHLfXcfMmLVY36B9qQKUqf+Z/EimQZVonnD42cLtxiIKcQOcb5gy2MS//FaW9iw NN2Xka2txJxixPZjDgBtvVpeBpI6CiT9RnW3VhRumBXElwbXZLzDVxr/32EgDcY2Pew44d 8Wlvvmu+v74D/secBE1qUPpTLOd/bIVJ5LmE46l5+QuxKDltE8nheJUBHLTjw3XgPe7M3Y LtcL9tBFr2Uz5hk6f6ilREDEuFg5dzo/9o558ja8HYqbuoK6k/0VkxNPSwCGiQ== From: Petre Rodan To: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Petre Rodan , Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko Subject: [PATCH 02/10] iio: accel: BMA220 split original spi driver Date: Mon, 1 Sep 2025 22:47:28 +0300 Message-ID: <20250901194742.11599-3-petre.rodan@subdimension.ro> X-Mailer: git-send-email 2.49.1 In-Reply-To: <20250901194742.11599-1-petre.rodan@subdimension.ro> References: <20250901194742.11599-1-petre.rodan@subdimension.ro> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Split original driver from bma220_spi.c into bma220_core.c and bma220.h with a minimal number of changes in preparation for the next patches. Signed-off-by: Petre Rodan --- drivers/iio/accel/Kconfig | 9 +- drivers/iio/accel/Makefile | 3 +- drivers/iio/accel/bma220.h | 17 ++ drivers/iio/accel/bma220_core.c | 310 ++++++++++++++++++++++++++++++++ drivers/iio/accel/bma220_spi.c | 309 ++----------------------------- 5 files changed, 354 insertions(+), 294 deletions(-) create mode 100644 drivers/iio/accel/bma220.h create mode 100644 drivers/iio/accel/bma220_core.c diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 8c3f7cf55d5f..2cc3075e2688 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -218,15 +218,20 @@ config BMA180 config BMA220 tristate "Bosch BMA220 3-Axis Accelerometer Driver" - depends on SPI select IIO_BUFFER select IIO_TRIGGERED_BUFFER + select BMA220_SPI if SPI help Say yes here to add support for the Bosch BMA220 triaxial acceleration sensor. To compile this driver as a module, choose M here: the - module will be called bma220_spi. + module will be called bma220_core and you will also get + bma220_spi if SPI is enabled. + +config BMA220_SPI + tristate + depends on BMA220 config BMA400 tristate "Bosch BMA400 3-Axis Accelerometer Driver" diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index ca8569e25aba..56a9f848f7f9 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -25,7 +25,8 @@ obj-$(CONFIG_ADXL380) +=3D adxl380.o obj-$(CONFIG_ADXL380_I2C) +=3D adxl380_i2c.o obj-$(CONFIG_ADXL380_SPI) +=3D adxl380_spi.o obj-$(CONFIG_BMA180) +=3D bma180.o -obj-$(CONFIG_BMA220) +=3D bma220_spi.o +obj-$(CONFIG_BMA220) +=3D bma220_core.o +obj-$(CONFIG_BMA220_SPI) +=3D bma220_spi.o obj-$(CONFIG_BMA400) +=3D bma400_core.o obj-$(CONFIG_BMA400_I2C) +=3D bma400_i2c.o obj-$(CONFIG_BMA400_SPI) +=3D bma400_spi.o diff --git a/drivers/iio/accel/bma220.h b/drivers/iio/accel/bma220.h new file mode 100644 index 000000000000..0606cf478f5f --- /dev/null +++ b/drivers/iio/accel/bma220.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Forward declarations needed by the bma220 sources. + * + * Copyright 2025 Petre Rodan + */ + +#ifndef _BMA220_H +#define _BMA220_H + +#include + +extern const struct dev_pm_ops bma220_pm_ops; + +int bma220_common_probe(struct spi_device *dev); + +#endif diff --git a/drivers/iio/accel/bma220_core.c b/drivers/iio/accel/bma220_cor= e.c new file mode 100644 index 000000000000..60fd35637d2d --- /dev/null +++ b/drivers/iio/accel/bma220_core.c @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * BMA220 Digital triaxial acceleration sensor driver + * + * Copyright (c) 2016,2020 Intel Corporation. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define BMA220_REG_ID 0x00 +#define BMA220_REG_ACCEL_X 0x02 +#define BMA220_REG_ACCEL_Y 0x03 +#define BMA220_REG_ACCEL_Z 0x04 +#define BMA220_REG_RANGE 0x11 +#define BMA220_REG_SUSPEND 0x18 + +#define BMA220_CHIP_ID 0xDD +#define BMA220_READ_MASK BIT(7) +#define BMA220_RANGE_MASK GENMASK(1, 0) +#define BMA220_SUSPEND_SLEEP 0xFF +#define BMA220_SUSPEND_WAKE 0x00 + +#define BMA220_DEVICE_NAME "bma220" + +#define BMA220_ACCEL_CHANNEL(index, reg, axis) { \ + .type =3D IIO_ACCEL, \ + .address =3D reg, \ + .modified =3D 1, \ + .channel2 =3D IIO_MOD_##axis, \ + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index =3D index, \ + .scan_type =3D { \ + .sign =3D 's', \ + .realbits =3D 6, \ + .storagebits =3D 8, \ + .shift =3D 2, \ + .endianness =3D IIO_CPU, \ + }, \ +} + +enum bma220_axis { + AXIS_X, + AXIS_Y, + AXIS_Z, +}; + +static const int bma220_scale_table[][2] =3D { + {0, 623000}, {1, 248000}, {2, 491000}, {4, 983000}, +}; + +struct bma220_data { + struct spi_device *spi_device; + struct mutex lock; + struct { + s8 chans[3]; + /* Ensure timestamp is naturally aligned. */ + aligned_s64 timestamp; + } scan; + u8 tx_buf[2] __aligned(IIO_DMA_MINALIGN); +}; + +static const struct iio_chan_spec bma220_channels[] =3D { + BMA220_ACCEL_CHANNEL(0, BMA220_REG_ACCEL_X, X), + BMA220_ACCEL_CHANNEL(1, BMA220_REG_ACCEL_Y, Y), + BMA220_ACCEL_CHANNEL(2, BMA220_REG_ACCEL_Z, Z), + IIO_CHAN_SOFT_TIMESTAMP(3), +}; + +static inline int bma220_read_reg(struct spi_device *spi, u8 reg) +{ + return spi_w8r8(spi, reg | BMA220_READ_MASK); +} + +static const unsigned long bma220_accel_scan_masks[] =3D { + BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z), + 0 +}; + +static irqreturn_t bma220_trigger_handler(int irq, void *p) +{ + int ret; + struct iio_poll_func *pf =3D p; + struct iio_dev *indio_dev =3D pf->indio_dev; + struct bma220_data *data =3D iio_priv(indio_dev); + struct spi_device *spi =3D data->spi_device; + + mutex_lock(&data->lock); + data->tx_buf[0] =3D BMA220_REG_ACCEL_X | BMA220_READ_MASK; + ret =3D spi_write_then_read(spi, data->tx_buf, 1, &data->scan.chans, + ARRAY_SIZE(bma220_channels) - 1); + if (ret < 0) + goto err; + + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + pf->timestamp); +err: + mutex_unlock(&data->lock); + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int bma220_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int ret; + u8 range_idx; + struct bma220_data *data =3D iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret =3D bma220_read_reg(data->spi_device, chan->address); + if (ret < 0) + return -EINVAL; + *val =3D sign_extend32(ret >> chan->scan_type.shift, + chan->scan_type.realbits - 1); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + ret =3D bma220_read_reg(data->spi_device, BMA220_REG_RANGE); + if (ret < 0) + return ret; + range_idx =3D ret & BMA220_RANGE_MASK; + *val =3D bma220_scale_table[range_idx][0]; + *val2 =3D bma220_scale_table[range_idx][1]; + return IIO_VAL_INT_PLUS_MICRO; + } + + return -EINVAL; +} + +static int bma220_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + int i; + int ret; + int index =3D -1; + struct bma220_data *data =3D iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + for (i =3D 0; i < ARRAY_SIZE(bma220_scale_table); i++) + if (val =3D=3D bma220_scale_table[i][0] && + val2 =3D=3D bma220_scale_table[i][1]) { + index =3D i; + break; + } + if (index < 0) + return -EINVAL; + + mutex_lock(&data->lock); + data->tx_buf[0] =3D BMA220_REG_RANGE; + data->tx_buf[1] =3D index; + ret =3D spi_write(data->spi_device, data->tx_buf, + sizeof(data->tx_buf)); + if (ret < 0) + dev_err(&data->spi_device->dev, + "failed to set measurement range\n"); + mutex_unlock(&data->lock); + + return 0; + } + + return -EINVAL; +} + +static int bma220_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SCALE: + *vals =3D (int *)bma220_scale_table; + *type =3D IIO_VAL_INT_PLUS_MICRO; + *length =3D ARRAY_SIZE(bma220_scale_table) * 2; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +static const struct iio_info bma220_info =3D { + .read_raw =3D bma220_read_raw, + .write_raw =3D bma220_write_raw, + .read_avail =3D bma220_read_avail, +}; + +static int bma220_init(struct spi_device *spi) +{ + int ret; + + ret =3D bma220_read_reg(spi, BMA220_REG_ID); + if (ret !=3D BMA220_CHIP_ID) + return -ENODEV; + + /* Make sure the chip is powered on */ + ret =3D bma220_read_reg(spi, BMA220_REG_SUSPEND); + if (ret =3D=3D BMA220_SUSPEND_WAKE) + ret =3D bma220_read_reg(spi, BMA220_REG_SUSPEND); + if (ret < 0) + return ret; + if (ret =3D=3D BMA220_SUSPEND_WAKE) + return -EBUSY; + + return 0; +} + +static int bma220_power(struct spi_device *spi, bool up) +{ + int i, ret; + + /** + * The chip can be suspended/woken up by a simple register read. + * So, we need up to 2 register reads of the suspend register + * to make sure that the device is in the desired state. + */ + for (i =3D 0; i < 2; i++) { + ret =3D bma220_read_reg(spi, BMA220_REG_SUSPEND); + if (ret < 0) + return ret; + + if (up && ret =3D=3D BMA220_SUSPEND_SLEEP) + return 0; + + if (!up && ret =3D=3D BMA220_SUSPEND_WAKE) + return 0; + } + + return -EBUSY; +} + +static void bma220_deinit(void *spi) +{ + bma220_power(spi, false); +} + +int bma220_common_probe(struct spi_device *spi) +{ + int ret; + struct iio_dev *indio_dev; + struct bma220_data *data; + + indio_dev =3D devm_iio_device_alloc(&spi->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data =3D iio_priv(indio_dev); + data->spi_device =3D spi; + mutex_init(&data->lock); + + indio_dev->info =3D &bma220_info; + indio_dev->name =3D BMA220_DEVICE_NAME; + indio_dev->modes =3D INDIO_DIRECT_MODE; + indio_dev->channels =3D bma220_channels; + indio_dev->num_channels =3D ARRAY_SIZE(bma220_channels); + indio_dev->available_scan_masks =3D bma220_accel_scan_masks; + + ret =3D bma220_init(data->spi_device); + if (ret) + return ret; + + ret =3D devm_add_action_or_reset(&spi->dev, bma220_deinit, spi); + if (ret) + return ret; + + ret =3D devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, + iio_pollfunc_store_time, + bma220_trigger_handler, NULL); + if (ret < 0) { + dev_err(&spi->dev, "iio triggered buffer setup failed\n"); + return ret; + } + + return devm_iio_device_register(&spi->dev, indio_dev); +} +EXPORT_SYMBOL_NS(bma220_common_probe, "IIO_BOSCH_BMA220"); + +static int bma220_suspend(struct device *dev) +{ + struct spi_device *spi =3D to_spi_device(dev); + + return bma220_power(spi, false); +} + +static int bma220_resume(struct device *dev) +{ + struct spi_device *spi =3D to_spi_device(dev); + + return bma220_power(spi, true); +} +EXPORT_NS_SIMPLE_DEV_PM_OPS(bma220_pm_ops, bma220_suspend, bma220_resume, + IIO_BOSCH_BMA220); + +MODULE_AUTHOR("Tiberiu Breana "); +MODULE_DESCRIPTION("BMA220 acceleration sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c index 01592eebf05b..be8348ad0a93 100644 --- a/drivers/iio/accel/bma220_spi.c +++ b/drivers/iio/accel/bma220_spi.c @@ -5,8 +5,8 @@ * Copyright (c) 2016,2020 Intel Corporation. */ -#include -#include +#include +#include #include #include #include @@ -14,295 +14,14 @@ #include #include -#include -#include -#include -#define BMA220_REG_ID 0x00 -#define BMA220_REG_ACCEL_X 0x02 -#define BMA220_REG_ACCEL_Y 0x03 -#define BMA220_REG_ACCEL_Z 0x04 -#define BMA220_REG_RANGE 0x11 -#define BMA220_REG_SUSPEND 0x18 +#include "bma220.h" -#define BMA220_CHIP_ID 0xDD -#define BMA220_READ_MASK BIT(7) -#define BMA220_RANGE_MASK GENMASK(1, 0) -#define BMA220_SUSPEND_SLEEP 0xFF -#define BMA220_SUSPEND_WAKE 0x00 - -#define BMA220_DEVICE_NAME "bma220" - -#define BMA220_ACCEL_CHANNEL(index, reg, axis) { \ - .type =3D IIO_ACCEL, \ - .address =3D reg, \ - .modified =3D 1, \ - .channel2 =3D IIO_MOD_##axis, \ - .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE), \ - .scan_index =3D index, \ - .scan_type =3D { \ - .sign =3D 's', \ - .realbits =3D 6, \ - .storagebits =3D 8, \ - .shift =3D 2, \ - .endianness =3D IIO_CPU, \ - }, \ -} - -enum bma220_axis { - AXIS_X, - AXIS_Y, - AXIS_Z, -}; - -static const int bma220_scale_table[][2] =3D { - {0, 623000}, {1, 248000}, {2, 491000}, {4, 983000}, -}; - -struct bma220_data { - struct spi_device *spi_device; - struct mutex lock; - struct { - s8 chans[3]; - /* Ensure timestamp is naturally aligned. */ - aligned_s64 timestamp; - } scan; - u8 tx_buf[2] __aligned(IIO_DMA_MINALIGN); -}; - -static const struct iio_chan_spec bma220_channels[] =3D { - BMA220_ACCEL_CHANNEL(0, BMA220_REG_ACCEL_X, X), - BMA220_ACCEL_CHANNEL(1, BMA220_REG_ACCEL_Y, Y), - BMA220_ACCEL_CHANNEL(2, BMA220_REG_ACCEL_Z, Z), - IIO_CHAN_SOFT_TIMESTAMP(3), -}; - -static inline int bma220_read_reg(struct spi_device *spi, u8 reg) -{ - return spi_w8r8(spi, reg | BMA220_READ_MASK); -} - -static const unsigned long bma220_accel_scan_masks[] =3D { - BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z), - 0 -}; - -static irqreturn_t bma220_trigger_handler(int irq, void *p) -{ - int ret; - struct iio_poll_func *pf =3D p; - struct iio_dev *indio_dev =3D pf->indio_dev; - struct bma220_data *data =3D iio_priv(indio_dev); - struct spi_device *spi =3D data->spi_device; - - mutex_lock(&data->lock); - data->tx_buf[0] =3D BMA220_REG_ACCEL_X | BMA220_READ_MASK; - ret =3D spi_write_then_read(spi, data->tx_buf, 1, &data->scan.chans, - ARRAY_SIZE(bma220_channels) - 1); - if (ret < 0) - goto err; - - iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), - pf->timestamp); -err: - mutex_unlock(&data->lock); - iio_trigger_notify_done(indio_dev->trig); - - return IRQ_HANDLED; -} - -static int bma220_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, long mask) -{ - int ret; - u8 range_idx; - struct bma220_data *data =3D iio_priv(indio_dev); - - switch (mask) { - case IIO_CHAN_INFO_RAW: - ret =3D bma220_read_reg(data->spi_device, chan->address); - if (ret < 0) - return -EINVAL; - *val =3D sign_extend32(ret >> chan->scan_type.shift, - chan->scan_type.realbits - 1); - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - ret =3D bma220_read_reg(data->spi_device, BMA220_REG_RANGE); - if (ret < 0) - return ret; - range_idx =3D ret & BMA220_RANGE_MASK; - *val =3D bma220_scale_table[range_idx][0]; - *val2 =3D bma220_scale_table[range_idx][1]; - return IIO_VAL_INT_PLUS_MICRO; - } - - return -EINVAL; -} - -static int bma220_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, int val2, long mask) -{ - int i; - int ret; - int index =3D -1; - struct bma220_data *data =3D iio_priv(indio_dev); - - switch (mask) { - case IIO_CHAN_INFO_SCALE: - for (i =3D 0; i < ARRAY_SIZE(bma220_scale_table); i++) - if (val =3D=3D bma220_scale_table[i][0] && - val2 =3D=3D bma220_scale_table[i][1]) { - index =3D i; - break; - } - if (index < 0) - return -EINVAL; - - mutex_lock(&data->lock); - data->tx_buf[0] =3D BMA220_REG_RANGE; - data->tx_buf[1] =3D index; - ret =3D spi_write(data->spi_device, data->tx_buf, - sizeof(data->tx_buf)); - if (ret < 0) - dev_err(&data->spi_device->dev, - "failed to set measurement range\n"); - mutex_unlock(&data->lock); - - return 0; - } - - return -EINVAL; -} - -static int bma220_read_avail(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - const int **vals, int *type, int *length, - long mask) -{ - switch (mask) { - case IIO_CHAN_INFO_SCALE: - *vals =3D (int *)bma220_scale_table; - *type =3D IIO_VAL_INT_PLUS_MICRO; - *length =3D ARRAY_SIZE(bma220_scale_table) * 2; - return IIO_AVAIL_LIST; - default: - return -EINVAL; - } -} - -static const struct iio_info bma220_info =3D { - .read_raw =3D bma220_read_raw, - .write_raw =3D bma220_write_raw, - .read_avail =3D bma220_read_avail, -}; - -static int bma220_init(struct spi_device *spi) +static int bma220_spi_probe(struct spi_device *spi) { - int ret; - - ret =3D bma220_read_reg(spi, BMA220_REG_ID); - if (ret !=3D BMA220_CHIP_ID) - return -ENODEV; - - /* Make sure the chip is powered on */ - ret =3D bma220_read_reg(spi, BMA220_REG_SUSPEND); - if (ret =3D=3D BMA220_SUSPEND_WAKE) - ret =3D bma220_read_reg(spi, BMA220_REG_SUSPEND); - if (ret < 0) - return ret; - if (ret =3D=3D BMA220_SUSPEND_WAKE) - return -EBUSY; - - return 0; + return bma220_common_probe(spi); } -static int bma220_power(struct spi_device *spi, bool up) -{ - int i, ret; - - /** - * The chip can be suspended/woken up by a simple register read. - * So, we need up to 2 register reads of the suspend register - * to make sure that the device is in the desired state. - */ - for (i =3D 0; i < 2; i++) { - ret =3D bma220_read_reg(spi, BMA220_REG_SUSPEND); - if (ret < 0) - return ret; - - if (up && ret =3D=3D BMA220_SUSPEND_SLEEP) - return 0; - - if (!up && ret =3D=3D BMA220_SUSPEND_WAKE) - return 0; - } - - return -EBUSY; -} - -static void bma220_deinit(void *spi) -{ - bma220_power(spi, false); -} - -static int bma220_probe(struct spi_device *spi) -{ - int ret; - struct iio_dev *indio_dev; - struct bma220_data *data; - - indio_dev =3D devm_iio_device_alloc(&spi->dev, sizeof(*data)); - if (!indio_dev) - return -ENOMEM; - - data =3D iio_priv(indio_dev); - data->spi_device =3D spi; - mutex_init(&data->lock); - - indio_dev->info =3D &bma220_info; - indio_dev->name =3D BMA220_DEVICE_NAME; - indio_dev->modes =3D INDIO_DIRECT_MODE; - indio_dev->channels =3D bma220_channels; - indio_dev->num_channels =3D ARRAY_SIZE(bma220_channels); - indio_dev->available_scan_masks =3D bma220_accel_scan_masks; - - ret =3D bma220_init(data->spi_device); - if (ret) - return ret; - - ret =3D devm_add_action_or_reset(&spi->dev, bma220_deinit, spi); - if (ret) - return ret; - - ret =3D devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, - iio_pollfunc_store_time, - bma220_trigger_handler, NULL); - if (ret < 0) { - dev_err(&spi->dev, "iio triggered buffer setup failed\n"); - return ret; - } - - return devm_iio_device_register(&spi->dev, indio_dev); -} - -static int bma220_suspend(struct device *dev) -{ - struct spi_device *spi =3D to_spi_device(dev); - - return bma220_power(spi, false); -} - -static int bma220_resume(struct device *dev) -{ - struct spi_device *spi =3D to_spi_device(dev); - - return bma220_power(spi, true); -} -static DEFINE_SIMPLE_DEV_PM_OPS(bma220_pm_ops, bma220_suspend, bma220_resu= me); - static const struct spi_device_id bma220_spi_id[] =3D { {"bma220", 0}, { } @@ -314,17 +33,25 @@ static const struct acpi_device_id bma220_acpi_id[] = =3D { }; MODULE_DEVICE_TABLE(spi, bma220_spi_id); -static struct spi_driver bma220_driver =3D { +static const struct of_device_id bma220_of_spi_match[] =3D { + { .compatible =3D "bosch,bma220" }, + { } +}; +MODULE_DEVICE_TABLE(of, bma220_of_spi_match); + +static struct spi_driver bma220_spi_driver =3D { .driver =3D { .name =3D "bma220_spi", .pm =3D pm_sleep_ptr(&bma220_pm_ops), + .of_match_table =3D bma220_of_spi_match, .acpi_match_table =3D bma220_acpi_id, }, - .probe =3D bma220_probe, + .probe =3D bma220_spi_probe, .id_table =3D bma220_spi_id, }; -module_spi_driver(bma220_driver); +module_spi_driver(bma220_spi_driver); MODULE_AUTHOR("Tiberiu Breana "); -MODULE_DESCRIPTION("BMA220 acceleration sensor driver"); -MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("BMA220 triaxial acceleration sensor spi driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_BOSCH_BMA220"); -- 2.49.1 From nobody Fri Oct 3 11:22:52 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 D737D32F76C; Mon, 1 Sep 2025 19:55:08 +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=1756756511; cv=none; b=jLQtcWSEq8S5qfabh2GLRy4luAoP6rypYC1cMbLBEoo/2RMGH82qH6Dr0lOxylgpYzYRzag/F+IZd05jXWkw1bT8AzoHvUGvdLSDiXCBW9ZYsjGTbfL649w7X6r2I1yVHEXhaY6nTeHGqQw09b9DwcxX3QODDK6xI3+yIxpY2SI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756756511; c=relaxed/simple; bh=G1WjPdsugVOgEk+OX4im96JVnrA/SLcGoEuuE/qOURU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qpNKYXIJe1XDYTmCF3OFbR7xXpO9Ms9L33IzR+5L8fNKTRa4/XrFer/ridlW13scMr8QImwsB5cBX/0dVDgLksG6XLDoKOKipJVgkff52pk9cmRbpsQuGr0mdb11hXKsxDs2bIfzp5HYoB8jQ2XffqnZZCme/uEkPUrqzuN8BHQ= 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=anZilxAG; 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="anZilxAG" Received: from localhost.localdomain (unknown [IPv6:2a02:2f0e:3503:4a00: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 93251173BEB; Mon, 01 Sep 2025 22:47:55 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=subdimension.ro; s=mail; t=1756756075; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=QxV2feckogM6L0+/fBWV7fSTSoPnrkAPSEcYxMpb1kQ=; b=anZilxAGRpL6K8t0lFk1SZbmVpN5zgrxAnbDvK3CZbL4YAIWShJkZqQRWEVqYhXLNxKCN7 AePNt4E2JkZ1PfONB1V2/3WewnaDEmy55UuSTIvdC48W2u3xC6UXEiO8+yriVjZKWWNwJc 4XiTGyw05rTwDsYMBCs6na4fUa1mIDiY2bW0mh7xd41hkaYbZvOcazP5Z5q3FRBgqJDK9j PkNTx56A5yEpKE8SlVc7+LF7YoeuypS9bdwjeHPF66E8B2AcO5OLBDGyB5xN0N+BS1a5r6 0pj/p3m4ecj4qxRVao8/y5Zti4D37GHiTez9bJ2ZfqLvCbbl3tIeGop1QaOGYA== From: Petre Rodan To: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Petre Rodan , Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko Subject: [PATCH 03/10] iio: accel: BMA220 migrate to regmap API Date: Mon, 1 Sep 2025 22:47:29 +0300 Message-ID: <20250901194742.11599-4-petre.rodan@subdimension.ro> X-Mailer: git-send-email 2.49.1 In-Reply-To: <20250901194742.11599-1-petre.rodan@subdimension.ro> References: <20250901194742.11599-1-petre.rodan@subdimension.ro> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Switch to regmap API. Signed-off-by: Petre Rodan --- drivers/iio/accel/Kconfig | 2 + drivers/iio/accel/bma220.h | 5 +- drivers/iio/accel/bma220_core.c | 417 ++++++++++++++++++++++++++------ drivers/iio/accel/bma220_spi.c | 12 +- 4 files changed, 354 insertions(+), 82 deletions(-) diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 2cc3075e2688..9b6c35b75948 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -218,6 +218,7 @@ config BMA180 config BMA220 tristate "Bosch BMA220 3-Axis Accelerometer Driver" + select REGMAP select IIO_BUFFER select IIO_TRIGGERED_BUFFER select BMA220_SPI if SPI @@ -231,6 +232,7 @@ config BMA220 config BMA220_SPI tristate + select REGMAP_SPI depends on BMA220 config BMA400 diff --git a/drivers/iio/accel/bma220.h b/drivers/iio/accel/bma220.h index 0606cf478f5f..5eefa9749d33 100644 --- a/drivers/iio/accel/bma220.h +++ b/drivers/iio/accel/bma220.h @@ -8,10 +8,13 @@ #ifndef _BMA220_H #define _BMA220_H +#include + #include +extern const struct regmap_config bma220_spi_regmap_config; extern const struct dev_pm_ops bma220_pm_ops; -int bma220_common_probe(struct spi_device *dev); +int bma220_common_probe(struct device *dev, struct regmap *regmap, int irq= ); #endif diff --git a/drivers/iio/accel/bma220_core.c b/drivers/iio/accel/bma220_cor= e.c index 60fd35637d2d..e6dac2e1cf4d 100644 --- a/drivers/iio/accel/bma220_core.c +++ b/drivers/iio/accel/bma220_core.c @@ -3,31 +3,133 @@ * BMA220 Digital triaxial acceleration sensor driver * * Copyright (c) 2016,2020 Intel Corporation. + * Copyright (c) 2025 Petre Rodan */ #include +#include +#include +#include +#include #include #include #include +#include +#include +#include +#include #include -#include -#include #include +#include +#include #include +#include #include #include +#include "bma220.h" + +/* + * Read-Only Registers + */ + +/* ID registers */ #define BMA220_REG_ID 0x00 +#define BMA220_REG_REVISION_ID 0x01 + +/* Acceleration registers */ #define BMA220_REG_ACCEL_X 0x02 #define BMA220_REG_ACCEL_Y 0x03 #define BMA220_REG_ACCEL_Z 0x04 + +/* + * Read-write configuration registers + */ +#define BMA220_REG_CONF0 0x05 +#define BMA220_HIGH_DUR_MSK GENMASK(5, 0) +#define BMA220_HIGH_HY_MSK GENMASK(7, 6) +#define BMA220_REG_CONF1 0x06 +#define BMA220_HIGH_TH_MSK GENMASK(3, 0) +#define BMA220_LOW_TH_MSK GENMASK(7, 4) +#define BMA220_REG_CONF2 0x07 +#define BMA220_LOW_DUR_MSK GENMASK(5, 0) +#define BMA220_LOW_HY_MSK GENMASK(7, 6) +#define BMA220_REG_CONF3 0x08 +#define BMA220_TT_DUR_MSK GENMASK(2, 0) +#define BMA220_TT_TH_MSK GENMASK(6, 3) +#define BMA220_TT_FILT_MSK BIT(7) +#define BMA220_REG_CONF4 0x09 +#define BMA220_SLOPE_DUR_MSK GENMASK(1, 0) +#define BMA220_SLOPE_TH_MSK GENMASK(5, 2) +#define BMA220_SLOPE_FILT_MSK BIT(6) +#define BMA220_ORIENT_EX_MSK BIT(7) +#define BMA220_REG_CONF5 0x0a +#define BMA220_TT_SAMP_MSK GENMASK(1, 0) +#define BMA220_ORIENT_BLOCKING_MSK GENMASK(3, 2) +#define BMA220_TIP_EN_MSK BIT(4) + +/* + * Read-only interrupt flags + */ +#define BMA220_REG_IF0 0x0b +/* interrupt flags */ +#define BMA220_IF_HIGH_SIGN BIT(0) +#define BMA220_IF_HIGH_FIRST_Z BIT(1) +#define BMA220_IF_HIGH_FIRST_Y BIT(2) +#define BMA220_IF_HIGH_FIRST_X BIT(3) +#define BMA220_IF_ORIENT_INT BIT(7) + +#define BMA220_REG_IF1 0x0c +/* interrupt flags */ +#define BMA220_IF_SLOPE BIT(0) +#define BMA220_IF_DRDY BIT(1) +#define BMA220_IF_HIGH BIT(2) +#define BMA220_IF_LOW BIT(3) +#define BMA220_IF_TT BIT(4) + +/* + * Read-write interrupt enable configuration registers + */ +#define BMA220_REG_IE0 0x0d +#define BMA220_INT_EN_TAP_Z_MSK BIT(0) +#define BMA220_INT_EN_TAP_Y_MSK BIT(1) +#define BMA220_INT_EN_TAP_X_MSK BIT(2) +#define BMA220_INT_EN_SLOPE_Z_MSK BIT(3) +#define BMA220_INT_EN_SLOPE_Y_MSK BIT(4) +#define BMA220_INT_EN_SLOPE_X_MSK BIT(5) +#define BMA220_INT_EN_ORIENT_MSK BIT(6) +#define BMA220_INT_EN_DRDY_MSK BIT(7) +#define BMA220_REG_IE1 0x0e +#define BMA220_INT_EN_HIGH_Z_MSK BIT(0) +#define BMA220_INT_EN_HIGH_Y_MSK BIT(1) +#define BMA220_INT_EN_HIGH_X_MSK BIT(2) +#define BMA220_INT_EN_LOW_MSK BIT(3) +#define BMA220_INT_LATCH_MSK GENMASK(6, 4) +#define BMA220_INT_LATCH_MAX 0x7 +#define BMA220_INT_RST_MSK BIT(7) +#define BMA220_INT_LATCH_LEN 8 +#define BMA220_REG_IE2 0x0f + +/* + * Read-write configuration registers + */ +#define BMA220_REG_FILTER 0x10 #define BMA220_REG_RANGE 0x11 +#define BMA220_REG_WDT 0x17 +#define BMA220_WDT_MASK GENMASK(2, 1) +#define BMA220_WDT_OFF 0x0 +#define BMA220_WDT_1MS BIT(1) +#define BMA220_WDT_10MS GENMASK(1, 0) +/* + * Read-only state change registers + */ #define BMA220_REG_SUSPEND 0x18 +#define BMA220_REG_SOFTRESET 0x19 #define BMA220_CHIP_ID 0xDD -#define BMA220_READ_MASK BIT(7) #define BMA220_RANGE_MASK GENMASK(1, 0) +#define BMA220_FILTER_MASK GENMASK(3, 0) #define BMA220_SUSPEND_SLEEP 0xFF #define BMA220_SUSPEND_WAKE 0x00 @@ -61,14 +163,16 @@ static const int bma220_scale_table[][2] =3D { }; struct bma220_data { - struct spi_device *spi_device; + struct device *dev; + struct regmap *regmap; struct mutex lock; + u8 range_idx; + struct iio_trigger *trig; struct { s8 chans[3]; /* Ensure timestamp is naturally aligned. */ aligned_s64 timestamp; - } scan; - u8 tx_buf[2] __aligned(IIO_DMA_MINALIGN); + } scan __aligned(IIO_DMA_MINALIGN); }; static const struct iio_chan_spec bma220_channels[] =3D { @@ -78,35 +182,81 @@ static const struct iio_chan_spec bma220_channels[] = =3D { IIO_CHAN_SOFT_TIMESTAMP(3), }; -static inline int bma220_read_reg(struct spi_device *spi, u8 reg) -{ - return spi_w8r8(spi, reg | BMA220_READ_MASK); -} - static const unsigned long bma220_accel_scan_masks[] =3D { BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z), 0 }; +static bool bma220_is_writable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case BMA220_REG_CONF0: + case BMA220_REG_CONF1: + case BMA220_REG_CONF2: + case BMA220_REG_CONF3: + case BMA220_REG_CONF4: + case BMA220_REG_CONF5: + case BMA220_REG_IE0: + case BMA220_REG_IE1: + case BMA220_REG_IE2: + case BMA220_REG_FILTER: + case BMA220_REG_RANGE: + case BMA220_REG_WDT: + return true; + default: + return false; + } +} + +static bool bma220_is_volatile_reg(struct device *dev, unsigned int reg) +{ + /* Don't cache any registers. */ + return true; +} + +const struct regmap_config bma220_spi_regmap_config =3D { + .reg_bits =3D 8, + .val_bits =3D 8, + .read_flag_mask =3D BIT(7), + .max_register =3D BMA220_REG_SOFTRESET, + .cache_type =3D REGCACHE_MAPLE, + .writeable_reg =3D bma220_is_writable_reg, + .volatile_reg =3D bma220_is_volatile_reg, +}; +EXPORT_SYMBOL_NS(bma220_spi_regmap_config, "IIO_BOSCH_BMA220"); + +static int bma220_data_rdy_trigger_set_state(struct iio_trigger *trig, + bool state) +{ + struct iio_dev *indio_dev =3D iio_trigger_get_drvdata(trig); + struct bma220_data *data =3D iio_priv(indio_dev); + + guard(mutex)(&data->lock); + return regmap_update_bits(data->regmap, BMA220_REG_IE0, + BMA220_INT_EN_DRDY_MSK, + FIELD_PREP(BMA220_INT_EN_DRDY_MSK, state)); +} + +static const struct iio_trigger_ops bma220_trigger_ops =3D { + .set_trigger_state =3D &bma220_data_rdy_trigger_set_state, + .validate_device =3D &iio_trigger_validate_own_device, +}; + static irqreturn_t bma220_trigger_handler(int irq, void *p) { int ret; struct iio_poll_func *pf =3D p; struct iio_dev *indio_dev =3D pf->indio_dev; struct bma220_data *data =3D iio_priv(indio_dev); - struct spi_device *spi =3D data->spi_device; - mutex_lock(&data->lock); - data->tx_buf[0] =3D BMA220_REG_ACCEL_X | BMA220_READ_MASK; - ret =3D spi_write_then_read(spi, data->tx_buf, 1, &data->scan.chans, - ARRAY_SIZE(bma220_channels) - 1); + ret =3D regmap_bulk_read(data->regmap, BMA220_REG_ACCEL_X, + &data->scan.chans, + sizeof(data->scan.chans)); if (ret < 0) - goto err; + return IRQ_NONE; iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), - pf->timestamp); -err: - mutex_unlock(&data->lock); + iio_get_time_ns(indio_dev)); iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; @@ -117,59 +267,66 @@ static int bma220_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { int ret; - u8 range_idx; + u8 index; + unsigned int reg; struct bma220_data *data =3D iio_priv(indio_dev); switch (mask) { case IIO_CHAN_INFO_RAW: - ret =3D bma220_read_reg(data->spi_device, chan->address); + ret =3D regmap_read(data->regmap, chan->address, ®); if (ret < 0) return -EINVAL; - *val =3D sign_extend32(ret >> chan->scan_type.shift, + *val =3D sign_extend32(reg >> chan->scan_type.shift, chan->scan_type.realbits - 1); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - ret =3D bma220_read_reg(data->spi_device, BMA220_REG_RANGE); - if (ret < 0) - return ret; - range_idx =3D ret & BMA220_RANGE_MASK; - *val =3D bma220_scale_table[range_idx][0]; - *val2 =3D bma220_scale_table[range_idx][1]; + index =3D data->range_idx; + *val =3D bma220_scale_table[index][0]; + *val2 =3D bma220_scale_table[index][1]; return IIO_VAL_INT_PLUS_MICRO; } return -EINVAL; } +static int bma220_find_match(const int (*tbl)[2], const int n, + const int val, const int val2) +{ + int i; + + for (i =3D 0; i < n; i++) { + if (tbl[i][0] =3D=3D val && tbl[i][1] =3D=3D val2) + return i; + } + + return -EINVAL; +} + static int bma220_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { - int i; int ret; int index =3D -1; struct bma220_data *data =3D iio_priv(indio_dev); + guard(mutex)(&data->lock); + switch (mask) { case IIO_CHAN_INFO_SCALE: - for (i =3D 0; i < ARRAY_SIZE(bma220_scale_table); i++) - if (val =3D=3D bma220_scale_table[i][0] && - val2 =3D=3D bma220_scale_table[i][1]) { - index =3D i; - break; - } + index =3D bma220_find_match(bma220_scale_table, + ARRAY_SIZE(bma220_scale_table), + val, val2); if (index < 0) return -EINVAL; - mutex_lock(&data->lock); - data->tx_buf[0] =3D BMA220_REG_RANGE; - data->tx_buf[1] =3D index; - ret =3D spi_write(data->spi_device, data->tx_buf, - sizeof(data->tx_buf)); + ret =3D regmap_update_bits(data->regmap, BMA220_REG_RANGE, + BMA220_RANGE_MASK, + FIELD_PREP(BMA220_RANGE_MASK, index)); if (ret < 0) - dev_err(&data->spi_device->dev, + dev_err(data->dev, "failed to set measurement range\n"); - mutex_unlock(&data->lock); + data->range_idx =3D index; return 0; } @@ -199,69 +356,150 @@ static const struct iio_info bma220_info =3D { .read_avail =3D bma220_read_avail, }; -static int bma220_init(struct spi_device *spi) +static int bma220_reset(struct bma220_data *data, bool up) { - int ret; + int i, ret; + unsigned int val; - ret =3D bma220_read_reg(spi, BMA220_REG_ID); - if (ret !=3D BMA220_CHIP_ID) - return -ENODEV; + guard(mutex)(&data->lock); - /* Make sure the chip is powered on */ - ret =3D bma220_read_reg(spi, BMA220_REG_SUSPEND); - if (ret =3D=3D BMA220_SUSPEND_WAKE) - ret =3D bma220_read_reg(spi, BMA220_REG_SUSPEND); - if (ret < 0) - return ret; - if (ret =3D=3D BMA220_SUSPEND_WAKE) - return -EBUSY; + /** + * The chip can be reset by a simple register read. + * We need up to 2 register reads of the softreset register + * to make sure that the device is in the desired state. + */ + for (i =3D 0; i < 2; i++) { + ret =3D regmap_read(data->regmap, BMA220_REG_SOFTRESET, &val); + if (ret < 0) + return ret; - return 0; + if (up && (val =3D=3D BMA220_SUSPEND_SLEEP)) + return 0; + + if (!up && (val =3D=3D BMA220_SUSPEND_WAKE)) + return 0; + } + + return -EBUSY; } -static int bma220_power(struct spi_device *spi, bool up) +static int bma220_power(struct bma220_data *data, bool up) { int i, ret; + unsigned int val; + guard(mutex)(&data->lock); /** * The chip can be suspended/woken up by a simple register read. * So, we need up to 2 register reads of the suspend register * to make sure that the device is in the desired state. */ for (i =3D 0; i < 2; i++) { - ret =3D bma220_read_reg(spi, BMA220_REG_SUSPEND); + ret =3D regmap_read(data->regmap, BMA220_REG_SUSPEND, &val); if (ret < 0) return ret; - if (up && ret =3D=3D BMA220_SUSPEND_SLEEP) + if (up && (val =3D=3D BMA220_SUSPEND_SLEEP)) return 0; - if (!up && ret =3D=3D BMA220_SUSPEND_WAKE) + if (!up && (val =3D=3D BMA220_SUSPEND_WAKE)) return 0; } return -EBUSY; } -static void bma220_deinit(void *spi) +static int bma220_init(struct bma220_data *data) +{ + int ret; + unsigned int val; + static const char * const regulator_names[] =3D { "vddd", "vddio", "vdda"= }; + + ret =3D devm_regulator_bulk_get_enable(data->dev, + ARRAY_SIZE(regulator_names), + regulator_names); + if (ret) + return dev_err_probe(data->dev, ret, "Failed to get regulators\n"); + + /* Try to read chip_id register. It must return 0xdd. */ + ret =3D regmap_read(data->regmap, BMA220_REG_ID, &val); + if (ret) { + dev_err(data->dev, "Failed to read chip id register\n"); + return ret; + } + + if (val !=3D BMA220_CHIP_ID) + return -ENODEV; + + ret =3D bma220_power(data, true); + if (ret) { + dev_err(data->dev, "Failed to power-on chip\n"); + return ret; + } + + ret =3D bma220_reset(data, true); + if (ret) { + dev_err(data->dev, "Failed to soft reset chip\n"); + return ret; + } + + return 0; +} + +static void bma220_deinit(void *data_ptr) { - bma220_power(spi, false); + struct bma220_data *data =3D data_ptr; + int ret; + + ret =3D bma220_power(data, false); + if (ret) + dev_warn(data->dev, + "Failed to put device into suspend mode (%pe)\n", + ERR_PTR(ret)); +} + +static irqreturn_t bma220_irq_handler(int irq, void *private) +{ + struct iio_dev *indio_dev =3D private; + struct bma220_data *data =3D iio_priv(indio_dev); + int rv; + u8 bma220_reg_if[2]; + + guard(mutex)(&data->lock); + rv =3D regmap_bulk_read(data->regmap, BMA220_REG_IF0, bma220_reg_if, + sizeof(bma220_reg_if)); + if (rv) + return IRQ_NONE; + + if (FIELD_GET(BMA220_IF_DRDY, bma220_reg_if[1])) { + iio_trigger_poll_nested(data->trig); + goto done; + } + +done: + + return IRQ_HANDLED; } -int bma220_common_probe(struct spi_device *spi) +int bma220_common_probe(struct device *dev, struct regmap *regmap, int irq) { int ret; struct iio_dev *indio_dev; struct bma220_data *data; - indio_dev =3D devm_iio_device_alloc(&spi->dev, sizeof(*data)); + indio_dev =3D devm_iio_device_alloc(dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; data =3D iio_priv(indio_dev); - data->spi_device =3D spi; - mutex_init(&data->lock); + data->regmap =3D regmap; + data->dev =3D dev; + + ret =3D bma220_init(data); + if (ret) + return ret; + mutex_init(&data->lock); indio_dev->info =3D &bma220_info; indio_dev->name =3D BMA220_DEVICE_NAME; indio_dev->modes =3D INDIO_DIRECT_MODE; @@ -269,38 +507,59 @@ int bma220_common_probe(struct spi_device *spi) indio_dev->num_channels =3D ARRAY_SIZE(bma220_channels); indio_dev->available_scan_masks =3D bma220_accel_scan_masks; - ret =3D bma220_init(data->spi_device); - if (ret) - return ret; + if (irq > 0) { + data->trig =3D devm_iio_trigger_alloc(dev, "%s-dev%d", + indio_dev->name, + iio_device_id(indio_dev)); + if (!data->trig) + return -ENOMEM; + + data->trig->ops =3D &bma220_trigger_ops; + iio_trigger_set_drvdata(data->trig, indio_dev); + + ret =3D devm_iio_trigger_register(data->dev, data->trig); + if (ret) + return dev_err_probe(data->dev, ret, + "iio trigger register fail\n"); + indio_dev->trig =3D iio_trigger_get(data->trig); + ret =3D devm_request_threaded_irq(dev, irq, NULL, + &bma220_irq_handler, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + indio_dev->name, indio_dev); + if (ret) + return dev_err_probe(data->dev, ret, + "request irq %d failed\n", irq); + } - ret =3D devm_add_action_or_reset(&spi->dev, bma220_deinit, spi); + ret =3D devm_add_action_or_reset(data->dev, bma220_deinit, data); if (ret) return ret; - ret =3D devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, - iio_pollfunc_store_time, + ret =3D devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, bma220_trigger_handler, NULL); if (ret < 0) { - dev_err(&spi->dev, "iio triggered buffer setup failed\n"); + dev_err(dev, "iio triggered buffer setup failed\n"); return ret; } - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } EXPORT_SYMBOL_NS(bma220_common_probe, "IIO_BOSCH_BMA220"); static int bma220_suspend(struct device *dev) { - struct spi_device *spi =3D to_spi_device(dev); + struct iio_dev *indio_dev =3D dev_get_drvdata(dev); + struct bma220_data *data =3D iio_priv(indio_dev); - return bma220_power(spi, false); + return bma220_power(data, false); } static int bma220_resume(struct device *dev) { - struct spi_device *spi =3D to_spi_device(dev); + struct iio_dev *indio_dev =3D dev_get_drvdata(dev); + struct bma220_data *data =3D iio_priv(indio_dev); - return bma220_power(spi, true); + return bma220_power(data, true); } EXPORT_NS_SIMPLE_DEV_PM_OPS(bma220_pm_ops, bma220_suspend, bma220_resume, IIO_BOSCH_BMA220); diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c index be8348ad0a93..00e3fba9436d 100644 --- a/drivers/iio/accel/bma220_spi.c +++ b/drivers/iio/accel/bma220_spi.c @@ -9,17 +9,25 @@ #include #include #include +#include #include #include -#include #include #include "bma220.h" static int bma220_spi_probe(struct spi_device *spi) { - return bma220_common_probe(spi); + struct regmap *regmap; + + regmap =3D devm_regmap_init_spi(spi, &bma220_spi_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "failed to create regmap\n"); + return PTR_ERR(regmap); + } + + return bma220_common_probe(&spi->dev, regmap, spi->irq); } static const struct spi_device_id bma220_spi_id[] =3D { -- 2.49.1 From nobody Fri Oct 3 11:22:52 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 D74C32580CA; Mon, 1 Sep 2025 19:55:08 +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=1756756510; cv=none; b=Gq/G7mS1pGJYSY2XehoJSotc9mwo7kDmal6qHJt+z+EoxLY85WaI2/2YR1LyCcwFQs5MVlTfWxySZTyf+HnEQrKyu7FkfUdIJ0nM97PxvPzmd/9BsXfLom6U36zOLrYBAX02fcprxeUbFO3SvCyatF5fG1xEXhyO/Kb8gI0JmUs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756756510; c=relaxed/simple; bh=tiZA4TdFvRoRUywLr07gSd71OMrtnadQIIVgAWv7o4g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ks6nhAS943M5OFVTAhItsJb8DXSxfjGP1nuBWONDJQdDHH/xbJhXo5ahJlo1G/inrUN5aO7StS3fPgIcjt/KiSh3bLIkrC1wxawdRbgQag1gTQG+JW4srOP1/nbyYtf8D6uD1hAwOMfDCcM1p59ATdyWtsZpl8iYDYuG4Anj15s= 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=z4e2INzR; 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="z4e2INzR" Received: from localhost.localdomain (unknown [IPv6:2a02:2f0e:3503:4a00: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 D7D4D173BEC; Mon, 01 Sep 2025 22:47:55 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=subdimension.ro; s=mail; t=1756756076; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=A8j/QOXN0ugvgXWg9xQZTmkY/Q+gPIG4c4igm/P83LQ=; b=z4e2INzRV/MAHqiEbDA41yzf10tUE4IBe7mW/nYQvux3I6qXItt7kDgT/nrxUbdVKf87SZ vpvK/8VYnCPMWv5qazBUSmU4mLQQ/GGjbp0BtFZZ93IEg9snWEh3qgC3qvQMeGb78UiDGO OxUyM6VutQCbAslLOSjP0TxAlbHmqEukVslw4RnnGPE00IPURg99V4T8mnF/AmRPyq7sKW CToQxS7+qcM4M8KUiWmXQ6QVNNs/zg6XqpOKt/rYSf4P2xSlEU5RF932MhfA2kZIE1dA7w mS2ALcrgQX6Qt2bOSTFD7OQKSzFD/zAqTFh4vmbypdiAuYulWORBNpD6L4ySVA== From: Petre Rodan To: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Petre Rodan , Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko Subject: [PATCH 04/10] iio: accel: BMA220 add i2c module Date: Mon, 1 Sep 2025 22:47:30 +0300 Message-ID: <20250901194742.11599-5-petre.rodan@subdimension.ro> X-Mailer: git-send-email 2.49.1 In-Reply-To: <20250901194742.11599-1-petre.rodan@subdimension.ro> References: <20250901194742.11599-1-petre.rodan@subdimension.ro> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add i2c module. Note that the kernel module transparently shifts all register addresses 1 bit to the left, so all functions will operate based on the SPI memory map. Signed-off-by: Petre Rodan --- drivers/iio/accel/Kconfig | 9 ++++- drivers/iio/accel/Makefile | 1 + drivers/iio/accel/bma220.h | 1 + drivers/iio/accel/bma220_core.c | 19 ++++++++++ drivers/iio/accel/bma220_i2c.c | 62 +++++++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 drivers/iio/accel/bma220_i2c.c diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 9b6c35b75948..b3c5b0b7a406 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -221,6 +221,7 @@ config BMA220 select REGMAP select IIO_BUFFER select IIO_TRIGGERED_BUFFER + select BMA220_I2C if I2C select BMA220_SPI if SPI help Say yes here to add support for the Bosch BMA220 triaxial @@ -228,7 +229,13 @@ config BMA220 To compile this driver as a module, choose M here: the module will be called bma220_core and you will also get - bma220_spi if SPI is enabled. + bma220_i2c if I2C is enabled and bma220_spi if SPI is + enabled. + +config BMA220_I2C + tristate + select REGMAP_I2C + depends on BMA220 config BMA220_SPI tristate diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index 56a9f848f7f9..fa440a859283 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_ADXL380_I2C) +=3D adxl380_i2c.o obj-$(CONFIG_ADXL380_SPI) +=3D adxl380_spi.o obj-$(CONFIG_BMA180) +=3D bma180.o obj-$(CONFIG_BMA220) +=3D bma220_core.o +obj-$(CONFIG_BMA220_I2C) +=3D bma220_i2c.o obj-$(CONFIG_BMA220_SPI) +=3D bma220_spi.o obj-$(CONFIG_BMA400) +=3D bma400_core.o obj-$(CONFIG_BMA400_I2C) +=3D bma400_i2c.o diff --git a/drivers/iio/accel/bma220.h b/drivers/iio/accel/bma220.h index 5eefa9749d33..ae4b74514629 100644 --- a/drivers/iio/accel/bma220.h +++ b/drivers/iio/accel/bma220.h @@ -13,6 +13,7 @@ #include extern const struct regmap_config bma220_spi_regmap_config; +extern const struct regmap_config bma220_i2c_regmap_config; extern const struct dev_pm_ops bma220_pm_ops; int bma220_common_probe(struct device *dev, struct regmap *regmap, int irq= ); diff --git a/drivers/iio/accel/bma220_core.c b/drivers/iio/accel/bma220_cor= e.c index e6dac2e1cf4d..fae84823d52b 100644 --- a/drivers/iio/accel/bma220_core.c +++ b/drivers/iio/accel/bma220_core.c @@ -225,6 +225,25 @@ const struct regmap_config bma220_spi_regmap_config = =3D { }; EXPORT_SYMBOL_NS(bma220_spi_regmap_config, "IIO_BOSCH_BMA220"); +/* + * Based on the datasheet the memory map differs between the SPI and the I= 2C + * implementations. I2C register addresses are simply shifted to the left + * by 1 bit yet the register size remains unchanged. + * This driver employs the SPI memory map to correlate register names to + * addresses regardless of the bus type. + */ + +const struct regmap_config bma220_i2c_regmap_config =3D { + .reg_bits =3D 8, + .val_bits =3D 8, + .reg_shift =3D -1, + .max_register =3D BMA220_REG_SOFTRESET, + .cache_type =3D REGCACHE_MAPLE, + .writeable_reg =3D bma220_is_writable_reg, + .volatile_reg =3D bma220_is_volatile_reg, +}; +EXPORT_SYMBOL_NS(bma220_i2c_regmap_config, "IIO_BOSCH_BMA220"); + static int bma220_data_rdy_trigger_set_state(struct iio_trigger *trig, bool state) { diff --git a/drivers/iio/accel/bma220_i2c.c b/drivers/iio/accel/bma220_i2c.c new file mode 100644 index 000000000000..8a1644aac287 --- /dev/null +++ b/drivers/iio/accel/bma220_i2c.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Bosch triaxial acceleration sensor + * + * Copyright (c) 2025 Petre Rodan + * + * Datasheet: https://media.digikey.com/pdf/Data%20Sheets/Bosch/BMA220.pdf + * I2C address is either 0x0b or 0x0a depending on CSB (pin 10) + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "bma220.h" + +static int bma220_i2c_probe(struct i2c_client *client) +{ + struct regmap *regmap; + + regmap =3D devm_regmap_init_i2c(client, &bma220_i2c_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "failed to create regmap\n"); + return PTR_ERR(regmap); + } + + return bma220_common_probe(&client->dev, regmap, client->irq); +} + +static const struct of_device_id bma220_i2c_match[] =3D { + { .compatible =3D "bosch,bma220" }, + { } +}; +MODULE_DEVICE_TABLE(of, bma220_i2c_match); + +static const struct i2c_device_id bma220_i2c_id[] =3D { + { "bma220" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, bma220_i2c_id); + +static struct i2c_driver bma220_i2c_driver =3D { + .driver =3D { + .name =3D "bma220_i2c", + .pm =3D pm_sleep_ptr(&bma220_pm_ops), + .of_match_table =3D bma220_i2c_match, + }, + .probe =3D bma220_i2c_probe, + .id_table =3D bma220_i2c_id, +}; +module_i2c_driver(bma220_i2c_driver); + +MODULE_AUTHOR("Petre Rodan "); +MODULE_DESCRIPTION("Bosch triaxial acceleration sensor i2c driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_BOSCH_BMA220"); -- 2.49.1 From nobody Fri Oct 3 11:22:52 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 BE2C321019C; Mon, 1 Sep 2025 19:48:03 +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=1756756086; cv=none; b=ZDvxBRQKH3VeedQMxVvQI8Irnb6JA8TkSvOoL6Dp0ed6KRjU3KHPhJD11vZbR7gOZ2KOahb/BJnrNtE1eCXB9Wh3REWu/+KVECnj5AE4V9GCg1Q3THweq1ZeLz+ZD4EMpqLGtpucIAa6uy8Mi5gkL2bjF3y8NV99v5KCEeiIK6I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756756086; c=relaxed/simple; bh=Tepe2HnmOQQtLKDtH3w0ZwrujUeBKRNKyeiSGGFLgT0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=knV/pWP06zV6Vtx65LFh/+Ycn6MpTr+dzVXxNxhF9Vwfz9Rgv8G+MtDnHAD6EUiX+17NTGEWtuGo/1ZyDL6LQ21OkCIZlzvqEBbeeIADb4ca7HOwcVfBH662+nrlMxjg/SoJqG2HHLjMN7lSHw9LX6LN0uITfRappwcU/3LlaUs= 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=40jOoNYa; 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="40jOoNYa" Received: from localhost.localdomain (unknown [IPv6:2a02:2f0e:3503:4a00: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 5615D173BED; Mon, 01 Sep 2025 22:47:56 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=subdimension.ro; s=mail; t=1756756076; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8037ziBQdvZlRDgfvedaXrcP/LtyZMhTXyYaCxnZVyc=; b=40jOoNYazEhJm79D9WXOe5HjI8YjXZl2uw1rA4Jz1ipRCFnxXfV2i4TwdHCQtqV4FTXMpx ZGhh1hsJiN5bghqli5SgtJs+H2Aa6n9Ku3n93pzi6N1bCmXphVpHHreUUtw9yJwm8TO5Yw Shaags3UD7mF+7CzC9jQGhXoabvn3xhJ/4gMrs7KuqoYdGttWWmh0Zg5OIfN77d89VgHpF 6aHhjSsggI4kDQws7zXikLvrpKhb32c9umerfbd49SKP74ez1Y3OZ9073PmvOg7+TYTI1g l8z0WZtHlkNZMGYjy1RlSgY/Iyc5nUA/BThVWvMQgdM7YUI/+nzJ9ikjnWmG3g== From: Petre Rodan To: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Petre Rodan , Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko Subject: [PATCH 05/10] iio: accel: BMA220 make use of the watchdog functionality Date: Mon, 1 Sep 2025 22:47:31 +0300 Message-ID: <20250901194742.11599-6-petre.rodan@subdimension.ro> X-Mailer: git-send-email 2.49.1 In-Reply-To: <20250901194742.11599-1-petre.rodan@subdimension.ro> References: <20250901194742.11599-1-petre.rodan@subdimension.ro> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Sometimes the sensor gets stuck and enters a condition in which it pulls SDA low, thus making the entire i2c bus unusable. The optional bosch,watchdog property mitigates this problem by clearing the condition after a period of 1 or 10ms. Signed-off-by: Petre Rodan --- drivers/iio/accel/bma220_core.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/iio/accel/bma220_core.c b/drivers/iio/accel/bma220_cor= e.c index fae84823d52b..86347cf8ab1e 100644 --- a/drivers/iio/accel/bma220_core.c +++ b/drivers/iio/accel/bma220_core.c @@ -158,6 +158,12 @@ enum bma220_axis { AXIS_Z, }; +enum bma220_prop_wdt { + BMA220_PROP_WDT_OFF, + BMA220_PROP_WDT_1MS, + BMA220_PROP_WDT_10MS, +}; + static const int bma220_scale_table[][2] =3D { {0, 623000}, {1, 248000}, {2, 491000}, {4, 983000}, }; @@ -428,10 +434,17 @@ static int bma220_power(struct bma220_data *data, boo= l up) return -EBUSY; } +static int bma220_wdt(struct bma220_data *data, const u8 val) +{ + return regmap_update_bits(data->regmap, BMA220_REG_WDT, BMA220_WDT_MASK, + FIELD_PREP(BMA220_WDT_MASK, val)); +} + static int bma220_init(struct bma220_data *data) { int ret; unsigned int val; + u32 watchdog; static const char * const regulator_names[] =3D { "vddd", "vddio", "vdda"= }; ret =3D devm_regulator_bulk_get_enable(data->dev, @@ -462,6 +475,25 @@ static int bma220_init(struct bma220_data *data) return ret; } + ret =3D device_property_read_u32(data->dev, "bosch,watchdog", &watchdog); + if (!ret) { + switch (watchdog) { + case BMA220_PROP_WDT_1MS: + ret =3D bma220_wdt(data, BMA220_WDT_1MS); + break; + case BMA220_PROP_WDT_10MS: + ret =3D bma220_wdt(data, BMA220_WDT_10MS); + break; + default: + ret =3D bma220_wdt(data, BMA220_WDT_OFF); + break; + } + if (ret) { + dev_err(data->dev, "Failed to set watchdog\n"); + return ret; + } + } + return 0; } -- 2.49.1 From nobody Fri Oct 3 11:22:52 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 BE26320E011; Mon, 1 Sep 2025 19:48:03 +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=1756756086; cv=none; b=k9SpN6fGEh5CNPxjh/83GGXslPUZKCq9QXJkWEV8CfZexoFaeuWN0soMgvk3gKIBsEhRckuav+DCmzrJGgYtv9txCoDlyN0WJlhdDoBoVlHpOjJCd6a7ofC21gisGoP/N7JwoJvIZfvrQG++ewans/PsMfyXU1m4awwvks22Jcc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756756086; c=relaxed/simple; bh=wLmWmflf8u7y40Xzi81r7dRJzmbcJfPGyzoimcWuoDQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=a403Y34U3irZBQe22YnzNant59ddryAhUWW1yHW6Zo047G8Kgwiu2w9QpVe1FbeRsJKJDH+lMSehPDGO+FKREG2Z+Z2yI5ZQ6Mejv0QSqZuwq0JstUXj7+KdfUkUYmcChjFJauIW/lFOCCOcncD0bU7o3yPSi/vC1E5hBtrWPwU= 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=bJYOUVGh; 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="bJYOUVGh" Received: from localhost.localdomain (unknown [IPv6:2a02:2f0e:3503:4a00: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 9E656173BEE; Mon, 01 Sep 2025 22:47:56 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=subdimension.ro; s=mail; t=1756756076; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=69u6iKKI76eah3bWQ71TVwjN/VHHBc+0BJ2bQX2S/fU=; b=bJYOUVGh9IisUx3CTNDqzNswCMJmeO86RnNaUveDT9eDBzrpUmGwXK+hG9F/VXK3mV1RW+ hwQCRPA8uF+4Ub/t1hORAKqNdTIjJJdJZiRZqWjht+aiFvTHkdTaCxwZtwygb5Q7yeOavN aaQUNRqHVEcY/41lFtc2EXdrZ5u+UiNpcAOXJgrQmc+8LZ4g+5t3l30gm3pNkx8IPxv/1q 7lajN7Lz2UFBjbKzaUhEmIsbI4xyYQZLtCyUFCzq2b09bDl9zF6R+4dhYdqefJ9+HJnGM8 R5bR8uNRqi2sIyRpFPbN3FeizhaGmbpWhKIi4+zeSko2Lc26ppt/DBw+soZRUA== From: Petre Rodan To: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Petre Rodan , Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko Subject: [PATCH 06/10] iio: accel: BMA220 add LPF cut-off frequency mapping Date: Mon, 1 Sep 2025 22:47:32 +0300 Message-ID: <20250901194742.11599-7-petre.rodan@subdimension.ro> X-Mailer: git-send-email 2.49.1 In-Reply-To: <20250901194742.11599-1-petre.rodan@subdimension.ro> References: <20250901194742.11599-1-petre.rodan@subdimension.ro> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" - add mapping for the low pass filter cut-off frequency. - make valid values visible for both the cut-off frequency and the scale. Signed-off-by: Petre Rodan --- drivers/iio/accel/bma220_core.c | 60 ++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/drivers/iio/accel/bma220_core.c b/drivers/iio/accel/bma220_cor= e.c index 86347cf8ab1e..e60acd62cf96 100644 --- a/drivers/iio/accel/bma220_core.c +++ b/drivers/iio/accel/bma220_core.c @@ -4,6 +4,15 @@ * * Copyright (c) 2016,2020 Intel Corporation. * Copyright (c) 2025 Petre Rodan + * + * + * Device register to IIO ABI mapping: + * + * Register | IIO ABI (sysfs) | valid valu= es + * --------------------------+--------------------------------+-----------= ---- + * scale (range) | in_accel_scale | see _avail= able + * cut-off freq (filt_config)| in_accel_filter_low_pass_... | see _avail= able + * -----------------------------------------------------------------------= ---- */ #include @@ -135,13 +144,23 @@ #define BMA220_DEVICE_NAME "bma220" +#define BMA220_COF_1000HZ 0x0 +#define BMA220_COF_500HZ 0x1 +#define BMA220_COF_250HZ 0x2 +#define BMA220_COF_125HZ 0x3 +#define BMA220_COF_64HZ 0x4 +#define BMA220_COF_32HZ 0x5 + #define BMA220_ACCEL_CHANNEL(index, reg, axis) { \ .type =3D IIO_ACCEL, \ .address =3D reg, \ .modified =3D 1, \ .channel2 =3D IIO_MOD_##axis, \ .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ + .info_mask_shared_by_type_available =3D BIT(IIO_CHAN_INFO_SCALE) |\ + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ .scan_index =3D index, \ .scan_type =3D { \ .sign =3D 's', \ @@ -172,6 +191,7 @@ struct bma220_data { struct device *dev; struct regmap *regmap; struct mutex lock; + u8 lpf_3db_freq_idx; u8 range_idx; struct iio_trigger *trig; struct { @@ -188,6 +208,18 @@ static const struct iio_chan_spec bma220_channels[] = =3D { IIO_CHAN_SOFT_TIMESTAMP(3), }; +/* + * Available cut-off frequencies of the low pass filter in Hz. + */ +static const int bma220_lpf_3db_freq_hz_table[][2] =3D { + [BMA220_COF_1000HZ] =3D {1000, 0}, + [BMA220_COF_500HZ] =3D {500, 0}, + [BMA220_COF_250HZ] =3D {250, 0}, + [BMA220_COF_125HZ] =3D {125, 0}, + [BMA220_COF_64HZ] =3D {64, 0}, + [BMA220_COF_32HZ] =3D {32, 0}, +}; + static const unsigned long bma220_accel_scan_masks[] =3D { BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z), 0 @@ -309,6 +341,11 @@ static int bma220_read_raw(struct iio_dev *indio_dev, *val =3D bma220_scale_table[index][0]; *val2 =3D bma220_scale_table[index][1]; return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + index =3D data->lpf_3db_freq_idx; + *val =3D bma220_lpf_3db_freq_hz_table[index][0]; + *val2 =3D bma220_lpf_3db_freq_hz_table[index][1]; + return IIO_VAL_INT_PLUS_MICRO; } return -EINVAL; @@ -353,6 +390,22 @@ static int bma220_write_raw(struct iio_dev *indio_dev, "failed to set measurement range\n"); data->range_idx =3D index; + return 0; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + index =3D bma220_find_match(bma220_lpf_3db_freq_hz_table, + ARRAY_SIZE(bma220_lpf_3db_freq_hz_table), + val, val2); + if (index < 0) + return -EINVAL; + + ret =3D regmap_update_bits(data->regmap, BMA220_REG_FILTER, + BMA220_FILTER_MASK, + FIELD_PREP(BMA220_FILTER_MASK, index)); + if (ret < 0) + dev_err(data->dev, + "failed to set low pass filter\n"); + data->lpf_3db_freq_idx =3D index; + return 0; } @@ -370,6 +423,11 @@ static int bma220_read_avail(struct iio_dev *indio_dev, *type =3D IIO_VAL_INT_PLUS_MICRO; *length =3D ARRAY_SIZE(bma220_scale_table) * 2; return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + *vals =3D (const int *)bma220_lpf_3db_freq_hz_table; + *type =3D IIO_VAL_INT_PLUS_MICRO; + *length =3D ARRAY_SIZE(bma220_lpf_3db_freq_hz_table) * 2; + return IIO_AVAIL_LIST; default: return -EINVAL; } -- 2.49.1 From nobody Fri Oct 3 11:22:52 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 E2D9526CE05; Mon, 1 Sep 2025 19:48:03 +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=1756756086; cv=none; b=E1pHC14Lh8L4ANODoTNwoiwZ+Fjeuaal517FBFwd/5RptLc3aGrhxwC5v9nYUtKuUPm9ZnEJ87NMwpgcgmSmmBgrkWPK6CSdjk+H01jqVIE1SBd4X0KzVl46DPxiHgwRC5mQTooMNF3whPMX6z4IcwtJXoG6m4dM8iCRYrA6Mdg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756756086; c=relaxed/simple; bh=cF3EvrApDf/cPk/HLyqyyg0xZlk+DVt3hkQn2VTPGa4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CBd1v/7fyKf6zDRSxfOU2koyjRFiCQ+IjXjh3eVrma8hZ2RyHVYop2f9E0Oh0g4ODsAO1qQNAObREWS45Aio5IiWbofDCWybDyCW6SOURv4z16Cb+iyf3gqw/WHs+PZe9/4jT+9FaR2b5S8a8U8yc98ouRwg/NoepRFhXkVorvE= 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=eXhQ/AvZ; 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="eXhQ/AvZ" Received: from localhost.localdomain (unknown [IPv6:2a02:2f0e:3503:4a00: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 E39E8173BEF; Mon, 01 Sep 2025 22:47:56 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=subdimension.ro; s=mail; t=1756756077; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0Ij4A38b6zGkOy+qUs09MDVVi9NjmgAjHdfoHDOqfCg=; b=eXhQ/AvZ6C8807FuuNscwNKQYTB+BVOVqQd/LxCmk6ASKDkDb+3rFLRT948d3EtuwMRG3k ZDdUYPLSerCvcvpVVn+gZcYtB452J1m1YbmYZ89p+l2XwNug+Ht6ukGM5MbLhCPKe5fyRl PWWOYWCSoeVVVxRbkk716ucUFGUhfIjkY+q4FRYucegEQj8aTQBktqsqSfZoR6JjJankbt ak8zhK1zg+MlrThdVLd5p7RPooqhSFN9eQARKvOytoAdjxFu2TseT7R35/DjcNT9jpOm1L Uo76f3KWe4r9tl9qHeHq8w+zoEdgHZZTVfxiMnYtTXmoPMnmJwJo/PnYbpruRQ== From: Petre Rodan To: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Petre Rodan , Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko Subject: [PATCH 07/10] iio: accel: BMA220 add debugfs reg access Date: Mon, 1 Sep 2025 22:47:33 +0300 Message-ID: <20250901194742.11599-8-petre.rodan@subdimension.ro> X-Mailer: git-send-email 2.49.1 In-Reply-To: <20250901194742.11599-1-petre.rodan@subdimension.ro> References: <20250901194742.11599-1-petre.rodan@subdimension.ro> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Allow read/write access to sensor registers for use in unit-tests. Signed-off-by: Petre Rodan --- drivers/iio/accel/bma220_core.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/iio/accel/bma220_core.c b/drivers/iio/accel/bma220_cor= e.c index e60acd62cf96..41889cdcef76 100644 --- a/drivers/iio/accel/bma220_core.c +++ b/drivers/iio/accel/bma220_core.c @@ -433,10 +433,21 @@ static int bma220_read_avail(struct iio_dev *indio_de= v, } } +static int bma220_reg_access(struct iio_dev *indio_dev, unsigned int reg, + unsigned int writeval, unsigned int *readval) +{ + struct bma220_data *data =3D iio_priv(indio_dev); + + if (readval) + return regmap_read(data->regmap, reg, readval); + return regmap_write(data->regmap, reg, writeval); +} + static const struct iio_info bma220_info =3D { .read_raw =3D bma220_read_raw, .write_raw =3D bma220_write_raw, .read_avail =3D bma220_read_avail, + .debugfs_reg_access =3D &bma220_reg_access, }; static int bma220_reset(struct bma220_data *data, bool up) -- 2.49.1 From nobody Fri Oct 3 11:22:52 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 E2E6726E6E3; Mon, 1 Sep 2025 19:48:03 +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=1756756086; cv=none; b=oKzyNsvBb+/+upcFOSSK1ZLZxzYiQ07JoetkTFbbmBR7wXUpd1s7IsdwpYCzpZlMth1ou0WqbXkU83OvZyyOpKCHSv5ehAESVKRYg+2DvuldR4ihBWbEttXgOXkqJz8Nj+v4oCB3Fhrbi1RzrV5XcU8xYf+eoF3BG5au0DjohoU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756756086; c=relaxed/simple; bh=SPTDnuWXlsl3c6JOcsuOtHHrw9B9ptG+74FIDORUjXQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZmLuLhXTuiVvDv1qZVaLq/TlhXNpHerCqTBWMiz8C3/OQHpf3fyR8NNmKe5suWiRxERSM5JsijebOjKAIkV2NPj6iqJuU9QlYRKTZfbbRPM/uKR9me4Hcq6gPKCv+wtzaRvTTZ8ITL8lrcsz+0JjUctG3T+JL44P2htA6ilH8+w= 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=VsOjxw5h; 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="VsOjxw5h" Received: from localhost.localdomain (unknown [IPv6:2a02:2f0e:3503:4a00: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 3238E173BF0; Mon, 01 Sep 2025 22:47:57 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=subdimension.ro; s=mail; t=1756756077; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CpOacFWMAeuverN5StFX9i0fstghOyKvYP+C9JNthCw=; b=VsOjxw5hWAPvfl75U7heUBGw9K2G7iY3+jk9cOAquCAAR35DAWKSlZd9LbdOQC5FUezS3J Raocoy42J+kyQIO3LtiQgs+0a5a8ENPYx/16ryw/7VlAM9MIptzJHF/0jyA58Lc3aDvKH5 44v7dYFgf2fsBDmJbU2abKJ1hus7MrSuIx4tRY3CKqB6BEqVDs067eSe2Oj152XzlZu0SR gyprOBOHQ8DJke3eY+VY23dXSvhyroIAUpC2otd5aRz5gP5fORaKmUfKIOTevrxhFBW+tM 9Xq/1Cb9Fbv94Ry2Dj1SBRRma1xY/euLeWWliqubEsmiBBlBPwcbVM3PnXyXjg== From: Petre Rodan To: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Petre Rodan , Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko Subject: [PATCH 08/10] iio: accel: BMA220 add events Date: Mon, 1 Sep 2025 22:47:34 +0300 Message-ID: <20250901194742.11599-9-petre.rodan@subdimension.ro> X-Mailer: git-send-email 2.49.1 In-Reply-To: <20250901194742.11599-1-petre.rodan@subdimension.ro> References: <20250901194742.11599-1-petre.rodan@subdimension.ro> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add events for tap detection and low-g, high-g, slope conditions. Ignored the 80-column rule for readability. Signed-off-by: Petre Rodan --- drivers/iio/accel/bma220_core.c | 686 ++++++++++++++++++++++++++++++++ 1 file changed, 686 insertions(+) diff --git a/drivers/iio/accel/bma220_core.c b/drivers/iio/accel/bma220_cor= e.c index 41889cdcef76..c8da6cc2eaf3 100644 --- a/drivers/iio/accel/bma220_core.c +++ b/drivers/iio/accel/bma220_core.c @@ -13,6 +13,37 @@ * scale (range) | in_accel_scale | see _avail= able * cut-off freq (filt_config)| in_accel_filter_low_pass_... | see _avail= able * -----------------------------------------------------------------------= ---- + * + * Events: + * Register | IIO ABI (sysfs) | valid v= alues + * --------------------------+-----------------------------------+--------= ---- + * high-g detection | | + * enable/disable irq | in_accel_*_thresh_rising_en | 0/1 + * threshold (high_th) | in_accel_thresh_rising_value | 0-15 + * hysteresis (high_hy) | in_accel_thresh_rising_hysteresis | 0-3 + * duration (high_dur) | in_accel_thresh_rising_period | 0-63 + * low-g detection | | + * enable/disable irq | in_accel_*_thresh_falling_en | 0/1 + * threshold (low_th) | in_accel_thresh_falling_value | 0-15 + * hysteresis (low_hy) | in_accel_thresh_falling_hysteresis| 0-3 + * duration (low_dur) | in_accel_thresh_falling_period | 0-63 + * slope detection | | + * enable/disable irq | in_accel_*_thresh_either_en | 0/1 + * threshold (slope_th) | in_accel_thresh_either_value | 0-15 + * duration (slope_dur) | in_accel_thresh_either_period | 0-3 + * tap sensing | | + * enable/disable singletap| in_accel_*_gesture_singletap_en | 0/1 [2] + * enable/disable doubletap| in_accel_*_gesture_doubletap_en | 0/1 [2] + * threshold (tt_th) | in_accel_gesture_singletap_value | 0-15 + * duration (tt_dur) | in_accel_gesture_doubletap_period | see [1] + * -----------------------------------------------------------------------= ----- + * + * [1] The event related sysfs interface provides and expects raw register= values + * (unshifted bitfields) based on the chip specifications. + * [2] Do not mix singletap and doubletap interrupt enable flags. + * + * To be on the safe side do not enable two or more concurrent interrupt e= vents + * of different types. */ #include @@ -151,6 +182,48 @@ #define BMA220_COF_64HZ 0x4 #define BMA220_COF_32HZ 0x5 +#define BMA220_TAP_TYPE_DOUBLE 0x0 +#define BMA220_TAP_TYPE_SINGLE 0x1 + +static const struct iio_event_spec bma220_events[] =3D { + { + .type =3D IIO_EV_TYPE_GESTURE, + .dir =3D IIO_EV_DIR_SINGLETAP, + .mask_separate =3D BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type =3D BIT(IIO_EV_INFO_VALUE) + }, + { + .type =3D IIO_EV_TYPE_GESTURE, + .dir =3D IIO_EV_DIR_DOUBLETAP, + .mask_separate =3D BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type =3D BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD), + }, + { + .type =3D IIO_EV_TYPE_THRESH, + .dir =3D IIO_EV_DIR_FALLING, + .mask_shared_by_type =3D BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD) | + BIT(IIO_EV_INFO_HYSTERESIS), + }, + { + .type =3D IIO_EV_TYPE_THRESH, + .dir =3D IIO_EV_DIR_RISING, + .mask_separate =3D BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type =3D BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD) | + BIT(IIO_EV_INFO_HYSTERESIS), + }, + { + .type =3D IIO_EV_TYPE_THRESH, + .dir =3D IIO_EV_DIR_EITHER, + .mask_separate =3D BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type =3D BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD), + }, +}; + #define BMA220_ACCEL_CHANNEL(index, reg, axis) { \ .type =3D IIO_ACCEL, \ .address =3D reg, \ @@ -162,6 +235,8 @@ .info_mask_shared_by_type_available =3D BIT(IIO_CHAN_INFO_SCALE) |\ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ .scan_index =3D index, \ + .event_spec =3D bma220_events, \ + .num_event_specs =3D ARRAY_SIZE(bma220_events), \ .scan_type =3D { \ .sign =3D 's', \ .realbits =3D 6, \ @@ -193,6 +268,7 @@ struct bma220_data { struct mutex lock; u8 lpf_3db_freq_idx; u8 range_idx; + u8 tap_type; struct iio_trigger *trig; struct { s8 chans[3]; @@ -299,6 +375,12 @@ static const struct iio_trigger_ops bma220_trigger_ops= =3D { .validate_device =3D &iio_trigger_validate_own_device, }; +static int bma220_reset_int(struct bma220_data *data) +{ + return regmap_update_bits(data->regmap, BMA220_REG_IE1, BMA220_INT_RST_MS= K, + FIELD_PREP(BMA220_INT_RST_MSK, 1)); +} + static irqreturn_t bma220_trigger_handler(int irq, void *p) { int ret; @@ -433,6 +515,564 @@ static int bma220_read_avail(struct iio_dev *indio_de= v, } } +static int bma220_is_tap_en(struct bma220_data *data, + enum iio_modifier axis, + int type, + bool *en) +{ + unsigned int reg_val, val; + int ret; + + ret =3D regmap_read(data->regmap, BMA220_REG_IE0, ®_val); + if (ret) + return ret; + + switch (axis) { + case IIO_MOD_X: + *en =3D FIELD_GET(BMA220_INT_EN_TAP_X_MSK, reg_val); + break; + case IIO_MOD_Y: + *en =3D FIELD_GET(BMA220_INT_EN_TAP_Y_MSK, reg_val); + break; + case IIO_MOD_Z: + *en =3D FIELD_GET(BMA220_INT_EN_TAP_Z_MSK, reg_val); + break; + default: + return -EINVAL; + } + + if (*en) { + ret =3D regmap_read(data->regmap, BMA220_REG_CONF5, ®_val); + if (ret) + return ret; + val =3D FIELD_GET(BMA220_TIP_EN_MSK, reg_val); + data->tap_type =3D val; +/* + * the tip_en reg_flag - if '1' it enables SingleTap, '0' DoubleTap + * truth table for the logic below, *en has to be switched to 0 in two cas= es: + * ST DT reg_val *en + * 1 0 0 (DT) 0 + * 1 0 1 (ST) 1 + * 0 1 0 (DT) 1 + * 0 1 1 (ST) 0 + */ + if ((type =3D=3D IIO_EV_DIR_DOUBLETAP) && val) + *en =3D false; + else if ((type =3D=3D IIO_EV_DIR_SINGLETAP) && !val) + *en =3D false; + } + + return 0; +} + +static int bma220_is_slope_en(struct bma220_data *data, + enum iio_modifier axis, + bool *en) +{ + unsigned int reg_val; + int ret; + + ret =3D regmap_read(data->regmap, BMA220_REG_IE0, ®_val); + if (ret) + return ret; + + switch (axis) { + case IIO_MOD_X: + *en =3D FIELD_GET(BMA220_INT_EN_SLOPE_X_MSK, reg_val); + break; + case IIO_MOD_Y: + *en =3D FIELD_GET(BMA220_INT_EN_SLOPE_Y_MSK, reg_val); + break; + case IIO_MOD_Z: + *en =3D FIELD_GET(BMA220_INT_EN_SLOPE_Z_MSK, reg_val); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int bma220_is_high_en(struct bma220_data *data, + enum iio_modifier axis, + bool *en) +{ + unsigned int reg_val; + int ret; + + ret =3D regmap_read(data->regmap, BMA220_REG_IE1, ®_val); + if (ret) + return ret; + + switch (axis) { + case IIO_MOD_X: + *en =3D FIELD_GET(BMA220_INT_EN_HIGH_X_MSK, reg_val); + break; + case IIO_MOD_Y: + *en =3D FIELD_GET(BMA220_INT_EN_HIGH_Y_MSK, reg_val); + break; + case IIO_MOD_Z: + *en =3D FIELD_GET(BMA220_INT_EN_HIGH_Z_MSK, reg_val); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int bma220_set_tap_en(struct bma220_data *data, + enum iio_modifier axis, + int type, + bool en) +{ + unsigned int flags =3D BMA220_TAP_TYPE_DOUBLE; + int ret; + + switch (axis) { + case IIO_MOD_X: + ret =3D regmap_update_bits(data->regmap, BMA220_REG_IE0, + BMA220_INT_EN_TAP_X_MSK, + FIELD_PREP(BMA220_INT_EN_TAP_X_MSK, en)); + break; + case IIO_MOD_Y: + ret =3D regmap_update_bits(data->regmap, BMA220_REG_IE0, + BMA220_INT_EN_TAP_Y_MSK, + FIELD_PREP(BMA220_INT_EN_TAP_Y_MSK, en)); + break; + case IIO_MOD_Z: + ret =3D regmap_update_bits(data->regmap, BMA220_REG_IE0, + BMA220_INT_EN_TAP_Z_MSK, + FIELD_PREP(BMA220_INT_EN_TAP_Z_MSK, en)); + break; + default: + return -EINVAL; + } + if (ret) + return ret; + + /* tip_en must be 1 to select singletap detection */ + if (type =3D=3D IIO_EV_DIR_SINGLETAP) + flags =3D BMA220_TAP_TYPE_SINGLE; + + ret =3D regmap_update_bits(data->regmap, BMA220_REG_CONF5, + BMA220_TIP_EN_MSK, + FIELD_PREP(BMA220_TIP_EN_MSK, flags)); + if (ret) + return ret; + + data->tap_type =3D flags; + + return 0; +} + +static int bma220_set_slope_en(struct bma220_data *data, + enum iio_modifier axis, + bool en) +{ + int ret; + + switch (axis) { + case IIO_MOD_X: + ret =3D regmap_update_bits(data->regmap, BMA220_REG_IE0, + BMA220_INT_EN_SLOPE_X_MSK, + FIELD_PREP(BMA220_INT_EN_SLOPE_X_MSK, en)); + break; + case IIO_MOD_Y: + ret =3D regmap_update_bits(data->regmap, BMA220_REG_IE0, + BMA220_INT_EN_SLOPE_Y_MSK, + FIELD_PREP(BMA220_INT_EN_SLOPE_Y_MSK, en)); + break; + case IIO_MOD_Z: + ret =3D regmap_update_bits(data->regmap, BMA220_REG_IE0, + BMA220_INT_EN_SLOPE_Z_MSK, + FIELD_PREP(BMA220_INT_EN_SLOPE_Z_MSK, en)); + break; + default: + return -EINVAL; + } + if (ret) + return ret; + + return 0; +} + +static int bma220_set_high_en(struct bma220_data *data, + enum iio_modifier axis, + bool en) +{ + int ret; + + switch (axis) { + case IIO_MOD_X: + ret =3D regmap_update_bits(data->regmap, BMA220_REG_IE1, + BMA220_INT_EN_HIGH_X_MSK, + FIELD_PREP(BMA220_INT_EN_HIGH_X_MSK, en)); + break; + case IIO_MOD_Y: + ret =3D regmap_update_bits(data->regmap, BMA220_REG_IE1, + BMA220_INT_EN_HIGH_Y_MSK, + FIELD_PREP(BMA220_INT_EN_HIGH_Y_MSK, en)); + break; + case IIO_MOD_Z: + ret =3D regmap_update_bits(data->regmap, BMA220_REG_IE1, + BMA220_INT_EN_HIGH_Z_MSK, + FIELD_PREP(BMA220_INT_EN_HIGH_Z_MSK, en)); + break; + default: + return -EINVAL; + } + if (ret) + return ret; + + return 0; +} + +// find out if the event is enabled +static int bma220_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct bma220_data *data =3D iio_priv(indio_dev); + bool int_en; + int ret; + unsigned int reg_val, val; + + guard(mutex)(&data->lock); + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (dir) { + case IIO_EV_DIR_SINGLETAP: + ret =3D bma220_is_tap_en(data, chan->channel2, + IIO_EV_DIR_SINGLETAP, &int_en); + if (ret) + return ret; + return int_en; + case IIO_EV_DIR_DOUBLETAP: + ret =3D bma220_is_tap_en(data, chan->channel2, + IIO_EV_DIR_DOUBLETAP, &int_en); + if (ret) + return ret; + return int_en; + default: + return -EINVAL; + } + case IIO_EV_TYPE_THRESH: + switch (dir) { + case IIO_EV_DIR_EITHER: + ret =3D bma220_is_slope_en(data, chan->channel2, &int_en); + if (ret) + return ret; + return int_en; + case IIO_EV_DIR_RISING: + ret =3D bma220_is_high_en(data, chan->channel2, &int_en); + if (ret) + return ret; + return int_en; + case IIO_EV_DIR_FALLING: + ret =3D regmap_read(data->regmap, BMA220_REG_IE1, + ®_val); + if (ret) + return ret; + val =3D FIELD_GET(BMA220_INT_EN_LOW_MSK, reg_val); + return val; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +// set if the event is enabled +static int bma220_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + bool state) +{ + struct bma220_data *data =3D iio_priv(indio_dev); + int ret =3D 0; + + guard(mutex)(&data->lock); + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (dir) { + case IIO_EV_DIR_SINGLETAP: + ret =3D bma220_set_tap_en(data, chan->channel2, + IIO_EV_DIR_SINGLETAP, state); + break; + case IIO_EV_DIR_DOUBLETAP: + ret =3D bma220_set_tap_en(data, chan->channel2, + IIO_EV_DIR_DOUBLETAP, state); + break; + default: + return -EINVAL; + } + break; + case IIO_EV_TYPE_THRESH: + switch (dir) { + case IIO_EV_DIR_EITHER: + ret =3D bma220_set_slope_en(data, chan->channel2, state); + break; + case IIO_EV_DIR_RISING: + ret =3D bma220_set_high_en(data, chan->channel2, state); + break; + case IIO_EV_DIR_FALLING: + ret =3D regmap_update_bits(data->regmap, BMA220_REG_IE1, + BMA220_INT_EN_LOW_MSK, + FIELD_PREP(BMA220_INT_EN_LOW_MSK, state)); + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + if (ret) + return ret; + + return bma220_reset_int(data); +} + +static int bma220_read_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + struct bma220_data *data =3D iio_priv(indio_dev); + unsigned int reg_val; + int ret; + + guard(mutex)(&data->lock); + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (info) { + case IIO_EV_INFO_VALUE: + ret =3D regmap_read(data->regmap, BMA220_REG_CONF3, ®_val); + *val =3D FIELD_GET(BMA220_TT_TH_MSK, reg_val); + break; + case IIO_EV_INFO_PERIOD: + ret =3D regmap_read(data->regmap, BMA220_REG_CONF3, ®_val); + *val =3D FIELD_GET(BMA220_TT_DUR_MSK, reg_val); + break; + default: + return -EINVAL; + } + break; + case IIO_EV_TYPE_THRESH: + switch (dir) { + case IIO_EV_DIR_EITHER: + switch (info) { + case IIO_EV_INFO_VALUE: + ret =3D regmap_read(data->regmap, BMA220_REG_CONF4, + ®_val); + *val =3D FIELD_GET(BMA220_SLOPE_TH_MSK, reg_val); + break; + case IIO_EV_INFO_PERIOD: + ret =3D regmap_read(data->regmap, BMA220_REG_CONF4, + ®_val); + *val =3D FIELD_GET(BMA220_SLOPE_DUR_MSK, reg_val); + break; + default: + return -EINVAL; + } + break; + case IIO_EV_DIR_RISING: + switch (info) { + case IIO_EV_INFO_VALUE: + ret =3D regmap_read(data->regmap, BMA220_REG_CONF1, + ®_val); + *val =3D FIELD_GET(BMA220_HIGH_TH_MSK, reg_val); + break; + case IIO_EV_INFO_PERIOD: + ret =3D regmap_read(data->regmap, BMA220_REG_CONF0, + ®_val); + *val =3D FIELD_GET(BMA220_HIGH_DUR_MSK, reg_val); + break; + case IIO_EV_INFO_HYSTERESIS: + ret =3D regmap_read(data->regmap, BMA220_REG_CONF0, + ®_val); + *val =3D FIELD_GET(BMA220_HIGH_HY_MSK, reg_val); + break; + default: + return -EINVAL; + } + break; + case IIO_EV_DIR_FALLING: + switch (info) { + case IIO_EV_INFO_VALUE: + ret =3D regmap_read(data->regmap, BMA220_REG_CONF1, + ®_val); + *val =3D FIELD_GET(BMA220_LOW_TH_MSK, reg_val); + break; + case IIO_EV_INFO_PERIOD: + ret =3D regmap_read(data->regmap, BMA220_REG_CONF2, + ®_val); + *val =3D FIELD_GET(BMA220_LOW_DUR_MSK, reg_val); + break; + case IIO_EV_INFO_HYSTERESIS: + ret =3D regmap_read(data->regmap, BMA220_REG_CONF2, + ®_val); + *val =3D FIELD_GET(BMA220_LOW_HY_MSK, reg_val); + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + if (ret) + return ret; + + return IIO_VAL_INT; +} + +static int bma220_write_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct bma220_data *data =3D iio_priv(indio_dev); + int ret; + + guard(mutex)(&data->lock); + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (info) { + case IIO_EV_INFO_VALUE: + if (!FIELD_FIT(BMA220_TT_TH_MSK, val)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, BMA220_REG_CONF3, + BMA220_TT_TH_MSK, + FIELD_PREP(BMA220_TT_TH_MSK, val)); + break; + case IIO_EV_INFO_PERIOD: + if (!FIELD_FIT(BMA220_TT_DUR_MSK, val)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, BMA220_REG_CONF3, + BMA220_TT_DUR_MSK, + FIELD_PREP(BMA220_TT_DUR_MSK, val)); + break; + default: + return -EINVAL; + } + break; + case IIO_EV_TYPE_THRESH: + switch (dir) { + case IIO_EV_DIR_EITHER: + switch (info) { + case IIO_EV_INFO_VALUE: + if (!FIELD_FIT(BMA220_SLOPE_TH_MSK, val)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, + BMA220_REG_CONF4, + BMA220_SLOPE_TH_MSK, + FIELD_PREP(BMA220_SLOPE_TH_MSK, val)); + break; + case IIO_EV_INFO_PERIOD: + if (!FIELD_FIT(BMA220_SLOPE_DUR_MSK, val)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, + BMA220_REG_CONF4, + BMA220_SLOPE_DUR_MSK, + FIELD_PREP(BMA220_SLOPE_DUR_MSK, val)); + break; + default: + return -EINVAL; + } + break; + case IIO_EV_DIR_RISING: + switch (info) { + case IIO_EV_INFO_VALUE: + if (!FIELD_FIT(BMA220_HIGH_TH_MSK, val)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, + BMA220_REG_CONF1, + BMA220_HIGH_TH_MSK, + FIELD_PREP(BMA220_HIGH_TH_MSK, val)); + break; + case IIO_EV_INFO_PERIOD: + if (!FIELD_FIT(BMA220_HIGH_DUR_MSK, val)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, + BMA220_REG_CONF0, + BMA220_HIGH_DUR_MSK, + FIELD_PREP(BMA220_HIGH_DUR_MSK, val)); + break; + case IIO_EV_INFO_HYSTERESIS: + if (!FIELD_FIT(BMA220_HIGH_HY_MSK, val)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, + BMA220_REG_CONF0, + BMA220_HIGH_HY_MSK, + FIELD_PREP(BMA220_HIGH_HY_MSK, val)); + break; + default: + return -EINVAL; + } + break; + case IIO_EV_DIR_FALLING: + switch (info) { + case IIO_EV_INFO_VALUE: + if (!FIELD_FIT(BMA220_LOW_TH_MSK, val)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, + BMA220_REG_CONF1, + BMA220_LOW_TH_MSK, + FIELD_PREP(BMA220_LOW_TH_MSK, val)); + break; + case IIO_EV_INFO_PERIOD: + if (!FIELD_FIT(BMA220_LOW_DUR_MSK, val)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, + BMA220_REG_CONF2, + BMA220_LOW_DUR_MSK, + FIELD_PREP(BMA220_LOW_DUR_MSK, val)); + break; + case IIO_EV_INFO_HYSTERESIS: + if (!FIELD_FIT(BMA220_LOW_HY_MSK, val)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, + BMA220_REG_CONF2, + BMA220_LOW_HY_MSK, + FIELD_PREP(BMA220_LOW_HY_MSK, val)); + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + if (ret) + return ret; + + return 0; +} + static int bma220_reg_access(struct iio_dev *indio_dev, unsigned int reg, unsigned int writeval, unsigned int *readval) { @@ -447,6 +1087,10 @@ static const struct iio_info bma220_info =3D { .read_raw =3D bma220_read_raw, .write_raw =3D bma220_write_raw, .read_avail =3D bma220_read_avail, + .read_event_config =3D bma220_read_event_config, + .write_event_config =3D bma220_write_event_config, + .read_event_value =3D bma220_read_event_value, + .write_event_value =3D bma220_write_event_value, .debugfs_reg_access =3D &bma220_reg_access, }; @@ -563,6 +1207,8 @@ static int bma220_init(struct bma220_data *data) } } + data->tap_type =3D BMA220_TAP_TYPE_DOUBLE; + return 0; } @@ -584,6 +1230,7 @@ static irqreturn_t bma220_irq_handler(int irq, void *p= rivate) struct bma220_data *data =3D iio_priv(indio_dev); int rv; u8 bma220_reg_if[2]; + s64 timestamp =3D iio_get_time_ns(indio_dev); guard(mutex)(&data->lock); rv =3D regmap_bulk_read(data->regmap, BMA220_REG_IF0, bma220_reg_if, @@ -596,6 +1243,45 @@ static irqreturn_t bma220_irq_handler(int irq, void *= private) goto done; } + if (FIELD_GET(BMA220_IF_HIGH, bma220_reg_if[1])) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_OR_Y_OR_Z, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + timestamp); + if (FIELD_GET(BMA220_IF_LOW, bma220_reg_if[1])) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_OR_Y_OR_Z, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + timestamp); + if (FIELD_GET(BMA220_IF_SLOPE, bma220_reg_if[1])) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_OR_Y_OR_Z, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_EITHER), + timestamp); + if (FIELD_GET(BMA220_IF_TT, bma220_reg_if[1])) { + + if (data->tap_type =3D=3D BMA220_TAP_TYPE_SINGLE) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_OR_Y_OR_Z, + IIO_EV_TYPE_GESTURE, + IIO_EV_DIR_SINGLETAP), + timestamp); + else + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_OR_Y_OR_Z, + IIO_EV_TYPE_GESTURE, + IIO_EV_DIR_DOUBLETAP), + timestamp); + } + done: return IRQ_HANDLED; -- 2.49.1 From nobody Fri Oct 3 11:22:52 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 E2E0326CE0C; Mon, 1 Sep 2025 19:48:03 +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=1756756086; cv=none; b=RqMG9VDfbvMbhqGZhytXot50LN8KY3kVErCND7GfVdXCF2xgIsgYNPTWUZafHrve/6OB/9nnJQw/lgofFygwp+YnsJSPr0Ow71X3rJ6xpWP4+/BK5D6gUUFUq179NxeZvB9EYMK1t8b2u/4C6dhGeCCE2dQEg12TPMXgy3ZKUp0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756756086; c=relaxed/simple; bh=K45IjixPrXgD03TC0E+tSKojr5KCH5C2CNhucTA/Dsc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=m4p+PKNbJql6szmKB03i0XdxD9k1qp8+BPQonTAwPv7f8t/NnZYd5aE2Q9GfskmombyjTNwZ5wOHPKFZvUbVoYdRhx6iIa95QIbLZPONNwUWzMVPo87ofgcU/+ykHFtyIIRYBJ6JNaLxfZTUia/gKBJKUwbvUBPYh4IW4GY7qFY= 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=h0X/8HKd; 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="h0X/8HKd" Received: from localhost.localdomain (unknown [IPv6:2a02:2f0e:3503:4a00: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 7A2C5173BF1; Mon, 01 Sep 2025 22:47:57 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=subdimension.ro; s=mail; t=1756756077; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eZYGiqF2skMc3RyZgs/wuMISopg/ogYPdjYAoGSQNbg=; b=h0X/8HKdBhkkt97nQ6MCm0X/FDXqLcZrWuLkIG0OIbYMqLhBTZDjMeOam45RiUL+a8w8Rv SnFtsPoxSEUcNOJOiA+O3nRxwwRNWmVOiKs8352+Tyn6o271Vs4Fh/p/IDNz0HN88Etyf2 rvy6ysWqQmi7Zav8Q2GvU97D5oQ8P4bES4C1GrurKpwlX+EjBCmJRk5leBUPGir0p3rXgQ SEZaPApx4TlTxNDq9x+Ldhz88P1ncwzONoAWudILzo0IiuxBkINVd3ZpKRQ8dNncbIed/s s/L7DhqAi1inVA8H2UxXMu932hzRD7sQT7aiXd1YK5x7ZuNCSTMZOhwvWOH4qA== From: Petre Rodan To: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Petre Rodan , Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko Subject: [PATCH 09/10] iio: accel: BMA220 add event attrs Date: Mon, 1 Sep 2025 22:47:35 +0300 Message-ID: <20250901194742.11599-10-petre.rodan@subdimension.ro> X-Mailer: git-send-email 2.49.1 In-Reply-To: <20250901194742.11599-1-petre.rodan@subdimension.ro> References: <20250901194742.11599-1-petre.rodan@subdimension.ro> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add event attributes not directly covered by the IIO API. Signed-off-by: Petre Rodan --- drivers/iio/accel/bma220_core.c | 178 +++++++++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 1 deletion(-) diff --git a/drivers/iio/accel/bma220_core.c b/drivers/iio/accel/bma220_cor= e.c index c8da6cc2eaf3..7a1064b408bb 100644 --- a/drivers/iio/accel/bma220_core.c +++ b/drivers/iio/accel/bma220_core.c @@ -31,11 +31,18 @@ * enable/disable irq | in_accel_*_thresh_either_en | 0/1 * threshold (slope_th) | in_accel_thresh_either_value | 0-15 * duration (slope_dur) | in_accel_thresh_either_period | 0-3 + * filter (slope_filt) | in_accel_slope_filt | 0/1 + * orientation | | + * mounting (orient_ex) | in_accel_orient_ex | 0/1 + * blocking | in_accel_orient_blocking | see [1] * tap sensing | | * enable/disable singletap| in_accel_*_gesture_singletap_en | 0/1 [2] * enable/disable doubletap| in_accel_*_gesture_doubletap_en | 0/1 [2] * threshold (tt_th) | in_accel_gesture_singletap_value | 0-15 * duration (tt_dur) | in_accel_gesture_doubletap_period | see [1] + * sample cnt (tt_samp) | in_accel_gesture_tap_sample_cnt | see [1] + * filter (tt_filt) | in_accel_gesture_tap_filt | 0/1 + * latch time (lat_int) | in_accel_latch_time | see [1] * -----------------------------------------------------------------------= ----- * * [1] The event related sysfs interface provides and expects raw register= values @@ -269,6 +276,7 @@ struct bma220_data { u8 lpf_3db_freq_idx; u8 range_idx; u8 tap_type; + bool irq_needs_clear_if; struct iio_trigger *trig; struct { s8 chans[3]; @@ -1083,7 +1091,167 @@ static int bma220_reg_access(struct iio_dev *indio_= dev, unsigned int reg, return regmap_write(data->regmap, reg, writeval); } +/* Event related attributes not directly covered by the IIO API */ +enum bma220_attributes { + BMA220_ATTR_TT_FILT, + BMA220_ATTR_TT_SAMP, + BMA220_ATTR_SLOPE_FILT, + BMA220_ATTR_ORIENT_EX, + BMA220_ATTR_ORIENT_BLOCKING, + BMA220_ATTR_LATCH_TIME, +}; + +static ssize_t event_attr_reg_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bma220_data *data =3D iio_priv(dev_to_iio_dev(dev)); + struct iio_dev_attr *iattr =3D to_iio_dev_attr(attr); + int ret =3D -EINVAL; + unsigned int reg_val, flags; + + guard(mutex)(&data->lock); + + switch (iattr->address) { + case BMA220_ATTR_TT_FILT: + ret =3D regmap_read(data->regmap, BMA220_REG_CONF3, ®_val); + flags =3D FIELD_GET(BMA220_TT_FILT_MSK, reg_val); + break; + case BMA220_ATTR_TT_SAMP: + ret =3D regmap_read(data->regmap, BMA220_REG_CONF5, ®_val); + flags =3D FIELD_GET(BMA220_TT_SAMP_MSK, reg_val); + break; + case BMA220_ATTR_SLOPE_FILT: + ret =3D regmap_read(data->regmap, BMA220_REG_CONF4, ®_val); + flags =3D FIELD_GET(BMA220_SLOPE_FILT_MSK, reg_val); + break; + case BMA220_ATTR_ORIENT_EX: + ret =3D regmap_read(data->regmap, BMA220_REG_CONF4, ®_val); + flags =3D FIELD_GET(BMA220_ORIENT_EX_MSK, reg_val); + break; + case BMA220_ATTR_ORIENT_BLOCKING: + ret =3D regmap_read(data->regmap, BMA220_REG_CONF5, ®_val); + flags =3D FIELD_GET(BMA220_ORIENT_BLOCKING_MSK, reg_val); + break; + case BMA220_ATTR_LATCH_TIME: + ret =3D regmap_read(data->regmap, BMA220_REG_IE1, ®_val); + flags =3D FIELD_GET(BMA220_INT_LATCH_MSK, reg_val); + break; + } + + if (ret) + return ret; + return sysfs_emit(buf, "%d\n", flags); +} + +static ssize_t event_attr_reg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct bma220_data *data =3D iio_priv(dev_to_iio_dev(dev)); + struct iio_dev_attr *iattr =3D to_iio_dev_attr(attr); + int ret =3D -EINVAL; + int value; + + if (kstrtoint(buf, 0, &value)) + return -EINVAL; + + guard(mutex)(&data->lock); + + switch (iattr->address) { + case BMA220_ATTR_TT_FILT: + if (!FIELD_FIT(BMA220_TT_FILT_MSK, value)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, BMA220_REG_CONF3, + BMA220_TT_FILT_MSK, + FIELD_PREP(BMA220_TT_FILT_MSK, value)); + break; + case BMA220_ATTR_TT_SAMP: + if (!FIELD_FIT(BMA220_TT_SAMP_MSK, value)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, BMA220_REG_CONF5, + BMA220_TT_SAMP_MSK, + FIELD_PREP(BMA220_TT_SAMP_MSK, value)); + break; + case BMA220_ATTR_SLOPE_FILT: + if (!FIELD_FIT(BMA220_SLOPE_FILT_MSK, value)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, BMA220_REG_CONF4, + BMA220_SLOPE_FILT_MSK, + FIELD_PREP(BMA220_SLOPE_FILT_MSK, value)); + break; + case BMA220_ATTR_ORIENT_EX: + if (!FIELD_FIT(BMA220_ORIENT_EX_MSK, value)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, BMA220_REG_CONF4, + BMA220_ORIENT_EX_MSK, + FIELD_PREP(BMA220_ORIENT_EX_MSK, value)); + break; + case BMA220_ATTR_ORIENT_BLOCKING: + if (!FIELD_FIT(BMA220_ORIENT_BLOCKING_MSK, value)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, BMA220_REG_CONF5, + BMA220_ORIENT_BLOCKING_MSK, + FIELD_PREP(BMA220_ORIENT_BLOCKING_MSK, + value)); + break; + case BMA220_ATTR_LATCH_TIME: + if (!FIELD_FIT(BMA220_INT_LATCH_MSK, value)) + return -EINVAL; + ret =3D regmap_update_bits(data->regmap, BMA220_REG_IE1, + BMA220_INT_LATCH_MSK, + FIELD_PREP(BMA220_INT_LATCH_MSK, value)); + if (value =3D=3D BMA220_INT_LATCH_MAX) + data->irq_needs_clear_if =3D true; + break; + } + + if (ret < 0) + return -EINVAL; + + return len; +} + +static IIO_DEVICE_ATTR(in_accel_gesture_tap_filt, 0644, + event_attr_reg_show, event_attr_reg_store, + BMA220_ATTR_TT_FILT); + +static IIO_DEVICE_ATTR(in_accel_gesture_tap_sample_cnt, 0644, + event_attr_reg_show, event_attr_reg_store, + BMA220_ATTR_TT_SAMP); + +static IIO_DEVICE_ATTR(in_accel_thresh_either_filt, 0644, + event_attr_reg_show, event_attr_reg_store, + BMA220_ATTR_SLOPE_FILT); + +static IIO_DEVICE_ATTR(in_accel_orient_ex, 0644, + event_attr_reg_show, event_attr_reg_store, + BMA220_ATTR_ORIENT_EX); + +static IIO_DEVICE_ATTR(in_accel_orient_blocking, 0644, + event_attr_reg_show, event_attr_reg_store, + BMA220_ATTR_ORIENT_BLOCKING); + +static IIO_DEVICE_ATTR(in_accel_latch_time, 0644, + event_attr_reg_show, event_attr_reg_store, + BMA220_ATTR_LATCH_TIME); + +static struct attribute *bma220_event_attributes[] =3D { + &iio_dev_attr_in_accel_gesture_tap_filt.dev_attr.attr, + &iio_dev_attr_in_accel_gesture_tap_sample_cnt.dev_attr.attr, + &iio_dev_attr_in_accel_thresh_either_filt.dev_attr.attr, + &iio_dev_attr_in_accel_orient_ex.dev_attr.attr, + &iio_dev_attr_in_accel_orient_blocking.dev_attr.attr, + &iio_dev_attr_in_accel_latch_time.dev_attr.attr, + NULL +}; + +static const struct attribute_group bma220_event_attribute_group =3D { + .attrs =3D bma220_event_attributes, +}; + static const struct iio_info bma220_info =3D { + .event_attrs =3D &bma220_event_attribute_group, .read_raw =3D bma220_read_raw, .write_raw =3D bma220_write_raw, .read_avail =3D bma220_read_avail, @@ -1207,6 +1375,7 @@ static int bma220_init(struct bma220_data *data) } } + data->irq_needs_clear_if =3D false; data->tap_type =3D BMA220_TAP_TYPE_DOUBLE; return 0; @@ -1228,7 +1397,7 @@ static irqreturn_t bma220_irq_handler(int irq, void *= private) { struct iio_dev *indio_dev =3D private; struct bma220_data *data =3D iio_priv(indio_dev); - int rv; + int rv, ret; u8 bma220_reg_if[2]; s64 timestamp =3D iio_get_time_ns(indio_dev); @@ -1283,6 +1452,13 @@ static irqreturn_t bma220_irq_handler(int irq, void = *private) } done: + if (data->irq_needs_clear_if) { + ret =3D bma220_reset_int(data); + if (ret) + dev_warn(data->dev, + "Failed to clear interrupt flag (%pe)\n", + ERR_PTR(ret)); + } return IRQ_HANDLED; } -- 2.49.1 From nobody Fri Oct 3 11:22:52 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 E2ED626E6FA; Mon, 1 Sep 2025 19:48:03 +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=1756756087; cv=none; b=TYSIXjGQba8PrxHVckGKamR09KvM7Z35qvCPjMNv/fWYAUdgJD6MnBOCmnRxk107ETin5aPqpLX/XU/Cw9+swxUwn/ktHvYr52WlzEV7qvqYqO5B2g39MOmbu122RMpCapd/j7wjeAjk+mxk7IreYSkmnyoO4h4XBxPbl9DYcDg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756756087; c=relaxed/simple; bh=MD4HCwUvfIvFN3UNE2WLqBZ2S3b0H6JiK7ZpEnzQ2RA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XXOZhrNNXjV12IbQp/rsaF/w4WpLD33XJLE20PU3cBO1vug2qJLk0TBL1dKzJ2gPVeJtkIfzOGa8WnOJr0gg6pmob2E2QHKRXDKfB8b6eQg89ve+VaXYcoJ1TeAlb7rHxjYUHa2ltgugPALpgkiWz8qz50Lm6+Ur0FBdoEffoMo= 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=2XRtVlFz; 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="2XRtVlFz" Received: from localhost.localdomain (unknown [IPv6:2a02:2f0e:3503:4a00: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 BDC4E173BF2; Mon, 01 Sep 2025 22:47:57 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=subdimension.ro; s=mail; t=1756756077; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=avicqrcP2k3aEOHhJaiNrVBkKGWsrB69WBiLZbLF7IY=; b=2XRtVlFzZ7FuwhCqcD1KJRDm5ckTeAgWiL3/Ts2qejB6t4QX6Nt28i3oQNr44d69+/beVB I3KcIkCI+Xgx3l9rRSgEtQMA9sES9ThYx0W9dC7AU0uvcX8ob8oJGqT9RHZ368FRQLGwb0 Kvl6HYTIz1r6J0DtteiVX6ur/g5z03qpmUnYOYbi9ZIwz5WCDO7vk2rrnFKRX+FVrCCq8v S26mo5X6e6iCaF7wpwRD7fEx4mKhYCleIGxAN12NowuY4FncZWAhy8angQ/v+DIdgB8lMV C9ehWfEm9zqgJPo7TIeCd2QTtKG4wLqvpIm36gzGzRhJYlLfzhu+CqdqnUkW2w== From: Petre Rodan To: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Petre Rodan , Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko Subject: [PATCH 10/10] iio: accel: BMA220 add maintainer Date: Mon, 1 Sep 2025 22:47:36 +0300 Message-ID: <20250901194742.11599-11-petre.rodan@subdimension.ro> X-Mailer: git-send-email 2.49.1 In-Reply-To: <20250901194742.11599-1-petre.rodan@subdimension.ro> References: <20250901194742.11599-1-petre.rodan@subdimension.ro> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add myself as maintainer of this driver. Signed-off-by: Petre Rodan --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index af1c8d2bfb3d..dd94505fb9a0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4402,6 +4402,13 @@ F: include/net/bond* F: include/uapi/linux/if_bonding.h F: tools/testing/selftests/drivers/net/bonding/ +BOSCH SENSORTEC BMA220 ACCELEROMETER IIO DRIVER +M: Petre Rodan +L: linux-iio@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/iio/accel/bosch,bma220.yaml +F: drivers/iio/accel/bma220* + BOSCH SENSORTEC BMA400 ACCELEROMETER IIO DRIVER M: Dan Robertson L: linux-iio@vger.kernel.org -- 2.49.1