From nobody Fri Sep 25 12:03:19 2026 Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.46]) (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 20554392836 for ; Sun, 13 Sep 2026 12:18:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789301926; cv=none; b=XirUytvbcp8DnA/lzvP6IxVFlXphNMnj+aOLIzUcVUijwP8tw5Bzc9wx3F+CHIJqbNcO/Tdcwy5MpTgSmFq3/JEYT61ed+IVw8CwcnF7QhlBcj+uefD6W21s3S3n8O6wJjyk+P7t8uQ4nhRXtSU7ylxVOfgNfT1Rl5uLdBoL/cE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789301926; c=relaxed/simple; bh=koUYc8Dq9lWw1oLPJynOIZpYM8lkDBbSyMSmWAIup4w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LlUoFjjjscjPVWrOqnyltqLZM55pIFhAxeG6McHT+B3dkNptPL1RuZuYGNBLzI0KSSLcATaYDlfUoRPdTA/4AS2Rmr8LFw7/C5INZUND8tXE3POsS5Grk37Nr5kk0uPlxfVxbAXNahiMyqwDqgcCkrOu/JDCE4AbbsNDnts1tUw= 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=YCG5d3Oz; arc=none smtp.client-ip=209.85.221.46 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="YCG5d3Oz" Received: by mail-wr1-f46.google.com with SMTP id ffacd0b85a97d-47de0093c42so2300682f8f.3 for ; Sun, 13 Sep 2026 05:18:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789301921; x=1789906721; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=rw9tIl3/QFpv/y5nx3+oqZIVRAfzeLzBB+R0xa6GvSg=; b=YCG5d3OzyGdCUlesuTMbJTKpy6QCIn7v0+w8PR0TyRyV/+RCZMuknh1n48vNOwznRs HpQixigQcvNH/aIH7T+PHhuFMFZ3Yb/GNDoHMYvQ4kzIP2NC/3rhXc4s/dtnDncIPAMt MaVDRsWeZENTLXFaw6zt+u09TVmdEC73h2W5EUOU7Uz1V0bLrwnHdkcd8/PNk+6byvDh uWi9q2xba0nAZIhZeb2AiPGEduQ2/oHnUhupgqkI6mWh2G4Tr9sMsL+3V1XKGm2XzgDa zWGZLOGS+bWyZreDYhNNA5w8mOqcqcCym1jpZ3rAdeQwCEcjy51jgrkXoI41SJ+KD0nA veuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789301921; x=1789906721; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=rw9tIl3/QFpv/y5nx3+oqZIVRAfzeLzBB+R0xa6GvSg=; b=e85vI3EaHe8fygfZ86rTesnlwlrr6HAXEljaRdbaPPiNGchSO2OuhFwE0hWwrXuTZI njH+wJA1cj1Ij0do+GXJpg6qahUdgoBv2xUSrYX9vB/7uIp1W9NHC1pHgorxFQXqO5cO WXeddjxK3al4GlID0Hg964LxDfUgpFwNk6RgPUpfCXo83cPSkSg4blH6Z9E0aWxItPdj omy49IClbcY2Vt0SR3vyUNIlie9NjO8/yBISSPperpj0I7F/ArvIJgGcmflTTEQTLBo7 goqINy1Bl4V+XmDtM8EShw0j0ZvHqRcc8URvXxlwUi+lwlu9/1RbIPRzlOmR0PN68kM3 j1kQ== X-Forwarded-Encrypted: i=1; AKwUvBx7aCj5EvFbTou66vPQrOnuR0tAkivtsGHF5bN2KN5dwoKWZ01i7eSbSZzOpK/6iHoLxdyvT9CcBAthheI=@vger.kernel.org X-Gm-Message-State: AFuF++kguhI42ebnATRyYL7H073gqt7ytTz+bPtc+Ku1AhECH7b/9d0n hI/F128MctIYxQ5gcih1VLG0a2+fhJXwddixoR95CrX52ez8KF7bA7kS X-Gm-Gg: AYBFou3NQFJ8QcF1Y4SMQy3hBxvSs5z5A+/ZxqrXbna/kPHik4LhlRilY4ZUaJ8nbPd vR1SUoPhml8hYNUpGZsVktFkiSXxBwLRmMjqNIdDdw5PXtFZG2SMVxjisUbvNFbB64Gpzu7Mj6U ffUVJyAm0I4av8iPCxKgi4r/18f8eGf41xPRRw7kbwCKngKg63Oyn6O/2w4xuvCkka4NTdMSk3y u8aO5TRdRo5AeNv6uGJyOWsCIY7GgPY8QfHxnC/jLNwWbRJc6OTWLvmLxjnp8d65VwiYEcFLqhV n664K4Xu7nB6nEvuiSyxM4wDQIhRWcyNYDSfhFux8x9riwGOQiHHVKaJhyHg00y8M2o12o4P+9G UTJZUOnI4KLEn+MioRTBLczFA3KiQU/r1LySunr26aG7QMCaLViZexagO7CUR11ewvGPM0Fo5gY tvCotDnFtI+FR4NhlyVaf+ibmt1bTtw6aaZlK2lxEyDhGALfqOTCcwDum+R//Nqpc0QUldwu0Gh J+PYJE3LjuPdc4= X-Received: by 2002:a05:6000:389:b0:486:fe82:70a5 with SMTP id ffacd0b85a97d-486fe827223mr1200808f8f.16.1789301921174; Sun, 13 Sep 2026 05:18:41 -0700 (PDT) Received: from [127.0.1.1] ([2001:4bb8:107:bfd1:de2c:7b4b:8652:b761]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-486eb2ecf2esm20241141f8f.2.2026.09.13.05.18.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 05:18:40 -0700 (PDT) From: Javier Carrasco Date: Sun, 13 Sep 2026 14:18:21 +0200 Subject: [PATCH v10 1/4] dt-bindings: iio: light: veml6030: add veml6031x00 ALS series Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260913-veml6031x00-v10-1-adbc26c30d3d@gmail.com> References: <20260913-veml6031x00-v10-0-adbc26c30d3d@gmail.com> In-Reply-To: <20260913-veml6031x00-v10-0-adbc26c30d3d@gmail.com> To: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Javier Carrasco , Jonathan Cameron , Krzysztof Kozlowski X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1789301917; l=3140; i=javier.carrasco.cruz@gmail.com; s=20260111; h=from:subject:message-id; bh=koUYc8Dq9lWw1oLPJynOIZpYM8lkDBbSyMSmWAIup4w=; b=31pPxfJ9k1dltUb1YNVk9Ckyljv03EUkaN0ugq2uqUTepqkmFP7x5tOVBp5xYkqqgBMxY/6uV ozy7lztO61BAI8UUwu8TwMmVTZwKQL8bWb2/nBm1R3FJVGLSJwWzDi/ X-Developer-Key: i=javier.carrasco.cruz@gmail.com; a=ed25519; pk=Lge8w8xidNSf/INy7JAIbAW+Hezkp3nsBh2OjKL7lLU= These ambient light sensors share their properties with the ones from the same manufacturer that are supported by this bindings. Note that only two datasheets are provided as every one of them covers two devices (veml6031x00/veml60311x00 and veml6031x01/veml60311x01). Reviewed-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Signed-off-by: Javier Carrasco --- .../devicetree/bindings/iio/light/vishay,veml6030.yaml | 13 +++++++++= +++- MAINTAINERS | 5 +++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/iio/light/vishay,veml6030.ya= ml b/Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml index 0041e1db6838..a44de649184a 100644 --- a/Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml +++ b/Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml @@ -4,7 +4,8 @@ $id: http://devicetree.org/schemas/iio/light/vishay,veml6030.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# =20 -title: VEML3235, VEML3328, VEML6030, VEML6035 and VEML7700 Ambient Light S= ensors (ALS) +title: VEML3235, VEML3328, VEML6030, VEML6031x00 series, VEML6035 + and VEML7700 Ambient Light Sensors (ALS) =20 maintainers: - Rishi Gupta @@ -23,6 +24,8 @@ description: | https://www.vishay.com/docs/80131/veml3235.pdf https://www.vishay.com/docs/84968/veml3328.pdf https://www.vishay.com/docs/84366/veml6030.pdf + https://www.vishay.com/docs/80007/veml6031x00.pdf + https://www.vishay.com/docs/80008/veml6031x01.pdf https://www.vishay.com/docs/84889/veml6035.pdf https://www.vishay.com/docs/84286/veml7700.pdf =20 @@ -32,6 +35,10 @@ properties: - vishay,veml3235 - vishay,veml3328 - vishay,veml6030 + - vishay,veml6031x00 + - vishay,veml6031x01 + - vishay,veml60311x00 + - vishay,veml60311x01 - vishay,veml6035 - vishay,veml7700 =20 @@ -69,6 +76,8 @@ allOf: properties: compatible: enum: + - vishay,veml6031x00 + - vishay,veml6031x01 - vishay,veml6035 then: properties: @@ -82,6 +91,8 @@ allOf: enum: - vishay,veml3235 - vishay,veml3328 + - vishay,veml60311x00 + - vishay,veml60311x01 - vishay,veml7700 then: properties: diff --git a/MAINTAINERS b/MAINTAINERS index 3a19da74d00c..57202b51fb66 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -29095,6 +29095,11 @@ S: Maintained F: Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml F: drivers/iio/light/veml6030.c =20 +VISHAY VEML6031X00 AMBIENT LIGHT SENSOR DRIVER +M: Javier Carrasco +S: Maintained +F: Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml + VISHAY VEML6046X00 RGBIR COLOR SENSOR DRIVER M: Andreas Klinger S: Maintained --=20 2.43.0 From nobody Fri Sep 25 12:03:19 2026 Received: from mail-wm2-f12.google.com (mail-wm2-f12.google.com [74.125.225.140]) (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 3DB123E9C2B for ; Sun, 13 Sep 2026 12:18:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.225.140 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789301927; cv=none; b=qZAFY81wJwXrOiow564jz2tWVBWwHtG2IcC+l53MuWJJJ+qq59bAjR9EtrK33UAcwG/lsbEGywFQUYBd6Ul/xUIpzgT31spkQZDOydTIW7YNXH/YOQvkl/itV+9z4CkQhE0sIhIfdEPW4YYw9ZpHpDiqsdHhjo6rzWLd++qCN5M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789301927; c=relaxed/simple; bh=K+dZwDdX5FA+cBNgrU+MPKgYxneqoPoPqHtGtcjSp/k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Z0LFpC6Rrh79VdTAr50kOXqRE6lrPkjbUO8fQKtX8FsefYjx6mqc86odpX+4j42/BZWmnCRV+mN8QI5UEFYtFl5ajJQz4HBhbHT/u/g/SVXho/R4T5kO0pqlPu2es/X179OzYngE+JE7uUb25NXN2a0ZK/NdQFskOy4KBlMWNjo= 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=X2PJG5f6; arc=none smtp.client-ip=74.125.225.140 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="X2PJG5f6" Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49b965f447cso7464505e9.3 for ; Sun, 13 Sep 2026 05:18:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789301923; x=1789906723; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=A5Qv66gxQUrcsxq+IMMc7XxmNJGfQIwe+qAYN0zRjnQ=; b=X2PJG5f6Dju1tASndA9loethgrMXcTpiROmABFvjvH/Z/zm1GTWAbnVFIIuoPl55q+ pSN9t8R/P6iFxf8bltJI1gKxJEsmR0NzoepHkL3+6NixCOQPUS//f2SlpZbdq2QtZRLI DqBCSlREBRqo1wfvoDuFRdAHIC9Xi4MTWyxBV0dCkqjdVbkut+C68gS7m4RHzRaV0hFK yIy+wV4HWKd+jQMq9iUJ71aUwlqSPo06chL9XKTVS6Aqc/U2O8pklT5AnsRUpnsVZGPR rv0ONlV9cN1WUHtaVZZq9tWorjwdGPlFcBsNali6l3TDJoxz+qrMpKRSS0u2MUIAkhlO 5aIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789301923; x=1789906723; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=A5Qv66gxQUrcsxq+IMMc7XxmNJGfQIwe+qAYN0zRjnQ=; b=MXAqFrNEa+8ThOEbNPuR2KKB3/rN1H4HZSfS3vooAAHtDHobCrqiPLiMWbZjnunDbF DKpuMz2MWI5KIhGmaHBlZTnMom9SaPXtsZAGxZu0187yqLJ2F/99ygTL5kL4JfTv1vwz M667DqWO/XEfTzKo7m1sKNN5wy4VahId5gwHhuMd02SBV94C9oV6lUyK7lvfNQC4+mot N1N+qfcwzV/54bvIPtX1ZE3gRTJhO3sZvHkyPFodxA5WMskhsT4UtSARG/uuKW4fmykI lT1N3ArZxTlKJg/AihVWtdVI3nl7eD0AHszhIaNKqU3kyUtkpdmrjnKYveBR1Y+cNz7B 0zBA== X-Forwarded-Encrypted: i=1; AKwUvByT0PyOdYWzLl7cvoRVnvYsJCAG7W7BONP9l6bZ4noyi8ZRYn4WOCusguVeyfJz7iN1GDae0rM4rccm55g=@vger.kernel.org X-Gm-Message-State: AFuF++mlXqx3QjOSgKuRexClLJu7AlfEOS73y6Lv+ggYIEq3w0iY5Taw nPx58QNdRpw93y/GYNL5CL4nMGLLzf7imfoXHdML0kTtubitV267bmfP X-Gm-Gg: AYBFou2NAg9AVW1pW2l0AOA1KX6Ut8cET4rILFKw0cN79t7wIwDB4aoL0fznoXf9H5u JCqIs8DSx5F/EoJPdtz4ZwZUVfX1iFW4JrIFOAxowNc2VqNSR3/pmJnk8674YLMSa4OK3L4KrWX XOs9ljFTPRO5742BT1j5hV4fGv6knCxeDU8AV63PbBm6VZEs1GOoQuxW+k+6zNPSdyVDlrwpUJm 4oorOhH6+RpWnNjlhJrF8JBCaw/EBCinzdayKbL+subvQND8EqV3kNeE3ZRUV3FUVNdFTc3S64k ta5+H5Qt7lBvNwu/T4j9aqTIgNOZ49CGJvb1Jmx+E8s1pOQOmbTvt30Y/ZWGwRYfoGIiOmR3u53 jy/otsztwFg04SaTe8VLFFZ6DKndgqNjXnEeyH4Df1Exj5Ml8wOrkiFNqx+snjgq2MveJrM3dgX 6f4nSqFzrU9/YirquCNtn9A4+B44Ul3ZCqPRzb9LEJuShh4ouQpDHZXj/gqCKhPJV7cCKMAMEDD 03J+i2oBN6zoMMt6PdtGfdppg== X-Received: by 2002:a5d:5f49:0:b0:486:ed36:b9c with SMTP id ffacd0b85a97d-486f6c49c2emr6355414f8f.29.1789301923212; Sun, 13 Sep 2026 05:18:43 -0700 (PDT) Received: from [127.0.1.1] ([2001:4bb8:107:bfd1:de2c:7b4b:8652:b761]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-486eb2ecf2esm20241141f8f.2.2026.09.13.05.18.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 05:18:42 -0700 (PDT) From: Javier Carrasco Date: Sun, 13 Sep 2026 14:18:22 +0200 Subject: [PATCH v10 2/4] iio: light: add support for veml6031x00 ALS series Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260913-veml6031x00-v10-2-adbc26c30d3d@gmail.com> References: <20260913-veml6031x00-v10-0-adbc26c30d3d@gmail.com> In-Reply-To: <20260913-veml6031x00-v10-0-adbc26c30d3d@gmail.com> To: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Javier Carrasco , Jonathan Cameron X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1789301917; l=21315; i=javier.carrasco.cruz@gmail.com; s=20260111; h=from:subject:message-id; bh=K+dZwDdX5FA+cBNgrU+MPKgYxneqoPoPqHtGtcjSp/k=; b=qMW10Jzdt/3EI8Fpzeby9fEHL0FewClZi5DBsOyAUBk867zq1vTUTlBRrHryokOC3dBLV4Ihy xHQtRQsDpJOAPGFu95x4W+xUSm4FzT6UQksSv/0CFV+11MMKnDCzR8B X-Developer-Key: i=javier.carrasco.cruz@gmail.com; a=ed25519; pk=Lge8w8xidNSf/INy7JAIbAW+Hezkp3nsBh2OjKL7lLU= Support device identification, raw ALS and IR readings, and configuration of the scale and integration time. Reviewed-by: Andy Shevchenko Signed-off-by: Javier Carrasco --- MAINTAINERS | 1 + drivers/iio/light/Kconfig | 12 + drivers/iio/light/Makefile | 1 + drivers/iio/light/veml6031x00.c | 678 ++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 692 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 57202b51fb66..c83f5af23d97 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -29099,6 +29099,7 @@ VISHAY VEML6031X00 AMBIENT LIGHT SENSOR DRIVER M: Javier Carrasco S: Maintained F: Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml +F: drivers/iio/light/veml6031x00.c =20 VISHAY VEML6046X00 RGBIR COLOR SENSOR DRIVER M: Andreas Klinger diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index f23bbce12c72..02291abeff60 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -741,6 +741,18 @@ config VEML6030 To compile this driver as a module, choose M here: the module will be called veml6030. =20 +config VEML6031X00 + tristate "VEML6031X00 ambient light sensor series" + select REGMAP_I2C + select IIO_GTS_HELPER + depends on I2C + help + Say Y here if you want to build a driver for the Vishay VEML6031X00 + ambient light sensor series. + + To compile this driver as a module, choose M here: the + module will be called veml6031x00. + config VEML6040 tristate "VEML6040 RGBW light sensor" select REGMAP_I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index 64e354c49ed8..6672ed01a819 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_VCNL4035) +=3D vcnl4035.o obj-$(CONFIG_VEML3235) +=3D veml3235.o obj-$(CONFIG_VEML3328) +=3D veml3328.o obj-$(CONFIG_VEML6030) +=3D veml6030.o +obj-$(CONFIG_VEML6031X00) +=3D veml6031x00.o obj-$(CONFIG_VEML6040) +=3D veml6040.o obj-$(CONFIG_VEML6046X00) +=3D veml6046x00.o obj-$(CONFIG_VEML6070) +=3D veml6070.o diff --git a/drivers/iio/light/veml6031x00.c b/drivers/iio/light/veml6031x0= 0.c new file mode 100644 index 000000000000..f3772577a05d --- /dev/null +++ b/drivers/iio/light/veml6031x00.c @@ -0,0 +1,678 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * VEML6031X00 Ambient Light Sensor + * + * Copyright (c) 2026, Javier Carrasco + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +/* Device registers */ +#define VEML6031X00_REG_CONF0 0x00 +#define VEML6031X00_REG_CONF1 0x01 +#define VEML6031X00_REG_ALS_L 0x10 +#define VEML6031X00_REG_ALS_H 0x11 +#define VEML6031X00_REG_IR_L 0x12 +#define VEML6031X00_REG_IR_H 0x13 +#define VEML6031X00_REG_ID_L 0x14 +#define VEML6031X00_REG_ID_H 0x15 + +/* Bit masks for specific functionality */ +#define VEML6031X00_CONF0_SD BIT(0) +#define VEML6031X00_CONF1_IR_SD BIT(7) + +#define VEML6031X00_GAIN_SEL(pd_div4, gain) (((pd_div4) << 2) | (gain)) + +struct veml6031x00_rf { + struct regmap_field *gain; + struct regmap_field *it; + struct regmap_field *pd_div4; +}; + +struct veml6031x00_chip { + const char *name; + const unsigned int part_id; +}; + +struct veml6031x00_data { + struct iio_gts gts; + struct regmap *regmap; + struct veml6031x00_rf rf; + const struct veml6031x00_chip *chip; + /* + * Serialize access to scale register fields scattered across multiple + * registers (rf.gain, rf.pd_div4, rf.it) to read and write them as a + * consistent set. + */ + struct mutex scale_lock; +}; + +static const struct iio_itime_sel_mul veml6031x00_it_sel[] =3D { + GAIN_SCALE_ITIME_US(3125, 0, 1), + GAIN_SCALE_ITIME_US(6250, 1, 2), + GAIN_SCALE_ITIME_US(12500, 2, 4), + GAIN_SCALE_ITIME_US(25000, 3, 8), + GAIN_SCALE_ITIME_US(50000, 4, 16), + GAIN_SCALE_ITIME_US(100000, 5, 32), + GAIN_SCALE_ITIME_US(200000, 6, 64), + GAIN_SCALE_ITIME_US(400000, 7, 128), +}; + +/* + * The gain selector encodes (PD_D4 << 2) | GAIN to identify each gain set= ting. + * Gains are multiplied by 8 to work with integers. The values in the iio-= gts + * tables don't need corrections because the maximum value of the scale re= fers + * to GAIN =3D x1, and the rest of the values are obtained from the result= ing + * linear function. + * TODO: add support for GAIN_0_165 and GAIN_0_660 + */ +#define VEML6031X00_SEL_GAIN_0_125 0x07 +#define VEML6031X00_SEL_GAIN_0_250 0x04 +#define VEML6031X00_SEL_GAIN_0_500 0x03 +#define VEML6031X00_SEL_GAIN_1_000 0x00 +#define VEML6031X00_SEL_GAIN_2_000 0x01 +static const struct iio_gain_sel_pair veml6031x00_gain_sel[] =3D { + GAIN_SCALE_GAIN(1, VEML6031X00_SEL_GAIN_0_125), + GAIN_SCALE_GAIN(2, VEML6031X00_SEL_GAIN_0_250), + GAIN_SCALE_GAIN(4, VEML6031X00_SEL_GAIN_0_500), + GAIN_SCALE_GAIN(8, VEML6031X00_SEL_GAIN_1_000), + GAIN_SCALE_GAIN(16, VEML6031X00_SEL_GAIN_2_000), +}; + +/* + * The shutdown bits (SD and ALS_IR_SD) are in different registers, and bo= th + * must be updated when changing the device power state. + */ +static int veml6031x00_set_power(struct veml6031x00_data *data, bool state) +{ + int ret; + + ret =3D regmap_assign_bits(data->regmap, VEML6031X00_REG_CONF0, + VEML6031X00_CONF0_SD, !state); + if (ret) + return ret; + + return regmap_assign_bits(data->regmap, VEML6031X00_REG_CONF1, + VEML6031X00_CONF1_IR_SD, !state); +} + +static void veml6031x00_als_shutdown_action(void *data) +{ + struct veml6031x00_data *priv =3D data; + struct device *dev =3D regmap_get_device(priv->regmap); + int ret; + + ret =3D veml6031x00_set_power(priv, false); + if (ret) + dev_warn(dev, "Failed to shut down device: %d\n", ret); +} + +static const struct iio_chan_spec veml6031x00_channels[] =3D { + { + .type =3D IIO_LIGHT, + .address =3D VEML6031X00_REG_ALS_L, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_separate_available =3D BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_SCALE), + }, + { + .type =3D IIO_INTENSITY, + .address =3D VEML6031X00_REG_IR_L, + .modified =3D 1, + .channel2 =3D IIO_MOD_LIGHT_IR, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW), + }, +}; + +static const struct regmap_range veml6031x00_readable_ranges[] =3D { + regmap_reg_range(VEML6031X00_REG_CONF0, VEML6031X00_REG_CONF1), + regmap_reg_range(VEML6031X00_REG_ALS_L, VEML6031X00_REG_ID_H), +}; + +static const struct regmap_access_table veml6031x00_readable_table =3D { + .yes_ranges =3D veml6031x00_readable_ranges, + .n_yes_ranges =3D ARRAY_SIZE(veml6031x00_readable_ranges), +}; + +static const struct regmap_range veml6031x00_writable_ranges[] =3D { + regmap_reg_range(VEML6031X00_REG_CONF0, VEML6031X00_REG_CONF1), +}; + +static const struct regmap_access_table veml6031x00_writable_table =3D { + .yes_ranges =3D veml6031x00_writable_ranges, + .n_yes_ranges =3D ARRAY_SIZE(veml6031x00_writable_ranges), +}; + +static const struct regmap_range veml6031x00_volatile_ranges[] =3D { + /* AF_TRIG in CONF0 is volatile */ + regmap_reg_range(VEML6031X00_REG_CONF0, VEML6031X00_REG_CONF0), + regmap_reg_range(VEML6031X00_REG_ALS_L, VEML6031X00_REG_IR_H), +}; + +static const struct regmap_access_table veml6031x00_volatile_table =3D { + .yes_ranges =3D veml6031x00_volatile_ranges, + .n_yes_ranges =3D ARRAY_SIZE(veml6031x00_volatile_ranges), +}; + +static const struct regmap_config veml6031x00_regmap_config =3D { + .name =3D "veml6031x00_regmap", + .reg_bits =3D 8, + .val_bits =3D 8, + .rd_table =3D &veml6031x00_readable_table, + .wr_table =3D &veml6031x00_writable_table, + .volatile_table =3D &veml6031x00_volatile_table, + .max_register =3D VEML6031X00_REG_ID_H, + .cache_type =3D REGCACHE_MAPLE, +}; + +static const struct reg_field veml6031x00_rf_it =3D + REG_FIELD(VEML6031X00_REG_CONF0, 4, 6); + +static const struct reg_field veml6031x00_rf_gain =3D + REG_FIELD(VEML6031X00_REG_CONF1, 3, 4); + +static const struct reg_field veml6031x00_rf_pd_div4 =3D + REG_FIELD(VEML6031X00_REG_CONF1, 6, 6); + +static int veml6031x00_regfield_init(struct veml6031x00_data *data) +{ + struct regmap *map =3D data->regmap; + struct device *dev =3D regmap_get_device(map); + struct regmap_field *rm_field; + struct veml6031x00_rf *rf =3D &data->rf; + + rm_field =3D devm_regmap_field_alloc(dev, map, veml6031x00_rf_gain); + if (IS_ERR(rm_field)) + return PTR_ERR(rm_field); + rf->gain =3D rm_field; + + rm_field =3D devm_regmap_field_alloc(dev, map, veml6031x00_rf_it); + if (IS_ERR(rm_field)) + return PTR_ERR(rm_field); + rf->it =3D rm_field; + + rm_field =3D devm_regmap_field_alloc(dev, map, veml6031x00_rf_pd_div4); + if (IS_ERR(rm_field)) + return PTR_ERR(rm_field); + rf->pd_div4 =3D rm_field; + + return 0; +} + +static int __veml6031x00_get_it(struct veml6031x00_data *data, int *val2) +{ + unsigned int it_idx; + int ret; + + ret =3D regmap_field_read(data->rf.it, &it_idx); + if (ret) + return ret; + + ret =3D iio_gts_find_int_time_by_sel(&data->gts, it_idx); + if (ret < 0) + return ret; + + *val2 =3D ret; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int veml6031x00_get_it(struct veml6031x00_data *data, int *val2) +{ + guard(mutex)(&data->scale_lock); + + return __veml6031x00_get_it(data, val2); +} + +static int veml6031x00_write_gain(struct veml6031x00_data *data, unsigned = int gain) +{ + int ret; + + ret =3D regmap_field_write(data->rf.pd_div4, gain >> 2); + if (ret) + return ret; + + return regmap_field_write(data->rf.gain, gain & 0x03); +} + +static int veml6031x00_set_it(struct iio_dev *iio, int val, int val2) +{ + struct veml6031x00_data *data =3D iio_priv(iio); + struct device *dev =3D regmap_get_device(data->regmap); + int ret, gain_sel, new_gain, prev_gain, prev_it; + unsigned int gain_reg, it_idx, pd_div4; + struct iio_gts *gts =3D &data->gts; + bool gain_in_range; + + if (val || !iio_gts_valid_time(gts, val2)) + return -EINVAL; + + guard(mutex)(&data->scale_lock); + + ret =3D regmap_field_read(data->rf.it, &it_idx); + if (ret) + return ret; + + ret =3D regmap_field_read(data->rf.gain, &gain_reg); + if (ret) + return ret; + + ret =3D regmap_field_read(data->rf.pd_div4, &pd_div4); + if (ret) + return ret; + + prev_it =3D iio_gts_find_int_time_by_sel(gts, it_idx); + if (prev_it < 0) + return prev_it; + + if (prev_it =3D=3D val2) + return 0; + + gain_sel =3D VEML6031X00_GAIN_SEL(pd_div4, gain_reg); + prev_gain =3D iio_gts_find_gain_by_sel(gts, gain_sel); + if (prev_gain < 0) + return prev_gain; + + ret =3D iio_gts_find_new_gain_by_gain_time_min(gts, prev_gain, prev_it, v= al2, + &new_gain, &gain_in_range); + if (ret) + return ret; + + if (!gain_in_range) + dev_dbg(dev, "Optimal gain out of range\n"); + + ret =3D iio_gts_find_sel_by_int_time(gts, val2); + if (ret < 0) + return ret; + + ret =3D regmap_field_write(data->rf.it, ret); + if (ret) + return ret; + + gain_sel =3D iio_gts_find_sel_by_gain(gts, new_gain); + if (gain_sel < 0) + return gain_sel; + + return veml6031x00_write_gain(data, gain_sel); +} + +static int veml6031x00_set_scale(struct iio_dev *iio, int val, int val2) +{ + struct veml6031x00_data *data =3D iio_priv(iio); + struct iio_gts *gts =3D &data->gts; + int gain_sel, it_sel, ret; + + ret =3D iio_gts_find_gain_time_sel_for_scale(gts, val, val2, &gain_sel, &= it_sel); + if (ret) + return ret; + + guard(mutex)(&data->scale_lock); + + ret =3D regmap_field_write(data->rf.it, it_sel); + if (ret) + return ret; + + return veml6031x00_write_gain(data, gain_sel); +} + +static int veml6031x00_get_scale(struct veml6031x00_data *data, int *val, = int *val2) +{ + unsigned int gain_reg, pd_div4, it_reg; + int gain, it, ret, sel; + + scoped_guard(mutex, &data->scale_lock) { + ret =3D regmap_field_read(data->rf.gain, &gain_reg); + if (ret) + return ret; + + ret =3D regmap_field_read(data->rf.pd_div4, &pd_div4); + if (ret) + return ret; + + sel =3D VEML6031X00_GAIN_SEL(pd_div4, gain_reg); + gain =3D iio_gts_find_gain_by_sel(&data->gts, sel); + if (gain < 0) + return gain; + + ret =3D regmap_field_read(data->rf.it, &it_reg); + if (ret) + return ret; + } + + it =3D iio_gts_find_int_time_by_sel(&data->gts, it_reg); + if (it < 0) + return it; + + ret =3D iio_gts_get_scale(&data->gts, gain, it, val, val2); + if (ret) + return ret; + + return IIO_VAL_INT_PLUS_NANO; +} + +static int veml6031x00_single_read(struct iio_dev *iio, enum iio_chan_type= type, + int *val) +{ + struct veml6031x00_data *data =3D iio_priv(iio); + unsigned int addr; + int it_usec, ret; + __le16 regval; + + switch (type) { + case IIO_LIGHT: + addr =3D VEML6031X00_REG_ALS_L; + break; + case IIO_INTENSITY: + addr =3D VEML6031X00_REG_IR_L; + break; + default: + return -EINVAL; + } + + guard(mutex)(&data->scale_lock); + + PM_RUNTIME_ACQUIRE_AUTOSUSPEND(regmap_get_device(data->regmap), pm); + ret =3D PM_RUNTIME_ACQUIRE_ERR(&pm); + if (ret) + return ret; + + ret =3D __veml6031x00_get_it(data, &it_usec); + if (ret < 0) + return ret; + + /* integration time + 10% to ensure completion */ + fsleep(it_usec + (it_usec / 10)); + + ret =3D regmap_bulk_read(data->regmap, addr, ®val, sizeof(regval)); + if (ret) + return ret; + + *val =3D le16_to_cpu(regval); + + return IIO_VAL_INT; +} + +static int veml6031x00_read_raw(struct iio_dev *iio, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct veml6031x00_data *data =3D iio_priv(iio); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + return veml6031x00_single_read(iio, chan->type, val); + case IIO_CHAN_INFO_INT_TIME: + *val =3D 0; + return veml6031x00_get_it(data, val2); + case IIO_CHAN_INFO_SCALE: + return veml6031x00_get_scale(data, val, val2); + default: + return -EINVAL; + } +} + +static int veml6031x00_read_avail(struct iio_dev *iio, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + struct veml6031x00_data *data =3D iio_priv(iio); + + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: + return iio_gts_avail_times(&data->gts, vals, type, length); + case IIO_CHAN_INFO_SCALE: + return iio_gts_all_avail_scales(&data->gts, vals, type, length); + default: + return -EINVAL; + } +} + +static int veml6031x00_write_raw(struct iio_dev *iio, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: + return veml6031x00_set_it(iio, val, val2); + case IIO_CHAN_INFO_SCALE: + return veml6031x00_set_scale(iio, val, val2); + default: + return -EINVAL; + } +} + +static int veml6031x00_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_INT_TIME: + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static const struct iio_info veml6031x00_info =3D { + .read_raw =3D veml6031x00_read_raw, + .read_avail =3D veml6031x00_read_avail, + .write_raw =3D veml6031x00_write_raw, + .write_raw_get_fmt =3D veml6031x00_write_raw_get_fmt, +}; + +static int veml6031x00_validate_part_id(struct veml6031x00_data *data) +{ + struct regmap *map =3D data->regmap; + struct device *dev =3D regmap_get_device(map); + unsigned int part_id; + int ret; + __le16 regval; + + ret =3D regmap_bulk_read(map, VEML6031X00_REG_ID_L, ®val, sizeof(regva= l)); + if (ret) + return dev_err_probe(dev, ret, "Failed to read ID\n"); + + part_id =3D le16_to_cpu(regval); + if (part_id !=3D data->chip->part_id) + dev_info(dev, "Unknown or unexpected ID %04x\n", part_id); + + return 0; +} + +static int veml6031x00_probe(struct i2c_client *i2c) +{ + struct device *dev =3D &i2c->dev; + struct veml6031x00_data *data; + struct iio_dev *iio; + int ret; + + iio =3D devm_iio_device_alloc(dev, sizeof(*data)); + if (!iio) + return -ENOMEM; + + data =3D iio_priv(iio); + i2c_set_clientdata(i2c, iio); + + data->chip =3D i2c_get_match_data(i2c); + if (!data->chip) + return dev_err_probe(dev, -ENODATA, "Failed to get chip data\n"); + + ret =3D devm_mutex_init(dev, &data->scale_lock); + if (ret) + return ret; + + data->regmap =3D devm_regmap_init_i2c(i2c, &veml6031x00_regmap_config); + if (IS_ERR(data->regmap)) + return dev_err_probe(dev, PTR_ERR(data->regmap), + "Failed to set regmap\n"); + + iio->name =3D data->chip->name; + iio->channels =3D veml6031x00_channels; + iio->num_channels =3D ARRAY_SIZE(veml6031x00_channels); + iio->modes =3D INDIO_DIRECT_MODE; + iio->info =3D &veml6031x00_info; + + ret =3D veml6031x00_regfield_init(data); + if (ret) + return dev_err_probe(dev, ret, "Failed to init regfield\n"); + + ret =3D devm_regulator_get_enable(dev, "vdd"); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable regulator\n"); + + /* The device starts in power down mode by default */ + ret =3D veml6031x00_set_power(data, true); + if (ret) + return dev_err_probe(dev, ret, "Failed to power on the device\n"); + + ret =3D devm_add_action_or_reset(dev, veml6031x00_als_shutdown_action, da= ta); + if (ret) + return dev_err_probe(dev, ret, "Failed to add shutdown action\n"); + + pm_runtime_set_autosuspend_delay(dev, 2000); + pm_runtime_use_autosuspend(dev); + ret =3D devm_pm_runtime_set_active_enabled(dev); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable runtime PM\n"); + + ret =3D veml6031x00_validate_part_id(data); + if (ret) + return ret; + + /* Max resolution =3D 6.9632 lx/cnt for gain =3D 0.125 and IT =3D 3.125ms= */ + ret =3D devm_iio_init_iio_gts(dev, 6, 963200000, + veml6031x00_gain_sel, + ARRAY_SIZE(veml6031x00_gain_sel), + veml6031x00_it_sel, + ARRAY_SIZE(veml6031x00_it_sel), + &data->gts); + if (ret) + return dev_err_probe(dev, ret, "Failed to init IIO GTS\n"); + + ret =3D devm_iio_device_register(dev, iio); + if (ret) + return dev_err_probe(dev, ret, "Failed to register IIO device\n"); + + return 0; +} + +static int veml6031x00_runtime_suspend(struct device *dev) +{ + struct veml6031x00_data *data =3D iio_priv(dev_get_drvdata(dev)); + + return veml6031x00_set_power(data, false); +} + +static int veml6031x00_runtime_resume(struct device *dev) +{ + struct veml6031x00_data *data =3D iio_priv(dev_get_drvdata(dev)); + + return veml6031x00_set_power(data, true); +} + +static DEFINE_RUNTIME_DEV_PM_OPS(veml6031x00_pm_ops, + veml6031x00_runtime_suspend, + veml6031x00_runtime_resume, + NULL); + +static const struct veml6031x00_chip veml6031x00_chip =3D { + .name =3D "veml6031x00", + .part_id =3D 0x0001, +}; + +static const struct veml6031x00_chip veml6031x01_chip =3D { + .name =3D "veml6031x01", + .part_id =3D 0x0001, +}; + +static const struct veml6031x00_chip veml60311x00_chip =3D { + .name =3D "veml60311x00", + .part_id =3D 0x1001, +}; + +static const struct veml6031x00_chip veml60311x01_chip =3D { + .name =3D "veml60311x01", + .part_id =3D 0x1001, +}; + +static const struct of_device_id veml6031x00_of_match[] =3D { + { + .compatible =3D "vishay,veml6031x00", + .data =3D &veml6031x00_chip, + }, + { + .compatible =3D "vishay,veml6031x01", + .data =3D &veml6031x01_chip, + }, + { + .compatible =3D "vishay,veml60311x00", + .data =3D &veml60311x00_chip, + }, + { + .compatible =3D "vishay,veml60311x01", + .data =3D &veml60311x01_chip, + }, + { } +}; +MODULE_DEVICE_TABLE(of, veml6031x00_of_match); + +static const struct i2c_device_id veml6031x00_id[] =3D { + { + .name =3D "veml6031x00", + .driver_data =3D (kernel_ulong_t)&veml6031x00_chip, + }, + { + .name =3D "veml6031x01", + .driver_data =3D (kernel_ulong_t)&veml6031x01_chip, + }, + { + .name =3D "veml60311x00", + .driver_data =3D (kernel_ulong_t)&veml60311x00_chip, + }, + { + .name =3D "veml60311x01", + .driver_data =3D (kernel_ulong_t)&veml60311x01_chip, + }, + { } +}; +MODULE_DEVICE_TABLE(i2c, veml6031x00_id); + +static struct i2c_driver veml6031x00_driver =3D { + .driver =3D { + .name =3D "veml6031x00", + .of_match_table =3D veml6031x00_of_match, + .pm =3D pm_ptr(&veml6031x00_pm_ops), + }, + .probe =3D veml6031x00_probe, + .id_table =3D veml6031x00_id, +}; +module_i2c_driver(veml6031x00_driver); + +MODULE_AUTHOR("Javier Carrasco "); +MODULE_DESCRIPTION("VEML6031X00 Ambient Light Sensor"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_GTS_HELPER"); --=20 2.43.0 From nobody Fri Sep 25 12:03:19 2026 Received: from mail-wr2-f12.google.com (mail-wr2-f12.google.com [74.125.225.76]) (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 127AE38DC53 for ; Sun, 13 Sep 2026 12:18:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.225.76 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789301928; cv=none; b=ajhNV6WOWl8VKuxuwmwQ3IF3v0WDjiSl3QrUhIw5HrIN9a9NGBAgXm5UcNu4WbV+ZxaDK0BuM9xRpZ1lqEydG1vfVp6/wo4/bJfPC48sUVWMCR1laEdwr5vLimYfINsqDM5tMXae0mbDDU3Z06cQcuZOrfQQGWGt6y1nJY7HBVo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789301928; c=relaxed/simple; bh=QCLyoNALvtQOVUWWgKT4N38ewa9Qau0InNlSI5vyyo0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mRXU6bwIGKgND0MAcBAeiWz3lDdrfO8uD1aLgow6oOJdrEZFB15Lv/CtYPuV8kFpkywqbRXCP7bEHRGOAzQMo4NY1OiWGS/N2/as9laA2CuhRuNrQoHoLfeC72MXSUMvI9sNsTWORH/8gL4Yy/zmF5ZSRYBQfDsJo4D/AjULhQ4= 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=gL/dBO5Q; arc=none smtp.client-ip=74.125.225.76 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="gL/dBO5Q" Received: by mail-wr2-f12.google.com with SMTP id ffacd0b85a97d-482f6350f91so490125f8f.1 for ; Sun, 13 Sep 2026 05:18:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789301925; x=1789906725; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=yRwhjp/IBhSw3Lk79MEayOHDigt6p4gE2z38qX/b6Cc=; b=gL/dBO5QhFjOa3iJ4TD4swRUrY123xITh2Vdq1CVWnPW2+s5bRk0++34sjqmvquQWv bOgJEv548ayXdGMI0zkFrA3kfrlNnTKAhPGxqwau2GjQafO/W+H4VbRxTWbS6dxT2+vh SQkGtdHd1IDU1avSw8in6ODP3rFoq9AAJ7lKtp+NlzVmD8wegbJa4CFVAdbiczdH5lce oxP5F7WDN0MMLRq27BqmYM5jbdiCp0bpKH1eMST+lPsW+08G4EIQaNxZggYkyVLu2nFU 8vHkvD2vh2w0CMKTIbikPvjRSm8v0T71EzUaVpWYStfO8vbGM42uywULVMM3PB16sCiq LvEA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789301925; x=1789906725; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=yRwhjp/IBhSw3Lk79MEayOHDigt6p4gE2z38qX/b6Cc=; b=kkgvq3yVG6llj/71c4XczyKWl650M4D0BgqHuCTVFCmQIXZkkuyzH2dhDFQpSFn76Z Fwlhhc6cMcJb4WSE0zZ+7bljXmQpewDNs7T3C4l07Pb0LGN5huoUxPDWb8VSmzwAhZ2F ZxOBLydoIoIV5kRGa4RS86zj0t8DMKpvw1JGoWvvtPeTORmC3XEpbadnv7pQeXlCdBOM Dc94d2Ybuh6+R7UILAjWCtmcCIBkqlsmREIFVRT5I58jjvB7aMDEaUGe/IZBdQo8g6m3 XelLAVrrEy8IBMVrj4APNQJREVW9/s+po99CtxZIrSksKFjDA90rRqPlKFirTmLpsN06 Io/w== X-Forwarded-Encrypted: i=1; AKwUvBxxDTPj3SAXlXjlCFOqmdDWruF+2uk2sGWEaBNLygwA2Ixg8ULKuiemjvKx514azDiMQq4ZlwYrmD0M0KQ=@vger.kernel.org X-Gm-Message-State: AFuF++lTyDkYmO9f/4Ne067qhUOmfpbpNcaJDjApsYXOTagHDDtjD0WZ VG28rFdMh/CQl9gsQiUrH5sNUd7vsXwWhU+cYWLPntOOBVK1itiFauNo X-Gm-Gg: AYBFou0Nl4ompfeHUBZ7meUyTFkH0/LXsPtQyI9c20YnYNXk1K3GOEgHOdUqzWvhoQT G2e6EEmCV/75MrscGOfJzKl++sPpLtHboin0FnILYngxpv8uQOsNkg+bs/Rg7cLR0A3dIuLQxge WagdBaNPmafywzQPtu94dhkk2JCaD8dDrqLP71hosGJvuIRP/VUUO6EV8HYKQNIdxlm2rlgd7Kq nSzEB37JiZ2HgWN/6Oii15jRHBkLLggezhEjm7t+troi0yAe1ubfJ5wJsO0J3hMyyTaG8t3obQS NmBdDV/YORAX+hsFeEr9QZndxb63gujEwm5jdTKDF1ZGf6vEHmP9VA9m9JQ/WMuEGsnU9BqUuaI /WCacZG7CvewHhcT1mQliubfa/yvR7pjlTDMnPpsO4b0c8wa0l6TmUnm9+sdupLPE/KSBDrGRvu JLVtVaubS3yx4xSDY59XpDgOuNRBIMpEa77jp75LYF1EQDg+dWnrTWhLGpriZzp20earsmiEs62 NLqEVEOB4GSW2+z X-Received: by 2002:a05:6000:2002:b0:485:8c17:9767 with SMTP id ffacd0b85a97d-486f6c4422amr6325362f8f.41.1789301925247; Sun, 13 Sep 2026 05:18:45 -0700 (PDT) Received: from [127.0.1.1] ([2001:4bb8:107:bfd1:de2c:7b4b:8652:b761]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-486eb2ecf2esm20241141f8f.2.2026.09.13.05.18.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 05:18:44 -0700 (PDT) From: Javier Carrasco Date: Sun, 13 Sep 2026 14:18:23 +0200 Subject: [PATCH v10 3/4] iio: light: veml6031x00: add support for triggered buffers Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260913-veml6031x00-v10-3-adbc26c30d3d@gmail.com> References: <20260913-veml6031x00-v10-0-adbc26c30d3d@gmail.com> In-Reply-To: <20260913-veml6031x00-v10-0-adbc26c30d3d@gmail.com> To: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Javier Carrasco , Jonathan Cameron X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1789301917; l=6221; i=javier.carrasco.cruz@gmail.com; s=20260111; h=from:subject:message-id; bh=QCLyoNALvtQOVUWWgKT4N38ewa9Qau0InNlSI5vyyo0=; b=KMLgyMiPoTQImRHlyyE/dFejTNZlWFvulvMM7tHAMB+2CE6KaE6Ap9onDgLdmzHxTpyGZ7sLp WDMkN5nHVS6B8tlBXlOSxDuiQ9UfFukoD8p5oRPixeHKLdqQQlccVlE X-Developer-Key: i=javier.carrasco.cruz@gmail.com; a=ed25519; pk=Lge8w8xidNSf/INy7JAIbAW+Hezkp3nsBh2OjKL7lLU= Add triggered buffer functionality for the two channels the device provides (ALS and IR). Reviewed-by: Andy Shevchenko Signed-off-by: Javier Carrasco --- drivers/iio/light/Kconfig | 2 + drivers/iio/light/veml6031x00.c | 113 ++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 115 insertions(+) diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 02291abeff60..462fff1ddef2 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -745,6 +745,8 @@ config VEML6031X00 tristate "VEML6031X00 ambient light sensor series" select REGMAP_I2C select IIO_GTS_HELPER + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER depends on I2C help Say Y here if you want to build a driver for the Vishay VEML6031X00 diff --git a/drivers/iio/light/veml6031x00.c b/drivers/iio/light/veml6031x0= 0.c index f3772577a05d..3d5a27a0baae 100644 --- a/drivers/iio/light/veml6031x00.c +++ b/drivers/iio/light/veml6031x00.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,8 @@ =20 #include #include +#include +#include =20 /* Device registers */ #define VEML6031X00_REG_CONF0 0x00 @@ -42,6 +45,12 @@ =20 #define VEML6031X00_GAIN_SEL(pd_div4, gain) (((pd_div4) << 2) | (gain)) =20 +enum veml6031x00_scan { + VEML6031X00_SCAN_ALS, + VEML6031X00_SCAN_IR, + VEML6031X00_SCAN_TIMESTAMP, +}; + struct veml6031x00_rf { struct regmap_field *gain; struct regmap_field *it; @@ -135,6 +144,13 @@ static const struct iio_chan_spec veml6031x00_channels= [] =3D { BIT(IIO_CHAN_INFO_SCALE), .info_mask_separate_available =3D BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index =3D VEML6031X00_SCAN_ALS, + .scan_type =3D { + .format =3D IIO_SCAN_FORMAT_UNSIGNED_INT, + .realbits =3D 16, + .storagebits =3D 16, + .endianness =3D IIO_LE, + }, }, { .type =3D IIO_INTENSITY, @@ -142,7 +158,15 @@ static const struct iio_chan_spec veml6031x00_channels= [] =3D { .modified =3D 1, .channel2 =3D IIO_MOD_LIGHT_IR, .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW), + .scan_index =3D VEML6031X00_SCAN_IR, + .scan_type =3D { + .format =3D IIO_SCAN_FORMAT_UNSIGNED_INT, + .realbits =3D 16, + .storagebits =3D 16, + .endianness =3D IIO_LE, + }, }, + IIO_CHAN_SOFT_TIMESTAMP(VEML6031X00_SCAN_TIMESTAMP), }; =20 static const struct regmap_range veml6031x00_readable_ranges[] =3D { @@ -390,6 +414,10 @@ static int veml6031x00_single_read(struct iio_dev *iio= , enum iio_chan_type type, return -EINVAL; } =20 + IIO_DEV_ACQUIRE_DIRECT_MODE(iio, claim); + if (IIO_DEV_ACQUIRE_FAILED(claim)) + return -EBUSY; + guard(mutex)(&data->scale_lock); =20 PM_RUNTIME_ACQUIRE_AUTOSUSPEND(regmap_get_device(data->regmap), pm); @@ -453,6 +481,10 @@ static int veml6031x00_write_raw(struct iio_dev *iio, struct iio_chan_spec const *chan, int val, int val2, long mask) { + IIO_DEV_ACQUIRE_DIRECT_MODE(iio, claim); + if (IIO_DEV_ACQUIRE_FAILED(claim)) + return -EBUSY; + switch (mask) { case IIO_CHAN_INFO_INT_TIME: return veml6031x00_set_it(iio, val, val2); @@ -484,6 +516,80 @@ static const struct iio_info veml6031x00_info =3D { .write_raw_get_fmt =3D veml6031x00_write_raw_get_fmt, }; =20 +static int veml6031x00_buffer_preenable(struct iio_dev *iio) +{ + struct veml6031x00_data *data =3D iio_priv(iio); + struct device *dev =3D regmap_get_device(data->regmap); + int ret, it_usec; + + ret =3D pm_runtime_resume_and_get(dev); + if (ret) + return ret; + + ret =3D veml6031x00_get_it(data, &it_usec); + if (ret < 0) { + pm_runtime_put_autosuspend(dev); + return ret; + } + + /* + * Wait one integration period + 10% margin so the first triggered + * read does not race with the sensor completing its first conversion + * after power-on. + */ + fsleep(it_usec + (it_usec / 10)); + + return 0; +} + +static int veml6031x00_buffer_postdisable(struct iio_dev *iio) +{ + struct veml6031x00_data *data =3D iio_priv(iio); + + pm_runtime_put_autosuspend(regmap_get_device(data->regmap)); + + return 0; +} + +static const struct iio_buffer_setup_ops veml6031x00_buffer_setup_ops =3D { + .preenable =3D veml6031x00_buffer_preenable, + .postdisable =3D veml6031x00_buffer_postdisable, +}; + +static irqreturn_t veml6031x00_trig_handler(int irq, void *p) +{ + struct iio_poll_func *pf =3D p; + struct iio_dev *iio =3D pf->indio_dev; + struct veml6031x00_data *data =3D iio_priv(iio); + struct regmap *map =3D data->regmap; + IIO_DECLARE_BUFFER_WITH_TS(__le16, scan, 2) =3D { }; + unsigned int i; + int ch, ret; + + if (test_bit(VEML6031X00_SCAN_ALS, iio->active_scan_mask) && + test_bit(VEML6031X00_SCAN_IR, iio->active_scan_mask)) { + ret =3D regmap_bulk_read(map, VEML6031X00_REG_ALS_L, + scan, 2 * sizeof(*scan)); + if (ret) + goto done; + } else { + i =3D 0; + iio_for_each_active_channel(iio, ch) { + ret =3D regmap_bulk_read(map, iio->channels[ch].address, + &scan[i++], sizeof(*scan)); + if (ret) + goto done; + } + } + + iio_push_to_buffers_with_ts(iio, scan, sizeof(scan), pf->timestamp); + +done: + iio_trigger_notify_done(iio->trig); + + return IRQ_HANDLED; +} + static int veml6031x00_validate_part_id(struct veml6031x00_data *data) { struct regmap *map =3D data->regmap; @@ -573,6 +679,13 @@ static int veml6031x00_probe(struct i2c_client *i2c) if (ret) return dev_err_probe(dev, ret, "Failed to init IIO GTS\n"); =20 + ret =3D devm_iio_triggered_buffer_setup(dev, iio, + iio_pollfunc_store_time, + veml6031x00_trig_handler, + &veml6031x00_buffer_setup_ops); + if (ret) + return dev_err_probe(dev, ret, "Failed to register triggered buffer\n"); + ret =3D devm_iio_device_register(dev, iio); if (ret) return dev_err_probe(dev, ret, "Failed to register IIO device\n"); --=20 2.43.0 From nobody Fri Sep 25 12:03:19 2026 Received: from mail-wr2-f12.google.com (mail-wr2-f12.google.com [74.125.225.76]) (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 5CE293CB548 for ; Sun, 13 Sep 2026 12:18:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.225.76 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789301935; cv=none; b=ISLyO+wkJ3YhrSWSAvV5MMH2NjHdtBP2pGYrvuW4IfWFa8KDBnmcQwSrNlRGEfGL3NIbUyzFDjZdoP3o4BhxukfGaAQGcYnhfGrNsM+z2mWLSvjQHpqLaIAUt+W1946eyw97R5F/l+ypWcTcIbawQQnO/LkzgOjASDFncCQ7Ktw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789301935; c=relaxed/simple; bh=eZrm9VgPDfvj9NnGaY/C3bGlOsNzm2Q/fr2DsEYcE3s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Z75gLGjXTVzusvDN/AF2I7MDZzGXG8I75777zcK2051mTFTM8xqPiUw1qwf0/PR7kkCxbnXRu5emJVv1i3YL7XvN/xQpjP4/rZrZtvxhNJ8LPh+YmYPMHo1HVINnTAWWjCmHqLZMx0/Eamd1TGpZFk2mzJNxjkx39qpKHOGkArc= 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=Tbxihx3w; arc=none smtp.client-ip=74.125.225.76 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="Tbxihx3w" Received: by mail-wr2-f12.google.com with SMTP id ffacd0b85a97d-482f635552aso835192f8f.2 for ; Sun, 13 Sep 2026 05:18:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789301928; x=1789906728; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=q8szB8DqOyKitYp7jPFMXf9uh6tzDvRuFilkb29yz70=; b=Tbxihx3wStb1K03OaXNqWggND5m/aUaratKs4eY9wXjtAqVCM1mo3jByzCuvT71Yqw RxnGCVevMYngdGRKYich5bb2am9Wx5vG5cuxpu4FQ30WEIoiOI0KfThVYOOmX8RRTYYl u+dzxyw1u7V0X4ObPYbi2roc1OvbN4yvTlVmiIfU4Bhlp5OtqujgE7mBx0HdJp5uronk ogUEQbAOkrZoDXxGIXqM8B6/QygyKIciCQM/2dE3beFA9M3IXxScUHJqrgVcihhLB/ip Iz+bVXEzOhFEOISznhlR6IslpW9eZhPV8mQlRdQSLedpND9NKpowv9SW2+74P3EoXEZr gXLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789301928; x=1789906728; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=q8szB8DqOyKitYp7jPFMXf9uh6tzDvRuFilkb29yz70=; b=HjpNPtqkCXjv6CfnG+k9HLn33UaEy/KcbL3fP/QgQ2EPRP3lm3h63Okw5upkj+TAN5 PvF4CUP6VavAdcqSby9bKKuZGWOeUgOni8XmQGyNceXj1db3D+bS3Yn1JFC8TMLrxH+d FSNZDOfcJSLvMmqAuxg1kdDSHpeWseo/hDgAhDKrUpM7HKTCCd42UpI0BO7tHuQ7EAoQ TWT9ZHealspoI8tmO1WodFgsKmOpwUtMxKGacFC407TxfkZ5Pn4XZbT+409Nz0917QyO pu57+NAmx3jszJRUanIS/QI7xKtiJtpe3rMTaou82u+21twg+AgdEiMqMIiszDlA9IEL sXUQ== X-Forwarded-Encrypted: i=1; AKwUvBzqCDk/e4mgHm2i/uw+3VuchVE1s1NUq8pZ19KhzOdubNwtUiXCiM9Tqzf3cA5PGbRMQZO60e2HUQxt1pc=@vger.kernel.org X-Gm-Message-State: AFuF++lLIGJ5b0VlQ5RF8mvzp7RL17nuIA6wuB+ZpIHaHHJB8CLMistb eJa2YnV95hLkY3hxyQmx5YayQ5SCw9TLRN9o5J0KwAtO8sDF7JCP1JcT X-Gm-Gg: AYBFou1uObUau5mNK6x5k2rv9gH8gJWyREo2GLc0wUtxsQ74+R9EGKAy81tge0Q3hrJ 3+tGr3YrGFQebq6eyBPqQFpYdvmfD9jsNpv9znea2POHLm/ZNpr1T0Qwdyp0BqppQSKI05oNC7k KhGDzRCNbb3arocv9Iv35fwUm1xmj7j/C/t4/ZsGVZhijiKKx2Qc6urBa4jy7czx52CGX28aM/a ev8wEFEDN7RbVFqPeEsikMvQ8vcUEcIIEthyRlpfEwqcveNpZ8q8JSPZNea7oizMAnRdoiv4LL5 ooWy2zicVrUCnULYgDhYL02Tv0/fIaVueCX3YZ3mhKsiJOGgj6bJ9bOkoUYdEZjxeujSeWNgx0Q avl/jx9kaEAcosYbgVYpQOaZVN84FWYjH/T4XPWSEL+RsuGTeO8AbITYFmSXV+7w2tjruyXpJR0 cCjpjFOGZwFsBbPghRU9XO4SKQZhcvVH1j7N7S01UVBWbrmSvwvzNxq0GgBu1IF/hHh68LDmmn5 +zmz93bNb2F53U= X-Received: by 2002:a05:6000:402a:b0:486:f4ba:58d6 with SMTP id ffacd0b85a97d-486f6bedeb7mr5941438f8f.12.1789301927305; Sun, 13 Sep 2026 05:18:47 -0700 (PDT) Received: from [127.0.1.1] ([2001:4bb8:107:bfd1:de2c:7b4b:8652:b761]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-486eb2ecf2esm20241141f8f.2.2026.09.13.05.18.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Sep 2026 05:18:46 -0700 (PDT) From: Javier Carrasco Date: Sun, 13 Sep 2026 14:18:24 +0200 Subject: [PATCH v10 4/4] iio: light: veml6031x00: add support for events and trigger Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260913-veml6031x00-v10-4-adbc26c30d3d@gmail.com> References: <20260913-veml6031x00-v10-0-adbc26c30d3d@gmail.com> In-Reply-To: <20260913-veml6031x00-v10-0-adbc26c30d3d@gmail.com> To: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Javier Carrasco , Jonathan Cameron X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1789301917; l=24576; i=javier.carrasco.cruz@gmail.com; s=20260111; h=from:subject:message-id; bh=eZrm9VgPDfvj9NnGaY/C3bGlOsNzm2Q/fr2DsEYcE3s=; b=Vqhe+v5G6R8Nb72uIY/x7/x3Pa5IL91J/n713RQWTHajvogsN4+CdjD1HZgw/1lcDRbUSJiV0 WN9VJJTmQD+BJMIkG2dWRNvlOMV4VCMLQ62l7LS/TG9jH407ag6P7TA X-Developer-Key: i=javier.carrasco.cruz@gmail.com; a=ed25519; pk=Lge8w8xidNSf/INy7JAIbAW+Hezkp3nsBh2OjKL7lLU= The device provides a shared interrupt line to notify events and data ready. Add support for configurations with and without an interrupt line, providing events and trigger support when an interrupt line is available. Reviewed-by: Andy Shevchenko Signed-off-by: Javier Carrasco --- drivers/iio/light/veml6031x00.c | 604 ++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 597 insertions(+), 7 deletions(-) diff --git a/drivers/iio/light/veml6031x00.c b/drivers/iio/light/veml6031x0= 0.c index 3d5a27a0baae..085a6e2ff717 100644 --- a/drivers/iio/light/veml6031x00.c +++ b/drivers/iio/light/veml6031x00.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,9 @@ #include =20 #include +#include +#include +#include #include #include #include @@ -32,16 +36,28 @@ /* Device registers */ #define VEML6031X00_REG_CONF0 0x00 #define VEML6031X00_REG_CONF1 0x01 +#define VEML6031X00_REG_WH_L 0x04 +#define VEML6031X00_REG_WH_H 0x05 +#define VEML6031X00_REG_WL_L 0x06 +#define VEML6031X00_REG_WL_H 0x07 #define VEML6031X00_REG_ALS_L 0x10 #define VEML6031X00_REG_ALS_H 0x11 #define VEML6031X00_REG_IR_L 0x12 #define VEML6031X00_REG_IR_H 0x13 #define VEML6031X00_REG_ID_L 0x14 #define VEML6031X00_REG_ID_H 0x15 +#define VEML6031X00_REG_INT 0x17 =20 /* Bit masks for specific functionality */ #define VEML6031X00_CONF0_SD BIT(0) +#define VEML6031X00_CONF0_AF_TRIG BIT(2) +#define VEML6031X00_CONF0_AF BIT(3) #define VEML6031X00_CONF1_IR_SD BIT(7) +#define VEML6031X00_INT_TH_H BIT(1) +#define VEML6031X00_INT_TH_L BIT(2) +#define VEML6031X00_INT_DRDY BIT(3) +#define VEML6031X00_INT_MASK \ + (VEML6031X00_INT_TH_L | VEML6031X00_INT_TH_H | VEML6031X00_INT_DRDY) =20 #define VEML6031X00_GAIN_SEL(pd_div4, gain) (((pd_div4) << 2) | (gain)) =20 @@ -53,8 +69,10 @@ enum veml6031x00_scan { =20 struct veml6031x00_rf { struct regmap_field *gain; + struct regmap_field *int_en; struct regmap_field *it; struct regmap_field *pd_div4; + struct regmap_field *pers; }; =20 struct veml6031x00_chip { @@ -65,6 +83,7 @@ struct veml6031x00_chip { struct veml6031x00_data { struct iio_gts gts; struct regmap *regmap; + struct iio_trigger *trig; struct veml6031x00_rf rf; const struct veml6031x00_chip *chip; /* @@ -73,6 +92,14 @@ struct veml6031x00_data { * consistent set. */ struct mutex scale_lock; + /* + * Serialize access to irq enable/disable by events and trigger + * (shared line). + */ + struct mutex irq_lock; + unsigned int interrupt_users; + bool ev_en; + bool trig_en; }; =20 static const struct iio_itime_sel_mul veml6031x00_it_sel[] =3D { @@ -107,6 +134,17 @@ static const struct iio_gain_sel_pair veml6031x00_gain= _sel[] =3D { GAIN_SCALE_GAIN(16, VEML6031X00_SEL_GAIN_2_000), }; =20 +static IIO_CONST_ATTR(in_illuminance_thresh_either_period_available, "1 2 = 4 8"); + +static struct attribute *veml6031x00_event_attributes[] =3D { + &iio_const_attr_in_illuminance_thresh_either_period_available.dev_attr.at= tr, + NULL +}; + +static const struct attribute_group veml6031x00_event_attr_group =3D { + .attrs =3D veml6031x00_event_attributes, +}; + /* * The shutdown bits (SD and ALS_IR_SD) are in different registers, and bo= th * must be updated when changing the device power state. @@ -135,6 +173,23 @@ static void veml6031x00_als_shutdown_action(void *data) dev_warn(dev, "Failed to shut down device: %d\n", ret); } =20 +static const struct iio_event_spec veml6031x00_event_spec[] =3D { + { + .type =3D IIO_EV_TYPE_THRESH, + .dir =3D IIO_EV_DIR_RISING, + .mask_separate =3D BIT(IIO_EV_INFO_VALUE), + }, { + .type =3D IIO_EV_TYPE_THRESH, + .dir =3D IIO_EV_DIR_FALLING, + .mask_separate =3D BIT(IIO_EV_INFO_VALUE), + }, { + .type =3D IIO_EV_TYPE_THRESH, + .dir =3D IIO_EV_DIR_EITHER, + .mask_separate =3D BIT(IIO_EV_INFO_PERIOD) | + BIT(IIO_EV_INFO_ENABLE), + }, +}; + static const struct iio_chan_spec veml6031x00_channels[] =3D { { .type =3D IIO_LIGHT, @@ -169,9 +224,47 @@ static const struct iio_chan_spec veml6031x00_channels= [] =3D { IIO_CHAN_SOFT_TIMESTAMP(VEML6031X00_SCAN_TIMESTAMP), }; =20 +static const struct iio_chan_spec veml6031x00_channels_irq[] =3D { + { + .type =3D IIO_LIGHT, + .address =3D VEML6031X00_REG_ALS_L, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_separate_available =3D BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_SCALE), + .event_spec =3D veml6031x00_event_spec, + .num_event_specs =3D ARRAY_SIZE(veml6031x00_event_spec), + .scan_index =3D VEML6031X00_SCAN_ALS, + .scan_type =3D { + .format =3D IIO_SCAN_FORMAT_UNSIGNED_INT, + .realbits =3D 16, + .storagebits =3D 16, + .endianness =3D IIO_LE, + }, + }, + { + .type =3D IIO_INTENSITY, + .address =3D VEML6031X00_REG_IR_L, + .modified =3D 1, + .channel2 =3D IIO_MOD_LIGHT_IR, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW), + .scan_index =3D VEML6031X00_SCAN_IR, + .scan_type =3D { + .format =3D IIO_SCAN_FORMAT_UNSIGNED_INT, + .realbits =3D 16, + .storagebits =3D 16, + .endianness =3D IIO_LE, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(VEML6031X00_SCAN_TIMESTAMP), +}; + static const struct regmap_range veml6031x00_readable_ranges[] =3D { regmap_reg_range(VEML6031X00_REG_CONF0, VEML6031X00_REG_CONF1), + regmap_reg_range(VEML6031X00_REG_WH_L, VEML6031X00_REG_WL_H), regmap_reg_range(VEML6031X00_REG_ALS_L, VEML6031X00_REG_ID_H), + regmap_reg_range(VEML6031X00_REG_INT, VEML6031X00_REG_INT), }; =20 static const struct regmap_access_table veml6031x00_readable_table =3D { @@ -181,6 +274,7 @@ static const struct regmap_access_table veml6031x00_rea= dable_table =3D { =20 static const struct regmap_range veml6031x00_writable_ranges[] =3D { regmap_reg_range(VEML6031X00_REG_CONF0, VEML6031X00_REG_CONF1), + regmap_reg_range(VEML6031X00_REG_WH_L, VEML6031X00_REG_WL_H), }; =20 static const struct regmap_access_table veml6031x00_writable_table =3D { @@ -192,6 +286,7 @@ static const struct regmap_range veml6031x00_volatile_r= anges[] =3D { /* AF_TRIG in CONF0 is volatile */ regmap_reg_range(VEML6031X00_REG_CONF0, VEML6031X00_REG_CONF0), regmap_reg_range(VEML6031X00_REG_ALS_L, VEML6031X00_REG_IR_H), + regmap_reg_range(VEML6031X00_REG_INT, VEML6031X00_REG_INT), }; =20 static const struct regmap_access_table veml6031x00_volatile_table =3D { @@ -199,6 +294,15 @@ static const struct regmap_access_table veml6031x00_vo= latile_table =3D { .n_yes_ranges =3D ARRAY_SIZE(veml6031x00_volatile_ranges), }; =20 +static const struct regmap_range veml6031x00_precious_ranges[] =3D { + regmap_reg_range(VEML6031X00_REG_INT, VEML6031X00_REG_INT), +}; + +static const struct regmap_access_table veml6031x00_precious_table =3D { + .yes_ranges =3D veml6031x00_precious_ranges, + .n_yes_ranges =3D ARRAY_SIZE(veml6031x00_precious_ranges), +}; + static const struct regmap_config veml6031x00_regmap_config =3D { .name =3D "veml6031x00_regmap", .reg_bits =3D 8, @@ -206,13 +310,20 @@ static const struct regmap_config veml6031x00_regmap_= config =3D { .rd_table =3D &veml6031x00_readable_table, .wr_table =3D &veml6031x00_writable_table, .volatile_table =3D &veml6031x00_volatile_table, - .max_register =3D VEML6031X00_REG_ID_H, + .precious_table =3D &veml6031x00_precious_table, + .max_register =3D VEML6031X00_REG_INT, .cache_type =3D REGCACHE_MAPLE, }; =20 +static const struct reg_field veml6031x00_rf_int_en =3D + REG_FIELD(VEML6031X00_REG_CONF0, 1, 1); + static const struct reg_field veml6031x00_rf_it =3D REG_FIELD(VEML6031X00_REG_CONF0, 4, 6); =20 +static const struct reg_field veml6031x00_rf_pers =3D + REG_FIELD(VEML6031X00_REG_CONF1, 1, 2); + static const struct reg_field veml6031x00_rf_gain =3D REG_FIELD(VEML6031X00_REG_CONF1, 3, 4); =20 @@ -236,11 +347,21 @@ static int veml6031x00_regfield_init(struct veml6031x= 00_data *data) return PTR_ERR(rm_field); rf->it =3D rm_field; =20 + rm_field =3D devm_regmap_field_alloc(dev, map, veml6031x00_rf_int_en); + if (IS_ERR(rm_field)) + return PTR_ERR(rm_field); + rf->int_en =3D rm_field; + rm_field =3D devm_regmap_field_alloc(dev, map, veml6031x00_rf_pd_div4); if (IS_ERR(rm_field)) return PTR_ERR(rm_field); rf->pd_div4 =3D rm_field; =20 + rm_field =3D devm_regmap_field_alloc(dev, map, veml6031x00_rf_pers); + if (IS_ERR(rm_field)) + return PTR_ERR(rm_field); + rf->pers =3D rm_field; + return 0; } =20 @@ -341,6 +462,31 @@ static int veml6031x00_set_it(struct iio_dev *iio, int= val, int val2) return veml6031x00_write_gain(data, gain_sel); } =20 +static int veml6031x00_read_period(struct iio_dev *iio, int *val) +{ + struct veml6031x00_data *data =3D iio_priv(iio); + unsigned int regval; + int ret; + + ret =3D regmap_field_read(data->rf.pers, ®val); + if (ret) + return ret; + + *val =3D BIT(regval); + + return IIO_VAL_INT; +} + +static int veml6031x00_write_period(struct iio_dev *iio, int val) +{ + struct veml6031x00_data *data =3D iio_priv(iio); + + if (val < 0 || val > 8 || !is_power_of_2(val)) + return -EINVAL; + + return regmap_field_write(data->rf.pers, ilog2(val)); +} + static int veml6031x00_set_scale(struct iio_dev *iio, int val, int val2) { struct veml6031x00_data *data =3D iio_priv(iio); @@ -395,6 +541,55 @@ static int veml6031x00_get_scale(struct veml6031x00_da= ta *data, int *val, int *v return IIO_VAL_INT_PLUS_NANO; } =20 +static int veml6031x00_read_th(struct iio_dev *iio, enum iio_event_directi= on dir, + int *val, int *val2) +{ + struct veml6031x00_data *data =3D iio_priv(iio); + __le16 regval; + int ret; + + if (dir =3D=3D IIO_EV_DIR_RISING) + ret =3D regmap_bulk_read(data->regmap, VEML6031X00_REG_WH_L, + ®val, sizeof(regval)); + else + ret =3D regmap_bulk_read(data->regmap, VEML6031X00_REG_WL_L, + ®val, sizeof(regval)); + if (ret) + return ret; + + *val =3D le16_to_cpu(regval); + + return IIO_VAL_INT; +} + +static int veml6031x00_write_th(struct iio_dev *iio, enum iio_event_direct= ion dir, + int val, int val2) +{ + struct veml6031x00_data *data =3D iio_priv(iio); + struct device *dev =3D regmap_get_device(data->regmap); + __le16 regval; + int ret; + + if (val < 0 || val > U16_MAX || val2) + return -EINVAL; + + regval =3D cpu_to_le16(val); + + if (dir =3D=3D IIO_EV_DIR_RISING) { + ret =3D regmap_bulk_write(data->regmap, VEML6031X00_REG_WH_L, + ®val, sizeof(regval)); + if (ret) + dev_dbg(dev, "Failed to set high threshold %d\n", ret); + } else { + ret =3D regmap_bulk_write(data->regmap, VEML6031X00_REG_WL_L, + ®val, sizeof(regval)); + if (ret) + dev_dbg(dev, "Failed to set low threshold %d\n", ret); + } + + return ret; +} + static int veml6031x00_single_read(struct iio_dev *iio, enum iio_chan_type= type, int *val) { @@ -509,13 +704,243 @@ static int veml6031x00_write_raw_get_fmt(struct iio_= dev *indio_dev, } } =20 +static int veml6031x00_set_interrupt(struct veml6031x00_data *data, bool s= tate) + __must_hold(&data->irq_lock) +{ + int ret; + + lockdep_assert_held(&data->irq_lock); + + if (state) { + data->interrupt_users++; + if (data->interrupt_users > 1) + return 0; + } else { + if (!data->interrupt_users) + return 0; + + data->interrupt_users--; + if (data->interrupt_users > 0) + return 0; + } + + ret =3D regmap_field_write(data->rf.int_en, state); + if (ret) { + if (state) + data->interrupt_users--; + else + data->interrupt_users++; + } + + return ret; +} + +static int veml6031x00_read_event_val(struct iio_dev *iio, + 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) +{ + switch (type) { + case IIO_EV_TYPE_THRESH: + if (dir =3D=3D IIO_EV_DIR_EITHER && info =3D=3D IIO_EV_INFO_PERIOD) + return veml6031x00_read_period(iio, val); + + return veml6031x00_read_th(iio, dir, val, val2); + default: + return -EINVAL; + } +} + +static int veml6031x00_write_event_val(struct iio_dev *iio, + 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) +{ + switch (info) { + case IIO_EV_INFO_VALUE: + return veml6031x00_write_th(iio, dir, val, val2); + case IIO_EV_INFO_PERIOD: + return veml6031x00_write_period(iio, val); + default: + return -EINVAL; + } +} + +static int veml6031x00_read_event_config(struct iio_dev *iio, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct veml6031x00_data *data =3D iio_priv(iio); + + guard(mutex)(&data->irq_lock); + + return data->ev_en; +} + +static int veml6031x00_event_enable(struct veml6031x00_data *data) +{ + struct device *dev =3D regmap_get_device(data->regmap); + int ret; + + ret =3D pm_runtime_resume_and_get(dev); + if (ret) + return ret; + + ret =3D veml6031x00_set_interrupt(data, true); + if (ret) { + pm_runtime_put_autosuspend(dev); + return ret; + } + + data->ev_en =3D true; + + return 0; +} + +static int veml6031x00_event_disable(struct veml6031x00_data *data) +{ + struct device *dev =3D regmap_get_device(data->regmap); + int ret; + + ret =3D veml6031x00_set_interrupt(data, false); + if (ret) + return ret; + + data->ev_en =3D false; + pm_runtime_put_autosuspend(dev); + + return 0; +} + +static int veml6031x00_write_event_config(struct iio_dev *iio, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + bool state) +{ + struct veml6031x00_data *data =3D iio_priv(iio); + + guard(mutex)(&data->irq_lock); + + /* avoid multiple increments/decrements from one source */ + if (state =3D=3D data->ev_en) + return 0; + + if (state) + return veml6031x00_event_enable(data); + + return veml6031x00_event_disable(data); +} + +static void veml6031x00_disable_event_action(void *arg) +{ + struct veml6031x00_data *data =3D arg; + struct device *dev =3D regmap_get_device(data->regmap); + int ret; + + guard(mutex)(&data->irq_lock); + + if (!data->ev_en) + return; + + ret =3D veml6031x00_set_interrupt(data, false); + if (ret) + dev_err(dev, "Failed to disable events: %d\n", ret); + else + data->ev_en =3D false; + + pm_runtime_put_sync(dev); +} + static const struct iio_info veml6031x00_info =3D { .read_raw =3D veml6031x00_read_raw, .read_avail =3D veml6031x00_read_avail, .write_raw =3D veml6031x00_write_raw, .write_raw_get_fmt =3D veml6031x00_write_raw_get_fmt, + .read_event_value =3D veml6031x00_read_event_val, + .write_event_value =3D veml6031x00_write_event_val, + .read_event_config =3D veml6031x00_read_event_config, + .write_event_config =3D veml6031x00_write_event_config, + .event_attrs =3D &veml6031x00_event_attr_group, }; =20 +static const struct iio_info veml6031x00_info_no_irq =3D { + .read_raw =3D veml6031x00_read_raw, + .read_avail =3D veml6031x00_read_avail, + .write_raw =3D veml6031x00_write_raw, + .write_raw_get_fmt =3D veml6031x00_write_raw_get_fmt, +}; + +static irqreturn_t veml6031x00_irq(int irq, void *private) +{ + struct iio_dev *iio =3D private; + struct veml6031x00_data *data =3D iio_priv(iio); + struct device *dev =3D regmap_get_device(data->regmap); + s64 timestamp; + unsigned int regval; + int ret; + bool trigger_poll; + + ret =3D pm_runtime_get_if_active(dev); + if (ret <=3D 0) + return IRQ_NONE; + + scoped_guard(mutex, &data->irq_lock) { + ret =3D regmap_read(data->regmap, VEML6031X00_REG_INT, ®val); + if (ret) { + dev_dbg(dev, "Failed to read interrupt register %d\n", ret); + pm_runtime_put(dev); + return IRQ_NONE; + } + + if (!(regval & VEML6031X00_INT_MASK)) { + pm_runtime_put(dev); + return IRQ_NONE; + } + + timestamp =3D iio_get_time_ns(iio); + + if (data->ev_en && + (regval & (VEML6031X00_INT_TH_H | VEML6031X00_INT_TH_L))) { + if (regval & VEML6031X00_INT_TH_H) + iio_push_event(iio, + IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + timestamp); + if (regval & VEML6031X00_INT_TH_L) + iio_push_event(iio, + IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + timestamp); + } + + trigger_poll =3D data->trig_en && (regval & VEML6031X00_INT_DRDY); + } + + /* + * iio_trigger_poll_nested() must be called with irq_lock released: + * it runs trig_handler() synchronously in this thread, which calls + * reenable() on completion, and that callback also takes irq_lock. + * iio_pollfunc_store_time() is not called for our own trigger, so the + * timestamp is stored here. + */ + if (trigger_poll) { + iio->pollfunc->timestamp =3D timestamp; + iio_trigger_poll_nested(data->trig); + } + + pm_runtime_put(dev); + + return IRQ_HANDLED; +} + static int veml6031x00_buffer_preenable(struct iio_dev *iio) { struct veml6031x00_data *data =3D iio_priv(iio); @@ -551,11 +976,85 @@ static int veml6031x00_buffer_postdisable(struct iio_= dev *iio) return 0; } =20 +static int __veml6031x00_set_trigger_state(struct veml6031x00_data *data, + bool state) + __must_hold(&data->irq_lock) +{ + int ret; + + lockdep_assert_held(&data->irq_lock); + + ret =3D veml6031x00_set_interrupt(data, state); + if (ret) + return ret; + + /* The AF bit must be updated before updating AF_TRIG */ + ret =3D regmap_assign_bits(data->regmap, VEML6031X00_REG_CONF0, + VEML6031X00_CONF0_AF, state); + if (ret) + goto disable_trigger; + + ret =3D regmap_assign_bits(data->regmap, VEML6031X00_REG_CONF0, + VEML6031X00_CONF0_AF_TRIG, state); + if (ret) { + regmap_assign_bits(data->regmap, VEML6031X00_REG_CONF0, + VEML6031X00_CONF0_AF, false); + goto disable_trigger; + } + + data->trig_en =3D state; + + return 0; + +disable_trigger: + data->trig_en =3D false; + if (state) + veml6031x00_set_interrupt(data, false); + return ret; +} + +static int veml6031x00_set_trigger_state(struct iio_trigger *trig, bool st= ate) +{ + struct iio_dev *iio =3D iio_trigger_get_drvdata(trig); + struct veml6031x00_data *data =3D iio_priv(iio); + + guard(mutex)(&data->irq_lock); + + if (state =3D=3D data->trig_en) + return 0; + + return __veml6031x00_set_trigger_state(data, state); +} + static const struct iio_buffer_setup_ops veml6031x00_buffer_setup_ops =3D { .preenable =3D veml6031x00_buffer_preenable, .postdisable =3D veml6031x00_buffer_postdisable, }; =20 +static void veml6031x00_trigger_reenable(struct iio_trigger *trig) +{ + struct iio_dev *iio =3D iio_trigger_get_drvdata(trig); + struct veml6031x00_data *data =3D iio_priv(iio); + int ret; + + guard(mutex)(&data->irq_lock); + + if (!data->trig_en) + return; + + ret =3D regmap_assign_bits(data->regmap, VEML6031X00_REG_CONF0, + VEML6031X00_CONF0_AF_TRIG, true); + if (ret) + dev_err(regmap_get_device(data->regmap), + "Failed to reenable trigger: %d\n", ret); +} + +static const struct iio_trigger_ops veml6031x00_trigger_ops =3D { + .validate_device =3D iio_trigger_validate_own_device, + .set_trigger_state =3D veml6031x00_set_trigger_state, + .reenable =3D veml6031x00_trigger_reenable, +}; + static irqreturn_t veml6031x00_trig_handler(int irq, void *p) { struct iio_poll_func *pf =3D p; @@ -609,6 +1108,84 @@ static int veml6031x00_validate_part_id(struct veml60= 31x00_data *data) return 0; } =20 +static int veml6031x00_hw_init(struct veml6031x00_data *data) +{ + struct regmap *map =3D data->regmap; + struct device *dev =3D regmap_get_device(map); + unsigned int val; + __le16 regval; + int ret; + + ret =3D regmap_assign_bits(data->regmap, VEML6031X00_REG_CONF0, + VEML6031X00_CONF0_AF | VEML6031X00_CONF0_AF_TRIG, 0); + if (ret) + return dev_err_probe(dev, ret, "Failed to disable trigger\n"); + + regval =3D 0; + ret =3D regmap_bulk_write(map, VEML6031X00_REG_WL_L, ®val, sizeof(regv= al)); + if (ret) + return dev_err_probe(dev, ret, "Failed to set low threshold\n"); + + regval =3D cpu_to_le16(U16_MAX); + ret =3D regmap_bulk_write(map, VEML6031X00_REG_WH_L, ®val, sizeof(regv= al)); + if (ret) + return dev_err_probe(dev, ret, "Failed to set high threshold\n"); + + ret =3D regmap_field_write(data->rf.int_en, 0); + if (ret) + return ret; + + ret =3D regmap_read(map, VEML6031X00_REG_INT, &val); + if (ret) + return dev_err_probe(dev, ret, "Failed to clear interrupts\n"); + + return 0; +} + +static int veml6031x00_setup_trigger(struct iio_dev *iio) +{ + struct veml6031x00_data *data =3D iio_priv(iio); + struct device *dev =3D regmap_get_device(data->regmap); + + data->trig =3D devm_iio_trigger_alloc(dev, "%s-drdy%d", + iio->name, iio_device_id(iio)); + if (!data->trig) + return -ENOMEM; + + data->trig->ops =3D &veml6031x00_trigger_ops; + iio_trigger_set_drvdata(data->trig, iio); + + return devm_iio_trigger_register(dev, data->trig); +} + +static int veml6031x00_init_iiodev(struct i2c_client *i2c, struct iio_dev = *iio) +{ + struct veml6031x00_data *data =3D iio_priv(iio); + struct device *dev =3D regmap_get_device(data->regmap); + int ret; + + iio->name =3D data->chip->name; + iio->modes =3D INDIO_DIRECT_MODE; + + if (!i2c->irq) { + iio->channels =3D veml6031x00_channels; + iio->num_channels =3D ARRAY_SIZE(veml6031x00_channels); + iio->info =3D &veml6031x00_info_no_irq; + + return 0; + } + + iio->channels =3D veml6031x00_channels_irq; + iio->num_channels =3D ARRAY_SIZE(veml6031x00_channels_irq); + iio->info =3D &veml6031x00_info; + + ret =3D veml6031x00_setup_trigger(iio); + if (ret) + return ret; + + return devm_add_action_or_reset(dev, veml6031x00_disable_event_action, da= ta); +} + static int veml6031x00_probe(struct i2c_client *i2c) { struct device *dev =3D &i2c->dev; @@ -631,17 +1208,15 @@ static int veml6031x00_probe(struct i2c_client *i2c) if (ret) return ret; =20 + ret =3D devm_mutex_init(dev, &data->irq_lock); + if (ret) + return ret; + data->regmap =3D devm_regmap_init_i2c(i2c, &veml6031x00_regmap_config); if (IS_ERR(data->regmap)) return dev_err_probe(dev, PTR_ERR(data->regmap), "Failed to set regmap\n"); =20 - iio->name =3D data->chip->name; - iio->channels =3D veml6031x00_channels; - iio->num_channels =3D ARRAY_SIZE(veml6031x00_channels); - iio->modes =3D INDIO_DIRECT_MODE; - iio->info =3D &veml6031x00_info; - ret =3D veml6031x00_regfield_init(data); if (ret) return dev_err_probe(dev, ret, "Failed to init regfield\n"); @@ -669,6 +1244,10 @@ static int veml6031x00_probe(struct i2c_client *i2c) if (ret) return ret; =20 + ret =3D veml6031x00_hw_init(data); + if (ret) + return ret; + /* Max resolution =3D 6.9632 lx/cnt for gain =3D 0.125 and IT =3D 3.125ms= */ ret =3D devm_iio_init_iio_gts(dev, 6, 963200000, veml6031x00_gain_sel, @@ -679,6 +1258,10 @@ static int veml6031x00_probe(struct i2c_client *i2c) if (ret) return dev_err_probe(dev, ret, "Failed to init IIO GTS\n"); =20 + ret =3D veml6031x00_init_iiodev(i2c, iio); + if (ret) + return dev_err_probe(dev, ret, "Failed to initialize IIO device\n"); + ret =3D devm_iio_triggered_buffer_setup(dev, iio, iio_pollfunc_store_time, veml6031x00_trig_handler, @@ -686,6 +1269,13 @@ static int veml6031x00_probe(struct i2c_client *i2c) if (ret) return dev_err_probe(dev, ret, "Failed to register triggered buffer\n"); =20 + if (i2c->irq) { + ret =3D devm_request_threaded_irq(dev, i2c->irq, NULL, veml6031x00_irq, + IRQF_ONESHOT, iio->name, iio); + if (ret) + return dev_err_probe(dev, ret, "Failed to request IRQ\n"); + } + ret =3D devm_iio_device_register(dev, iio); if (ret) return dev_err_probe(dev, ret, "Failed to register IIO device\n"); --=20 2.43.0