From patchwork Wed Apr 16 16:21:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Vecera X-Patchwork-Id: 14054207 X-Patchwork-Delegate: kuba@kernel.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 19F9B1A23BE for ; Wed, 16 Apr 2025 16:22:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820526; cv=none; b=r10DQrKbHKkQS6NYPQ6CYra5jwoJj6P4+Mpnbu1ThYlCwCwfKTSZ2/uln/nqRrtlPoDb7YUHtd01RRdG+pZ7OG6kyHMrLlIVCAWJeINDyonmfXbZjLSOcMTXD7YT2E0H5yHu2ExHBavZDW5FC/ypf5Nsv5kjCq0OykBYXFKAVH4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820526; c=relaxed/simple; bh=pvztLf2+f/TeR7vcXBvLoFOJlmGc+oGeCk8DZGt4HUs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ENURo6Gj/PmD88tEpi0ngjLKpXpQFD80znn1y9CXvuQXdvXzR6bVKrgQuynJYePNsRv5bh7SmtRQDlWLMJ4G5QSqtjHYs9JTk6YI4RxQ0ovYryUdDrARpWfTvaszBBvOJmLufK0G6Xh2zEhspaLNDM0W/tMf4yqbzq6bmt8TBAE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=EEqaRyk9; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="EEqaRyk9" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1744820524; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VODoBL80CQHBrJrr7R/ZL/MS/tpTwQM1Yp3DwpdKziM=; b=EEqaRyk9YSGVZX7Kv1rnd8yk92TicNo2sJrtiMjalQhd6lrQyXSRM7R0U9UPhCzBlUj4NH rAZD1uJY5b0YjatH0fB9WU4lVTS/XtSEmo5TkqNeEq/id5DfzJ9E7UV2hstcN9Tf2u8Alf ZafEbk6jHCUcxBFgbLLjbRCnLMY9UL0= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-108-anChNQjwMRS_B3QDKNEIeg-1; Wed, 16 Apr 2025 12:22:01 -0400 X-MC-Unique: anChNQjwMRS_B3QDKNEIeg-1 X-Mimecast-MFC-AGG-ID: anChNQjwMRS_B3QDKNEIeg_1744820516 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0BC951800878; Wed, 16 Apr 2025 16:21:56 +0000 (UTC) Received: from p16v.luc.cera.cz (unknown [10.44.33.32]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0F103180045B; Wed, 16 Apr 2025 16:21:50 +0000 (UTC) From: Ivan Vecera To: netdev@vger.kernel.org Cc: Vadim Fedorenko , Arkadiusz Kubalewski , Jiri Pirko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Prathosh Satish , Lee Jones , Kees Cook , Andy Shevchenko , Andrew Morton , Michal Schmidt , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v3 net-next 1/8] dt-bindings: dpll: Add device tree bindings for DPLL device and pin Date: Wed, 16 Apr 2025 18:21:37 +0200 Message-ID: <20250416162144.670760-2-ivecera@redhat.com> In-Reply-To: <20250416162144.670760-1-ivecera@redhat.com> References: <20250416162144.670760-1-ivecera@redhat.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Patchwork-Delegate: kuba@kernel.org Add a common DT schema for DPLL device and associated pin. The DPLL (device phase-locked loop) is a device used for precise clock synchronization in networking and telecom hardware. The device itself is equipped with one or more DPLLs (channels) and one or more physical input and output pins. Each DPLL channel is used either to provide pulse-per-clock signal or to drive ethernet equipment clock. The input and output pins have a label (specifies board label), type (specifies its usage depending on wiring), list of supported or allowed frequencies (depending on how the pin is connected and where) and can support embedded sync capability. Signed-off-by: Ivan Vecera --- v1->v3: * rewritten description for both device and pin * dropped num-dplls property * supported-frequencies property renamed to supported-frequencies-hz --- .../devicetree/bindings/dpll/dpll-device.yaml | 76 +++++++++++++++++++ .../devicetree/bindings/dpll/dpll-pin.yaml | 44 +++++++++++ MAINTAINERS | 2 + 3 files changed, 122 insertions(+) create mode 100644 Documentation/devicetree/bindings/dpll/dpll-device.yaml create mode 100644 Documentation/devicetree/bindings/dpll/dpll-pin.yaml diff --git a/Documentation/devicetree/bindings/dpll/dpll-device.yaml b/Documentation/devicetree/bindings/dpll/dpll-device.yaml new file mode 100644 index 0000000000000..11a02b74e28b7 --- /dev/null +++ b/Documentation/devicetree/bindings/dpll/dpll-device.yaml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dpll/dpll-device.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Digital Phase-Locked Loop (DPLL) Device + +maintainers: + - Ivan Vecera + +description: + Digital Phase-Locked Loop (DPLL) device is used for precise clock + synchronization in networking and telecom hardware. The device can + have one or more channels (DPLLs) and one or more physical input and + output pins. Each DPLL channel can either produce pulse-per-clock signal + or drive ethernet equipment clock. The type of each channel can be + indicated by dpll-types property. + +properties: + $nodename: + pattern: "^dpll(@.*)?$" + + "#address-cells": + const: 0 + + "#size-cells": + const: 0 + + dpll-types: + description: List of DPLL channel types, one per DPLL instance. + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + items: + enum: [pps, eec] + + input-pins: + type: object + description: DPLL input pins + unevaluatedProperties: false + + properties: + "#address-cells": + const: 1 + "#size-cells": + const: 0 + + patternProperties: + "^pin@[0-9]+$": + $ref: /schemas/dpll/dpll-pin.yaml + unevaluatedProperties: false + + required: + - "#address-cells" + - "#size-cells" + + output-pins: + type: object + description: DPLL output pins + unevaluatedProperties: false + + properties: + "#address-cells": + const: 1 + "#size-cells": + const: 0 + + patternProperties: + "^pin@[0-9]+$": + $ref: /schemas/dpll/dpll-pin.yaml + unevaluatedProperties: false + + required: + - "#address-cells" + - "#size-cells" + +additionalProperties: true diff --git a/Documentation/devicetree/bindings/dpll/dpll-pin.yaml b/Documentation/devicetree/bindings/dpll/dpll-pin.yaml new file mode 100644 index 0000000000000..44af3a4398a5f --- /dev/null +++ b/Documentation/devicetree/bindings/dpll/dpll-pin.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dpll/dpll-pin.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: DPLL Pin + +maintainers: + - Ivan Vecera + +description: | + The DPLL pin is either a physical input or output pin that is provided + by a DPLL( Digital Phase-Locked Loop) device. The pin is identified by + its physical order number that is stored in reg property and can have + an additional set of properties like supported (allowed) frequencies, + label, type and may support embedded sync. + Note that the pin in this context has nothing to do with pinctrl. + +properties: + reg: + description: Hardware index of the DPLL pin. + $ref: /schemas/types.yaml#/definitions/uint32 + + esync-control: + description: Indicates whether the pin supports embedded sync functionality. + type: boolean + + label: + description: String exposed as the pin board label + $ref: /schemas/types.yaml#/definitions/string + + supported-frequencies-hz: + description: List of supported frequencies for this pin, expressed in Hz. + + type: + description: Type of the pin + $ref: /schemas/types.yaml#/definitions/string + enum: [ext, gnss, int, mux, synce] + +required: + - reg + +additionalProperties: false diff --git a/MAINTAINERS b/MAINTAINERS index 1248443035f43..f645ef38d2224 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7187,6 +7187,8 @@ M: Arkadiusz Kubalewski M: Jiri Pirko L: netdev@vger.kernel.org S: Supported +F: Documentation/devicetree/bindings/dpll/dpll-device.yaml +F: Documentation/devicetree/bindings/dpll/dpll-pin.yaml F: Documentation/driver-api/dpll.rst F: drivers/dpll/* F: include/linux/dpll.h From patchwork Wed Apr 16 16:21:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Vecera X-Patchwork-Id: 14054208 X-Patchwork-Delegate: kuba@kernel.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 164B0212B31 for ; Wed, 16 Apr 2025 16:22:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820531; cv=none; b=K9DBAr5J2nw3a3z4JKEy67x2lDDVXEAM11JF2RaTZjA9LPsydHd6ZF472jAWhyK5UTa+xgiGmlFCYFN3OYX7rrp6BPmDGlPq+v9VRuSVE/DCJh0Ln9H8VwayUJ8z/A5hieFvTRxFTVkAO19BpOt7Vfq9yHykLaUgaiKb+4fe2G0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820531; c=relaxed/simple; bh=aQfGhYphwtdsVQYR1n6GCV280C9Iv47jePw0KVZiRqo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hhZm0cex+MRDUI35ACVtTtjWaPn0VKESVD3ySgGjIPIUZRNrvi6q0meuMT1jhLbgO/ORdbWpQiBJCXndikxYexfi/qORbBmxU0CvinWFac53ejH2rQSwdOCyvNxBrR9CAqeO42k1QXAvhQPf1+7zw8ueuukXbJJrXBmObar+YYM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=EtpsDvxM; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="EtpsDvxM" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1744820528; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=c1E5OFYBgnUMUUJtH2lEiHD6dZG1MJrGDVETUsXtNfk=; b=EtpsDvxMoZoT1sdTvvlZNPAFzxPH6W/haLgrfC8k5vBLwm7A7DJbtPjL73VxDnCznOy3xW QEw4YMlUqnuehMYvHxZPVxJIC5R/6NZLAXDMhX1bv0rbrVz3JBW6qPmZuefQO91nlbJdtZ JRsCCvZD/TdmdKUSodqsUT9CzxhgQBE= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-32-N6v62SgwM6ifAzqG-ziAuw-1; Wed, 16 Apr 2025 12:22:04 -0400 X-MC-Unique: N6v62SgwM6ifAzqG-ziAuw-1 X-Mimecast-MFC-AGG-ID: N6v62SgwM6ifAzqG-ziAuw_1744820522 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CDD851956095; Wed, 16 Apr 2025 16:22:01 +0000 (UTC) Received: from p16v.luc.cera.cz (unknown [10.44.33.32]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 91FC11800352; Wed, 16 Apr 2025 16:21:56 +0000 (UTC) From: Ivan Vecera To: netdev@vger.kernel.org Cc: Vadim Fedorenko , Arkadiusz Kubalewski , Jiri Pirko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Prathosh Satish , Lee Jones , Kees Cook , Andy Shevchenko , Andrew Morton , Michal Schmidt , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v3 net-next 2/8] dt-bindings: dpll: Add support for Microchip Azurite chip family Date: Wed, 16 Apr 2025 18:21:38 +0200 Message-ID: <20250416162144.670760-3-ivecera@redhat.com> In-Reply-To: <20250416162144.670760-1-ivecera@redhat.com> References: <20250416162144.670760-1-ivecera@redhat.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Patchwork-Delegate: kuba@kernel.org Add DT bindings for Microchip Azurite DPLL chip family. These chips provides up to 5 independent DPLL channels, 10 differential or single-ended inputs and 10 differential or 20 single-ended outputs. It can be connected via I2C or SPI busses. Signed-off-by: Ivan Vecera --- v1->v3: * single file for both i2c & spi * 5 compatibles for all supported chips from the family --- .../bindings/dpll/microchip,zl30731.yaml | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 Documentation/devicetree/bindings/dpll/microchip,zl30731.yaml diff --git a/Documentation/devicetree/bindings/dpll/microchip,zl30731.yaml b/Documentation/devicetree/bindings/dpll/microchip,zl30731.yaml new file mode 100644 index 0000000000000..cb1486d140382 --- /dev/null +++ b/Documentation/devicetree/bindings/dpll/microchip,zl30731.yaml @@ -0,0 +1,115 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dpll/microchip,zl3073x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip Azurite DPLL device + +maintainers: + - Ivan Vecera + +description: + Microchip Azurite DPLL (ZL3073x) is a family of DPLL devices that + provides up to 5 independent DPLL channels, up to 10 differential or + single-ended inputs and 10 differential or 20 single-ended outputs. + These devices support both I2C and SPI interfaces. + +properties: + compatible: + enum: + - microchip,zl30731 + - microchip,zl30732 + - microchip,zl30733 + - microchip,zl30734 + - microchip,zl30735 + + reg: + maxItems: 1 + +required: + - compatible + - reg + +allOf: + - $ref: /schemas/dpll/dpll-device.yaml# + - $ref: /schemas/spi/spi-peripheral-props.yaml# + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + dpll@70 { + compatible = "microchip,zl30732"; + reg = <0x70>; + dpll-types = "pps", "eec"; + + input-pins { + #address-cells = <1>; + #size-cells = <0>; + + pin@0 { /* REF0P */ + reg = <0>; + label = "Input 0"; + supported-frequencies = /bits/ 64 <1 1000>; + type = "ext"; + }; + }; + + output-pins { + #address-cells = <1>; + #size-cells = <0>; + + pin@3 { /* OUT1N */ + reg = <3>; + esync-control; + label = "Output 1"; + supported-frequencies = /bits/ 64 <1 10000>; + type = "gnss"; + }; + }; + }; + }; + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + dpll@70 { + compatible = "microchip,zl30731"; + reg = <0x70>; + spi-max-frequency = <12500000>; + + dpll-types = "pps"; + + input-pins { + #address-cells = <1>; + #size-cells = <0>; + + pin@0 { /* REF0P */ + reg = <0>; + label = "Input 0"; + supported-frequencies = /bits/ 64 <1 1000>; + type = "ext"; + }; + }; + + output-pins { + #address-cells = <1>; + #size-cells = <0>; + + pin@3 { /* OUT1N */ + reg = <3>; + esync-control; + label = "Output 1"; + supported-frequencies = /bits/ 64 <1 10000>; + type = "gnss"; + }; + }; + }; + }; +... From patchwork Wed Apr 16 16:21:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Vecera X-Patchwork-Id: 14054209 X-Patchwork-Delegate: kuba@kernel.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C9ADF2135BC for ; Wed, 16 Apr 2025 16:22:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820539; cv=none; b=uMeNxKTVKkf5/IKJzN6Yt260oYNSPpKCDsVJQfiR4nCx44YIiFRLLtQm+gLEXJSjZTccRW20+zP2pSWZdbXz32RNdWrwms9nlNBzYU5oGOtuTRR18cuZyyTgptKnMvZpx+gR1AjT2a+++KYoG0mCYn12UnU82+MkhBQfNmUU4Cw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820539; c=relaxed/simple; bh=T55z9sc/d4/6bLn4CQV8/tIT2cm47S8kd9/1wjb6Ej0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DooeHh4fhZA8Chu1eVua3+s3KVu88+WFn75gJaRPnPgT/Vul5sOlluADYNREXmduqTCtAuSrI7otVX5w7CvpK6rMb7Rw2cfbX4qCeJn1P+L/AOdHiKfwuVufVHff/hKflQg/rBYgA+G+yR2jC4A9eSMWK8ErbYuknNREkDQ//5A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=duHGDwLd; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="duHGDwLd" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1744820536; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6XxcqG/4fYZlHnCMo/LifOl8siUw/d7QSk0+ya0B1EY=; b=duHGDwLdvTmzNFJa7e+55lAeuqyXK7E7w8/zYWPcY1FT1pmTZ6lkwU7Tk4oW+g+0wDKFJY xvxGdG5n7WgOHf2IM8+cqPANt46z1P80L1CK5E+2hx68q0DqdU6DnbjPpeyzQ9zDICBujG xJYoKs+HzO9Kzi0oM+cWHA9l0+QDDEc= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-511-H-lVoIc3PSetCr9wNUK0Cw-1; Wed, 16 Apr 2025 12:22:09 -0400 X-MC-Unique: H-lVoIc3PSetCr9wNUK0Cw-1 X-Mimecast-MFC-AGG-ID: H-lVoIc3PSetCr9wNUK0Cw_1744820527 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 550541800981; Wed, 16 Apr 2025 16:22:07 +0000 (UTC) Received: from p16v.luc.cera.cz (unknown [10.44.33.32]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 49332180094C; Wed, 16 Apr 2025 16:22:02 +0000 (UTC) From: Ivan Vecera To: netdev@vger.kernel.org Cc: Vadim Fedorenko , Arkadiusz Kubalewski , Jiri Pirko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Prathosh Satish , Lee Jones , Kees Cook , Andy Shevchenko , Andrew Morton , Michal Schmidt , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v3 net-next 3/8] mfd: Add Microchip ZL3073x support Date: Wed, 16 Apr 2025 18:21:39 +0200 Message-ID: <20250416162144.670760-4-ivecera@redhat.com> In-Reply-To: <20250416162144.670760-1-ivecera@redhat.com> References: <20250416162144.670760-1-ivecera@redhat.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Patchwork-Delegate: kuba@kernel.org Add base MFD driver for Microchip Azurite ZL3073x chip family. These chips provide DPLL and PHC (PTP) functionality and they can be connected over I2C or SPI bus. The MFD driver provide basic communication and synchronization over the bus and common functionality that are used by the DPLL driver (in the part 2) and by the PTP driver (will be added later). The chip family is characterized by following properties: * up to 5 separate DPLL units (channels) * 5 synthesizers * 10 input pins (references) * 10 outputs * 20 output pins (output pin pair shares one output) * Each reference and output can act in differential or single-ended mode (reference or output in differential mode consumes 2 pins) * Each output is connected to one of the synthesizers * Each synthesizer is driven by one of the DPLL unit The device uses 7-bit addresses and 8-bits for values. It exposes 8-, 16-, 32- and 48-bits registers in address range <0x000,0x77F>. Due to 7bit addressing the range is organized into pages of size 128 and each page contains page selector register (0x7F). To read/write multi-byte registers the device supports bulk transfers. There are 2 kinds of registers, simple ones that are present at register pages 0..9 and mailbox ones that are present at register pages 10..14. To access mailbox type registers a caller has to take mailbox_mutex that ensures the reading and committing mailbox content is done atomically. More information about it in later patch from the series. Signed-off-by: Ivan Vecera --- v2->v3: * added chip_info with valid chip ids and num of DPLLs for compatibles * regmap is using implicit locking * mailbox registers requires extra mutex to be held * added helpers to access registers * report device firmware and config version using dev_dbg * fixed regmap ranges * enabled rbtree regcache for page selector v1->v2: * fixed header issues * removed usage of of_match_ptr * added check for devm_mutex_init * removed commas after sentinels * removed variable initialization in zl3073x_i2c_probe() * moved device tables closer to their users * renamed zl3073x_dev_alloc() to zl3073x_devm_alloc() * removed empty zl3073x_dev_exit() * spidev renamed to spi * squashed together with device DT bindings * used dev_err_probe() instead of dev_err() during probe * added some function documentation DT bindings: * spliced to separate files for i2c and spi * fixed property order in DT bindings' examples * added description --- MAINTAINERS | 9 ++ drivers/mfd/Kconfig | 30 +++++ drivers/mfd/Makefile | 5 + drivers/mfd/zl3073x-core.c | 218 +++++++++++++++++++++++++++++++ drivers/mfd/zl3073x-i2c.c | 68 ++++++++++ drivers/mfd/zl3073x-spi.c | 68 ++++++++++ drivers/mfd/zl3073x.h | 31 +++++ include/linux/mfd/zl3073x.h | 50 +++++++ include/linux/mfd/zl3073x_regs.h | 105 +++++++++++++++ 9 files changed, 584 insertions(+) create mode 100644 drivers/mfd/zl3073x-core.c create mode 100644 drivers/mfd/zl3073x-i2c.c create mode 100644 drivers/mfd/zl3073x-spi.c create mode 100644 drivers/mfd/zl3073x.h create mode 100644 include/linux/mfd/zl3073x.h create mode 100644 include/linux/mfd/zl3073x_regs.h diff --git a/MAINTAINERS b/MAINTAINERS index f645ef38d2224..cf050f59696e0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15992,6 +15992,15 @@ L: linux-wireless@vger.kernel.org S: Supported F: drivers/net/wireless/microchip/ +MICROCHIP ZL3073X DRIVER +M: Ivan Vecera +M: Prathosh Satish +L: netdev@vger.kernel.org +S: Supported +F: Documentation/devicetree/bindings/dpll/microchip,zl3073x*.yaml +F: drivers/mfd/zl3073x* +F: include/linux/mfd/zl3073x.h + MICROSEMI MIPS SOCS M: Alexandre Belloni M: UNGLinuxDriver@microchip.com diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 22b9363100394..7d7902ec1d89a 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -2422,5 +2422,35 @@ config MFD_UPBOARD_FPGA To compile this driver as a module, choose M here: the module will be called upboard-fpga. +config MFD_ZL3073X_CORE + tristate + select MFD_CORE + +config MFD_ZL3073X_I2C + tristate "Microchip Azurite DPLL/PTP/SyncE with I2C" + depends on I2C + select MFD_ZL3073X_CORE + select REGMAP_I2C + help + Say Y here if you want to build I2C support for the Microchip + Azurite DPLL/PTP/SyncE chip family. + + To compile this driver as a module, choose M here: the module + will be called zl3073x_i2c and you will also get zl3073x for + the core module. + +config MFD_ZL3073X_SPI + tristate "Microchip Azurite DPLL/PTP/SyncE with SPI" + depends on SPI + select MFD_ZL3073X_CORE + select REGMAP_SPI + help + Say Y here if you want to build SPI support for the Microchip + Azurite DPLL/PTP/SyncE chip family. + + To compile this driver as a module, choose M here: the module + will be called zl3073x_spi and you will also get zl3073x for + the core module. + endmenu endif diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 948cbdf42a18b..76e2babc1538f 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -290,3 +290,8 @@ obj-$(CONFIG_MFD_RSMU_I2C) += rsmu_i2c.o rsmu_core.o obj-$(CONFIG_MFD_RSMU_SPI) += rsmu_spi.o rsmu_core.o obj-$(CONFIG_MFD_UPBOARD_FPGA) += upboard-fpga.o + +zl3073x-y := zl3073x-core.o +obj-$(CONFIG_MFD_ZL3073X_CORE) += zl3073x.o +obj-$(CONFIG_MFD_ZL3073X_I2C) += zl3073x-i2c.o +obj-$(CONFIG_MFD_ZL3073X_SPI) += zl3073x-spi.o diff --git a/drivers/mfd/zl3073x-core.c b/drivers/mfd/zl3073x-core.c new file mode 100644 index 0000000000000..0455d6ae37da5 --- /dev/null +++ b/drivers/mfd/zl3073x-core.c @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "zl3073x.h" + +/* Chip IDs for zl30731 */ +static const u16 zl30731_ids[] = { + 0x0E93, + 0x1E93, + 0x2E93, +}; + +/* Chip IDs for zl30732 */ +static const u16 zl30732_ids[] = { + 0x0E30, + 0x0E94, + 0x1E94, + 0x1F60, + 0x2E94, + 0x3FC4, +}; + +/* Chip IDs for zl30733 */ +static const u16 zl30733_ids[] = { + 0x0E95, + 0x1E95, + 0x2E95, +}; + +/* Chip IDs for zl30734 */ +static const u16 zl30734_ids[] = { + 0x0E96, + 0x1E96, + 0x2E96, +}; + +/* Chip IDs for zl30735 */ +static const u16 zl30735_ids[] = { + 0x0E97, + 0x1E97, + 0x2E97, +}; + +const struct zl3073x_chip_info zl3073x_chip_info[] = { + [ZL30731] = { + .ids = zl30731_ids, + .num_ids = ARRAY_SIZE(zl30731_ids), + .num_channels = 1, + }, + [ZL30732] = { + .ids = zl30732_ids, + .num_ids = ARRAY_SIZE(zl30732_ids), + .num_channels = 2, + }, + [ZL30733] = { + .ids = zl30733_ids, + .num_ids = ARRAY_SIZE(zl30733_ids), + .num_channels = 3, + }, + [ZL30734] = { + .ids = zl30734_ids, + .num_ids = ARRAY_SIZE(zl30734_ids), + .num_channels = 4, + }, + [ZL30735] = { + .ids = zl30735_ids, + .num_ids = ARRAY_SIZE(zl30735_ids), + .num_channels = 5, + }, +}; +EXPORT_SYMBOL_NS_GPL(zl3073x_chip_info, "ZL3073X"); + +#define ZL_NUM_PAGES 15 +#define ZL_NUM_SIMPLE_PAGES 10 +#define ZL_PAGE_SEL 0x7F +#define ZL_PAGE_SEL_MASK GENMASK(3, 0) +#define ZL_NUM_REGS (ZL_NUM_PAGES * ZL_PAGE_SIZE) + +/* Regmap range configuration */ +static const struct regmap_range_cfg zl3073x_regmap_range = { + .range_min = ZL_RANGE_OFF, + .range_max = ZL_RANGE_OFF + ZL_NUM_REGS - 1, + .selector_reg = ZL_PAGE_SEL, + .selector_mask = ZL_PAGE_SEL_MASK, + .selector_shift = 0, + .window_start = 0, + .window_len = ZL_PAGE_SIZE, +}; + +static bool +zl3073x_is_volatile_reg(struct device *dev, unsigned int reg) +{ + /* Only page selector is non-volatile */ + return (reg != ZL_PAGE_SEL); +} + +static const struct regmap_config zl3073x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = ZL_RANGE_OFF + ZL_NUM_REGS - 1, + .ranges = &zl3073x_regmap_range, + .num_ranges = 1, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = zl3073x_is_volatile_reg, +}; + +/** + * zl3073x_devm_alloc - allocates zl3073x device structure + * @dev: pointer to device structure + * + * Allocates zl3073x device structure as device resource and initializes + * regmap_mutex. + * + * Return: pointer to zl3073x device on success, error pointer on error + */ +struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev) +{ + struct zl3073x_dev *zldev; + int rc; + + zldev = devm_kzalloc(dev, sizeof(*zldev), GFP_KERNEL); + if (!zldev) + return ERR_PTR(-ENOMEM); + + zldev->dev = dev; + + /* We have to initialize regmap mutex here because during + * zl3073x_dev_probe() is too late as the regmaps are already + * initialized. + */ + rc = devm_mutex_init(zldev->dev, &zldev->mailbox_lock); + if (rc) { + dev_err_probe(zldev->dev, rc, "Failed to initialize mutex\n"); + return ERR_PTR(rc); + } + + return zldev; +} +EXPORT_SYMBOL_NS_GPL(zl3073x_devm_alloc, "ZL3073X"); + +/** + * zl3073x_dev_init_regmap_config - initialize regmap config + * @regmap_cfg: regmap_config structure to fill + * + * Initializes regmap config common for I2C and SPI. + */ +void zl3073x_dev_init_regmap_config(struct regmap_config *regmap_cfg) +{ + *regmap_cfg = zl3073x_regmap_config; +} +EXPORT_SYMBOL_NS_GPL(zl3073x_dev_init_regmap_config, "ZL3073X"); + +/** + * zl3073x_dev_probe - initialize zl3073x device + * @zldev: pointer to zl3073x device + * @chip_info: chip info based on compatible + * + * Common initialization of zl3073x device structure. + * + * Returns: 0 on success, <0 on error + */ +int zl3073x_dev_probe(struct zl3073x_dev *zldev, + const struct zl3073x_chip_info *chip_info) +{ + u16 id, revision, fw_ver; + u32 cfg_ver; + int i, rc; + + /* Read chip ID */ + rc = zl3073x_read_id(zldev, &id); + if (rc) + return rc; + + /* Check it matches */ + for (i = 0; i < chip_info->num_ids; i++) { + if (id == chip_info->ids[i]) + break; + } + + if (i == chip_info->num_ids) { + dev_err(zldev->dev, "Unknown or non-match chip ID: 0x%0x\n", id); + return -ENODEV; + } + + /* Read revision, firmware version and custom config version */ + rc = zl3073x_read_revision(zldev, &revision); + if (rc) + return rc; + rc = zl3073x_read_fw_ver(zldev, &fw_ver); + if (rc) + return rc; + rc = zl3073x_read_custom_config_ver(zldev, &cfg_ver); + if (rc) + return rc; + + dev_dbg(zldev->dev, "ChipID(%X), ChipRev(%X), FwVer(%u)\n", id, + revision, fw_ver); + dev_dbg(zldev->dev, "Custom config version: %lu.%lu.%lu.%lu\n", + FIELD_GET(GENMASK(31, 24), cfg_ver), + FIELD_GET(GENMASK(23, 16), cfg_ver), + FIELD_GET(GENMASK(15, 8), cfg_ver), + FIELD_GET(GENMASK(7, 0), cfg_ver)); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(zl3073x_dev_probe, "ZL3073X"); + +MODULE_AUTHOR("Ivan Vecera "); +MODULE_DESCRIPTION("Microchip ZL3073x core driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/zl3073x-i2c.c b/drivers/mfd/zl3073x-i2c.c new file mode 100644 index 0000000000000..76bc9a0463180 --- /dev/null +++ b/drivers/mfd/zl3073x-i2c.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include "zl3073x.h" + +static int zl3073x_i2c_probe(struct i2c_client *client) +{ + struct regmap_config regmap_cfg; + struct device *dev = &client->dev; + struct zl3073x_dev *zldev; + + zldev = zl3073x_devm_alloc(dev); + if (IS_ERR(zldev)) + return PTR_ERR(zldev); + + i2c_set_clientdata(client, zldev); + + zl3073x_dev_init_regmap_config(®map_cfg); + + zldev->regmap = devm_regmap_init_i2c(client, ®map_cfg); + if (IS_ERR(zldev->regmap)) { + dev_err_probe(dev, PTR_ERR(zldev->regmap), + "Failed to initialize regmap\n"); + return PTR_ERR(zldev->regmap); + } + + return zl3073x_dev_probe(zldev, i2c_get_match_data(client)); +} + +static const struct i2c_device_id zl3073x_i2c_id[] = { + { "zl30731", .driver_data = (kernel_ulong_t)&zl3073x_chip_info[ZL30731] }, + { "zl30732", .driver_data = (kernel_ulong_t)&zl3073x_chip_info[ZL30732] }, + { "zl30733", .driver_data = (kernel_ulong_t)&zl3073x_chip_info[ZL30733] }, + { "zl30734", .driver_data = (kernel_ulong_t)&zl3073x_chip_info[ZL30734] }, + { "zl30735", .driver_data = (kernel_ulong_t)&zl3073x_chip_info[ZL30735] }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, zl3073x_i2c_id); + +static const struct of_device_id zl3073x_i2c_of_match[] = { + { .compatible = "microchip,zl30731", .data = &zl3073x_chip_info[ZL30731] }, + { .compatible = "microchip,zl30732", .data = &zl3073x_chip_info[ZL30732] }, + { .compatible = "microchip,zl30733", .data = &zl3073x_chip_info[ZL30733] }, + { .compatible = "microchip,zl30734", .data = &zl3073x_chip_info[ZL30734] }, + { .compatible = "microchip,zl30735", .data = &zl3073x_chip_info[ZL30735] }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, zl3073x_i2c_of_match); + +static struct i2c_driver zl3073x_i2c_driver = { + .driver = { + .name = "zl3073x-i2c", + .of_match_table = zl3073x_i2c_of_match, + }, + .probe = zl3073x_i2c_probe, + .id_table = zl3073x_i2c_id, +}; +module_i2c_driver(zl3073x_i2c_driver); + +MODULE_AUTHOR("Ivan Vecera "); +MODULE_DESCRIPTION("Microchip ZL3073x I2C driver"); +MODULE_IMPORT_NS("ZL3073X"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/zl3073x-spi.c b/drivers/mfd/zl3073x-spi.c new file mode 100644 index 0000000000000..d0fc2d2221c0d --- /dev/null +++ b/drivers/mfd/zl3073x-spi.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include "zl3073x.h" + +static int zl3073x_spi_probe(struct spi_device *spi) +{ + struct regmap_config regmap_cfg; + struct device *dev = &spi->dev; + struct zl3073x_dev *zldev; + + zldev = zl3073x_devm_alloc(dev); + if (IS_ERR(zldev)) + return PTR_ERR(zldev); + + spi_set_drvdata(spi, zldev); + + zl3073x_dev_init_regmap_config(®map_cfg); + + zldev->regmap = devm_regmap_init_spi(spi, ®map_cfg); + if (IS_ERR(zldev->regmap)) { + dev_err_probe(dev, PTR_ERR(zldev->regmap), + "Failed to initialize regmap\n"); + return PTR_ERR(zldev->regmap); + } + + return zl3073x_dev_probe(zldev, spi_get_device_match_data(spi)); +} + +static const struct spi_device_id zl3073x_spi_id[] = { + { "zl30731", .driver_data = (kernel_ulong_t)&zl3073x_chip_info[ZL30731] }, + { "zl30731", .driver_data = (kernel_ulong_t)&zl3073x_chip_info[ZL30732] }, + { "zl30731", .driver_data = (kernel_ulong_t)&zl3073x_chip_info[ZL30733] }, + { "zl30731", .driver_data = (kernel_ulong_t)&zl3073x_chip_info[ZL30734] }, + { "zl30731", .driver_data = (kernel_ulong_t)&zl3073x_chip_info[ZL30735] }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(spi, zl3073x_spi_id); + +static const struct of_device_id zl3073x_spi_of_match[] = { + { .compatible = "microchip,zl30731", .data = &zl3073x_chip_info[ZL30731] }, + { .compatible = "microchip,zl30732", .data = &zl3073x_chip_info[ZL30732] }, + { .compatible = "microchip,zl30733", .data = &zl3073x_chip_info[ZL30733] }, + { .compatible = "microchip,zl30734", .data = &zl3073x_chip_info[ZL30734] }, + { .compatible = "microchip,zl30735", .data = &zl3073x_chip_info[ZL30735] }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, zl3073x_spi_of_match); + +static struct spi_driver zl3073x_spi_driver = { + .driver = { + .name = "zl3073x-spi", + .of_match_table = zl3073x_spi_of_match, + }, + .probe = zl3073x_spi_probe, + .id_table = zl3073x_spi_id, +}; +module_spi_driver(zl3073x_spi_driver); + +MODULE_AUTHOR("Ivan Vecera "); +MODULE_DESCRIPTION("Microchip ZL3073x SPI driver"); +MODULE_IMPORT_NS("ZL3073X"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/zl3073x.h b/drivers/mfd/zl3073x.h new file mode 100644 index 0000000000000..3a2fea61cf579 --- /dev/null +++ b/drivers/mfd/zl3073x.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __ZL3073X_CORE_H +#define __ZL3073X_CORE_H + +struct device; +struct regmap_config; +struct zl3073x_dev; + +enum zl3073x_chip_type { + ZL30731, + ZL30732, + ZL30733, + ZL30734, + ZL30735, +}; + +struct zl3073x_chip_info { + const u16 *ids; + size_t num_ids; + int num_channels; +}; + +extern const struct zl3073x_chip_info zl3073x_chip_info[]; + +struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev); +void zl3073x_dev_init_regmap_config(struct regmap_config *regmap_cfg); +int zl3073x_dev_probe(struct zl3073x_dev *zldev, + const struct zl3073x_chip_info *chip_info); + +#endif /* __ZL3073X_CORE_H */ diff --git a/include/linux/mfd/zl3073x.h b/include/linux/mfd/zl3073x.h new file mode 100644 index 0000000000000..b68481dcf77a5 --- /dev/null +++ b/include/linux/mfd/zl3073x.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __LINUX_MFD_ZL3073X_H +#define __LINUX_MFD_ZL3073X_H + +#include + +struct device; +struct regmap; + +/** + * struct zl3073x_dev - zl3073x device + * @dev: pointer to device + * @regmap: regmap to access device registers + * @mailbox_lock: mutex protecting an access to mailbox registers + */ +struct zl3073x_dev { + struct device *dev; + struct regmap *regmap; + struct mutex mailbox_lock; +}; + +/** + * zl3073x_mailbox_lock - Lock the device mailbox registers + * @zldev: zl3073x device pointer + * + * Caller has to held this lock when it needs to access device mailbox + * registers. + */ +static inline void zl3073x_mailbox_lock(struct zl3073x_dev *zldev) +{ + mutex_lock(&zldev->mailbox_lock); +} + +/** + * zl3073x_mailbox_unlock - Unlock the device mailbox registers + * @zldev: zl3073x device pointer + * + * Caller has to unlock this lock when it finishes accessing device mailbox + * registers. + */ +static inline void zl3073x_mailbox_unlock(struct zl3073x_dev *zldev) +{ + mutex_unlock(&zldev->mailbox_lock); +} + +DEFINE_GUARD(zl3073x_mailbox, struct zl3073x_dev *, zl3073x_mailbox_lock(_T), + zl3073x_mailbox_unlock(_T)); + +#endif /* __LINUX_MFD_ZL3073X_H */ diff --git a/include/linux/mfd/zl3073x_regs.h b/include/linux/mfd/zl3073x_regs.h new file mode 100644 index 0000000000000..453a5da8ac63f --- /dev/null +++ b/include/linux/mfd/zl3073x_regs.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __LINUX_MFD_ZL3073X_REGS_H +#define __LINUX_MFD_ZL3073X_REGS_H + +#include +#include +#include +#include +#include +#include + +/* Registers are mapped at offset 0x100 */ +#define ZL_RANGE_OFF 0x100 +#define ZL_PAGE_SIZE 0x80 +#define ZL_REG_ADDR(_pg, _off) (ZL_RANGE_OFF + (_pg) * ZL_PAGE_SIZE + (_off)) + +/************************** + * Register Page 0, General + **************************/ + +/* + * Register 'id' + * Page: 0, Offset: 0x01, Size: 16 bits + */ +#define ZL_REG_ID ZL_REG_ADDR(0, 0x01) + +static inline __maybe_unused int +zl3073x_read_id(struct zl3073x_dev *zldev, u16 *value) +{ + __be16 temp; + int rc; + + rc = regmap_bulk_read(zldev->regmap, ZL_REG_ID, &temp, sizeof(temp)); + if (rc) + return rc; + + *value = be16_to_cpu(temp); + return rc; +} + +/* + * Register 'revision' + * Page: 0, Offset: 0x03, Size: 16 bits + */ +#define ZL_REG_REVISION ZL_REG_ADDR(0, 0x03) + +static inline __maybe_unused int +zl3073x_read_revision(struct zl3073x_dev *zldev, u16 *value) +{ + __be16 temp; + int rc; + + rc = regmap_bulk_read(zldev->regmap, ZL_REG_REVISION, &temp, + sizeof(temp)); + if (rc) + return rc; + + *value = be16_to_cpu(temp); + return rc; +} + +/* + * Register 'fw_ver' + * Page: 0, Offset: 0x05, Size: 16 bits + */ +#define ZL_REG_FW_VER ZL_REG_ADDR(0, 0x05) + +static inline __maybe_unused int +zl3073x_read_fw_ver(struct zl3073x_dev *zldev, u16 *value) +{ + __be16 temp; + int rc; + + rc = regmap_bulk_read(zldev->regmap, ZL_REG_FW_VER, &temp, + sizeof(temp)); + if (rc) + return rc; + + *value = be16_to_cpu(temp); + return rc; +} + +/* + * Register 'custom_config_ver' + * Page: 0, Offset: 0x07, Size: 32 bits + */ +#define ZL_REG_CUSTOM_CONFIG_VER ZL_REG_ADDR(0, 0x07) + +static inline __maybe_unused int +zl3073x_read_custom_config_ver(struct zl3073x_dev *zldev, u32 *value) +{ + __be32 temp; + int rc; + + rc = regmap_bulk_read(zldev->regmap, ZL_REG_CUSTOM_CONFIG_VER, &temp, + sizeof(temp)); + if (rc) + return rc; + + *value = be32_to_cpu(temp); + return rc; +} + +#endif /* __LINUX_MFD_ZL3073X_REGS_H */ From patchwork Wed Apr 16 16:21:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Vecera X-Patchwork-Id: 14054210 X-Patchwork-Delegate: kuba@kernel.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5E83C214A60 for ; Wed, 16 Apr 2025 16:22:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820543; cv=none; b=bLqPUeoZAxmTEvmGc9mDyB23NXX96s1gWZ9GFIUOolX2h3WsCZXoWHFV8jhpdWFJTGeI4hH9YcEHnhs+x86pAtdUT8BRInyF2DqOx3o7msY4GX3ic1y30JqP5/xpqHQ0pNGbWwBb25NYDvlwoIORpMZY6zN9vFnB/RlgFonsRnk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820543; c=relaxed/simple; bh=qLpO/eKYIGCFvjkI4c9bvOECPSxSEKHEZEhy0rk4jyg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=macUzP0CVVWL/9h04RJoa1AlzRPuquGxGJz0tUt+4Wr0yehMA+Ky2l6pZ79xu28A6me6V4QOhVJmqC1BczhWqS3tWh3GiM1fJW6JHDzXNQr26BXJO1bEHUQQgkqIYwuG1I4ZjnjglJ8uXfeNh4RcDoDRqj+/KtqbvxmgVj0viJg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=QIA01b/6; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="QIA01b/6" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1744820540; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=C0LuOHZvP1P1dwLlicwz/s117HJCINnm2wIz4uJxIs8=; b=QIA01b/6qcCdI/Rh4q77NmP2JHTzXOoQZz6moYuQZr7F8twNe7yBMCiEDtAML3TA/xBvpG C+O7slOZwqpQ4miNX6va440EqqhAPLXJuwqOfVoxNDPXGRw/DgQBedmErfWc63dRjeuL75 E/iKtP9gUeFNTUzFCuwXGbBTb48wUvs= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-556--nWDcjrrOtOMh3xXBYolWw-1; Wed, 16 Apr 2025 12:22:15 -0400 X-MC-Unique: -nWDcjrrOtOMh3xXBYolWw-1 X-Mimecast-MFC-AGG-ID: -nWDcjrrOtOMh3xXBYolWw_1744820533 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0E4061956095; Wed, 16 Apr 2025 16:22:13 +0000 (UTC) Received: from p16v.luc.cera.cz (unknown [10.44.33.32]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C6B53180045B; Wed, 16 Apr 2025 16:22:07 +0000 (UTC) From: Ivan Vecera To: netdev@vger.kernel.org Cc: Vadim Fedorenko , Arkadiusz Kubalewski , Jiri Pirko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Prathosh Satish , Lee Jones , Kees Cook , Andy Shevchenko , Andrew Morton , Michal Schmidt , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v3 net-next 4/8] mfd: zl3073x: Add support for devlink device info Date: Wed, 16 Apr 2025 18:21:40 +0200 Message-ID: <20250416162144.670760-5-ivecera@redhat.com> In-Reply-To: <20250416162144.670760-1-ivecera@redhat.com> References: <20250416162144.670760-1-ivecera@redhat.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Patchwork-Delegate: kuba@kernel.org Use devlink_alloc() to alloc zl3073x_dev structure, register the device as a devlink device and add devlink callback to provide devlink device info. Signed-off-by: Ivan Vecera --- v2->v3: * merged devlink device allocation, registration and device info callback v1->v2: - dependency on NET moved to MFD_ZL3073X_CORE in Kconfig - devlink register managed way --- drivers/mfd/Kconfig | 2 + drivers/mfd/zl3073x-core.c | 106 ++++++++++++++++++++++++++++++++++++- 2 files changed, 106 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 7d7902ec1d89a..e4eca15af175d 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -2424,6 +2424,8 @@ config MFD_UPBOARD_FPGA config MFD_ZL3073X_CORE tristate + depends on NET + select NET_DEVLINK select MFD_CORE config MFD_ZL3073X_I2C diff --git a/drivers/mfd/zl3073x-core.c b/drivers/mfd/zl3073x-core.c index 0455d6ae37da5..8a15237e0f731 100644 --- a/drivers/mfd/zl3073x-core.c +++ b/drivers/mfd/zl3073x-core.c @@ -8,7 +8,10 @@ #include #include #include +#include #include +#include +#include #include "zl3073x.h" /* Chip IDs for zl30731 */ @@ -112,6 +115,83 @@ static const struct regmap_config zl3073x_regmap_config = { .volatile_reg = zl3073x_is_volatile_reg, }; +/** + * zl3073x_devlink_info_get - Devlink device info callback + * @devlink: devlink structure pointer + * @req: devlink request pointer to store information + * @extack: netlink extack pointer to report errors + * + * Return: 0 on success, <0 on error + */ +static int zl3073x_devlink_info_get(struct devlink *devlink, + struct devlink_info_req *req, + struct netlink_ext_ack *extack) +{ + struct zl3073x_dev *zldev = devlink_priv(devlink); + u16 id, revision, fw_ver; + char buf[16]; + u32 cfg_ver; + int rc; + + rc = zl3073x_read_id(zldev, &id); + if (rc) + return rc; + + snprintf(buf, sizeof(buf), "%X", id); + rc = devlink_info_version_fixed_put(req, + DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, + buf); + if (rc) + return rc; + + rc = zl3073x_read_revision(zldev, &revision); + if (rc) + return rc; + + snprintf(buf, sizeof(buf), "%X", revision); + rc = devlink_info_version_fixed_put(req, + DEVLINK_INFO_VERSION_GENERIC_ASIC_REV, + buf); + if (rc) + return rc; + + rc = zl3073x_read_fw_ver(zldev, &fw_ver); + if (rc) + return rc; + + snprintf(buf, sizeof(buf), "%u", fw_ver); + rc = devlink_info_version_fixed_put(req, + DEVLINK_INFO_VERSION_GENERIC_FW, + buf); + if (rc) + return rc; + + rc = zl3073x_read_custom_config_ver(zldev, &cfg_ver); + if (rc) + return rc; + + /* No custom config version */ + if (cfg_ver == U32_MAX) + return 0; + + snprintf(buf, sizeof(buf), "%lu.%lu.%lu.%lu", + FIELD_GET(GENMASK(31, 24), cfg_ver), + FIELD_GET(GENMASK(23, 16), cfg_ver), + FIELD_GET(GENMASK(15, 8), cfg_ver), + FIELD_GET(GENMASK(7, 0), cfg_ver)); + + return devlink_info_version_running_put(req, "cfg.custom_ver", buf); +} + +static const struct devlink_ops zl3073x_devlink_ops = { + .info_get = zl3073x_devlink_info_get, +}; + +static void zl3073x_devlink_free(void *ptr) +{ + devlink_free(ptr); +} + /** * zl3073x_devm_alloc - allocates zl3073x device structure * @dev: pointer to device structure @@ -124,12 +204,18 @@ static const struct regmap_config zl3073x_regmap_config = { struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev) { struct zl3073x_dev *zldev; + struct devlink *devlink; int rc; - zldev = devm_kzalloc(dev, sizeof(*zldev), GFP_KERNEL); - if (!zldev) + devlink = devlink_alloc(&zl3073x_devlink_ops, sizeof(*zldev), dev); + if (!devlink) return ERR_PTR(-ENOMEM); + /* Add devres action to free devlink device */ + if (devm_add_action_or_reset(dev, zl3073x_devlink_free, devlink)) + return ERR_PTR(-ENOMEM); + + zldev = devlink_priv(devlink); zldev->dev = dev; /* We have to initialize regmap mutex here because during @@ -158,6 +244,11 @@ void zl3073x_dev_init_regmap_config(struct regmap_config *regmap_cfg) } EXPORT_SYMBOL_NS_GPL(zl3073x_dev_init_regmap_config, "ZL3073X"); +static void zl3073x_devlink_unregister(void *ptr) +{ + devlink_unregister(ptr); +} + /** * zl3073x_dev_probe - initialize zl3073x device * @zldev: pointer to zl3073x device @@ -171,6 +262,7 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev, const struct zl3073x_chip_info *chip_info) { u16 id, revision, fw_ver; + struct devlink *devlink; u32 cfg_ver; int i, rc; @@ -209,6 +301,16 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev, FIELD_GET(GENMASK(15, 8), cfg_ver), FIELD_GET(GENMASK(7, 0), cfg_ver)); + /* Register the device as devlink device */ + devlink = priv_to_devlink(zldev); + devlink_register(devlink); + + /* Add devres action to unregister devlink device */ + rc = devm_add_action_or_reset(zldev->dev, zl3073x_devlink_unregister, + devlink); + if (rc) + return rc; + return 0; } EXPORT_SYMBOL_NS_GPL(zl3073x_dev_probe, "ZL3073X"); From patchwork Wed Apr 16 16:21:41 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Vecera X-Patchwork-Id: 14054211 X-Patchwork-Delegate: kuba@kernel.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 22ECF212B13 for ; Wed, 16 Apr 2025 16:22:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820548; cv=none; b=bfUQHXtFEvYpvRw1kItSCe52VI56i5j10fdMHojKo1QuBIjlM2phvlvaifCHLlvT257J8+SKlGf+eMq/iwwA3oh9lRonK8WChr+Bztf+gxPI4cj/V90yWe/o9YhfZX5BglQVXKn4X52hzxEZz/kDzrWS8dHXt4+p9qvrH4Lm3j8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820548; c=relaxed/simple; bh=AlVk1jARPDtF+JXxxt8g+SSWreLxNZwTAeaiMpuL/DA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EjHm2mXDCLHv82VSolHAowCGE8hxkiJbu//EYU852udDmrmaSmLzVXZqi00Gor9uQGCPNXSzVw1XjeTIztjcZc8TBTyhcDvt0VnG2q1OzYQNBKJhojyPGotAdHljyFTJdQ/83KldAiqUA2sACy59mif3N+JmMnl8J4MRl+sKrXA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=LyiER6c7; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="LyiER6c7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1744820544; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=QZOMbzNzCnYqOD/Fg32EUBdQRRFhbTfULTEXRMpBSck=; b=LyiER6c7RKJbg11ZfFk9Jo3th+x4/kMjW719ZUdcFuL10aIEX8DZsv+RNdTmDyqRnxNR3Y wHEzyJfgALpVKxhQ+XN32vaAWNTl6nCIFjaDB8fzFymCOUxHm6faaDGjP8idsgX+pe9X4n ZFns7jvZVoDW8RPp+uXjt5jkysMaw6Q= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-507-0oA8FA39NWii0mJVFvkF1w-1; Wed, 16 Apr 2025 12:22:20 -0400 X-MC-Unique: 0oA8FA39NWii0mJVFvkF1w-1 X-Mimecast-MFC-AGG-ID: 0oA8FA39NWii0mJVFvkF1w_1744820538 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 4C32219560A7; Wed, 16 Apr 2025 16:22:18 +0000 (UTC) Received: from p16v.luc.cera.cz (unknown [10.44.33.32]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7DBF71801765; Wed, 16 Apr 2025 16:22:13 +0000 (UTC) From: Ivan Vecera To: netdev@vger.kernel.org Cc: Vadim Fedorenko , Arkadiusz Kubalewski , Jiri Pirko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Prathosh Satish , Lee Jones , Kees Cook , Andy Shevchenko , Andrew Morton , Michal Schmidt , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v3 net-next 5/8] mfd: zl3073x: Add functions to work with register mailboxes Date: Wed, 16 Apr 2025 18:21:41 +0200 Message-ID: <20250416162144.670760-6-ivecera@redhat.com> In-Reply-To: <20250416162144.670760-1-ivecera@redhat.com> References: <20250416162144.670760-1-ivecera@redhat.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Patchwork-Delegate: kuba@kernel.org Registers present in page 10 and higher are called mailbox type registers. Each page represents a mailbox and is used to read and write configuration of particular object (dpll, output, reference & synth). The mailbox page contains mask register that is used to select an index of requested object to work with and semaphore register to indicate what operation is requested. The rest of registers in the particular register page are latch registers that are filled by the firmware during read operation or by the driver prior write operation. For read operation the driver... 1) ... updates the mailbox mask register with index of particular object 2) ... sets the mailbox semaphore register read bit 3) ... waits for the semaphore register read bit to be cleared by FW 4) ... reads the configuration from latch registers For write operation the driver... 1) ... writes the requested configuration to latch registers 2) ... sets the mailbox mask register for the DPLL to be updated 3) ... sets the mailbox semaphore register bit for the write operation 4) ... waits for the semaphore register bit to be cleared by FW Add functions to read and write mailboxes for all supported object types. All these functions as well as functions accessing mailbox latch registers (zl3073x_mb_* functions) have to be called with zl3073x_dev->mailbox_lock held and a caller is responsible to take this lock. Signed-off-by: Ivan Vecera v1->v3: * dropped ZL3073X_MB_OP macro usage --- drivers/mfd/zl3073x-core.c | 232 +++++++++++++++++++++++ include/linux/mfd/zl3073x.h | 12 ++ include/linux/mfd/zl3073x_regs.h | 304 +++++++++++++++++++++++++++++++ 3 files changed, 548 insertions(+) diff --git a/drivers/mfd/zl3073x-core.c b/drivers/mfd/zl3073x-core.c index 8a15237e0f731..3d18786c769d2 100644 --- a/drivers/mfd/zl3073x-core.c +++ b/drivers/mfd/zl3073x-core.c @@ -115,6 +115,238 @@ static const struct regmap_config zl3073x_regmap_config = { .volatile_reg = zl3073x_is_volatile_reg, }; +/** + * zl3073x_mb_dpll_read - read given DPLL configuration to mailbox + * @zldev: pointer to device structure + * @index: DPLL index + * + * Reads configuration of given DPLL into DPLL mailbox. + * + * Context: Process context. Expects zldev->regmap_lock to be held by caller. + * Return: 0 on success, <0 on error + */ +int zl3073x_mb_dpll_read(struct zl3073x_dev *zldev, u8 index) +{ + int rc; + + /* Select requested index in mask register */ + rc = zl3073x_mb_write_dpll_mb_mask(zldev, BIT(index)); + if (rc) + return rc; + + /* Perform read operation */ + rc = zl3073x_mb_write_dpll_mb_sem(zldev, ZL_DPLL_MB_SEM_RD); + if (rc) + return rc; + + /* Wait for the command to actually finish */ + return zl3073x_mb_poll_dpll_mb_sem(zldev, ZL_DPLL_MB_SEM_RD); +} +EXPORT_SYMBOL_GPL(zl3073x_mb_dpll_read); + +/** + * zl3073x_mb_dpll_write - write given DPLL configuration from mailbox + * @zldev: pointer to device structure + * @index: DPLL index + * + * Writes (commits) configuration of given DPLL from DPLL mailbox. + * + * Context: Process context. Expects zldev->regmap_lock to be held by caller. + * Return: 0 on success, <0 on error + */ +int zl3073x_mb_dpll_write(struct zl3073x_dev *zldev, u8 index) +{ + int rc; + + /* Select requested index in mask register */ + rc = zl3073x_mb_write_dpll_mb_mask(zldev, BIT(index)); + if (rc) + return rc; + + /* Perform read operation */ + rc = zl3073x_mb_write_dpll_mb_sem(zldev, ZL_DPLL_MB_SEM_WR); + if (rc) + return rc; + + /* Wait for the command to actually finish */ + return zl3073x_mb_poll_dpll_mb_sem(zldev, ZL_DPLL_MB_SEM_WR); +} +EXPORT_SYMBOL_GPL(zl3073x_mb_dpll_write); + +/** + * zl3073x_mb_output_read - read given output configuration to mailbox + * @zldev: pointer to device structure + * @index: output index + * + * Reads configuration of given output into output mailbox. + * + * Context: Process context. Expects zldev->regmap_lock to be held by caller. + * Return: 0 on success, <0 on error + */ +int zl3073x_mb_output_read(struct zl3073x_dev *zldev, u8 index) +{ + int rc; + + /* Select requested index in mask register */ + rc = zl3073x_mb_write_output_mb_mask(zldev, BIT(index)); + if (rc) + return rc; + + /* Perform read operation */ + rc = zl3073x_mb_write_output_mb_sem(zldev, ZL_OUTPUT_MB_SEM_RD); + if (rc) + return rc; + + /* Wait for the command to actually finish */ + return zl3073x_mb_poll_output_mb_sem(zldev, ZL_OUTPUT_MB_SEM_RD); +} +EXPORT_SYMBOL_GPL(zl3073x_mb_output_read); + +/** + * zl3073x_mb_output_write - write given output configuration from mailbox + * @zldev: pointer to device structure + * @index: output index + * + * Writes (commits) configuration of given output from output mailbox. + * + * Context: Process context. Expects zldev->regmap_lock to be held by caller. + * Return: 0 on success, <0 on error + */ +int zl3073x_mb_output_write(struct zl3073x_dev *zldev, u8 index) +{ + int rc; + + /* Select requested index in mask register */ + rc = zl3073x_mb_write_output_mb_mask(zldev, BIT(index)); + if (rc) + return rc; + + /* Perform read operation */ + rc = zl3073x_mb_write_output_mb_sem(zldev, ZL_OUTPUT_MB_SEM_WR); + if (rc) + return rc; + + /* Wait for the command to actually finish */ + return zl3073x_mb_poll_output_mb_sem(zldev, ZL_OUTPUT_MB_SEM_WR); +} +EXPORT_SYMBOL_GPL(zl3073x_mb_output_write); + +/** + * zl3073x_mb_ref_read - read given reference configuration to mailbox + * @zldev: pointer to device structure + * @index: reference index + * + * Reads configuration of given reference into ref mailbox. + * + * Context: Process context. Expects zldev->regmap_lock to be held by caller. + * Return: 0 on success, <0 on error + */ +int zl3073x_mb_ref_read(struct zl3073x_dev *zldev, u8 index) +{ + int rc; + + /* Select requested index in mask register */ + rc = zl3073x_mb_write_ref_mb_mask(zldev, BIT(index)); + if (rc) + return rc; + + /* Perform read operation */ + rc = zl3073x_mb_write_ref_mb_sem(zldev, ZL_REF_MB_SEM_RD); + if (rc) + return rc; + + /* Wait for the command to actually finish */ + return zl3073x_mb_poll_ref_mb_sem(zldev, ZL_REF_MB_SEM_RD); +} +EXPORT_SYMBOL_GPL(zl3073x_mb_ref_read); + +/** + * zl3073x_mb_ref_write - write given reference configuration from mailbox + * @zldev: pointer to device structure + * @index: reference index + * + * Writes (commits) configuration of given reference from ref mailbox. + * + * Context: Process context. Expects zldev->regmap_lock to be held by caller. + * Return: 0 on success, <0 on error + */ +int zl3073x_mb_ref_write(struct zl3073x_dev *zldev, u8 index) +{ + int rc; + + /* Select requested index in mask register */ + rc = zl3073x_mb_write_ref_mb_mask(zldev, BIT(index)); + if (rc) + return rc; + + /* Perform read operation */ + rc = zl3073x_mb_write_ref_mb_sem(zldev, ZL_REF_MB_SEM_WR); + if (rc) + return rc; + + /* Wait for the command to actually finish */ + return zl3073x_mb_poll_ref_mb_sem(zldev, ZL_REF_MB_SEM_WR); +} +EXPORT_SYMBOL_GPL(zl3073x_mb_ref_write); + +/** + * zl3073x_mb_synth_read - read given synth configuration to mailbox + * @zldev: pointer to device structure + * @index: synth index + * + * Reads configuration of given synth into synth mailbox. + * + * Context: Process context. Expects zldev->regmap_lock to be held by caller. + * Return: 0 on success, <0 on error + */ +int zl3073x_mb_synth_read(struct zl3073x_dev *zldev, u8 index) +{ + int rc; + + /* Select requested index in mask register */ + rc = zl3073x_mb_write_synth_mb_mask(zldev, BIT(index)); + if (rc) + return rc; + + /* Perform read operation */ + rc = zl3073x_mb_write_synth_mb_sem(zldev, ZL_SYNTH_MB_SEM_RD); + if (rc) + return rc; + + /* Wait for the command to actually finish */ + return zl3073x_mb_poll_synth_mb_sem(zldev, ZL_SYNTH_MB_SEM_RD); +} +EXPORT_SYMBOL_GPL(zl3073x_mb_synth_read); + +/** + * zl3073x_mb_synth_write - write given synth configuration from mailbox + * @zldev: pointer to device structure + * @index: synth index + * + * Writes (commits) configuration of given synth from synth mailbox. + * + * Context: Process context. Expects zldev->regmap_lock to be held by caller. + * Return: 0 on success, <0 on error + */ +int zl3073x_mb_synth_write(struct zl3073x_dev *zldev, u8 index) +{ + int rc; + + /* Select requested index in mask register */ + rc = zl3073x_mb_write_synth_mb_mask(zldev, BIT(index)); + if (rc) + return rc; + + /* Perform read operation */ + rc = zl3073x_mb_write_synth_mb_sem(zldev, ZL_SYNTH_MB_SEM_WR); + if (rc) + return rc; + + /* Wait for the command to actually finish */ + return zl3073x_mb_poll_synth_mb_sem(zldev, ZL_SYNTH_MB_SEM_WR); +} +EXPORT_SYMBOL_GPL(zl3073x_mb_synth_write); + /** * zl3073x_devlink_info_get - Devlink device info callback * @devlink: devlink structure pointer diff --git a/include/linux/mfd/zl3073x.h b/include/linux/mfd/zl3073x.h index b68481dcf77a5..53813a8c39660 100644 --- a/include/linux/mfd/zl3073x.h +++ b/include/linux/mfd/zl3073x.h @@ -47,4 +47,16 @@ static inline void zl3073x_mailbox_unlock(struct zl3073x_dev *zldev) DEFINE_GUARD(zl3073x_mailbox, struct zl3073x_dev *, zl3073x_mailbox_lock(_T), zl3073x_mailbox_unlock(_T)); +/* + * Mailbox operations + */ +int zl3073x_mb_dpll_read(struct zl3073x_dev *zldev, u8 index); +int zl3073x_mb_dpll_write(struct zl3073x_dev *zldev, u8 index); +int zl3073x_mb_output_read(struct zl3073x_dev *zldev, u8 index); +int zl3073x_mb_output_write(struct zl3073x_dev *zldev, u8 index); +int zl3073x_mb_ref_read(struct zl3073x_dev *zldev, u8 index); +int zl3073x_mb_ref_write(struct zl3073x_dev *zldev, u8 index); +int zl3073x_mb_synth_read(struct zl3073x_dev *zldev, u8 index); +int zl3073x_mb_synth_write(struct zl3073x_dev *zldev, u8 index); + #endif /* __LINUX_MFD_ZL3073X_H */ diff --git a/include/linux/mfd/zl3073x_regs.h b/include/linux/mfd/zl3073x_regs.h index 453a5da8ac63f..d155650349c97 100644 --- a/include/linux/mfd/zl3073x_regs.h +++ b/include/linux/mfd/zl3073x_regs.h @@ -15,6 +15,10 @@ #define ZL_PAGE_SIZE 0x80 #define ZL_REG_ADDR(_pg, _off) (ZL_RANGE_OFF + (_pg) * ZL_PAGE_SIZE + (_off)) +/* Register polling sleep & timeout */ +#define ZL_POLL_SLEEP_US 10 +#define ZL_POLL_TIMEOUT_US 2000000 + /************************** * Register Page 0, General **************************/ @@ -102,4 +106,304 @@ zl3073x_read_custom_config_ver(struct zl3073x_dev *zldev, u32 *value) return rc; } +/******************************* + * Register Page 10, Ref Mailbox + *******************************/ + +/* + * Register 'ref_mb_mask' + * Page: 10, Offset: 0x02, Size: 16 bits + */ +#define ZL_REG_REF_MB_MASK ZL_REG_ADDR(10, 0x02) + +static inline __maybe_unused int +zl3073x_mb_read_ref_mb_mask(struct zl3073x_dev *zldev, u16 *value) +{ + __be16 temp; + int rc; + + lockdep_assert_held(&zldev->mailbox_lock); + rc = regmap_bulk_read(zldev->regmap, ZL_REG_REF_MB_MASK, &temp, + sizeof(temp)); + if (rc) + return rc; + + *value = be16_to_cpu(temp); + return rc; +} + +static inline __maybe_unused int +zl3073x_mb_write_ref_mb_mask(struct zl3073x_dev *zldev, u16 value) +{ + __be16 temp; + + lockdep_assert_held(&zldev->mailbox_lock); + temp = cpu_to_be16(value); + return regmap_bulk_write(zldev->regmap, ZL_REG_REF_MB_MASK, &temp, + sizeof(temp)); +} + +/* + * Register 'ref_mb_sem' + * Page: 10, Offset: 0x04, Size: 8 bits + */ +#define ZL_REG_REF_MB_SEM ZL_REG_ADDR(10, 0x04) +#define ZL_REF_MB_SEM_WR BIT(0) +#define ZL_REF_MB_SEM_RD BIT(1) + +static inline __maybe_unused int +zl3073x_mb_read_ref_mb_sem(struct zl3073x_dev *zldev, u8 *value) +{ + unsigned int v; + int rc; + + lockdep_assert_held(&zldev->mailbox_lock); + rc = regmap_read(zldev->regmap, ZL_REG_REF_MB_SEM, &v); + *value = v; + return rc; +} + +static inline __maybe_unused int +zl3073x_mb_write_ref_mb_sem(struct zl3073x_dev *zldev, u8 value) +{ + lockdep_assert_held(&zldev->mailbox_lock); + return regmap_write(zldev->regmap, ZL_REG_REF_MB_SEM, value); +} + +static inline __maybe_unused int +zl3073x_mb_poll_ref_mb_sem(struct zl3073x_dev *zldev, u8 bitmask) +{ + unsigned int v; + + lockdep_assert_held(&zldev->mailbox_lock); + return regmap_read_poll_timeout(zldev->regmap, ZL_REG_REF_MB_SEM, v, + !(v & bitmask), ZL_POLL_SLEEP_US, + ZL_POLL_TIMEOUT_US); +} + +/******************************** + * Register Page 12, DPLL Mailbox + ********************************/ + +/* + * Register 'dpll_mb_mask' + * Page: 12, Offset: 0x02, Size: 16 bits + */ +#define ZL_REG_DPLL_MB_MASK ZL_REG_ADDR(12, 0x02) + +static inline __maybe_unused int +zl3073x_mb_read_dpll_mb_mask(struct zl3073x_dev *zldev, u16 *value) +{ + __be16 temp; + int rc; + + lockdep_assert_held(&zldev->mailbox_lock); + rc = regmap_bulk_read(zldev->regmap, ZL_REG_DPLL_MB_MASK, &temp, + sizeof(temp)); + if (rc) + return rc; + + *value = be16_to_cpu(temp); + return rc; +} + +static inline __maybe_unused int +zl3073x_mb_write_dpll_mb_mask(struct zl3073x_dev *zldev, u16 value) +{ + __be16 temp; + + lockdep_assert_held(&zldev->mailbox_lock); + temp = cpu_to_be16(value); + return regmap_bulk_write(zldev->regmap, ZL_REG_DPLL_MB_MASK, &temp, + sizeof(temp)); +} + +/* + * Register 'dpll_mb_sem' + * Page: 12, Offset: 0x04, Size: 8 bits + */ +#define ZL_REG_DPLL_MB_SEM ZL_REG_ADDR(12, 0x04) +#define ZL_DPLL_MB_SEM_WR BIT(0) +#define ZL_DPLL_MB_SEM_RD BIT(1) + +static inline __maybe_unused int +zl3073x_mb_read_dpll_mb_sem(struct zl3073x_dev *zldev, u8 *value) +{ + unsigned int v; + int rc; + + lockdep_assert_held(&zldev->mailbox_lock); + rc = regmap_read(zldev->regmap, ZL_REG_DPLL_MB_SEM, &v); + *value = v; + return rc; +} + +static inline __maybe_unused int +zl3073x_mb_write_dpll_mb_sem(struct zl3073x_dev *zldev, u8 value) +{ + lockdep_assert_held(&zldev->mailbox_lock); + return regmap_write(zldev->regmap, ZL_REG_DPLL_MB_SEM, value); +} + +static inline __maybe_unused int +zl3073x_mb_poll_dpll_mb_sem(struct zl3073x_dev *zldev, u8 bitmask) +{ + unsigned int v; + + lockdep_assert_held(&zldev->mailbox_lock); + return regmap_read_poll_timeout(zldev->regmap, ZL_REG_DPLL_MB_SEM, v, + !(v & bitmask), ZL_POLL_SLEEP_US, + ZL_POLL_TIMEOUT_US); +} + +/********************************* + * Register Page 13, Synth Mailbox + *********************************/ + +/* + * Register 'synth_mb_mask' + * Page: 13, Offset: 0x02, Size: 16 bits + */ +#define ZL_REG_SYNTH_MB_MASK ZL_REG_ADDR(13, 0x02) + +static inline __maybe_unused int +zl3073x_mb_read_synth_mb_mask(struct zl3073x_dev *zldev, u16 *value) +{ + __be16 temp; + int rc; + + lockdep_assert_held(&zldev->mailbox_lock); + rc = regmap_bulk_read(zldev->regmap, ZL_REG_SYNTH_MB_MASK, &temp, + sizeof(temp)); + if (rc) + return rc; + + *value = be16_to_cpu(temp); + return rc; +} + +static inline __maybe_unused int +zl3073x_mb_write_synth_mb_mask(struct zl3073x_dev *zldev, u16 value) +{ + __be16 temp; + + lockdep_assert_held(&zldev->mailbox_lock); + temp = cpu_to_be16(value); + return regmap_bulk_write(zldev->regmap, ZL_REG_SYNTH_MB_MASK, &temp, + sizeof(temp)); +} + +/* + * Register 'synth_mb_sem' + * Page: 13, Offset: 0x04, Size: 8 bits + */ +#define ZL_REG_SYNTH_MB_SEM ZL_REG_ADDR(13, 0x04) +#define ZL_SYNTH_MB_SEM_WR BIT(0) +#define ZL_SYNTH_MB_SEM_RD BIT(1) + +static inline __maybe_unused int +zl3073x_mb_read_synth_mb_sem(struct zl3073x_dev *zldev, u8 *value) +{ + unsigned int v; + int rc; + + lockdep_assert_held(&zldev->mailbox_lock); + rc = regmap_read(zldev->regmap, ZL_REG_SYNTH_MB_SEM, &v); + *value = v; + return rc; +} + +static inline __maybe_unused int +zl3073x_mb_write_synth_mb_sem(struct zl3073x_dev *zldev, u8 value) +{ + lockdep_assert_held(&zldev->mailbox_lock); + return regmap_write(zldev->regmap, ZL_REG_SYNTH_MB_SEM, value); +} + +static inline __maybe_unused int +zl3073x_mb_poll_synth_mb_sem(struct zl3073x_dev *zldev, u8 bitmask) +{ + unsigned int v; + + lockdep_assert_held(&zldev->mailbox_lock); + return regmap_read_poll_timeout(zldev->regmap, ZL_REG_SYNTH_MB_SEM, v, + !(v & bitmask), ZL_POLL_SLEEP_US, + ZL_POLL_TIMEOUT_US); +} + +/********************************** + * Register Page 14, Output Mailbox + **********************************/ + +/* + * Register 'output_mb_mask' + * Page: 14, Offset: 0x02, Size: 16 bits + */ +#define ZL_REG_OUTPUT_MB_MASK ZL_REG_ADDR(14, 0x02) + +static inline __maybe_unused int +zl3073x_mb_read_output_mb_mask(struct zl3073x_dev *zldev, u16 *value) +{ + __be16 temp; + int rc; + + lockdep_assert_held(&zldev->mailbox_lock); + rc = regmap_bulk_read(zldev->regmap, ZL_REG_OUTPUT_MB_MASK, &temp, + sizeof(temp)); + if (rc) + return rc; + + *value = be16_to_cpu(temp); + return rc; +} + +static inline __maybe_unused int +zl3073x_mb_write_output_mb_mask(struct zl3073x_dev *zldev, u16 value) +{ + __be16 temp; + + lockdep_assert_held(&zldev->mailbox_lock); + temp = cpu_to_be16(value); + return regmap_bulk_write(zldev->regmap, ZL_REG_OUTPUT_MB_MASK, &temp, + sizeof(temp)); +} + +/* + * Register 'output_mb_sem' + * Page: 14, Offset: 0x04, Size: 8 bits + */ +#define ZL_REG_OUTPUT_MB_SEM ZL_REG_ADDR(14, 0x04) +#define ZL_OUTPUT_MB_SEM_WR BIT(0) +#define ZL_OUTPUT_MB_SEM_RD BIT(1) + +static inline __maybe_unused int +zl3073x_mb_read_output_mb_sem(struct zl3073x_dev *zldev, u8 *value) +{ + unsigned int v; + int rc; + + lockdep_assert_held(&zldev->mailbox_lock); + rc = regmap_read(zldev->regmap, ZL_REG_OUTPUT_MB_SEM, &v); + *value = v; + return rc; +} + +static inline __maybe_unused int +zl3073x_mb_write_output_mb_sem(struct zl3073x_dev *zldev, u8 value) +{ + lockdep_assert_held(&zldev->mailbox_lock); + return regmap_write(zldev->regmap, ZL_REG_OUTPUT_MB_SEM, value); +} + +static inline __maybe_unused int +zl3073x_mb_poll_output_mb_sem(struct zl3073x_dev *zldev, u8 bitmask) +{ + unsigned int v; + + lockdep_assert_held(&zldev->mailbox_lock); + return regmap_read_poll_timeout(zldev->regmap, ZL_REG_OUTPUT_MB_SEM, v, + !(v & bitmask), ZL_POLL_SLEEP_US, + ZL_POLL_TIMEOUT_US); +} + #endif /* __LINUX_MFD_ZL3073X_REGS_H */ From patchwork Wed Apr 16 16:21:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Vecera X-Patchwork-Id: 14054212 X-Patchwork-Delegate: kuba@kernel.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E82AC215F4C for ; Wed, 16 Apr 2025 16:22:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820553; cv=none; b=ejvn/flBMkZstMHBNcD7h5D3by9zoP7xeO1dgP5gfIxnOHlQjs2KvXc4URte/yv8GUa6Dl+Ee+D9Cq9iXXGiqNkcu2sBOKk7tQgchzSU9aS+jr5FRR8yrxv1K4fRAwdnRUNfTtR1XIXqXHN8ZlDoEXLX4s/psz+paEhHmvEppQs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820553; c=relaxed/simple; bh=0dqG/BGHObDxpCDroZlU6KQBh5h1H5phftiCDFOZ4Dk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tkYoF4eJWWc28xvUHSf5plZx/kt4z63mBtjI5yPASOPwj2TO1QM4dmCCeZiEYeGDOnwN88zfQKz9XOhDjRV5LWWIiQT/bDD7I+s+/t256YFy6z3iQzpJRTf1BrPKe/hD/WqkQb7S/65N43Zmu8d7DO6/gFywR32/1537a/JwQ70= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=clfROOy5; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="clfROOy5" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1744820550; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=aiB1aBtR1yuJyWpVsoB3DbcH3jm+uu0Drkre1B2Skjs=; b=clfROOy5qetGxZxxEpfxK3P/hxr9o20CWcfSPVeh8ymwPg1EgxbSNodRQhTMpPS/k5dp1a B+NwbCWPfnOIRUGGRStKmNUhac+C1V0UNJI/GNO0A2kavuZse+zhD2hs5t+cGxiSGWUeFB sIkMmvEqwllysctfbg9o79rvICmfcpw= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-695-vPUb5T6BOfm-PsqSL67Ulg-1; Wed, 16 Apr 2025 12:22:25 -0400 X-MC-Unique: vPUb5T6BOfm-PsqSL67Ulg-1 X-Mimecast-MFC-AGG-ID: vPUb5T6BOfm-PsqSL67Ulg_1744820543 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6C7E6195604F; Wed, 16 Apr 2025 16:22:23 +0000 (UTC) Received: from p16v.luc.cera.cz (unknown [10.44.33.32]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id BADCC180045B; Wed, 16 Apr 2025 16:22:18 +0000 (UTC) From: Ivan Vecera To: netdev@vger.kernel.org Cc: Vadim Fedorenko , Arkadiusz Kubalewski , Jiri Pirko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Prathosh Satish , Lee Jones , Kees Cook , Andy Shevchenko , Andrew Morton , Michal Schmidt , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v3 net-next 6/8] mfd: zl3073x: Add clock_id field Date: Wed, 16 Apr 2025 18:21:42 +0200 Message-ID: <20250416162144.670760-7-ivecera@redhat.com> In-Reply-To: <20250416162144.670760-1-ivecera@redhat.com> References: <20250416162144.670760-1-ivecera@redhat.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Patchwork-Delegate: kuba@kernel.org Add .clock_id to zl3073x_dev structure that will be used by later commits introducing DPLL driver. The clock ID is necessary for DPLL device registration. To generate such ID use chip ID read during device initialization for this. For the case where are multiple zl3073x based chips the chip ID is shifted and lower bits are filled by an unique value. For I2C case it is I2C device address and for SPI case it is chip-select value. Signed-off-by: Ivan Vecera --- drivers/mfd/zl3073x-core.c | 6 +++++- drivers/mfd/zl3073x-i2c.c | 4 +++- drivers/mfd/zl3073x-spi.c | 4 +++- drivers/mfd/zl3073x.h | 2 +- include/linux/mfd/zl3073x.h | 2 ++ 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/zl3073x-core.c b/drivers/mfd/zl3073x-core.c index 3d18786c769d2..5a0e2bb1a969f 100644 --- a/drivers/mfd/zl3073x-core.c +++ b/drivers/mfd/zl3073x-core.c @@ -485,13 +485,14 @@ static void zl3073x_devlink_unregister(void *ptr) * zl3073x_dev_probe - initialize zl3073x device * @zldev: pointer to zl3073x device * @chip_info: chip info based on compatible + * @dev_id: device ID to be used as part of clock ID * * Common initialization of zl3073x device structure. * * Returns: 0 on success, <0 on error */ int zl3073x_dev_probe(struct zl3073x_dev *zldev, - const struct zl3073x_chip_info *chip_info) + const struct zl3073x_chip_info *chip_info, u8 dev_id) { u16 id, revision, fw_ver; struct devlink *devlink; @@ -533,6 +534,9 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev, FIELD_GET(GENMASK(15, 8), cfg_ver), FIELD_GET(GENMASK(7, 0), cfg_ver)); + /* Use chip ID and given dev ID as clock ID */ + zldev->clock_id = ((u64)id << 8) | dev_id; + /* Register the device as devlink device */ devlink = priv_to_devlink(zldev); devlink_register(devlink); diff --git a/drivers/mfd/zl3073x-i2c.c b/drivers/mfd/zl3073x-i2c.c index 76bc9a0463180..ae0ad6b7b0129 100644 --- a/drivers/mfd/zl3073x-i2c.c +++ b/drivers/mfd/zl3073x-i2c.c @@ -29,7 +29,9 @@ static int zl3073x_i2c_probe(struct i2c_client *client) return PTR_ERR(zldev->regmap); } - return zl3073x_dev_probe(zldev, i2c_get_match_data(client)); + /* Initialize device and use I2C address as dev ID */ + return zl3073x_dev_probe(zldev, i2c_get_match_data(client), + client->addr); } static const struct i2c_device_id zl3073x_i2c_id[] = { diff --git a/drivers/mfd/zl3073x-spi.c b/drivers/mfd/zl3073x-spi.c index d0fc2d2221c0d..6e6ec88b40d72 100644 --- a/drivers/mfd/zl3073x-spi.c +++ b/drivers/mfd/zl3073x-spi.c @@ -29,7 +29,9 @@ static int zl3073x_spi_probe(struct spi_device *spi) return PTR_ERR(zldev->regmap); } - return zl3073x_dev_probe(zldev, spi_get_device_match_data(spi)); + /* Initialize device and use SPI chip select value as dev ID */ + return zl3073x_dev_probe(zldev, spi_get_device_match_data(spi), + spi_get_chipselect(spi, 0)); } static const struct spi_device_id zl3073x_spi_id[] = { diff --git a/drivers/mfd/zl3073x.h b/drivers/mfd/zl3073x.h index 3a2fea61cf579..abd1ab9a56ded 100644 --- a/drivers/mfd/zl3073x.h +++ b/drivers/mfd/zl3073x.h @@ -26,6 +26,6 @@ extern const struct zl3073x_chip_info zl3073x_chip_info[]; struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev); void zl3073x_dev_init_regmap_config(struct regmap_config *regmap_cfg); int zl3073x_dev_probe(struct zl3073x_dev *zldev, - const struct zl3073x_chip_info *chip_info); + const struct zl3073x_chip_info *chip_info, u8 dev_id); #endif /* __ZL3073X_CORE_H */ diff --git a/include/linux/mfd/zl3073x.h b/include/linux/mfd/zl3073x.h index 53813a8c39660..5074f64a70137 100644 --- a/include/linux/mfd/zl3073x.h +++ b/include/linux/mfd/zl3073x.h @@ -13,11 +13,13 @@ struct regmap; * @dev: pointer to device * @regmap: regmap to access device registers * @mailbox_lock: mutex protecting an access to mailbox registers + * @clock_id: clock id of the device */ struct zl3073x_dev { struct device *dev; struct regmap *regmap; struct mutex mailbox_lock; + u64 clock_id; }; /** From patchwork Wed Apr 16 16:21:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Vecera X-Patchwork-Id: 14054224 X-Patchwork-Delegate: kuba@kernel.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0C54D21129D for ; Wed, 16 Apr 2025 16:22:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820559; cv=none; b=F4Ok59td+Lk9mNoZBsGfb3jhMsu2BuP6KUTm4UL59+jrKa994BC9h2fhLYUimULJkgZfhkV6NwcJ9tqZoGr9Y3wc1IJSM1Yi1+v61D0AKMbZwfEXY5oYbQ03bejRaIa+tlBvja9gTqYREM+ZpEzAVI4Nma1zNYL8ukB4exUq62A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820559; c=relaxed/simple; bh=2xHx+yz3yF8J2zXfHdbMO51YcjlDcHVhF/eIBh1KogU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GIvzal4g3iXgYIXbo8yJdUz5GTqI8UdcU8asn+k59jouos52NwF8jDCzVAWmGIA1/daTi784liaV/k9JobvugFvcMsxDtg462Z6Rd9khrOE/uIqJnX4QCBU9+UA3dld3nhNYX2wcUTIJepqvCDU6LinWW78Fj8LpCwnM6f0nE94= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=YIKJboab; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="YIKJboab" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1744820556; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=V0aQVfkk9JI5FdD9Vn4JrLbdLxth97WWpb7cgDFoJ9w=; b=YIKJboabgzvr10E14aICJUd1SIHBT5+4JMWKsCecbLpDFLYXsAEhAsKQ8+EYCXN8m9B3tY 1lYjqj5/vMF33Hbon8BgHX31iUw/7ngbM2h/H4kvMHFAg79rxbnLxIUvHn+WqbL78VSieK dk4Bjdnf02iplBu5cV74wzZwPoVDbD0= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-617-MTJgngZWP1Ghd5-pcDVCpA-1; Wed, 16 Apr 2025 12:22:30 -0400 X-MC-Unique: MTJgngZWP1Ghd5-pcDVCpA-1 X-Mimecast-MFC-AGG-ID: MTJgngZWP1Ghd5-pcDVCpA_1744820548 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8DFB619560A0; Wed, 16 Apr 2025 16:22:28 +0000 (UTC) Received: from p16v.luc.cera.cz (unknown [10.44.33.32]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id BE9481800352; Wed, 16 Apr 2025 16:22:23 +0000 (UTC) From: Ivan Vecera To: netdev@vger.kernel.org Cc: Vadim Fedorenko , Arkadiusz Kubalewski , Jiri Pirko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Prathosh Satish , Lee Jones , Kees Cook , Andy Shevchenko , Andrew Morton , Michal Schmidt , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v3 net-next 7/8] mfd: zl3073x: Fetch invariants during probe Date: Wed, 16 Apr 2025 18:21:43 +0200 Message-ID: <20250416162144.670760-8-ivecera@redhat.com> In-Reply-To: <20250416162144.670760-1-ivecera@redhat.com> References: <20250416162144.670760-1-ivecera@redhat.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Patchwork-Delegate: kuba@kernel.org Several configuration parameters will not be changed in runtime so we can load them during probe to avoid excessive reads from the hardware. These parameters will be frequently read by the DPLL driver from this series and later by PHC/PTP sub-device driver. Read the following parameters from the device during probe and store them for later use: * synthesizers' frequencies and driving DPLL channel * input pins' enablement and type (single-ended or differential) * outputs'associated synths, signal format and enablement Signed-off-by: Ivan Vecera --- v2->v3: * dropped usage of macros for generating helper functions v1->v2: * fixed and added inline documentation --- drivers/mfd/zl3073x-core.c | 237 +++++++++++++++++++++++++++++++ include/linux/mfd/zl3073x.h | 161 +++++++++++++++++++++ include/linux/mfd/zl3073x_regs.h | 184 ++++++++++++++++++++++++ 3 files changed, 582 insertions(+) diff --git a/drivers/mfd/zl3073x-core.c b/drivers/mfd/zl3073x-core.c index 5a0e2bb1a969f..0bd31591245a2 100644 --- a/drivers/mfd/zl3073x-core.c +++ b/drivers/mfd/zl3073x-core.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -481,6 +482,237 @@ static void zl3073x_devlink_unregister(void *ptr) devlink_unregister(ptr); } +/** + * zl3073x_input_state_fetch - get input state + * @zldev: pointer to zl3073x_dev structure + * @index: input pin index to fetch state for + * + * Function fetches information for the given input reference that are + * invariant and stores them for later use. + * + * Return: 0 on success, <0 on error + */ +static int +zl3073x_input_state_fetch(struct zl3073x_dev *zldev, u8 index) +{ + struct zl3073x_input *input; + u8 ref_config; + int rc; + + if (index >= ZL3073X_NUM_INPUTS) + return -EINVAL; + + input = &zldev->input[index]; + + /* If the input is differential then the configuration for N-pin + * reference is ignored and P-pin config is used for both. + */ + if (zl3073x_is_n_pin(index) && + zl3073x_input_is_diff(zldev, index - 1)) { + input->enabled = zl3073x_input_is_enabled(zldev, index - 1); + input->diff = true; + + return 0; + } + + guard(zl3073x_mailbox)(zldev); + + /* Read reference configuration into mailbox */ + rc = zl3073x_mb_ref_read(zldev, index); + if (rc) + return rc; + + /* Read reference config register */ + rc = zl3073x_mb_read_ref_config(zldev, &ref_config); + if (rc) + return rc; + + /* Store info about input reference enablement and if it is + * configured in differential mode or not. + */ + input->enabled = FIELD_GET(ZL_REF_CONFIG_ENABLE, ref_config); + input->diff = FIELD_GET(ZL_REF_CONFIG_DIFF_EN, ref_config); + + dev_dbg(zldev->dev, "INPUT%u is %sabled and configured as %s\n", index, + input->enabled ? "en" : "dis", + input->diff ? "differential" : "single-ended"); + + return rc; +} + +/** + * zl3073x_output_state_fetch - get output state + * @zldev: pointer to zl3073x_dev structure + * @index: output index to fetch state for + * + * Function fetches information for the given output (not output pin) + * that are invariant and stores them for later use. + * + * Return: 0 on success, <0 on error + */ +static int +zl3073x_output_state_fetch(struct zl3073x_dev *zldev, u8 index) +{ + struct zl3073x_output *output; + u8 output_ctrl, output_mode; + int rc; + + if (index >= ZL3073X_NUM_OUTPUTS) + return -EINVAL; + + output = &zldev->output[index]; + + /* Read output control register */ + rc = zl3073x_read_output_ctrl(zldev, index, &output_ctrl); + if (rc) + return rc; + + /* Store info about output enablement and synthesizer the output + * is connected to. + */ + output->enabled = FIELD_GET(ZL_OUTPUT_CTRL_EN, output_ctrl); + output->synth = FIELD_GET(ZL_OUTPUT_CTRL_SYNTH_SEL, output_ctrl); + + dev_dbg(zldev->dev, "OUTPUT%u is %sabled, connected to SYNTH%u\n", + index, output->enabled ? "en" : "dis", output->synth); + + guard(zl3073x_mailbox)(zldev); + + /* Load given output config into mailbox */ + rc = zl3073x_mb_output_read(zldev, index); + if (rc) + return rc; + + /* Read output mode from mailbox */ + rc = zl3073x_mb_read_output_mode(zldev, &output_mode); + if (rc) + return rc; + + /* Extract and store output signal format */ + output->signal_format = FIELD_GET(ZL_OUTPUT_MODE_SIGNAL_FORMAT, + output_mode); + + dev_dbg(zldev->dev, "OUTPUT%u has signal format 0x%02x\n", index, + output->signal_format); + + return rc; +} + +/** + * zl3073x_synth_state_fetch - get synth state + * @zldev: pointer to zl3073x_dev structure + * @index: synth index to fetch state for + * + * Function fetches information for the given synthesizer that are + * invariant and stores them for later use. + * + * Return: 0 on success, <0 on error + */ +static int +zl3073x_synth_state_fetch(struct zl3073x_dev *zldev, u8 index) +{ + u16 base, numerator, denominator; + u8 synth_ctrl; + u32 mult; + int rc; + + /* Read synth control register */ + rc = zl3073x_read_synth_ctrl(zldev, index, &synth_ctrl); + if (rc) + return rc; + + /* Extract and store DPLL channel the synth is driven by */ + zldev->synth[index].dpll = FIELD_GET(ZL_SYNTH_CTRL_DPLL_SEL, + synth_ctrl); + + dev_dbg(zldev->dev, "SYNTH%u is connected to DPLL%u\n", index, + zldev->synth[index].dpll); + + guard(zl3073x_mailbox)(zldev); + + /* Read synth configuration into mailbox */ + rc = zl3073x_mb_synth_read(zldev, index); + if (rc) + return rc; + + /* The output frequency is determined by the following formula: + * base * multiplier * numerator / denominator + * + * Therefore get all this number and calculate the output frequency + */ + rc = zl3073x_mb_read_synth_freq_base(zldev, &base); + if (rc) + return rc; + + rc = zl3073x_mb_read_synth_freq_mult(zldev, &mult); + if (rc) + return rc; + + rc = zl3073x_mb_read_synth_freq_m(zldev, &numerator); + if (rc) + return rc; + + rc = zl3073x_mb_read_synth_freq_n(zldev, &denominator); + if (rc) + return rc; + + /* Check denominator for zero to avoid div by 0 */ + if (!denominator) { + dev_err(zldev->dev, + "Zero divisor for SYNTH%u retrieved from device\n", + index); + return -EINVAL; + } + + /* Compute and store synth frequency */ + zldev->synth[index].freq = mul_u64_u32_div(mul_u32_u32(base, mult), + numerator, denominator); + + dev_dbg(zldev->dev, "SYNTH%u frequency: %llu Hz\n", index, + zldev->synth[index].freq); + + return rc; +} + +static int +zl3073x_dev_state_fetch(struct zl3073x_dev *zldev) +{ + int rc; + u8 i; + + for (i = 0; i < ZL3073X_NUM_INPUTS; i++) { + rc = zl3073x_input_state_fetch(zldev, i); + if (rc) { + dev_err(zldev->dev, + "Failed to fetch input state: %pe\n", + ERR_PTR(rc)); + return rc; + } + } + + for (i = 0; i < ZL3073X_NUM_SYNTHS; i++) { + rc = zl3073x_synth_state_fetch(zldev, i); + if (rc) { + dev_err(zldev->dev, + "Failed to fetch synth state: %pe\n", + ERR_PTR(rc)); + return rc; + } + } + + for (i = 0; i < ZL3073X_NUM_OUTPUTS; i++) { + rc = zl3073x_output_state_fetch(zldev, i); + if (rc) { + dev_err(zldev->dev, + "Failed to fetch output state: %pe\n", + ERR_PTR(rc)); + return rc; + } + } + + return rc; +} + /** * zl3073x_dev_probe - initialize zl3073x device * @zldev: pointer to zl3073x device @@ -537,6 +769,11 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev, /* Use chip ID and given dev ID as clock ID */ zldev->clock_id = ((u64)id << 8) | dev_id; + /* Fetch device state */ + rc = zl3073x_dev_state_fetch(zldev); + if (rc) + return rc; + /* Register the device as devlink device */ devlink = priv_to_devlink(zldev); devlink_register(devlink); diff --git a/include/linux/mfd/zl3073x.h b/include/linux/mfd/zl3073x.h index 5074f64a70137..c77d0815b4dfd 100644 --- a/include/linux/mfd/zl3073x.h +++ b/include/linux/mfd/zl3073x.h @@ -8,18 +8,75 @@ struct device; struct regmap; +/* + * Hardware limits for ZL3073x chip family + */ +#define ZL3073X_NUM_INPUTS 10 +#define ZL3073X_NUM_OUTPUTS 10 +#define ZL3073X_NUM_SYNTHS 5 + +/** + * struct zl3073x_input - input invariant info + * @enabled: input is enabled or disabled + * @diff: true if input is differential + */ +struct zl3073x_input { + bool enabled; + bool diff; +}; + +/** + * struct zl3073x_output - output invariant info + * @enabled: output is enabled or disabled + * @synth: synthesizer the output is connected to + * @signal_format: output signal format + */ +struct zl3073x_output { + bool enabled; + u8 synth; + u8 signal_format; +#define ZL_OUTPUT_SIGNAL_FORMAT_DISABLED 0 +#define ZL_OUTPUT_SIGNAL_FORMAT_LVDS 1 +#define ZL_OUTPUT_SIGNAL_FORMAT_DIFFERENTIAL 2 +#define ZL_OUTPUT_SIGNAL_FORMAT_LOWVCM 3 +#define ZL_OUTPUT_SIGNAL_FORMAT_TWO 4 +#define ZL_OUTPUT_SIGNAL_FORMAT_ONE_P 5 +#define ZL_OUTPUT_SIGNAL_FORMAT_ONE_N 6 +#define ZL_OUTPUT_SIGNAL_FORMAT_TWO_INV 7 +#define ZL_OUTPUT_SIGNAL_FORMAT_TWO_N_DIV 12 +#define ZL_OUTPUT_SIGNAL_FORMAT_TWO_N_DIV_INV 15 +}; + +/** + * struct zl3073x_synth - synthesizer invariant info + * @freq: synthesizer frequency + * @dpll: ID of DPLL the synthesizer is driven by + */ +struct zl3073x_synth { + u64 freq; + u8 dpll; +}; + /** * struct zl3073x_dev - zl3073x device * @dev: pointer to device * @regmap: regmap to access device registers * @mailbox_lock: mutex protecting an access to mailbox registers * @clock_id: clock id of the device + * @input: array of inputs' invariants + * @output: array of outputs' invariants + * @synth: array of synthesizers' invariants */ struct zl3073x_dev { struct device *dev; struct regmap *regmap; struct mutex mailbox_lock; u64 clock_id; + + /* Invariants */ + struct zl3073x_input input[ZL3073X_NUM_INPUTS]; + struct zl3073x_output output[ZL3073X_NUM_OUTPUTS]; + struct zl3073x_synth synth[ZL3073X_NUM_SYNTHS]; }; /** @@ -61,4 +118,108 @@ int zl3073x_mb_ref_write(struct zl3073x_dev *zldev, u8 index); int zl3073x_mb_synth_read(struct zl3073x_dev *zldev, u8 index); int zl3073x_mb_synth_write(struct zl3073x_dev *zldev, u8 index); +static inline +bool zl3073x_is_n_pin(u8 index) +{ + /* P-pins indices are even while N-pins are odd */ + return index & 1; +} + +static inline +bool zl3073x_is_p_pin(u8 index) +{ + return !zl3073x_is_n_pin(index); +} + +/** + * zl3073x_input_is_diff - check if the given input ref is differential + * @zldev: pointer to zl3073x device + * @index: output index + * + * Return: true if input is differential, false if input is single-ended + */ +static inline +bool zl3073x_input_is_diff(struct zl3073x_dev *zldev, u8 index) +{ + return zldev->input[index].diff; +} + +/** + * zl3073x_input_is_enabled - check if the given input ref is enabled + * @zldev: pointer to zl3073x device + * @index: input index + * + * Return: true if input is enabled, false if input is disabled + */ +static inline +bool zl3073x_input_is_enabled(struct zl3073x_dev *zldev, u8 index) +{ + return zldev->input[index].enabled; +} + +/** + * zl3073x_output_is_enabled - check if the given output is enabled + * @zldev: pointer to zl3073x device + * @index: output index + * + * Return: true if output is enabled, false if output is disabled + */ +static inline +u8 zl3073x_output_is_enabled(struct zl3073x_dev *zldev, u8 index) +{ + return zldev->output[index].enabled; +} + +/** + * zl3073x_output_signal_format_get - get output signal format + * @zldev: pointer to zl3073x device + * @index: output index + * + * Return: signal format of given output + */ +static inline +u8 zl3073x_output_signal_format_get(struct zl3073x_dev *zldev, u8 index) +{ + return zldev->output[index].signal_format; +} + +/** + * zl3073x_output_synth_get - get synth connected to given output + * @zldev: pointer to zl3073x device + * @index: output index + * + * Return: index of synth connected to given output. + */ +static inline +u8 zl3073x_output_synth_get(struct zl3073x_dev *zldev, u8 index) +{ + return zldev->output[index].synth; +} + +/** + * zl3073x_synth_dpll_get - get DPLL ID the synth is driven by + * @zldev: pointer to zl3073x device + * @index: synth index + * + * Return: ID of DPLL the given synthetizer is driven by + */ +static inline +u64 zl3073x_synth_dpll_get(struct zl3073x_dev *zldev, u8 index) +{ + return zldev->synth[index].dpll; +} + +/** + * zl3073x_synth_freq_get - get synth current freq + * @zldev: pointer to zl3073x device + * @index: synth index + * + * Return: frequency of given synthetizer + */ +static inline +u64 zl3073x_synth_freq_get(struct zl3073x_dev *zldev, u8 index) +{ + return zldev->synth[index].freq; +} + #endif /* __LINUX_MFD_ZL3073X_H */ diff --git a/include/linux/mfd/zl3073x_regs.h b/include/linux/mfd/zl3073x_regs.h index d155650349c97..ff5b2e6fae9d0 100644 --- a/include/linux/mfd/zl3073x_regs.h +++ b/include/linux/mfd/zl3073x_regs.h @@ -106,6 +106,63 @@ zl3073x_read_custom_config_ver(struct zl3073x_dev *zldev, u32 *value) return rc; } +/*********************************** + * Register Page 9, Synth and Output + ***********************************/ + +/* + * Register array 'synth_ctrl' + * Page: 9, Offset: 0x00, Size: 8 bits, Items: 5, Stride: 1 + */ +#define ZL_REG_SYNTH_CTRL ZL_REG_ADDR(9, 0x00) +#define ZL_REG_SYNTH_CTRL_ITEMS 5 +#define ZL_REG_SYNTH_CTRL_STRIDE 1 +#define ZL_SYNTH_CTRL_EN BIT(0) +#define ZL_SYNTH_CTRL_DPLL_SEL GENMASK(6, 4) + +static inline __maybe_unused int +zl3073x_read_synth_ctrl(struct zl3073x_dev *zldev, unsigned int idx, u8 *value) +{ + unsigned int addr, v; + int rc; + + if (idx >= ZL_REG_SYNTH_CTRL_ITEMS) + return -EINVAL; + + addr = ZL_REG_SYNTH_CTRL + idx * ZL_REG_SYNTH_CTRL_STRIDE; + rc = regmap_read(zldev->regmap, addr, &v); + *value = v; + return rc; +} + +/* + * Register array 'output_ctrl' + * Page: 9, Offset: 0x28, Size: 8 bits, Items: 10, Stride: 1 + */ +#define ZL_REG_OUTPUT_CTRL ZL_REG_ADDR(9, 0x28) +#define ZL_REG_OUTPUT_CTRL_ITEMS 10 +#define ZL_REG_OUTPUT_CTRL_STRIDE 1 +#define ZL_OUTPUT_CTRL_EN BIT(0) +#define ZL_OUTPUT_CTRL_STOP BIT(1) +#define ZL_OUTPUT_CTRL_STOP_HIGH BIT(2) +#define ZL_OUTPUT_CTRL_STOP_HZ BIT(3) +#define ZL_OUTPUT_CTRL_SYNTH_SEL GENMASK(6, 4) + +static inline __maybe_unused int +zl3073x_read_output_ctrl(struct zl3073x_dev *zldev, unsigned int idx, u8 *value) +{ + unsigned int addr, v; + int rc; + + if (idx >= ZL_REG_OUTPUT_CTRL_ITEMS) + return -EINVAL; + + addr = ZL_REG_OUTPUT_CTRL + idx * ZL_REG_OUTPUT_CTRL_STRIDE; + rc = regmap_read(zldev->regmap, addr, &v); + *value = v; + return rc; +} + /******************************* * Register Page 10, Ref Mailbox *******************************/ @@ -181,6 +238,26 @@ zl3073x_mb_poll_ref_mb_sem(struct zl3073x_dev *zldev, u8 bitmask) ZL_POLL_TIMEOUT_US); } +/* + * Register 'ref_config' + * Page: 10, Offset: 0x0d, Size: 8 bits + */ +#define ZL_REG_REF_CONFIG ZL_REG_ADDR(10, 0x0d) +#define ZL_REF_CONFIG_ENABLE BIT(0) +#define ZL_REF_CONFIG_DIFF_EN BIT(2) + +static inline __maybe_unused int +zl3073x_mb_read_ref_config(struct zl3073x_dev *zldev, u8 *value) +{ + unsigned int v; + int rc; + + lockdep_assert_held(&zldev->mailbox_lock); + rc = regmap_read(zldev->regmap, ZL_REG_REF_CONFIG, &v); + *value = v; + return rc; +} + /******************************** * Register Page 12, DPLL Mailbox ********************************/ @@ -331,6 +408,94 @@ zl3073x_mb_poll_synth_mb_sem(struct zl3073x_dev *zldev, u8 bitmask) ZL_POLL_TIMEOUT_US); } +/* + * Register 'synth_freq_base' + * Page: 13, Offset: 0x06, Size: 16 bits + */ +#define ZL_REG_SYNTH_FREQ_BASE ZL_REG_ADDR(13, 0x06) + +static inline __maybe_unused int +zl3073x_mb_read_synth_freq_base(struct zl3073x_dev *zldev, u16 *value) +{ + __be16 temp; + int rc; + + lockdep_assert_held(&zldev->mailbox_lock); + rc = regmap_bulk_read(zldev->regmap, ZL_REG_SYNTH_FREQ_BASE, &temp, + sizeof(temp)); + if (rc) + return rc; + + *value = be16_to_cpu(temp); + return rc; +} + +/* + * Register 'synth_freq_mult' + * Page: 13, Offset: 0x08, Size: 32 bits + */ +#define ZL_REG_SYNTH_FREQ_MULT ZL_REG_ADDR(13, 0x08) + +static inline __maybe_unused int +zl3073x_mb_read_synth_freq_mult(struct zl3073x_dev *zldev, u32 *value) +{ + __be32 temp; + int rc; + + lockdep_assert_held(&zldev->mailbox_lock); + rc = regmap_bulk_read(zldev->regmap, ZL_REG_SYNTH_FREQ_MULT, &temp, + sizeof(temp)); + if (rc) + return rc; + + *value = be32_to_cpu(temp); + return rc; +} + +/* + * Register 'synth_freq_m' + * Page: 13, Offset: 0x0c, Size: 16 bits + */ +#define ZL_REG_SYNTH_FREQ_M ZL_REG_ADDR(13, 0x0c) + +static inline __maybe_unused int +zl3073x_mb_read_synth_freq_m(struct zl3073x_dev *zldev, u16 *value) +{ + __be16 temp; + int rc; + + lockdep_assert_held(&zldev->mailbox_lock); + rc = regmap_bulk_read(zldev->regmap, ZL_REG_SYNTH_FREQ_M, &temp, + sizeof(temp)); + if (rc) + return rc; + + *value = be16_to_cpu(temp); + return rc; +} + +/* + * Register 'synth_freq_n' + * Page: 13, Offset: 0x0e, Size: 16 bits + */ +#define ZL_REG_SYNTH_FREQ_N ZL_REG_ADDR(13, 0x0e) + +static inline __maybe_unused int +zl3073x_mb_read_synth_freq_n(struct zl3073x_dev *zldev, u16 *value) +{ + __be16 temp; + int rc; + + lockdep_assert_held(&zldev->mailbox_lock); + rc = regmap_bulk_read(zldev->regmap, ZL_REG_SYNTH_FREQ_N, &temp, + sizeof(temp)); + if (rc) + return rc; + + *value = be16_to_cpu(temp); + return rc; +} + /********************************** * Register Page 14, Output Mailbox **********************************/ @@ -406,4 +571,23 @@ zl3073x_mb_poll_output_mb_sem(struct zl3073x_dev *zldev, u8 bitmask) ZL_POLL_TIMEOUT_US); } +/* + * Register 'output_mode' + * Page: 14, Offset: 0x05, Size: 8 bits + */ +#define ZL_REG_OUTPUT_MODE ZL_REG_ADDR(14, 0x05) +#define ZL_OUTPUT_MODE_SIGNAL_FORMAT GENMASK(7, 4) + +static inline __maybe_unused int +zl3073x_mb_read_output_mode(struct zl3073x_dev *zldev, u8 *value) +{ + unsigned int v; + int rc; + + lockdep_assert_held(&zldev->mailbox_lock); + rc = regmap_read(zldev->regmap, ZL_REG_OUTPUT_MODE, &v); + *value = v; + return rc; +} + #endif /* __LINUX_MFD_ZL3073X_REGS_H */ From patchwork Wed Apr 16 16:21:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Vecera X-Patchwork-Id: 14054225 X-Patchwork-Delegate: kuba@kernel.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8C884218593 for ; Wed, 16 Apr 2025 16:22:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820562; cv=none; b=Bhvf2kcgXy+UR1CXvVTTThJvIaX2GeSUNDC453q8y3K1X2r9aCyDcca09KlPyMqh1yvh/Is9cWFn97WPSGE8+XFGqx0xagTOP4b4JVKSH7aBIDvLfw/4QioSA573zA/sGkf0ypXuLBN0PGQPGcZ+rBKKd7CfIVNDZdj5iA+QqrM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744820562; c=relaxed/simple; bh=mhroH62gvO9ZeN3ndrEuib78iEtzPLbdjGEAf/xy5vQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iVhwvOjgMSA6YiHXQ9yJBI23Vk57M2g8FRbzQR3/SkQ4NSlPqgSkj9efGqdi5rxerKFsJkvv6RhyYsdCS8ovw3CkAOTL212C137AHxBBrBnMEQWaAoGOunDsFozLM/G2F40/fQvkJcNwpl73wz8v9BA0M/+E5HUezENHHHF+7oY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=LMBdQWi/; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="LMBdQWi/" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1744820559; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=c0XIADaqXMLiabHFp8+DtJN4Xp5Pbh8dJJfLV+eNoh8=; b=LMBdQWi/wNvuPMlUseMbruniviIUButUwjFbD14VQfc8CtJRYnCk75D3JOfsEhcNHHzfrS KDTTxzlkAjfoaLSwMFlJ7PQr4KE98WJjI8PF0IDlaDbntwI2dgC8JaTt/70KCM7UhXeSLG D83/KIvuE9sAq62sf2lJGf6wRfyDOzo= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-217-O_wDi8XxMiOsSbKJ6eKitg-1; Wed, 16 Apr 2025 12:22:36 -0400 X-MC-Unique: O_wDi8XxMiOsSbKJ6eKitg-1 X-Mimecast-MFC-AGG-ID: O_wDi8XxMiOsSbKJ6eKitg_1744820554 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C04B719560A7; Wed, 16 Apr 2025 16:22:33 +0000 (UTC) Received: from p16v.luc.cera.cz (unknown [10.44.33.32]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 09D0E1800965; Wed, 16 Apr 2025 16:22:28 +0000 (UTC) From: Ivan Vecera To: netdev@vger.kernel.org Cc: Vadim Fedorenko , Arkadiusz Kubalewski , Jiri Pirko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Prathosh Satish , Lee Jones , Kees Cook , Andy Shevchenko , Andrew Morton , Michal Schmidt , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v3 net-next 8/8] mfd: zl3073x: Register DPLL sub-device during init Date: Wed, 16 Apr 2025 18:21:44 +0200 Message-ID: <20250416162144.670760-9-ivecera@redhat.com> In-Reply-To: <20250416162144.670760-1-ivecera@redhat.com> References: <20250416162144.670760-1-ivecera@redhat.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Patchwork-Delegate: kuba@kernel.org Register DPLL sub-devices to expose this functionality provided by ZL3073x chip family. Each sub-device represents one of the provided DPLL channels. Signed-off-by: Ivan Vecera --- drivers/mfd/zl3073x-core.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/mfd/zl3073x-core.c b/drivers/mfd/zl3073x-core.c index 0bd31591245a2..fda77724a8452 100644 --- a/drivers/mfd/zl3073x-core.c +++ b/drivers/mfd/zl3073x-core.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -774,6 +775,20 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev, if (rc) return rc; + /* Add DPLL sub-device cell for each DPLL channel */ + for (i = 0; i < chip_info->num_channels; i++) { + struct mfd_cell dpll_dev = MFD_CELL_BASIC("zl3073x-dpll", NULL, + NULL, 0, i); + + rc = devm_mfd_add_devices(zldev->dev, PLATFORM_DEVID_AUTO, + &dpll_dev, 1, NULL, 0, NULL); + if (rc) { + dev_err_probe(zldev->dev, rc, + "Failed to add DPLL sub-device\n"); + return rc; + } + } + /* Register the device as devlink device */ devlink = priv_to_devlink(zldev); devlink_register(devlink);