From patchwork Wed Feb 19 12:30:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 13982055 Received: from mail-lj1-f173.google.com (mail-lj1-f173.google.com [209.85.208.173]) (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 105AF1CAA85; Wed, 19 Feb 2025 12:30:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968220; cv=none; b=M7TfCtuosaRrCoGTo4LvfriuiV74AhpHqjqiDVExihviugPESf29pOeeENvr7w0OGol+JRmr5IiH1Ui0jilfT8rYQSYxz/81LVOGHQWhQ1UwA5/4crk96iEYtA7kShTgxfF2Ilug/RMGD1DkK3U3XnzaHexmfpH476vpQUbO6pA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968220; c=relaxed/simple; bh=3gWSTns6gMmB1JQU1DSavPgSrppmWBtW/fPGFzLygso=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=iRJlXh6V08q06QZqMat7wD9zJ5Rl1lD2yxy0fe+aCGOrgcQkZweUPMnecMZ8Jnfh/p1kOXrfPV8PzCljQ99rneyOjXbKjzzvYK4DxVuEEpP5YPEkFiM9Hb0Y8pG6f65Cj+7zDFdf5bfcqAnokjrSFSR3PaCRml4zuC0l3bo2Tf0= 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=FLvFn57X; arc=none smtp.client-ip=209.85.208.173 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="FLvFn57X" Received: by mail-lj1-f173.google.com with SMTP id 38308e7fff4ca-30930b0b420so38840261fa.2; Wed, 19 Feb 2025 04:30:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739968217; x=1740573017; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=1hUrd+Gyy/ajIhuvrP2MqW/IazkO3sAPZGITYXZm04k=; b=FLvFn57Xg0E7pm28+Im79KZEtJ10U3kbuvxsSCBH8+8Ml+KwWCWmvIPE2v0H6DsOJH KoVG6oBmemXCnWhId22okS3n2T8gFExUpPSSfBs4jp//SzGBlGmGaYVAqjeUte09C51U w3lmhSZmmr78DpD7ELWIfNiuWPWv5lvUJfYxKMwNYlTSlzzL4HeTIN1IQm/y0zNy5dhv 33tMyBVYxW6Ipb651R58DOzvNbOdj/+g8Lg+wvBurm5Xn7kS7qzPvDtd9Xvfch1YRfk1 PyyJWl8dTgUwulz5aSXp9TmgZZdgJhLxKqTcjlQDCDzOXWxdmQD9T2ba/oA9P6CYQiJU mWSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739968217; x=1740573017; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=1hUrd+Gyy/ajIhuvrP2MqW/IazkO3sAPZGITYXZm04k=; b=YM+tMSI0BdPGOIx4068FaHmMoGTMvX2ttzXtuBo+DSloN2PlVy4PzoKuQPjw84O+ek k4bOc9vjJFK+2e3ZeL/Wu/qvZZwQruuCf1c/n5nSVhftRzk9dA7OvaECBYH7UOKczHiS dCBbDFUsqjnAlA5i8i8LFz1WE4ijPjt+Eod7Dr6VEXniujzCjDCr+HOMBTpit0b3+0yw 8VcBSQhDzxfqdeO27FWmpvM3oNP/dEAwXFIbRGvsFKbjpawfi0qK+OLu/qqdgu01MynI w5tGyn2hDSa5Husld93XsH2jWK7Xbwto+nLkA4YpNbQeQJkPc2phq4CEilHtDEovBFbi zpKg== X-Forwarded-Encrypted: i=1; AJvYcCU3wj2m6u6vzb8Zv8y4FoHjEngoWWMRxMKo82MxMp4DS3tDdB0tJIV1PcSnHjyjJDaIbAbLYkP8/2Bz@vger.kernel.org, AJvYcCUOPDDp4XNiITH4rhr1sMx+XE3NCBlgtS0otlw5692QerEbRW9rRakCNrt+ZoghpX5XLg/WIaqGE36w@vger.kernel.org, AJvYcCVG1Nl9oVsr3fTha9CXT2z4FtjmHPJUuHlr2cnZr96lJTruL5oOvjHSt6+2aj9s3oiIDuNWzvdHp5pcYXwGIZEhb4c=@vger.kernel.org, AJvYcCWr1dlbAiUfpVajAb9EFOsUIY1XfeMIapC8Z8jxJYo3oHJ/2PoeVQ5LEhtN7ONvGhhxKWx7du7p/ymvOIAy@vger.kernel.org X-Gm-Message-State: AOJu0YxFDA3giiMdQ9+t7lyWC1aR9HuBtbAGdKUxltqy7d6wfrOa8qK3 yNWSJOai5WAW16RK0psMhbOUG2o6Lm7QJHUhF+UcF5lqj7S8ic/M X-Gm-Gg: ASbGncuOHPj48n3w9lqze58PtZXUW4+l3CnSKfLgbe0PrrZgJnR+/OegN4J1rxLtk1a bgdMAookgLIW8kKbDp8XkMub+QdHnSmVxF76ubY0+1Kzp3LdFX/DtRAzWL0QdaV2VssljoZKdg2 4x+kd4/neDTd8uzSV33pD9/a4btqW3JYK1okZhwVzbJQyVn1BqlAKUeJkkzXNUK8hhYk9iA4Rs3 SBN5FqG8lUtb5zPSY/m7FjV/B692+xzq9+U7SQ9gY/5Q7Bc8NFmTePcWHszDd7Qtr5QF0N+p741 qGJpHjKiX3xgMj4UWJVcUQ== X-Google-Smtp-Source: AGHT+IFF8ZAOezRn1kWhpmBq+gPrOLGIPq15CfW2c+RFEDW/9HuXUxU0qk6Hp+MJg1WFZfej+FArLQ== X-Received: by 2002:a2e:b176:0:b0:309:25f6:8dcb with SMTP id 38308e7fff4ca-30a44dbb334mr9639561fa.5.1739968216796; Wed, 19 Feb 2025 04:30:16 -0800 (PST) Received: from mva-rohm ([2a10:a5c0:800d:dd00:8fdf:935a:2c85:d703]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-309e57cc68esm13923301fa.114.2025.02.19.04.30.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Feb 2025 04:30:14 -0800 (PST) Date: Wed, 19 Feb 2025 14:30:09 +0200 From: Matti Vaittinen To: Matti Vaittinen , Matti Vaittinen Cc: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matti Vaittinen , Lad Prabhakar , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Hugo Villeneuve , Nuno Sa , David Lechner , Javier Carrasco , Andy Shevchenko , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev Subject: [PATCH v3 1/9] dt-bindings: ROHM BD79124 ADC/GPO Message-ID: <52db5ddb99dcd8da847f8fe595efa74c3ab1573c.1739967040.git.mazziesaccount@gmail.com> References: Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Add binding document for the ROHM BD79124 ADC / GPO. ROHM BD79124 is a 8-channel, 12-bit ADC. The input pins can also be used as general purpose outputs. Signed-off-by: Matti Vaittinen Reviewed-by: Conor Dooley --- Revision history: v2 => v3: - Restrict channel numbers to 0-7 as suggested by Conor RFC v1 => v2: - drop MFD and represent directly as ADC - drop pinmux and treat all non ADC channel pins as GPOs --- .../bindings/iio/adc/rohm,bd79124.yaml | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/rohm,bd79124.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/rohm,bd79124.yaml b/Documentation/devicetree/bindings/iio/adc/rohm,bd79124.yaml new file mode 100644 index 000000000000..503285823376 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/rohm,bd79124.yaml @@ -0,0 +1,114 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/rohm,bd79124.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ROHM BD79124 ADC/GPO + +maintainers: + - Matti Vaittinen + +description: | + The ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports + an automatic measurement mode, with an alarm interrupt for out-of-window + measurements. ADC input pins can be also configured as general purpose + outputs. + +properties: + compatible: + const: rohm,bd79124 + + reg: + description: + I2C slave address. + maxItems: 1 + + interrupts: + maxItems: 1 + + gpio-controller: true + + "#gpio-cells": + const: 1 + description: + The pin number. + + vdd-supply: true + + iovdd-supply: true + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +patternProperties: + "^channel@[0-7]+$": + type: object + $ref: /schemas/iio/adc/adc.yaml# + description: Represents ADC channel. + + properties: + reg: + description: AIN pin number + minimum: 0 + maximum: 7 + + required: + - reg + + additionalProperties: false + +required: + - compatible + - reg + - iovdd-supply + - vdd-supply + +additionalProperties: false + +examples: + - | + #include + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + adc: adc@10 { + compatible = "rohm,bd79124"; + reg = <0x10>; + + interrupt-parent = <&gpio1>; + interrupts = <29 8>; + + vdd-supply = <&dummyreg>; + iovdd-supply = <&dummyreg>; + + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + }; + channel@1 { + reg = <1>; + }; + channel@2 { + reg = <2>; + }; + channel@3 { + reg = <3>; + }; + channel@4 { + reg = <4>; + }; + channel@5 { + reg = <5>; + }; + channel@6 { + reg = <6>; + }; + }; + }; From patchwork Wed Feb 19 12:30:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 13982065 Received: from mail-lj1-f169.google.com (mail-lj1-f169.google.com [209.85.208.169]) (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 9DD821D5AC0; Wed, 19 Feb 2025 12:30:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968239; cv=none; b=Td7rKXGhY0ArJuH3fH10SjJNWsJnqAdiG5dVuwBF868OQ+9ZpZ7LHiB2y/nEW7prveD/f61uXbxkcCtHnpexgPlbCd/k5nni7PM4AdSwvSURH4uRErD1j5P8BE6UdSmcMg7Ti31JGIemZVW1cFc3IzUN5WTyduNMUIeeN5VE5R0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968239; c=relaxed/simple; bh=tgTP6swMute83bKTBlLKzUP6WGhz4RuTtl2RaWC6gak=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=NhLbQPZH+dutD4955ZdLQwTFKQiSMIy98/NnSSQd1dOUZsgFKMQiimPAr+fq1RupgUzrHWV/JpfHh0OwkT0/SUSsPwaxPT7Z7lXkiEc7/r5BapveGQIrfBcBEmaTbGQwgsBaq88u6AoEFvv3p4G7foRgL5UPwNAELCCCX/mJZpQ= 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=j3J4DYOy; arc=none smtp.client-ip=209.85.208.169 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="j3J4DYOy" Received: by mail-lj1-f169.google.com with SMTP id 38308e7fff4ca-307c13298eeso9308851fa.0; Wed, 19 Feb 2025 04:30:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739968234; x=1740573034; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=+gRANWQiTUbafkGO9fwshwTqOYl/mRZcDzeC9SF4EWE=; b=j3J4DYOyS3tV8HS9DZxJWqboEhjBCgJBU619kkJaVDNXxmzF/Uh9Xeo8uBWsKPIFL+ aGtJOK9hVgPV5dDdm+7s2nBODmuU3+fQEUpwf86N6oG10rqplhLWrPlml4rz5AL41X03 1S5CwiqktAm9Jj23CRG7YuOd2Qm3nunFxYTwNNQstnRZzGvsXVxciU1dQNaO1dSOtwEh w3w+Q81lGxeRPdJ3iPjDN18Q6tLipMrlUy/NXuG0bODWG1q0ZWh5huQU/YgSYGB+ksPx kgriGa6jfdZAzRhOQKBSE4mttD8zp+yG4rBmGJfGbkDY1mV3E+tNas5tP4BIc/5HT9CG dzvQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739968234; x=1740573034; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=+gRANWQiTUbafkGO9fwshwTqOYl/mRZcDzeC9SF4EWE=; b=jomZEvE0pS//dWD4/yinTmnguoQqY5p/5+H5rfmH+3RA64SiXL1QYyctj0TkRTeMDU VJW0w2huQ0yc7TaxO/+8KcxtN86Q6H7HfWNFhQl0abE4dyldEqsjXkyDuM7glZBQyLwC uTHY5ZyYxcvBDXaB1QEFFkF0n446RRszMzeATtzb9hxSlp84ku2V0YZ0TUUot31zSe7t 2e7McF73Rx0V2UFZkWmAtsSXbnI9T87zDvzxEt4WFheIAP5L7S+dgERgenOfE3fn9sej /tdIZAfooSOG1wc52+rppCingYpbyZYnzqOa3QeaQRladpcStR6VYm2INB7vXxI4WlTv ApKA== X-Forwarded-Encrypted: i=1; AJvYcCUA21GDtTSUVAxgxNRPLRey4kJbkec/E9KLq90Wwtle1iTr8D9pymjrihJH1HrQOKqPEeQZR1jOmC41UAvS@vger.kernel.org, AJvYcCVQSoj57MgeVTd0/buwnuces88oMBoVB6HTMmJvCeRtbl/JQRQFjLYsgU0fXOLu8Dq0SQrsC4K4TKSc@vger.kernel.org, AJvYcCWMBA9AgcdfSAM5Xi9u/q23vzvH+uvtg015yWla3lxOimsU0q2Gi+gIvgSgwhBVhL0/5iKIUN94uL82@vger.kernel.org, AJvYcCX4vPeTa8hix/iP7lnlteTFsS1IVqdX1dwbCGN/BpUWrbAMoWe0ZDCCjfFN+FiAZJlpbK+aLXjb7HJETt5TZde09cQ=@vger.kernel.org X-Gm-Message-State: AOJu0Yye0iSbJoEEh8OA4ATrwWO1gLiv++zNn1P8drBDhVlgsYGnzarA kDbcw9M1kEg9B2cA3SgMDB4rheOAGLm1Soz/xXX9ytNBoejoxQrU X-Gm-Gg: ASbGncvZmzQBUc6JGJgsA/3HMYNBRPhQuxFd7CKqLElTPh4hFoxuma3dK8mU4ZRbpO6 Q5zHDCcCEboL6nccjtHxOy/zTZ091z0rlkDMkCJau7zJRpgrv29IZLy/lattfn3hfuIUOluDNIN VaDlGKhA4IeMB2Z3DcdG4CdcnL9UxRa+rzhfvXKE0uXzf0FfrXzgQNyxwkxB2bVSh3Cn709AHL1 PDNQBGr4265YINe5ubKB+RNAKoUWC0KPSz0vFLWsOA/qHqzFERHkZJWJXlpp9lQyVVqoLPjkGad Wk8XPnuHYT3PSh/D1jGwIw== X-Google-Smtp-Source: AGHT+IHMuqGjJPJmwx6XEk4wd+AYe/hAr14LA7ZB3GETJw2tINvrS45+HcCU40rfNoKlPNXMWabz/g== X-Received: by 2002:a2e:9f15:0:b0:309:2696:c293 with SMTP id 38308e7fff4ca-30a440f8e73mr13589371fa.4.1739968233293; Wed, 19 Feb 2025 04:30:33 -0800 (PST) Received: from mva-rohm ([2a10:a5c0:800d:dd00:8fdf:935a:2c85:d703]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-30a3ce198e6sm5776661fa.3.2025.02.19.04.30.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Feb 2025 04:30:31 -0800 (PST) Date: Wed, 19 Feb 2025 14:30:27 +0200 From: Matti Vaittinen To: Matti Vaittinen , Matti Vaittinen Cc: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matti Vaittinen , Lad Prabhakar , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Hugo Villeneuve , Nuno Sa , David Lechner , Javier Carrasco , Andy Shevchenko , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev Subject: [PATCH v3 2/9] iio: adc: add helpers for parsing ADC nodes Message-ID: <6c5b678526e227488592d004c315a967b9809701.1739967040.git.mazziesaccount@gmail.com> References: Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: There are ADC ICs which may have some of the AIN pins usable for other functions. These ICs may have some of the AIN pins wired so that they should not be used for ADC. (Preferred?) way for marking pins which can be used as ADC inputs is to add corresponding channels@N nodes in the device tree as described in the ADC binding yaml. Add couple of helper functions which can be used to retrieve the channel information from the device node. Signed-off-by: Matti Vaittinen --- Revision history: v2 => v3: Mostly based on review comments by Jonathan - Support differential and single-ended channels(*) - Rename iio_adc_device_get_channels() as - Improve spelling - Drop support for cases where DT comes from parent device's node - Decrease loop indent by reverting node name check conditions - Don't set 'chan->indexed' by number of channels to keep the interface consistent no matter how many channels are connected. - Fix ID range check and related comment RFC v1 => v2: - New patch (*) The support for single-ended and differential channels is 100% untested. I am not convinced it is actually an improvement over the *_simple() helpers which only supported getting the ID from the "reg". In theory they could be used. In practice, while I skimmed through the in-tree ADC drivers which used the for_each_child_node() construct - it seemed that most of those which supported differential inputs had also some other per-channel properties to read. Those users would in any case need to loop through the nodes to get those other properties. If I am once more allowed to go back to proposing the _simple() variant which only covers the case: "chan ID in 'reg' property"... Dropping support for differential and single-ended channels would simplify this helper a lot. It'd allow dropping the sanity check as well as the extra parameters callers need to pass to tell what kind of properties they expect. That'd (in my opinion) made the last patches (to actual ADC drivers) in this series a much more lean and worthy ;) Finally, we could add own functions for differential/single-ended/all channels when the next driver which uses differential or single-ended channels - and which does not need other per-channel properties - lands in tree. That would still simplify the helper API usage for those drivers touched at the end of this series. I (still) think it might be nice to have helpers for fetching also the other generic (non vendor specific) ADC properties (as listed in the Documentation/devicetree/bindings/iio/adc/adc.yaml) - but as I don't have use for those in BD79124 driver (at least not for now), I don't imnplement them yet. Anyways, this commit creates a place for such helpers. --- drivers/iio/adc/Kconfig | 3 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/industrialio-adc.c | 304 +++++++++++++++++++++++++++++ include/linux/iio/adc-helpers.h | 56 ++++++ 4 files changed, 364 insertions(+) create mode 100644 drivers/iio/adc/industrialio-adc.c create mode 100644 include/linux/iio/adc-helpers.h diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 849c90203071..37b70a65da6f 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -6,6 +6,9 @@ menu "Analog to digital converters" +config IIO_ADC_HELPER + tristate + config AB8500_GPADC bool "ST-Ericsson AB8500 GPADC driver" depends on AB8500_CORE && REGULATOR_AB8500 diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index ee19afba62b7..956c121a7544 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -57,6 +57,7 @@ obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o obj-$(CONFIG_GEHC_PMC_ADC) += gehc-pmc-adc.o obj-$(CONFIG_HI8435) += hi8435.o obj-$(CONFIG_HX711) += hx711.o +obj-$(CONFIG_IIO_ADC_HELPER) += industrialio-adc.o obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o obj-$(CONFIG_IMX8QXP_ADC) += imx8qxp-adc.o obj-$(CONFIG_IMX93_ADC) += imx93_adc.o diff --git a/drivers/iio/adc/industrialio-adc.c b/drivers/iio/adc/industrialio-adc.c new file mode 100644 index 000000000000..0281d64ae112 --- /dev/null +++ b/drivers/iio/adc/industrialio-adc.c @@ -0,0 +1,304 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Helpers for parsing common ADC information from a firmware node. + * + * Copyright (c) 2025 Matti Vaittinen + */ + +#include +#include +#include + +#include + +int iio_adc_device_num_channels(struct device *dev) +{ + int num_chan = 0; + + device_for_each_child_node_scoped(dev, child) + if (fwnode_name_eq(child, "channel")) + num_chan++; + + return num_chan; +} +EXPORT_SYMBOL_GPL(iio_adc_device_num_channels); + +static const char *iio_adc_type2prop(int type) +{ + switch (type) { + case IIO_ADC_CHAN_PROP_TYPE_REG: + return "reg"; + case IIO_ADC_CHAN_PROP_TYPE_SINGLE_ENDED: + return "single-channel"; + case IIO_ADC_CHAN_PROP_TYPE_DIFF: + return "diff-channels"; + case IIO_ADC_CHAN_PROP_COMMON: + return "common-mode-channel"; + default: + return "unknown"; + } +} + +/* + * Sanity check. Ensure that: + * - At least some type(s) are allowed + * - All types found are also expected + * - If plain "reg" is not allowed, either single-ended or differential + * properties are found. + */ +static int iio_adc_prop_type_check_sanity(struct device *dev, + const struct iio_adc_props *expected_props, int found_types) +{ + unsigned long allowed_types = expected_props->allowed | + expected_props->required; + + if (!allowed_types || allowed_types & (~IIO_ADC_CHAN_PROP_TYPE_ALL)) { + dev_dbg(dev, "Invalid adc allowed prop types 0x%lx\n", + allowed_types); + + return -EINVAL; + } + if (found_types & (~allowed_types)) { + long unknown_types = found_types & (~allowed_types); + int type; + + for_each_set_bit(type, &unknown_types, + IIO_ADC_CHAN_NUM_PROP_TYPES - 1) { + dev_err(dev, "Unsupported channel property %s\n", + iio_adc_type2prop(type)); + } + + return -EINVAL; + } + + /* + * The IIO_ADC_CHAN_PROP_TYPE_REG is special. We always require it to + * be found in the dt. (If not, we'll error out before calling this + * function.) However, listing it in 'allowed' types means the "reg" + * alone can be used to indicate the channel ID. + * + * Thus, we don't add it in the found properties either - so check for + * found and allowed properties passes even if user hasn't explicitly + * added the 'IIO_ADC_CHAN_PROP_TYPE_REG' to be allowed. (This is the + * case if either differential or single-ended property is required). + * + * Hence, for this check we need to explicitly add the + * IIO_ADC_CHAN_PROP_TYPE_REG to 'found' properties to make the check + * pass when "reg" is the property which is required to have the + * channel ID. + * + * We could of course always add the IIO_ADC_CHAN_PROP_TYPE_REG in + * allowed types and found types - but then we wouldn't catch the case + * where user says the "reg" alone is not sufficient. + */ + if ((~(found_types | IIO_ADC_CHAN_PROP_TYPE_REG)) & expected_props->required) { + long missing_types; + int type; + + missing_types = (~found_types) & expected_props->required; + + for_each_set_bit(type, &missing_types, + IIO_ADC_CHAN_NUM_PROP_TYPES - 1) { + dev_err(dev, "required channel specifier '%s' not found\n", + iio_adc_type2prop(type)); + } + + return -EINVAL; + } + + /* Check if we require something else but the "reg" property */ + if (!(allowed_types & IIO_ADC_CHAN_PROP_TYPE_REG)) { + if (found_types & IIO_ADC_CHAN_PROP_TYPE_SINGLE_ENDED || + found_types & IIO_ADC_CHAN_PROP_TYPE_DIFF) + return 0; + + dev_err(dev, "channel specifier not found\n"); + + return -EINVAL; + } + + return 0; +} + +/** + * iio_adc_device_channels_by_property - get ADC channel IDs + * + * Scan the device node for ADC channel information. Return an array of found + * IDs. Caller needs to provide the memory for the array and provide maximum + * number of IDs the array can store. + * + * @dev: Pointer to the ADC device + * @channels: Array where the found IDs will be stored. + * @max_channels: Number of IDs that fit in the array. + * @expected_props: Bitmaps of channel property types (for checking). + * + * Return: Number of found channels on succes. 0 if no channels + * was found. Negative value to indicate failure. + */ +int iio_adc_device_channels_by_property(struct device *dev, int *channels, + int max_channels, const struct iio_adc_props *expected_props) +{ + int num_chan = 0, ret; + + device_for_each_child_node_scoped(dev, child) { + u32 ch, diff[2], se; + struct iio_adc_props tmp; + int chtypes_found = 0; + + if (!fwnode_name_eq(child, "channel")) + continue; + + if (num_chan == max_channels) + return -EINVAL; + + ret = fwnode_property_read_u32(child, "reg", &ch); + if (ret) + return ret; + + ret = fwnode_property_read_u32_array(child, "diff-channels", + &diff[0], 2); + if (!ret) + chtypes_found |= IIO_ADC_CHAN_PROP_TYPE_DIFF; + + ret = fwnode_property_read_u32(child, "single-channel", &se); + if (!ret) + chtypes_found |= IIO_ADC_CHAN_PROP_TYPE_SINGLE_ENDED; + + tmp = *expected_props; + /* + * We don't bother reading the "common-mode-channel" here as it + * doesn't really affect on the primary channel ID. We remove + * it from the required properties to allow the sanity check + * pass here also for drivers which require it. + */ + tmp.required &= (~BIT(IIO_ADC_CHAN_PROP_COMMON)); + + ret = iio_adc_prop_type_check_sanity(dev, &tmp, chtypes_found); + if (ret) + return ret; + + if (chtypes_found & IIO_ADC_CHAN_PROP_TYPE_DIFF) + ch = diff[0]; + else if (chtypes_found & IIO_ADC_CHAN_PROP_TYPE_SINGLE_ENDED) + ch = se; + + /* + * We assume the channel IDs start from 0. If it seems this is + * not a sane assumption, then we can relax this check or add + * 'allowed ID range' parameter. + * + * Let's just start with this simple assumption. + */ + if (ch >= max_channels) + return -ERANGE; + + channels[num_chan] = ch; + num_chan++; + } + + return num_chan; + +} +EXPORT_SYMBOL_GPL(iio_adc_device_channels_by_property); + +/** + * devm_iio_adc_device_alloc_chaninfo - allocate and fill iio_chan_spec for adc + * + * Scan the device node for ADC channel information. Allocate and populate the + * iio_chan_spec structure corresponding to channels that are found. The memory + * for iio_chan_spec structure will be freed upon device detach. Try parent + * device node if given device has no fwnode associated to cover also MFD + * devices. + * + * @dev: Pointer to the ADC device. + * @template: Template iio_chan_spec from which the fields of all + * found and allocated channels are initialized. + * @cs: Location where pointer to allocated iio_chan_spec + * should be stored. + * @expected_props: Bitmaps of channel property types (for checking). + * + * Return: Number of found channels on succes. Negative value to indicate + * failure. + */ +int devm_iio_adc_device_alloc_chaninfo(struct device *dev, + const struct iio_chan_spec *template, + struct iio_chan_spec **cs, + const struct iio_adc_props *expected_props) +{ + struct iio_chan_spec *chan; + int num_chan = 0, ret; + + num_chan = iio_adc_device_num_channels(dev); + if (num_chan < 1) + return num_chan; + + *cs = devm_kcalloc(dev, num_chan, sizeof(**cs), GFP_KERNEL); + if (!*cs) + return -ENOMEM; + + chan = &(*cs)[0]; + + device_for_each_child_node_scoped(dev, child) { + u32 ch, diff[2], se, common; + int chtypes_found = 0; + + if (!fwnode_name_eq(child, "channel")) + continue; + + ret = fwnode_property_read_u32(child, "reg", &ch); + if (ret) + return ret; + + ret = fwnode_property_read_u32_array(child, "diff-channels", + &diff[0], 2); + if (!ret) + chtypes_found |= IIO_ADC_CHAN_PROP_TYPE_DIFF; + + ret = fwnode_property_read_u32(child, "single-channel", &se); + if (!ret) + chtypes_found |= IIO_ADC_CHAN_PROP_TYPE_SINGLE_ENDED; + + ret = fwnode_property_read_u32(child, "common-mode-channel", + &common); + if (!ret) + chtypes_found |= BIT(IIO_ADC_CHAN_PROP_COMMON); + + ret = iio_adc_prop_type_check_sanity(dev, expected_props, + chtypes_found); + if (ret) + return ret; + + *chan = *template; + chan->channel = ch; + + if (chtypes_found & IIO_ADC_CHAN_PROP_TYPE_DIFF) { + chan->differential = 1; + chan->channel = diff[0]; + chan->channel2 = diff[1]; + + } else if (chtypes_found & IIO_ADC_CHAN_PROP_TYPE_SINGLE_ENDED) { + chan->channel = se; + if (chtypes_found & BIT(IIO_ADC_CHAN_PROP_COMMON)) + chan->channel2 = common; + } + + /* + * We assume the channel IDs start from 0. If it seems this is + * not a sane assumption, then we have to add 'allowed ID ranges' + * to the struct iio_adc_props because some of the callers may + * rely on the IDs being in this range - and have arrays indexed + * by the ID. + */ + if (chan->channel >= num_chan) + return -ERANGE; + + chan++; + } + + return num_chan; +} +EXPORT_SYMBOL_GPL(devm_iio_adc_device_alloc_chaninfo); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Matti Vaittinen "); +MODULE_DESCRIPTION("IIO ADC fwnode parsing helpers"); diff --git a/include/linux/iio/adc-helpers.h b/include/linux/iio/adc-helpers.h new file mode 100644 index 000000000000..f7791d45dbd2 --- /dev/null +++ b/include/linux/iio/adc-helpers.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* The industrial I/O ADC helpers + * + * Copyright (c) 2025 Matti Vaittinen + */ + +#ifndef _INDUSTRIAL_IO_ADC_HELPERS_H_ +#define _INDUSTRIAL_IO_ADC_HELPERS_H_ + +#include + +struct device; +struct fwnode_handle; + +enum { + IIO_ADC_CHAN_PROP_REG, + IIO_ADC_CHAN_PROP_SINGLE_ENDED, + IIO_ADC_CHAN_PROP_DIFF, + IIO_ADC_CHAN_PROP_COMMON, + IIO_ADC_CHAN_NUM_PROP_TYPES +}; + +/* + * Channel property types to be used with iio_adc_device_get_channels, + * devm_iio_adc_device_alloc_chaninfo, ... + */ +#define IIO_ADC_CHAN_PROP_TYPE_REG BIT(IIO_ADC_CHAN_PROP_REG) +#define IIO_ADC_CHAN_PROP_TYPE_SINGLE_ENDED BIT(IIO_ADC_CHAN_PROP_SINGLE_ENDED) +#define IIO_ADC_CHAN_PROP_TYPE_SINGLE_COMMON \ + (BIT(IIO_ADC_CHAN_PROP_SINGLE_ENDED) | BIT(IIO_ADC_CHAN_PROP_COMMON)) +#define IIO_ADC_CHAN_PROP_TYPE_DIFF BIT(IIO_ADC_CHAN_PROP_DIFF) +#define IIO_ADC_CHAN_PROP_TYPE_ALL GENMASK(IIO_ADC_CHAN_NUM_PROP_TYPES - 1, 0) + +/** + * iio_adc_chan_props - information of expected device-tree channel properties + * + * @required: Bitmask of property definitions of required channel properties + * @allowed: Bitmask of property definitions of optional channel properties. + * Listing of required properties is not needed here. + */ +struct iio_adc_props { + unsigned long required; + unsigned long allowed; +}; + +int iio_adc_device_num_channels(struct device *dev); +int devm_iio_adc_device_alloc_chaninfo(struct device *dev, + const struct iio_chan_spec *template, + struct iio_chan_spec **cs, + const struct iio_adc_props *expected_props); + +int iio_adc_device_channels_by_property(struct device *dev, int *channels, + int max_channels, + const struct iio_adc_props *expected_props); +#endif /* _INDUSTRIAL_IO_ADC_HELPERS_H_ */ From patchwork Wed Feb 19 12:30:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 13982066 Received: from mail-lj1-f169.google.com (mail-lj1-f169.google.com [209.85.208.169]) (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 302871D52B; Wed, 19 Feb 2025 12:30:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968254; cv=none; b=JVCQRcBZAcZ89pQ+jO9G1VbFb0XgXrmix/3syOFILEeTxzP1Fcalaa1IbGx1UXd/ekPTnaJYvrMFLX2IAc6Abh6dGoYEVj6o+03BTmPjeRiqLdsxDLXWCmIDmh1YBYdGJPhGfc+RhnXHWNnHq34WoPIojfJKQxK1LKJKyBRnPKw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968254; c=relaxed/simple; bh=d9JhYXsnghcz2/KgqFgHowXqg7hEZF+JzXfMfoHMC50=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=diK6ry8ml/4cBSkqR7UufhiBTRKJyd+8Z0xEU6uwNBrDy0Cr7Pq6ISfaPEfv2id6SqwkJyxM09F6PYdtz2XqShFNmx4w2sz6NIaorR7OxZINoD+30vNs6JYBU+Uadui/vrjzqt0C8AzbEf9ifiktvYrJZ6RMuXePpOoABt2iuTE= 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=e6ndQ2Uq; arc=none smtp.client-ip=209.85.208.169 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="e6ndQ2Uq" Received: by mail-lj1-f169.google.com with SMTP id 38308e7fff4ca-307d1ab59c6so69334671fa.1; Wed, 19 Feb 2025 04:30:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739968249; x=1740573049; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=WeZIae6i5fqo6f26wLpjChgiIOLzZTNNStJ9CeilpHA=; b=e6ndQ2UqDu1AN9RuHEit40N7rhbuktSleJicOf6M5OyPUPM+ZntwO8Z7bRIoxTeWs4 +d2z6XUGBjRoUKSbmSYrH3SHGc9c2RttZcElHPfTgE0zi+rPoyDZimoxmyhIZj1HPNVg /lVFWKTgbkYGkCNTcoehI+Kl2qh1GFjfTTIGtShE+jKX7Oy+teN+KIeE1hA5m247zSyg O6JPnPpMzzmUls6siSbUWR1M9+HFVxTvy510+ywmSbzf307lvr1brxAuHMpV/oAPKWJZ O2mPZ59CYJXxlqJa40ZLvkc5tb/vB6Q7kSXCAVHYTzL9vUhCcZCCiYWkecG6ZaF4Ivxo iaUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739968249; x=1740573049; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=WeZIae6i5fqo6f26wLpjChgiIOLzZTNNStJ9CeilpHA=; b=xGrH6HxJ+pN8Monr0bH4n/oWC22XCw3BTuEF8PRY8Vdjxm+0BHft16RlcrL6leFZfi rYot/3S5j03qwlf+jgFF6ngXDeXOJc+esTlvFfH3Lb7acd4IlIfLm1SGEelKcrPeMVtB H+RWrOC1YWbFk/08JPfQkV07iJfEVr5oba8BcSy0Iz/aSDtvX2IckPnKoi6yObE29ptz j5CjQRUFcf1cdsWCaOzjdg64bnhhaRVd/EQU7BM/mRA0clQBhvKfleBzD0/LatmTAJdo u1NUOhcCBAZvqvrATgZabuKcORTZ9Z3sa81/BMutpqkL3jtwTYd3q5XfirxQz6KbVICP bP8w== X-Forwarded-Encrypted: i=1; AJvYcCUmNpQ7c+HCATjeGMXxkKjlpaF4mC6/TCHNPc5H7XpqQphyz1RaVICINyQ83fBIC4nxr2LumRClq78G/o2kbgELfjA=@vger.kernel.org, AJvYcCVF8SBahETrtxRIgdUKYQUJfIKmGhwOaAgxM5qA44k+gvvm9dKgzPJ/z905V+PteX48gJdfkytAWYMh@vger.kernel.org, AJvYcCWmxALlpOtYCfGaKEFy+hE9s4T8Mob+OPtSpZjQDcGOTdrwV480sD1mP4QmgKB8B8Lt8Yhd+FhGlRNVpX6Z@vger.kernel.org, AJvYcCXny2wKnGgGx7XFrHm9dIv7TwWTK+sSw31uPb4QHjnKF76s70jES60F1C7uxWcje6xMzYdLOixkvRhG@vger.kernel.org X-Gm-Message-State: AOJu0YyExNePtBgO/eSNem8K1A39INQVEyVvuLReepIntwrNTWqaTEHq qID7pq8koIDnQngVuLtqdVqQccW+9p9mKNjiCNWXDxJiA1yqde5+ X-Gm-Gg: ASbGncuPUbpLEd+NpLJz2RIlZCPQMD3LBKCwTl1GN+0arhq107mjDZwafs1TM8e7sBc b64oK7lH2XuLRYqI4uIgLiOcCD/zmLyHTIxQBHaGyI8zIGDqIzSdc7OP4xbYtddfYRHCftlyuTH gUyQZV1L7LPsbqxJPqRRcnWyOlayGHSw38uQ2vnUlWXCCSBnPPfIbB+zlEtO+ies0afZS91OQVu jPMrv1lBlDZeqxNjxip+DHUVGo1T3Uk5lF6MkpbUgKPzexj39doTlFti26fHwS5rzQYA9p3C6/d SvL/nVV4fHBbKseo2LdJuQ== X-Google-Smtp-Source: AGHT+IGTaJj8u1LcvL8BuKsGXZMBSiCm3qLQBrpBq0Nmi0BjPPHFUYblnxDkNMNFCesuFVIfv7JMCA== X-Received: by 2002:a05:6512:3195:b0:545:aa5:d451 with SMTP id 2adb3069b0e04-5462eef47d6mr1245794e87.25.1739968248680; Wed, 19 Feb 2025 04:30:48 -0800 (PST) Received: from mva-rohm ([2a10:a5c0:800d:dd00:8fdf:935a:2c85:d703]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5452d4fe147sm1715642e87.182.2025.02.19.04.30.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Feb 2025 04:30:47 -0800 (PST) Date: Wed, 19 Feb 2025 14:30:43 +0200 From: Matti Vaittinen To: Matti Vaittinen , Matti Vaittinen Cc: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matti Vaittinen , Lad Prabhakar , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Hugo Villeneuve , Nuno Sa , David Lechner , Javier Carrasco , Andy Shevchenko , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, Linus Walleij Subject: [PATCH v3 3/9] iio: adc: Support ROHM BD79124 ADC Message-ID: <67b7713724d7591f6321a8f5dfef8cd711f38d34.1739967040.git.mazziesaccount@gmail.com> References: Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: The ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports an automatic measurement mode, with an alarm interrupt for out-of-window measurements. The window is configurable for each channel. The I2C protocol for manual start of the measurement and data reading is somewhat peculiar. It requires the master to do clock stretching after sending the I2C slave-address until the slave has captured the data. Needless to say this is not well suopported by the I2C controllers. Thus the driver does not support the BD79124's manual measurement mode but implements the measurements using automatic measurement mode relying on the BD79124's ability of storing latest measurements into register. The driver does also support configuring the threshold events for detecting the out-of-window events. The BD79124 keeps asserting IRQ for as long as the measured voltage is out of the configured window. Thus the driver masks the received event for a fixed duration (1 second) when an event is handled. This prevents the user-space from choking on the events The ADC input pins can be also configured as general purpose outputs. Those pins which don't have corresponding ADC channel node in the device-tree will be controllable as GPO. Signed-off-by: Matti Vaittinen --- Revision history: v2 => v3: - Fix uninitialized return value reported by the kernel test robot - Fix indent - Adapt to adc-helper changes supporting also single-ended and differential channels RFC v1 => v2: - Add event throttling (constant delay of 1 sec) - rename variable 'd' to 'data' - Use ADC helpers to detect pins used for ADC - bd79124 drop MFD and pinmux && handle GPO in this driver - Drop adc suffix from the IIO file name --- drivers/iio/adc/Kconfig | 12 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/rohm-bd79124.c | 1162 ++++++++++++++++++++++++++++++++ 3 files changed, 1175 insertions(+) create mode 100644 drivers/iio/adc/rohm-bd79124.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 37b70a65da6f..a2a36a4ec644 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -1191,6 +1191,18 @@ config RN5T618_ADC This driver can also be built as a module. If so, the module will be called rn5t618-adc. +config ROHM_BD79124 + tristate "Rohm BD79124 ADC driver" + depends on I2C + select REGMAP_I2C + select IIO_ADC_HELPER + help + Say yes here to build support for the ROHM BD79124 ADC. The + ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports + also an automatic measurement mode, with an alarm interrupt for + out-of-window measurements. The window is configurable for each + channel. + config ROCKCHIP_SARADC tristate "Rockchip SARADC driver" depends on ARCH_ROCKCHIP || COMPILE_TEST diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 956c121a7544..43f159aba390 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -108,6 +108,7 @@ obj-$(CONFIG_QCOM_VADC_COMMON) += qcom-vadc-common.o obj-$(CONFIG_RCAR_GYRO_ADC) += rcar-gyroadc.o obj-$(CONFIG_RICHTEK_RTQ6056) += rtq6056.o obj-$(CONFIG_RN5T618_ADC) += rn5t618-adc.o +obj-$(CONFIG_ROHM_BD79124) += rohm-bd79124.o obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o obj-$(CONFIG_RZG2L_ADC) += rzg2l_adc.o obj-$(CONFIG_SC27XX_ADC) += sc27xx_adc.o diff --git a/drivers/iio/adc/rohm-bd79124.c b/drivers/iio/adc/rohm-bd79124.c new file mode 100644 index 000000000000..5e23bc8d9ce2 --- /dev/null +++ b/drivers/iio/adc/rohm-bd79124.c @@ -0,0 +1,1162 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ROHM ADC driver for BD79124 ADC/GPO device + * https://fscdn.rohm.com/en/products/databook/datasheet/ic/data_converter/dac/bd79124muf-c-e.pdf + * + * Copyright (c) 2025, ROHM Semiconductor. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define BD79124_I2C_MULTI_READ 0x30 +#define BD79124_I2C_MULTI_WRITE 0x28 +#define BD79124_REG_MAX 0xaf + +#define BD79124_REG_SYSTEM_STATUS 0x0 +#define BD79124_REG_GEN_CFG 0x01 +#define BD79124_REG_OPMODE_CFG 0x04 +#define BD79124_REG_PINCFG 0x05 +#define BD79124_REG_GPO_VAL 0x0B +#define BD79124_REG_SEQUENCE_CFG 0x10 +#define BD79124_REG_MANUAL_CHANNELS 0x11 +#define BD79124_REG_AUTO_CHANNELS 0x12 +#define BD79124_REG_ALERT_CH_SEL 0x14 +#define BD79124_REG_EVENT_FLAG 0x18 +#define BD79124_REG_EVENT_FLAG_HI 0x1a +#define BD79124_REG_EVENT_FLAG_LO 0x1c +#define BD79124_REG_HYSTERESIS_CH0 0x20 +#define BD79124_REG_EVENTCOUNT_CH0 0x22 +#define BD79124_REG_RECENT_CH0_LSB 0xa0 +#define BD79124_REG_RECENT_CH7_MSB 0xaf + +#define BD79124_ADC_BITS 12 +#define BD79124_MASK_CONV_MODE GENMASK(6, 5) +#define BD79124_MASK_AUTO_INTERVAL GENMASK(1, 0) +#define BD79124_CONV_MODE_MANSEQ 0 +#define BD79124_CONV_MODE_AUTO 1 +#define BD79124_INTERVAL_075 0 +#define BD79124_INTERVAL_150 1 +#define BD79124_INTERVAL_300 2 +#define BD79124_INTERVAL_600 3 + +#define BD79124_MASK_DWC_EN BIT(4) +#define BD79124_MASK_STATS_EN BIT(5) +#define BD79124_MASK_SEQ_START BIT(4) +#define BD79124_MASK_SEQ_MODE GENMASK(1, 0) +#define BD79124_MASK_SEQ_MANUAL 0 +#define BD79124_MASK_SEQ_SEQ 1 + +#define BD79124_MASK_HYSTERESIS GENMASK(3, 0) +#define BD79124_LOW_LIMIT_MIN 0 +#define BD79124_HIGH_LIMIT_MAX GENMASK(11, 0) + +/* + * The high limit, low limit and last measurement result are each stored in + * 2 consequtive registers. 4 bits are in the high bits of the 1.st register + * and 8 bits in the next register. + * + * These macros return the address of the 1.st reg for the given channel + */ +#define BD79124_GET_HIGH_LIMIT_REG(ch) (BD79124_REG_HYSTERESIS_CH0 + (ch) * 4) +#define BD79124_GET_LOW_LIMIT_REG(ch) (BD79124_REG_EVENTCOUNT_CH0 + (ch) * 4) +#define BD79124_GET_LIMIT_REG(ch, dir) ((dir) == IIO_EV_DIR_RISING ? \ + BD79124_GET_HIGH_LIMIT_REG(ch) : BD79124_GET_LOW_LIMIT_REG(ch)) +#define BD79124_GET_RECENT_RES_REG(ch) (BD79124_REG_RECENT_CH0_LSB + (ch) * 2) + +/* + * The hysteresis for a channel is stored in the same register where the + * 4 bits of high limit reside. + */ +#define BD79124_GET_HYSTERESIS_REG(ch) BD79124_GET_HIGH_LIMIT_REG(ch) + +#define BD79124_MAX_NUM_CHANNELS 8 + +/* + * We require the "reg" property and allow no other + * channel specifiers for the BD79124. + */ +static const struct iio_adc_props expected_props = { + .required = IIO_ADC_CHAN_PROP_TYPE_REG, +}; + +struct bd79124_data { + s64 timestamp; + struct regmap *map; + struct device *dev; + int vmax; + /* + * Keep measurement status so read_raw() knows if the measurement needs + * to be started. + */ + int alarm_monitored[BD79124_MAX_NUM_CHANNELS]; + /* + * The BD79124 does not allow disabling/enabling limit separately for + * one direction only. Hence, we do the disabling by changing the limit + * to maximum/minimum measurable value. This means we need to cache + * the limit in order to maintain it over the time limit is disabled. + */ + u16 alarm_r_limit[BD79124_MAX_NUM_CHANNELS]; + u16 alarm_f_limit[BD79124_MAX_NUM_CHANNELS]; + /* Bitmask of disabled events (for rate limiting) for each channel. */ + int alarm_suppressed[BD79124_MAX_NUM_CHANNELS]; + /* + * The BD79124 is configured to run the measurements in the background. + * This is done for the event monitoring as well as for the read_raw(). + * Protect the measurement starting/stopping using a mutex. + */ + struct mutex mutex; + struct delayed_work alm_enable_work; + struct gpio_chip gc; +}; + +/* Read-only regs */ +static const struct regmap_range bd79124_ro_ranges[] = { + { + .range_min = BD79124_REG_EVENT_FLAG, + .range_max = BD79124_REG_EVENT_FLAG, + }, { + .range_min = BD79124_REG_RECENT_CH0_LSB, + .range_max = BD79124_REG_RECENT_CH7_MSB, + }, +}; + +static const struct regmap_access_table bd79124_ro_regs = { + .no_ranges = &bd79124_ro_ranges[0], + .n_no_ranges = ARRAY_SIZE(bd79124_ro_ranges), +}; + +static const struct regmap_range bd79124_volatile_ranges[] = { + { + .range_min = BD79124_REG_RECENT_CH0_LSB, + .range_max = BD79124_REG_RECENT_CH7_MSB, + }, { + .range_min = BD79124_REG_EVENT_FLAG, + .range_max = BD79124_REG_EVENT_FLAG, + }, { + .range_min = BD79124_REG_EVENT_FLAG_HI, + .range_max = BD79124_REG_EVENT_FLAG_HI, + }, { + .range_min = BD79124_REG_EVENT_FLAG_LO, + .range_max = BD79124_REG_EVENT_FLAG_LO, + }, { + .range_min = BD79124_REG_SYSTEM_STATUS, + .range_max = BD79124_REG_SYSTEM_STATUS, + }, +}; + +static const struct regmap_access_table bd79124_volatile_regs = { + .yes_ranges = &bd79124_volatile_ranges[0], + .n_yes_ranges = ARRAY_SIZE(bd79124_volatile_ranges), +}; + +static const struct regmap_range bd79124_precious_ranges[] = { + { + .range_min = BD79124_REG_EVENT_FLAG_HI, + .range_max = BD79124_REG_EVENT_FLAG_HI, + }, { + .range_min = BD79124_REG_EVENT_FLAG_LO, + .range_max = BD79124_REG_EVENT_FLAG_LO, + }, +}; + +static const struct regmap_access_table bd79124_precious_regs = { + .yes_ranges = &bd79124_precious_ranges[0], + .n_yes_ranges = ARRAY_SIZE(bd79124_precious_ranges), +}; + +static const struct regmap_config bd79124_regmap = { + .reg_bits = 16, + .val_bits = 8, + .read_flag_mask = BD79124_I2C_MULTI_READ, + .write_flag_mask = BD79124_I2C_MULTI_WRITE, + .max_register = BD79124_REG_MAX, + .cache_type = REGCACHE_MAPLE, + .volatile_table = &bd79124_volatile_regs, + .wr_table = &bd79124_ro_regs, + .precious_table = &bd79124_precious_regs, +}; + +static int bd79124gpo_direction_get(struct gpio_chip *gc, unsigned int offset) +{ + return GPIO_LINE_DIRECTION_OUT; +} + +static void bd79124gpo_set(struct gpio_chip *gc, unsigned int offset, int value) +{ + struct bd79124_data *data = gpiochip_get_data(gc); + + if (value) + regmap_set_bits(data->map, BD79124_REG_GPO_VAL, BIT(offset)); + else + regmap_clear_bits(data->map, BD79124_REG_GPO_VAL, BIT(offset)); +} + +static void bd79124gpo_set_multiple(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits) +{ + int ret, val; + struct bd79124_data *data = gpiochip_get_data(gc); + + /* Ensure all GPIOs in 'mask' are set to be GPIOs */ + ret = regmap_read(data->map, BD79124_REG_PINCFG, &val); + if (ret) + return; + + if ((val & *mask) != *mask) { + dev_dbg(data->dev, "Invalid mux config. Can't set value.\n"); + /* Do not set value for pins configured as ADC inputs */ + *mask &= val; + } + + regmap_update_bits(data->map, BD79124_REG_GPO_VAL, *mask, *bits); +} + +static int bd79124_init_valid_mask(struct gpio_chip *gc, + unsigned long *valid_mask, + unsigned int ngpios) +{ + int adc_channels[BD79124_MAX_NUM_CHANNELS]; + int ret, num_channels, gpo_chan, j; + + *valid_mask = 0; + + ret = iio_adc_device_channels_by_property(gc->parent, adc_channels, + BD79124_MAX_NUM_CHANNELS, + &expected_props); + if (ret < 0) + return ret; + + num_channels = ret; + + for (gpo_chan = 0; gpo_chan < BD79124_MAX_NUM_CHANNELS; gpo_chan++) { + for (j = 0; j < num_channels; j++) { + if (adc_channels[j] == gpo_chan) + break; + } + if (j == num_channels) + *valid_mask |= BIT(gpo_chan); + } + + return 0; +} + +/* Template for GPIO chip */ +static const struct gpio_chip bd79124gpo_chip = { + .label = "bd79124-gpo", + .get_direction = bd79124gpo_direction_get, + .set = bd79124gpo_set, + .set_multiple = bd79124gpo_set_multiple, + .init_valid_mask = bd79124_init_valid_mask, + .can_sleep = true, + .ngpio = 8, + .base = -1, +}; + +struct bd79124_raw { + u8 bit0_3; /* Is set in high bits of the byte */ + u8 bit4_11; +}; +#define BD79124_RAW_TO_INT(r) ((r.bit4_11 << 4) | (r.bit0_3 >> 4)) + +/* + * The high and low limits as well as the recent result values are stored in + * the same way in 2 consequent registers. The first register contains 4 bits + * of the value. These bits are stored in the high bits [7:4] of register, but + * they represent the low bits [3:0] of the value. + * The value bits [11:4] are stored in the next register. + * + * Read data from register and convert to integer. + */ +static int bd79124_read_reg_to_int(struct bd79124_data *data, int reg, + unsigned int *val) +{ + int ret; + struct bd79124_raw raw; + + ret = regmap_bulk_read(data->map, reg, &raw, sizeof(raw)); + if (ret) { + dev_dbg(data->dev, "bulk_read failed %d\n", ret); + + return ret; + } + + *val = BD79124_RAW_TO_INT(raw); + + return 0; +} + +/* + * The high and low limits as well as the recent result values are stored in + * the same way in 2 consequent registers. The first register contains 4 bits + * of the value. These bits are stored in the high bits [7:4] of register, but + * they represent the low bits [3:0] of the value. + * The value bits [11:4] are stored in the next regoster. + * + * Conver the integer to register format and write it using rmw cycle. + */ +static int bd79124_write_int_to_reg(struct bd79124_data *data, int reg, + unsigned int val) +{ + struct bd79124_raw raw; + int ret, tmp; + + raw.bit4_11 = (u8)(val >> 4); + raw.bit0_3 = (u8)(val << 4); + + ret = regmap_read(data->map, reg, &tmp); + if (ret) + return ret; + + raw.bit0_3 |= (0xf & tmp); + + return regmap_bulk_write(data->map, reg, &raw, sizeof(raw)); +} + +static const struct iio_event_spec bd79124_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_HYSTERESIS), + }, +}; + +static const struct iio_chan_spec bd79124_chan_template_noirq = { + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .indexed = 1, +}; + +static const struct iio_chan_spec bd79124_chan_template = { + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .indexed = 1, + .event_spec = bd79124_events, + .num_event_specs = ARRAY_SIZE(bd79124_events), +}; + +static int bd79124_read_event_value(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, int *val, + int *val2) +{ + struct bd79124_data *data = iio_priv(iio_dev); + int ret, reg; + + if (chan->channel >= BD79124_MAX_NUM_CHANNELS) + return -EINVAL; + + switch (info) { + case IIO_EV_INFO_VALUE: + if (dir == IIO_EV_DIR_RISING) + *val = data->alarm_r_limit[chan->channel]; + else if (dir == IIO_EV_DIR_FALLING) + *val = data->alarm_f_limit[chan->channel]; + else + return -EINVAL; + + return IIO_VAL_INT; + + case IIO_EV_INFO_HYSTERESIS: + reg = BD79124_GET_HYSTERESIS_REG(chan->channel); + ret = regmap_read(data->map, reg, val); + if (ret) + return ret; + /* Mask the non hysteresis bits */ + *val &= BD79124_MASK_HYSTERESIS; + /* + * The data-sheet says the hysteresis register value needs to be + * sifted left by 3 (or multiplied by 8, depending on the + * page :] ) + */ + *val <<= 3; + + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int bd79124_start_measurement(struct bd79124_data *data, int chan) +{ + int val, ret, regval; + + /* See if already started */ + ret = regmap_read(data->map, BD79124_REG_AUTO_CHANNELS, &val); + if (val & BIT(chan)) + return 0; + + ret = regmap_clear_bits(data->map, BD79124_REG_SEQUENCE_CFG, + BD79124_MASK_SEQ_START); + if (ret) + return ret; + + /* Add the channel to measured channels */ + ret = regmap_write(data->map, BD79124_REG_AUTO_CHANNELS, val | BIT(chan)); + if (ret) + return ret; + + ret = regmap_set_bits(data->map, BD79124_REG_SEQUENCE_CFG, + BD79124_MASK_SEQ_START); + if (ret) + return ret; + + /* + * Start the measurement at the background. Don't bother checking if + * it was started, regmap has cache. + */ + regval = FIELD_PREP(BD79124_MASK_CONV_MODE, BD79124_CONV_MODE_AUTO); + + return regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG, + BD79124_MASK_CONV_MODE, regval); +} + +static int bd79124_stop_measurement(struct bd79124_data *data, int chan) +{ + int val, ret; + + /* See if already stopped */ + ret = regmap_read(data->map, BD79124_REG_AUTO_CHANNELS, &val); + if (!(val & BIT(chan))) + return 0; + + ret = regmap_clear_bits(data->map, BD79124_REG_SEQUENCE_CFG, + BD79124_MASK_SEQ_START); + + /* Clear the channel from the measured channels */ + ret = regmap_write(data->map, BD79124_REG_AUTO_CHANNELS, + (~BIT(chan)) & val); + if (ret) + return ret; + + /* + * Stop background conversion for power saving if it was the last + * channel + */ + if (!((~BIT(chan)) & val)) { + int regval = FIELD_PREP(BD79124_MASK_CONV_MODE, + BD79124_CONV_MODE_MANSEQ); + + ret = regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG, + BD79124_MASK_CONV_MODE, regval); + if (ret) + return ret; + } + + return regmap_set_bits(data->map, BD79124_REG_SEQUENCE_CFG, + BD79124_MASK_SEQ_START); +} + +static int bd79124_read_event_config(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct bd79124_data *data = iio_priv(iio_dev); + + if (chan->channel >= BD79124_MAX_NUM_CHANNELS) + return -EINVAL; + + return (data->alarm_monitored[chan->channel] & BIT(dir)); +} + +static int bd79124_disable_event(struct bd79124_data *data, + enum iio_event_direction dir, int channel) +{ + int dir_bit = BIT(dir), reg; + unsigned int limit; + + guard(mutex)(&data->mutex); + /* + * Set thresholds either to 0 or to 2^12 - 1 as appropriate to prevent + * alerts and thus disable event generation. + */ + if (dir == IIO_EV_DIR_RISING) { + reg = BD79124_GET_HIGH_LIMIT_REG(channel); + limit = BD79124_HIGH_LIMIT_MAX; + } else if (dir == IIO_EV_DIR_FALLING) { + reg = BD79124_GET_LOW_LIMIT_REG(channel); + limit = BD79124_LOW_LIMIT_MIN; + } else { + return -EINVAL; + } + + data->alarm_monitored[channel] &= (~dir_bit); + /* + * Stop measurement if there is no more events to monitor. + * We don't bother checking the retval because the limit + * setting should in any case effectively disable the alarm. + */ + if (!data->alarm_monitored[channel]) { + bd79124_stop_measurement(data, channel); + regmap_clear_bits(data->map, BD79124_REG_ALERT_CH_SEL, + BIT(channel)); + } + + return bd79124_write_int_to_reg(data, reg, limit); +} + +static int bd79124_enable_event(struct bd79124_data *data, + enum iio_event_direction dir, unsigned int channel) +{ + int dir_bit = BIT(dir); + int reg; + u16 *limit; + int ret; + + guard(mutex)(&data->mutex); + /* Set channel to be measured */ + ret = bd79124_start_measurement(data, channel); + if (ret) + return ret; + + data->alarm_monitored[channel] |= dir_bit; + + /* Add the channel to the list of monitored channels */ + ret = regmap_set_bits(data->map, BD79124_REG_ALERT_CH_SEL, + BIT(channel)); + if (ret) + return ret; + + if (dir == IIO_EV_DIR_RISING) { + limit = &data->alarm_f_limit[channel]; + reg = BD79124_GET_HIGH_LIMIT_REG(channel); + } else { + limit = &data->alarm_f_limit[channel]; + reg = BD79124_GET_LOW_LIMIT_REG(channel); + } + /* Don't write the new limit to the hardware if we are in the + * rate-limit period. The timer which re-enables the event will set + * the limit. + */ + if (!(data->alarm_suppressed[channel] & dir_bit)) { + ret = bd79124_write_int_to_reg(data, reg, *limit); + if (ret) + return ret; + } + + /* + * Enable comparator. Trust the regmap cache, no need to check + * if it was already enabled. + * + * We could do this in the hw-init, but there may be users who + * never enable alarms and for them it makes sense to not + * enable the comparator at probe. + */ + return regmap_set_bits(data->map, BD79124_REG_GEN_CFG, + BD79124_MASK_DWC_EN); + +} + +static int bd79124_write_event_config(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, bool state) +{ + struct bd79124_data *data = iio_priv(iio_dev); + + if (chan->channel >= BD79124_MAX_NUM_CHANNELS) + return -EINVAL; + + if (state) + return bd79124_enable_event(data, dir, chan->channel); + + return bd79124_disable_event(data, dir, chan->channel); +} + +static int bd79124_write_event_value(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, int val, + int val2) +{ + struct bd79124_data *data = iio_priv(iio_dev); + int reg; + + if (chan->channel >= BD79124_MAX_NUM_CHANNELS) + return -EINVAL; + + switch (info) { + case IIO_EV_INFO_VALUE: + if (dir == IIO_EV_DIR_RISING) { + guard(mutex)(&data->mutex); + + data->alarm_r_limit[chan->channel] = val; + reg = BD79124_GET_HIGH_LIMIT_REG(chan->channel); + } else if (dir == IIO_EV_DIR_FALLING) { + guard(mutex)(&data->mutex); + + data->alarm_f_limit[chan->channel] = val; + reg = BD79124_GET_LOW_LIMIT_REG(chan->channel); + } else { + return -EINVAL; + } + /* + * We don't want to enable the alarm if it is not enabled or + * if it is suppressed. In that case skip writing to the + * register. + */ + if (!(data->alarm_monitored[chan->channel] & BIT(dir)) || + data->alarm_suppressed[chan->channel] & BIT(dir)) + return 0; + + return bd79124_write_int_to_reg(data, reg, val); + + case IIO_EV_INFO_HYSTERESIS: + reg = BD79124_GET_HYSTERESIS_REG(chan->channel); + val >>= 3; + + return regmap_update_bits(data->map, reg, BD79124_MASK_HYSTERESIS, + val); + default: + return -EINVAL; + } +} + +static int bd79124_single_chan_seq(struct bd79124_data *data, int chan, int *old) +{ + int ret; + + ret = regmap_clear_bits(data->map, BD79124_REG_SEQUENCE_CFG, + BD79124_MASK_SEQ_START); + if (ret) + return ret; + + /* + * It may be we have some channels monitored for alarms so we want to + * cache the old config and return it when the single channel + * measurement has been completed. + */ + ret = regmap_read(data->map, BD79124_REG_AUTO_CHANNELS, old); + if (ret) + return ret; + + ret = regmap_write(data->map, BD79124_REG_AUTO_CHANNELS, BIT(chan)); + if (ret) + return ret; + + /* Restart the sequencer */ + return regmap_set_bits(data->map, BD79124_REG_SEQUENCE_CFG, + BD79124_MASK_SEQ_START); +} + +static int bd79124_single_chan_seq_end(struct bd79124_data *data, int old) +{ + int ret; + + ret = regmap_clear_bits(data->map, BD79124_REG_SEQUENCE_CFG, + BD79124_MASK_SEQ_START); + if (ret) + return ret; + + ret = regmap_write(data->map, BD79124_REG_AUTO_CHANNELS, old); + if (ret) + return ret; + + return regmap_set_bits(data->map, BD79124_REG_SEQUENCE_CFG, + BD79124_MASK_SEQ_START); +} + +static int bd79124_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long m) +{ + struct bd79124_data *data = iio_priv(iio_dev); + int ret; + + if (chan->channel >= BD79124_MAX_NUM_CHANNELS) + return -EINVAL; + + switch (m) { + case IIO_CHAN_INFO_RAW: + { + int old_chan_cfg, tmp; + int regval; + + guard(mutex)(&data->mutex); + + /* + * Start the automatic conversion. This is needed here if no + * events have been enabled. + */ + regval = FIELD_PREP(BD79124_MASK_CONV_MODE, + BD79124_CONV_MODE_AUTO); + ret = regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG, + BD79124_MASK_CONV_MODE, regval); + if (ret) + return ret; + + ret = bd79124_single_chan_seq(data, chan->channel, &old_chan_cfg); + if (ret) + return ret; + + /* The maximum conversion time is 6 uS. */ + udelay(6); + + ret = bd79124_read_reg_to_int(data, + BD79124_GET_RECENT_RES_REG(chan->channel), + val); + /* + * Return the old chan config even if data reading failed in + * order to re-enable the event monitoring. + */ + tmp = bd79124_single_chan_seq_end(data, old_chan_cfg); + if (tmp) + dev_err(data->dev, + "Failed to return config. Alarms may be disabled\n"); + + if (ret) + return ret; + + return IIO_VAL_INT; + } + case IIO_CHAN_INFO_SCALE: + *val = data->vmax / 1000; + *val2 = BD79124_ADC_BITS; + return IIO_VAL_FRACTIONAL_LOG2; + default: + return -EINVAL; + } +} + +static const struct iio_info bd79124_info = { + .read_raw = bd79124_read_raw, + .read_event_config = &bd79124_read_event_config, + .write_event_config = &bd79124_write_event_config, + .read_event_value = &bd79124_read_event_value, + .write_event_value = &bd79124_write_event_value, +}; + +static void bd79124_re_enable_lo(struct bd79124_data *data, unsigned int channel) +{ + int ret, evbit = BIT(IIO_EV_DIR_FALLING); + + if (!(data->alarm_suppressed[channel] & evbit)) + return; + + data->alarm_suppressed[channel] &= (~evbit); + + if (!(data->alarm_monitored[channel] & evbit)) + return; + + ret = bd79124_write_int_to_reg(data, BD79124_GET_LOW_LIMIT_REG(channel), + data->alarm_f_limit[channel]); + if (ret) + dev_warn(data->dev, "Low limit enabling failed for channel%d\n", + channel); +} + +static void bd79124_re_enable_hi(struct bd79124_data *data, unsigned int channel) +{ + int ret, evbit = BIT(IIO_EV_DIR_RISING); + + if (!(data->alarm_suppressed[channel] & evbit)) + return; + + data->alarm_suppressed[channel] &= (~evbit); + + if (!(data->alarm_monitored[channel] & evbit)) + return; + + ret = bd79124_write_int_to_reg(data, BD79124_GET_HIGH_LIMIT_REG(channel), + data->alarm_r_limit[channel]); + if (ret) + dev_warn(data->dev, "High limit enabling failed for channel%d\n", + channel); +} + +static void bd79124_alm_enable_worker(struct work_struct *work) +{ + int i; + struct bd79124_data *data = container_of(work, struct bd79124_data, + alm_enable_work.work); + + guard(mutex)(&data->mutex); + /* + * We should not re-enable the event if user has disabled it while + * rate-limiting was enabled. + */ + for (i = 0; i < BD79124_MAX_NUM_CHANNELS; i++) { + bd79124_re_enable_hi(data, i); + bd79124_re_enable_lo(data, i); + } +} + +static int __bd79124_event_ratelimit(struct bd79124_data *data, int reg, + unsigned int limit) +{ + int ret; + + if (limit > BD79124_HIGH_LIMIT_MAX) + return -EINVAL; + + ret = bd79124_write_int_to_reg(data, reg, limit); + if (ret) + return ret; + + /* + * We use 1 sec 'grace period'. At the moment I see no reason to make + * this user configurable. We need an ABI for this if configuration is + * needed. + */ + schedule_delayed_work(&data->alm_enable_work, + msecs_to_jiffies(1000)); + + return 0; +} + +static int bd79124_event_ratelimit_hi(struct bd79124_data *data, + unsigned int channel) +{ + int reg, limit; + + guard(mutex)(&data->mutex); + data->alarm_suppressed[channel] |= BIT(IIO_EV_DIR_RISING); + + reg = BD79124_GET_HIGH_LIMIT_REG(channel); + limit = BD79124_HIGH_LIMIT_MAX; + + return __bd79124_event_ratelimit(data, reg, limit); +} + +static int bd79124_event_ratelimit_lo(struct bd79124_data *data, + unsigned int channel) +{ + int reg, limit; + + guard(mutex)(&data->mutex); + data->alarm_suppressed[channel] |= BIT(IIO_EV_DIR_FALLING); + + reg = BD79124_GET_LOW_LIMIT_REG(channel); + limit = BD79124_LOW_LIMIT_MIN; + + return __bd79124_event_ratelimit(data, reg, limit); +} + +static irqreturn_t bd79124_event_handler(int irq, void *priv) +{ + int ret, i_hi, i_lo, i; + struct iio_dev *iio_dev = priv; + struct bd79124_data *data = iio_priv(iio_dev); + + /* + * Return IRQ_NONE if bailing-out without acking. This allows the IRQ + * subsystem to disable the offending IRQ line if we get a hardware + * problem. This behaviour has saved my poor bottom a few times in the + * past as, instead of getting unusably unresponsive, the system has + * spilled out the magic words "...nobody cared". + */ + ret = regmap_read(data->map, BD79124_REG_EVENT_FLAG_HI, &i_hi); + if (ret) + return IRQ_NONE; + + ret = regmap_read(data->map, BD79124_REG_EVENT_FLAG_LO, &i_lo); + if (ret) + return IRQ_NONE; + + if (!i_lo && !i_hi) + return IRQ_NONE; + + for (i = 0; i < BD79124_MAX_NUM_CHANNELS; i++) { + u64 ecode; + + if (BIT(i) & i_hi) { + ecode = IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i, + IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING); + + iio_push_event(iio_dev, ecode, data->timestamp); + /* + * The BD79124 keeps the IRQ asserted for as long as + * the voltage exceeds the threshold. It causes the IRQ + * to keep firing. + * + * Disable the event for the channel and schedule the + * re-enabling the event later to prevent storm of + * events. + */ + ret = bd79124_event_ratelimit_hi(data, i); + if (ret) + return IRQ_NONE; + } + if (BIT(i) & i_lo) { + ecode = IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i, + IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING); + + iio_push_event(iio_dev, ecode, data->timestamp); + ret = bd79124_event_ratelimit_lo(data, i); + if (ret) + return IRQ_NONE; + } + } + + ret = regmap_write(data->map, BD79124_REG_EVENT_FLAG_HI, i_hi); + if (ret) + return IRQ_NONE; + + ret = regmap_write(data->map, BD79124_REG_EVENT_FLAG_LO, i_lo); + if (ret) + return IRQ_NONE; + + return IRQ_HANDLED; +} + +static irqreturn_t bd79124_irq_handler(int irq, void *priv) +{ + struct iio_dev *iio_dev = priv; + struct bd79124_data *data = iio_priv(iio_dev); + + data->timestamp = iio_get_time_ns(iio_dev); + + return IRQ_WAKE_THREAD; +} + +struct bd79124_reg_init { + int reg; + int val; +}; + +static int bd79124_chan_init(struct bd79124_data *data, int channel) +{ + struct bd79124_reg_init inits[] = { + { .reg = BD79124_GET_HIGH_LIMIT_REG(channel), .val = 4095 }, + { .reg = BD79124_GET_LOW_LIMIT_REG(channel), .val = 0 }, + }; + int i, ret; + + for (i = 0; i < ARRAY_SIZE(inits); i++) { + ret = regmap_write(data->map, inits[i].reg, inits[i].val); + if (ret) + return ret; + } + + return 0; +} + +static bool bd79124_is_in_array(int *arr, int num_items, int val) +{ + int i; + + for (i = 0; i < num_items; i++) + if (arr[i] == val) + return true; + + return false; +} + +static int bd79124_mux_init(struct bd79124_data *data) +{ + int adc_chans[BD79124_MAX_NUM_CHANNELS]; + int num_adc, chan, regval = 0; + + num_adc = iio_adc_device_channels_by_property(data->dev, &adc_chans[0], + BD79124_MAX_NUM_CHANNELS, + &expected_props); + if (num_adc < 0) + return num_adc; + + /* + * Set a mux register bit for each pin which is free to be used as + * a GPO. + */ + for (chan = 0; chan < BD79124_MAX_NUM_CHANNELS; chan++) + if (!bd79124_is_in_array(&adc_chans[0], num_adc, chan)) + regval |= BIT(chan); + + return regmap_write(data->map, BD79124_REG_PINCFG, regval); +} + +static int bd79124_hw_init(struct bd79124_data *data) +{ + int ret, regval, i; + + ret = bd79124_mux_init(data); + if (ret) + return ret; + + for (i = 0; i < BD79124_MAX_NUM_CHANNELS; i++) { + ret = bd79124_chan_init(data, i); + if (ret) + return ret; + data->alarm_r_limit[i] = 4095; + } + /* Stop auto sequencer */ + ret = regmap_clear_bits(data->map, BD79124_REG_SEQUENCE_CFG, + BD79124_MASK_SEQ_START); + if (ret) + return ret; + + /* Enable writing the measured values to the regsters */ + ret = regmap_set_bits(data->map, BD79124_REG_GEN_CFG, + BD79124_MASK_STATS_EN); + if (ret) + return ret; + + /* Set no channels to be auto-measured */ + ret = regmap_write(data->map, BD79124_REG_AUTO_CHANNELS, 0x0); + if (ret) + return ret; + + /* Set no channels to be manually measured */ + ret = regmap_write(data->map, BD79124_REG_MANUAL_CHANNELS, 0x0); + if (ret) + return ret; + + /* Set the measurement interval to 0.75 mS */ + regval = FIELD_PREP(BD79124_MASK_AUTO_INTERVAL, BD79124_INTERVAL_075); + ret = regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG, + BD79124_MASK_AUTO_INTERVAL, regval); + if (ret) + return ret; + + /* Sequencer mode to auto */ + ret = regmap_set_bits(data->map, BD79124_REG_SEQUENCE_CFG, + BD79124_MASK_SEQ_SEQ); + if (ret) + return ret; + + /* Don't start the measurement */ + regval = FIELD_PREP(BD79124_MASK_CONV_MODE, BD79124_CONV_MODE_MANSEQ); + + return regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG, + BD79124_MASK_CONV_MODE, BD79124_CONV_MODE_MANSEQ); + +} + +static int bd79124_probe(struct i2c_client *i2c) +{ + struct bd79124_data *data; + struct iio_dev *iio_dev; + const struct iio_chan_spec *template; + struct iio_chan_spec *cs; + struct device *dev = &i2c->dev; + int ret; + + iio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!iio_dev) + return -ENOMEM; + + data = iio_priv(iio_dev); + data->dev = dev; + data->map = devm_regmap_init_i2c(i2c, &bd79124_regmap); + if (IS_ERR(data->map)) + return dev_err_probe(dev, PTR_ERR(data->map), + "Failed to initialize Regmap\n"); + + ret = devm_regulator_get_enable_read_voltage(dev, "vdd"); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to get the Vdd\n"); + + data->vmax = ret; + + ret = devm_regulator_get_enable(dev, "iovdd"); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to enable I/O voltage\n"); + + ret = devm_delayed_work_autocancel(dev, &data->alm_enable_work, + bd79124_alm_enable_worker); + if (ret) + return ret; + + if (i2c->irq) { + template = &bd79124_chan_template; + } else { + template = &bd79124_chan_template_noirq; + dev_dbg(dev, "No IRQ found, events disabled\n"); + } + ret = devm_iio_adc_device_alloc_chaninfo(dev, template, &cs, + &expected_props); + if (ret < 0) + return ret; + + iio_dev->channels = cs; + iio_dev->num_channels = ret; + iio_dev->info = &bd79124_info; + iio_dev->name = "bd79124"; + iio_dev->modes = INDIO_DIRECT_MODE; + + data->gc = bd79124gpo_chip; + data->gc.parent = dev; + + mutex_init(&data->mutex); + + ret = bd79124_hw_init(data); + if (ret) + return ret; + + ret = devm_gpiochip_add_data(data->dev, &data->gc, data); + if (ret) + return dev_err_probe(data->dev, ret, "gpio init Failed\n"); + + if (i2c->irq > 0) { + ret = devm_request_threaded_irq(data->dev, i2c->irq, + bd79124_irq_handler, + &bd79124_event_handler, IRQF_ONESHOT, + "adc-thresh-alert", iio_dev); + if (ret) + return dev_err_probe(data->dev, ret, + "Failed to register IRQ\n"); + } + + return devm_iio_device_register(data->dev, iio_dev); +} + +static const struct of_device_id bd79124_of_match[] = { + { .compatible = "rohm,bd79124" }, + { } +}; +MODULE_DEVICE_TABLE(of, bd79124_of_match); + +static const struct i2c_device_id bd79124_id[] = { + { "bd79124", }, + { } +}; +MODULE_DEVICE_TABLE(i2c, bd79124_id); + +static struct i2c_driver bd79124_driver = { + .driver = { + .name = "bd79124", + .of_match_table = bd79124_of_match, + }, + .probe = bd79124_probe, + .id_table = bd79124_id, +}; +module_i2c_driver(bd79124_driver); + +MODULE_AUTHOR("Matti Vaittinen "); +MODULE_DESCRIPTION("Driver for ROHM BD79124 ADC"); +MODULE_LICENSE("GPL"); From patchwork Wed Feb 19 12:30:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 13982067 Received: from mail-lf1-f43.google.com (mail-lf1-f43.google.com [209.85.167.43]) (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 6EBAC1E1025; Wed, 19 Feb 2025 12:31:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968270; cv=none; b=iXrJ/OpOYWbNDQVGdu/ZqEqRURc19MrZU/hIdPZZkkKu9k9G8YX6wPhhNIqD3vudOVIPubYgJUzs8ZJJ9MkrkG+nE4uVmnQQ96f3Ot4lkpJve3GgPwTsJ5Jd8hHkG4eAcKIimpHYQI+/OpvejRLcNerm84psoZMi1dsBm7hyMP8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968270; c=relaxed/simple; bh=I3shXO9b9Bf/a89JD+NZvm3W9P/MGQLFbKoUjj5IlzA=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=txet8K/Ki2V+umjLgAnJNBzVGTuOw0spuTKCmvf1wDFUDVYI/a659UMOftqS9JLMEuTihDiKuYwIzvDLwlpjHnYWcoQk6xYOBSnHJdXCRU6NhpfITr0AUttbPVNIhONlt08CbbkltCOpWAqHtPXKOMadXuyxqX7A6cinb8xGc+I= 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=nBm8Wdjm; arc=none smtp.client-ip=209.85.167.43 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="nBm8Wdjm" Received: by mail-lf1-f43.google.com with SMTP id 2adb3069b0e04-546210287c1so3321515e87.2; Wed, 19 Feb 2025 04:31:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739968266; x=1740573066; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=XNzXBsdWjpLDVsAJfw/fASRvRFeX+ndkn8tRpPOZpL4=; b=nBm8Wdjm6B4UUIdnPkxXMm2MXCOIk6RJXoJl9aramJjfd8uLkChm8yEZPw3NiW8fYM t+jrrO/LiyZnFlOn+KP/YeNAVUzSs0eK3LynGp340lWyeJotu18gNL7xiy5a+RIPqHS5 jMSRwVFcArH8OgS3Y6HuM95sM7M66r8d0jfAPUy+GvNshlxNcrk2oq9UMfQ+XHI54ZR1 9HKf9vC9apwcHKIVY0PxT3IzLlowSUopccSS2jeo437lOFQMlaGBO9OffdE+J+4E7S7H v+UtkLGgl8b50PMgKvS9NM2haKeAiEndmsK/fjaebp/E+0beG+v/4mbDczZjnCWkCBuL TtYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739968266; x=1740573066; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=XNzXBsdWjpLDVsAJfw/fASRvRFeX+ndkn8tRpPOZpL4=; b=tIKucsXwpLKP2U8v+MzhBwl+uqC0nJoFsvKL+q85qes7GRqQuMZqMiKR+vIUwyJGJ9 k99e4PKVikycUYmuQD8/MTNq69voNLOvXPGyYBLZICIBhGJL8Ocd52z+c1ukfORDhZYc +ZoArf5Z35AyF8OIaFcejNhY2WdS5SNVLOpqhFm+CxxlE38EzkeLnmeO09H0JdxBr2r6 FTTljsjFyKAIgvBJsvC9t9+X3UFxWkaDakM5HTpoB27DFKG8YI27XAy0eujuEMKAIqJ9 CbFAtm5mOyZMe8jbcbPE8LvlGFp5o6jK8g/V5KwXV6JAt5/796DJ7X6KzX85ZTwworcs hONA== X-Forwarded-Encrypted: i=1; AJvYcCU7lEpqxmX7bj4faG74YfUWZ07XQNO27UK32kuLTiM6EUjEIys1oyjnkTa1biS/rzQcyY+hnan9jsz0O5P1@vger.kernel.org, AJvYcCUfaPKuzxH1OLETCUY1fO95aogA9pCAeEtTmAIybE3+2AUUGxLpFFtbJpuvGBdfrLejYCO3GnFYRb3YhQJ7Bmsaru0=@vger.kernel.org, AJvYcCVjtGhjZ5A29r522F2ro3L0Vm28/89xWdJGE5jFA8NrFrVm5chiUArgsoFg7gwcldxWPG48eMnezn94@vger.kernel.org, AJvYcCWXk/k7Bgl2N49VSQU9UkuOzZ0qIpbTkxgw1zZ2GWce7+4mqSg4pniiFawaw6hyJh+7veIFN1pSxunn@vger.kernel.org X-Gm-Message-State: AOJu0Yzw1cqZ+krJlFq/iVaRR+slOgwVAYq1bKmjthg35nIIBcNPC943 CZ7stdNtXcTQo4qMqp7XBMlA6EdufeTs0Ch7XNXwO56v1xt989x4 X-Gm-Gg: ASbGncvcBV/HEhES7EADwOpDRdS/SWs8J6d1gvfeqpaKL3V8hOGqt9I94nsPY2oQigd rKMioS2VUIc6gX0kpTBnPHMSdPj3PEGKrsf+kJlqQdi8P5yb7rn9T88AnSF0dPsgPX4+cyTHUr/ FAtUXzY+XiQcXsg+Ve8/dueUy7Slgq22FW6hBhf9WM/+VzG1h+dASGu1nWWQt8T75jqiOfkP4LH /HOaEhQ3LWWU7Wdv7fO/uB128RN+c5tmG32ngKK7ffzDPYvS4crO/HoDdYugD5qubeeXDWPvyJq LV6Nu0TKK4B+r94jvWk++A== X-Google-Smtp-Source: AGHT+IGbVYVIJzf3Ky5RtSpHDBC96A6gAGmLe92KwdhKJGUa87dA9Nei6u7W+ae65z5/SkdH7rRhrA== X-Received: by 2002:a05:6512:114e:b0:545:b9a:b4b4 with SMTP id 2adb3069b0e04-5452fe8fd01mr6567349e87.52.1739968266349; Wed, 19 Feb 2025 04:31:06 -0800 (PST) Received: from mva-rohm ([2a10:a5c0:800d:dd00:8fdf:935a:2c85:d703]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5461cfe3a7fsm1193290e87.34.2025.02.19.04.31.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Feb 2025 04:31:03 -0800 (PST) Date: Wed, 19 Feb 2025 14:30:58 +0200 From: Matti Vaittinen To: Matti Vaittinen , Matti Vaittinen Cc: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matti Vaittinen , Lad Prabhakar , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Hugo Villeneuve , Nuno Sa , David Lechner , Javier Carrasco , Andy Shevchenko , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev Subject: [PATCH v3 4/9] MAINTAINERS: Add IIO ADC helpers Message-ID: <65fa17207c7c716d66efb95733e6a37512465605.1739967040.git.mazziesaccount@gmail.com> References: Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Add undersigned as a maintainer for the IIO ADC helpers. Signed-off-by: Matti Vaittinen --- Revision history: RFC v1 => v2: - New patch --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index a87ddad78e26..bfe2f53fa74d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11099,6 +11099,13 @@ L: linux-media@vger.kernel.org S: Maintained F: drivers/media/rc/iguanair.c +IIO ADC HELPERS +M: Matti Vaittinen +L: linux-iio@vger.kernel.org +S: Maintained +F: drivers/iio/adc/industrialio-adc.c +F: include/linux/iio/adc-helpers.h + IIO BACKEND FRAMEWORK M: Nuno Sa R: Olivier Moysan From patchwork Wed Feb 19 12:31:20 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 13982068 Received: from mail-lf1-f45.google.com (mail-lf1-f45.google.com [209.85.167.45]) (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 272951E0DD0; Wed, 19 Feb 2025 12:31:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968289; cv=none; b=ofGKkgZwA+XN5hhvNkjnHQZTE9pxqlTrJCED+DprbxX2w610m/sPzYHLabkvdTNkBkJuOab6URWZGEDhml2tqyhn2LA+ze1LaNhZAweQ00aRrs8iz9FqFvhyMyM5Mg/fvY9mb15MES1BNTavgsx3mL5Z7C5bADlQE9vr7fJ66tU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968289; c=relaxed/simple; bh=l4lUpmHuMR9617shjfZBPRDF5NOsdDEGA4OIBTz+Rhg=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=dvRpAI3AIcXP4Schep2KcZfBspTxZVhg6lewub6SvrUOr135qMeY6cPY4l6OHqpPZe/4eRQ4wdUTqmLmT0CoB/7ixtny79DrkEZRaTiunp/Zk5aqYHI/OzhZf74r/36rETcVM5AgbmxeEl+jacTxF2xwS5q0QIc/OwziiW5YEK0= 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=D9BnB0TC; arc=none smtp.client-ip=209.85.167.45 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="D9BnB0TC" Received: by mail-lf1-f45.google.com with SMTP id 2adb3069b0e04-54622940ef7so3351003e87.3; Wed, 19 Feb 2025 04:31:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739968286; x=1740573086; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=B9YlWf0udibHi5PYSeWM2mVi7/K2aWeL2dI07eP9SBw=; b=D9BnB0TCYLwTXndY1dbL5XdnSbtdKVnnWp5MRlikSQNtr9F02Tnmg0ccpsIKoHVJki Kl/wh5MHZoI9EWtG/73oTWARGRxxLdGKvHlGeJ6fG4uNZbSLsI/4x16YbE0+wmK85txa IT66WRbHbuchwBxxSVb72gzO1fDJFLWY1Qp5wMeL5oYNVCy80Jm8f/kRrtztuUrFIVgd NWXXcoTjwfR8TKP+0xKtKJKKAyHZWdQ3wntqQP3QQswdbiKEjKT/z8EyXnqGeWh3I5wI dT5pAXmLgq6dZKZxjhEK/xFQWy6UZPjP7+ULskSgbk/r3aH1V3bVkx2kOWFWGGmPf499 jrQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739968286; x=1740573086; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=B9YlWf0udibHi5PYSeWM2mVi7/K2aWeL2dI07eP9SBw=; b=sI5IFEpvO60jtTe7XoGMZSFssCeQvAgwAOqJdJmycpPlfb6eNBaghW4YfBoevtowvw BScm7TBzWlOOdxr23QCP2ZTRcAqfu3S4cmsAmjXDS0BMUjPpoE2YS9EpBok59Keri0oF SQNen1zgj0uY5Lo/7DfUJ6UVs9+0bpCu7jl1jcckooi7B4m+zvI1PWF3Yz2KShF28ecW mNZwgUrAF1YHPNBJQFEwX6UM1tisYlzSOUy5zfrrU4l9GzPlIa/z2W1RbY6J6oARFZX5 S34wyGbXk4MMWa527pZB/UijXxegBlYCI/KGhBIt8rynrIk95h02ND2nUUy6FD3PkMvz fvww== X-Forwarded-Encrypted: i=1; AJvYcCU2mMwnbC7l4QBW5cf55xx69m4m4N7BCDhWzcZkNDjn7MNsOyHywxE3422ZvWl0a8gNCQ+udcz0AIxM@vger.kernel.org, AJvYcCU5CtvcT3jCzFE4HQL/UPJMvd9HUUT5IBGh5T+J5iIy7CrRLNCoxNuyPBPlSoK0K7dgw6PHifMvxeV9zaR5S0y/ryU=@vger.kernel.org, AJvYcCUG9M2ith40fSVEZ0btexDkoh5fVSDaGr5I3oTHROXM+xbBuHVHpHEc8Tpja9CtMonqL5gTX1zIRUU6@vger.kernel.org, AJvYcCVyDvNH2VecR2wvDfBKB8RL2axyKPyLyOTZ7Z+U33yiBSIdgWj42RLbkUkeolNnfgRXYUfzMrFc8+z/f6KZ@vger.kernel.org X-Gm-Message-State: AOJu0YwUinekAwe+r1z87B+U7XK4qWKqLnfl+EVo53ZaiWxJbD3Xxhw3 O8Uv1JmCbA+DBbrUEZPiPMkhN0H3JRFlQBPffg9nq6/PM6NWXgqK X-Gm-Gg: ASbGncvKItGOEBr2J0ZJ7xfZgGuSoV6nKV0d5157wdRoQLrAwC0Zv7lMU4AlCvpFLCg d9RyLq/jpxWJ0w7UtzuirQLuzWPCbGjSRziFt+rFartbp7ffWb63bANwX45vfnhFkW5nkKiHgI/ UEi3N/plu/hpNyqaQGAGzG6sr7ikuyfoV8K1nPmzZIUKBt8vFhFzmWO9gEQ22wiR4eIzKantY+5 JK+CkZX6FOyCgIBgAbDazftKZ8vrGQEztAdsdei0TLBh9wkuuDBC9ZnchQoe5IOPW2fAD6WOjre VPbvV+p736ohHsvNZLnuDw== X-Google-Smtp-Source: AGHT+IECGLbBg8/Gfg56YN71xZxnO3b9XbM0HqSAvG6g7x6DJxq2h38ifv+YIKS+tWOSHyQD921kRg== X-Received: by 2002:a05:6512:131a:b0:545:cc2:accd with SMTP id 2adb3069b0e04-5462eee4789mr1463016e87.20.1739968285827; Wed, 19 Feb 2025 04:31:25 -0800 (PST) Received: from mva-rohm ([2a10:a5c0:800d:dd00:8fdf:935a:2c85:d703]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5451f08332bsm2121536e87.48.2025.02.19.04.31.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Feb 2025 04:31:24 -0800 (PST) Date: Wed, 19 Feb 2025 14:31:20 +0200 From: Matti Vaittinen To: Matti Vaittinen , Matti Vaittinen Cc: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matti Vaittinen , Lad Prabhakar , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Hugo Villeneuve , Nuno Sa , David Lechner , Javier Carrasco , Andy Shevchenko , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev Subject: [PATCH v3 5/9] MAINTAINERS: Add ROHM BD79124 ADC/GPO Message-ID: <33dd64a9f43ded7809e9d96de81c975cf9d68a5c.1739967040.git.mazziesaccount@gmail.com> References: Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Add undersigned as a maintainer for the ROHM BD79124 ADC/GPO driver. Signed-off-by: Matti Vaittinen --- Revision history: RFC v1 => v2: - Drop MFD and pinmux drivers --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index bfe2f53fa74d..2021327e665e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20299,6 +20299,11 @@ S: Supported F: drivers/power/supply/bd99954-charger.c F: drivers/power/supply/bd99954-charger.h +ROHM BD79124 ADC / GPO IC +M: Matti Vaittinen +S: Supported +F: drivers/iio/adc/rohm-bd79124.c + ROHM BH1745 COLOUR SENSOR M: Mudit Sharma L: linux-iio@vger.kernel.org From patchwork Wed Feb 19 12:31:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 13982069 Received: from mail-lf1-f45.google.com (mail-lf1-f45.google.com [209.85.167.45]) (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 C49531DFE32; Wed, 19 Feb 2025 12:31:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968306; cv=none; b=EY4ozWge1L7m89Svn5mFEQ/AfbC1T6dcdO12JBpAGR4bj1hHuzjtlpKR10KEhIeyyj34Sxlgb+jZoM9RDcCBGpx8i5rEpe9i1QKruo7Q5LAmM64YAE28EWm679sYOnrCXwDozYnCpShWY9s8t7hS8sI8HU0Cr1zv9RIkFrm7TDc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968306; c=relaxed/simple; bh=nx5txx/Kg5W/IwYSUOjcsemEGNxj/YYzmzKKdPde/cI=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=FKdfIA7D4GCIYNIlE1iaaEr0Ah9NqYTRwYXFYUu4Ijmo9+UuDRXdjwLMBbGTgI4ENDsrex1r2ibCCpdGXAicp4eXIbPaPNs8NZr+zpavicU8VYl3+lklimHAo5hSVsZf75F2p76L5NTu7rDCilZuKNOMi4LjWe+jCqaacjytqlY= 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=YdcnsAvj; arc=none smtp.client-ip=209.85.167.45 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="YdcnsAvj" Received: by mail-lf1-f45.google.com with SMTP id 2adb3069b0e04-54626a71b40so2571239e87.3; Wed, 19 Feb 2025 04:31:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739968303; x=1740573103; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=KWwxIm6ZCjF1USQojkSFaiOLUy9epdYG89n1EjgogqY=; b=YdcnsAvjaY4O9eY+EebssyM9I9yxUbOZ9knHjKrSaONRBy84MZ4KSolVFjNQcoKIMw TadDSp90Pa8q0wNDG1wm6yHJJu+xYWTKmM+SNQdceVS8PQCVUdu5OYNmy8hrJrokPZow RXPDjfwnMYXKmlTchQRfY2jcKMEQQz1wCZjzNRveOujwfNQKtdf1JoMesCcHs06gt0NA j/wJt5ItljgNg3nX3xSAS5doE359r+OHi6hPhZJfyZPvl6MX5ehy5iqfrVUYxjHTUc8n 28PAABL+Od9ME9pqXYZt618YdskiJrT4OFFykDkGs2+GgylWL5ZXRaPMQwic5wUQEXvN FBSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739968303; x=1740573103; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=KWwxIm6ZCjF1USQojkSFaiOLUy9epdYG89n1EjgogqY=; b=Csq3rYX3KfOkU9ErpmPe2AaHvds1QjlVTetZSjq0UkDeTonO+8sXFejts4rDYkJVqp 1DtHmB72KtSPVkMicy8NfJTyqnNzi4n83tNhoOphgpJG6lInzumpAWqVBwfFzV+rQsG1 fKFEHz5TScUg+RbKpkfS50FOFGwBUnJRvpjpiht8vgHK5OL9BLTlGU0MKw+vXmzOhNGe OnYLAFyAm02a98/eHTG6VM7e+MSiNbWmoeqOFsQZ6JWpLV4X3qf8gUa/tjNl+yBbyAkc FNiosWYIVw/Yv3W7mI78rPJd39J8iwWqJ8GsCI5eM3515yDKA1uprFIbJ//fBy3gAOa3 R8Rw== X-Forwarded-Encrypted: i=1; AJvYcCUohoUcw5lLILzvqjxpnNvlUE5G4GP7XRUMSma+Lvyp9u1E31dUb6XWP+ehIhBPZuF43skssVs9Gbki@vger.kernel.org, AJvYcCVawHbvsYnVq3KP5Jc8WmbfqX7pAwfhjtPee0G7pl3BaOmY+jQAO08ZsCkc/5cTa+Y/qNP0wdHV71CRo3G3@vger.kernel.org, AJvYcCVzCAjfQHRqjw2KoA31GcrmzEZpo/d7y/DkkS54KLVTDfGL/xnBnAIHthzxu6B14xVFn1nbdENR7G0j@vger.kernel.org, AJvYcCXBCwuW/CnP8ntA6M3Ikv6mRCCIPLwfEfyo2kzPssccOoQuie3yFy9SZmaUdaJWKlyC/mWxkVmWhQyPC74XgLYCcIc=@vger.kernel.org X-Gm-Message-State: AOJu0Yys3XCU3E3A8gASQmHE6E9Jq936N8ncWrMYX4NOp7vO5vM05JQT jzw7yAsShSvBTW0g6DQ/xrCALCwaV0syjqwbgonFWyNBjEINhCbH X-Gm-Gg: ASbGncu5malrQgPJ+v04jedhWu+KhlMLD/4J7xGF5e3GVO0kdLO4gICd5aQzX7XMD2u IlICwuHM3jmDUta2Idf1Ek3rm2XB//FPeobRNE8DrigLv1gCAwuQcE8B9IAMGXKTRkneM2Hksm5 YNvem5iaBOnz+5aNNjgaHWXFVxRIO4mfU90Tx+0MTGQ6j1teVgbx3M3EBrwplezdUNusNXbTCbl 0vR9oKlziz1eTqkzIzuXIqG9cHJWENpCf6yA7REMrcArt21GWVYVxYOyqeP/8ANiA8cdxCle27o Ea1ipY7yJVN7u8rxSX6OWw== X-Google-Smtp-Source: AGHT+IG3W//1SoXeekfyezOA2c+1vtKbVddXk84fyMfPvHE7Xk/Tk638LkqZRnBlykN65C1+4lMkfQ== X-Received: by 2002:a19:2d11:0:b0:546:27f0:21a7 with SMTP id 2adb3069b0e04-54627f02773mr3187290e87.49.1739968302667; Wed, 19 Feb 2025 04:31:42 -0800 (PST) Received: from mva-rohm ([2a10:a5c0:800d:dd00:8fdf:935a:2c85:d703]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5453961f67fsm1390216e87.23.2025.02.19.04.31.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Feb 2025 04:31:41 -0800 (PST) Date: Wed, 19 Feb 2025 14:31:38 +0200 From: Matti Vaittinen To: Matti Vaittinen , Matti Vaittinen Cc: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matti Vaittinen , Lad Prabhakar , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Hugo Villeneuve , Nuno Sa , David Lechner , Javier Carrasco , Andy Shevchenko , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev Subject: [PATCH v3 6/9] iio: adc: rzg2l_adc: Use adc-helpers Message-ID: <25c5d22f6f0cbd1355eee2e9d9103c3ee71cebdc.1739967040.git.mazziesaccount@gmail.com> References: Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: The new devm_iio_adc_device_alloc_chaninfo() -helper is intended to help drivers avoid open-coding the for_each_node -loop for getting the channel IDs. The helper provides standard way to detect the ADC channel nodes (by the node name), and a standard way to convert the "reg", "diff-channels", "single-channel" and the "common-mode-channel" to channel identification numbers used in the struct iio_chan_spec. Furthermore, the helper checks the ID is in range of 0 ... num-channels. The original driver treated all found child nodes as channel nodes. The new helper requires channel nodes to be named channel[@N]. This should help avoid problems with devices which may contain also other but ADC child nodes. Quick grep from arch/* with the rzg2l_adc's compatible string didn't reveal any in-tree .dts with channel nodes named othervice. Also, same grep shows all the .dts seem to have channel IDs between 0..num of channels. Use the new helper. Signed-off-by: Matti Vaittinen --- Revision history: v2 => v3: - New patch I picked the rzg2l_adc in this series because it has a straightforward approach for populating the struct iio_chan_spec. Only other member in the stuct besides the .channel, which can't use a 'template' -data, is the .datasheet_name. This makes the rzg2l_adc well suited for example user of this new helper. I hope this patch helps to evaluate whether these helpers are worth the hassle. The change is compile tested only!! Testing before applying is highly appreciated (as always!). --- drivers/iio/adc/rzg2l_adc.c | 41 ++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/iio/adc/rzg2l_adc.c b/drivers/iio/adc/rzg2l_adc.c index cd3a7e46ea53..3e1c74019785 100644 --- a/drivers/iio/adc/rzg2l_adc.c +++ b/drivers/iio/adc/rzg2l_adc.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -299,20 +300,34 @@ static irqreturn_t rzg2l_adc_isr(int irq, void *dev_id) return IRQ_HANDLED; } +static const struct iio_chan_spec rzg2l_adc_chan_template = { + .type = IIO_VOLTAGE, + .indexed = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +}; + +static const struct iio_adc_props rzg2l_adc_chan_props = { + .required = IIO_ADC_CHAN_PROP_TYPE_REG, +}; + static int rzg2l_adc_parse_properties(struct platform_device *pdev, struct rzg2l_adc *adc) { struct iio_chan_spec *chan_array; struct rzg2l_adc_data *data; - unsigned int channel; int num_channels; - int ret; u8 i; data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - num_channels = device_get_child_node_count(&pdev->dev); + num_channels = devm_iio_adc_device_alloc_chaninfo(&pdev->dev, + &rzg2l_adc_chan_template, &chan_array, + &rzg2l_adc_chan_props); + + if (num_channels < 0) + return num_channels; + if (!num_channels) { dev_err(&pdev->dev, "no channel children\n"); return -ENODEV; @@ -323,26 +338,10 @@ static int rzg2l_adc_parse_properties(struct platform_device *pdev, struct rzg2l return -EINVAL; } - chan_array = devm_kcalloc(&pdev->dev, num_channels, sizeof(*chan_array), - GFP_KERNEL); - if (!chan_array) - return -ENOMEM; - - i = 0; - device_for_each_child_node_scoped(&pdev->dev, fwnode) { - ret = fwnode_property_read_u32(fwnode, "reg", &channel); - if (ret) - return ret; - - if (channel >= RZG2L_ADC_MAX_CHANNELS) - return -EINVAL; + for (i = 0; i < num_channels; i++) { + int channel = chan_array[i].channel; - chan_array[i].type = IIO_VOLTAGE; - chan_array[i].indexed = 1; - chan_array[i].channel = channel; - chan_array[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW); chan_array[i].datasheet_name = rzg2l_adc_channel_name[channel]; - i++; } data->num_channels = num_channels; From patchwork Wed Feb 19 12:31:51 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 13982070 Received: from mail-lf1-f52.google.com (mail-lf1-f52.google.com [209.85.167.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 2724C1E5B71; Wed, 19 Feb 2025 12:31:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968321; cv=none; b=pvIoAj16eDDBxO7Cq7KVuLd32hk727QxON9SvNwbHR94apARVFk3r83dudAE94UYQ1po6orBYywcwr3je2bUgMz7WACiZPBDKATTQK8br76OUFNE0xJi/CbDnXhEDe4gRVtaJTeVYqsOR4Z/0adY061pCNQIGwuShNCR3m9ZU+w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968321; c=relaxed/simple; bh=U0JRwfZpNRp+812FgOW9ZHl/nMZWKI1NbdstILYPpaY=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=QoWnd7Nw2gDskOKLxHnZcHUuL+4fna8UYNM4iOBiiqGgJZMKzztDA7ibDB/qt+yZ9u1FDsJOVxImQLSKUOxBC4+aN0bSXKpqAnplpBEK1UHIAJ6crBvAdz8CmaQ154sCxgjQDFOECAvipaqZQzcH/XEW+NaidYF7QbSBtDqqARg= 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=carIGxqz; arc=none smtp.client-ip=209.85.167.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="carIGxqz" Received: by mail-lf1-f52.google.com with SMTP id 2adb3069b0e04-5461b5281bcso3422299e87.3; Wed, 19 Feb 2025 04:31:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739968317; x=1740573117; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=K/8lsdpKrVRGvDk8bdsIYhaiCtFIej4Yk5OWrIJakDc=; b=carIGxqzkRkRgey0H0ILDYuhc/AsFMSBHEJ+nwaKN9kGg8imcDRk16skeysNqFUTNd ObskyAo22W/XKs0vZtDR50tcFwZsa8WfGkETMk+eRJvHhqqEzUo2g+vIasCv0ic9fdf/ u0BmtoE05G/42htdRf6ZbPNSFk5VkEDFEd1ixvvOVR+duSznx1DRBfRAU83jlOVBMBmH B+k6b/KN7Mi1Z2ivK37NZazh/7gxIBcNWVawQ5C03fpuz39PeSLCIqpxB4drR4HMzgf0 JYGYA1iqiuqs764kqVFcdYEORn9Gt6xJFjZw0ujkAWSd2gfV/MxUh8U+3EcN8kq5h3bB Ot2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739968317; x=1740573117; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=K/8lsdpKrVRGvDk8bdsIYhaiCtFIej4Yk5OWrIJakDc=; b=RQ1/bPoU04Y5jtBFQzmwGoTWdhAsShUjoVgqeL3xLfecCT90CnrQuenAi77aMQHuCi bmYO6gBV4v2TIMXaumlwBUCmGf7WrwdECsUJ53XS8vx8furg8PxwdUuW7MVP2I9ipBjt A8bAFJB6da/DgfC/XIW7WOnjmKv0/Hc6xy4xLxnMcSH4DUoTvQSisNCrHxqF9rk5vZP7 L5uFvgzKhYCfouMWiEM3NkkMfvAEzDwmbljIuyADrW6+QfDzCeShmVKqKlVFSOMHzYLq UR33g60K88njomT7KxNgVfPzY9eC2YC473EptpN6mCm9a41Xf7/OAtr/bTSSmcziRB7i z9jA== X-Forwarded-Encrypted: i=1; AJvYcCUO+5FjQd4PnVWcnnHAxse24tkII8ZrmYc0iYAQJF3MVP5VLrenKaF8of896AcgidH+IF+nKfGzi86x@vger.kernel.org, AJvYcCWveyMinYaT+h5i9VzgDUAN2nnIcXV6rO/VV/AHlAfHhglsm+7IxImFTwIN/sU1y44VRujptKBqVprdFlhLlqPv8Ik=@vger.kernel.org, AJvYcCX2TOX5+pw3Q+KHc7KK4Iubm7Ei2gkROePHpZp5poAtYJNN/cxxJG4a4JmtMXWSWKrmYsjIZK7vCauL1pNW@vger.kernel.org, AJvYcCXVaftHwN5bJ123qIad45YWSOHw+PbLC3gZGDZmKEw80bmJ8cqu8HqXb9dhLcin/dlFyQ7D2/RjZc+/@vger.kernel.org X-Gm-Message-State: AOJu0Yz9Po1IUze8MVDN1imFT4dTNddUcaCwnWW1HU3jUQ9Say152xNL VREckkBMAjw8946/eNVb356sv6YLqxbT8Lrj1rE3MWEq9arCMemZ X-Gm-Gg: ASbGnct9fWLpnw9np+ARnbbPyEr+zp9Y7AQvvODgZ5HW9jURNmSuzI+7ww8cKkl47wI sHiax1v4k/dyfczqhZROys9VkCVlaqt3qkSIjEqQE1wsazPZk27HokCGwLloMJl6f8n0c7h0kYk IvxaPfVrnsxyM3+1H4qbjw++rGa6b2F+3s5QnEcRCcFDchBx0IF5QV4RVZsbGXmtB3cfrxEOnTK m208SNsSxBoGoYcZ1+y0loAFVcZlxHXdPx/8PSUG3SjpKjg0e1xwQd/vt4xmrJeFRYATQTzsdml Q38I5d7SGPIvxL8d3poSkQ== X-Google-Smtp-Source: AGHT+IHxBzOtMjJ6R20Hyns4SI3S/h1XqzVvWjCS9fdPX3gfnk60+xs7fGA4Wr7UNOkuWHPHq9EJQw== X-Received: by 2002:a05:6512:1286:b0:545:2950:5360 with SMTP id 2adb3069b0e04-5452fe570a5mr6750403e87.22.1739968316988; Wed, 19 Feb 2025 04:31:56 -0800 (PST) Received: from mva-rohm ([2a10:a5c0:800d:dd00:8fdf:935a:2c85:d703]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5461db6474bsm1137730e87.58.2025.02.19.04.31.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Feb 2025 04:31:56 -0800 (PST) Date: Wed, 19 Feb 2025 14:31:51 +0200 From: Matti Vaittinen To: Matti Vaittinen , Matti Vaittinen Cc: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matti Vaittinen , Lad Prabhakar , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Hugo Villeneuve , Nuno Sa , David Lechner , Javier Carrasco , Andy Shevchenko , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev Subject: [PATCH v3 7/9] iio: adc: sun20i-gpadc: Use adc-helpers Message-ID: <21b9af362b64a1d9c2a13cc46242dd6955996c46.1739967040.git.mazziesaccount@gmail.com> References: Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: The new devm_iio_adc_device_alloc_chaninfo() -helper is intended to help drivers avoid open-coding the for_each_node -loop for getting the channel IDs. The helper provides standard way to detect the ADC channel nodes (by the node name), and a standard way to convert the "reg", "diff-channels", "single-channel" and the "common-mode-channel" to channel identification numbers used in the struct iio_chan_spec. Furthermore, the helper checks the ID is in range of 0 ... num-channels. The original driver treated all found child nodes as channel nodes. The new helper requires channel nodes to be named channel[@N]. This should help avoid problems with devices which may contain also other but ADC child nodes. Quick grep from arch/* with the sun20i-gpadc's compatible string didn't reveal any in-tree .dts with channel nodes named othervice. Also, same grep shows all the in-tree .dts seem to have channel IDs between 0..num of channels. Use the new helper. Signed-off-by: Matti Vaittinen --- Revision history: v2 => v3: - New patch I picked the sun20i-gpadc in this series because it has a straightforward approach for populating the struct iio_chan_spec. Everything else except the .channel can use 'template'-data. This makes the sun20i-gpadc well suited to be an example user of this new helper. I hope this patch helps to evaluate whether these helpers are worth the hassle. The change is compile tested only!! Testing before applying is highly appreciated (as always!). Also, even though I tried to audit the dts files for the reg-properties in the channel nodes, use of references didn't make it easy. I can't guarantee I didn't miss anything. --- drivers/iio/adc/sun20i-gpadc-iio.c | 42 ++++++++++++++---------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/drivers/iio/adc/sun20i-gpadc-iio.c b/drivers/iio/adc/sun20i-gpadc-iio.c index 136b8d9c294f..36d48d95f029 100644 --- a/drivers/iio/adc/sun20i-gpadc-iio.c +++ b/drivers/iio/adc/sun20i-gpadc-iio.c @@ -15,6 +15,7 @@ #include #include +#include #include #define SUN20I_GPADC_DRIVER_NAME "sun20i-gpadc" @@ -149,37 +150,32 @@ static void sun20i_gpadc_reset_assert(void *data) reset_control_assert(rst); } +static const struct iio_chan_spec sun20i_gpadc_chan_template = { + .type = IIO_VOLTAGE, + .indexed = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), +}; + +static const struct iio_adc_props sun20i_gpadc_chan_props = { + .required = IIO_ADC_CHAN_PROP_TYPE_REG, +}; + static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev, struct device *dev) { - unsigned int channel; - int num_channels, i, ret; + int num_channels; struct iio_chan_spec *channels; - num_channels = device_get_child_node_count(dev); + num_channels = devm_iio_adc_device_alloc_chaninfo(dev, + &sun20i_gpadc_chan_template, &channels, + &sun20i_gpadc_chan_props); + if (num_channels < 0) + return num_channels; + if (num_channels == 0) return dev_err_probe(dev, -ENODEV, "no channel children\n"); - channels = devm_kcalloc(dev, num_channels, sizeof(*channels), - GFP_KERNEL); - if (!channels) - return -ENOMEM; - - i = 0; - device_for_each_child_node_scoped(dev, node) { - ret = fwnode_property_read_u32(node, "reg", &channel); - if (ret) - return dev_err_probe(dev, ret, "invalid channel number\n"); - - channels[i].type = IIO_VOLTAGE; - channels[i].indexed = 1; - channels[i].channel = channel; - channels[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW); - channels[i].info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); - - i++; - } - indio_dev->channels = channels; indio_dev->num_channels = num_channels; From patchwork Wed Feb 19 12:32:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 13982071 Received: from mail-lf1-f43.google.com (mail-lf1-f43.google.com [209.85.167.43]) (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 1C8D71DF26A; Wed, 19 Feb 2025 12:32:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968337; cv=none; b=o82CuosiJqTI+Z/Vxnt/Fo3B6WMTTOyPnKGIWo5UFChbOfVQKUxJ04S2dC6Y4uaP4INXw0FvAJ8AmOajfaKSGaALM4ukqvepGjsA4RJKgD1c42COQV1hLjixAUALdkU2VkZbfxb7VIpEgrygZkQMI2lgaYajDmwzD3KHaWIGqA4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968337; c=relaxed/simple; bh=IBbz+wObyAhqTzMziGPirWIFuoReTJvh68cD9yxqDCk=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=KxDYu+iaQWfZtHawTB+yHuhzxTUf+0pfVfHw7kbhRNtnhf8bkRMvbSY2lvFrM2h1dwbGapDZekVTHRyhaCozrf62X0R4pHK88FFBYkMFEko524Vh3zd3shMjAv/EYmLgf7kAprn789D9eH55J5a0+NJdSGtsj9ecYWbVKFCrHzs= 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=CDTxzSnG; arc=none smtp.client-ip=209.85.167.43 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="CDTxzSnG" Received: by mail-lf1-f43.google.com with SMTP id 2adb3069b0e04-54622940ef7so3351812e87.3; Wed, 19 Feb 2025 04:32:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739968333; x=1740573133; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=872sDDSaszSL1+yhyVainkn552F70TCEUEKtazE+wZs=; b=CDTxzSnGy23+3naIwWYEaxwQFE1u/TNZ3nVIN+chfbtMwKQaSwonP3tmnFGO0gLlJN A+a7U80U3CNibHCY7vFy6K11xhKklkgTcv4wjiJed6twmrM2xNbd2o14i5A1tAjuW0lU cTRrGEsJAPKbaWXbhcg/5qm/f4aN9sLYWgWw5do31V1S1o279qQX2aYVlHyRNCDX0Xxb J/ZMYRDkXnuw1AHNFovHRF9khAGpLMlRY2udxNtWQVvVzHmFqNcr0ZjdQIEB8udQEL5u rF1ZWuNuMEIJoExfvHfJsmKhoIKggBZ6/jwOTCKTuXvCtv63KEz+tya3ruMrAVAJGz2B 1O+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739968333; x=1740573133; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=872sDDSaszSL1+yhyVainkn552F70TCEUEKtazE+wZs=; b=qXuEdPPCfOy6T+nYhYOX4Jid0ef2BvtU1jFUvAuKCSLfw1OECaoSLHVKCOGOk1Cygq St0NnbdF0sdGZq3NG77RVjRpykekYn0WG6yJIQbwXIYCp3jh/i0ej7eiYe2EStOe1B2c SfAdr6z/J8Sux/zdJC0icyIR3RiATroE3P4nxv02rhIbbUJ9KVD30KuuQKUE3JNXTPCn nismSX4N48XZ5eM3jVU8XkWBi8+pH0qZ4C9X2KE5EcTMBQx23NOVxrZAv3u9swjW0pR1 gpOeIqpS3mwngXtDcu13urPLSfupdkb9Ewrnw1RFwtn6yjo9FxYciq6/uTeN27OursXl 9O4A== X-Forwarded-Encrypted: i=1; AJvYcCVeYSslkE/YfGP2yopsqMKHeP+A+p5rTLYpXwG0ExA3S2sNTKKKKyM3gKKwUthaWtL3dSPkLgCwF3dN1xOKe/niXzI=@vger.kernel.org, AJvYcCWW317SxU/JOakvWcyNKTGYfRtEuEhkFvYNs0SjPnAFGmOre+08LlF0h6kBFmIGLb/SAD5GJW3BSlZn@vger.kernel.org, AJvYcCX6bA9cUt4siduePMTBNflhaz0hhWn7+juCJdLCp+au0P/cBNc77r3zLkJRdIuFcGLcSF2/31ghsIhR@vger.kernel.org, AJvYcCXdT3QBlC57XSgCDRlOmRyMEUYBOg58T8Fld6grfwZ9+kOxlcPoDCQ608pTazK9i9MsD6XjPwSvX62Ss8rJ@vger.kernel.org X-Gm-Message-State: AOJu0Yw0Z9LR52SugG9bd0/0n85dB/N2KViui/UgV8MTf3SFHoJ9dHO1 ngjWKwaUkVeZ7WL7qyoPKVLN3LJqZ+5lH1gIcsm1GJetbQKxEKMY X-Gm-Gg: ASbGncvECr9KO0FdwtefXKi/CMasV++SPxEiNsplmXi2Xse/gwXRRkLHGmGLUDGucXq 0d5jX5h/55K06x2f5MOZQO0gCfWYPnb/XIbl4eX9Uyr9O7jVa39Rw/rqdU2VrUuBnG3SMrVO2Av UsTfKKtzr+pfizGJsNmK9uFzm/qIYS6pcRnDiUkVYq5DEboaLxc5IgDZ0aagyaGKuq6UleeY8S3 2OHdfGAR98blluWwxvkSQbx457TSv3KNv4xkd4hp4kE0gaLOJ0C9xXcHGoMztPgpRhXRPWCRjDV 19Gl+dWoUfDnu8TMIXT6NQ== X-Google-Smtp-Source: AGHT+IET+JJuBMU3Y/6jzse1ZgT54+aygXA9AXNLRXFpXqkVIx7/7mkYzYqgDRV3tj+3kjGQpH/r/A== X-Received: by 2002:a05:6512:2249:b0:545:c08:e17b with SMTP id 2adb3069b0e04-5462eef2242mr1448277e87.23.1739968332998; Wed, 19 Feb 2025 04:32:12 -0800 (PST) Received: from mva-rohm ([2a10:a5c0:800d:dd00:8fdf:935a:2c85:d703]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5452f6efbf5sm1596646e87.18.2025.02.19.04.32.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Feb 2025 04:32:11 -0800 (PST) Date: Wed, 19 Feb 2025 14:32:06 +0200 From: Matti Vaittinen To: Matti Vaittinen , Matti Vaittinen Cc: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matti Vaittinen , Lad Prabhakar , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Hugo Villeneuve , Nuno Sa , David Lechner , Javier Carrasco , Andy Shevchenko , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev Subject: [PATCH v3 8/9] iio: adc: ti-ads7924 Drop unnecessary function parameters Message-ID: <3155f491753944d6511d058a09f6f6c505d551f9.1739967040.git.mazziesaccount@gmail.com> References: Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Device pointer is the only variable which is used by the ads7924_get_channels_config() and which is declared outside this function. Still, the function gets the iio_device and i2c_client as parameters. The sole caller of this function (probe) already has the device pointer which it can directly pass to the function. Simplify code by passing the device pointer directly as a parameter instead of digging it from the iio_device's private data. Signed-off-by: Matti Vaittinen --- This commit is compile-tested only! All further testing is appreciated. --- drivers/iio/adc/ti-ads7924.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/iio/adc/ti-ads7924.c b/drivers/iio/adc/ti-ads7924.c index 66b54c0d75aa..b1f745f75dbe 100644 --- a/drivers/iio/adc/ti-ads7924.c +++ b/drivers/iio/adc/ti-ads7924.c @@ -251,11 +251,8 @@ static const struct iio_info ads7924_info = { .read_raw = ads7924_read_raw, }; -static int ads7924_get_channels_config(struct i2c_client *client, - struct iio_dev *indio_dev) +static int ads7924_get_channels_config(struct device *dev) { - struct ads7924_data *priv = iio_priv(indio_dev); - struct device *dev = priv->dev; struct fwnode_handle *node; int num_channels = 0; @@ -380,7 +377,7 @@ static int ads7924_probe(struct i2c_client *client) indio_dev->num_channels = ARRAY_SIZE(ads7924_channels); indio_dev->info = &ads7924_info; - ret = ads7924_get_channels_config(client, indio_dev); + ret = ads7924_get_channels_config(dev); if (ret < 0) return dev_err_probe(dev, ret, "failed to get channels configuration\n"); From patchwork Wed Feb 19 12:32:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 13982072 Received: from mail-lj1-f182.google.com (mail-lj1-f182.google.com [209.85.208.182]) (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 5ABC71DF974; Wed, 19 Feb 2025 12:32:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968352; cv=none; b=JWbTX9lcHxNyA/8JQ/7NU0ZlVOaj2uFLsR1HOcuMOFLo+H1EmJTHnj9u7vH+eUr4/lxEtJlrR2oEXX3G3Qn9pUNR89zj3hNUu1bcrFsUGvoV3UIlyZdz9oHC5xspdc6+io6Kk+YDxaaHSaGNwgwK0s36edci33fHy+zdQ9sIgyc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739968352; c=relaxed/simple; bh=H48Lkeq71Idm7qh8MQ4iHSeWtKwyxrxWrUPyhfQpTto=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=plRNjXfHtGy4o9Gp937UL/hBG52+HCRIm0ObxLndoTy2x6+eys4SRpv5Bn4/06ZkigNowOksIQkgvwoYT39oIrgzOfUKEUfcXa3gYuS2sml7gJ2teqwF7/UeyuweTp/wL1aTu55TvuuHuXOjjDhcrPzc1N6tY/JR9Q0bDupDRdk= 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=e/OA+Qfz; arc=none smtp.client-ip=209.85.208.182 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="e/OA+Qfz" Received: by mail-lj1-f182.google.com with SMTP id 38308e7fff4ca-30a2dfcfd83so32471981fa.1; Wed, 19 Feb 2025 04:32:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1739968348; x=1740573148; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=0DYvjW5f0VauVHlYQoEoi+1LNEnpUSDiH5KvYpk6CeA=; b=e/OA+QfzQEH5ZJiXdsVhdvFFAoz4cIkk5u9WZ4dDvanaUPM+BbJBVVxX/OTSZ3HpcL keiT+Q0TCN0gCuXp1k8Uh9rXoud4szV0JzhU7UjujeupWLzC1KW9jcATjoDMMbHtcgrk E0rKytfACS7dgvi+io27akEpp5a9W3Jd67Vl/UXfLLY417Grf+xXVj0iPEx6k/QoEu+I 1sZrfJRprMSS1k69OZjDBiJ1WIh3rDinQDsT0ZjcjsvqCsqpZh8eOq8NPjdlLpxEz4cp ytYD970KO1UHfWceBWKzop9In7SKEJ+y4AEjYQ+y6Ze2lzr8oaigsnt/BYJ1lMmi4gSO aekw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739968348; x=1740573148; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=0DYvjW5f0VauVHlYQoEoi+1LNEnpUSDiH5KvYpk6CeA=; b=BIH1KPJnROumdh+z4Or57q5Ik4wIie7x/aVl9NVWrkbu72Or3daHIwO0MNPUGCVmkk CXL0Bhv5sB2olf0xBFpKeUT9is1Eewcj8+FKTX+re/ltcdBOt5A/QbuRWSvbp0av2Vh+ g8vAZWVks74WURjVjm6d9vdVClTjQUxmMI2DTYWA09cROzEm0kuLRUPqcV7E2mIx0R/w hkTSoP2q7oRTb3/Z/9lZlN6KAxHvhW+Hu21GBdinvueK0VmBHCW8IlLjLmSQ7f8lgwFO OD/BvwR+FJ/4fxJ4TRWoh3a3CPUqu+GyIJ0xmb22plWfVB+MQ8mOVwcVy+qL+2T//tnd Wu2g== X-Forwarded-Encrypted: i=1; AJvYcCU3etnTrypxRUoP9LmnVDkabWFRYSjTreJH8aOrYAX8zcYl8aHXeODWio5ckSIOptukowK7yG8OgRJRDNHeo/zT8Ms=@vger.kernel.org, AJvYcCUTYi5DlGMNbKP8zlHRx6zjx6k7SUVpGBkdZ1OlFXXmO5Q4az3Sd6GvDHGVcS9trW0byj4FUhXl0vqYXp1f@vger.kernel.org, AJvYcCUeXCt5FYNndsQwS50vgmQhBlsHYlTbzQ4zfrbUEn0jQL56FmS35KdlFNSmNjTU3ltH6uHwemBlgIdd@vger.kernel.org, AJvYcCVK1nMXUcqCyvPnuzxk7NBp1x+ekwrAv9osIl3wVloIFqH3dKCH8vYiTg/3TldXmRcVuaXXjFji5FMY@vger.kernel.org X-Gm-Message-State: AOJu0YxnkdztyGrqIJMGXy2Je4BFpOrYuNfmhMQuWnDtnTW+z8Za5ieN jhX9w3onO/0w5n5kuGNjp7uVUmRM2PEpwJyEnrfI7v1ehfIOq0Ux X-Gm-Gg: ASbGncsGbWm0G00iY1MutaTYQXWz/Uj1v2F7fYSO3sP5+IwS6Vko8xmJ/Y9UusHz0Os SBpwxmuYZ8kuKtzlIzYdmwRIFZueSVyQOFUhwgPmc8Q4CapIXsVAvTFzNOIl3JvXwVXsD91uGwT gbsH4JR5sBfLEYfS1acv317R73vbSdabQkffchXxBijN/emperOhnijvCDvDI+PLKoLb2LAwrgN 8qXUFi0acBDj+MD6CHujJgcsabIgoyT9C+0ajyTqtFH690UQXai31A0w3Ciq6gZtsmb0/Fg7ZHn fchKRTXeLhys9mh1uOuLbg== X-Google-Smtp-Source: AGHT+IGpj+sXTk9ydInkrFSzD/8u3Ea569jfA3qPAyfTIDaLYJDMfGIteoPF8DQijF1k+5z6DuXOPg== X-Received: by 2002:a2e:9905:0:b0:308:f01f:181f with SMTP id 38308e7fff4ca-30927aff022mr48385981fa.31.1739968348109; Wed, 19 Feb 2025 04:32:28 -0800 (PST) Received: from mva-rohm ([2a10:a5c0:800d:dd00:8fdf:935a:2c85:d703]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-30a344c8900sm9350131fa.22.2025.02.19.04.32.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Feb 2025 04:32:27 -0800 (PST) Date: Wed, 19 Feb 2025 14:32:23 +0200 From: Matti Vaittinen To: Matti Vaittinen , Matti Vaittinen Cc: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matti Vaittinen , Lad Prabhakar , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Hugo Villeneuve , Nuno Sa , David Lechner , Javier Carrasco , Andy Shevchenko , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev Subject: [PATCH v3 9/9] iio: adc: ti-ads7924: Respect device tree config Message-ID: <3279aa9348e7149bfbd433daaa201f2eb5873e1f.1739967040.git.mazziesaccount@gmail.com> References: Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: The ti-ads7924 driver ignores the device-tree ADC channel specification and always exposes all 4 channels to users whether they are present in the device-tree or not. Additionally, the "reg" values in the channel nodes are ignored, although an error is printed if they are out of range. Register only the channels described in the device-tree, and use the reg property as a channel ID. Signed-off-by: Matti Vaittinen --- Revision history: v2 => v3: New patch Please note that this is potentially breaking existing users if they have wrong values in the device-tree. I believe the device-tree should ideally be respected, and if it says device X has only one channel, then we should believe it and not register 4. Well, we don't live in the ideal world, so even though I believe this is TheRightThingToDo - it may cause havoc because correct device-tree has not been required from the day 1. So, please review and test and apply at your own risk :) As a side note, this might warrant a fixes tag but the adc-helper -stuff is hardly worth to be backported... (And I've already exceeded my time budget with this series - hence I'll leave crafting backportable fix to TI people ;) ) This has only been compile tested! All testing is highly appreciated. --- drivers/iio/adc/ti-ads7924.c | 80 +++++++++++++++++------------------- 1 file changed, 37 insertions(+), 43 deletions(-) diff --git a/drivers/iio/adc/ti-ads7924.c b/drivers/iio/adc/ti-ads7924.c index b1f745f75dbe..a5b8f7c81b8a 100644 --- a/drivers/iio/adc/ti-ads7924.c +++ b/drivers/iio/adc/ti-ads7924.c @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -119,15 +120,12 @@ #define ADS7924_TOTAL_CONVTIME_US (ADS7924_PWRUPTIME_US + ADS7924_ACQTIME_US + \ ADS7924_CONVTIME_US) -#define ADS7924_V_CHAN(_chan, _addr) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .channel = _chan, \ - .address = _addr, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ - .datasheet_name = "AIN"#_chan, \ -} +static const struct iio_chan_spec ads7924_chan_template = { + .type = IIO_VOLTAGE, + .indexed = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), +}; struct ads7924_data { struct device *dev; @@ -182,13 +180,6 @@ static const struct regmap_config ads7924_regmap_config = { .writeable_reg = ads7924_is_writeable_reg, }; -static const struct iio_chan_spec ads7924_channels[] = { - ADS7924_V_CHAN(0, ADS7924_DATA0_U_REG), - ADS7924_V_CHAN(1, ADS7924_DATA1_U_REG), - ADS7924_V_CHAN(2, ADS7924_DATA2_U_REG), - ADS7924_V_CHAN(3, ADS7924_DATA3_U_REG), -}; - static int ads7924_get_adc_result(struct ads7924_data *data, struct iio_chan_spec const *chan, int *val) { @@ -251,32 +242,38 @@ static const struct iio_info ads7924_info = { .read_raw = ads7924_read_raw, }; -static int ads7924_get_channels_config(struct device *dev) +static const struct iio_adc_props ads7924_chan_props = { + .required = IIO_ADC_CHAN_PROP_TYPE_REG, +}; + +static int ads7924_get_channels_config(struct iio_dev *indio_dev, + struct device *dev) { - struct fwnode_handle *node; - int num_channels = 0; + struct iio_chan_spec *chan_array; + int num_channels = 0, i; - device_for_each_child_node(dev, node) { - u32 pval; - unsigned int channel; + num_channels = devm_iio_adc_device_alloc_chaninfo(dev, + &ads7924_chan_template, &chan_array, + &ads7924_chan_props); - if (fwnode_property_read_u32(node, "reg", &pval)) { - dev_err(dev, "invalid reg on %pfw\n", node); - continue; - } + if (num_channels < 0) + return num_channels; - channel = pval; - if (channel >= ADS7924_CHANNELS) { - dev_err(dev, "invalid channel index %d on %pfw\n", - channel, node); - continue; - } + if (!num_channels) + return -EINVAL; + + for (i = 0; i < num_channels; i++) { + static const char * const datasheet_names[] = { + "AIN0", "AIN1", "AIN2", "AIN3" + }; + int ch_id = chan_array[i].channel; - num_channels++; + chan_array[i].address = ADS7924_DATA0_U_REG + ch_id; + chan_array[i].datasheet_name = datasheet_names[ch_id]; } - if (!num_channels) - return -EINVAL; + indio_dev->channels = chan_array; + indio_dev->num_channels = num_channels; return 0; } @@ -370,18 +367,15 @@ static int ads7924_probe(struct i2c_client *client) mutex_init(&data->lock); - indio_dev->name = "ads7924"; - indio_dev->modes = INDIO_DIRECT_MODE; - - indio_dev->channels = ads7924_channels; - indio_dev->num_channels = ARRAY_SIZE(ads7924_channels); - indio_dev->info = &ads7924_info; - - ret = ads7924_get_channels_config(dev); + ret = ads7924_get_channels_config(indio_dev, dev); if (ret < 0) return dev_err_probe(dev, ret, "failed to get channels configuration\n"); + indio_dev->name = "ads7924"; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &ads7924_info; + data->regmap = devm_regmap_init_i2c(client, &ads7924_regmap_config); if (IS_ERR(data->regmap)) return dev_err_probe(dev, PTR_ERR(data->regmap),