From nobody Sat Jun 13 17:03:44 2026 Received: from mail-wm1-f49.google.com (mail-wm1-f49.google.com [209.85.128.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5F3743E92AD for ; Wed, 6 May 2026 09:43:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778060597; cv=none; b=OrypLzegAvrkr/8X1i0WZ621FemNLn+tA7eUCbpHLKmRkGuRs19TX+JMUp0S+ZZJhF5KrJ5xOHyPUS7dIhajYFqLdbNhbf9MRoottEx1ILLU3dgAuoMo4745he3rewg1kioRRg3mLhwUCDN1bnQukCUKYlMhNSoEaMLDqsXQ8bo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778060597; c=relaxed/simple; bh=ysOM9Kct8nbEr9b0Y1azVTfz0Lluey37G1xkKUL+RfQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Jjg3JyX5Ws4L6UsYqGoI0UyIcn0NYxs5MGu09aSB7WYf2lDcfFMkV4e633aitx2sj6fZGSk8XDQu1wvg9FSVFPBzpyIJ7pUg2XK6qG28PTyosgSk7ly/AZ16IZA6/ve95x758c9G+BEx/l6PZv0KMJ0fF6ntfIUvwMB1SQozUc4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=QQvcl61k; arc=none smtp.client-ip=209.85.128.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QQvcl61k" Received: by mail-wm1-f49.google.com with SMTP id 5b1f17b1804b1-48d146705b4so21943045e9.3 for ; Wed, 06 May 2026 02:43:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778060595; x=1778665395; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=AVJiSaUDY5cXEIWM3/OB6LtH3p4O/jWuhpWa5OWqcmE=; b=QQvcl61kDUbagQeronsGIKd5ueiPebTnFB17Ig2WWeBqQKrIVJDZL50vzhcJCjA15l M5x6cVjZFlV5ycaVGntvgN545uay3SZ9RpD5lz8605m3QiWBBJ95YHBB8hYYmUWqd89W Kp2EuQztYSpuX2nIW3bjhu3LhwgBG2jwmxUxyDFu2A3JzyXBr7TvxSMsEjAV470EJoWw J76tVfo2jVVRog+z5ceKndGmB0U/z/2JMyS9qeJV56xYNfrxBHjkA+/3MNyNa7CaiqID 7F+WBguqyOZwID0p/paw6/qr177ukJLXTZThxfkbqPnvvsJ+NtdZvBMJBwfvcqwgRYgL XdzQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778060595; x=1778665395; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=AVJiSaUDY5cXEIWM3/OB6LtH3p4O/jWuhpWa5OWqcmE=; b=Uv026f0KWkK7S8DtO9Y2Zm3r2XUOheWHX6WKVOT8NUB+x1wFkgg5X2VsYCiky8lSFo uXASu3vvpc1szK9LPkTv3PUte4E5pRAVzai2aiYunFVmSoKMa4FSAs3HH/53BnYYgWjr QNHa8PrkHsmbn1lLkIcUdIFwuMq4ABNMq6tUzJYMvbOXRHDH6E14O+5JH6KHhDOm4O57 qVW+dsoPo9a0G2Z6dXKq28JhgigURXr7fYymgo83SZkvAoI/Mn3YXJoYiNfOFXbCMIDL bzWxmXZmSReGGsJR6uNbkoW4oMkcs8BRcEIujHPkbZ18e6+H0QyVbdNmXtVMQ2yHBfQs 0lWA== X-Forwarded-Encrypted: i=1; AFNElJ9QSGnJEzQ8N7KrZdBwbIYHNMDNSd3KFQolhmmXRmeWdEzBMB+QlwVY6biWH8Z6j7Z8SOhxnlUcMpaQGbE=@vger.kernel.org X-Gm-Message-State: AOJu0YzvUxrouQV0Ichhv5/TFnFnTIvGGL3AWJcErvaD4I4EzCvfLPl6 RWxefpKC95oOVfCtLtAP2Tnu/x0eNofSkDy6h/iefQz8rGLEZD/3x7livy6Jbg== X-Gm-Gg: AeBDieuYDHECjlZSk5Jgi2VoPWMSUsVeiSGu3kwFQo+c+EUE6/SXxENm0a+CQ3xe8HF QnB0pOyLbjaPjSLCQQXn3BdYT1/aFIKT7y9HhsJSyE9NZfL9t6rFQAaVxDHQ0CmOJeKStz2B9sx /U26/8KqnUgOxo1trhPUliyCNTjPShcIvYawEGs/wzi+QVC2eYfe/1IQoG4X2jQdOdNEQqAejaK j4FLbtmNiTA9qL7TJ1dUtmS1ApY388DSlYz0nFnZHp04sUxSIU1NCnnAeMWFF5QyHrO3BnOrOVB 3w+8jEGb3mXK3HIgm7ZwyHhFNGK0SeLUG6/mOLKVaN7yobwB3+4ngwNkB7YuJQYdb93kS+bJQR7 K/q5NjcrTFid1SnYw//7VVH2BLiCkdYSL/8Afq5Y+QbUn0Pp+b9z47EQKcycIbxt8QvOPMMDXpH QXyTbJvW+cUvpnx1Gy0PZalfA5N2YxkqTyjL9/6cEJ54Yo4iQq1XzP/SWLAor0jSM= X-Received: by 2002:a05:600c:3b96:b0:48a:66a8:9981 with SMTP id 5b1f17b1804b1-48e51f55272mr49914355e9.27.1778060594746; Wed, 06 May 2026 02:43:14 -0700 (PDT) Received: from aldo-conte-t14.tailf68ad9.ts.net ([217.61.173.50]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-450524831cdsm12362230f8f.5.2026.05.06.02.43.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 May 2026 02:43:14 -0700 (PDT) From: Aldo Conte To: jic23@kernel.org Cc: dlechner@baylibre.com, nuno.sa@analog.com, andy@kernel.org, shuah@kernel.org, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kernel-mentees@lists.linux.dev Subject: [PATCH 1/3] iio: light: tcs3472: use devm for resource management Date: Wed, 6 May 2026 11:43:09 +0200 Message-ID: <20260506094311.222500-2-aldocontelk@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260506094311.222500-1-aldocontelk@gmail.com> References: <20260506094311.222500-1-aldocontelk@gmail.com> 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" Found by code inspection. Convert the driver to use device-managed resource allocation: - Add tcs3472_powerdown_action() and register it with devm_add_action_or_reset() to ensure the device is powered down on cleanup. Before this patch, the chip remained powered if probe failed after enabling it. - Replace iio_triggered_buffer_setup() with devm_iio_triggered_buffer_setup(). - Replace request_threaded_irq() with devm_request_threaded_irq(). - Replace iio_device_register() with devm_iio_device_register(). - Remove tcs3472_remove() as all cleanup is now handled by devm. Compiled with `make drivers/iio/light/tcs3472.o W=3D1`. Tested on Raspberry Pi 3B with TCS3472 (Adafruit breakout): Verified that RGBC channel reads return valid data and that ENABLE register is cleared to 0x00 on device removal. Signed-off-by: Aldo Conte --- drivers/iio/light/tcs3472.c | 85 ++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 49 deletions(-) diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c index 12429a3261b3..6d37a473c420 100644 --- a/drivers/iio/light/tcs3472.c +++ b/drivers/iio/light/tcs3472.c @@ -440,6 +440,28 @@ static const struct iio_info tcs3472_info =3D { .attrs =3D &tcs3472_attribute_group, }; =20 +static int tcs3472_powerdown(struct tcs3472_data *data) +{ + int ret; + u8 enable_mask =3D TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON; + + mutex_lock(&data->lock); + + ret =3D i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE, + data->enable & ~enable_mask); + if (!ret) + data->enable &=3D ~enable_mask; + + mutex_unlock(&data->lock); + + return ret; +} + +static void tcs3472_powerdown_action(void *data) +{ + tcs3472_powerdown(data); +} + static int tcs3472_probe(struct i2c_client *client) { struct tcs3472_data *data; @@ -510,61 +532,27 @@ static int tcs3472_probe(struct i2c_client *client) if (ret < 0) return ret; =20 - ret =3D iio_triggered_buffer_setup(indio_dev, NULL, - tcs3472_trigger_handler, NULL); + ret =3D devm_add_action_or_reset(&client->dev, + tcs3472_powerdown_action, data); + if (ret) + return ret; + + ret =3D devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL, + tcs3472_trigger_handler, NULL); if (ret < 0) return ret; =20 if (client->irq) { - ret =3D request_threaded_irq(client->irq, NULL, - tcs3472_event_handler, - IRQF_TRIGGER_FALLING | IRQF_SHARED | - IRQF_ONESHOT, - client->name, indio_dev); + ret =3D devm_request_threaded_irq(&client->dev, client->irq, + NULL, tcs3472_event_handler, + IRQF_TRIGGER_FALLING | IRQF_SHARED | + IRQF_ONESHOT, + client->name, indio_dev); if (ret) - goto buffer_cleanup; + return ret; } =20 - ret =3D iio_device_register(indio_dev); - if (ret < 0) - goto free_irq; - - return 0; - -free_irq: - if (client->irq) - free_irq(client->irq, indio_dev); -buffer_cleanup: - iio_triggered_buffer_cleanup(indio_dev); - return ret; -} - -static int tcs3472_powerdown(struct tcs3472_data *data) -{ - int ret; - u8 enable_mask =3D TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON; - - mutex_lock(&data->lock); - - ret =3D i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE, - data->enable & ~enable_mask); - if (!ret) - data->enable &=3D ~enable_mask; - - mutex_unlock(&data->lock); - - return ret; -} - -static void tcs3472_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev =3D i2c_get_clientdata(client); - - iio_device_unregister(indio_dev); - if (client->irq) - free_irq(client->irq, indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - tcs3472_powerdown(iio_priv(indio_dev)); + return devm_iio_device_register(&client->dev, indio_dev); } =20 static int tcs3472_suspend(struct device *dev) @@ -608,7 +596,6 @@ static struct i2c_driver tcs3472_driver =3D { .pm =3D pm_sleep_ptr(&tcs3472_pm_ops), }, .probe =3D tcs3472_probe, - .remove =3D tcs3472_remove, .id_table =3D tcs3472_id, }; module_i2c_driver(tcs3472_driver); --=20 2.54.0 From nobody Sat Jun 13 17:03:44 2026 Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F5C93E928E for ; Wed, 6 May 2026 09:43:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778060599; cv=none; b=XVasdvuN6Dze0FddoazYNcUE+Pp+L0MTzM/Tf8Z+STk6FJ0MMXlNzMoGPVxmCFKXZfWpGC8V51p+Yy5TEmvXpL7Ilu5crq80RqGyqrofXqpv3Y/82fx2fcEUw9VsE3sQBJN8DXly7iLxbXjHmsAszxPQtic0Ts2BMmA44d2kNgo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778060599; c=relaxed/simple; bh=K0ZzDlMSF/TZUll7GK0885r5ENR7KhCrSPg5rkH27bw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gl/bbCf40UbY8+hLj7HtSs9RYT57PVAEKFaFJS06O8HmwQgQU94V4kyiHlEqNMdKW1P4sksFAwfplIYZ4sku5BK48ZYoX2C8aFJyqBrTqIkmw625nj9WIYDS0XrPkychcxReSbNLWbWcVYiZWr/2s88DGmF4kDlV7uRiTSnI1cg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=rbwIcU+F; arc=none smtp.client-ip=209.85.221.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="rbwIcU+F" Received: by mail-wr1-f51.google.com with SMTP id ffacd0b85a97d-43fe608cb92so3661674f8f.2 for ; Wed, 06 May 2026 02:43:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778060596; x=1778665396; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fpIP3p3SfC47hlzL1+77n9qrEmTKSfZyEerx12Yk+Z4=; b=rbwIcU+FOhWc5SYCR8LGHhJYdoeyZDbB1+ZJrdsC1J52uxOwmJfxfDCsoXjus0nO3R Pw//dSTA9+njm3YYJ7nqsPVhX5c/0dQuRHC1kcVFlxvIwYXh3B3HM59bIFz1Bmr1XDrB qQmQX/1le/amsX22t1i9pkRJUyzaf2JKFC2aaFRpCakehpHe2Wj3tYXTtDTIGAvP0+Y9 lt0A3hA5rZvNVldcvErhXnk8COYd4wlgNmKzHieY3fwyNKREfkgjroYd3ZO70s6e9gQF GJ5QfrHmwE1GHnKHdVnDGDXers6wMvbMJhDnticVFCt376iHIFk5kH+KKOGULJQeQcgN F2/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778060596; x=1778665396; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=fpIP3p3SfC47hlzL1+77n9qrEmTKSfZyEerx12Yk+Z4=; b=eBg7WbLVy2pTde3W66MwfIuCENv0vb7G2JiV3Fr41ncMLJtvpKX1q5ZMmxRK2bf6zT Wn/1kDB2tx5R5jhtg9HPhWbuozgAsqaQMT9ObZv8juvLTjrXl1/nr79/V5Sjyr6h/P+j OKVzQo8vaZaJjDSveCdXXvs0WS2J7uXyI/9TDyRlzX8FDxfHhJoEXgACI4c29g6Zh4SC Uu+LfWu/BMyCh7LPkCrrFWGhzflZFfrUNGdhAhgWUjPfy8buvUzI+y2RDH67B+yqGESZ VlPdS/XA+eJn3G6/swRZdcD1aqrspHep2MfG6NTjO1HglXcsZVmOP2XNDadouoitbtye 4ugw== X-Forwarded-Encrypted: i=1; AFNElJ+l88P9xKE5nCvtxQIyMgvA17E0v0laEOFpfWLVs4HQhqfAyYVhGqoF5cMT1jYDeDwbjimP05pJlrqxt8o=@vger.kernel.org X-Gm-Message-State: AOJu0YyKqMjimyHjxdLX8j2oYpfDcsdO8gY+WajuWO5ZulRCjlMPHvlw aTJb9URJ2VdVpBf1nhhSMvkLDvSQRFrYCLs8NxCT95wgWq059l/K6nCC X-Gm-Gg: AeBDieuBJq2WVajMmuBNMbAzAXyVuo1SrUl6arrG5ddjmXBepSytDfo4auw/d/V4T+Z VG7kY74CuiGP1/HcL3pmKSMSIiFRc2LN+NMKk7aAdt8ZUpMMXhzy4M9Vm6OTiw1z3K/wDR5t7J0 uvBKi2sHMu+9dDjjEPM03NYHtqSXnqI8frDIomeMB9ykHqDQ3ZFFd9c9OI/av8QOzbmqOuUE+Cy A+HGTjqGA44B2L4jZM8diA7O7Mdh/GHyh2bmBRXnvmDuks2Ik4l5RzF39/BshF5v/YW8s6SO8mY TMJkB8xbXaDk2jacOhmlSpnTkWtAowKmoqYF1gQfy+ZwazEbHBKLdfU/Pf/+DuzjnHI/HddkYU8 CBZbKWSh2kBwYG363WSNJGlYqwk3AJPEePuYJ/y4JBtNmAVP3Q/uR/HRDsyWd+tDLjaV/ZQm8J9 kKdxGL20z9QvJ1FjLj8Qy+ufI0cBca8I3MRClbtcLvJKEpGrQYOH/SUVyjsAey8Zv7yKipHS0Zz g== X-Received: by 2002:a5d:5d89:0:b0:449:4079:4c39 with SMTP id ffacd0b85a97d-4515d5c5750mr4294374f8f.29.1778060595738; Wed, 06 May 2026 02:43:15 -0700 (PDT) Received: from aldo-conte-t14.tailf68ad9.ts.net ([217.61.173.50]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-450524831cdsm12362230f8f.5.2026.05.06.02.43.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 May 2026 02:43:15 -0700 (PDT) From: Aldo Conte To: jic23@kernel.org Cc: dlechner@baylibre.com, nuno.sa@analog.com, andy@kernel.org, shuah@kernel.org, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kernel-mentees@lists.linux.dev Subject: [PATCH 2/3] iio: light: tcs3472: implement wait time and sampling frequency Date: Wed, 6 May 2026 11:43:10 +0200 Message-ID: <20260506094311.222500-3-aldocontelk@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260506094311.222500-1-aldocontelk@gmail.com> References: <20260506094311.222500-1-aldocontelk@gmail.com> 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" The TCS3472 has a wait state controlled by the WEN bit in the ENABLE register and the WAIT register, with ad additional WLONG bit in CONFIG that if set multiplies the wait step by 12. The driver previously defined TCS3472_WTIME but never used it leaving the TODO comment on the top of the source file. Implement sampling frequency control via IIO_CHAN_INFO_SAMP_FREQ: - Reading sampling_frequancy computes the chip's actual cycle time as the sum of ATIME, RGBC initialization time (that is fixed) and the WAIT time that depends on WLONG and WEN bits. WEN is used to enable the chip to consider the WAIT state (without which it would proceed directly to the rgbc init state). - Writing sampling_frequency programs WTIME accordingly with current ATIME in order to obtain a cycle period that approximates as close as possible the requested frequency. - If the requested frequency is too low (and so the cycle is too large) the WLONG bit is asserted. - If the requested frequency is too high to be reached with a non-zero wait time, WEN is disabled so that wtime_us becomes 0 and conversions run back-to-back at the maximum rate accordingly with ATIME. - The user's last requested frequency is saved in the driver's private data in order to use it when a new integration time (ATIME) is requested: when ATIME changes, the wait time is recalculated to ensure that the previous requested frequency is ashered to as closely as possible. - The cycle time computation respects the WEN and WLONG for the evaluation of wtime_us. - Concurrent access to driver's private data into the tcs3472_set_sampling_freq function is protected by the guard(mutex). Tested on a Raspberry Pi 3B with a TCS3472 breakout at I2C address 0x29, by writing values to `sampling_frequency` and veifying the reported value via `cat sampling_frequency`, and checking that changing `integration_time` preserves the previusly requested sampling frequency. Signed-off-by: Aldo Conte --- drivers/iio/light/tcs3472.c | 171 ++++++++++++++++++++++++++++++++++-- 1 file changed, 162 insertions(+), 9 deletions(-) diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c index 6d37a473c420..de51eb61f42a 100644 --- a/drivers/iio/light/tcs3472.c +++ b/drivers/iio/light/tcs3472.c @@ -9,14 +9,14 @@ * TCS34727) * * Datasheet: http://ams.com/eng/content/download/319364/1117183/file/TCS3= 472_Datasheet_EN_v2.pdf - * - * TODO: wait time */ =20 #include #include #include #include +#include +#include =20 #include #include @@ -51,9 +51,11 @@ #define TCS3472_STATUS_AINT BIT(4) #define TCS3472_STATUS_AVALID BIT(0) #define TCS3472_ENABLE_AIEN BIT(4) +#define TCS3472_ENABLE_WEN BIT(3) #define TCS3472_ENABLE_AEN BIT(1) #define TCS3472_ENABLE_PON BIT(0) #define TCS3472_CONTROL_AGAIN_MASK (BIT(0) | BIT(1)) +#define TCS3472_CONFIG_WLONG BIT(1) =20 struct tcs3472_data { struct i2c_client *client; @@ -64,6 +66,10 @@ struct tcs3472_data { u8 control; u8 atime; u8 apers; + u8 wtime; + bool wlong; + int target_freq_hz; + int target_freq_uhz; }; =20 static const struct iio_event_spec tcs3472_events[] =3D { @@ -89,6 +95,7 @@ static const struct iio_event_spec tcs3472_events[] =3D { .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_CALIBSCALE) | \ BIT(IIO_CHAN_INFO_INT_TIME), \ + .info_mask_shared_by_all =3D BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .channel2 =3D IIO_MOD_LIGHT_##_color, \ .address =3D _addr, \ .scan_index =3D _si, \ @@ -112,6 +119,22 @@ static const struct iio_chan_spec tcs3472_channels[] = =3D { IIO_CHAN_SOFT_TIMESTAMP(4), }; =20 +static unsigned int tcs3472_cycle_time_us(struct tcs3472_data *data) +{ + unsigned int atime_us =3D (256 - data->atime) * 2400; + unsigned int init_us =3D 2400; + unsigned int wtime_us; + + if (!(data->enable & TCS3472_ENABLE_WEN)) + wtime_us =3D 0; + else if (data->wlong) + wtime_us =3D (256 - data->wtime) * 28800; + else + wtime_us =3D (256 - data->wtime) * 2400; + + return wtime_us + init_us + atime_us; +} + static int tcs3472_req_data(struct tcs3472_data *data) { int tries =3D 50; @@ -164,16 +187,118 @@ static int tcs3472_read_raw(struct iio_dev *indio_de= v, *val =3D 0; *val2 =3D (256 - data->atime) * 2400; return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SAMP_FREQ: { + unsigned int cycle_us =3D tcs3472_cycle_time_us(data); + + *val =3D USEC_PER_SEC / cycle_us; + *val2 =3D (u64)(USEC_PER_SEC % cycle_us) * USEC_PER_SEC / cycle_us; + return IIO_VAL_INT_PLUS_MICRO; + } } return -EINVAL; } =20 +static int tcs3472_set_sampling_freq(struct tcs3472_data *data, + int val, int val2) +{ + unsigned int atime_us =3D (256 - data->atime) * 2400; + unsigned int init_us =3D 2400; + u64 cycle_us; + s64 wait_us; + int wtime; + bool wlong =3D false; + int ret; + + if (val < 0 || (val =3D=3D 0 && val2 <=3D 0)) + return -EINVAL; + + guard(mutex)(&data->lock); + + cycle_us =3D div_u64((u64)USEC_PER_SEC * USEC_PER_SEC, + (u64)val * USEC_PER_SEC + val2); + + wait_us =3D (s64)cycle_us - init_us - atime_us; + + /* Wait state is not needed. + * Requested frequency is too high to be reached with any + * non-zero wait time. Disable WEN so the chip runs at the + * maximum rate allowed by ATIME alone. + */ + if (wait_us < 2400) { + if (data->enable & TCS3472_ENABLE_WEN) { + data->enable &=3D ~TCS3472_ENABLE_WEN; + ret =3D i2c_smbus_write_byte_data(data->client, + TCS3472_ENABLE, + data->enable); + if (ret < 0) + return ret; + } + + data->target_freq_hz =3D val; + data->target_freq_uhz =3D val2; + return 0; + } + + /* + * Wait state is needed: make sure WEN is active before + * programming WTIME (and possibly WLONG). + */ + if (!(data->enable & TCS3472_ENABLE_WEN)) { + data->enable |=3D TCS3472_ENABLE_WEN; + ret =3D i2c_smbus_write_byte_data(data->client, + TCS3472_ENABLE, + data->enable); + if (ret < 0) + return ret; + } + + wtime =3D 256 - (int)DIV_ROUND_CLOSEST((unsigned long)wait_us, 2400); + if (wtime < 0) { + wlong =3D true; + wtime =3D 256 - (int)DIV_ROUND_CLOSEST((unsigned long)wait_us, + 28800); + if (wtime < 0) + wtime =3D 0; + } + if (wtime > 255) + wtime =3D 255; + + if (wlong !=3D data->wlong) { + ret =3D i2c_smbus_read_byte_data(data->client, TCS3472_CONFIG); + if (ret < 0) + return ret; + + if (wlong) + ret |=3D TCS3472_CONFIG_WLONG; + else + ret &=3D ~TCS3472_CONFIG_WLONG; + + ret =3D i2c_smbus_write_byte_data(data->client, + TCS3472_CONFIG, ret); + if (ret < 0) + return ret; + + data->wlong =3D wlong; + } + + ret =3D i2c_smbus_write_byte_data(data->client, TCS3472_WTIME, wtime); + if (ret < 0) + return ret; + + data->wtime =3D wtime; + data->target_freq_hz =3D val; + data->target_freq_uhz =3D val2; + + return 0; +} + static int tcs3472_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { struct tcs3472_data *data =3D iio_priv(indio_dev); int i; + int ret; =20 switch (mask) { case IIO_CHAN_INFO_CALIBSCALE: @@ -195,13 +320,22 @@ static int tcs3472_write_raw(struct iio_dev *indio_de= v, for (i =3D 0; i < 256; i++) { if (val2 =3D=3D (256 - i) * 2400) { data->atime =3D i; - return i2c_smbus_write_byte_data( - data->client, TCS3472_ATIME, - data->atime); + ret =3D i2c_smbus_write_byte_data(data->client, + TCS3472_ATIME, + data->atime); + if (ret < 0) + return ret; + /* since ATIME has changed, recalculate + * WTIME to maintain sampling freq + */ + return tcs3472_set_sampling_freq(data, + data->target_freq_hz, + data->target_freq_uhz); } - } return -EINVAL; + case IIO_CHAN_INFO_SAMP_FREQ: + return tcs3472_set_sampling_freq(data, val, val2); } return -EINVAL; } @@ -443,7 +577,8 @@ static const struct iio_info tcs3472_info =3D { static int tcs3472_powerdown(struct tcs3472_data *data) { int ret; - u8 enable_mask =3D TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON; + u8 enable_mask =3D TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON | + TCS3472_ENABLE_WEN; =20 mutex_lock(&data->lock); =20 @@ -466,6 +601,7 @@ static int tcs3472_probe(struct i2c_client *client) { struct tcs3472_data *data; struct iio_dev *indio_dev; + unsigned int cycle_us; int ret; =20 indio_dev =3D devm_iio_device_alloc(&client->dev, sizeof(*data)); @@ -504,6 +640,16 @@ static int tcs3472_probe(struct i2c_client *client) return ret; data->atime =3D ret; =20 + ret =3D i2c_smbus_read_byte_data(data->client, TCS3472_WTIME); + if (ret < 0) + return ret; + data->wtime =3D ret; + + ret =3D i2c_smbus_read_byte_data(data->client, TCS3472_CONFIG); + if (ret < 0) + return ret; + data->wlong =3D ret & TCS3472_CONFIG_WLONG; + ret =3D i2c_smbus_read_word_data(data->client, TCS3472_AILT); if (ret < 0) return ret; @@ -525,13 +671,19 @@ static int tcs3472_probe(struct i2c_client *client) return ret; =20 /* enable device */ - data->enable =3D ret | TCS3472_ENABLE_PON | TCS3472_ENABLE_AEN; + data->enable =3D ret | TCS3472_ENABLE_PON | TCS3472_ENABLE_AEN | + TCS3472_ENABLE_WEN; data->enable &=3D ~TCS3472_ENABLE_AIEN; ret =3D i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE, data->enable); if (ret < 0) return ret; =20 + cycle_us =3D tcs3472_cycle_time_us(data); + data->target_freq_hz =3D USEC_PER_SEC / cycle_us; + data->target_freq_uhz =3D (u64)(USEC_PER_SEC % cycle_us) * + USEC_PER_SEC / cycle_us; + ret =3D devm_add_action_or_reset(&client->dev, tcs3472_powerdown_action, data); if (ret) @@ -567,7 +719,8 @@ static int tcs3472_resume(struct device *dev) struct tcs3472_data *data =3D iio_priv(i2c_get_clientdata( to_i2c_client(dev))); int ret; - u8 enable_mask =3D TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON; + u8 enable_mask =3D TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON | + TCS3472_ENABLE_WEN; =20 mutex_lock(&data->lock); =20 --=20 2.54.0 From nobody Sat Jun 13 17:03:44 2026 Received: from mail-wm1-f52.google.com (mail-wm1-f52.google.com [209.85.128.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9176F3E9F8D for ; Wed, 6 May 2026 09:43:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778060600; cv=none; b=jsey8eG0FOXWaOamHmFHTiJaIMr5sQdq2XlW595eGjLViU7Z6cCF+qTMzI5MczeQ+TLVJLx1cPDB645U3mlMEtRySR8xSR5QFn7Z3nqJft8t6OZzP8jtr0wwBjutwGX4inG5H5rCE7tXO8jo9L63GxKtwQ3vTtUnDIjVN+9/4S8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778060600; c=relaxed/simple; bh=2+rjlZIRA63grEnrCctTTX55LWNNJVSjsZdCutZlPVk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MsVVS+rE8vHVEWbeusWtjrWYYMu81he/TaASZ5Imll4ajquBBH5EV6T3brLbiZmnG/6EIMyBjhc85zhfGu8dzD4A9aPL8931nrZAZYEZpOYMK+vfRH1XaTz2Lxwi8tCAYnNfIfnOsmrsK44RENTEI8ToYSJgNlAwGSyTgU0PjIU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=GGLOgrfe; arc=none smtp.client-ip=209.85.128.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="GGLOgrfe" Received: by mail-wm1-f52.google.com with SMTP id 5b1f17b1804b1-488a9033b2cso55062545e9.2 for ; Wed, 06 May 2026 02:43:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778060597; x=1778665397; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=//fZv9m4aqiXRdm3cWQw41INGXka3X8pR0Na3eJTV1Y=; b=GGLOgrfeIQ7nEaRWqNEYSUWe40e/uYKDrgFj/6QGLqhcmq1e0kRkx10AChI3JlyY3Q MTINxRWLMQukBPG5t18olNklFOVuzYkUM5OO8sg0hwci6hOFhY1WmsoKQ0+19G8pDZIh RoDtSOGWMF/bNFlc9zwgmONRwoi9myIzXjERLV9nDKFDvuzFZtZ5AQYKKkh1FcYjbNS+ mOmDGHFfEWTy9jgMDYGYWksGqmQ6cvtYcqWm1ZwTjCIS+ydCy3XfgovlKTziL/3D+zzg KqyWjaWarZ59VvA/hVzIWd6nwcAKX7plB5+6R8VuKReFnfkJBy/LoT9by+Con8He676j +DvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778060597; x=1778665397; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=//fZv9m4aqiXRdm3cWQw41INGXka3X8pR0Na3eJTV1Y=; b=dxGM3C+wnHGbheH4RBOMjc6V09KovdNG6v0Klk+0vOlhQWn4ZoE6gbtpCoMea2e89U wfoso3qWlr229LEsq20jpITUKhaguQ7AZmyC+aiKnnO/0PPZjfBgeRbHvOu90XP+BYyo rlS79mR1F2w5UEOKMpFbXbdUZbsrurGTHlMcl5aMn5vcRsUr3HkQZ28u9g/6RurPJ8NG wvGXVy3KiCB9QaoxK2Lv6ZFQ4CBPpMYyQZV1ulZXOHelYqsjaAtW7G9R7k2vrC25juR/ AGFzXl0pYYwEFXDi8tP/rQgKdY1xHl71++4wDHm4rY9BnSWiBcHBs2isWczTqXBTcFPm y/Lw== X-Forwarded-Encrypted: i=1; AFNElJ+0hSCvztXohNJtCMqd26TlInanV2+DzswVwVdrD4F+B0f30tnjk0NVe9u3oHs+ORWmbNJ9hF3I6iP/uuY=@vger.kernel.org X-Gm-Message-State: AOJu0Yx2ocHiegNuTTb+7VM/tYXIhDlbrrF7k0j5zNsiHpW2+JtBfWSX 51DC9DL5bxxY2FjOZVoo9+vOWfgHJAgX4Plzy/oyy7JQPiE97NKbddZC X-Gm-Gg: AeBDievbX/1K7iXdowAUKa1mhpLP6g8ZFoV+ZN26A2AvWfdK4Mvnvu32Z1jE0Dbj0Gl XYsLwXE4IxrtpinZwwP3hwWQSZ1VoIAebT2YgEly+4Jsq1dA4a2zW7YVs5yPUZfcGdDPpKZtB3X jjE1j0mQ7eM1SjY8EWcCm5MbOcLhUhAYuOow3C2m3rgv/q8pLnq5v83gqFit2UQs2b9E2YqhubV 1iC5bhRhdMG5fBLfwsmeROWYspYdhMxAbUaGUZIlrD2U0H/BSvgV9nqCS8bzAdzS8utWALkGQA+ s7T1tO80eCAS7IyN/OlBj4BXviOiaAMi8WOamLP8mBgCp2c8SPhZxDio8s6eXYh4sFIcFTtRMvZ 3D2jXAn63Y1KThNBkrn8jH7MPur+CfCLNRigG84q0ZNd3Qgv2JyORa2jdKv+0cKW+hj6bL3CTH9 hts8fm3ZPZSQNGPZqhZqGnaxgVhOXA+tDH+xjmBw6fco3/fvQsKZmahpSF/kaiCj/x3gEsiLcPy A== X-Received: by 2002:a05:600c:2e0c:b0:489:1c2d:211e with SMTP id 5b1f17b1804b1-48e51e0c833mr27253085e9.5.1778060596883; Wed, 06 May 2026 02:43:16 -0700 (PDT) Received: from aldo-conte-t14.tailf68ad9.ts.net ([217.61.173.50]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-450524831cdsm12362230f8f.5.2026.05.06.02.43.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 May 2026 02:43:16 -0700 (PDT) From: Aldo Conte To: jic23@kernel.org Cc: dlechner@baylibre.com, nuno.sa@analog.com, andy@kernel.org, shuah@kernel.org, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kernel-mentees@lists.linux.dev Subject: [PATCH 3/3] iio: light: tcs3472: Use guard(mutex)() family over manual locking Date: Wed, 6 May 2026 11:43:11 +0200 Message-ID: <20260506094311.222500-4-aldocontelk@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260506094311.222500-1-aldocontelk@gmail.com> References: <20260506094311.222500-1-aldocontelk@gmail.com> 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" Convert tcs3472_read_event_config, tcs3472_write_event_config, tcs3472_write_event, tcs3472_powerdown and tcs3472_resume to use automatico cleanup with guard(mutex)() instead of the old manual locking method. Found by code inspection. Tested on a Raspberry Pi 3B with a TCS34725 at 0x29 address. The following fields were read and written without any issues: sampling_frequency, integration_time, calibscale and the threshold event interface. The unload of the driver works cleanly. Signed-off-by: Aldo Conte --- drivers/iio/light/tcs3472.c | 39 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c index de51eb61f42a..90552f47a373 100644 --- a/drivers/iio/light/tcs3472.c +++ b/drivers/iio/light/tcs3472.c @@ -393,7 +393,7 @@ static int tcs3472_write_event(struct iio_dev *indio_de= v, int period; int i; =20 - mutex_lock(&data->lock); + guard(mutex)(&data->lock); switch (info) { case IIO_EV_INFO_VALUE: switch (dir) { @@ -404,18 +404,17 @@ static int tcs3472_write_event(struct iio_dev *indio_= dev, command =3D TCS3472_AILT; break; default: - ret =3D -EINVAL; - goto error; + return -EINVAL; } ret =3D i2c_smbus_write_word_data(data->client, command, val); if (ret) - goto error; + return ret; =20 if (dir =3D=3D IIO_EV_DIR_RISING) data->high_thresh =3D val; else data->low_thresh =3D val; - break; + return 0; case IIO_EV_INFO_PERIOD: period =3D val * USEC_PER_SEC + val2; for (i =3D 1; i < ARRAY_SIZE(tcs3472_intr_pers) - 1; i++) { @@ -425,18 +424,13 @@ static int tcs3472_write_event(struct iio_dev *indio_= dev, } ret =3D i2c_smbus_write_byte_data(data->client, TCS3472_PERS, i); if (ret) - goto error; + return ret; =20 data->apers =3D i; - break; + return 0; default: - ret =3D -EINVAL; - break; + return -EINVAL; } -error: - mutex_unlock(&data->lock); - - return ret; } =20 static int tcs3472_read_event_config(struct iio_dev *indio_dev, @@ -444,13 +438,9 @@ static int tcs3472_read_event_config(struct iio_dev *i= ndio_dev, enum iio_event_direction dir) { struct tcs3472_data *data =3D iio_priv(indio_dev); - int ret; =20 - mutex_lock(&data->lock); - ret =3D !!(data->enable & TCS3472_ENABLE_AIEN); - mutex_unlock(&data->lock); - - return ret; + guard(mutex)(&data->lock); + return !!(data->enable & TCS3472_ENABLE_AIEN); } =20 static int tcs3472_write_event_config(struct iio_dev *indio_dev, @@ -461,7 +451,7 @@ static int tcs3472_write_event_config(struct iio_dev *i= ndio_dev, int ret =3D 0; u8 enable_old; =20 - mutex_lock(&data->lock); + guard(mutex)(&data->lock); =20 enable_old =3D data->enable; =20 @@ -476,7 +466,6 @@ static int tcs3472_write_event_config(struct iio_dev *i= ndio_dev, if (ret) data->enable =3D enable_old; } - mutex_unlock(&data->lock); =20 return ret; } @@ -580,15 +569,13 @@ static int tcs3472_powerdown(struct tcs3472_data *dat= a) u8 enable_mask =3D TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON | TCS3472_ENABLE_WEN; =20 - mutex_lock(&data->lock); + guard(mutex)(&data->lock); =20 ret =3D i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE, data->enable & ~enable_mask); if (!ret) data->enable &=3D ~enable_mask; =20 - mutex_unlock(&data->lock); - return ret; } =20 @@ -722,15 +709,13 @@ static int tcs3472_resume(struct device *dev) u8 enable_mask =3D TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON | TCS3472_ENABLE_WEN; =20 - mutex_lock(&data->lock); + guard(mutex)(&data->lock); =20 ret =3D i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE, data->enable | enable_mask); if (!ret) data->enable |=3D enable_mask; =20 - mutex_unlock(&data->lock); - return ret; } =20 --=20 2.54.0