All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/6] Add the Lantiq PEF2256 audio support
@ 2023-03-22 13:46 Herve Codina
  2023-03-22 13:46 ` [PATCH v3 1/6] dt-bindings: mfd: Add the Lantiq PEF2256 E1/T1/J1 framer Herve Codina
                   ` (11 more replies)
  0 siblings, 12 replies; 29+ messages in thread
From: Herve Codina @ 2023-03-22 13:46 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni

Hi,

This series adds support for audio using the Lantiq PEF2256 framer.

The Lantiq PEF2256 is a framer and line interface component designed to
fulfill all required interfacing between an analog E1/T1/J1 line and the
digital PCM system highway/H.100 bus.

The first part of this series (patches 1 to 4) adds the Lantiq PEF2256
driver core.
The second part (patches 5 to 7) adds the audio support using the Lantiq
PEF2256 driver core.

The consumer/provider relation between the codec and the driver core
allows to use the PEF2256 framer for other purpose than audio support.

Compared to the previous iteration
  https://lore.kernel.org/linux-kernel/20230316122741.577663-1-herve.codina@bootlin.com/
This v3 series mainly:
  - takes into account pef2256.c modifications suggested by Christophe.
  - fixes binding
  - Moves to MFD.
  - Merges MAINTAINERS entries

Best regards,
Herve Codina

Changes v2 -> v3
  - Patch 1
    Remove unneeded 'allOf' and quotes.
    Add several 'additionalProperties: false'
    Fix example (node name, interrupts and reg properties)
    Replace the lantiq,sysclk-rate-hz property by sclkr and sclkx clocks.
    Define 'lantiq,frame-format' property in top level.
    Move to MFD

  - Patch 2
    Fix some #define.
    Compact the register accessor helpers.
    Rework pef2256_get_version().
    Merge v1.2 and v2.x GCM setup functions into one pef2256_setup_gcm().
    Update comments, avoid duplicates and change some conditionals.
    Remove the carrier spinlock and use atomic_t.
    Make exported symbol consistent and use EXPORT_SYMBOL_GPL.
    Remove the no more needed pef2256_get_byphandle() and
    devm_pef2256_get_byphandle().
    Replace the lantiq,sysclk-rate-hz property by sclkr and sclkx clocks.
    Move to MFD

  - Patch 4
    Remove, merged with patch 7

  - Patch 4 (patch 5 in v2)
    Update title and description.
    Remove incorrect SPI reference.
    Remove the 'lantiq,pef2256' phandle.
    Fix commit log

  - Patch 5 (patch 6 in v2)
    Remove devm_pef2256_get_byphandle().
    Fix commit log

  - Patch 6 (patch 7 in v2)
    Merge v2 patch 4. One entry only for PEF2256

Changes v1 -> v2
  - Patch 2
    Remove duplicate const qualifiers.
    Add HAS_IOMEM as a dependency

  - Patch 3
    Fix a "Block quote ends without a blank line; unexpected unindent"
    syntax issue.

Herve Codina (6):
  dt-bindings: mfd: Add the Lantiq  PEF2256 E1/T1/J1 framer
  mfd: Add support for the Lantiq PEF2256 framer
  Documentation: sysfs: Document the Lantiq PEF2256 sysfs entry
  dt-bindings: sound: Add support for the Lantiq PEF2256 codec
  ASoC: codecs: Add support for the Lantiq PEF2256 codec
  MAINTAINERS: Add the Lantiq PEF2256 driver entry

 .../sysfs-bus-platform-devices-pef2256        |   12 +
 .../bindings/mfd/lantiq,pef2256.yaml          |  205 +++
 .../bindings/sound/lantiq,pef2256-codec.yaml  |   54 +
 MAINTAINERS                                   |   10 +
 drivers/mfd/Kconfig                           |   16 +
 drivers/mfd/Makefile                          |    1 +
 drivers/mfd/pef2256.c                         | 1355 +++++++++++++++++
 include/linux/mfd/pef2256.h                   |   28 +
 sound/soc/codecs/Kconfig                      |   14 +
 sound/soc/codecs/Makefile                     |    2 +
 sound/soc/codecs/pef2256-codec.c              |  390 +++++
 11 files changed, 2087 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256
 create mode 100644 Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
 create mode 100644 drivers/mfd/pef2256.c
 create mode 100644 include/linux/mfd/pef2256.h
 create mode 100644 sound/soc/codecs/pef2256-codec.c

-- 
2.39.2


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH v3 1/6] dt-bindings: mfd: Add the Lantiq  PEF2256 E1/T1/J1 framer
  2023-03-22 13:46 [PATCH v3 0/6] Add the Lantiq PEF2256 audio support Herve Codina
@ 2023-03-22 13:46 ` Herve Codina
  2023-03-22 21:58   ` Krzysztof Kozlowski
  2023-03-22 13:46 ` Herve Codina via Alsa-devel
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 29+ messages in thread
From: Herve Codina @ 2023-03-22 13:46 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni

The Lantiq PEF2256 is a framer and line interface component designed to
fulfill all required interfacing between an analog E1/T1/J1 line and the
digital PCM system highway/H.100 bus.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 .../bindings/mfd/lantiq,pef2256.yaml          | 205 ++++++++++++++++++
 1 file changed, 205 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml

diff --git a/Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml b/Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
new file mode 100644
index 000000000000..affbf20df0a2
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
@@ -0,0 +1,205 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/lantiq,pef2256.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Lantiq PEF2256
+
+maintainers:
+  - Herve Codina <herve.codina@bootlin.com>
+
+description:
+  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and
+  line interface component designed to fulfill all required interfacing between
+  an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.
+
+properties:
+  compatible:
+    items:
+      - const: lantiq,pef2256
+      - const: simple-mfd
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Master clock
+      - description: Receive System Clock
+      - description: Transmit System Clock
+
+  clock-names:
+    items:
+      - const: mclk
+      - const: sclkr
+      - const: sclkx
+
+  interrupts:
+    maxItems: 1
+
+  reset-gpios:
+    description:
+      GPIO used to reset the device.
+    maxItems: 1
+
+  pinctrl:
+    $ref: /schemas/pinctrl/pinctrl.yaml#
+
+    patternProperties:
+      '-pins$':
+        type: object
+        $ref: /schemas/pinctrl/pincfg-node.yaml#
+
+        properties:
+          pins:
+            enum: [ RPA, RPB, RPC, RPD, XPA, XPB, XPC, XPD ]
+
+          function:
+            enum: [ SYPR, RFM, RFMB, RSIGM, RSIG, DLR, FREEZE, RFSP, LOS,
+                    SYPX, XFMS, XSIG, TCLK, XMFB, XSIGM, DLX, XCLK, XLT,
+                    GPI, GPOH, GPOL ]
+
+        additionalProperties: false
+
+        required:
+          - pins
+          - function
+
+    additionalProperties: false
+
+  lantiq,line-interface:
+    $ref: /schemas/types.yaml#/definitions/string
+    enum: [e1, t1j1]
+    default: e1
+    description: |
+      The line interface type
+        - e1: E1 line
+        - t1j1: T1/J1 line
+
+  lantiq,frame-format:
+    $ref: /schemas/types.yaml#/definitions/string
+    description:
+      The line interface frame format.
+
+  lantiq,data-rate-bps:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [2048000, 4096000, 8192000, 16384000]
+    default: 2048000
+    description:
+      Data rate (bit per seconds) on the system highway.
+
+  lantiq,clock-falling-edge:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      Data is sent on falling edge of the clock (and received on the rising
+      edge). If 'clock-falling-edge' is not present, data is sent on the
+      rising edge (and received on the falling edge).
+
+  lantiq,channel-phase:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1, 2, 3, 4, 5, 6, 7]
+    default: 0
+    description:
+      The pef2256 delivers a full frame (32 8bit time-slots in E1 and 24 8bit
+      time-slots 8 8bit signaling in E1/J1) every 125us. This lead to a data
+      rate of 2048000 bit/s. When lantiq,data-rate-bps is more than 2048000
+      bit/s, the data (all 32 8bit) present in the frame are interleave with
+      unused time-slots. The lantiq,channel-phase property allows to set the
+      correct alignment of the interleave mechanism.
+      For instance, suppose lantiq,data-rate-bps = 8192000 (ie 4*2048000), and
+      lantiq,channel-phase = 2, the interleave schema with unused time-slots
+      (nu) and used time-slots (XX) for TSi is
+        nu nu XX nu nu nu XX nu nu nu XX nu
+        <-- TSi --> <- TSi+1 -> <- TSi+2 ->
+      With lantiq,data-rate-bps = 8192000, and lantiq,channel-phase = 1, the
+      interleave schema is
+        nu XX nu nu nu XX nu nu nu XX nu nu
+        <-- TSi --> <- TSi+1 -> <- TSi+2 ->
+      With lantiq,data-rate-bps = 4096000 (ie 2*2048000), and
+      lantiq,channel-phase = 1, the interleave schema is
+        nu    XX    nu    XX    nu    XX
+        <-- TSi --> <- TSi+1 -> <- TSi+2 ->
+
+  lantiq,subordinate:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      If present, the pef2256 works in subordinate mode. In this mode it
+      synchronizes on line interface clock signals. Otherwise, it synchronizes
+      on internal clocks.
+
+patternProperties:
+  '^codec([0-9]|[1-2][0-9]|3[0-1])?$':
+    $ref: /schemas/sound/lantiq,pef2256-codec.yaml
+
+allOf:
+  - if:
+      properties:
+        lantiq,line-interface:
+          contains:
+            const: e1
+    then:
+      properties:
+        lantiq,frame-format:
+          enum: [doubleframe, crc4-multiframe, auto-multiframe]
+          default: doubleframe
+          description: |
+            The E1 line interface frame format
+              - doubleframe: Doubleframe format
+              - crc4-multiframe: CRC4 multiframe format
+              - auto-multiframe: CRC4 multiframe format with interworking
+                                 capabilities (ITU-T G.706 Annex B)
+
+    else:
+      # T1/J1 line
+      properties:
+        lantiq,frame-format:
+          enum: [4frame, 12frame, 24frame, 72frame]
+          default: 12frame
+          description: |
+            The T1/J1 line interface frame format
+              - 4frame: 4-frame multiframe format (F4)
+              - 12frame: 12-frame multiframe format (F12, D3/4)
+              - 24frame: 24-frame multiframe format (ESF)
+              - 72frame: 72-frame multiframe format (F72, remote switch mode)
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    framer@2000000 {
+      compatible = "lantiq,pef2256", "simple-mfd";
+      reg = <0x2000000 0x100>;
+      interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+      interrupt-parent = <&intc>;
+      clocks = <&clk_mclk>, <&clk_sclkr>, <&clk_sclkx>;
+      clock-names = "mclk", "sclkr", "sclkx";
+      reset-gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
+      lantiq,data-rate-bps = <4096000>;
+
+      pinctrl {
+        pef2256_rpa_sypr: rpa-pins {
+          pins = "RPA";
+          function = "SYPR";
+        };
+        pef2256_xpa_sypx: xpa-pins {
+          pins = "XPA";
+          function = "SYPX";
+        };
+      };
+
+      codec {
+        compatible = "lantiq,pef2256-codec";
+        #sound-dai-cells = <0>;
+      };
+    };
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 1/6] dt-bindings: mfd: Add the Lantiq  PEF2256 E1/T1/J1 framer
  2023-03-22 13:46 [PATCH v3 0/6] Add the Lantiq PEF2256 audio support Herve Codina
  2023-03-22 13:46 ` [PATCH v3 1/6] dt-bindings: mfd: Add the Lantiq PEF2256 E1/T1/J1 framer Herve Codina
@ 2023-03-22 13:46 ` Herve Codina via Alsa-devel
  2023-03-22 13:46 ` [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer Herve Codina via Alsa-devel
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 29+ messages in thread
From: Herve Codina via Alsa-devel @ 2023-03-22 13:46 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni


[-- Attachment #0: Type: message/rfc822, Size: 10935 bytes --]

From: Herve Codina <herve.codina@bootlin.com>
To: Herve Codina <herve.codina@bootlin.com>, Lee Jones <lee@kernel.org>, Rob Herring <robh+dt@kernel.org>, Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>, Liam Girdwood <lgirdwood@gmail.com>, Mark Brown <broonie@kernel.org>, Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>
Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, alsa-devel@alsa-project.org, Christophe Leroy <christophe.leroy@csgroup.eu>, Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Subject: [PATCH v3 1/6] dt-bindings: mfd: Add the Lantiq  PEF2256 E1/T1/J1 framer
Date: Wed, 22 Mar 2023 14:46:49 +0100
Message-ID: <20230322134654.219957-2-herve.codina@bootlin.com>

The Lantiq PEF2256 is a framer and line interface component designed to
fulfill all required interfacing between an analog E1/T1/J1 line and the
digital PCM system highway/H.100 bus.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 .../bindings/mfd/lantiq,pef2256.yaml          | 205 ++++++++++++++++++
 1 file changed, 205 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml

diff --git a/Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml b/Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
new file mode 100644
index 000000000000..affbf20df0a2
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
@@ -0,0 +1,205 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/lantiq,pef2256.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Lantiq PEF2256
+
+maintainers:
+  - Herve Codina <herve.codina@bootlin.com>
+
+description:
+  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and
+  line interface component designed to fulfill all required interfacing between
+  an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.
+
+properties:
+  compatible:
+    items:
+      - const: lantiq,pef2256
+      - const: simple-mfd
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Master clock
+      - description: Receive System Clock
+      - description: Transmit System Clock
+
+  clock-names:
+    items:
+      - const: mclk
+      - const: sclkr
+      - const: sclkx
+
+  interrupts:
+    maxItems: 1
+
+  reset-gpios:
+    description:
+      GPIO used to reset the device.
+    maxItems: 1
+
+  pinctrl:
+    $ref: /schemas/pinctrl/pinctrl.yaml#
+
+    patternProperties:
+      '-pins$':
+        type: object
+        $ref: /schemas/pinctrl/pincfg-node.yaml#
+
+        properties:
+          pins:
+            enum: [ RPA, RPB, RPC, RPD, XPA, XPB, XPC, XPD ]
+
+          function:
+            enum: [ SYPR, RFM, RFMB, RSIGM, RSIG, DLR, FREEZE, RFSP, LOS,
+                    SYPX, XFMS, XSIG, TCLK, XMFB, XSIGM, DLX, XCLK, XLT,
+                    GPI, GPOH, GPOL ]
+
+        additionalProperties: false
+
+        required:
+          - pins
+          - function
+
+    additionalProperties: false
+
+  lantiq,line-interface:
+    $ref: /schemas/types.yaml#/definitions/string
+    enum: [e1, t1j1]
+    default: e1
+    description: |
+      The line interface type
+        - e1: E1 line
+        - t1j1: T1/J1 line
+
+  lantiq,frame-format:
+    $ref: /schemas/types.yaml#/definitions/string
+    description:
+      The line interface frame format.
+
+  lantiq,data-rate-bps:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [2048000, 4096000, 8192000, 16384000]
+    default: 2048000
+    description:
+      Data rate (bit per seconds) on the system highway.
+
+  lantiq,clock-falling-edge:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      Data is sent on falling edge of the clock (and received on the rising
+      edge). If 'clock-falling-edge' is not present, data is sent on the
+      rising edge (and received on the falling edge).
+
+  lantiq,channel-phase:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1, 2, 3, 4, 5, 6, 7]
+    default: 0
+    description:
+      The pef2256 delivers a full frame (32 8bit time-slots in E1 and 24 8bit
+      time-slots 8 8bit signaling in E1/J1) every 125us. This lead to a data
+      rate of 2048000 bit/s. When lantiq,data-rate-bps is more than 2048000
+      bit/s, the data (all 32 8bit) present in the frame are interleave with
+      unused time-slots. The lantiq,channel-phase property allows to set the
+      correct alignment of the interleave mechanism.
+      For instance, suppose lantiq,data-rate-bps = 8192000 (ie 4*2048000), and
+      lantiq,channel-phase = 2, the interleave schema with unused time-slots
+      (nu) and used time-slots (XX) for TSi is
+        nu nu XX nu nu nu XX nu nu nu XX nu
+        <-- TSi --> <- TSi+1 -> <- TSi+2 ->
+      With lantiq,data-rate-bps = 8192000, and lantiq,channel-phase = 1, the
+      interleave schema is
+        nu XX nu nu nu XX nu nu nu XX nu nu
+        <-- TSi --> <- TSi+1 -> <- TSi+2 ->
+      With lantiq,data-rate-bps = 4096000 (ie 2*2048000), and
+      lantiq,channel-phase = 1, the interleave schema is
+        nu    XX    nu    XX    nu    XX
+        <-- TSi --> <- TSi+1 -> <- TSi+2 ->
+
+  lantiq,subordinate:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      If present, the pef2256 works in subordinate mode. In this mode it
+      synchronizes on line interface clock signals. Otherwise, it synchronizes
+      on internal clocks.
+
+patternProperties:
+  '^codec([0-9]|[1-2][0-9]|3[0-1])?$':
+    $ref: /schemas/sound/lantiq,pef2256-codec.yaml
+
+allOf:
+  - if:
+      properties:
+        lantiq,line-interface:
+          contains:
+            const: e1
+    then:
+      properties:
+        lantiq,frame-format:
+          enum: [doubleframe, crc4-multiframe, auto-multiframe]
+          default: doubleframe
+          description: |
+            The E1 line interface frame format
+              - doubleframe: Doubleframe format
+              - crc4-multiframe: CRC4 multiframe format
+              - auto-multiframe: CRC4 multiframe format with interworking
+                                 capabilities (ITU-T G.706 Annex B)
+
+    else:
+      # T1/J1 line
+      properties:
+        lantiq,frame-format:
+          enum: [4frame, 12frame, 24frame, 72frame]
+          default: 12frame
+          description: |
+            The T1/J1 line interface frame format
+              - 4frame: 4-frame multiframe format (F4)
+              - 12frame: 12-frame multiframe format (F12, D3/4)
+              - 24frame: 24-frame multiframe format (ESF)
+              - 72frame: 72-frame multiframe format (F72, remote switch mode)
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    framer@2000000 {
+      compatible = "lantiq,pef2256", "simple-mfd";
+      reg = <0x2000000 0x100>;
+      interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+      interrupt-parent = <&intc>;
+      clocks = <&clk_mclk>, <&clk_sclkr>, <&clk_sclkx>;
+      clock-names = "mclk", "sclkr", "sclkx";
+      reset-gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
+      lantiq,data-rate-bps = <4096000>;
+
+      pinctrl {
+        pef2256_rpa_sypr: rpa-pins {
+          pins = "RPA";
+          function = "SYPR";
+        };
+        pef2256_xpa_sypx: xpa-pins {
+          pins = "XPA";
+          function = "SYPX";
+        };
+      };
+
+      codec {
+        compatible = "lantiq,pef2256-codec";
+        #sound-dai-cells = <0>;
+      };
+    };
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer
  2023-03-22 13:46 [PATCH v3 0/6] Add the Lantiq PEF2256 audio support Herve Codina
                   ` (2 preceding siblings ...)
  2023-03-22 13:46 ` [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer Herve Codina via Alsa-devel
@ 2023-03-22 13:46 ` Herve Codina
  2023-03-23  7:30   ` Krzysztof Kozlowski
  2023-03-26 15:49   ` kernel test robot
  2023-03-22 13:46 ` [PATCH v3 3/6] Documentation: sysfs: Document the Lantiq PEF2256 sysfs entry Herve Codina
                   ` (7 subsequent siblings)
  11 siblings, 2 replies; 29+ messages in thread
From: Herve Codina @ 2023-03-22 13:46 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni

The Lantiq PEF2256 is a framer and line interface component designed to
fulfill all required interfacing between an analog E1/T1/J1 line and the
digital PCM system highway/H.100 bus.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 drivers/mfd/Kconfig         |   16 +
 drivers/mfd/Makefile        |    1 +
 drivers/mfd/pef2256.c       | 1355 +++++++++++++++++++++++++++++++++++
 include/linux/mfd/pef2256.h |   28 +
 4 files changed, 1400 insertions(+)
 create mode 100644 drivers/mfd/pef2256.c
 create mode 100644 include/linux/mfd/pef2256.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index fcc141e067b9..174c6fe3e539 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1063,6 +1063,22 @@ config PCF50633_GPIO
 	  Say yes here if you want to include support GPIO for pins on
 	  the PCF50633 chip.
 
+config MFD_PEF2256
+	tristate "Lantiq PEF2256 (FALC56) framer"
+	select PINCTRL
+	select PINMUX
+	select GENERIC_PINCONF
+	help
+	  This option enables support for the Lantiq PEF2256 framer, also known
+	  as FALC56. This framer and its line interface component is designed
+	  to fulfill all required interfacing between analog E1/T1/J1 lines and
+	  the digital PCM system highway.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pef2256.
+
 config MFD_PM8XXX
 	tristate "Qualcomm PM8xxx PMIC chips driver"
 	depends on (ARM || HEXAGON || COMPILE_TEST)
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 2f6c89d1e277..b2bb6e6a141c 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -195,6 +195,7 @@ obj-$(CONFIG_MFD_SI476X_CORE)	+= si476x-core.o
 
 obj-$(CONFIG_MFD_CS5535)	+= cs5535-mfd.o
 obj-$(CONFIG_MFD_OMAP_USB_HOST)	+= omap-usb-host.o omap-usb-tll.o
+obj-$(CONFIG_MFD_PEF2256)	+= pef2256.o
 obj-$(CONFIG_MFD_PM8XXX) 	+= qcom-pm8xxx.o ssbi.o
 obj-$(CONFIG_MFD_QCOM_RPM)	+= qcom_rpm.o
 obj-$(CONFIG_MFD_SPMI_PMIC)	+= qcom-spmi-pmic.o
diff --git a/drivers/mfd/pef2256.c b/drivers/mfd/pef2256.c
new file mode 100644
index 000000000000..a710b736ec95
--- /dev/null
+++ b/drivers/mfd/pef2256.c
@@ -0,0 +1,1355 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PEF2256 also known as FALC56 driver
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina <herve.codina@bootlin.com>
+ */
+
+#include <linux/mfd/pef2256.h>
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define PEF2256_CMDR		0x02 /* Command Register */
+#define   PEF2256_CMDR_RRES	  BIT(6)
+#define   PEF2256_CMDR_XRES	  BIT(4)
+#define   PEF2256_CMDR_SRES	  BIT(0)
+#define PEF2256_IMR0	        0x14 /* Interrupt Mask Register 0 */
+#define PEF2256_IMR1	        0x15 /* Interrupt Mask Register 1 */
+#define PEF2256_IMR2	        0x16 /* Interrupt Mask Register 2 */
+#define PEF2256_IMR3	        0x17 /* Interrupt Mask Register 3 */
+#define PEF2256_IMR4	        0x18 /* Interrupt Mask Register 4 */
+#define PEF2256_IMR5	        0x19 /* Interrupt Mask Register 5 */
+#define PEF2256_FMR0	        0x1C /* Framer Mode Register 0 */
+#define   PEF2256_FMR0_XC_MASK	  (0x3 << 6)
+#define     PEF2256_FMR0_XC_NRZ	    (0x0 << 6)
+#define     PEF2256_FMR0_XC_CMI	    (0x1 << 6)
+#define     PEF2256_FMR0_XC_AMI	    (0x2 << 6)
+#define     PEF2256_FMR0_XC_HDB3    (0x3 << 6)
+#define   PEF2256_FMR0_RC_MASK	  (0x3 << 4)
+#define     PEF2256_FMR0_RC_NRZ	    (0x0 << 4)
+#define     PEF2256_FMR0_RC_CMI	    (0x1 << 4)
+#define     PEF2256_FMR0_RC_AMI	    (0x2 << 4)
+#define     PEF2256_FMR0_RC_HDB3    (0x3 << 4)
+#define PEF2256_FMR1	        0x1D /* Framer Mode Register 1 */
+#define   PEF2256_FMR1_XFS	  BIT(3)
+#define   PEF2256_FMR1_ECM	  BIT(2)
+/* SSD is defined on 2 bits. The other bit is on SIC1 register */
+#define   PEF2256_FMR1_SSD_MASK   BIT(1)
+#define     PEF2256_FMR1_SSD_2048   0
+#define     PEF2256_FMR1_SSD_4096   BIT(1)
+#define     PEF2256_FMR1_SSD_8192   0
+#define     PEF2256_FMR1_SSD_16384  BIT(1)
+#define PEF2256_FMR2	        0x1E /* Framer Mode Register 2 */
+#define   PEF2256_FMR2_RFS_MASK	  (0x3 << 6)
+#define     PEF2256_FMR2_RFS_DOUBLEFRAME      (0x0 << 6)
+#define     PEF2256_FMR2_RFS_CRC4_MULTIFRAME  (0x2 << 6)
+#define     PEF2256_FMR2_RFS_AUTO_MULTIFRAME  (0x3 << 6)
+#define   PEF2256_FMR2_AXRA	  BIT(1)
+#define PEF2256_LOOP	        0x1F /* Channel Loop-Back */
+#define PEF2256_XSW	        0x20 /* Transmit Service Word */
+#define   PEF2256_XSW_XSIS	  BIT(7)
+#define   PEF2256_XSW_XTM	  BIT(6)
+#define   PEF2256_XSW_XY_MASK	  (0x1f << 0)
+#define     PEF2256_XSW_XY(_v)	    ((_v) & 0x1f)
+#define PEF2256_XSP	        0x21 /* Transmit Spare Bits */
+#define   PEF2256_XSP_XSIF	  BIT(2)
+#define PEF2256_XC0	        0x22 /* Transmit Control 0 */
+#define PEF2256_XC1	        0x23 /* Transmit Control 1 */
+#define PEF2256_RC0	        0x24 /* Receive Control 0 */
+#define   PEF2256_RC0_SWD	  BIT(7)
+#define   PEF2256_RC0_ASY4	  BIT(6)
+#define PEF2256_RC1	        0x25 /* Receive Control 1 */
+#define PEF2256_XPM0	        0x26 /* Transmit Pulse Mask 0 */
+#define PEF2256_XPM1	        0x27 /* Transmit Pulse Mask 1 */
+#define PEF2256_XPM2	        0x28 /* Transmit Pulse Mask 2 */
+#define   PEF2256_XPM2_XLT	  BIT(6)
+#define PEF2256_TSWM	        0x29 /* Transparent Service Word Mask */
+#define PEF2256_LIM0	        0x36 /* Line Interface Mode 0 */
+#define   PEF2256_2X_LIM0_BIT3	  BIT(3) /* v2.x, described as a forced '1' bit */
+#define   PEF2256_LIM0_MAS	  BIT(0)
+#define PEF2256_LIM1	        0x37 /* Line Interface Mode 1 */
+#define   PEF2256_12_LIM1_RIL_MASK   (0x7 << 4)
+#define     PEF2256_12_LIM1_RIL_910    (0x0 << 4)
+#define     PEF2256_12_LIM1_RIL_740    (0x1 << 4)
+#define     PEF2256_12_LIM1_RIL_590    (0x2 << 4)
+#define     PEF2256_12_LIM1_RIL_420    (0x3 << 4)
+#define     PEF2256_12_LIM1_RIL_320    (0x4 << 4)
+#define     PEF2256_12_LIM1_RIL_210    (0x5 << 4)
+#define     PEF2256_12_LIM1_RIL_160    (0x6 << 4)
+#define     PEF2256_12_LIM1_RIL_100    (0x7 << 4)
+#define   PEF2256_2X_LIM1_RIL_MASK   (0x7 << 4)
+#define     PEF2256_2X_LIM1_RIL_2250   (0x0 << 4)
+#define     PEF2256_2X_LIM1_RIL_1100   (0x1 << 4)
+#define     PEF2256_2X_LIM1_RIL_600    (0x2 << 4)
+#define     PEF2256_2X_LIM1_RIL_350    (0x3 << 4)
+#define     PEF2256_2X_LIM1_RIL_210    (0x4 << 4)
+#define     PEF2256_2X_LIM1_RIL_140    (0x5 << 4)
+#define     PEF2256_2X_LIM1_RIL_100    (0x6 << 4)
+#define     PEF2256_2X_LIM1_RIL_50     (0x7 << 4)
+#define PEF2256_PCD	        0x38 /* Pulse Count Detection */
+#define PEF2256_PCR	        0x39 /* Pulse Count Recovery */
+#define PEF2256_LIM2	        0x3A /* Line Interface Mode 2 */
+#define   PEF2256_LIM2_SLT_MASK	  (0x3 << 4)
+#define     PEF2256_LIM2_SLT_THR55  (0x0 << 4)
+#define     PEF2256_LIM2_SLT_THR67  (0x1 << 4)
+#define     PEF2256_LIM2_SLT_THR50  (0x2 << 4)
+#define     PEF2256_LIM2_SLT_THR45  (0x3 << 4)
+#define   PEF2256_LIM2_ELT	  BIT(2)
+#define PEF2256_SIC1	        0x3E /* System Interface Control 1 */
+#define   PEF2256_SIC1_SSC_MASK   (BIT(7) |  BIT(3))
+#define     PEF2256_SIC1_SSC_2048   (0)
+#define     PEF2256_SIC1_SSC_4096   BIT(3)
+#define     PEF2256_SIC1_SSC_8192   BIT(7)
+#define     PEF2256_SIC1_SSC_16384  (BIT(7) |  BIT(3))
+/* SSD is defined on 2 bits. The other bit is on FMR1 register */
+#define   PEF2256_SIC1_SSD_MASK   BIT(6)
+#define     PEF2256_SIC1_SSD_2048   0
+#define     PEF2256_SIC1_SSD_4096   0
+#define     PEF2256_SIC1_SSD_8192   BIT(6)
+#define     PEF2256_SIC1_SSD_16384  BIT(6)
+#define   PEF2256_SIC1_RBS_MASK	  (0x3 << 4)
+#define     PEF2256_SIC1_RBS_2FRAMES (0x0 << 4)
+#define     PEF2256_SIC1_RBS_1FRAME  (0x1 << 4)
+#define     PEF2256_SIC1_RBS_96BITS  (0x2 << 4)
+#define     PEF2256_SIC1_RBS_BYPASS  (0x3 << 4)
+#define   PEF2256_SIC1_XBS_MASK	  (0x3 << 0)
+#define     PEF2256_SIC1_XBS_BYPASS  (0x0 << 0)
+#define     PEF2256_SIC1_XBS_1FRAME  (0x1 << 0)
+#define     PEF2256_SIC1_XBS_2FRAMES (0x2 << 0)
+#define     PEF2256_SIC1_XBS_96BITS  (0x3 << 0)
+#define PEF2256_SIC2	        0x3F /* System Interface Control 2 */
+#define   PEF2256_SIC2_SICS_MASK       (0x7 << 1)
+#define     PEF2256_SIC2_SICS(_v)        ((_v) << 1)
+#define PEF2256_SIC3	        0x40 /* System Interface Control 3 */
+#define   PEF2256_SIC3_RTRI	  BIT(5)
+#define   PEF2256_SIC3_RESX	  BIT(3)
+#define   PEF2256_SIC3_RESR	  BIT(2)
+#define PEF2256_CMR1	        0x44 /* Clock Mode Register 1 */
+#define   PEF2256_CMR1_RS_MASK	  (0x3 << 4)
+#define     PEF2256_CMR1_RS_DPLL	   (0x0 << 4)
+#define     PEF2256_CMR1_RS_DPLL_LOS_HIGH  (0x1 << 4)
+#define     PEF2256_CMR1_RS_DCOR_2048	   (0x2 << 4)
+#define     PEF2256_CMR1_RS_DCOR_8192	   (0x3 << 4)
+#define   PEF2256_CMR1_DCS	  BIT(3)
+#define PEF2256_CMR2	        0x45 /* Clock Mode Register 2 */
+#define   PEF2256_CMR2_DCOXC	  BIT(5)
+#define PEF2256_GCR	        0x46 /* Global Configuration Register */
+#define   PEF2256_GCR_SCI	  BIT(6)
+#define   PEF2256_GCR_ECMC	  BIT(4)
+#define PEF2256_PC1	        0x80 /* Port Configuration 1 */
+#define PEF2256_PC2	        0x81 /* Port Configuration 2 */
+#define PEF2256_PC3	        0x82 /* Port Configuration 3 */
+#define PEF2256_PC4	        0x83 /* Port Configuration 4 */
+#define   PEF2256_12_PC_RPC_MASK  (0x7 << 4)
+#define     PEF2256_12_PC_RPC_SYPR	(0x0 << 4)
+#define     PEF2256_12_PC_RPC_RFM	(0x1 << 4)
+#define     PEF2256_12_PC_RPC_RFMB	(0x2 << 4)
+#define     PEF2256_12_PC_RPC_RSIGM	(0x3 << 4)
+#define     PEF2256_12_PC_RPC_RSIG	(0x4 << 4)
+#define     PEF2256_12_PC_RPC_DLR	(0x5 << 4)
+#define     PEF2256_12_PC_RPC_FREEZE	(0x6 << 4)
+#define     PEF2256_12_PC_RPC_RFSP	(0x7 << 4)
+#define   PEF2256_12_PC_XPC_MASK  (0xf << 0)
+#define     PEF2256_12_PC_XPC_SYPX	(0x0 << 0)
+#define     PEF2256_12_PC_XPC_XFMS	(0x1 << 0)
+#define     PEF2256_12_PC_XPC_XSIG	(0x2 << 0)
+#define     PEF2256_12_PC_XPC_TCLK	(0x3 << 0)
+#define     PEF2256_12_PC_XPC_XMFB	(0x4 << 0)
+#define     PEF2256_12_PC_XPC_XSIGM	(0x5 << 0)
+#define     PEF2256_12_PC_XPC_DLX	(0x6 << 0)
+#define     PEF2256_12_PC_XPC_XCLK	(0x7 << 0)
+#define     PEF2256_12_PC_XPC_XLT	(0x8 << 0)
+#define   PEF2256_2X_PC_RPC_MASK  (0xf << 4)
+#define     PEF2256_2X_PC_RPC_SYPR	(0x0 << 4)
+#define     PEF2256_2X_PC_RPC_RFM	(0x1 << 4)
+#define     PEF2256_2X_PC_RPC_RFMB	(0x2 << 4)
+#define     PEF2256_2X_PC_RPC_RSIGM	(0x3 << 4)
+#define     PEF2256_2X_PC_RPC_RSIG	(0x4 << 4)
+#define     PEF2256_2X_PC_RPC_DLR	(0x5 << 4)
+#define     PEF2256_2X_PC_RPC_FREEZE	(0x6 << 4)
+#define     PEF2256_2X_PC_RPC_RFSP	(0x7 << 4)
+#define     PEF2256_2X_PC_RPC_GPI	(0x9 << 4)
+#define     PEF2256_2X_PC_RPC_GPOH	(0xa << 4)
+#define     PEF2256_2X_PC_RPC_GPOL	(0xb << 4)
+#define     PEF2256_2X_PC_RPC_LOS	(0xc << 4)
+#define   PEF2256_2X_PC_XPC_MASK  (0xf << 0)
+#define     PEF2256_2X_PC_XPC_SYPX	(0x0 << 0)
+#define     PEF2256_2X_PC_XPC_XFMS	(0x1 << 0)
+#define     PEF2256_2X_PC_XPC_XSIG	(0x2 << 0)
+#define     PEF2256_2X_PC_XPC_TCLK	(0x3 << 0)
+#define     PEF2256_2X_PC_XPC_XMFB	(0x4 << 0)
+#define     PEF2256_2X_PC_XPC_XSIGM	(0x5 << 0)
+#define     PEF2256_2X_PC_XPC_DLX	(0x6 << 0)
+#define     PEF2256_2X_PC_XPC_XCLK	(0x7 << 0)
+#define     PEF2256_2X_PC_XPC_XLT	(0x8 << 0)
+#define     PEF2256_2X_PC_XPC_GPI	(0x9 << 0)
+#define     PEF2256_2X_PC_XPC_GPOH	(0xa << 0)
+#define     PEF2256_2X_PC_XPC_GPOL	(0xb << 0)
+#define PEF2256_PC5	        0x84 /* Port Configuration 5 */
+#define   PEF2256_PC5_CRP         BIT(0)
+#define PEF2256_GPC1	        0x85 /* Global Port Configuration 1 */
+#define   PEF2256_GPC1_CSFP_MASK	  (0x3 << 5)
+#define   PEF2256_GPC1_CSFP_SEC_IN_HIGH   (0x0 << 5)
+#define   PEF2256_GPC1_CSFP_SEC_OUT_HIGH  (0x1 << 5)
+#define   PEF2256_GPC1_CSFP_FSC_OUT_HIGH  (0x2 << 5)
+#define   PEF2256_GPC1_CSFP_FSC_OUT_LOW   (0x3 << 5)
+#define PEF2256_PC6	        0x86 /* Port Configuration 6 */
+#define PEF2256_GCM(_n)         (0x92 + (_n) - 1) /* Global Counter Mode n=1..8 */
+#define PEF2256_GCM1	        0x92 /* Global Counter Mode 1 */
+#define PEF2256_GCM2	        0x93 /* Global Counter Mode 2 */
+#define PEF2256_GCM3	        0x94 /* Global Counter Mode 3 */
+#define PEF2256_GCM4	        0x95 /* Global Counter Mode 4 */
+#define PEF2256_GCM5	        0x96 /* Global Counter Mode 5 */
+#define PEF2256_GCM6	        0x97 /* Global Counter Mode 6 */
+#define PEF2256_GCM7	        0x98 /* Global Counter Mode 7 */
+#define PEF2256_GCM8	        0x99 /* Global Counter Mode 8 */
+
+#define PEF2256_VSTR	0x4A /* Version Status Register */
+#define   PEF2256_VSTR_VERSION_12  0x00
+#define   PEF2256_VSTR_VERSION_21  0x10
+#define   PEF2256_VSTR_VERSION_2x  0x05
+#define PEF2256_FRS0	0x4C /* Framer Receive Status 0 */
+#define   PEF2256_FRS0_LOS	BIT(7)
+#define   PEF2256_FRS0_AIS	BIT(6)
+#define PEF2256_ISR(_n) (0x68 + (_n)) /* Interrupt Status Register (n=0..5) */
+#define PEF2256_ISR0	0x68 /* Interrupt Status Register 0 */
+#define PEF2256_ISR1	0x69 /* Interrupt Status Register 1 */
+#define PEF2256_ISR2	0x6A /* Interrupt Status Register 2 */
+#define PEF2256_ISR3	0x6B /* Interrupt Status Register 3 */
+#define PEF2256_ISR4	0x6C /* Interrupt Status Register 4 */
+#define PEF2256_ISR5	0x6D /* Interrupt Status Register 5 */
+#define PEF2256_GIS	0x6E /* Global Interrupt Status */
+#define   PEF2256_GIS_ISR(_n)	(1 << (_n))
+#define PEF2256_WID	0xEC /* Wafer Identification Register */
+#define   PEF2256_12_WID_MASK        0x03
+#define     PEF2256_12_WID_VERSION_12  0x03
+#define   PEF2256_2X_WID_MASK        0xc0
+#define     PEF2256_2X_WID_VERSION_21  0x00
+#define     PEF2256_2X_WID_VERSION_22  0x40
+
+/* IMR2/ISR2 Interrupts */
+#define PEF2256_INT2_AIS  BIT(3)
+#define PEF2256_INT2_LOS  BIT(2)
+
+enum pef2256_version {
+	PEF2256_VERSION_UNKNOWN,
+	PEF2256_VERSION_1_2,
+	PEF2256_VERSION_2_1,
+	PEF2256_VERSION_2_2,
+};
+
+enum pef2256_frame_type {
+	PEF2256_FRAME_E1_DOUBLEFRAME,
+	PEF2256_FRAME_E1_CRC4_MULTIFRAME,
+	PEF2256_FRAME_E1_AUTO_MULTIFRAME,
+	PEF2256_FRAME_T1J1_4FRAME,
+	PEF2256_FRAME_T1J1_12FRAME,
+	PEF2256_FRAME_T1J1_24FRAME,
+	PEF2256_FRAME_T1J1_72FRAME,
+};
+
+struct pef2256_pinreg_desc {
+	int offset;
+	u8 mask;
+};
+
+struct pef2256_function_desc {
+	const char *name;
+	const char * const*groups;
+	unsigned int ngroups;
+	u8 func_val;
+};
+
+struct pef2256 {
+	struct device *dev;
+	void *__iomem regs;
+	enum pef2256_version version;
+	struct clk *mclk;
+	struct clk *sclkr;
+	struct clk *sclkx;
+	struct gpio_desc *reset_gpio;
+	struct {
+		struct pinctrl_desc pctrl_desc;
+		const struct pef2256_function_desc *functions;
+		unsigned int nfunctions;
+	} pinctrl;
+	bool is_e1;
+	unsigned long sysclk_rate;
+	u32 data_rate;
+	bool is_tx_falling_edge;
+	bool is_subordinate;
+	enum pef2256_frame_type frame_type;
+	u8 channel_phase;
+	atomic_t carrier;
+	struct atomic_notifier_head event_notifier_list;
+};
+
+static inline u8 pef2256_read8(struct pef2256 *pef2256, int offset)
+{
+	return ioread8(pef2256->regs + offset);
+}
+
+static inline void pef2256_write8(struct pef2256 *pef2256, int offset, u8 val)
+{
+	iowrite8(val, pef2256->regs + offset);
+}
+
+static inline void pef2256_clrbits8(struct pef2256 *pef2256, int offset, u8 clr)
+{
+	pef2256_write8(pef2256, offset, pef2256_read8(pef2256, offset) & ~clr);
+}
+
+static inline void pef2256_setbits8(struct pef2256 *pef2256, int offset, u8 set)
+{
+	pef2256_write8(pef2256, offset, pef2256_read8(pef2256, offset) | set);
+}
+
+
+static inline void pef2256_clrsetbits8(struct pef2256 *pef2256, int offset, u8 clr, u8 set)
+{
+	u8 v;
+
+	v = pef2256_read8(pef2256, offset);
+	v &= ~clr;
+	v |= set;
+	pef2256_write8(pef2256, offset, v);
+}
+
+static enum pef2256_version pef2256_get_version(struct pef2256 *pef2256)
+{
+	enum pef2256_version version = PEF2256_VERSION_UNKNOWN;
+	const char *version_txt;
+	u8 vstr, wid;
+
+	vstr = pef2256_read8(pef2256, PEF2256_VSTR);
+	wid = pef2256_read8(pef2256, PEF2256_WID);
+
+	switch (vstr) {
+	case PEF2256_VSTR_VERSION_12:
+		if ((wid & PEF2256_12_WID_MASK) == PEF2256_12_WID_VERSION_12) {
+			version_txt = "1.2";
+			version = PEF2256_VERSION_1_2;
+		}
+		break;
+	case PEF2256_VSTR_VERSION_2x:
+		switch (wid & PEF2256_2X_WID_MASK) {
+		case PEF2256_2X_WID_VERSION_21:
+			version_txt = "2.1 (2.x)";
+			version = PEF2256_VERSION_2_1;
+			break;
+		case PEF2256_2X_WID_VERSION_22:
+			version_txt = "2.2 (2.x)";
+			version = PEF2256_VERSION_2_2;
+			break;
+		}
+		break;
+	case PEF2256_VSTR_VERSION_21:
+		version_txt = "2.1";
+		version = PEF2256_VERSION_2_1;
+		break;
+	}
+
+	if (version == PEF2256_VERSION_UNKNOWN)
+		dev_err(pef2256->dev, "Unknown version (0x%02x, 0x%02x)\n", vstr, wid);
+	else
+		dev_info(pef2256->dev, "Version %s detected\n", version_txt);
+
+	return version;
+}
+
+enum pef2256_gcm_config_item {
+	PEF2256_GCM_CONFIG_1544000 = 0,
+	PEF2256_GCM_CONFIG_2048000,
+	PEF2256_GCM_CONFIG_8192000,
+	PEF2256_GCM_CONFIG_10000000,
+	PEF2256_GCM_CONFIG_12352000,
+	PEF2256_GCM_CONFIG_16384000,
+};
+
+struct pef2256_gcm_config {
+	u8 gcm_12[6];
+	u8 gcm_2x[8];
+};
+
+static const struct pef2256_gcm_config pef2256_gcm_configs[] = {
+	[PEF2256_GCM_CONFIG_1544000] = {
+		.gcm_12 = {0xF0, 0x51, 0x00, 0x80, 0x00, 0x15},
+		.gcm_2x = {0x00, 0x15, 0x00, 0x08, 0x00, 0x3F, 0x9C, 0xDF},
+	},
+	[PEF2256_GCM_CONFIG_2048000] = {
+		.gcm_12 = {0x00, 0x58, 0xD2, 0xC2, 0x00, 0x10},
+		.gcm_2x = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x2F, 0xDB, 0xDF},
+	},
+	[PEF2256_GCM_CONFIG_8192000] = {
+		.gcm_12 = {0x00, 0x58, 0xD2, 0xC2, 0x03, 0x10},
+		.gcm_2x = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x0B, 0xDB, 0xDF},
+	},
+	[PEF2256_GCM_CONFIG_10000000] = {
+		.gcm_12 = {0x90, 0x51, 0x81, 0x8F, 0x04, 0x10},
+		.gcm_2x = {0x40, 0x1B, 0x3D, 0x0A, 0x00, 0x07, 0xC9, 0xDC},
+	},
+	[PEF2256_GCM_CONFIG_12352000] = {
+		.gcm_12 = {0xF0, 0x51, 0x00, 0x80, 0x07, 0x15},
+		.gcm_2x = {0x00, 0x19, 0x00, 0x08, 0x01, 0x0A, 0x98, 0xDA},
+	},
+	[PEF2256_GCM_CONFIG_16384000] = {
+		.gcm_12 = {0x00, 0x58, 0xD2, 0xC2, 0x07, 0x10},
+		.gcm_2x = {0x00, 0x18, 0xFB, 0x0B, 0x01, 0x0B, 0xDB, 0xDF},
+	},
+};
+
+static int pef2256_setup_gcm(struct pef2256 *pef2256)
+{
+	enum pef2256_gcm_config_item item;
+	unsigned long mclk_rate;
+	const u8 *gcm;
+	int i, count;
+
+	mclk_rate = clk_get_rate(pef2256->mclk);
+	switch (mclk_rate) {
+	case 1544000:
+		item = PEF2256_GCM_CONFIG_1544000;
+		break;
+	case 2048000:
+		item = PEF2256_GCM_CONFIG_2048000;
+		break;
+	case 8192000:
+		item = PEF2256_GCM_CONFIG_8192000;
+		break;
+	case 10000000:
+		item = PEF2256_GCM_CONFIG_10000000;
+		break;
+	case 12352000:
+		item = PEF2256_GCM_CONFIG_12352000;
+		break;
+	case 16384000:
+		item = PEF2256_GCM_CONFIG_16384000;
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported v2.x MCLK rate %lu\n", mclk_rate);
+		return -EINVAL;
+	}
+
+	BUILD_BUG_ON(item >= ARRAY_SIZE(pef2256_gcm_configs));
+
+	if (pef2256->version == PEF2256_VERSION_1_2) {
+		gcm = pef2256_gcm_configs[item].gcm_12;
+		count = ARRAY_SIZE(pef2256_gcm_configs[item].gcm_12);
+	} else {
+		gcm = pef2256_gcm_configs[item].gcm_2x;
+		count = ARRAY_SIZE(pef2256_gcm_configs[item].gcm_2x);
+	}
+
+	for (i = 0; i < count; i++)
+		pef2256_write8(pef2256, PEF2256_GCM(i+1), *(gcm + i));
+
+	return 0;
+}
+
+static int pef2256_setup_e1(struct pef2256 *pef2256)
+{
+	u8 fmr1, fmr2, sic1;
+	int ret;
+
+	/* Basic setup, Master clocking mode (GCM8..1) */
+	ret = pef2256_setup_gcm(pef2256);
+	if (ret)
+		return ret;
+
+	/* RCLK output : DPLL clock, DCO-X enabled, DCO-X internal ref clock */
+	pef2256_write8(pef2256, PEF2256_CMR1, 0x00);
+
+	/*
+	 * SCLKR selected, SCLKX selected,
+	 * receive synchro pulse sourced by SYPR,
+	 * transmit synchro pulse sourced by SYPX
+	 */
+	pef2256_write8(pef2256, PEF2256_CMR2, 0x00);
+
+	/* NRZ coding, no alarm simulation */
+	pef2256_write8(pef2256, PEF2256_FMR0, 0x00);
+
+	/*
+	 * E1, frame format, 2 Mbit/s system data rate, no AIS
+	 * transmission to remote end or system interface, payload loop
+	 * off, transmit remote alarm on
+	 */
+	fmr1 = 0x00;
+	fmr2 = PEF2256_FMR2_AXRA;
+	switch (pef2256->frame_type) {
+	case PEF2256_FRAME_E1_DOUBLEFRAME:
+		fmr2 |= PEF2256_FMR2_RFS_DOUBLEFRAME;
+		break;
+	case PEF2256_FRAME_E1_CRC4_MULTIFRAME:
+		fmr1 |= PEF2256_FMR1_XFS;
+		fmr2 |= PEF2256_FMR2_RFS_CRC4_MULTIFRAME;
+		break;
+	case PEF2256_FRAME_E1_AUTO_MULTIFRAME:
+		fmr1 |= PEF2256_FMR1_XFS;
+		fmr2 |= PEF2256_FMR2_RFS_AUTO_MULTIFRAME;
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported frame type %d\n", pef2256->frame_type);
+		return -EINVAL;
+	}
+	pef2256_write8(pef2256, PEF2256_FMR1, fmr1);
+	pef2256_write8(pef2256, PEF2256_FMR2, fmr2);
+
+	/* E1 default for the receive slicer threshold */
+	pef2256_write8(pef2256, PEF2256_LIM2, PEF2256_LIM2_SLT_THR50);
+	if (!pef2256->is_subordinate) {
+		/* SEC input, active high */
+		pef2256_write8(pef2256, PEF2256_GPC1, PEF2256_GPC1_CSFP_SEC_IN_HIGH);
+	} else {
+		/* Loop-timed */
+		pef2256_setbits8(pef2256, PEF2256_LIM2, PEF2256_LIM2_ELT);
+		/* FSC output, active high */
+		pef2256_write8(pef2256, PEF2256_GPC1, PEF2256_GPC1_CSFP_FSC_OUT_HIGH);
+	}
+
+	/* internal second timer, power on */
+	pef2256_write8(pef2256, PEF2256_GCR, 0x00);
+
+	/*
+	 * slave mode, local loop off, mode short-haul
+	 * In v2.x, bit3 is a forced 1 bit in the datasheet -> Need to be set.
+	 */
+	if (pef2256->version == PEF2256_VERSION_1_2)
+		pef2256_write8(pef2256, PEF2256_LIM0, 0x00);
+	else
+		pef2256_write8(pef2256, PEF2256_LIM0, PEF2256_2X_LIM0_BIT3);
+
+	/* analog interface selected, remote loop off */
+	pef2256_write8(pef2256, PEF2256_LIM1, 0x00);
+
+	/*
+	 * SCLKR, SCLKX, RCLK configured to inputs,
+	 * XFMS active low, CLK1 and CLK2 pin configuration
+	 */
+	pef2256_write8(pef2256, PEF2256_PC5, 0x00);
+	pef2256_write8(pef2256, PEF2256_PC6, 0x00);
+
+	/*
+	 * 2.048 MHz system clocking rate, receive buffer 2 frames, transmit
+	 * buffer bypass, data sampled and transmitted on the falling edge of
+	 * SCLKR/X, automatic freeze signaling, data is active in the first
+	 * channel phase
+	 */
+	pef2256_write8(pef2256, PEF2256_SIC1, 0x00);
+	pef2256_write8(pef2256, PEF2256_SIC2, 0x00);
+	pef2256_write8(pef2256, PEF2256_SIC3, 0x00);
+
+	/* channel loop-back and single frame mode are disabled */
+	pef2256_write8(pef2256, PEF2256_LOOP, 0x00);
+
+	/* all bits of the transmitted service word are cleared */
+	pef2256_write8(pef2256, PEF2256_XSW, PEF2256_XSW_XY(0x1F));
+	/* CAS disabled and clear spare bit values */
+	pef2256_write8(pef2256, PEF2256_XSP, 0x00);
+
+	/* no transparent mode active */
+	pef2256_write8(pef2256, PEF2256_TSWM, 0x00);
+
+	/*
+	 * the transmit clock offset is cleared
+	 * the transmit time slot offset is cleared
+	 */
+	pef2256_write8(pef2256, PEF2256_XC0, 0x00);
+
+	/* Keep default value for the transmit offset */
+	pef2256_write8(pef2256, PEF2256_XC1, 0x9C);
+
+	/*
+	 * transmit pulse mask, default value from datasheet
+	 * transmitter in tristate mode
+	 */
+	if (pef2256->version == PEF2256_VERSION_1_2)
+		pef2256_write8(pef2256, PEF2256_XPM0, 0x7B);
+	else
+		pef2256_write8(pef2256, PEF2256_XPM0, 0x9C);
+	pef2256_write8(pef2256, PEF2256_XPM1, 0x03);
+	pef2256_write8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT | 0x00);
+
+	/* "master" mode */
+	if (!pef2256->is_subordinate)
+		pef2256_setbits8(pef2256, PEF2256_LIM0, PEF2256_LIM0_MAS);
+
+	/* transmit line in normal operation */
+	pef2256_clrbits8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT);
+
+	/* receive input threshold = 0,21V */
+	if (pef2256->version == PEF2256_VERSION_1_2)
+		pef2256_clrsetbits8(pef2256, PEF2256_LIM1, PEF2256_12_LIM1_RIL_MASK,
+				    PEF2256_12_LIM1_RIL_210);
+	else
+		pef2256_clrsetbits8(pef2256, PEF2256_LIM1, PEF2256_2X_LIM1_RIL_MASK,
+				    PEF2256_2X_LIM1_RIL_210);
+
+	/* transmit line coding = HDB3 */
+	pef2256_clrsetbits8(pef2256, PEF2256_FMR0, PEF2256_FMR0_XC_MASK, PEF2256_FMR0_XC_HDB3);
+
+	/* receive line coding = HDB3 */
+	pef2256_clrsetbits8(pef2256, PEF2256_FMR0, PEF2256_FMR0_RC_MASK, PEF2256_FMR0_RC_HDB3);
+
+	/* detection of LOS alarm = 176 pulses (ie (10 + 1) * 16) */
+	pef2256_write8(pef2256, PEF2256_PCD, 10);
+
+	/* recovery of LOS alarm = 22 pulses (ie 21 + 1) */
+	pef2256_write8(pef2256, PEF2256_PCR, 21);
+
+	/* DCO-X center frequency enabled */
+	pef2256_setbits8(pef2256, PEF2256_CMR2, PEF2256_CMR2_DCOXC);
+
+	if (pef2256->is_subordinate) {
+		/* select RCLK source = 2M,  disable switching from RCLK to SYNC */
+		pef2256_clrsetbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_RS_MASK,
+				    PEF2256_CMR1_RS_DCOR_2048);
+		pef2256_setbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_DCS);
+
+		/* transmit buffer size = 2 frames, transparent mode */
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_XBS_MASK,
+				    PEF2256_SIC1_XBS_2FRAMES);
+		pef2256_setbits8(pef2256, PEF2256_XSW, PEF2256_XSW_XTM);
+	}
+
+	if (pef2256->version != PEF2256_VERSION_1_2) {
+		/* during inactive channel phase switch RDO/RSIG into tri-state */
+		pef2256_setbits8(pef2256, PEF2256_SIC3, PEF2256_SIC3_RTRI);
+	}
+
+	if (pef2256->is_tx_falling_edge) {
+		/* falling edge sync pulse transmit, rising edge sync pulse receive */
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC3, PEF2256_SIC3_RESX, PEF2256_SIC3_RESR);
+	} else {
+		/* rising edge sync pulse transmit, falling edge sync pulse receive */
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC3, PEF2256_SIC3_RESR, PEF2256_SIC3_RESX);
+	}
+
+	/* transmit offset counter (XCO10..0) = 4 */
+	pef2256_write8(pef2256, PEF2256_XC0, 0);
+	pef2256_write8(pef2256, PEF2256_XC1, 4);
+	/* receive offset counter (RCO10..0) = 4 */
+	pef2256_write8(pef2256, PEF2256_RC0, 0);
+	pef2256_write8(pef2256, PEF2256_RC1, 4);
+
+	/* system clock rate */
+	switch (pef2256->sysclk_rate) {
+	case 2048000:
+		sic1 = PEF2256_SIC1_SSC_2048;
+		break;
+	case 4096000:
+		sic1 = PEF2256_SIC1_SSC_4096;
+		break;
+	case 8192000:
+		sic1 = PEF2256_SIC1_SSC_8192;
+		break;
+	case 16384000:
+		sic1 = PEF2256_SIC1_SSC_16384;
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported sysclk rate %lu\n", pef2256->sysclk_rate);
+		return -EINVAL;
+	}
+	pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_SSC_MASK, sic1);
+
+	/* data clock rate */
+	switch (pef2256->data_rate) {
+	case 2048000:
+		fmr1 = PEF2256_FMR1_SSD_2048;
+		sic1 = PEF2256_SIC1_SSD_2048;
+		break;
+	case 4096000:
+		fmr1 = PEF2256_FMR1_SSD_4096;
+		sic1 = PEF2256_SIC1_SSD_4096;
+		break;
+	case 8192000:
+		fmr1 = PEF2256_FMR1_SSD_8192;
+		sic1 = PEF2256_SIC1_SSD_8192;
+		break;
+	case 16384000:
+		fmr1 = PEF2256_FMR1_SSD_16384;
+		sic1 = PEF2256_SIC1_SSD_16384;
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported data rate %u\n", pef2256->data_rate);
+		return -EINVAL;
+	}
+	pef2256_clrsetbits8(pef2256, PEF2256_FMR1, PEF2256_FMR1_SSD_MASK, fmr1);
+	pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_SSD_MASK, sic1);
+
+	/* channel phase */
+	pef2256_clrsetbits8(pef2256, PEF2256_SIC2, PEF2256_SIC2_SICS_MASK,
+			    PEF2256_SIC2_SICS(pef2256->channel_phase));
+
+	/* error counter latched every 1s */
+	pef2256_setbits8(pef2256, PEF2256_FMR1, PEF2256_FMR1_ECM);
+	/* error counter mode COFA */
+	pef2256_setbits8(pef2256, PEF2256_GCR, PEF2256_GCR_ECMC);
+	/* errors in service words have no influence */
+	pef2256_setbits8(pef2256, PEF2256_RC0, PEF2256_RC0_SWD);
+	/* 4 consecutive incorrect FAS causes loss of sync */
+	pef2256_setbits8(pef2256, PEF2256_RC0, PEF2256_RC0_ASY4);
+	/* Si-Bit, Spare bit For International, FAS word */
+	pef2256_setbits8(pef2256, PEF2256_XSW, PEF2256_XSW_XSIS);
+	pef2256_setbits8(pef2256, PEF2256_XSP, PEF2256_XSP_XSIF);
+
+	/* port RCLK is output */
+	pef2256_setbits8(pef2256, PEF2256_PC5, PEF2256_PC5_CRP);
+	/* status changed interrupt at both up and down */
+	pef2256_setbits8(pef2256, PEF2256_GCR, PEF2256_GCR_SCI);
+
+	/* Clear any ISR2 pending interrupts and unmask needed interrupts */
+	pef2256_read8(pef2256, PEF2256_ISR2);
+	pef2256_clrbits8(pef2256, PEF2256_IMR2, PEF2256_INT2_LOS | PEF2256_INT2_AIS);
+
+	/* reset lines */
+	pef2256_write8(pef2256, PEF2256_CMDR, PEF2256_CMDR_RRES | PEF2256_CMDR_XRES);
+	return 0;
+}
+
+static int pef2256_setup(struct pef2256 *pef2256)
+{
+	if (pef2256->is_e1)
+		return pef2256_setup_e1(pef2256);
+
+	dev_err(pef2256->dev, "Only E1 line is currently supported\n");
+	return -EOPNOTSUPP;
+}
+
+
+
+static void pef2256_isr_default_handler(struct pef2256 *pef2256, u8 nbr, u8 isr)
+{
+	dev_warn(pef2256->dev, "ISR%u: 0x%02x not handled\n", nbr, isr);
+}
+
+static bool pef2256_is_carrier_on(struct pef2256 *pef2256)
+{
+	u8 frs0;
+
+	frs0 = pef2256_read8(pef2256, PEF2256_FRS0);
+	return !(frs0 & (PEF2256_FRS0_LOS | PEF2256_FRS0_AIS));
+}
+
+static void pef2256_isr2_handler(struct pef2256 *pef2256, u8 nbr, u8 isr)
+{
+	bool carrier;
+
+	if (isr & (PEF2256_INT2_LOS | PEF2256_INT2_AIS)) {
+		carrier = pef2256_is_carrier_on(pef2256);
+		if (atomic_xchg(&pef2256->carrier, carrier) != carrier)
+			atomic_notifier_call_chain(&pef2256->event_notifier_list,
+						   PEF2256_EVENT_CARRIER, NULL);
+	}
+}
+
+static irqreturn_t pef2256_irq_handler(int irq, void *priv)
+{
+	void (*pef2256_isr_handler[])(struct pef2256 *, u8, u8) = {
+		[0] = pef2256_isr_default_handler,
+		[1] = pef2256_isr_default_handler,
+		[2] = pef2256_isr2_handler,
+		[3] = pef2256_isr_default_handler,
+		[4] = pef2256_isr_default_handler,
+		[5] = pef2256_isr_default_handler
+	};
+	struct pef2256 *pef2256 = (struct pef2256 *)priv;
+	u8 gis;
+	u8 isr;
+	u8 n;
+
+	gis = pef2256_read8(pef2256, PEF2256_GIS);
+
+	for (n = 0; n < ARRAY_SIZE(pef2256_isr_handler) ; n++) {
+		if (gis & PEF2256_GIS_ISR(n)) {
+			isr = pef2256_read8(pef2256, PEF2256_ISR(n));
+			pef2256_isr_handler[n](pef2256, n, isr);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int pef2256_check_rates(struct pef2256 *pef2256, unsigned long sysclk_rate,
+			       unsigned long data_rate)
+{
+	unsigned long rate;
+
+	switch (sysclk_rate) {
+	case 2048000:
+	case 4096000:
+	case 8192000:
+	case 16384000:
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported system clock rate %lu\n", sysclk_rate);
+		return -EINVAL;
+	}
+
+	for (rate = data_rate; rate <= data_rate * 4; rate *= 2) {
+		if (rate == sysclk_rate)
+			return 0;
+	}
+	dev_err(pef2256->dev, "Unsupported data rate %lu with system clock rate %lu\n",
+		data_rate, sysclk_rate);
+	return -EINVAL;
+}
+
+static int pef2556_of_parse(struct pef2256 *pef2256, struct device_node *np)
+{
+	const char *str;
+	int ret;
+
+	str = "e1";
+	ret = of_property_read_string(np, "lantiq,line-interface", &str);
+	if (ret && ret != -EINVAL) {
+		dev_err(pef2256->dev, "%pOF: failed to read lantiq,line-interface\n",
+			np);
+		return ret;
+	}
+	if (!strcmp(str, "e1")) {
+		pef2256->is_e1 = true;
+	} else if (!strcmp(str, "t1j1")) {
+		pef2256->is_e1 = false;
+	} else {
+		dev_err(pef2256->dev, "%pOF: Invalid lantiq,line-interface (%s)\n",
+			np, str);
+		return -EINVAL;
+	}
+	dev_dbg(pef2256->dev, "config: %s line\n", pef2256->is_e1 ? "E1" : "T1/J1");
+
+	pef2256->data_rate = 2048000;
+	ret = of_property_read_u32(np, "lantiq,data-rate-bps", &pef2256->data_rate);
+	if (ret && ret != -EINVAL) {
+		dev_err(pef2256->dev, "%pOF: failed to read lantiq,data-rate-bps\n", np);
+		return ret;
+	}
+	dev_dbg(pef2256->dev, "config: data rate %u bps\n", pef2256->data_rate);
+
+	ret =  pef2256_check_rates(pef2256, pef2256->sysclk_rate, pef2256->data_rate);
+	if (ret)
+		return ret;
+
+	pef2256->is_tx_falling_edge = of_property_read_bool(np, "lantiq,clock-falling-edge");
+	dev_dbg(pef2256->dev, "config: tx on %s edge\n",
+		pef2256->is_tx_falling_edge ? "falling" : "rising");
+
+	pef2256->is_subordinate = of_property_read_bool(np, "lantiq,subordinate");
+	dev_dbg(pef2256->dev, "config: subordinate %s\n",
+		pef2256->is_subordinate ? "on" : "off");
+
+	str = pef2256->is_e1 ? "doubleframe" : "12frame";
+	ret = of_property_read_string(np, "lantiq,frame-format", &str);
+	if (ret && ret != -EINVAL) {
+		dev_err(pef2256->dev, "%pOF: failed to read lantiq,frame-format\n",
+			np);
+		return ret;
+	}
+	if (pef2256->is_e1) {
+		if (!strcmp(str, "doubleframe")) {
+			pef2256->frame_type = PEF2256_FRAME_E1_DOUBLEFRAME;
+		} else if (!strcmp(str, "crc4-multiframe")) {
+			pef2256->frame_type = PEF2256_FRAME_E1_CRC4_MULTIFRAME;
+		} else if (!strcmp(str, "auto-multiframe")) {
+			pef2256->frame_type = PEF2256_FRAME_E1_AUTO_MULTIFRAME;
+		} else {
+			dev_err(pef2256->dev, "%pOF: Invalid lantiq,frame-format (%s)\n",
+				np, str);
+			return -EINVAL;
+		}
+	} else {
+		if (!strcmp(str, "4frame")) {
+			pef2256->frame_type = PEF2256_FRAME_T1J1_4FRAME;
+		} else if (!strcmp(str, "12frame")) {
+			pef2256->frame_type = PEF2256_FRAME_T1J1_12FRAME;
+		} else if (!strcmp(str, "24frame")) {
+			pef2256->frame_type = PEF2256_FRAME_T1J1_24FRAME;
+		} else if (!strcmp(str, "72frame")) {
+			pef2256->frame_type = PEF2256_FRAME_T1J1_72FRAME;
+		} else {
+			dev_err(pef2256->dev, "%pOF: Invalid lantiq,frame-format (%s)\n",
+				np, str);
+			return -EINVAL;
+		}
+	}
+	dev_dbg(pef2256->dev, "config: frame type %d\n", pef2256->frame_type);
+
+	pef2256->channel_phase = 0;
+	ret = of_property_read_u8(np, "lantiq,channel-phase", &pef2256->channel_phase);
+	if (ret && ret != -EINVAL) {
+		dev_err(pef2256->dev, "%pOF: failed to read lantiq,channel-phase\n",
+			np);
+		return ret;
+	}
+	if (pef2256->channel_phase >= pef2256->sysclk_rate / pef2256->data_rate) {
+		dev_err(pef2256->dev, "%pOF: Invalid lantiq,channel-phase %u\n",
+			np, pef2256->channel_phase);
+		return -EINVAL;
+	}
+	dev_dbg(pef2256->dev, "config: channel phase %u\n", pef2256->channel_phase);
+
+	return 0;
+}
+
+static int pef2256_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct pef2256 *pef2256 = pinctrl_dev_get_drvdata(pctldev);
+
+	/* We map 1 group <-> 1 pin */
+	return pef2256->pinctrl.pctrl_desc.npins;
+}
+
+static const char *pef2256_get_group_name(struct pinctrl_dev *pctldev,
+					  unsigned int selector)
+{
+	struct pef2256 *pef2256 = pinctrl_dev_get_drvdata(pctldev);
+
+	/* We map 1 group <-> 1 pin */
+	return pef2256->pinctrl.pctrl_desc.pins[selector].name;
+}
+
+static int pef2256_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector,
+			     const unsigned int **pins,
+			     unsigned int *num_pins)
+{
+	struct pef2256 *pef2256 = pinctrl_dev_get_drvdata(pctldev);
+
+	/* We map 1 group <-> 1 pin */
+	*pins = &pef2256->pinctrl.pctrl_desc.pins[selector].number;
+	*num_pins = 1;
+
+	return 0;
+}
+
+static const struct pinctrl_ops pef2256_pctlops = {
+	.get_groups_count	= pef2256_get_groups_count,
+	.get_group_name		= pef2256_get_group_name,
+	.get_group_pins		= pef2256_get_group_pins,
+	.dt_node_to_map		= pinconf_generic_dt_node_to_map_pin,
+	.dt_free_map		= pinconf_generic_dt_free_map,
+};
+
+static int pef2256_get_functions_count(struct pinctrl_dev *pctldev)
+{
+	struct pef2256 *pef2256 = pinctrl_dev_get_drvdata(pctldev);
+
+	return pef2256->pinctrl.nfunctions;
+}
+
+static const char *pef2256_get_function_name(struct pinctrl_dev *pctldev,
+					     unsigned int selector)
+{
+	struct pef2256 *pef2256 = pinctrl_dev_get_drvdata(pctldev);
+
+	return pef2256->pinctrl.functions[selector].name;
+}
+
+
+static int pef2256_get_function_groups(struct pinctrl_dev *pctldev, unsigned int selector,
+			 const char * const **groups,
+			 unsigned * const num_groups)
+{
+	struct pef2256 *pef2256 = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = pef2256->pinctrl.functions[selector].groups;
+	*num_groups = pef2256->pinctrl.functions[selector].ngroups;
+	return 0;
+}
+
+static int pef2256_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
+			   unsigned int group_selector)
+{
+	struct pef2256 *pef2256 = pinctrl_dev_get_drvdata(pctldev);
+	const struct pef2256_pinreg_desc *pinreg_desc;
+	u8 func_val;
+
+	dev_dbg(pef2256->dev, "set %s to %s function\n",
+		pef2256->pinctrl.pctrl_desc.pins[group_selector].name,
+		pef2256->pinctrl.functions[func_selector].name);
+
+	/* We map 1 group <-> 1 pin */
+	pinreg_desc = pef2256->pinctrl.pctrl_desc.pins[group_selector].drv_data;
+	func_val = pef2256->pinctrl.functions[func_selector].func_val;
+
+	pef2256_clrsetbits8(pef2256, pinreg_desc->offset, pinreg_desc->mask,
+			    func_val & pinreg_desc->mask);
+
+	return 0;
+}
+
+static const struct pinmux_ops pef2256_pmxops = {
+	.get_functions_count	= pef2256_get_functions_count,
+	.get_function_name	= pef2256_get_function_name,
+	.get_function_groups	= pef2256_get_function_groups,
+	.set_mux		= pef2256_set_mux,
+};
+
+#define PEF2256_PINCTRL_PIN(_number, _name, _offset, _mask) { \
+	.number = _number, \
+	.name = _name, \
+	.drv_data = &(struct pef2256_pinreg_desc) { \
+		.offset = _offset, \
+		.mask = _mask, \
+	}, \
+}
+
+static const struct pinctrl_pin_desc pef2256_v12_pins[] = {
+	PEF2256_PINCTRL_PIN(0, "RPA", PEF2256_PC1, PEF2256_12_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(1, "RPB", PEF2256_PC2, PEF2256_12_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(2, "RPC", PEF2256_PC3, PEF2256_12_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(3, "RPD", PEF2256_PC4, PEF2256_12_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(4, "XPA", PEF2256_PC1, PEF2256_12_PC_XPC_MASK),
+	PEF2256_PINCTRL_PIN(5, "XPB", PEF2256_PC2, PEF2256_12_PC_XPC_MASK),
+	PEF2256_PINCTRL_PIN(6, "XPC", PEF2256_PC3, PEF2256_12_PC_XPC_MASK),
+	PEF2256_PINCTRL_PIN(7, "XPD", PEF2256_PC4, PEF2256_12_PC_XPC_MASK),
+};
+
+static const struct pinctrl_pin_desc pef2256_v2x_pins[] = {
+	PEF2256_PINCTRL_PIN(0, "RPA", PEF2256_PC1, PEF2256_2X_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(1, "RPB", PEF2256_PC2, PEF2256_2X_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(2, "RPC", PEF2256_PC3, PEF2256_2X_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(3, "RPD", PEF2256_PC4, PEF2256_2X_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(4, "XPA", PEF2256_PC1, PEF2256_2X_PC_XPC_MASK),
+	PEF2256_PINCTRL_PIN(5, "XPB", PEF2256_PC2, PEF2256_2X_PC_XPC_MASK),
+	PEF2256_PINCTRL_PIN(6, "XPC", PEF2256_PC3, PEF2256_2X_PC_XPC_MASK),
+	PEF2256_PINCTRL_PIN(7, "XPD", PEF2256_PC4, PEF2256_2X_PC_XPC_MASK),
+};
+
+static const char *const pef2256_rp_groups[] = { "RPA", "RPB", "RPC", "RPD" };
+static const char *const pef2256_xp_groups[] = { "XPA", "XPB", "XPC", "XPD" };
+static const char *const pef2256_all_groups[] = { "RPA", "RPB", "RPC", "RPD",
+						  "XPA", "XPB", "XPC", "XPD" };
+
+#define PEF2256_FUNCTION(_name, _func_val, _groups) { \
+	.name = _name, \
+	.groups = _groups, \
+	.ngroups = ARRAY_SIZE(_groups), \
+	.func_val = _func_val, \
+}
+
+static const struct pef2256_function_desc pef2256_v2x_functions[] = {
+	PEF2256_FUNCTION("SYPR",   PEF2256_2X_PC_RPC_SYPR,   pef2256_rp_groups),
+	PEF2256_FUNCTION("RFM",    PEF2256_2X_PC_RPC_RFM,    pef2256_rp_groups),
+	PEF2256_FUNCTION("RFMB",   PEF2256_2X_PC_RPC_RFMB,   pef2256_rp_groups),
+	PEF2256_FUNCTION("RSIGM",  PEF2256_2X_PC_RPC_RSIGM,  pef2256_rp_groups),
+	PEF2256_FUNCTION("RSIG",   PEF2256_2X_PC_RPC_RSIG,   pef2256_rp_groups),
+	PEF2256_FUNCTION("DLR",    PEF2256_2X_PC_RPC_DLR,    pef2256_rp_groups),
+	PEF2256_FUNCTION("FREEZE", PEF2256_2X_PC_RPC_FREEZE, pef2256_rp_groups),
+	PEF2256_FUNCTION("RFSP",   PEF2256_2X_PC_RPC_RFSP,   pef2256_rp_groups),
+	PEF2256_FUNCTION("LOS",    PEF2256_2X_PC_RPC_LOS,    pef2256_rp_groups),
+
+	PEF2256_FUNCTION("SYPX",  PEF2256_2X_PC_XPC_SYPX,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XFMS",  PEF2256_2X_PC_XPC_XFMS,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XSIG",  PEF2256_2X_PC_XPC_XSIG,  pef2256_xp_groups),
+	PEF2256_FUNCTION("TCLK",  PEF2256_2X_PC_XPC_TCLK,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XMFB",  PEF2256_2X_PC_XPC_XMFB,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XSIGM", PEF2256_2X_PC_XPC_XSIGM, pef2256_xp_groups),
+	PEF2256_FUNCTION("DLX",   PEF2256_2X_PC_XPC_DLX,   pef2256_xp_groups),
+	PEF2256_FUNCTION("XCLK",  PEF2256_2X_PC_XPC_XCLK,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XLT",   PEF2256_2X_PC_XPC_XLT,   pef2256_xp_groups),
+
+	PEF2256_FUNCTION("GPI",  PEF2256_2X_PC_RPC_GPI | PEF2256_2X_PC_XPC_GPI,
+			 pef2256_all_groups),
+	PEF2256_FUNCTION("GPOH", PEF2256_2X_PC_RPC_GPOH | PEF2256_2X_PC_XPC_GPOH,
+			 pef2256_all_groups),
+	PEF2256_FUNCTION("GPOL", PEF2256_2X_PC_RPC_GPOL | PEF2256_2X_PC_XPC_GPOL,
+			 pef2256_all_groups),
+};
+
+static const struct pef2256_function_desc pef2256_v12_functions[] = {
+	PEF2256_FUNCTION("SYPR",   PEF2256_12_PC_RPC_SYPR,   pef2256_rp_groups),
+	PEF2256_FUNCTION("RFM",    PEF2256_12_PC_RPC_RFM,    pef2256_rp_groups),
+	PEF2256_FUNCTION("RFMB",   PEF2256_12_PC_RPC_RFMB,   pef2256_rp_groups),
+	PEF2256_FUNCTION("RSIGM",  PEF2256_12_PC_RPC_RSIGM,  pef2256_rp_groups),
+	PEF2256_FUNCTION("RSIG",   PEF2256_12_PC_RPC_RSIG,   pef2256_rp_groups),
+	PEF2256_FUNCTION("DLR",    PEF2256_12_PC_RPC_DLR,    pef2256_rp_groups),
+	PEF2256_FUNCTION("FREEZE", PEF2256_12_PC_RPC_FREEZE, pef2256_rp_groups),
+	PEF2256_FUNCTION("RFSP",   PEF2256_12_PC_RPC_RFSP,   pef2256_rp_groups),
+
+	PEF2256_FUNCTION("SYPX",  PEF2256_12_PC_XPC_SYPX,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XFMS",  PEF2256_12_PC_XPC_XFMS,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XSIG",  PEF2256_12_PC_XPC_XSIG,  pef2256_xp_groups),
+	PEF2256_FUNCTION("TCLK",  PEF2256_12_PC_XPC_TCLK,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XMFB",  PEF2256_12_PC_XPC_XMFB,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XSIGM", PEF2256_12_PC_XPC_XSIGM, pef2256_xp_groups),
+	PEF2256_FUNCTION("DLX",   PEF2256_12_PC_XPC_DLX,   pef2256_xp_groups),
+	PEF2256_FUNCTION("XCLK",  PEF2256_12_PC_XPC_XCLK,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XLT",   PEF2256_12_PC_XPC_XLT,   pef2256_xp_groups),
+};
+
+
+static int pef2256_register_pinctrl(struct pef2256 *pef2256)
+{
+	struct pinctrl_dev	*pctrl;
+
+	pef2256->pinctrl.pctrl_desc.name    = dev_name(pef2256->dev);
+	pef2256->pinctrl.pctrl_desc.owner   = THIS_MODULE;
+	pef2256->pinctrl.pctrl_desc.pctlops = &pef2256_pctlops;
+	pef2256->pinctrl.pctrl_desc.pmxops  = &pef2256_pmxops;
+	if (pef2256->version == PEF2256_VERSION_1_2) {
+		pef2256->pinctrl.pctrl_desc.pins  = pef2256_v12_pins;
+		pef2256->pinctrl.pctrl_desc.npins = ARRAY_SIZE(pef2256_v12_pins);
+		pef2256->pinctrl.functions  = pef2256_v12_functions;
+		pef2256->pinctrl.nfunctions = ARRAY_SIZE(pef2256_v12_functions);
+	} else {
+		pef2256->pinctrl.pctrl_desc.pins  = pef2256_v2x_pins;
+		pef2256->pinctrl.pctrl_desc.npins = ARRAY_SIZE(pef2256_v2x_pins);
+		pef2256->pinctrl.functions  = pef2256_v2x_functions;
+		pef2256->pinctrl.nfunctions = ARRAY_SIZE(pef2256_v2x_functions);
+	}
+
+	pctrl = devm_pinctrl_register(pef2256->dev, &pef2256->pinctrl.pctrl_desc, pef2256);
+	if (IS_ERR(pctrl)) {
+		dev_err(pef2256->dev, "pinctrl driver registration failed\n");
+		return PTR_ERR(pctrl);
+	}
+
+	return 0;
+}
+
+static void pef2256_reset_pinmux(struct pef2256 *pef2256)
+{
+	u8 val;
+	/*
+	 * Reset values cannot be used.
+	 * They define the SYPR/SYPX pin mux for all the RPx and XPx pins and
+	 * Only one pin can be muxed to SYPR and one pin can be muxed to SYPX.
+	 * Choose here an other reset value.
+	 */
+	if (pef2256->version == PEF2256_VERSION_1_2)
+		val = PEF2256_12_PC_XPC_XCLK | PEF2256_12_PC_RPC_RFSP;
+	else
+		val = PEF2256_2X_PC_XPC_GPI | PEF2256_2X_PC_RPC_GPI;
+
+	pef2256_write8(pef2256, PEF2256_PC1, val);
+	pef2256_write8(pef2256, PEF2256_PC2, val);
+	pef2256_write8(pef2256, PEF2256_PC3, val);
+	pef2256_write8(pef2256, PEF2256_PC4, val);
+}
+
+static ssize_t subordinate_show(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	struct pef2256 *pef2256 = dev_get_drvdata(dev);
+
+	return sysfs_emit(buf, "%d\n", pef2256->is_subordinate);
+}
+
+static ssize_t subordinate_store(struct device *dev, struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct pef2256 *pef2256 = dev_get_drvdata(dev);
+	int ret;
+
+	if (strtobool(buf, &pef2256->is_subordinate) < 0)
+		return -EINVAL;
+
+	ret = pef2256_setup(pef2256);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(subordinate);
+
+static const struct attribute_group pef2256_attribute_group = {
+	.attrs = (struct attribute *[]) {
+		&dev_attr_subordinate.attr,
+		NULL,
+	},
+};
+
+static int pef2256_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	unsigned long sclkr_rate, sclkx_rate;
+	struct pef2256 *pef2256;
+	int ret;
+	int irq;
+
+	pef2256 = devm_kzalloc(&pdev->dev, sizeof(*pef2256), GFP_KERNEL);
+	if (!pef2256)
+		return -ENOMEM;
+
+	pef2256->dev = &pdev->dev;
+	ATOMIC_INIT_NOTIFIER_HEAD(&pef2256->event_notifier_list);
+
+	pef2256->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(pef2256->regs))
+		return PTR_ERR(pef2256->regs);
+
+	pef2256->mclk = devm_clk_get_enabled(&pdev->dev, "mclk");
+	if (IS_ERR(pef2256->mclk))
+		return PTR_ERR(pef2256->mclk);
+	dev_dbg(pef2256->dev, "mclk %lu Hz\n", clk_get_rate(pef2256->mclk));
+
+	pef2256->sclkr = devm_clk_get_enabled(&pdev->dev, "sclkr");
+	if (IS_ERR(pef2256->sclkr))
+		return PTR_ERR(pef2256->sclkr);
+
+	pef2256->sclkx = devm_clk_get_enabled(&pdev->dev, "sclkx");
+	if (IS_ERR(pef2256->sclkx))
+		return PTR_ERR(pef2256->sclkx);
+
+	/*
+	 * Both SCLKR (receive) and SCLKX (transmit) must have the same rate,
+	 * stored as sysclk_rate.
+	 * The exact value will be checked at pef2256_check_rates()
+	 */
+	sclkr_rate = clk_get_rate(pef2256->sclkr);
+	sclkx_rate = clk_get_rate(pef2256->sclkx);
+	dev_dbg(pef2256->dev, "sclkr %lu Hz\n", sclkr_rate);
+	dev_dbg(pef2256->dev, "sclkx %lu Hz\n", sclkx_rate);
+	if (sclkr_rate != sclkx_rate) {
+		dev_err(pef2256->dev, "clk rate mismatch. sclkr %lu Hz, sclkx %lu Hz\n",
+			sclkr_rate, sclkx_rate);
+		return -EINVAL;
+	}
+	pef2256->sysclk_rate = sclkr_rate;
+
+	/* Reset the component. The MCLK clock must be active during reset */
+	pef2256->reset_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(pef2256->reset_gpio))
+		return PTR_ERR(pef2256->reset_gpio);
+	if (pef2256->reset_gpio) {
+		gpiod_set_value_cansleep(pef2256->reset_gpio, 1);
+		udelay(10);
+		gpiod_set_value_cansleep(pef2256->reset_gpio, 0);
+		udelay(10);
+	}
+
+	pef2256->version = pef2256_get_version(pef2256);
+	if (pef2256->version == PEF2256_VERSION_UNKNOWN)
+		return -ENODEV;
+
+	ret = pef2556_of_parse(pef2256, np);
+	if (ret)
+		return ret;
+
+	/* Disable interrupts */
+	pef2256_write8(pef2256, PEF2256_IMR0, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR1, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR2, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR3, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR4, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR5, 0xff);
+
+	/* Clear any pending interrupts */
+	pef2256_read8(pef2256, PEF2256_ISR0);
+	pef2256_read8(pef2256, PEF2256_ISR1);
+	pef2256_read8(pef2256, PEF2256_ISR2);
+	pef2256_read8(pef2256, PEF2256_ISR3);
+	pef2256_read8(pef2256, PEF2256_ISR4);
+	pef2256_read8(pef2256, PEF2256_ISR5);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+	ret = devm_request_irq(pef2256->dev, irq, pef2256_irq_handler, 0, "pef2256", pef2256);
+	if (ret < 0)
+		return ret;
+
+	pef2256_reset_pinmux(pef2256);
+	ret = pef2256_register_pinctrl(pef2256);
+	if (ret)
+		return ret;
+
+	/*
+	 * We are going to reset the E1 lines during setup() call and the ISR2
+	 * interrupt used to detect the carrier state changed is masked.
+	 * It is time to initialize our internal carrier state flag.
+	 */
+	atomic_set(&pef2256->carrier, 0);
+
+	ret = pef2256_setup(pef2256);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, pef2256);
+
+	ret = sysfs_create_group(&pef2256->dev->kobj, &pef2256_attribute_group);
+	if (ret < 0) {
+		dev_err(pef2256->dev, "sysfs registration failed (%d)\n", ret);
+		platform_set_drvdata(pdev, NULL);
+		return ret;
+	}
+
+	ret = devm_of_platform_populate(pef2256->dev);
+	if (ret < 0) {
+		dev_err(pef2256->dev, "platform populate failed (%d)\n", ret);
+		platform_set_drvdata(pdev, NULL);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int pef2256_remove(struct platform_device *pdev)
+{
+	struct pef2256 *pef2256 = platform_get_drvdata(pdev);
+
+	/* Disable interrupts */
+	pef2256_write8(pef2256, PEF2256_IMR0, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR1, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR2, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR3, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR4, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR5, 0xff);
+
+	sysfs_remove_group(&pef2256->dev->kobj, &pef2256_attribute_group);
+
+	return 0;
+}
+
+static const struct of_device_id pef2256_id_table[] = {
+	{ .compatible = "lantiq,pef2256" },
+	{} /* sentinel */
+};
+MODULE_DEVICE_TABLE(of, pef2256_id_table);
+
+static struct platform_driver pef2256_driver = {
+	.driver = {
+		.name = "lantiq-pef2256",
+		.of_match_table = of_match_ptr(pef2256_id_table),
+	},
+	.probe = pef2256_probe,
+	.remove = pef2256_remove,
+};
+module_platform_driver(pef2256_driver);
+
+int pef2256_register_event_notifier(struct pef2256 *pef2256, struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&pef2256->event_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(pef2256_register_event_notifier);
+
+int pef2256_unregister_event_notifier(struct pef2256 *pef2256, struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(&pef2256->event_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(pef2256_unregister_event_notifier);
+
+bool pef2256_get_carrier(struct pef2256 *pef2256)
+{
+	return !!atomic_read(&pef2256->carrier);
+}
+EXPORT_SYMBOL_GPL(pef2256_get_carrier);
+
+MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
+MODULE_DESCRIPTION("PEF2256 driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/pef2256.h b/include/linux/mfd/pef2256.h
new file mode 100644
index 000000000000..0c0afcefa3ef
--- /dev/null
+++ b/include/linux/mfd/pef2256.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * PEF2256 management
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina <herve.codina@bootlin.com>
+ */
+#ifndef __PEF2256_H__
+#define __PEF2256_H__
+
+#include <linux/types.h>
+
+struct pef2256;
+struct notifier_block;
+
+enum pef2256_event {
+	PEF2256_EVENT_CARRIER, /* Carrier state changed */
+};
+
+/* The nb.notifier_call function registered must not sleep */
+int pef2256_register_event_notifier(struct pef2256 *pef2256, struct notifier_block *nb);
+int pef2256_unregister_event_notifier(struct pef2256 *pef2256, struct notifier_block *nb);
+
+/* Retrieve carrier state. true: carrier on, false: carrier off */
+bool pef2256_get_carrier(struct pef2256 *pef2256);
+
+#endif /* __PEF2256_H__ */
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer
  2023-03-22 13:46 [PATCH v3 0/6] Add the Lantiq PEF2256 audio support Herve Codina
  2023-03-22 13:46 ` [PATCH v3 1/6] dt-bindings: mfd: Add the Lantiq PEF2256 E1/T1/J1 framer Herve Codina
  2023-03-22 13:46 ` Herve Codina via Alsa-devel
@ 2023-03-22 13:46 ` Herve Codina via Alsa-devel
  2023-03-26 18:22   ` kernel test robot
  2023-03-22 13:46 ` Herve Codina
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 29+ messages in thread
From: Herve Codina via Alsa-devel @ 2023-03-22 13:46 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni


[-- Attachment #0: Type: message/rfc822, Size: 54461 bytes --]

From: Herve Codina <herve.codina@bootlin.com>
To: Herve Codina <herve.codina@bootlin.com>, Lee Jones <lee@kernel.org>, Rob Herring <robh+dt@kernel.org>, Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>, Liam Girdwood <lgirdwood@gmail.com>, Mark Brown <broonie@kernel.org>, Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>
Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, alsa-devel@alsa-project.org, Christophe Leroy <christophe.leroy@csgroup.eu>, Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Subject: [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer
Date: Wed, 22 Mar 2023 14:46:50 +0100
Message-ID: <20230322134654.219957-3-herve.codina@bootlin.com>

The Lantiq PEF2256 is a framer and line interface component designed to
fulfill all required interfacing between an analog E1/T1/J1 line and the
digital PCM system highway/H.100 bus.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 drivers/mfd/Kconfig         |   16 +
 drivers/mfd/Makefile        |    1 +
 drivers/mfd/pef2256.c       | 1355 +++++++++++++++++++++++++++++++++++
 include/linux/mfd/pef2256.h |   28 +
 4 files changed, 1400 insertions(+)
 create mode 100644 drivers/mfd/pef2256.c
 create mode 100644 include/linux/mfd/pef2256.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index fcc141e067b9..174c6fe3e539 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1063,6 +1063,22 @@ config PCF50633_GPIO
 	  Say yes here if you want to include support GPIO for pins on
 	  the PCF50633 chip.
 
+config MFD_PEF2256
+	tristate "Lantiq PEF2256 (FALC56) framer"
+	select PINCTRL
+	select PINMUX
+	select GENERIC_PINCONF
+	help
+	  This option enables support for the Lantiq PEF2256 framer, also known
+	  as FALC56. This framer and its line interface component is designed
+	  to fulfill all required interfacing between analog E1/T1/J1 lines and
+	  the digital PCM system highway.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pef2256.
+
 config MFD_PM8XXX
 	tristate "Qualcomm PM8xxx PMIC chips driver"
 	depends on (ARM || HEXAGON || COMPILE_TEST)
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 2f6c89d1e277..b2bb6e6a141c 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -195,6 +195,7 @@ obj-$(CONFIG_MFD_SI476X_CORE)	+= si476x-core.o
 
 obj-$(CONFIG_MFD_CS5535)	+= cs5535-mfd.o
 obj-$(CONFIG_MFD_OMAP_USB_HOST)	+= omap-usb-host.o omap-usb-tll.o
+obj-$(CONFIG_MFD_PEF2256)	+= pef2256.o
 obj-$(CONFIG_MFD_PM8XXX) 	+= qcom-pm8xxx.o ssbi.o
 obj-$(CONFIG_MFD_QCOM_RPM)	+= qcom_rpm.o
 obj-$(CONFIG_MFD_SPMI_PMIC)	+= qcom-spmi-pmic.o
diff --git a/drivers/mfd/pef2256.c b/drivers/mfd/pef2256.c
new file mode 100644
index 000000000000..a710b736ec95
--- /dev/null
+++ b/drivers/mfd/pef2256.c
@@ -0,0 +1,1355 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PEF2256 also known as FALC56 driver
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina <herve.codina@bootlin.com>
+ */
+
+#include <linux/mfd/pef2256.h>
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define PEF2256_CMDR		0x02 /* Command Register */
+#define   PEF2256_CMDR_RRES	  BIT(6)
+#define   PEF2256_CMDR_XRES	  BIT(4)
+#define   PEF2256_CMDR_SRES	  BIT(0)
+#define PEF2256_IMR0	        0x14 /* Interrupt Mask Register 0 */
+#define PEF2256_IMR1	        0x15 /* Interrupt Mask Register 1 */
+#define PEF2256_IMR2	        0x16 /* Interrupt Mask Register 2 */
+#define PEF2256_IMR3	        0x17 /* Interrupt Mask Register 3 */
+#define PEF2256_IMR4	        0x18 /* Interrupt Mask Register 4 */
+#define PEF2256_IMR5	        0x19 /* Interrupt Mask Register 5 */
+#define PEF2256_FMR0	        0x1C /* Framer Mode Register 0 */
+#define   PEF2256_FMR0_XC_MASK	  (0x3 << 6)
+#define     PEF2256_FMR0_XC_NRZ	    (0x0 << 6)
+#define     PEF2256_FMR0_XC_CMI	    (0x1 << 6)
+#define     PEF2256_FMR0_XC_AMI	    (0x2 << 6)
+#define     PEF2256_FMR0_XC_HDB3    (0x3 << 6)
+#define   PEF2256_FMR0_RC_MASK	  (0x3 << 4)
+#define     PEF2256_FMR0_RC_NRZ	    (0x0 << 4)
+#define     PEF2256_FMR0_RC_CMI	    (0x1 << 4)
+#define     PEF2256_FMR0_RC_AMI	    (0x2 << 4)
+#define     PEF2256_FMR0_RC_HDB3    (0x3 << 4)
+#define PEF2256_FMR1	        0x1D /* Framer Mode Register 1 */
+#define   PEF2256_FMR1_XFS	  BIT(3)
+#define   PEF2256_FMR1_ECM	  BIT(2)
+/* SSD is defined on 2 bits. The other bit is on SIC1 register */
+#define   PEF2256_FMR1_SSD_MASK   BIT(1)
+#define     PEF2256_FMR1_SSD_2048   0
+#define     PEF2256_FMR1_SSD_4096   BIT(1)
+#define     PEF2256_FMR1_SSD_8192   0
+#define     PEF2256_FMR1_SSD_16384  BIT(1)
+#define PEF2256_FMR2	        0x1E /* Framer Mode Register 2 */
+#define   PEF2256_FMR2_RFS_MASK	  (0x3 << 6)
+#define     PEF2256_FMR2_RFS_DOUBLEFRAME      (0x0 << 6)
+#define     PEF2256_FMR2_RFS_CRC4_MULTIFRAME  (0x2 << 6)
+#define     PEF2256_FMR2_RFS_AUTO_MULTIFRAME  (0x3 << 6)
+#define   PEF2256_FMR2_AXRA	  BIT(1)
+#define PEF2256_LOOP	        0x1F /* Channel Loop-Back */
+#define PEF2256_XSW	        0x20 /* Transmit Service Word */
+#define   PEF2256_XSW_XSIS	  BIT(7)
+#define   PEF2256_XSW_XTM	  BIT(6)
+#define   PEF2256_XSW_XY_MASK	  (0x1f << 0)
+#define     PEF2256_XSW_XY(_v)	    ((_v) & 0x1f)
+#define PEF2256_XSP	        0x21 /* Transmit Spare Bits */
+#define   PEF2256_XSP_XSIF	  BIT(2)
+#define PEF2256_XC0	        0x22 /* Transmit Control 0 */
+#define PEF2256_XC1	        0x23 /* Transmit Control 1 */
+#define PEF2256_RC0	        0x24 /* Receive Control 0 */
+#define   PEF2256_RC0_SWD	  BIT(7)
+#define   PEF2256_RC0_ASY4	  BIT(6)
+#define PEF2256_RC1	        0x25 /* Receive Control 1 */
+#define PEF2256_XPM0	        0x26 /* Transmit Pulse Mask 0 */
+#define PEF2256_XPM1	        0x27 /* Transmit Pulse Mask 1 */
+#define PEF2256_XPM2	        0x28 /* Transmit Pulse Mask 2 */
+#define   PEF2256_XPM2_XLT	  BIT(6)
+#define PEF2256_TSWM	        0x29 /* Transparent Service Word Mask */
+#define PEF2256_LIM0	        0x36 /* Line Interface Mode 0 */
+#define   PEF2256_2X_LIM0_BIT3	  BIT(3) /* v2.x, described as a forced '1' bit */
+#define   PEF2256_LIM0_MAS	  BIT(0)
+#define PEF2256_LIM1	        0x37 /* Line Interface Mode 1 */
+#define   PEF2256_12_LIM1_RIL_MASK   (0x7 << 4)
+#define     PEF2256_12_LIM1_RIL_910    (0x0 << 4)
+#define     PEF2256_12_LIM1_RIL_740    (0x1 << 4)
+#define     PEF2256_12_LIM1_RIL_590    (0x2 << 4)
+#define     PEF2256_12_LIM1_RIL_420    (0x3 << 4)
+#define     PEF2256_12_LIM1_RIL_320    (0x4 << 4)
+#define     PEF2256_12_LIM1_RIL_210    (0x5 << 4)
+#define     PEF2256_12_LIM1_RIL_160    (0x6 << 4)
+#define     PEF2256_12_LIM1_RIL_100    (0x7 << 4)
+#define   PEF2256_2X_LIM1_RIL_MASK   (0x7 << 4)
+#define     PEF2256_2X_LIM1_RIL_2250   (0x0 << 4)
+#define     PEF2256_2X_LIM1_RIL_1100   (0x1 << 4)
+#define     PEF2256_2X_LIM1_RIL_600    (0x2 << 4)
+#define     PEF2256_2X_LIM1_RIL_350    (0x3 << 4)
+#define     PEF2256_2X_LIM1_RIL_210    (0x4 << 4)
+#define     PEF2256_2X_LIM1_RIL_140    (0x5 << 4)
+#define     PEF2256_2X_LIM1_RIL_100    (0x6 << 4)
+#define     PEF2256_2X_LIM1_RIL_50     (0x7 << 4)
+#define PEF2256_PCD	        0x38 /* Pulse Count Detection */
+#define PEF2256_PCR	        0x39 /* Pulse Count Recovery */
+#define PEF2256_LIM2	        0x3A /* Line Interface Mode 2 */
+#define   PEF2256_LIM2_SLT_MASK	  (0x3 << 4)
+#define     PEF2256_LIM2_SLT_THR55  (0x0 << 4)
+#define     PEF2256_LIM2_SLT_THR67  (0x1 << 4)
+#define     PEF2256_LIM2_SLT_THR50  (0x2 << 4)
+#define     PEF2256_LIM2_SLT_THR45  (0x3 << 4)
+#define   PEF2256_LIM2_ELT	  BIT(2)
+#define PEF2256_SIC1	        0x3E /* System Interface Control 1 */
+#define   PEF2256_SIC1_SSC_MASK   (BIT(7) |  BIT(3))
+#define     PEF2256_SIC1_SSC_2048   (0)
+#define     PEF2256_SIC1_SSC_4096   BIT(3)
+#define     PEF2256_SIC1_SSC_8192   BIT(7)
+#define     PEF2256_SIC1_SSC_16384  (BIT(7) |  BIT(3))
+/* SSD is defined on 2 bits. The other bit is on FMR1 register */
+#define   PEF2256_SIC1_SSD_MASK   BIT(6)
+#define     PEF2256_SIC1_SSD_2048   0
+#define     PEF2256_SIC1_SSD_4096   0
+#define     PEF2256_SIC1_SSD_8192   BIT(6)
+#define     PEF2256_SIC1_SSD_16384  BIT(6)
+#define   PEF2256_SIC1_RBS_MASK	  (0x3 << 4)
+#define     PEF2256_SIC1_RBS_2FRAMES (0x0 << 4)
+#define     PEF2256_SIC1_RBS_1FRAME  (0x1 << 4)
+#define     PEF2256_SIC1_RBS_96BITS  (0x2 << 4)
+#define     PEF2256_SIC1_RBS_BYPASS  (0x3 << 4)
+#define   PEF2256_SIC1_XBS_MASK	  (0x3 << 0)
+#define     PEF2256_SIC1_XBS_BYPASS  (0x0 << 0)
+#define     PEF2256_SIC1_XBS_1FRAME  (0x1 << 0)
+#define     PEF2256_SIC1_XBS_2FRAMES (0x2 << 0)
+#define     PEF2256_SIC1_XBS_96BITS  (0x3 << 0)
+#define PEF2256_SIC2	        0x3F /* System Interface Control 2 */
+#define   PEF2256_SIC2_SICS_MASK       (0x7 << 1)
+#define     PEF2256_SIC2_SICS(_v)        ((_v) << 1)
+#define PEF2256_SIC3	        0x40 /* System Interface Control 3 */
+#define   PEF2256_SIC3_RTRI	  BIT(5)
+#define   PEF2256_SIC3_RESX	  BIT(3)
+#define   PEF2256_SIC3_RESR	  BIT(2)
+#define PEF2256_CMR1	        0x44 /* Clock Mode Register 1 */
+#define   PEF2256_CMR1_RS_MASK	  (0x3 << 4)
+#define     PEF2256_CMR1_RS_DPLL	   (0x0 << 4)
+#define     PEF2256_CMR1_RS_DPLL_LOS_HIGH  (0x1 << 4)
+#define     PEF2256_CMR1_RS_DCOR_2048	   (0x2 << 4)
+#define     PEF2256_CMR1_RS_DCOR_8192	   (0x3 << 4)
+#define   PEF2256_CMR1_DCS	  BIT(3)
+#define PEF2256_CMR2	        0x45 /* Clock Mode Register 2 */
+#define   PEF2256_CMR2_DCOXC	  BIT(5)
+#define PEF2256_GCR	        0x46 /* Global Configuration Register */
+#define   PEF2256_GCR_SCI	  BIT(6)
+#define   PEF2256_GCR_ECMC	  BIT(4)
+#define PEF2256_PC1	        0x80 /* Port Configuration 1 */
+#define PEF2256_PC2	        0x81 /* Port Configuration 2 */
+#define PEF2256_PC3	        0x82 /* Port Configuration 3 */
+#define PEF2256_PC4	        0x83 /* Port Configuration 4 */
+#define   PEF2256_12_PC_RPC_MASK  (0x7 << 4)
+#define     PEF2256_12_PC_RPC_SYPR	(0x0 << 4)
+#define     PEF2256_12_PC_RPC_RFM	(0x1 << 4)
+#define     PEF2256_12_PC_RPC_RFMB	(0x2 << 4)
+#define     PEF2256_12_PC_RPC_RSIGM	(0x3 << 4)
+#define     PEF2256_12_PC_RPC_RSIG	(0x4 << 4)
+#define     PEF2256_12_PC_RPC_DLR	(0x5 << 4)
+#define     PEF2256_12_PC_RPC_FREEZE	(0x6 << 4)
+#define     PEF2256_12_PC_RPC_RFSP	(0x7 << 4)
+#define   PEF2256_12_PC_XPC_MASK  (0xf << 0)
+#define     PEF2256_12_PC_XPC_SYPX	(0x0 << 0)
+#define     PEF2256_12_PC_XPC_XFMS	(0x1 << 0)
+#define     PEF2256_12_PC_XPC_XSIG	(0x2 << 0)
+#define     PEF2256_12_PC_XPC_TCLK	(0x3 << 0)
+#define     PEF2256_12_PC_XPC_XMFB	(0x4 << 0)
+#define     PEF2256_12_PC_XPC_XSIGM	(0x5 << 0)
+#define     PEF2256_12_PC_XPC_DLX	(0x6 << 0)
+#define     PEF2256_12_PC_XPC_XCLK	(0x7 << 0)
+#define     PEF2256_12_PC_XPC_XLT	(0x8 << 0)
+#define   PEF2256_2X_PC_RPC_MASK  (0xf << 4)
+#define     PEF2256_2X_PC_RPC_SYPR	(0x0 << 4)
+#define     PEF2256_2X_PC_RPC_RFM	(0x1 << 4)
+#define     PEF2256_2X_PC_RPC_RFMB	(0x2 << 4)
+#define     PEF2256_2X_PC_RPC_RSIGM	(0x3 << 4)
+#define     PEF2256_2X_PC_RPC_RSIG	(0x4 << 4)
+#define     PEF2256_2X_PC_RPC_DLR	(0x5 << 4)
+#define     PEF2256_2X_PC_RPC_FREEZE	(0x6 << 4)
+#define     PEF2256_2X_PC_RPC_RFSP	(0x7 << 4)
+#define     PEF2256_2X_PC_RPC_GPI	(0x9 << 4)
+#define     PEF2256_2X_PC_RPC_GPOH	(0xa << 4)
+#define     PEF2256_2X_PC_RPC_GPOL	(0xb << 4)
+#define     PEF2256_2X_PC_RPC_LOS	(0xc << 4)
+#define   PEF2256_2X_PC_XPC_MASK  (0xf << 0)
+#define     PEF2256_2X_PC_XPC_SYPX	(0x0 << 0)
+#define     PEF2256_2X_PC_XPC_XFMS	(0x1 << 0)
+#define     PEF2256_2X_PC_XPC_XSIG	(0x2 << 0)
+#define     PEF2256_2X_PC_XPC_TCLK	(0x3 << 0)
+#define     PEF2256_2X_PC_XPC_XMFB	(0x4 << 0)
+#define     PEF2256_2X_PC_XPC_XSIGM	(0x5 << 0)
+#define     PEF2256_2X_PC_XPC_DLX	(0x6 << 0)
+#define     PEF2256_2X_PC_XPC_XCLK	(0x7 << 0)
+#define     PEF2256_2X_PC_XPC_XLT	(0x8 << 0)
+#define     PEF2256_2X_PC_XPC_GPI	(0x9 << 0)
+#define     PEF2256_2X_PC_XPC_GPOH	(0xa << 0)
+#define     PEF2256_2X_PC_XPC_GPOL	(0xb << 0)
+#define PEF2256_PC5	        0x84 /* Port Configuration 5 */
+#define   PEF2256_PC5_CRP         BIT(0)
+#define PEF2256_GPC1	        0x85 /* Global Port Configuration 1 */
+#define   PEF2256_GPC1_CSFP_MASK	  (0x3 << 5)
+#define   PEF2256_GPC1_CSFP_SEC_IN_HIGH   (0x0 << 5)
+#define   PEF2256_GPC1_CSFP_SEC_OUT_HIGH  (0x1 << 5)
+#define   PEF2256_GPC1_CSFP_FSC_OUT_HIGH  (0x2 << 5)
+#define   PEF2256_GPC1_CSFP_FSC_OUT_LOW   (0x3 << 5)
+#define PEF2256_PC6	        0x86 /* Port Configuration 6 */
+#define PEF2256_GCM(_n)         (0x92 + (_n) - 1) /* Global Counter Mode n=1..8 */
+#define PEF2256_GCM1	        0x92 /* Global Counter Mode 1 */
+#define PEF2256_GCM2	        0x93 /* Global Counter Mode 2 */
+#define PEF2256_GCM3	        0x94 /* Global Counter Mode 3 */
+#define PEF2256_GCM4	        0x95 /* Global Counter Mode 4 */
+#define PEF2256_GCM5	        0x96 /* Global Counter Mode 5 */
+#define PEF2256_GCM6	        0x97 /* Global Counter Mode 6 */
+#define PEF2256_GCM7	        0x98 /* Global Counter Mode 7 */
+#define PEF2256_GCM8	        0x99 /* Global Counter Mode 8 */
+
+#define PEF2256_VSTR	0x4A /* Version Status Register */
+#define   PEF2256_VSTR_VERSION_12  0x00
+#define   PEF2256_VSTR_VERSION_21  0x10
+#define   PEF2256_VSTR_VERSION_2x  0x05
+#define PEF2256_FRS0	0x4C /* Framer Receive Status 0 */
+#define   PEF2256_FRS0_LOS	BIT(7)
+#define   PEF2256_FRS0_AIS	BIT(6)
+#define PEF2256_ISR(_n) (0x68 + (_n)) /* Interrupt Status Register (n=0..5) */
+#define PEF2256_ISR0	0x68 /* Interrupt Status Register 0 */
+#define PEF2256_ISR1	0x69 /* Interrupt Status Register 1 */
+#define PEF2256_ISR2	0x6A /* Interrupt Status Register 2 */
+#define PEF2256_ISR3	0x6B /* Interrupt Status Register 3 */
+#define PEF2256_ISR4	0x6C /* Interrupt Status Register 4 */
+#define PEF2256_ISR5	0x6D /* Interrupt Status Register 5 */
+#define PEF2256_GIS	0x6E /* Global Interrupt Status */
+#define   PEF2256_GIS_ISR(_n)	(1 << (_n))
+#define PEF2256_WID	0xEC /* Wafer Identification Register */
+#define   PEF2256_12_WID_MASK        0x03
+#define     PEF2256_12_WID_VERSION_12  0x03
+#define   PEF2256_2X_WID_MASK        0xc0
+#define     PEF2256_2X_WID_VERSION_21  0x00
+#define     PEF2256_2X_WID_VERSION_22  0x40
+
+/* IMR2/ISR2 Interrupts */
+#define PEF2256_INT2_AIS  BIT(3)
+#define PEF2256_INT2_LOS  BIT(2)
+
+enum pef2256_version {
+	PEF2256_VERSION_UNKNOWN,
+	PEF2256_VERSION_1_2,
+	PEF2256_VERSION_2_1,
+	PEF2256_VERSION_2_2,
+};
+
+enum pef2256_frame_type {
+	PEF2256_FRAME_E1_DOUBLEFRAME,
+	PEF2256_FRAME_E1_CRC4_MULTIFRAME,
+	PEF2256_FRAME_E1_AUTO_MULTIFRAME,
+	PEF2256_FRAME_T1J1_4FRAME,
+	PEF2256_FRAME_T1J1_12FRAME,
+	PEF2256_FRAME_T1J1_24FRAME,
+	PEF2256_FRAME_T1J1_72FRAME,
+};
+
+struct pef2256_pinreg_desc {
+	int offset;
+	u8 mask;
+};
+
+struct pef2256_function_desc {
+	const char *name;
+	const char * const*groups;
+	unsigned int ngroups;
+	u8 func_val;
+};
+
+struct pef2256 {
+	struct device *dev;
+	void *__iomem regs;
+	enum pef2256_version version;
+	struct clk *mclk;
+	struct clk *sclkr;
+	struct clk *sclkx;
+	struct gpio_desc *reset_gpio;
+	struct {
+		struct pinctrl_desc pctrl_desc;
+		const struct pef2256_function_desc *functions;
+		unsigned int nfunctions;
+	} pinctrl;
+	bool is_e1;
+	unsigned long sysclk_rate;
+	u32 data_rate;
+	bool is_tx_falling_edge;
+	bool is_subordinate;
+	enum pef2256_frame_type frame_type;
+	u8 channel_phase;
+	atomic_t carrier;
+	struct atomic_notifier_head event_notifier_list;
+};
+
+static inline u8 pef2256_read8(struct pef2256 *pef2256, int offset)
+{
+	return ioread8(pef2256->regs + offset);
+}
+
+static inline void pef2256_write8(struct pef2256 *pef2256, int offset, u8 val)
+{
+	iowrite8(val, pef2256->regs + offset);
+}
+
+static inline void pef2256_clrbits8(struct pef2256 *pef2256, int offset, u8 clr)
+{
+	pef2256_write8(pef2256, offset, pef2256_read8(pef2256, offset) & ~clr);
+}
+
+static inline void pef2256_setbits8(struct pef2256 *pef2256, int offset, u8 set)
+{
+	pef2256_write8(pef2256, offset, pef2256_read8(pef2256, offset) | set);
+}
+
+
+static inline void pef2256_clrsetbits8(struct pef2256 *pef2256, int offset, u8 clr, u8 set)
+{
+	u8 v;
+
+	v = pef2256_read8(pef2256, offset);
+	v &= ~clr;
+	v |= set;
+	pef2256_write8(pef2256, offset, v);
+}
+
+static enum pef2256_version pef2256_get_version(struct pef2256 *pef2256)
+{
+	enum pef2256_version version = PEF2256_VERSION_UNKNOWN;
+	const char *version_txt;
+	u8 vstr, wid;
+
+	vstr = pef2256_read8(pef2256, PEF2256_VSTR);
+	wid = pef2256_read8(pef2256, PEF2256_WID);
+
+	switch (vstr) {
+	case PEF2256_VSTR_VERSION_12:
+		if ((wid & PEF2256_12_WID_MASK) == PEF2256_12_WID_VERSION_12) {
+			version_txt = "1.2";
+			version = PEF2256_VERSION_1_2;
+		}
+		break;
+	case PEF2256_VSTR_VERSION_2x:
+		switch (wid & PEF2256_2X_WID_MASK) {
+		case PEF2256_2X_WID_VERSION_21:
+			version_txt = "2.1 (2.x)";
+			version = PEF2256_VERSION_2_1;
+			break;
+		case PEF2256_2X_WID_VERSION_22:
+			version_txt = "2.2 (2.x)";
+			version = PEF2256_VERSION_2_2;
+			break;
+		}
+		break;
+	case PEF2256_VSTR_VERSION_21:
+		version_txt = "2.1";
+		version = PEF2256_VERSION_2_1;
+		break;
+	}
+
+	if (version == PEF2256_VERSION_UNKNOWN)
+		dev_err(pef2256->dev, "Unknown version (0x%02x, 0x%02x)\n", vstr, wid);
+	else
+		dev_info(pef2256->dev, "Version %s detected\n", version_txt);
+
+	return version;
+}
+
+enum pef2256_gcm_config_item {
+	PEF2256_GCM_CONFIG_1544000 = 0,
+	PEF2256_GCM_CONFIG_2048000,
+	PEF2256_GCM_CONFIG_8192000,
+	PEF2256_GCM_CONFIG_10000000,
+	PEF2256_GCM_CONFIG_12352000,
+	PEF2256_GCM_CONFIG_16384000,
+};
+
+struct pef2256_gcm_config {
+	u8 gcm_12[6];
+	u8 gcm_2x[8];
+};
+
+static const struct pef2256_gcm_config pef2256_gcm_configs[] = {
+	[PEF2256_GCM_CONFIG_1544000] = {
+		.gcm_12 = {0xF0, 0x51, 0x00, 0x80, 0x00, 0x15},
+		.gcm_2x = {0x00, 0x15, 0x00, 0x08, 0x00, 0x3F, 0x9C, 0xDF},
+	},
+	[PEF2256_GCM_CONFIG_2048000] = {
+		.gcm_12 = {0x00, 0x58, 0xD2, 0xC2, 0x00, 0x10},
+		.gcm_2x = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x2F, 0xDB, 0xDF},
+	},
+	[PEF2256_GCM_CONFIG_8192000] = {
+		.gcm_12 = {0x00, 0x58, 0xD2, 0xC2, 0x03, 0x10},
+		.gcm_2x = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x0B, 0xDB, 0xDF},
+	},
+	[PEF2256_GCM_CONFIG_10000000] = {
+		.gcm_12 = {0x90, 0x51, 0x81, 0x8F, 0x04, 0x10},
+		.gcm_2x = {0x40, 0x1B, 0x3D, 0x0A, 0x00, 0x07, 0xC9, 0xDC},
+	},
+	[PEF2256_GCM_CONFIG_12352000] = {
+		.gcm_12 = {0xF0, 0x51, 0x00, 0x80, 0x07, 0x15},
+		.gcm_2x = {0x00, 0x19, 0x00, 0x08, 0x01, 0x0A, 0x98, 0xDA},
+	},
+	[PEF2256_GCM_CONFIG_16384000] = {
+		.gcm_12 = {0x00, 0x58, 0xD2, 0xC2, 0x07, 0x10},
+		.gcm_2x = {0x00, 0x18, 0xFB, 0x0B, 0x01, 0x0B, 0xDB, 0xDF},
+	},
+};
+
+static int pef2256_setup_gcm(struct pef2256 *pef2256)
+{
+	enum pef2256_gcm_config_item item;
+	unsigned long mclk_rate;
+	const u8 *gcm;
+	int i, count;
+
+	mclk_rate = clk_get_rate(pef2256->mclk);
+	switch (mclk_rate) {
+	case 1544000:
+		item = PEF2256_GCM_CONFIG_1544000;
+		break;
+	case 2048000:
+		item = PEF2256_GCM_CONFIG_2048000;
+		break;
+	case 8192000:
+		item = PEF2256_GCM_CONFIG_8192000;
+		break;
+	case 10000000:
+		item = PEF2256_GCM_CONFIG_10000000;
+		break;
+	case 12352000:
+		item = PEF2256_GCM_CONFIG_12352000;
+		break;
+	case 16384000:
+		item = PEF2256_GCM_CONFIG_16384000;
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported v2.x MCLK rate %lu\n", mclk_rate);
+		return -EINVAL;
+	}
+
+	BUILD_BUG_ON(item >= ARRAY_SIZE(pef2256_gcm_configs));
+
+	if (pef2256->version == PEF2256_VERSION_1_2) {
+		gcm = pef2256_gcm_configs[item].gcm_12;
+		count = ARRAY_SIZE(pef2256_gcm_configs[item].gcm_12);
+	} else {
+		gcm = pef2256_gcm_configs[item].gcm_2x;
+		count = ARRAY_SIZE(pef2256_gcm_configs[item].gcm_2x);
+	}
+
+	for (i = 0; i < count; i++)
+		pef2256_write8(pef2256, PEF2256_GCM(i+1), *(gcm + i));
+
+	return 0;
+}
+
+static int pef2256_setup_e1(struct pef2256 *pef2256)
+{
+	u8 fmr1, fmr2, sic1;
+	int ret;
+
+	/* Basic setup, Master clocking mode (GCM8..1) */
+	ret = pef2256_setup_gcm(pef2256);
+	if (ret)
+		return ret;
+
+	/* RCLK output : DPLL clock, DCO-X enabled, DCO-X internal ref clock */
+	pef2256_write8(pef2256, PEF2256_CMR1, 0x00);
+
+	/*
+	 * SCLKR selected, SCLKX selected,
+	 * receive synchro pulse sourced by SYPR,
+	 * transmit synchro pulse sourced by SYPX
+	 */
+	pef2256_write8(pef2256, PEF2256_CMR2, 0x00);
+
+	/* NRZ coding, no alarm simulation */
+	pef2256_write8(pef2256, PEF2256_FMR0, 0x00);
+
+	/*
+	 * E1, frame format, 2 Mbit/s system data rate, no AIS
+	 * transmission to remote end or system interface, payload loop
+	 * off, transmit remote alarm on
+	 */
+	fmr1 = 0x00;
+	fmr2 = PEF2256_FMR2_AXRA;
+	switch (pef2256->frame_type) {
+	case PEF2256_FRAME_E1_DOUBLEFRAME:
+		fmr2 |= PEF2256_FMR2_RFS_DOUBLEFRAME;
+		break;
+	case PEF2256_FRAME_E1_CRC4_MULTIFRAME:
+		fmr1 |= PEF2256_FMR1_XFS;
+		fmr2 |= PEF2256_FMR2_RFS_CRC4_MULTIFRAME;
+		break;
+	case PEF2256_FRAME_E1_AUTO_MULTIFRAME:
+		fmr1 |= PEF2256_FMR1_XFS;
+		fmr2 |= PEF2256_FMR2_RFS_AUTO_MULTIFRAME;
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported frame type %d\n", pef2256->frame_type);
+		return -EINVAL;
+	}
+	pef2256_write8(pef2256, PEF2256_FMR1, fmr1);
+	pef2256_write8(pef2256, PEF2256_FMR2, fmr2);
+
+	/* E1 default for the receive slicer threshold */
+	pef2256_write8(pef2256, PEF2256_LIM2, PEF2256_LIM2_SLT_THR50);
+	if (!pef2256->is_subordinate) {
+		/* SEC input, active high */
+		pef2256_write8(pef2256, PEF2256_GPC1, PEF2256_GPC1_CSFP_SEC_IN_HIGH);
+	} else {
+		/* Loop-timed */
+		pef2256_setbits8(pef2256, PEF2256_LIM2, PEF2256_LIM2_ELT);
+		/* FSC output, active high */
+		pef2256_write8(pef2256, PEF2256_GPC1, PEF2256_GPC1_CSFP_FSC_OUT_HIGH);
+	}
+
+	/* internal second timer, power on */
+	pef2256_write8(pef2256, PEF2256_GCR, 0x00);
+
+	/*
+	 * slave mode, local loop off, mode short-haul
+	 * In v2.x, bit3 is a forced 1 bit in the datasheet -> Need to be set.
+	 */
+	if (pef2256->version == PEF2256_VERSION_1_2)
+		pef2256_write8(pef2256, PEF2256_LIM0, 0x00);
+	else
+		pef2256_write8(pef2256, PEF2256_LIM0, PEF2256_2X_LIM0_BIT3);
+
+	/* analog interface selected, remote loop off */
+	pef2256_write8(pef2256, PEF2256_LIM1, 0x00);
+
+	/*
+	 * SCLKR, SCLKX, RCLK configured to inputs,
+	 * XFMS active low, CLK1 and CLK2 pin configuration
+	 */
+	pef2256_write8(pef2256, PEF2256_PC5, 0x00);
+	pef2256_write8(pef2256, PEF2256_PC6, 0x00);
+
+	/*
+	 * 2.048 MHz system clocking rate, receive buffer 2 frames, transmit
+	 * buffer bypass, data sampled and transmitted on the falling edge of
+	 * SCLKR/X, automatic freeze signaling, data is active in the first
+	 * channel phase
+	 */
+	pef2256_write8(pef2256, PEF2256_SIC1, 0x00);
+	pef2256_write8(pef2256, PEF2256_SIC2, 0x00);
+	pef2256_write8(pef2256, PEF2256_SIC3, 0x00);
+
+	/* channel loop-back and single frame mode are disabled */
+	pef2256_write8(pef2256, PEF2256_LOOP, 0x00);
+
+	/* all bits of the transmitted service word are cleared */
+	pef2256_write8(pef2256, PEF2256_XSW, PEF2256_XSW_XY(0x1F));
+	/* CAS disabled and clear spare bit values */
+	pef2256_write8(pef2256, PEF2256_XSP, 0x00);
+
+	/* no transparent mode active */
+	pef2256_write8(pef2256, PEF2256_TSWM, 0x00);
+
+	/*
+	 * the transmit clock offset is cleared
+	 * the transmit time slot offset is cleared
+	 */
+	pef2256_write8(pef2256, PEF2256_XC0, 0x00);
+
+	/* Keep default value for the transmit offset */
+	pef2256_write8(pef2256, PEF2256_XC1, 0x9C);
+
+	/*
+	 * transmit pulse mask, default value from datasheet
+	 * transmitter in tristate mode
+	 */
+	if (pef2256->version == PEF2256_VERSION_1_2)
+		pef2256_write8(pef2256, PEF2256_XPM0, 0x7B);
+	else
+		pef2256_write8(pef2256, PEF2256_XPM0, 0x9C);
+	pef2256_write8(pef2256, PEF2256_XPM1, 0x03);
+	pef2256_write8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT | 0x00);
+
+	/* "master" mode */
+	if (!pef2256->is_subordinate)
+		pef2256_setbits8(pef2256, PEF2256_LIM0, PEF2256_LIM0_MAS);
+
+	/* transmit line in normal operation */
+	pef2256_clrbits8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT);
+
+	/* receive input threshold = 0,21V */
+	if (pef2256->version == PEF2256_VERSION_1_2)
+		pef2256_clrsetbits8(pef2256, PEF2256_LIM1, PEF2256_12_LIM1_RIL_MASK,
+				    PEF2256_12_LIM1_RIL_210);
+	else
+		pef2256_clrsetbits8(pef2256, PEF2256_LIM1, PEF2256_2X_LIM1_RIL_MASK,
+				    PEF2256_2X_LIM1_RIL_210);
+
+	/* transmit line coding = HDB3 */
+	pef2256_clrsetbits8(pef2256, PEF2256_FMR0, PEF2256_FMR0_XC_MASK, PEF2256_FMR0_XC_HDB3);
+
+	/* receive line coding = HDB3 */
+	pef2256_clrsetbits8(pef2256, PEF2256_FMR0, PEF2256_FMR0_RC_MASK, PEF2256_FMR0_RC_HDB3);
+
+	/* detection of LOS alarm = 176 pulses (ie (10 + 1) * 16) */
+	pef2256_write8(pef2256, PEF2256_PCD, 10);
+
+	/* recovery of LOS alarm = 22 pulses (ie 21 + 1) */
+	pef2256_write8(pef2256, PEF2256_PCR, 21);
+
+	/* DCO-X center frequency enabled */
+	pef2256_setbits8(pef2256, PEF2256_CMR2, PEF2256_CMR2_DCOXC);
+
+	if (pef2256->is_subordinate) {
+		/* select RCLK source = 2M,  disable switching from RCLK to SYNC */
+		pef2256_clrsetbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_RS_MASK,
+				    PEF2256_CMR1_RS_DCOR_2048);
+		pef2256_setbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_DCS);
+
+		/* transmit buffer size = 2 frames, transparent mode */
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_XBS_MASK,
+				    PEF2256_SIC1_XBS_2FRAMES);
+		pef2256_setbits8(pef2256, PEF2256_XSW, PEF2256_XSW_XTM);
+	}
+
+	if (pef2256->version != PEF2256_VERSION_1_2) {
+		/* during inactive channel phase switch RDO/RSIG into tri-state */
+		pef2256_setbits8(pef2256, PEF2256_SIC3, PEF2256_SIC3_RTRI);
+	}
+
+	if (pef2256->is_tx_falling_edge) {
+		/* falling edge sync pulse transmit, rising edge sync pulse receive */
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC3, PEF2256_SIC3_RESX, PEF2256_SIC3_RESR);
+	} else {
+		/* rising edge sync pulse transmit, falling edge sync pulse receive */
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC3, PEF2256_SIC3_RESR, PEF2256_SIC3_RESX);
+	}
+
+	/* transmit offset counter (XCO10..0) = 4 */
+	pef2256_write8(pef2256, PEF2256_XC0, 0);
+	pef2256_write8(pef2256, PEF2256_XC1, 4);
+	/* receive offset counter (RCO10..0) = 4 */
+	pef2256_write8(pef2256, PEF2256_RC0, 0);
+	pef2256_write8(pef2256, PEF2256_RC1, 4);
+
+	/* system clock rate */
+	switch (pef2256->sysclk_rate) {
+	case 2048000:
+		sic1 = PEF2256_SIC1_SSC_2048;
+		break;
+	case 4096000:
+		sic1 = PEF2256_SIC1_SSC_4096;
+		break;
+	case 8192000:
+		sic1 = PEF2256_SIC1_SSC_8192;
+		break;
+	case 16384000:
+		sic1 = PEF2256_SIC1_SSC_16384;
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported sysclk rate %lu\n", pef2256->sysclk_rate);
+		return -EINVAL;
+	}
+	pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_SSC_MASK, sic1);
+
+	/* data clock rate */
+	switch (pef2256->data_rate) {
+	case 2048000:
+		fmr1 = PEF2256_FMR1_SSD_2048;
+		sic1 = PEF2256_SIC1_SSD_2048;
+		break;
+	case 4096000:
+		fmr1 = PEF2256_FMR1_SSD_4096;
+		sic1 = PEF2256_SIC1_SSD_4096;
+		break;
+	case 8192000:
+		fmr1 = PEF2256_FMR1_SSD_8192;
+		sic1 = PEF2256_SIC1_SSD_8192;
+		break;
+	case 16384000:
+		fmr1 = PEF2256_FMR1_SSD_16384;
+		sic1 = PEF2256_SIC1_SSD_16384;
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported data rate %u\n", pef2256->data_rate);
+		return -EINVAL;
+	}
+	pef2256_clrsetbits8(pef2256, PEF2256_FMR1, PEF2256_FMR1_SSD_MASK, fmr1);
+	pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_SSD_MASK, sic1);
+
+	/* channel phase */
+	pef2256_clrsetbits8(pef2256, PEF2256_SIC2, PEF2256_SIC2_SICS_MASK,
+			    PEF2256_SIC2_SICS(pef2256->channel_phase));
+
+	/* error counter latched every 1s */
+	pef2256_setbits8(pef2256, PEF2256_FMR1, PEF2256_FMR1_ECM);
+	/* error counter mode COFA */
+	pef2256_setbits8(pef2256, PEF2256_GCR, PEF2256_GCR_ECMC);
+	/* errors in service words have no influence */
+	pef2256_setbits8(pef2256, PEF2256_RC0, PEF2256_RC0_SWD);
+	/* 4 consecutive incorrect FAS causes loss of sync */
+	pef2256_setbits8(pef2256, PEF2256_RC0, PEF2256_RC0_ASY4);
+	/* Si-Bit, Spare bit For International, FAS word */
+	pef2256_setbits8(pef2256, PEF2256_XSW, PEF2256_XSW_XSIS);
+	pef2256_setbits8(pef2256, PEF2256_XSP, PEF2256_XSP_XSIF);
+
+	/* port RCLK is output */
+	pef2256_setbits8(pef2256, PEF2256_PC5, PEF2256_PC5_CRP);
+	/* status changed interrupt at both up and down */
+	pef2256_setbits8(pef2256, PEF2256_GCR, PEF2256_GCR_SCI);
+
+	/* Clear any ISR2 pending interrupts and unmask needed interrupts */
+	pef2256_read8(pef2256, PEF2256_ISR2);
+	pef2256_clrbits8(pef2256, PEF2256_IMR2, PEF2256_INT2_LOS | PEF2256_INT2_AIS);
+
+	/* reset lines */
+	pef2256_write8(pef2256, PEF2256_CMDR, PEF2256_CMDR_RRES | PEF2256_CMDR_XRES);
+	return 0;
+}
+
+static int pef2256_setup(struct pef2256 *pef2256)
+{
+	if (pef2256->is_e1)
+		return pef2256_setup_e1(pef2256);
+
+	dev_err(pef2256->dev, "Only E1 line is currently supported\n");
+	return -EOPNOTSUPP;
+}
+
+
+
+static void pef2256_isr_default_handler(struct pef2256 *pef2256, u8 nbr, u8 isr)
+{
+	dev_warn(pef2256->dev, "ISR%u: 0x%02x not handled\n", nbr, isr);
+}
+
+static bool pef2256_is_carrier_on(struct pef2256 *pef2256)
+{
+	u8 frs0;
+
+	frs0 = pef2256_read8(pef2256, PEF2256_FRS0);
+	return !(frs0 & (PEF2256_FRS0_LOS | PEF2256_FRS0_AIS));
+}
+
+static void pef2256_isr2_handler(struct pef2256 *pef2256, u8 nbr, u8 isr)
+{
+	bool carrier;
+
+	if (isr & (PEF2256_INT2_LOS | PEF2256_INT2_AIS)) {
+		carrier = pef2256_is_carrier_on(pef2256);
+		if (atomic_xchg(&pef2256->carrier, carrier) != carrier)
+			atomic_notifier_call_chain(&pef2256->event_notifier_list,
+						   PEF2256_EVENT_CARRIER, NULL);
+	}
+}
+
+static irqreturn_t pef2256_irq_handler(int irq, void *priv)
+{
+	void (*pef2256_isr_handler[])(struct pef2256 *, u8, u8) = {
+		[0] = pef2256_isr_default_handler,
+		[1] = pef2256_isr_default_handler,
+		[2] = pef2256_isr2_handler,
+		[3] = pef2256_isr_default_handler,
+		[4] = pef2256_isr_default_handler,
+		[5] = pef2256_isr_default_handler
+	};
+	struct pef2256 *pef2256 = (struct pef2256 *)priv;
+	u8 gis;
+	u8 isr;
+	u8 n;
+
+	gis = pef2256_read8(pef2256, PEF2256_GIS);
+
+	for (n = 0; n < ARRAY_SIZE(pef2256_isr_handler) ; n++) {
+		if (gis & PEF2256_GIS_ISR(n)) {
+			isr = pef2256_read8(pef2256, PEF2256_ISR(n));
+			pef2256_isr_handler[n](pef2256, n, isr);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int pef2256_check_rates(struct pef2256 *pef2256, unsigned long sysclk_rate,
+			       unsigned long data_rate)
+{
+	unsigned long rate;
+
+	switch (sysclk_rate) {
+	case 2048000:
+	case 4096000:
+	case 8192000:
+	case 16384000:
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported system clock rate %lu\n", sysclk_rate);
+		return -EINVAL;
+	}
+
+	for (rate = data_rate; rate <= data_rate * 4; rate *= 2) {
+		if (rate == sysclk_rate)
+			return 0;
+	}
+	dev_err(pef2256->dev, "Unsupported data rate %lu with system clock rate %lu\n",
+		data_rate, sysclk_rate);
+	return -EINVAL;
+}
+
+static int pef2556_of_parse(struct pef2256 *pef2256, struct device_node *np)
+{
+	const char *str;
+	int ret;
+
+	str = "e1";
+	ret = of_property_read_string(np, "lantiq,line-interface", &str);
+	if (ret && ret != -EINVAL) {
+		dev_err(pef2256->dev, "%pOF: failed to read lantiq,line-interface\n",
+			np);
+		return ret;
+	}
+	if (!strcmp(str, "e1")) {
+		pef2256->is_e1 = true;
+	} else if (!strcmp(str, "t1j1")) {
+		pef2256->is_e1 = false;
+	} else {
+		dev_err(pef2256->dev, "%pOF: Invalid lantiq,line-interface (%s)\n",
+			np, str);
+		return -EINVAL;
+	}
+	dev_dbg(pef2256->dev, "config: %s line\n", pef2256->is_e1 ? "E1" : "T1/J1");
+
+	pef2256->data_rate = 2048000;
+	ret = of_property_read_u32(np, "lantiq,data-rate-bps", &pef2256->data_rate);
+	if (ret && ret != -EINVAL) {
+		dev_err(pef2256->dev, "%pOF: failed to read lantiq,data-rate-bps\n", np);
+		return ret;
+	}
+	dev_dbg(pef2256->dev, "config: data rate %u bps\n", pef2256->data_rate);
+
+	ret =  pef2256_check_rates(pef2256, pef2256->sysclk_rate, pef2256->data_rate);
+	if (ret)
+		return ret;
+
+	pef2256->is_tx_falling_edge = of_property_read_bool(np, "lantiq,clock-falling-edge");
+	dev_dbg(pef2256->dev, "config: tx on %s edge\n",
+		pef2256->is_tx_falling_edge ? "falling" : "rising");
+
+	pef2256->is_subordinate = of_property_read_bool(np, "lantiq,subordinate");
+	dev_dbg(pef2256->dev, "config: subordinate %s\n",
+		pef2256->is_subordinate ? "on" : "off");
+
+	str = pef2256->is_e1 ? "doubleframe" : "12frame";
+	ret = of_property_read_string(np, "lantiq,frame-format", &str);
+	if (ret && ret != -EINVAL) {
+		dev_err(pef2256->dev, "%pOF: failed to read lantiq,frame-format\n",
+			np);
+		return ret;
+	}
+	if (pef2256->is_e1) {
+		if (!strcmp(str, "doubleframe")) {
+			pef2256->frame_type = PEF2256_FRAME_E1_DOUBLEFRAME;
+		} else if (!strcmp(str, "crc4-multiframe")) {
+			pef2256->frame_type = PEF2256_FRAME_E1_CRC4_MULTIFRAME;
+		} else if (!strcmp(str, "auto-multiframe")) {
+			pef2256->frame_type = PEF2256_FRAME_E1_AUTO_MULTIFRAME;
+		} else {
+			dev_err(pef2256->dev, "%pOF: Invalid lantiq,frame-format (%s)\n",
+				np, str);
+			return -EINVAL;
+		}
+	} else {
+		if (!strcmp(str, "4frame")) {
+			pef2256->frame_type = PEF2256_FRAME_T1J1_4FRAME;
+		} else if (!strcmp(str, "12frame")) {
+			pef2256->frame_type = PEF2256_FRAME_T1J1_12FRAME;
+		} else if (!strcmp(str, "24frame")) {
+			pef2256->frame_type = PEF2256_FRAME_T1J1_24FRAME;
+		} else if (!strcmp(str, "72frame")) {
+			pef2256->frame_type = PEF2256_FRAME_T1J1_72FRAME;
+		} else {
+			dev_err(pef2256->dev, "%pOF: Invalid lantiq,frame-format (%s)\n",
+				np, str);
+			return -EINVAL;
+		}
+	}
+	dev_dbg(pef2256->dev, "config: frame type %d\n", pef2256->frame_type);
+
+	pef2256->channel_phase = 0;
+	ret = of_property_read_u8(np, "lantiq,channel-phase", &pef2256->channel_phase);
+	if (ret && ret != -EINVAL) {
+		dev_err(pef2256->dev, "%pOF: failed to read lantiq,channel-phase\n",
+			np);
+		return ret;
+	}
+	if (pef2256->channel_phase >= pef2256->sysclk_rate / pef2256->data_rate) {
+		dev_err(pef2256->dev, "%pOF: Invalid lantiq,channel-phase %u\n",
+			np, pef2256->channel_phase);
+		return -EINVAL;
+	}
+	dev_dbg(pef2256->dev, "config: channel phase %u\n", pef2256->channel_phase);
+
+	return 0;
+}
+
+static int pef2256_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct pef2256 *pef2256 = pinctrl_dev_get_drvdata(pctldev);
+
+	/* We map 1 group <-> 1 pin */
+	return pef2256->pinctrl.pctrl_desc.npins;
+}
+
+static const char *pef2256_get_group_name(struct pinctrl_dev *pctldev,
+					  unsigned int selector)
+{
+	struct pef2256 *pef2256 = pinctrl_dev_get_drvdata(pctldev);
+
+	/* We map 1 group <-> 1 pin */
+	return pef2256->pinctrl.pctrl_desc.pins[selector].name;
+}
+
+static int pef2256_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector,
+			     const unsigned int **pins,
+			     unsigned int *num_pins)
+{
+	struct pef2256 *pef2256 = pinctrl_dev_get_drvdata(pctldev);
+
+	/* We map 1 group <-> 1 pin */
+	*pins = &pef2256->pinctrl.pctrl_desc.pins[selector].number;
+	*num_pins = 1;
+
+	return 0;
+}
+
+static const struct pinctrl_ops pef2256_pctlops = {
+	.get_groups_count	= pef2256_get_groups_count,
+	.get_group_name		= pef2256_get_group_name,
+	.get_group_pins		= pef2256_get_group_pins,
+	.dt_node_to_map		= pinconf_generic_dt_node_to_map_pin,
+	.dt_free_map		= pinconf_generic_dt_free_map,
+};
+
+static int pef2256_get_functions_count(struct pinctrl_dev *pctldev)
+{
+	struct pef2256 *pef2256 = pinctrl_dev_get_drvdata(pctldev);
+
+	return pef2256->pinctrl.nfunctions;
+}
+
+static const char *pef2256_get_function_name(struct pinctrl_dev *pctldev,
+					     unsigned int selector)
+{
+	struct pef2256 *pef2256 = pinctrl_dev_get_drvdata(pctldev);
+
+	return pef2256->pinctrl.functions[selector].name;
+}
+
+
+static int pef2256_get_function_groups(struct pinctrl_dev *pctldev, unsigned int selector,
+			 const char * const **groups,
+			 unsigned * const num_groups)
+{
+	struct pef2256 *pef2256 = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = pef2256->pinctrl.functions[selector].groups;
+	*num_groups = pef2256->pinctrl.functions[selector].ngroups;
+	return 0;
+}
+
+static int pef2256_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
+			   unsigned int group_selector)
+{
+	struct pef2256 *pef2256 = pinctrl_dev_get_drvdata(pctldev);
+	const struct pef2256_pinreg_desc *pinreg_desc;
+	u8 func_val;
+
+	dev_dbg(pef2256->dev, "set %s to %s function\n",
+		pef2256->pinctrl.pctrl_desc.pins[group_selector].name,
+		pef2256->pinctrl.functions[func_selector].name);
+
+	/* We map 1 group <-> 1 pin */
+	pinreg_desc = pef2256->pinctrl.pctrl_desc.pins[group_selector].drv_data;
+	func_val = pef2256->pinctrl.functions[func_selector].func_val;
+
+	pef2256_clrsetbits8(pef2256, pinreg_desc->offset, pinreg_desc->mask,
+			    func_val & pinreg_desc->mask);
+
+	return 0;
+}
+
+static const struct pinmux_ops pef2256_pmxops = {
+	.get_functions_count	= pef2256_get_functions_count,
+	.get_function_name	= pef2256_get_function_name,
+	.get_function_groups	= pef2256_get_function_groups,
+	.set_mux		= pef2256_set_mux,
+};
+
+#define PEF2256_PINCTRL_PIN(_number, _name, _offset, _mask) { \
+	.number = _number, \
+	.name = _name, \
+	.drv_data = &(struct pef2256_pinreg_desc) { \
+		.offset = _offset, \
+		.mask = _mask, \
+	}, \
+}
+
+static const struct pinctrl_pin_desc pef2256_v12_pins[] = {
+	PEF2256_PINCTRL_PIN(0, "RPA", PEF2256_PC1, PEF2256_12_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(1, "RPB", PEF2256_PC2, PEF2256_12_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(2, "RPC", PEF2256_PC3, PEF2256_12_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(3, "RPD", PEF2256_PC4, PEF2256_12_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(4, "XPA", PEF2256_PC1, PEF2256_12_PC_XPC_MASK),
+	PEF2256_PINCTRL_PIN(5, "XPB", PEF2256_PC2, PEF2256_12_PC_XPC_MASK),
+	PEF2256_PINCTRL_PIN(6, "XPC", PEF2256_PC3, PEF2256_12_PC_XPC_MASK),
+	PEF2256_PINCTRL_PIN(7, "XPD", PEF2256_PC4, PEF2256_12_PC_XPC_MASK),
+};
+
+static const struct pinctrl_pin_desc pef2256_v2x_pins[] = {
+	PEF2256_PINCTRL_PIN(0, "RPA", PEF2256_PC1, PEF2256_2X_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(1, "RPB", PEF2256_PC2, PEF2256_2X_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(2, "RPC", PEF2256_PC3, PEF2256_2X_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(3, "RPD", PEF2256_PC4, PEF2256_2X_PC_RPC_MASK),
+	PEF2256_PINCTRL_PIN(4, "XPA", PEF2256_PC1, PEF2256_2X_PC_XPC_MASK),
+	PEF2256_PINCTRL_PIN(5, "XPB", PEF2256_PC2, PEF2256_2X_PC_XPC_MASK),
+	PEF2256_PINCTRL_PIN(6, "XPC", PEF2256_PC3, PEF2256_2X_PC_XPC_MASK),
+	PEF2256_PINCTRL_PIN(7, "XPD", PEF2256_PC4, PEF2256_2X_PC_XPC_MASK),
+};
+
+static const char *const pef2256_rp_groups[] = { "RPA", "RPB", "RPC", "RPD" };
+static const char *const pef2256_xp_groups[] = { "XPA", "XPB", "XPC", "XPD" };
+static const char *const pef2256_all_groups[] = { "RPA", "RPB", "RPC", "RPD",
+						  "XPA", "XPB", "XPC", "XPD" };
+
+#define PEF2256_FUNCTION(_name, _func_val, _groups) { \
+	.name = _name, \
+	.groups = _groups, \
+	.ngroups = ARRAY_SIZE(_groups), \
+	.func_val = _func_val, \
+}
+
+static const struct pef2256_function_desc pef2256_v2x_functions[] = {
+	PEF2256_FUNCTION("SYPR",   PEF2256_2X_PC_RPC_SYPR,   pef2256_rp_groups),
+	PEF2256_FUNCTION("RFM",    PEF2256_2X_PC_RPC_RFM,    pef2256_rp_groups),
+	PEF2256_FUNCTION("RFMB",   PEF2256_2X_PC_RPC_RFMB,   pef2256_rp_groups),
+	PEF2256_FUNCTION("RSIGM",  PEF2256_2X_PC_RPC_RSIGM,  pef2256_rp_groups),
+	PEF2256_FUNCTION("RSIG",   PEF2256_2X_PC_RPC_RSIG,   pef2256_rp_groups),
+	PEF2256_FUNCTION("DLR",    PEF2256_2X_PC_RPC_DLR,    pef2256_rp_groups),
+	PEF2256_FUNCTION("FREEZE", PEF2256_2X_PC_RPC_FREEZE, pef2256_rp_groups),
+	PEF2256_FUNCTION("RFSP",   PEF2256_2X_PC_RPC_RFSP,   pef2256_rp_groups),
+	PEF2256_FUNCTION("LOS",    PEF2256_2X_PC_RPC_LOS,    pef2256_rp_groups),
+
+	PEF2256_FUNCTION("SYPX",  PEF2256_2X_PC_XPC_SYPX,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XFMS",  PEF2256_2X_PC_XPC_XFMS,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XSIG",  PEF2256_2X_PC_XPC_XSIG,  pef2256_xp_groups),
+	PEF2256_FUNCTION("TCLK",  PEF2256_2X_PC_XPC_TCLK,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XMFB",  PEF2256_2X_PC_XPC_XMFB,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XSIGM", PEF2256_2X_PC_XPC_XSIGM, pef2256_xp_groups),
+	PEF2256_FUNCTION("DLX",   PEF2256_2X_PC_XPC_DLX,   pef2256_xp_groups),
+	PEF2256_FUNCTION("XCLK",  PEF2256_2X_PC_XPC_XCLK,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XLT",   PEF2256_2X_PC_XPC_XLT,   pef2256_xp_groups),
+
+	PEF2256_FUNCTION("GPI",  PEF2256_2X_PC_RPC_GPI | PEF2256_2X_PC_XPC_GPI,
+			 pef2256_all_groups),
+	PEF2256_FUNCTION("GPOH", PEF2256_2X_PC_RPC_GPOH | PEF2256_2X_PC_XPC_GPOH,
+			 pef2256_all_groups),
+	PEF2256_FUNCTION("GPOL", PEF2256_2X_PC_RPC_GPOL | PEF2256_2X_PC_XPC_GPOL,
+			 pef2256_all_groups),
+};
+
+static const struct pef2256_function_desc pef2256_v12_functions[] = {
+	PEF2256_FUNCTION("SYPR",   PEF2256_12_PC_RPC_SYPR,   pef2256_rp_groups),
+	PEF2256_FUNCTION("RFM",    PEF2256_12_PC_RPC_RFM,    pef2256_rp_groups),
+	PEF2256_FUNCTION("RFMB",   PEF2256_12_PC_RPC_RFMB,   pef2256_rp_groups),
+	PEF2256_FUNCTION("RSIGM",  PEF2256_12_PC_RPC_RSIGM,  pef2256_rp_groups),
+	PEF2256_FUNCTION("RSIG",   PEF2256_12_PC_RPC_RSIG,   pef2256_rp_groups),
+	PEF2256_FUNCTION("DLR",    PEF2256_12_PC_RPC_DLR,    pef2256_rp_groups),
+	PEF2256_FUNCTION("FREEZE", PEF2256_12_PC_RPC_FREEZE, pef2256_rp_groups),
+	PEF2256_FUNCTION("RFSP",   PEF2256_12_PC_RPC_RFSP,   pef2256_rp_groups),
+
+	PEF2256_FUNCTION("SYPX",  PEF2256_12_PC_XPC_SYPX,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XFMS",  PEF2256_12_PC_XPC_XFMS,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XSIG",  PEF2256_12_PC_XPC_XSIG,  pef2256_xp_groups),
+	PEF2256_FUNCTION("TCLK",  PEF2256_12_PC_XPC_TCLK,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XMFB",  PEF2256_12_PC_XPC_XMFB,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XSIGM", PEF2256_12_PC_XPC_XSIGM, pef2256_xp_groups),
+	PEF2256_FUNCTION("DLX",   PEF2256_12_PC_XPC_DLX,   pef2256_xp_groups),
+	PEF2256_FUNCTION("XCLK",  PEF2256_12_PC_XPC_XCLK,  pef2256_xp_groups),
+	PEF2256_FUNCTION("XLT",   PEF2256_12_PC_XPC_XLT,   pef2256_xp_groups),
+};
+
+
+static int pef2256_register_pinctrl(struct pef2256 *pef2256)
+{
+	struct pinctrl_dev	*pctrl;
+
+	pef2256->pinctrl.pctrl_desc.name    = dev_name(pef2256->dev);
+	pef2256->pinctrl.pctrl_desc.owner   = THIS_MODULE;
+	pef2256->pinctrl.pctrl_desc.pctlops = &pef2256_pctlops;
+	pef2256->pinctrl.pctrl_desc.pmxops  = &pef2256_pmxops;
+	if (pef2256->version == PEF2256_VERSION_1_2) {
+		pef2256->pinctrl.pctrl_desc.pins  = pef2256_v12_pins;
+		pef2256->pinctrl.pctrl_desc.npins = ARRAY_SIZE(pef2256_v12_pins);
+		pef2256->pinctrl.functions  = pef2256_v12_functions;
+		pef2256->pinctrl.nfunctions = ARRAY_SIZE(pef2256_v12_functions);
+	} else {
+		pef2256->pinctrl.pctrl_desc.pins  = pef2256_v2x_pins;
+		pef2256->pinctrl.pctrl_desc.npins = ARRAY_SIZE(pef2256_v2x_pins);
+		pef2256->pinctrl.functions  = pef2256_v2x_functions;
+		pef2256->pinctrl.nfunctions = ARRAY_SIZE(pef2256_v2x_functions);
+	}
+
+	pctrl = devm_pinctrl_register(pef2256->dev, &pef2256->pinctrl.pctrl_desc, pef2256);
+	if (IS_ERR(pctrl)) {
+		dev_err(pef2256->dev, "pinctrl driver registration failed\n");
+		return PTR_ERR(pctrl);
+	}
+
+	return 0;
+}
+
+static void pef2256_reset_pinmux(struct pef2256 *pef2256)
+{
+	u8 val;
+	/*
+	 * Reset values cannot be used.
+	 * They define the SYPR/SYPX pin mux for all the RPx and XPx pins and
+	 * Only one pin can be muxed to SYPR and one pin can be muxed to SYPX.
+	 * Choose here an other reset value.
+	 */
+	if (pef2256->version == PEF2256_VERSION_1_2)
+		val = PEF2256_12_PC_XPC_XCLK | PEF2256_12_PC_RPC_RFSP;
+	else
+		val = PEF2256_2X_PC_XPC_GPI | PEF2256_2X_PC_RPC_GPI;
+
+	pef2256_write8(pef2256, PEF2256_PC1, val);
+	pef2256_write8(pef2256, PEF2256_PC2, val);
+	pef2256_write8(pef2256, PEF2256_PC3, val);
+	pef2256_write8(pef2256, PEF2256_PC4, val);
+}
+
+static ssize_t subordinate_show(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	struct pef2256 *pef2256 = dev_get_drvdata(dev);
+
+	return sysfs_emit(buf, "%d\n", pef2256->is_subordinate);
+}
+
+static ssize_t subordinate_store(struct device *dev, struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct pef2256 *pef2256 = dev_get_drvdata(dev);
+	int ret;
+
+	if (strtobool(buf, &pef2256->is_subordinate) < 0)
+		return -EINVAL;
+
+	ret = pef2256_setup(pef2256);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(subordinate);
+
+static const struct attribute_group pef2256_attribute_group = {
+	.attrs = (struct attribute *[]) {
+		&dev_attr_subordinate.attr,
+		NULL,
+	},
+};
+
+static int pef2256_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	unsigned long sclkr_rate, sclkx_rate;
+	struct pef2256 *pef2256;
+	int ret;
+	int irq;
+
+	pef2256 = devm_kzalloc(&pdev->dev, sizeof(*pef2256), GFP_KERNEL);
+	if (!pef2256)
+		return -ENOMEM;
+
+	pef2256->dev = &pdev->dev;
+	ATOMIC_INIT_NOTIFIER_HEAD(&pef2256->event_notifier_list);
+
+	pef2256->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(pef2256->regs))
+		return PTR_ERR(pef2256->regs);
+
+	pef2256->mclk = devm_clk_get_enabled(&pdev->dev, "mclk");
+	if (IS_ERR(pef2256->mclk))
+		return PTR_ERR(pef2256->mclk);
+	dev_dbg(pef2256->dev, "mclk %lu Hz\n", clk_get_rate(pef2256->mclk));
+
+	pef2256->sclkr = devm_clk_get_enabled(&pdev->dev, "sclkr");
+	if (IS_ERR(pef2256->sclkr))
+		return PTR_ERR(pef2256->sclkr);
+
+	pef2256->sclkx = devm_clk_get_enabled(&pdev->dev, "sclkx");
+	if (IS_ERR(pef2256->sclkx))
+		return PTR_ERR(pef2256->sclkx);
+
+	/*
+	 * Both SCLKR (receive) and SCLKX (transmit) must have the same rate,
+	 * stored as sysclk_rate.
+	 * The exact value will be checked at pef2256_check_rates()
+	 */
+	sclkr_rate = clk_get_rate(pef2256->sclkr);
+	sclkx_rate = clk_get_rate(pef2256->sclkx);
+	dev_dbg(pef2256->dev, "sclkr %lu Hz\n", sclkr_rate);
+	dev_dbg(pef2256->dev, "sclkx %lu Hz\n", sclkx_rate);
+	if (sclkr_rate != sclkx_rate) {
+		dev_err(pef2256->dev, "clk rate mismatch. sclkr %lu Hz, sclkx %lu Hz\n",
+			sclkr_rate, sclkx_rate);
+		return -EINVAL;
+	}
+	pef2256->sysclk_rate = sclkr_rate;
+
+	/* Reset the component. The MCLK clock must be active during reset */
+	pef2256->reset_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(pef2256->reset_gpio))
+		return PTR_ERR(pef2256->reset_gpio);
+	if (pef2256->reset_gpio) {
+		gpiod_set_value_cansleep(pef2256->reset_gpio, 1);
+		udelay(10);
+		gpiod_set_value_cansleep(pef2256->reset_gpio, 0);
+		udelay(10);
+	}
+
+	pef2256->version = pef2256_get_version(pef2256);
+	if (pef2256->version == PEF2256_VERSION_UNKNOWN)
+		return -ENODEV;
+
+	ret = pef2556_of_parse(pef2256, np);
+	if (ret)
+		return ret;
+
+	/* Disable interrupts */
+	pef2256_write8(pef2256, PEF2256_IMR0, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR1, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR2, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR3, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR4, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR5, 0xff);
+
+	/* Clear any pending interrupts */
+	pef2256_read8(pef2256, PEF2256_ISR0);
+	pef2256_read8(pef2256, PEF2256_ISR1);
+	pef2256_read8(pef2256, PEF2256_ISR2);
+	pef2256_read8(pef2256, PEF2256_ISR3);
+	pef2256_read8(pef2256, PEF2256_ISR4);
+	pef2256_read8(pef2256, PEF2256_ISR5);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+	ret = devm_request_irq(pef2256->dev, irq, pef2256_irq_handler, 0, "pef2256", pef2256);
+	if (ret < 0)
+		return ret;
+
+	pef2256_reset_pinmux(pef2256);
+	ret = pef2256_register_pinctrl(pef2256);
+	if (ret)
+		return ret;
+
+	/*
+	 * We are going to reset the E1 lines during setup() call and the ISR2
+	 * interrupt used to detect the carrier state changed is masked.
+	 * It is time to initialize our internal carrier state flag.
+	 */
+	atomic_set(&pef2256->carrier, 0);
+
+	ret = pef2256_setup(pef2256);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, pef2256);
+
+	ret = sysfs_create_group(&pef2256->dev->kobj, &pef2256_attribute_group);
+	if (ret < 0) {
+		dev_err(pef2256->dev, "sysfs registration failed (%d)\n", ret);
+		platform_set_drvdata(pdev, NULL);
+		return ret;
+	}
+
+	ret = devm_of_platform_populate(pef2256->dev);
+	if (ret < 0) {
+		dev_err(pef2256->dev, "platform populate failed (%d)\n", ret);
+		platform_set_drvdata(pdev, NULL);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int pef2256_remove(struct platform_device *pdev)
+{
+	struct pef2256 *pef2256 = platform_get_drvdata(pdev);
+
+	/* Disable interrupts */
+	pef2256_write8(pef2256, PEF2256_IMR0, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR1, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR2, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR3, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR4, 0xff);
+	pef2256_write8(pef2256, PEF2256_IMR5, 0xff);
+
+	sysfs_remove_group(&pef2256->dev->kobj, &pef2256_attribute_group);
+
+	return 0;
+}
+
+static const struct of_device_id pef2256_id_table[] = {
+	{ .compatible = "lantiq,pef2256" },
+	{} /* sentinel */
+};
+MODULE_DEVICE_TABLE(of, pef2256_id_table);
+
+static struct platform_driver pef2256_driver = {
+	.driver = {
+		.name = "lantiq-pef2256",
+		.of_match_table = of_match_ptr(pef2256_id_table),
+	},
+	.probe = pef2256_probe,
+	.remove = pef2256_remove,
+};
+module_platform_driver(pef2256_driver);
+
+int pef2256_register_event_notifier(struct pef2256 *pef2256, struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&pef2256->event_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(pef2256_register_event_notifier);
+
+int pef2256_unregister_event_notifier(struct pef2256 *pef2256, struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(&pef2256->event_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(pef2256_unregister_event_notifier);
+
+bool pef2256_get_carrier(struct pef2256 *pef2256)
+{
+	return !!atomic_read(&pef2256->carrier);
+}
+EXPORT_SYMBOL_GPL(pef2256_get_carrier);
+
+MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
+MODULE_DESCRIPTION("PEF2256 driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/pef2256.h b/include/linux/mfd/pef2256.h
new file mode 100644
index 000000000000..0c0afcefa3ef
--- /dev/null
+++ b/include/linux/mfd/pef2256.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * PEF2256 management
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina <herve.codina@bootlin.com>
+ */
+#ifndef __PEF2256_H__
+#define __PEF2256_H__
+
+#include <linux/types.h>
+
+struct pef2256;
+struct notifier_block;
+
+enum pef2256_event {
+	PEF2256_EVENT_CARRIER, /* Carrier state changed */
+};
+
+/* The nb.notifier_call function registered must not sleep */
+int pef2256_register_event_notifier(struct pef2256 *pef2256, struct notifier_block *nb);
+int pef2256_unregister_event_notifier(struct pef2256 *pef2256, struct notifier_block *nb);
+
+/* Retrieve carrier state. true: carrier on, false: carrier off */
+bool pef2256_get_carrier(struct pef2256 *pef2256);
+
+#endif /* __PEF2256_H__ */
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 3/6] Documentation: sysfs: Document the Lantiq PEF2256 sysfs entry
  2023-03-22 13:46 [PATCH v3 0/6] Add the Lantiq PEF2256 audio support Herve Codina
                   ` (3 preceding siblings ...)
  2023-03-22 13:46 ` Herve Codina
@ 2023-03-22 13:46 ` Herve Codina
  2023-03-22 13:46 ` Herve Codina via Alsa-devel
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 29+ messages in thread
From: Herve Codina @ 2023-03-22 13:46 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni

Document the "subordinate" sysfs attribute exposed by the PEF2256
driver.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 .../ABI/testing/sysfs-bus-platform-devices-pef2256   | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256

diff --git a/Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256 b/Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256
new file mode 100644
index 000000000000..95ba1ae55daf
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256
@@ -0,0 +1,12 @@
+What:		/sys/bus/platform/devices/*.pef2256/subordinate
+KernelVersion:	6.4
+Contact:	Herve Codina <herve.codina@bootlin.com>
+Description:
+		(RW) Controls whether the PEF2256 works as subordinate or main
+		device mode.
+
+		- 0: main device mode
+		- 1: subordinate mode
+
+		In subordinate device mode it synchronizes on line interface
+		clock signals. Otherwise, it synchronizes on internal clocks.
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 3/6] Documentation: sysfs: Document the Lantiq PEF2256 sysfs entry
  2023-03-22 13:46 [PATCH v3 0/6] Add the Lantiq PEF2256 audio support Herve Codina
                   ` (4 preceding siblings ...)
  2023-03-22 13:46 ` [PATCH v3 3/6] Documentation: sysfs: Document the Lantiq PEF2256 sysfs entry Herve Codina
@ 2023-03-22 13:46 ` Herve Codina via Alsa-devel
  2023-03-22 13:46 ` [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec Herve Codina
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 29+ messages in thread
From: Herve Codina via Alsa-devel @ 2023-03-22 13:46 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni


[-- Attachment #0: Type: message/rfc822, Size: 4984 bytes --]

From: Herve Codina <herve.codina@bootlin.com>
To: Herve Codina <herve.codina@bootlin.com>, Lee Jones <lee@kernel.org>, Rob Herring <robh+dt@kernel.org>, Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>, Liam Girdwood <lgirdwood@gmail.com>, Mark Brown <broonie@kernel.org>, Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>
Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, alsa-devel@alsa-project.org, Christophe Leroy <christophe.leroy@csgroup.eu>, Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Subject: [PATCH v3 3/6] Documentation: sysfs: Document the Lantiq PEF2256 sysfs entry
Date: Wed, 22 Mar 2023 14:46:51 +0100
Message-ID: <20230322134654.219957-4-herve.codina@bootlin.com>

Document the "subordinate" sysfs attribute exposed by the PEF2256
driver.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 .../ABI/testing/sysfs-bus-platform-devices-pef2256   | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256

diff --git a/Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256 b/Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256
new file mode 100644
index 000000000000..95ba1ae55daf
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256
@@ -0,0 +1,12 @@
+What:		/sys/bus/platform/devices/*.pef2256/subordinate
+KernelVersion:	6.4
+Contact:	Herve Codina <herve.codina@bootlin.com>
+Description:
+		(RW) Controls whether the PEF2256 works as subordinate or main
+		device mode.
+
+		- 0: main device mode
+		- 1: subordinate mode
+
+		In subordinate device mode it synchronizes on line interface
+		clock signals. Otherwise, it synchronizes on internal clocks.
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec
  2023-03-22 13:46 [PATCH v3 0/6] Add the Lantiq PEF2256 audio support Herve Codina
                   ` (5 preceding siblings ...)
  2023-03-22 13:46 ` Herve Codina via Alsa-devel
@ 2023-03-22 13:46 ` Herve Codina
  2023-03-22 21:59   ` Krzysztof Kozlowski
  2023-03-22 13:46 ` Herve Codina via Alsa-devel
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 29+ messages in thread
From: Herve Codina @ 2023-03-22 13:46 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni

The Lantiq PEF2256 is a framer and line interface component designed to
fulfill all required interfacing between an analog E1/T1/J1 line and the
digital PCM system highway/H.100 bus.

The codec support allows to use some of the PCM system highway
time-slots as audio channels to transport audio data over the E1/T1/J1
lines.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 .../bindings/sound/lantiq,pef2256-codec.yaml  | 54 +++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml

diff --git a/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
new file mode 100644
index 000000000000..da35b70cda99
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/lantiq,pef2256-codec.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Lantiq PEF2256 codec
+
+maintainers:
+  - Herve Codina <herve.codina@bootlin.com>
+
+description: |
+  Codec support for PEF2256.
+
+  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and
+  line interface component designed to fulfill all required interfacing between
+  an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.
+
+  The codec support allows to use some of the PCM system highway time-slots as
+  audio channels to transport audio data over the E1/T1/J1 lines.
+
+  The time-slots used by the codec must be set and so, the properties
+  'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and
+  'dai-tdm-slot-rx-mask' must be present in the ALSA sound card node for
+  sub-nodes that involve the codec. The codec uses 8bit time-slots.
+  'dai-tdm-tdm-slot-with' must be set to 8.
+  The tx and rx masks define the PEF2256 time-slots assigned to the codec.
+
+  The PEF2256 codec node should be a child of a PEF2256 node.
+  Refer to the bindings described in
+  Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
+
+allOf:
+  - $ref: dai-common.yaml#
+
+properties:
+  compatible:
+    const: lantiq,pef2256-codec
+
+  '#sound-dai-cells':
+    const: 0
+
+required:
+  - compatible
+  - '#sound-dai-cells'
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    codec {
+        compatible = "lantiq,pef2256-codec";
+        #sound-dai-cells = <0>;
+    };
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec
  2023-03-22 13:46 [PATCH v3 0/6] Add the Lantiq PEF2256 audio support Herve Codina
                   ` (6 preceding siblings ...)
  2023-03-22 13:46 ` [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec Herve Codina
@ 2023-03-22 13:46 ` Herve Codina via Alsa-devel
  2023-03-22 13:46 ` [PATCH v3 5/6] ASoC: codecs: " Herve Codina
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 29+ messages in thread
From: Herve Codina via Alsa-devel @ 2023-03-22 13:46 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni


[-- Attachment #0: Type: message/rfc822, Size: 6506 bytes --]

From: Herve Codina <herve.codina@bootlin.com>
To: Herve Codina <herve.codina@bootlin.com>, Lee Jones <lee@kernel.org>, Rob Herring <robh+dt@kernel.org>, Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>, Liam Girdwood <lgirdwood@gmail.com>, Mark Brown <broonie@kernel.org>, Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>
Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, alsa-devel@alsa-project.org, Christophe Leroy <christophe.leroy@csgroup.eu>, Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Subject: [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec
Date: Wed, 22 Mar 2023 14:46:52 +0100
Message-ID: <20230322134654.219957-5-herve.codina@bootlin.com>

The Lantiq PEF2256 is a framer and line interface component designed to
fulfill all required interfacing between an analog E1/T1/J1 line and the
digital PCM system highway/H.100 bus.

The codec support allows to use some of the PCM system highway
time-slots as audio channels to transport audio data over the E1/T1/J1
lines.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 .../bindings/sound/lantiq,pef2256-codec.yaml  | 54 +++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml

diff --git a/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
new file mode 100644
index 000000000000..da35b70cda99
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/lantiq,pef2256-codec.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Lantiq PEF2256 codec
+
+maintainers:
+  - Herve Codina <herve.codina@bootlin.com>
+
+description: |
+  Codec support for PEF2256.
+
+  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and
+  line interface component designed to fulfill all required interfacing between
+  an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.
+
+  The codec support allows to use some of the PCM system highway time-slots as
+  audio channels to transport audio data over the E1/T1/J1 lines.
+
+  The time-slots used by the codec must be set and so, the properties
+  'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and
+  'dai-tdm-slot-rx-mask' must be present in the ALSA sound card node for
+  sub-nodes that involve the codec. The codec uses 8bit time-slots.
+  'dai-tdm-tdm-slot-with' must be set to 8.
+  The tx and rx masks define the PEF2256 time-slots assigned to the codec.
+
+  The PEF2256 codec node should be a child of a PEF2256 node.
+  Refer to the bindings described in
+  Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
+
+allOf:
+  - $ref: dai-common.yaml#
+
+properties:
+  compatible:
+    const: lantiq,pef2256-codec
+
+  '#sound-dai-cells':
+    const: 0
+
+required:
+  - compatible
+  - '#sound-dai-cells'
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    codec {
+        compatible = "lantiq,pef2256-codec";
+        #sound-dai-cells = <0>;
+    };
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 5/6] ASoC: codecs: Add support for the Lantiq PEF2256 codec
  2023-03-22 13:46 [PATCH v3 0/6] Add the Lantiq PEF2256 audio support Herve Codina
                   ` (7 preceding siblings ...)
  2023-03-22 13:46 ` Herve Codina via Alsa-devel
@ 2023-03-22 13:46 ` Herve Codina
  2023-03-22 13:46 ` Herve Codina via Alsa-devel
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 29+ messages in thread
From: Herve Codina @ 2023-03-22 13:46 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni

The Lantiq PEF2256 is a framer and line interface component designed to
fulfill all required interfacing between an analog E1/T1/J1 line and the
digital PCM system highway/H.100 bus.

The codec support allows to use some of the PCM system highway
time-slots as audio channels to transport audio data over the E1/T1/J1
lines. It provides also line carrier detection events reported through
the ALSA jack detection feature.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 sound/soc/codecs/Kconfig         |  14 ++
 sound/soc/codecs/Makefile        |   2 +
 sound/soc/codecs/pef2256-codec.c | 390 +++++++++++++++++++++++++++++++
 3 files changed, 406 insertions(+)
 create mode 100644 sound/soc/codecs/pef2256-codec.c

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 0be061953e9a..4f78da914fc7 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -168,6 +168,7 @@ config SND_SOC_ALL_CODECS
 	imply SND_SOC_PCM512x_I2C
 	imply SND_SOC_PCM512x_SPI
 	imply SND_SOC_PEB2466
+	imply SND_SOC_PEF2256
 	imply SND_SOC_RK3328
 	imply SND_SOC_RK817
 	imply SND_SOC_RT274
@@ -1252,6 +1253,19 @@ config SND_SOC_PEB2466
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-soc-peb2466.
 
+config SND_SOC_PEF2256
+	tristate "Lantiq PEF2256 codec"
+	depends on MFD_PEF2256
+	help
+	  Enable support for the Lantiq PEF2256 (FALC56) codec.
+	  The PEF2256 is a framer and line interface between analog E1/T1/J1
+	  line and a digital PCM bus.
+	  This codec allows to use some of the time slots available on the
+	  PEF2256 PCM bus to transport some audio data.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-soc-pef2256.
+
 config SND_SOC_RK3328
 	tristate "Rockchip RK3328 audio CODEC"
 	select REGMAP_MMIO
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 20b388b77f1f..11bd66d46f7b 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -188,6 +188,7 @@ snd-soc-pcm512x-objs := pcm512x.o
 snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
 snd-soc-pcm512x-spi-objs := pcm512x-spi.o
 snd-soc-peb2466-objs := peb2466.o
+snd-soc-pef2256-objs := pef2256-codec.o
 snd-soc-rk3328-objs := rk3328_codec.o
 snd-soc-rk817-objs := rk817_codec.o
 snd-soc-rl6231-objs := rl6231.o
@@ -551,6 +552,7 @@ obj-$(CONFIG_SND_SOC_PCM512x)	+= snd-soc-pcm512x.o
 obj-$(CONFIG_SND_SOC_PCM512x_I2C)	+= snd-soc-pcm512x-i2c.o
 obj-$(CONFIG_SND_SOC_PCM512x_SPI)	+= snd-soc-pcm512x-spi.o
 obj-$(CONFIG_SND_SOC_PEB2466)	+= snd-soc-peb2466.o
+obj-$(CONFIG_SND_SOC_PEF2256)	+= snd-soc-pef2256.o
 obj-$(CONFIG_SND_SOC_RK3328)	+= snd-soc-rk3328.o
 obj-$(CONFIG_SND_SOC_RK817)	+= snd-soc-rk817.o
 obj-$(CONFIG_SND_SOC_RL6231)	+= snd-soc-rl6231.o
diff --git a/sound/soc/codecs/pef2256-codec.c b/sound/soc/codecs/pef2256-codec.c
new file mode 100644
index 000000000000..366df39bd866
--- /dev/null
+++ b/sound/soc/codecs/pef2256-codec.c
@@ -0,0 +1,390 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// pef2256.c  --  Lantiq PEF2256 ALSA SoC driver
+//
+// Copyright 2023 CS GROUP France
+//
+// Author: Herve Codina <herve.codina@bootlin.com>
+
+#include <linux/clk.h>
+#include <linux/mfd/pef2256.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <sound/jack.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+#define PEF2256_NB_CHANNEL	32
+#define PEF2256_JACK_MASK (SND_JACK_LINEIN | SND_JACK_LINEOUT)
+
+struct pef2256_codec {
+	struct pef2256 *pef2256;
+	struct device *dev;
+	struct snd_soc_jack jack;
+	struct notifier_block nb;
+	struct work_struct carrier_work;
+	int max_chan_playback;
+	int max_chan_capture;
+};
+
+static int pef2256_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+				    unsigned int rx_mask, int slots, int width)
+{
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(dai->component);
+
+	switch (width) {
+	case 0:
+		/* Not set -> default 8 */
+	case 8:
+		break;
+	default:
+		dev_err(dai->dev, "tdm slot width %d not supported\n", width);
+		return -EINVAL;
+	}
+
+	pef2256->max_chan_playback = hweight32(tx_mask);
+	if (pef2256->max_chan_playback > PEF2256_NB_CHANNEL) {
+		dev_err(dai->dev, "too much tx slots defined (mask = 0x%x) support max %d\n",
+			tx_mask, PEF2256_NB_CHANNEL);
+		return -EINVAL;
+	}
+
+	pef2256->max_chan_capture = hweight32(rx_mask);
+	if (pef2256->max_chan_capture > PEF2256_NB_CHANNEL) {
+		dev_err(dai->dev, "too much rx slots defined (mask = 0x%x) support max %d\n",
+			rx_mask, PEF2256_NB_CHANNEL);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * The constraints for format/channel is to match with the number of 8bit
+ * time-slots available.
+ */
+static int pef2256_dai_hw_rule_channels_by_format(struct snd_soc_dai *dai,
+						  struct snd_pcm_hw_params *params,
+						  unsigned int nb_ts)
+{
+	struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	snd_pcm_format_t format = params_format(params);
+	struct snd_interval ch = {0};
+
+	switch (snd_pcm_format_physical_width(format)) {
+	case 8:
+		ch.max = nb_ts;
+		break;
+	case 16:
+		ch.max = nb_ts/2;
+		break;
+	case 32:
+		ch.max = nb_ts/4;
+		break;
+	case 64:
+		ch.max = nb_ts/8;
+		break;
+	default:
+		dev_err(dai->dev, "format physical width %u not supported\n",
+			snd_pcm_format_physical_width(format));
+		return -EINVAL;
+	}
+
+	ch.min = ch.max ? 1 : 0;
+
+	return snd_interval_refine(c, &ch);
+}
+
+static int pef2256_dai_hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params,
+							   struct snd_pcm_hw_rule *rule)
+{
+	struct snd_soc_dai *dai = rule->private;
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(dai->component);
+
+	return pef2256_dai_hw_rule_channels_by_format(dai, params, pef2256->max_chan_playback);
+}
+
+static int pef2256_dai_hw_rule_capture_channels_by_format(struct snd_pcm_hw_params *params,
+							  struct snd_pcm_hw_rule *rule)
+{
+	struct snd_soc_dai *dai = rule->private;
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(dai->component);
+
+	return pef2256_dai_hw_rule_channels_by_format(dai, params, pef2256->max_chan_capture);
+}
+
+static int pef2256_dai_hw_rule_format_by_channels(struct snd_soc_dai *dai,
+						  struct snd_pcm_hw_params *params,
+						  unsigned int nb_ts)
+{
+	struct snd_mask *f_old = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+	unsigned int channels = params_channels(params);
+	unsigned int slot_width;
+	struct snd_mask f_new;
+	unsigned int i;
+
+	if (!channels || channels > nb_ts) {
+		dev_err(dai->dev, "channels %u not supported\n", nb_ts);
+		return -EINVAL;
+	}
+
+	slot_width = (nb_ts / channels) * 8;
+
+	snd_mask_none(&f_new);
+	for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
+		if (snd_mask_test(f_old, i)) {
+			if (snd_pcm_format_physical_width(i) <= slot_width)
+				snd_mask_set(&f_new, i);
+		}
+	}
+
+	return snd_mask_refine(f_old, &f_new);
+}
+
+static int pef2256_dai_hw_rule_playback_format_by_channels(struct snd_pcm_hw_params *params,
+							   struct snd_pcm_hw_rule *rule)
+{
+	struct snd_soc_dai *dai = rule->private;
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(dai->component);
+
+	return pef2256_dai_hw_rule_format_by_channels(dai, params, pef2256->max_chan_playback);
+}
+
+static int pef2256_dai_hw_rule_capture_format_by_channels(struct snd_pcm_hw_params *params,
+							  struct snd_pcm_hw_rule *rule)
+{
+	struct snd_soc_dai *dai = rule->private;
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(dai->component);
+
+	return pef2256_dai_hw_rule_format_by_channels(dai, params, pef2256->max_chan_capture);
+}
+
+static u64 pef2256_formats(u8 nb_ts)
+{
+	u64 formats;
+	unsigned int chan_width;
+	unsigned int format_width;
+	int i;
+
+	if (!nb_ts)
+		return 0;
+
+	formats = 0;
+	chan_width = nb_ts * 8;
+	for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
+		/* Support physical width multiple of 8bit */
+		format_width = snd_pcm_format_physical_width(i);
+		if (format_width == 0 || format_width % 8)
+			continue;
+
+		/*
+		 * And support physical width that can fit N times in the
+		 * channel
+		 */
+		if (format_width > chan_width || chan_width % format_width)
+			continue;
+
+		formats |= (1ULL << i);
+	}
+	return formats;
+}
+
+static int pef2256_dai_startup(struct snd_pcm_substream *substream,
+			       struct snd_soc_dai *dai)
+{
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(dai->component);
+	snd_pcm_hw_rule_func_t hw_rule_channels_by_format;
+	snd_pcm_hw_rule_func_t hw_rule_format_by_channels;
+	unsigned int frame_bits;
+	u64 format;
+	int ret;
+
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		format = pef2256_formats(pef2256->max_chan_capture);
+		hw_rule_channels_by_format = pef2256_dai_hw_rule_capture_channels_by_format;
+		hw_rule_format_by_channels = pef2256_dai_hw_rule_capture_format_by_channels;
+		frame_bits = pef2256->max_chan_capture * 8;
+	} else {
+		format = pef2256_formats(pef2256->max_chan_playback);
+		hw_rule_channels_by_format = pef2256_dai_hw_rule_playback_channels_by_format;
+		hw_rule_format_by_channels = pef2256_dai_hw_rule_playback_format_by_channels;
+		frame_bits = pef2256->max_chan_playback * 8;
+	}
+
+	ret = snd_pcm_hw_constraint_mask64(substream->runtime,
+					   SNDRV_PCM_HW_PARAM_FORMAT, format);
+	if (ret) {
+		dev_err(dai->dev, "Failed to add format constraint (%d)\n", ret);
+		return ret;
+	}
+
+	ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				  hw_rule_channels_by_format, dai,
+				  SNDRV_PCM_HW_PARAM_FORMAT, -1);
+	if (ret) {
+		dev_err(dai->dev, "Failed to add channels rule (%d)\n", ret);
+		return ret;
+	}
+
+	ret = snd_pcm_hw_rule_add(substream->runtime, 0,  SNDRV_PCM_HW_PARAM_FORMAT,
+				  hw_rule_format_by_channels, dai,
+				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	if (ret) {
+		dev_err(dai->dev, "Failed to add format rule (%d)\n", ret);
+		return ret;
+	}
+
+	ret = snd_pcm_hw_constraint_single(substream->runtime,
+					   SNDRV_PCM_HW_PARAM_FRAME_BITS,
+					   frame_bits);
+	if (ret < 0) {
+		dev_err(dai->dev, "Failed to add frame_bits constraint (%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static u64 pef2256_dai_formats[] = {
+	SND_SOC_POSSIBLE_DAIFMT_DSP_B,
+};
+
+static const struct snd_soc_dai_ops pef2256_dai_ops = {
+	.startup	= pef2256_dai_startup,
+	.set_tdm_slot	= pef2256_dai_set_tdm_slot,
+	.auto_selectable_formats     = pef2256_dai_formats,
+	.num_auto_selectable_formats = ARRAY_SIZE(pef2256_dai_formats),
+};
+
+static struct snd_soc_dai_driver pef2256_dai_driver = {
+	.name = "pef2256",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = PEF2256_NB_CHANNEL,
+		.rates = SNDRV_PCM_RATE_8000,
+		.formats = U64_MAX, /* Will be refined on DAI .startup() */
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = PEF2256_NB_CHANNEL,
+		.rates = SNDRV_PCM_RATE_8000,
+		.formats = U64_MAX, /* Will be refined on DAI .startup() */
+	},
+	.ops = &pef2256_dai_ops,
+};
+
+static void pef2256_carrier_work(struct work_struct *work)
+{
+	struct pef2256_codec *pef2256 = container_of(work, struct pef2256_codec, carrier_work);
+	int status;
+
+	status = pef2256_get_carrier(pef2256->pef2256) ? PEF2256_JACK_MASK : 0;
+	snd_soc_jack_report(&pef2256->jack, status, PEF2256_JACK_MASK);
+}
+
+static int pef2256_carrier_notifier(struct notifier_block *nb, unsigned long action,
+				    void *data)
+{
+	struct pef2256_codec *pef2256 = container_of(nb, struct pef2256_codec, nb);
+
+	switch (action) {
+	case PEF2256_EVENT_CARRIER:
+		queue_work(system_power_efficient_wq, &pef2256->carrier_work);
+		break;
+	default:
+		return NOTIFY_DONE;
+	}
+
+	return NOTIFY_OK;
+}
+
+static int pef2256_component_probe(struct snd_soc_component *component)
+{
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(component);
+	char *name;
+	int ret;
+
+	INIT_WORK(&pef2256->carrier_work, pef2256_carrier_work);
+
+	name = "carrier";
+	if (component->name_prefix) {
+		name = kasprintf(GFP_KERNEL, "%s carrier", component->name_prefix);
+		if (!name)
+			return -ENOMEM;
+	}
+
+	ret = snd_soc_card_jack_new(component->card, name, PEF2256_JACK_MASK, &pef2256->jack);
+	if (component->name_prefix)
+		kfree(name); /* A copy is done by snd_soc_card_jack_new */
+	if (ret) {
+		dev_err(component->dev, "Cannot create jack\n");
+		return ret;
+	}
+
+	pef2256->nb.notifier_call = pef2256_carrier_notifier;
+	ret = pef2256_register_event_notifier(pef2256->pef2256, &pef2256->nb);
+	if (ret) {
+		dev_err(component->dev, "Cannot register event notifier\n");
+		return ret;
+	}
+
+	/* Queue work to set the initial value */
+	queue_work(system_power_efficient_wq, &pef2256->carrier_work);
+
+	return 0;
+}
+
+static void pef2256_component_remove(struct snd_soc_component *component)
+{
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(component);
+
+	pef2256_unregister_event_notifier(pef2256->pef2256, &pef2256->nb);
+	cancel_work_sync(&pef2256->carrier_work);
+}
+
+static const struct snd_soc_component_driver pef2256_component_driver = {
+	.probe		= pef2256_component_probe,
+	.remove		= pef2256_component_remove,
+	.endianness	= 1,
+};
+
+static int pef2256_codec_probe(struct platform_device *pdev)
+{
+	struct pef2256_codec *pef2256;
+
+	pef2256 = devm_kzalloc(&pdev->dev, sizeof(*pef2256), GFP_KERNEL);
+	if (!pef2256)
+		return -ENOMEM;
+
+	pef2256->dev = &pdev->dev;
+	pef2256->pef2256 = dev_get_drvdata(pef2256->dev->parent);
+
+	platform_set_drvdata(pdev, pef2256);
+
+	return devm_snd_soc_register_component(&pdev->dev, &pef2256_component_driver,
+					       &pef2256_dai_driver, 1);
+}
+
+static const struct of_device_id pef2256_codec_of_match[] = {
+	{ .compatible = "lantiq,pef2256-codec" },
+	{} /* sentinel */
+};
+MODULE_DEVICE_TABLE(of, pef2256_codec_of_match);
+
+static struct platform_driver pef2256_codec_driver = {
+	.driver = {
+		.name = "lantiq-pef2256-codec",
+		.of_match_table = of_match_ptr(pef2256_codec_of_match),
+	},
+	.probe = pef2256_codec_probe,
+};
+module_platform_driver(pef2256_codec_driver);
+
+MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
+MODULE_DESCRIPTION("PEF2256 ALSA SoC driver");
+MODULE_LICENSE("GPL");
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 5/6] ASoC: codecs: Add support for the Lantiq PEF2256 codec
  2023-03-22 13:46 [PATCH v3 0/6] Add the Lantiq PEF2256 audio support Herve Codina
                   ` (8 preceding siblings ...)
  2023-03-22 13:46 ` [PATCH v3 5/6] ASoC: codecs: " Herve Codina
@ 2023-03-22 13:46 ` Herve Codina via Alsa-devel
  2023-03-22 13:46 ` [PATCH v3 6/6] MAINTAINERS: Add the Lantiq PEF2256 driver entry Herve Codina
  2023-03-22 13:46 ` Herve Codina via Alsa-devel
  11 siblings, 0 replies; 29+ messages in thread
From: Herve Codina via Alsa-devel @ 2023-03-22 13:46 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni


[-- Attachment #0: Type: message/rfc822, Size: 18297 bytes --]

From: Herve Codina <herve.codina@bootlin.com>
To: Herve Codina <herve.codina@bootlin.com>, Lee Jones <lee@kernel.org>, Rob Herring <robh+dt@kernel.org>, Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>, Liam Girdwood <lgirdwood@gmail.com>, Mark Brown <broonie@kernel.org>, Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>
Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, alsa-devel@alsa-project.org, Christophe Leroy <christophe.leroy@csgroup.eu>, Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Subject: [PATCH v3 5/6] ASoC: codecs: Add support for the Lantiq PEF2256 codec
Date: Wed, 22 Mar 2023 14:46:53 +0100
Message-ID: <20230322134654.219957-6-herve.codina@bootlin.com>

The Lantiq PEF2256 is a framer and line interface component designed to
fulfill all required interfacing between an analog E1/T1/J1 line and the
digital PCM system highway/H.100 bus.

The codec support allows to use some of the PCM system highway
time-slots as audio channels to transport audio data over the E1/T1/J1
lines. It provides also line carrier detection events reported through
the ALSA jack detection feature.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 sound/soc/codecs/Kconfig         |  14 ++
 sound/soc/codecs/Makefile        |   2 +
 sound/soc/codecs/pef2256-codec.c | 390 +++++++++++++++++++++++++++++++
 3 files changed, 406 insertions(+)
 create mode 100644 sound/soc/codecs/pef2256-codec.c

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 0be061953e9a..4f78da914fc7 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -168,6 +168,7 @@ config SND_SOC_ALL_CODECS
 	imply SND_SOC_PCM512x_I2C
 	imply SND_SOC_PCM512x_SPI
 	imply SND_SOC_PEB2466
+	imply SND_SOC_PEF2256
 	imply SND_SOC_RK3328
 	imply SND_SOC_RK817
 	imply SND_SOC_RT274
@@ -1252,6 +1253,19 @@ config SND_SOC_PEB2466
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-soc-peb2466.
 
+config SND_SOC_PEF2256
+	tristate "Lantiq PEF2256 codec"
+	depends on MFD_PEF2256
+	help
+	  Enable support for the Lantiq PEF2256 (FALC56) codec.
+	  The PEF2256 is a framer and line interface between analog E1/T1/J1
+	  line and a digital PCM bus.
+	  This codec allows to use some of the time slots available on the
+	  PEF2256 PCM bus to transport some audio data.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-soc-pef2256.
+
 config SND_SOC_RK3328
 	tristate "Rockchip RK3328 audio CODEC"
 	select REGMAP_MMIO
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 20b388b77f1f..11bd66d46f7b 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -188,6 +188,7 @@ snd-soc-pcm512x-objs := pcm512x.o
 snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
 snd-soc-pcm512x-spi-objs := pcm512x-spi.o
 snd-soc-peb2466-objs := peb2466.o
+snd-soc-pef2256-objs := pef2256-codec.o
 snd-soc-rk3328-objs := rk3328_codec.o
 snd-soc-rk817-objs := rk817_codec.o
 snd-soc-rl6231-objs := rl6231.o
@@ -551,6 +552,7 @@ obj-$(CONFIG_SND_SOC_PCM512x)	+= snd-soc-pcm512x.o
 obj-$(CONFIG_SND_SOC_PCM512x_I2C)	+= snd-soc-pcm512x-i2c.o
 obj-$(CONFIG_SND_SOC_PCM512x_SPI)	+= snd-soc-pcm512x-spi.o
 obj-$(CONFIG_SND_SOC_PEB2466)	+= snd-soc-peb2466.o
+obj-$(CONFIG_SND_SOC_PEF2256)	+= snd-soc-pef2256.o
 obj-$(CONFIG_SND_SOC_RK3328)	+= snd-soc-rk3328.o
 obj-$(CONFIG_SND_SOC_RK817)	+= snd-soc-rk817.o
 obj-$(CONFIG_SND_SOC_RL6231)	+= snd-soc-rl6231.o
diff --git a/sound/soc/codecs/pef2256-codec.c b/sound/soc/codecs/pef2256-codec.c
new file mode 100644
index 000000000000..366df39bd866
--- /dev/null
+++ b/sound/soc/codecs/pef2256-codec.c
@@ -0,0 +1,390 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// pef2256.c  --  Lantiq PEF2256 ALSA SoC driver
+//
+// Copyright 2023 CS GROUP France
+//
+// Author: Herve Codina <herve.codina@bootlin.com>
+
+#include <linux/clk.h>
+#include <linux/mfd/pef2256.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <sound/jack.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+#define PEF2256_NB_CHANNEL	32
+#define PEF2256_JACK_MASK (SND_JACK_LINEIN | SND_JACK_LINEOUT)
+
+struct pef2256_codec {
+	struct pef2256 *pef2256;
+	struct device *dev;
+	struct snd_soc_jack jack;
+	struct notifier_block nb;
+	struct work_struct carrier_work;
+	int max_chan_playback;
+	int max_chan_capture;
+};
+
+static int pef2256_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+				    unsigned int rx_mask, int slots, int width)
+{
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(dai->component);
+
+	switch (width) {
+	case 0:
+		/* Not set -> default 8 */
+	case 8:
+		break;
+	default:
+		dev_err(dai->dev, "tdm slot width %d not supported\n", width);
+		return -EINVAL;
+	}
+
+	pef2256->max_chan_playback = hweight32(tx_mask);
+	if (pef2256->max_chan_playback > PEF2256_NB_CHANNEL) {
+		dev_err(dai->dev, "too much tx slots defined (mask = 0x%x) support max %d\n",
+			tx_mask, PEF2256_NB_CHANNEL);
+		return -EINVAL;
+	}
+
+	pef2256->max_chan_capture = hweight32(rx_mask);
+	if (pef2256->max_chan_capture > PEF2256_NB_CHANNEL) {
+		dev_err(dai->dev, "too much rx slots defined (mask = 0x%x) support max %d\n",
+			rx_mask, PEF2256_NB_CHANNEL);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * The constraints for format/channel is to match with the number of 8bit
+ * time-slots available.
+ */
+static int pef2256_dai_hw_rule_channels_by_format(struct snd_soc_dai *dai,
+						  struct snd_pcm_hw_params *params,
+						  unsigned int nb_ts)
+{
+	struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	snd_pcm_format_t format = params_format(params);
+	struct snd_interval ch = {0};
+
+	switch (snd_pcm_format_physical_width(format)) {
+	case 8:
+		ch.max = nb_ts;
+		break;
+	case 16:
+		ch.max = nb_ts/2;
+		break;
+	case 32:
+		ch.max = nb_ts/4;
+		break;
+	case 64:
+		ch.max = nb_ts/8;
+		break;
+	default:
+		dev_err(dai->dev, "format physical width %u not supported\n",
+			snd_pcm_format_physical_width(format));
+		return -EINVAL;
+	}
+
+	ch.min = ch.max ? 1 : 0;
+
+	return snd_interval_refine(c, &ch);
+}
+
+static int pef2256_dai_hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params,
+							   struct snd_pcm_hw_rule *rule)
+{
+	struct snd_soc_dai *dai = rule->private;
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(dai->component);
+
+	return pef2256_dai_hw_rule_channels_by_format(dai, params, pef2256->max_chan_playback);
+}
+
+static int pef2256_dai_hw_rule_capture_channels_by_format(struct snd_pcm_hw_params *params,
+							  struct snd_pcm_hw_rule *rule)
+{
+	struct snd_soc_dai *dai = rule->private;
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(dai->component);
+
+	return pef2256_dai_hw_rule_channels_by_format(dai, params, pef2256->max_chan_capture);
+}
+
+static int pef2256_dai_hw_rule_format_by_channels(struct snd_soc_dai *dai,
+						  struct snd_pcm_hw_params *params,
+						  unsigned int nb_ts)
+{
+	struct snd_mask *f_old = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+	unsigned int channels = params_channels(params);
+	unsigned int slot_width;
+	struct snd_mask f_new;
+	unsigned int i;
+
+	if (!channels || channels > nb_ts) {
+		dev_err(dai->dev, "channels %u not supported\n", nb_ts);
+		return -EINVAL;
+	}
+
+	slot_width = (nb_ts / channels) * 8;
+
+	snd_mask_none(&f_new);
+	for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
+		if (snd_mask_test(f_old, i)) {
+			if (snd_pcm_format_physical_width(i) <= slot_width)
+				snd_mask_set(&f_new, i);
+		}
+	}
+
+	return snd_mask_refine(f_old, &f_new);
+}
+
+static int pef2256_dai_hw_rule_playback_format_by_channels(struct snd_pcm_hw_params *params,
+							   struct snd_pcm_hw_rule *rule)
+{
+	struct snd_soc_dai *dai = rule->private;
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(dai->component);
+
+	return pef2256_dai_hw_rule_format_by_channels(dai, params, pef2256->max_chan_playback);
+}
+
+static int pef2256_dai_hw_rule_capture_format_by_channels(struct snd_pcm_hw_params *params,
+							  struct snd_pcm_hw_rule *rule)
+{
+	struct snd_soc_dai *dai = rule->private;
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(dai->component);
+
+	return pef2256_dai_hw_rule_format_by_channels(dai, params, pef2256->max_chan_capture);
+}
+
+static u64 pef2256_formats(u8 nb_ts)
+{
+	u64 formats;
+	unsigned int chan_width;
+	unsigned int format_width;
+	int i;
+
+	if (!nb_ts)
+		return 0;
+
+	formats = 0;
+	chan_width = nb_ts * 8;
+	for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
+		/* Support physical width multiple of 8bit */
+		format_width = snd_pcm_format_physical_width(i);
+		if (format_width == 0 || format_width % 8)
+			continue;
+
+		/*
+		 * And support physical width that can fit N times in the
+		 * channel
+		 */
+		if (format_width > chan_width || chan_width % format_width)
+			continue;
+
+		formats |= (1ULL << i);
+	}
+	return formats;
+}
+
+static int pef2256_dai_startup(struct snd_pcm_substream *substream,
+			       struct snd_soc_dai *dai)
+{
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(dai->component);
+	snd_pcm_hw_rule_func_t hw_rule_channels_by_format;
+	snd_pcm_hw_rule_func_t hw_rule_format_by_channels;
+	unsigned int frame_bits;
+	u64 format;
+	int ret;
+
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		format = pef2256_formats(pef2256->max_chan_capture);
+		hw_rule_channels_by_format = pef2256_dai_hw_rule_capture_channels_by_format;
+		hw_rule_format_by_channels = pef2256_dai_hw_rule_capture_format_by_channels;
+		frame_bits = pef2256->max_chan_capture * 8;
+	} else {
+		format = pef2256_formats(pef2256->max_chan_playback);
+		hw_rule_channels_by_format = pef2256_dai_hw_rule_playback_channels_by_format;
+		hw_rule_format_by_channels = pef2256_dai_hw_rule_playback_format_by_channels;
+		frame_bits = pef2256->max_chan_playback * 8;
+	}
+
+	ret = snd_pcm_hw_constraint_mask64(substream->runtime,
+					   SNDRV_PCM_HW_PARAM_FORMAT, format);
+	if (ret) {
+		dev_err(dai->dev, "Failed to add format constraint (%d)\n", ret);
+		return ret;
+	}
+
+	ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				  hw_rule_channels_by_format, dai,
+				  SNDRV_PCM_HW_PARAM_FORMAT, -1);
+	if (ret) {
+		dev_err(dai->dev, "Failed to add channels rule (%d)\n", ret);
+		return ret;
+	}
+
+	ret = snd_pcm_hw_rule_add(substream->runtime, 0,  SNDRV_PCM_HW_PARAM_FORMAT,
+				  hw_rule_format_by_channels, dai,
+				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	if (ret) {
+		dev_err(dai->dev, "Failed to add format rule (%d)\n", ret);
+		return ret;
+	}
+
+	ret = snd_pcm_hw_constraint_single(substream->runtime,
+					   SNDRV_PCM_HW_PARAM_FRAME_BITS,
+					   frame_bits);
+	if (ret < 0) {
+		dev_err(dai->dev, "Failed to add frame_bits constraint (%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static u64 pef2256_dai_formats[] = {
+	SND_SOC_POSSIBLE_DAIFMT_DSP_B,
+};
+
+static const struct snd_soc_dai_ops pef2256_dai_ops = {
+	.startup	= pef2256_dai_startup,
+	.set_tdm_slot	= pef2256_dai_set_tdm_slot,
+	.auto_selectable_formats     = pef2256_dai_formats,
+	.num_auto_selectable_formats = ARRAY_SIZE(pef2256_dai_formats),
+};
+
+static struct snd_soc_dai_driver pef2256_dai_driver = {
+	.name = "pef2256",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = PEF2256_NB_CHANNEL,
+		.rates = SNDRV_PCM_RATE_8000,
+		.formats = U64_MAX, /* Will be refined on DAI .startup() */
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = PEF2256_NB_CHANNEL,
+		.rates = SNDRV_PCM_RATE_8000,
+		.formats = U64_MAX, /* Will be refined on DAI .startup() */
+	},
+	.ops = &pef2256_dai_ops,
+};
+
+static void pef2256_carrier_work(struct work_struct *work)
+{
+	struct pef2256_codec *pef2256 = container_of(work, struct pef2256_codec, carrier_work);
+	int status;
+
+	status = pef2256_get_carrier(pef2256->pef2256) ? PEF2256_JACK_MASK : 0;
+	snd_soc_jack_report(&pef2256->jack, status, PEF2256_JACK_MASK);
+}
+
+static int pef2256_carrier_notifier(struct notifier_block *nb, unsigned long action,
+				    void *data)
+{
+	struct pef2256_codec *pef2256 = container_of(nb, struct pef2256_codec, nb);
+
+	switch (action) {
+	case PEF2256_EVENT_CARRIER:
+		queue_work(system_power_efficient_wq, &pef2256->carrier_work);
+		break;
+	default:
+		return NOTIFY_DONE;
+	}
+
+	return NOTIFY_OK;
+}
+
+static int pef2256_component_probe(struct snd_soc_component *component)
+{
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(component);
+	char *name;
+	int ret;
+
+	INIT_WORK(&pef2256->carrier_work, pef2256_carrier_work);
+
+	name = "carrier";
+	if (component->name_prefix) {
+		name = kasprintf(GFP_KERNEL, "%s carrier", component->name_prefix);
+		if (!name)
+			return -ENOMEM;
+	}
+
+	ret = snd_soc_card_jack_new(component->card, name, PEF2256_JACK_MASK, &pef2256->jack);
+	if (component->name_prefix)
+		kfree(name); /* A copy is done by snd_soc_card_jack_new */
+	if (ret) {
+		dev_err(component->dev, "Cannot create jack\n");
+		return ret;
+	}
+
+	pef2256->nb.notifier_call = pef2256_carrier_notifier;
+	ret = pef2256_register_event_notifier(pef2256->pef2256, &pef2256->nb);
+	if (ret) {
+		dev_err(component->dev, "Cannot register event notifier\n");
+		return ret;
+	}
+
+	/* Queue work to set the initial value */
+	queue_work(system_power_efficient_wq, &pef2256->carrier_work);
+
+	return 0;
+}
+
+static void pef2256_component_remove(struct snd_soc_component *component)
+{
+	struct pef2256_codec *pef2256 = snd_soc_component_get_drvdata(component);
+
+	pef2256_unregister_event_notifier(pef2256->pef2256, &pef2256->nb);
+	cancel_work_sync(&pef2256->carrier_work);
+}
+
+static const struct snd_soc_component_driver pef2256_component_driver = {
+	.probe		= pef2256_component_probe,
+	.remove		= pef2256_component_remove,
+	.endianness	= 1,
+};
+
+static int pef2256_codec_probe(struct platform_device *pdev)
+{
+	struct pef2256_codec *pef2256;
+
+	pef2256 = devm_kzalloc(&pdev->dev, sizeof(*pef2256), GFP_KERNEL);
+	if (!pef2256)
+		return -ENOMEM;
+
+	pef2256->dev = &pdev->dev;
+	pef2256->pef2256 = dev_get_drvdata(pef2256->dev->parent);
+
+	platform_set_drvdata(pdev, pef2256);
+
+	return devm_snd_soc_register_component(&pdev->dev, &pef2256_component_driver,
+					       &pef2256_dai_driver, 1);
+}
+
+static const struct of_device_id pef2256_codec_of_match[] = {
+	{ .compatible = "lantiq,pef2256-codec" },
+	{} /* sentinel */
+};
+MODULE_DEVICE_TABLE(of, pef2256_codec_of_match);
+
+static struct platform_driver pef2256_codec_driver = {
+	.driver = {
+		.name = "lantiq-pef2256-codec",
+		.of_match_table = of_match_ptr(pef2256_codec_of_match),
+	},
+	.probe = pef2256_codec_probe,
+};
+module_platform_driver(pef2256_codec_driver);
+
+MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
+MODULE_DESCRIPTION("PEF2256 ALSA SoC driver");
+MODULE_LICENSE("GPL");
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 6/6] MAINTAINERS: Add the Lantiq PEF2256 driver entry
  2023-03-22 13:46 [PATCH v3 0/6] Add the Lantiq PEF2256 audio support Herve Codina
                   ` (9 preceding siblings ...)
  2023-03-22 13:46 ` Herve Codina via Alsa-devel
@ 2023-03-22 13:46 ` Herve Codina
  2023-03-22 13:46 ` Herve Codina via Alsa-devel
  11 siblings, 0 replies; 29+ messages in thread
From: Herve Codina @ 2023-03-22 13:46 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni

After contributing the driver, add myself as the maintainer for the
Lantiq PEF2256 driver.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 MAINTAINERS | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index fcb69242cd19..be38a24c031c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11651,6 +11651,16 @@ S:	Maintained
 F:	arch/mips/lantiq
 F:	drivers/soc/lantiq
 
+LANTIQ PEF2256 DRIVER
+M:	Herve Codina <herve.codina@bootlin.com>
+S:	Maintained
+F:	Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256
+F:	Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
+F:	Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
+F:	drivers/mfd/pef2256.c
+F:	include/linux/mfd/pef2256.h
+F:	sound/soc/codecs/pef2256-codec.c
+
 LASI 53c700 driver for PARISC
 M:	"James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
 L:	linux-scsi@vger.kernel.org
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 6/6] MAINTAINERS: Add the Lantiq PEF2256 driver entry
  2023-03-22 13:46 [PATCH v3 0/6] Add the Lantiq PEF2256 audio support Herve Codina
                   ` (10 preceding siblings ...)
  2023-03-22 13:46 ` [PATCH v3 6/6] MAINTAINERS: Add the Lantiq PEF2256 driver entry Herve Codina
@ 2023-03-22 13:46 ` Herve Codina via Alsa-devel
  11 siblings, 0 replies; 29+ messages in thread
From: Herve Codina via Alsa-devel @ 2023-03-22 13:46 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni


[-- Attachment #0: Type: message/rfc822, Size: 4879 bytes --]

From: Herve Codina <herve.codina@bootlin.com>
To: Herve Codina <herve.codina@bootlin.com>, Lee Jones <lee@kernel.org>, Rob Herring <robh+dt@kernel.org>, Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>, Liam Girdwood <lgirdwood@gmail.com>, Mark Brown <broonie@kernel.org>, Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>
Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, alsa-devel@alsa-project.org, Christophe Leroy <christophe.leroy@csgroup.eu>, Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Subject: [PATCH v3 6/6] MAINTAINERS: Add the Lantiq PEF2256 driver entry
Date: Wed, 22 Mar 2023 14:46:54 +0100
Message-ID: <20230322134654.219957-7-herve.codina@bootlin.com>

After contributing the driver, add myself as the maintainer for the
Lantiq PEF2256 driver.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 MAINTAINERS | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index fcb69242cd19..be38a24c031c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11651,6 +11651,16 @@ S:	Maintained
 F:	arch/mips/lantiq
 F:	drivers/soc/lantiq
 
+LANTIQ PEF2256 DRIVER
+M:	Herve Codina <herve.codina@bootlin.com>
+S:	Maintained
+F:	Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256
+F:	Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
+F:	Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
+F:	drivers/mfd/pef2256.c
+F:	include/linux/mfd/pef2256.h
+F:	sound/soc/codecs/pef2256-codec.c
+
 LASI 53c700 driver for PARISC
 M:	"James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
 L:	linux-scsi@vger.kernel.org
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 1/6] dt-bindings: mfd: Add the Lantiq PEF2256 E1/T1/J1 framer
  2023-03-22 13:46 ` [PATCH v3 1/6] dt-bindings: mfd: Add the Lantiq PEF2256 E1/T1/J1 framer Herve Codina
@ 2023-03-22 21:58   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2023-03-22 21:58 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni

On 22/03/2023 14:46, Herve Codina wrote:
> The Lantiq PEF2256 is a framer and line interface component designed to
> fulfill all required interfacing between an analog E1/T1/J1 line and the
> digital PCM system highway/H.100 bus.
> 


> +  lantiq,channel-phase:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    enum: [0, 1, 2, 3, 4, 5, 6, 7]
> +    default: 0
> +    description:
> +      The pef2256 delivers a full frame (32 8bit time-slots in E1 and 24 8bit
> +      time-slots 8 8bit signaling in E1/J1) every 125us. This lead to a data
> +      rate of 2048000 bit/s. When lantiq,data-rate-bps is more than 2048000
> +      bit/s, the data (all 32 8bit) present in the frame are interleave with
> +      unused time-slots. The lantiq,channel-phase property allows to set the
> +      correct alignment of the interleave mechanism.
> +      For instance, suppose lantiq,data-rate-bps = 8192000 (ie 4*2048000), and
> +      lantiq,channel-phase = 2, the interleave schema with unused time-slots
> +      (nu) and used time-slots (XX) for TSi is
> +        nu nu XX nu nu nu XX nu nu nu XX nu
> +        <-- TSi --> <- TSi+1 -> <- TSi+2 ->
> +      With lantiq,data-rate-bps = 8192000, and lantiq,channel-phase = 1, the
> +      interleave schema is
> +        nu XX nu nu nu XX nu nu nu XX nu nu
> +        <-- TSi --> <- TSi+1 -> <- TSi+2 ->
> +      With lantiq,data-rate-bps = 4096000 (ie 2*2048000), and
> +      lantiq,channel-phase = 1, the interleave schema is
> +        nu    XX    nu    XX    nu    XX
> +        <-- TSi --> <- TSi+1 -> <- TSi+2 ->
> +
> +  lantiq,subordinate:
> +    $ref: /schemas/types.yaml#/definitions/flag
> +    description:
> +      If present, the pef2256 works in subordinate mode. In this mode it
> +      synchronizes on line interface clock signals. Otherwise, it synchronizes
> +      on internal clocks.
> +
> +patternProperties:
> +  '^codec([0-9]|[1-2][0-9]|3[0-1])?$':
> +    $ref: /schemas/sound/lantiq,pef2256-codec.yaml

Does not look bisectable. I also could not find in commit msg or in
cover letter description of patch merging requirements.
> +
> +allOf:

allOf goes usually after required, just like in example-schema.
Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec
  2023-03-22 13:46 ` [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec Herve Codina
@ 2023-03-22 21:59   ` Krzysztof Kozlowski
  2023-03-23  7:27     ` Herve Codina
  2023-03-23  7:27     ` Herve Codina via Alsa-devel
  0 siblings, 2 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2023-03-22 21:59 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni

On 22/03/2023 14:46, Herve Codina wrote:
> The Lantiq PEF2256 is a framer and line interface component designed to
> fulfill all required interfacing between an analog E1/T1/J1 line and the
> digital PCM system highway/H.100 bus.
> 
> The codec support allows to use some of the PCM system highway
> time-slots as audio channels to transport audio data over the E1/T1/J1
> lines.
> 
> Signed-off-by: Herve Codina <herve.codina@bootlin.com>
> ---
>  .../bindings/sound/lantiq,pef2256-codec.yaml  | 54 +++++++++++++++++++
>  1 file changed, 54 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
> 
> diff --git a/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
> new file mode 100644
> index 000000000000..da35b70cda99
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
> @@ -0,0 +1,54 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/lantiq,pef2256-codec.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Lantiq PEF2256 codec
> +
> +maintainers:
> +  - Herve Codina <herve.codina@bootlin.com>
> +
> +description: |
> +  Codec support for PEF2256.
> +
> +  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and
> +  line interface component designed to fulfill all required interfacing between
> +  an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.
> +
> +  The codec support allows to use some of the PCM system highway time-slots as
> +  audio channels to transport audio data over the E1/T1/J1 lines.
> +
> +  The time-slots used by the codec must be set and so, the properties
> +  'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and
> +  'dai-tdm-slot-rx-mask' must be present in the ALSA sound card node for
> +  sub-nodes that involve the codec. The codec uses 8bit time-slots.
> +  'dai-tdm-tdm-slot-with' must be set to 8.
> +  The tx and rx masks define the PEF2256 time-slots assigned to the codec.
> +
> +  The PEF2256 codec node should be a child of a PEF2256 node.
> +  Refer to the bindings described in
> +  Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
> +
> +allOf:
> +  - $ref: dai-common.yaml#
> +
> +properties:
> +  compatible:
> +    const: lantiq,pef2256-codec
> +
> +  '#sound-dai-cells':
> +    const: 0

You do not have here any resources, so the entire binding can be dropped
and merged into the parent.

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec
  2023-03-22 21:59   ` Krzysztof Kozlowski
@ 2023-03-23  7:27     ` Herve Codina
  2023-03-23  7:31         ` Krzysztof Kozlowski
  2023-03-23  7:27     ` Herve Codina via Alsa-devel
  1 sibling, 1 reply; 29+ messages in thread
From: Herve Codina @ 2023-03-23  7:27 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Liam Girdwood,
	Mark Brown, Jaroslav Kysela, Takashi Iwai, linux-kernel,
	devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni

Hi Krzysztof

On Wed, 22 Mar 2023 22:59:37 +0100
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:

> On 22/03/2023 14:46, Herve Codina wrote:
> > The Lantiq PEF2256 is a framer and line interface component designed to
> > fulfill all required interfacing between an analog E1/T1/J1 line and the
> > digital PCM system highway/H.100 bus.
> > 
> > The codec support allows to use some of the PCM system highway
> > time-slots as audio channels to transport audio data over the E1/T1/J1
> > lines.
> > 
> > Signed-off-by: Herve Codina <herve.codina@bootlin.com>
> > ---
> >  .../bindings/sound/lantiq,pef2256-codec.yaml  | 54 +++++++++++++++++++
> >  1 file changed, 54 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
> > 
> > diff --git a/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
> > new file mode 100644
> > index 000000000000..da35b70cda99
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
> > @@ -0,0 +1,54 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/sound/lantiq,pef2256-codec.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Lantiq PEF2256 codec
> > +
> > +maintainers:
> > +  - Herve Codina <herve.codina@bootlin.com>
> > +
> > +description: |
> > +  Codec support for PEF2256.
> > +
> > +  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and
> > +  line interface component designed to fulfill all required interfacing between
> > +  an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.
> > +
> > +  The codec support allows to use some of the PCM system highway time-slots as
> > +  audio channels to transport audio data over the E1/T1/J1 lines.
> > +
> > +  The time-slots used by the codec must be set and so, the properties
> > +  'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and
> > +  'dai-tdm-slot-rx-mask' must be present in the ALSA sound card node for
> > +  sub-nodes that involve the codec. The codec uses 8bit time-slots.
> > +  'dai-tdm-tdm-slot-with' must be set to 8.
> > +  The tx and rx masks define the PEF2256 time-slots assigned to the codec.
> > +
> > +  The PEF2256 codec node should be a child of a PEF2256 node.
> > +  Refer to the bindings described in
> > +  Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
> > +
> > +allOf:
> > +  - $ref: dai-common.yaml#
> > +
> > +properties:
> > +  compatible:
> > +    const: lantiq,pef2256-codec
> > +
> > +  '#sound-dai-cells':
> > +    const: 0  
> 
> You do not have here any resources, so the entire binding can be dropped
> and merged into the parent.
> 
> Best regards,
> Krzysztof
> 

Ok,
Do you expect all these properties (except compatible) merged at the parent
level or may I keep a child node with these properties including the
compatible property (ie. yaml file merge).

Regards,
Hervé

-- 
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec
  2023-03-22 21:59   ` Krzysztof Kozlowski
  2023-03-23  7:27     ` Herve Codina
@ 2023-03-23  7:27     ` Herve Codina via Alsa-devel
  1 sibling, 0 replies; 29+ messages in thread
From: Herve Codina via Alsa-devel @ 2023-03-23  7:27 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Liam Girdwood,
	Mark Brown, Takashi Iwai, linux-kernel, devicetree, alsa-devel,
	Christophe Leroy, Thomas Petazzoni


[-- Attachment #0: Type: message/rfc822, Size: 7309 bytes --]

From: Herve Codina <herve.codina@bootlin.com>
To: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Cc: Lee Jones <lee@kernel.org>, Rob Herring <robh+dt@kernel.org>, Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>, Liam Girdwood <lgirdwood@gmail.com>, Mark Brown <broonie@kernel.org>, Takashi Iwai <tiwai@suse.com>, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, alsa-devel@alsa-project.org, Christophe Leroy <christophe.leroy@csgroup.eu>, Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Subject: Re: [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec
Date: Thu, 23 Mar 2023 08:27:58 +0100
Message-ID: <20230323082758.5e4385ff@bootlin.com>

Hi Krzysztof

On Wed, 22 Mar 2023 22:59:37 +0100
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:

> On 22/03/2023 14:46, Herve Codina wrote:
> > The Lantiq PEF2256 is a framer and line interface component designed to
> > fulfill all required interfacing between an analog E1/T1/J1 line and the
> > digital PCM system highway/H.100 bus.
> > 
> > The codec support allows to use some of the PCM system highway
> > time-slots as audio channels to transport audio data over the E1/T1/J1
> > lines.
> > 
> > Signed-off-by: Herve Codina <herve.codina@bootlin.com>
> > ---
> >  .../bindings/sound/lantiq,pef2256-codec.yaml  | 54 +++++++++++++++++++
> >  1 file changed, 54 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
> > 
> > diff --git a/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
> > new file mode 100644
> > index 000000000000..da35b70cda99
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
> > @@ -0,0 +1,54 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/sound/lantiq,pef2256-codec.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Lantiq PEF2256 codec
> > +
> > +maintainers:
> > +  - Herve Codina <herve.codina@bootlin.com>
> > +
> > +description: |
> > +  Codec support for PEF2256.
> > +
> > +  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and
> > +  line interface component designed to fulfill all required interfacing between
> > +  an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.
> > +
> > +  The codec support allows to use some of the PCM system highway time-slots as
> > +  audio channels to transport audio data over the E1/T1/J1 lines.
> > +
> > +  The time-slots used by the codec must be set and so, the properties
> > +  'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and
> > +  'dai-tdm-slot-rx-mask' must be present in the ALSA sound card node for
> > +  sub-nodes that involve the codec. The codec uses 8bit time-slots.
> > +  'dai-tdm-tdm-slot-with' must be set to 8.
> > +  The tx and rx masks define the PEF2256 time-slots assigned to the codec.
> > +
> > +  The PEF2256 codec node should be a child of a PEF2256 node.
> > +  Refer to the bindings described in
> > +  Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
> > +
> > +allOf:
> > +  - $ref: dai-common.yaml#
> > +
> > +properties:
> > +  compatible:
> > +    const: lantiq,pef2256-codec
> > +
> > +  '#sound-dai-cells':
> > +    const: 0  
> 
> You do not have here any resources, so the entire binding can be dropped
> and merged into the parent.
> 
> Best regards,
> Krzysztof
> 

Ok,
Do you expect all these properties (except compatible) merged at the parent
level or may I keep a child node with these properties including the
compatible property (ie. yaml file merge).

Regards,
Hervé

-- 
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer
  2023-03-22 13:46 ` Herve Codina
@ 2023-03-23  7:30   ` Krzysztof Kozlowski
  2023-03-23  8:31     ` Herve Codina
  2023-03-23  8:31     ` Herve Codina via Alsa-devel
  2023-03-26 15:49   ` kernel test robot
  1 sibling, 2 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2023-03-23  7:30 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: linux-kernel, devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni

On 22/03/2023 14:46, Herve Codina wrote:
> The Lantiq PEF2256 is a framer and line interface component designed to
> fulfill all required interfacing between an analog E1/T1/J1 line and the
> digital PCM system highway/H.100 bus.
> 
> Signed-off-by: Herve Codina <herve.codina@bootlin.com>


> +static const struct of_device_id pef2256_id_table[] = {
> +	{ .compatible = "lantiq,pef2256" },
> +	{} /* sentinel */
> +};
> +MODULE_DEVICE_TABLE(of, pef2256_id_table);
> +
> +static struct platform_driver pef2256_driver = {
> +	.driver = {
> +		.name = "lantiq-pef2256",
> +		.of_match_table = of_match_ptr(pef2256_id_table),

Drop of_match_ptr. This will case warnings with W=1 and !OF.

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec
  2023-03-23  7:27     ` Herve Codina
@ 2023-03-23  7:31         ` Krzysztof Kozlowski
  0 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2023-03-23  7:31 UTC (permalink / raw)
  To: Herve Codina
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Liam Girdwood,
	Mark Brown, Jaroslav Kysela, Takashi Iwai, linux-kernel,
	devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni

On 23/03/2023 08:27, Herve Codina wrote:
> Hi Krzysztof
> 
> On Wed, 22 Mar 2023 22:59:37 +0100
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:
> 
>> On 22/03/2023 14:46, Herve Codina wrote:
>>> The Lantiq PEF2256 is a framer and line interface component designed to
>>> fulfill all required interfacing between an analog E1/T1/J1 line and the
>>> digital PCM system highway/H.100 bus.
>>>
>>> The codec support allows to use some of the PCM system highway
>>> time-slots as audio channels to transport audio data over the E1/T1/J1
>>> lines.
>>>
>>> Signed-off-by: Herve Codina <herve.codina@bootlin.com>
>>> ---
>>>  .../bindings/sound/lantiq,pef2256-codec.yaml  | 54 +++++++++++++++++++
>>>  1 file changed, 54 insertions(+)
>>>  create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
>>>
>>> diff --git a/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
>>> new file mode 100644
>>> index 000000000000..da35b70cda99
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
>>> @@ -0,0 +1,54 @@
>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>> +%YAML 1.2
>>> +---
>>> +$id: http://devicetree.org/schemas/sound/lantiq,pef2256-codec.yaml#
>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>> +
>>> +title: Lantiq PEF2256 codec
>>> +
>>> +maintainers:
>>> +  - Herve Codina <herve.codina@bootlin.com>
>>> +
>>> +description: |
>>> +  Codec support for PEF2256.
>>> +
>>> +  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and
>>> +  line interface component designed to fulfill all required interfacing between
>>> +  an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.
>>> +
>>> +  The codec support allows to use some of the PCM system highway time-slots as
>>> +  audio channels to transport audio data over the E1/T1/J1 lines.
>>> +
>>> +  The time-slots used by the codec must be set and so, the properties
>>> +  'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and
>>> +  'dai-tdm-slot-rx-mask' must be present in the ALSA sound card node for
>>> +  sub-nodes that involve the codec. The codec uses 8bit time-slots.
>>> +  'dai-tdm-tdm-slot-with' must be set to 8.
>>> +  The tx and rx masks define the PEF2256 time-slots assigned to the codec.
>>> +
>>> +  The PEF2256 codec node should be a child of a PEF2256 node.
>>> +  Refer to the bindings described in
>>> +  Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
>>> +
>>> +allOf:
>>> +  - $ref: dai-common.yaml#
>>> +
>>> +properties:
>>> +  compatible:
>>> +    const: lantiq,pef2256-codec
>>> +
>>> +  '#sound-dai-cells':
>>> +    const: 0  
>>
>> You do not have here any resources, so the entire binding can be dropped
>> and merged into the parent.
>>
>> Best regards,
>> Krzysztof
>>
> 
> Ok,
> Do you expect all these properties (except compatible) merged at the parent

You have only two properties here - dai cells and name-prefix...

> level or may I keep a child node with these properties including the
> compatible property (ie. yaml file merge).

I was thinking that these should be merged into parent because usually
you do not need child node for this. However now I started to think how
the codec driver would look like. Essentially the parent MFD driver
would need to register dais...

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec
@ 2023-03-23  7:31         ` Krzysztof Kozlowski
  0 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2023-03-23  7:31 UTC (permalink / raw)
  To: Herve Codina
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Liam Girdwood,
	Mark Brown, Takashi Iwai, linux-kernel, devicetree, alsa-devel,
	Christophe Leroy, Thomas Petazzoni

On 23/03/2023 08:27, Herve Codina wrote:
> Hi Krzysztof
> 
> On Wed, 22 Mar 2023 22:59:37 +0100
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:
> 
>> On 22/03/2023 14:46, Herve Codina wrote:
>>> The Lantiq PEF2256 is a framer and line interface component designed to
>>> fulfill all required interfacing between an analog E1/T1/J1 line and the
>>> digital PCM system highway/H.100 bus.
>>>
>>> The codec support allows to use some of the PCM system highway
>>> time-slots as audio channels to transport audio data over the E1/T1/J1
>>> lines.
>>>
>>> Signed-off-by: Herve Codina <herve.codina@bootlin.com>
>>> ---
>>>  .../bindings/sound/lantiq,pef2256-codec.yaml  | 54 +++++++++++++++++++
>>>  1 file changed, 54 insertions(+)
>>>  create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
>>>
>>> diff --git a/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
>>> new file mode 100644
>>> index 000000000000..da35b70cda99
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
>>> @@ -0,0 +1,54 @@
>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>> +%YAML 1.2
>>> +---
>>> +$id: http://devicetree.org/schemas/sound/lantiq,pef2256-codec.yaml#
>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>> +
>>> +title: Lantiq PEF2256 codec
>>> +
>>> +maintainers:
>>> +  - Herve Codina <herve.codina@bootlin.com>
>>> +
>>> +description: |
>>> +  Codec support for PEF2256.
>>> +
>>> +  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and
>>> +  line interface component designed to fulfill all required interfacing between
>>> +  an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.
>>> +
>>> +  The codec support allows to use some of the PCM system highway time-slots as
>>> +  audio channels to transport audio data over the E1/T1/J1 lines.
>>> +
>>> +  The time-slots used by the codec must be set and so, the properties
>>> +  'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and
>>> +  'dai-tdm-slot-rx-mask' must be present in the ALSA sound card node for
>>> +  sub-nodes that involve the codec. The codec uses 8bit time-slots.
>>> +  'dai-tdm-tdm-slot-with' must be set to 8.
>>> +  The tx and rx masks define the PEF2256 time-slots assigned to the codec.
>>> +
>>> +  The PEF2256 codec node should be a child of a PEF2256 node.
>>> +  Refer to the bindings described in
>>> +  Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
>>> +
>>> +allOf:
>>> +  - $ref: dai-common.yaml#
>>> +
>>> +properties:
>>> +  compatible:
>>> +    const: lantiq,pef2256-codec
>>> +
>>> +  '#sound-dai-cells':
>>> +    const: 0  
>>
>> You do not have here any resources, so the entire binding can be dropped
>> and merged into the parent.
>>
>> Best regards,
>> Krzysztof
>>
> 
> Ok,
> Do you expect all these properties (except compatible) merged at the parent

You have only two properties here - dai cells and name-prefix...

> level or may I keep a child node with these properties including the
> compatible property (ie. yaml file merge).

I was thinking that these should be merged into parent because usually
you do not need child node for this. However now I started to think how
the codec driver would look like. Essentially the parent MFD driver
would need to register dais...

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec
  2023-03-23  7:31         ` Krzysztof Kozlowski
  (?)
  (?)
@ 2023-03-23  8:10         ` Herve Codina
  2023-03-26 12:21             ` Krzysztof Kozlowski
  -1 siblings, 1 reply; 29+ messages in thread
From: Herve Codina @ 2023-03-23  8:10 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Liam Girdwood,
	Mark Brown, Jaroslav Kysela, Takashi Iwai, linux-kernel,
	devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni

On Thu, 23 Mar 2023 08:31:28 +0100
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:

> On 23/03/2023 08:27, Herve Codina wrote:
> > Hi Krzysztof
> > 
> > On Wed, 22 Mar 2023 22:59:37 +0100
> > Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:
> >   
> >> On 22/03/2023 14:46, Herve Codina wrote:  
> >>> The Lantiq PEF2256 is a framer and line interface component designed to
> >>> fulfill all required interfacing between an analog E1/T1/J1 line and the
> >>> digital PCM system highway/H.100 bus.
> >>>
> >>> The codec support allows to use some of the PCM system highway
> >>> time-slots as audio channels to transport audio data over the E1/T1/J1
> >>> lines.
> >>>
> >>> Signed-off-by: Herve Codina <herve.codina@bootlin.com>
> >>> ---
> >>>  .../bindings/sound/lantiq,pef2256-codec.yaml  | 54 +++++++++++++++++++
> >>>  1 file changed, 54 insertions(+)
> >>>  create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
> >>>
> >>> diff --git a/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
> >>> new file mode 100644
> >>> index 000000000000..da35b70cda99
> >>> --- /dev/null
> >>> +++ b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
> >>> @@ -0,0 +1,54 @@
> >>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> >>> +%YAML 1.2
> >>> +---
> >>> +$id: http://devicetree.org/schemas/sound/lantiq,pef2256-codec.yaml#
> >>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> >>> +
> >>> +title: Lantiq PEF2256 codec
> >>> +
> >>> +maintainers:
> >>> +  - Herve Codina <herve.codina@bootlin.com>
> >>> +
> >>> +description: |
> >>> +  Codec support for PEF2256.
> >>> +
> >>> +  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and
> >>> +  line interface component designed to fulfill all required interfacing between
> >>> +  an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.
> >>> +
> >>> +  The codec support allows to use some of the PCM system highway time-slots as
> >>> +  audio channels to transport audio data over the E1/T1/J1 lines.
> >>> +
> >>> +  The time-slots used by the codec must be set and so, the properties
> >>> +  'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and
> >>> +  'dai-tdm-slot-rx-mask' must be present in the ALSA sound card node for
> >>> +  sub-nodes that involve the codec. The codec uses 8bit time-slots.
> >>> +  'dai-tdm-tdm-slot-with' must be set to 8.
> >>> +  The tx and rx masks define the PEF2256 time-slots assigned to the codec.
> >>> +
> >>> +  The PEF2256 codec node should be a child of a PEF2256 node.
> >>> +  Refer to the bindings described in
> >>> +  Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
> >>> +
> >>> +allOf:
> >>> +  - $ref: dai-common.yaml#
> >>> +
> >>> +properties:
> >>> +  compatible:
> >>> +    const: lantiq,pef2256-codec
> >>> +
> >>> +  '#sound-dai-cells':
> >>> +    const: 0    
> >>
> >> You do not have here any resources, so the entire binding can be dropped
> >> and merged into the parent.
> >>
> >> Best regards,
> >> Krzysztof
> >>  
> > 
> > Ok,
> > Do you expect all these properties (except compatible) merged at the parent  
> 
> You have only two properties here - dai cells and name-prefix...
> 
> > level or may I keep a child node with these properties including the
> > compatible property (ie. yaml file merge).  
> 
> I was thinking that these should be merged into parent because usually
> you do not need child node for this. However now I started to think how
> the codec driver would look like. Essentially the parent MFD driver
> would need to register dais...
> 

There is also something specific to audio, the slots definition
'dai-tdm-slot-tx-mask' and 'dai-tdm-slot-rx-mask'. These slots definitions
are set at the ALSA sound card sub-nodes.
So, I can have multiple codec in the PEF2256.

For instance:
  framer {
    compatible = "lantiq,pef2256", "simple-mfd";
    ...
    pef2256_codec0: codec0 {
      compatible = "lantiq,pef2256-codec";
      #sound-dai-cells = <0>;
    };
    pef2256_codec1: codec1 {
      compatible = "lantiq,pef2256-codec";
      #sound-dai-cells = <0>;
    };
  };

  sound {
    compatible = "simple-audio-card";
    #address-cells = <1>;
    #size-cells = <0>;
    simple-audio-card,dai-link@0 { /* CPU DAI1 - pef2256 codec 1 */
      reg = <0>;
      cpu {
        sound-dai = <&cpu_dai1>;
      };
      codec {
        sound-dai = <&pef2256_codec0>;
	dai-tdm-slot-num = <4>;
	dai-tdm-slot-width = <8>;
	/* TS 2, 3, 4, 5 */
	dai-tdm-slot-tx-mask = <0 1 1 1 1>;
	dai-tdm-slot-rx-mask = <0 1 1 1 1>;
      };
    simple-audio-card,dai-link@1 { /* CPU DAI2 - pef2256 codec 2 */
      reg = <1>;
      cpu {
        sound-dai = <&cpu_dai2>;
      };
      codec {
	sound-dai = <&pef2256_codec1>;
	dai-tdm-slot-num = <4>;
	dai-tdm-slot-width = <8>;
	/* TS 6, 7, 8, 9 */
	dai-tdm-slot-tx-mask = <0 0 0 0 0 1 1 1 1>;
	dai-tdm-slot-rx-mask = <0 0 0 0 0 1 1 1 1>;
      };
    };
  };

To solve this, I can use #sound-dai-cells = <1>; but this will complicate
the driver itself and is it really needed ?
Having "simple-mfd" dans sub-nodes keep all things simple.

Regards,
Hervé

-- 
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec
  2023-03-23  7:31         ` Krzysztof Kozlowski
  (?)
@ 2023-03-23  8:10         ` Herve Codina via Alsa-devel
  -1 siblings, 0 replies; 29+ messages in thread
From: Herve Codina via Alsa-devel @ 2023-03-23  8:10 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Liam Girdwood,
	Mark Brown, Takashi Iwai, linux-kernel, devicetree, alsa-devel,
	Christophe Leroy, Thomas Petazzoni


[-- Attachment #0: Type: message/rfc822, Size: 9581 bytes --]

From: Herve Codina <herve.codina@bootlin.com>
To: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Cc: Lee Jones <lee@kernel.org>, Rob Herring <robh+dt@kernel.org>, Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>, Liam Girdwood <lgirdwood@gmail.com>, Mark Brown <broonie@kernel.org>, Takashi Iwai <tiwai@suse.com>, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, alsa-devel@alsa-project.org, Christophe Leroy <christophe.leroy@csgroup.eu>, Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Subject: Re: [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec
Date: Thu, 23 Mar 2023 09:10:01 +0100
Message-ID: <20230323091001.100ca343@bootlin.com>

On Thu, 23 Mar 2023 08:31:28 +0100
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:

> On 23/03/2023 08:27, Herve Codina wrote:
> > Hi Krzysztof
> > 
> > On Wed, 22 Mar 2023 22:59:37 +0100
> > Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:
> >   
> >> On 22/03/2023 14:46, Herve Codina wrote:  
> >>> The Lantiq PEF2256 is a framer and line interface component designed to
> >>> fulfill all required interfacing between an analog E1/T1/J1 line and the
> >>> digital PCM system highway/H.100 bus.
> >>>
> >>> The codec support allows to use some of the PCM system highway
> >>> time-slots as audio channels to transport audio data over the E1/T1/J1
> >>> lines.
> >>>
> >>> Signed-off-by: Herve Codina <herve.codina@bootlin.com>
> >>> ---
> >>>  .../bindings/sound/lantiq,pef2256-codec.yaml  | 54 +++++++++++++++++++
> >>>  1 file changed, 54 insertions(+)
> >>>  create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
> >>>
> >>> diff --git a/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
> >>> new file mode 100644
> >>> index 000000000000..da35b70cda99
> >>> --- /dev/null
> >>> +++ b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
> >>> @@ -0,0 +1,54 @@
> >>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> >>> +%YAML 1.2
> >>> +---
> >>> +$id: http://devicetree.org/schemas/sound/lantiq,pef2256-codec.yaml#
> >>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> >>> +
> >>> +title: Lantiq PEF2256 codec
> >>> +
> >>> +maintainers:
> >>> +  - Herve Codina <herve.codina@bootlin.com>
> >>> +
> >>> +description: |
> >>> +  Codec support for PEF2256.
> >>> +
> >>> +  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and
> >>> +  line interface component designed to fulfill all required interfacing between
> >>> +  an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.
> >>> +
> >>> +  The codec support allows to use some of the PCM system highway time-slots as
> >>> +  audio channels to transport audio data over the E1/T1/J1 lines.
> >>> +
> >>> +  The time-slots used by the codec must be set and so, the properties
> >>> +  'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and
> >>> +  'dai-tdm-slot-rx-mask' must be present in the ALSA sound card node for
> >>> +  sub-nodes that involve the codec. The codec uses 8bit time-slots.
> >>> +  'dai-tdm-tdm-slot-with' must be set to 8.
> >>> +  The tx and rx masks define the PEF2256 time-slots assigned to the codec.
> >>> +
> >>> +  The PEF2256 codec node should be a child of a PEF2256 node.
> >>> +  Refer to the bindings described in
> >>> +  Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
> >>> +
> >>> +allOf:
> >>> +  - $ref: dai-common.yaml#
> >>> +
> >>> +properties:
> >>> +  compatible:
> >>> +    const: lantiq,pef2256-codec
> >>> +
> >>> +  '#sound-dai-cells':
> >>> +    const: 0    
> >>
> >> You do not have here any resources, so the entire binding can be dropped
> >> and merged into the parent.
> >>
> >> Best regards,
> >> Krzysztof
> >>  
> > 
> > Ok,
> > Do you expect all these properties (except compatible) merged at the parent  
> 
> You have only two properties here - dai cells and name-prefix...
> 
> > level or may I keep a child node with these properties including the
> > compatible property (ie. yaml file merge).  
> 
> I was thinking that these should be merged into parent because usually
> you do not need child node for this. However now I started to think how
> the codec driver would look like. Essentially the parent MFD driver
> would need to register dais...
> 

There is also something specific to audio, the slots definition
'dai-tdm-slot-tx-mask' and 'dai-tdm-slot-rx-mask'. These slots definitions
are set at the ALSA sound card sub-nodes.
So, I can have multiple codec in the PEF2256.

For instance:
  framer {
    compatible = "lantiq,pef2256", "simple-mfd";
    ...
    pef2256_codec0: codec0 {
      compatible = "lantiq,pef2256-codec";
      #sound-dai-cells = <0>;
    };
    pef2256_codec1: codec1 {
      compatible = "lantiq,pef2256-codec";
      #sound-dai-cells = <0>;
    };
  };

  sound {
    compatible = "simple-audio-card";
    #address-cells = <1>;
    #size-cells = <0>;
    simple-audio-card,dai-link@0 { /* CPU DAI1 - pef2256 codec 1 */
      reg = <0>;
      cpu {
        sound-dai = <&cpu_dai1>;
      };
      codec {
        sound-dai = <&pef2256_codec0>;
	dai-tdm-slot-num = <4>;
	dai-tdm-slot-width = <8>;
	/* TS 2, 3, 4, 5 */
	dai-tdm-slot-tx-mask = <0 1 1 1 1>;
	dai-tdm-slot-rx-mask = <0 1 1 1 1>;
      };
    simple-audio-card,dai-link@1 { /* CPU DAI2 - pef2256 codec 2 */
      reg = <1>;
      cpu {
        sound-dai = <&cpu_dai2>;
      };
      codec {
	sound-dai = <&pef2256_codec1>;
	dai-tdm-slot-num = <4>;
	dai-tdm-slot-width = <8>;
	/* TS 6, 7, 8, 9 */
	dai-tdm-slot-tx-mask = <0 0 0 0 0 1 1 1 1>;
	dai-tdm-slot-rx-mask = <0 0 0 0 0 1 1 1 1>;
      };
    };
  };

To solve this, I can use #sound-dai-cells = <1>; but this will complicate
the driver itself and is it really needed ?
Having "simple-mfd" dans sub-nodes keep all things simple.

Regards,
Hervé

-- 
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer
  2023-03-23  7:30   ` Krzysztof Kozlowski
@ 2023-03-23  8:31     ` Herve Codina
  2023-03-23  8:31     ` Herve Codina via Alsa-devel
  1 sibling, 0 replies; 29+ messages in thread
From: Herve Codina @ 2023-03-23  8:31 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Liam Girdwood,
	Mark Brown, Jaroslav Kysela, Takashi Iwai, linux-kernel,
	devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni

On Thu, 23 Mar 2023 08:30:39 +0100
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:

> On 22/03/2023 14:46, Herve Codina wrote:
> > The Lantiq PEF2256 is a framer and line interface component designed to
> > fulfill all required interfacing between an analog E1/T1/J1 line and the
> > digital PCM system highway/H.100 bus.
> > 
> > Signed-off-by: Herve Codina <herve.codina@bootlin.com>  
> 
> 
> > +static const struct of_device_id pef2256_id_table[] = {
> > +	{ .compatible = "lantiq,pef2256" },
> > +	{} /* sentinel */
> > +};
> > +MODULE_DEVICE_TABLE(of, pef2256_id_table);
> > +
> > +static struct platform_driver pef2256_driver = {
> > +	.driver = {
> > +		.name = "lantiq-pef2256",
> > +		.of_match_table = of_match_ptr(pef2256_id_table),  
> 
> Drop of_match_ptr. This will case warnings with W=1 and !OF.
> 
> Best regards,
> Krzysztof
> 

Acked. Will be dropped in v4.

Thanks.
Hervé

-- 
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer
  2023-03-23  7:30   ` Krzysztof Kozlowski
  2023-03-23  8:31     ` Herve Codina
@ 2023-03-23  8:31     ` Herve Codina via Alsa-devel
  1 sibling, 0 replies; 29+ messages in thread
From: Herve Codina via Alsa-devel @ 2023-03-23  8:31 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Liam Girdwood,
	Mark Brown, Takashi Iwai, linux-kernel, devicetree, alsa-devel,
	Christophe Leroy, Thomas Petazzoni


[-- Attachment #0: Type: message/rfc822, Size: 5122 bytes --]

From: Herve Codina <herve.codina@bootlin.com>
To: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Cc: Lee Jones <lee@kernel.org>, Rob Herring <robh+dt@kernel.org>, Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>, Liam Girdwood <lgirdwood@gmail.com>, Mark Brown <broonie@kernel.org>, Takashi Iwai <tiwai@suse.com>, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, alsa-devel@alsa-project.org, Christophe Leroy <christophe.leroy@csgroup.eu>, Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Subject: Re: [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer
Date: Thu, 23 Mar 2023 09:31:54 +0100
Message-ID: <20230323093154.5852f81b@bootlin.com>

On Thu, 23 Mar 2023 08:30:39 +0100
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:

> On 22/03/2023 14:46, Herve Codina wrote:
> > The Lantiq PEF2256 is a framer and line interface component designed to
> > fulfill all required interfacing between an analog E1/T1/J1 line and the
> > digital PCM system highway/H.100 bus.
> > 
> > Signed-off-by: Herve Codina <herve.codina@bootlin.com>  
> 
> 
> > +static const struct of_device_id pef2256_id_table[] = {
> > +	{ .compatible = "lantiq,pef2256" },
> > +	{} /* sentinel */
> > +};
> > +MODULE_DEVICE_TABLE(of, pef2256_id_table);
> > +
> > +static struct platform_driver pef2256_driver = {
> > +	.driver = {
> > +		.name = "lantiq-pef2256",
> > +		.of_match_table = of_match_ptr(pef2256_id_table),  
> 
> Drop of_match_ptr. This will case warnings with W=1 and !OF.
> 
> Best regards,
> Krzysztof
> 

Acked. Will be dropped in v4.

Thanks.
Hervé

-- 
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec
  2023-03-23  8:10         ` Herve Codina
@ 2023-03-26 12:21             ` Krzysztof Kozlowski
  0 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2023-03-26 12:21 UTC (permalink / raw)
  To: Herve Codina
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Liam Girdwood,
	Mark Brown, Jaroslav Kysela, Takashi Iwai, linux-kernel,
	devicetree, alsa-devel, Christophe Leroy, Thomas Petazzoni

On 23/03/2023 09:10, Herve Codina wrote:
> On Thu, 23 Mar 2023 08:31:28 +0100
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:
> 
>> On 23/03/2023 08:27, Herve Codina wrote:
>>> Hi Krzysztof
>>>
>>> On Wed, 22 Mar 2023 22:59:37 +0100
>>> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:
>>>   
>>>> On 22/03/2023 14:46, Herve Codina wrote:  
>>>>> The Lantiq PEF2256 is a framer and line interface component designed to
>>>>> fulfill all required interfacing between an analog E1/T1/J1 line and the
>>>>> digital PCM system highway/H.100 bus.
>>>>>
>>>>> The codec support allows to use some of the PCM system highway
>>>>> time-slots as audio channels to transport audio data over the E1/T1/J1
>>>>> lines.
>>>>>
>>>>> Signed-off-by: Herve Codina <herve.codina@bootlin.com>
>>>>> ---
>>>>>  .../bindings/sound/lantiq,pef2256-codec.yaml  | 54 +++++++++++++++++++
>>>>>  1 file changed, 54 insertions(+)
>>>>>  create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
>>>>>
>>>>> diff --git a/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
>>>>> new file mode 100644
>>>>> index 000000000000..da35b70cda99
>>>>> --- /dev/null
>>>>> +++ b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
>>>>> @@ -0,0 +1,54 @@
>>>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>>>> +%YAML 1.2
>>>>> +---
>>>>> +$id: http://devicetree.org/schemas/sound/lantiq,pef2256-codec.yaml#
>>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>>> +
>>>>> +title: Lantiq PEF2256 codec
>>>>> +
>>>>> +maintainers:
>>>>> +  - Herve Codina <herve.codina@bootlin.com>
>>>>> +
>>>>> +description: |
>>>>> +  Codec support for PEF2256.
>>>>> +
>>>>> +  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and
>>>>> +  line interface component designed to fulfill all required interfacing between
>>>>> +  an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.
>>>>> +
>>>>> +  The codec support allows to use some of the PCM system highway time-slots as
>>>>> +  audio channels to transport audio data over the E1/T1/J1 lines.
>>>>> +
>>>>> +  The time-slots used by the codec must be set and so, the properties
>>>>> +  'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and
>>>>> +  'dai-tdm-slot-rx-mask' must be present in the ALSA sound card node for
>>>>> +  sub-nodes that involve the codec. The codec uses 8bit time-slots.
>>>>> +  'dai-tdm-tdm-slot-with' must be set to 8.
>>>>> +  The tx and rx masks define the PEF2256 time-slots assigned to the codec.
>>>>> +
>>>>> +  The PEF2256 codec node should be a child of a PEF2256 node.
>>>>> +  Refer to the bindings described in
>>>>> +  Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
>>>>> +
>>>>> +allOf:
>>>>> +  - $ref: dai-common.yaml#
>>>>> +
>>>>> +properties:
>>>>> +  compatible:
>>>>> +    const: lantiq,pef2256-codec
>>>>> +
>>>>> +  '#sound-dai-cells':
>>>>> +    const: 0    
>>>>
>>>> You do not have here any resources, so the entire binding can be dropped
>>>> and merged into the parent.
>>>>
>>>> Best regards,
>>>> Krzysztof
>>>>  
>>>
>>> Ok,
>>> Do you expect all these properties (except compatible) merged at the parent  
>>
>> You have only two properties here - dai cells and name-prefix...
>>
>>> level or may I keep a child node with these properties including the
>>> compatible property (ie. yaml file merge).  
>>
>> I was thinking that these should be merged into parent because usually
>> you do not need child node for this. However now I started to think how
>> the codec driver would look like. Essentially the parent MFD driver
>> would need to register dais...
>>
> 
> There is also something specific to audio, the slots definition
> 'dai-tdm-slot-tx-mask' and 'dai-tdm-slot-rx-mask'. These slots definitions
> are set at the ALSA sound card sub-nodes.
> So, I can have multiple codec in the PEF2256.
> 
> For instance:
>   framer {
>     compatible = "lantiq,pef2256", "simple-mfd";
>     ...
>     pef2256_codec0: codec0 {
>       compatible = "lantiq,pef2256-codec";
>       #sound-dai-cells = <0>;
>     };
>     pef2256_codec1: codec1 {
>       compatible = "lantiq,pef2256-codec";
>       #sound-dai-cells = <0>;
>     };
>   };

Then include it in the example. It would cut short this discussion.


Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec
@ 2023-03-26 12:21             ` Krzysztof Kozlowski
  0 siblings, 0 replies; 29+ messages in thread
From: Krzysztof Kozlowski @ 2023-03-26 12:21 UTC (permalink / raw)
  To: Herve Codina
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Liam Girdwood,
	Mark Brown, Takashi Iwai, linux-kernel, devicetree, alsa-devel,
	Christophe Leroy, Thomas Petazzoni

On 23/03/2023 09:10, Herve Codina wrote:
> On Thu, 23 Mar 2023 08:31:28 +0100
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:
> 
>> On 23/03/2023 08:27, Herve Codina wrote:
>>> Hi Krzysztof
>>>
>>> On Wed, 22 Mar 2023 22:59:37 +0100
>>> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:
>>>   
>>>> On 22/03/2023 14:46, Herve Codina wrote:  
>>>>> The Lantiq PEF2256 is a framer and line interface component designed to
>>>>> fulfill all required interfacing between an analog E1/T1/J1 line and the
>>>>> digital PCM system highway/H.100 bus.
>>>>>
>>>>> The codec support allows to use some of the PCM system highway
>>>>> time-slots as audio channels to transport audio data over the E1/T1/J1
>>>>> lines.
>>>>>
>>>>> Signed-off-by: Herve Codina <herve.codina@bootlin.com>
>>>>> ---
>>>>>  .../bindings/sound/lantiq,pef2256-codec.yaml  | 54 +++++++++++++++++++
>>>>>  1 file changed, 54 insertions(+)
>>>>>  create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
>>>>>
>>>>> diff --git a/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
>>>>> new file mode 100644
>>>>> index 000000000000..da35b70cda99
>>>>> --- /dev/null
>>>>> +++ b/Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
>>>>> @@ -0,0 +1,54 @@
>>>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>>>> +%YAML 1.2
>>>>> +---
>>>>> +$id: http://devicetree.org/schemas/sound/lantiq,pef2256-codec.yaml#
>>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>>> +
>>>>> +title: Lantiq PEF2256 codec
>>>>> +
>>>>> +maintainers:
>>>>> +  - Herve Codina <herve.codina@bootlin.com>
>>>>> +
>>>>> +description: |
>>>>> +  Codec support for PEF2256.
>>>>> +
>>>>> +  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and
>>>>> +  line interface component designed to fulfill all required interfacing between
>>>>> +  an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.
>>>>> +
>>>>> +  The codec support allows to use some of the PCM system highway time-slots as
>>>>> +  audio channels to transport audio data over the E1/T1/J1 lines.
>>>>> +
>>>>> +  The time-slots used by the codec must be set and so, the properties
>>>>> +  'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and
>>>>> +  'dai-tdm-slot-rx-mask' must be present in the ALSA sound card node for
>>>>> +  sub-nodes that involve the codec. The codec uses 8bit time-slots.
>>>>> +  'dai-tdm-tdm-slot-with' must be set to 8.
>>>>> +  The tx and rx masks define the PEF2256 time-slots assigned to the codec.
>>>>> +
>>>>> +  The PEF2256 codec node should be a child of a PEF2256 node.
>>>>> +  Refer to the bindings described in
>>>>> +  Documentation/devicetree/bindings/mfd/lantiq,pef2256.yaml
>>>>> +
>>>>> +allOf:
>>>>> +  - $ref: dai-common.yaml#
>>>>> +
>>>>> +properties:
>>>>> +  compatible:
>>>>> +    const: lantiq,pef2256-codec
>>>>> +
>>>>> +  '#sound-dai-cells':
>>>>> +    const: 0    
>>>>
>>>> You do not have here any resources, so the entire binding can be dropped
>>>> and merged into the parent.
>>>>
>>>> Best regards,
>>>> Krzysztof
>>>>  
>>>
>>> Ok,
>>> Do you expect all these properties (except compatible) merged at the parent  
>>
>> You have only two properties here - dai cells and name-prefix...
>>
>>> level or may I keep a child node with these properties including the
>>> compatible property (ie. yaml file merge).  
>>
>> I was thinking that these should be merged into parent because usually
>> you do not need child node for this. However now I started to think how
>> the codec driver would look like. Essentially the parent MFD driver
>> would need to register dais...
>>
> 
> There is also something specific to audio, the slots definition
> 'dai-tdm-slot-tx-mask' and 'dai-tdm-slot-rx-mask'. These slots definitions
> are set at the ALSA sound card sub-nodes.
> So, I can have multiple codec in the PEF2256.
> 
> For instance:
>   framer {
>     compatible = "lantiq,pef2256", "simple-mfd";
>     ...
>     pef2256_codec0: codec0 {
>       compatible = "lantiq,pef2256-codec";
>       #sound-dai-cells = <0>;
>     };
>     pef2256_codec1: codec1 {
>       compatible = "lantiq,pef2256-codec";
>       #sound-dai-cells = <0>;
>     };
>   };

Then include it in the example. It would cut short this discussion.


Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer
  2023-03-22 13:46 ` Herve Codina
  2023-03-23  7:30   ` Krzysztof Kozlowski
@ 2023-03-26 15:49   ` kernel test robot
  1 sibling, 0 replies; 29+ messages in thread
From: kernel test robot @ 2023-03-26 15:49 UTC (permalink / raw)
  To: Herve Codina, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
  Cc: oe-kbuild-all, linux-kernel, devicetree, alsa-devel,
	Christophe Leroy, Thomas Petazzoni

Hi Herve,

I love your patch! Yet something to improve:

[auto build test ERROR on lee-mfd/for-mfd-next]
[also build test ERROR on broonie-sound/for-next lee-leds/for-leds-next robh/for-next linus/master v6.3-rc3 next-20230324]
[cannot apply to lee-mfd/for-mfd-fixes]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Herve-Codina/dt-bindings-mfd-Add-the-Lantiq-PEF2256-E1-T1-J1-framer/20230322-214827
base:   https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
patch link:    https://lore.kernel.org/r/20230322134654.219957-3-herve.codina%40bootlin.com
patch subject: [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer
config: parisc-randconfig-p001-20230326 (https://download.01.org/0day-ci/archive/20230326/202303262358.vWU2dypT-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/53e683ee1cad96a898f7fed03f88a3898e8dcd15
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Herve-Codina/dt-bindings-mfd-Add-the-Lantiq-PEF2256-E1-T1-J1-framer/20230322-214827
        git checkout 53e683ee1cad96a898f7fed03f88a3898e8dcd15
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=parisc olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=parisc SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202303262358.vWU2dypT-lkp@intel.com/

All errors (new ones prefixed by >>):

   hppa-linux-ld: drivers/mfd/pef2256.o: in function `.LC58':
>> pef2256.c:(.rodata.cst4+0x54): undefined reference to `pinconf_generic_dt_node_to_map'

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer
  2023-03-22 13:46 ` [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer Herve Codina via Alsa-devel
@ 2023-03-26 18:22   ` kernel test robot
  0 siblings, 0 replies; 29+ messages in thread
From: kernel test robot @ 2023-03-26 18:22 UTC (permalink / raw)
  To: Herve Codina via Alsa-devel, Herve Codina, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai
  Cc: oe-kbuild-all, linux-kernel, devicetree, alsa-devel,
	Christophe Leroy, Thomas Petazzoni

Hi Herve,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on lee-mfd/for-mfd-next]
[also build test ERROR on broonie-sound/for-next lee-leds/for-leds-next robh/for-next linus/master v6.3-rc3 next-20230324]
[cannot apply to lee-mfd/for-mfd-fixes]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Herve-Codina-via-Alsa-devel/mfd-Add-support-for-the-Lantiq-PEF2256-framer/20230322-215208
base:   https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
patch link:    https://lore.kernel.org/r/167949286900.26.3992817728812049195%40mailman-core.alsa-project.org
patch subject: [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer
config: m68k-randconfig-c024-20230326 (https://download.01.org/0day-ci/archive/20230327/202303270203.QeRuuc9d-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/d60948895815b59306d870e7c189741b7d14d5e2
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Herve-Codina-via-Alsa-devel/mfd-Add-support-for-the-Lantiq-PEF2256-framer/20230322-215208
        git checkout d60948895815b59306d870e7c189741b7d14d5e2
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=m68k olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=m68k SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202303270203.QeRuuc9d-lkp@intel.com/

All errors (new ones prefixed by >>):

   m68k-linux-ld: drivers/mfd/pef2256.o: in function `pinconf_generic_dt_node_to_map_pin':
>> pef2256.c:(.text+0x280): undefined reference to `pinconf_generic_dt_node_to_map'

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer
@ 2023-03-24  5:28 kernel test robot
  0 siblings, 0 replies; 29+ messages in thread
From: kernel test robot @ 2023-03-24  5:28 UTC (permalink / raw)
  To: oe-kbuild; +Cc: lkp

:::::: 
:::::: Manual check reason: "low confidence bisect report"
:::::: 

BCC: lkp@intel.com
CC: oe-kbuild-all@lists.linux.dev
In-Reply-To: <167949286900.26.3992817728812049195@mailman-core.alsa-project.org>
References: <167949286900.26.3992817728812049195@mailman-core.alsa-project.org>
TO: "Herve Codina via Alsa-devel" <alsa-devel@alsa-project.org>
TO: Herve Codina <herve.codina@bootlin.com>
TO: Lee Jones <lee@kernel.org>
TO: Rob Herring <robh+dt@kernel.org>
TO: Krzysztof Kozlowski <krzk@kernel.org>
TO: Liam Girdwood <lgirdwood@gmail.com>
TO: Mark Brown <broonie@kernel.org>
TO: Jaroslav Kysela <perex@perex.cz>
TO: Takashi Iwai <tiwai@suse.com>
CC: linux-kernel@vger.kernel.org
CC: devicetree@vger.kernel.org
CC: alsa-devel@alsa-project.org
CC: Christophe Leroy <christophe.leroy@csgroup.eu>
CC: Thomas Petazzoni <thomas.petazzoni@bootlin.com>

Hi Herve,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on lee-mfd/for-mfd-next]
[also build test WARNING on broonie-sound/for-next lee-leds/for-leds-next robh/for-next linus/master v6.3-rc3 next-20230323]
[cannot apply to lee-mfd/for-mfd-fixes]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Herve-Codina-via-Alsa-devel/mfd-Add-support-for-the-Lantiq-PEF2256-framer/20230322-215208
base:   https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
patch link:    https://lore.kernel.org/r/167949286900.26.3992817728812049195%40mailman-core.alsa-project.org
patch subject: [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer
:::::: branch date: 2 days ago
:::::: commit date: 2 days ago
config: openrisc-randconfig-s033-20230324 (https://download.01.org/0day-ci/archive/20230324/202303241313.pYnyzYXe-lkp@intel.com/config)
compiler: or1k-linux-gcc (GCC) 12.1.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.4-39-gce1a6720-dirty
        # https://github.com/intel-lab-lkp/linux/commit/d60948895815b59306d870e7c189741b7d14d5e2
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Herve-Codina-via-Alsa-devel/mfd-Add-support-for-the-Lantiq-PEF2256-framer/20230322-215208
        git checkout d60948895815b59306d870e7c189741b7d14d5e2
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=openrisc olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=openrisc SHELL=/bin/bash drivers/mfd/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/r/202303241313.pYnyzYXe-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/mfd/pef2256.c:1192:23: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected void *[noderef] regs @@     got void [noderef] __iomem * @@
   drivers/mfd/pef2256.c:1192:23: sparse:     expected void *[noderef] regs
   drivers/mfd/pef2256.c:1192:23: sparse:     got void [noderef] __iomem *
>> drivers/mfd/pef2256.c:303:38: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void const volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:303:38: sparse:     expected void const volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:303:38: sparse:     got void *
>> drivers/mfd/pef2256.c:303:24: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:303:24: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:303:38: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void const volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:303:38: sparse:     expected void const volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:303:38: sparse:     got void *
>> drivers/mfd/pef2256.c:303:24: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:303:24: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:303:38: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void const volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:303:38: sparse:     expected void const volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:303:38: sparse:     got void *
>> drivers/mfd/pef2256.c:303:24: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:303:24: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
>> drivers/mfd/pef2256.c:303:24: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:308:37: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:308:37: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:308:37: sparse:     got void *
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
   drivers/mfd/pef2256.c:308:23: sparse: sparse: dereference of noderef expression
>> drivers/mfd/pef2256.c:303:38: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void const volatile [noderef] __iomem *addr @@     got void * @@
   drivers/mfd/pef2256.c:303:38: sparse:     expected void const volatile [noderef] __iomem *addr
   drivers/mfd/pef2256.c:303:38: sparse:     got void *
   drivers/mfd/pef2256.c:303:24: sparse: sparse: too many warnings

vim +1192 drivers/mfd/pef2256.c

d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1176  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1177  static int pef2256_probe(struct platform_device *pdev)
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1178  {
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1179  	struct device_node *np = pdev->dev.of_node;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1180  	unsigned long sclkr_rate, sclkx_rate;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1181  	struct pef2256 *pef2256;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1182  	int ret;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1183  	int irq;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1184  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1185  	pef2256 = devm_kzalloc(&pdev->dev, sizeof(*pef2256), GFP_KERNEL);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1186  	if (!pef2256)
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1187  		return -ENOMEM;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1188  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1189  	pef2256->dev = &pdev->dev;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1190  	ATOMIC_INIT_NOTIFIER_HEAD(&pef2256->event_notifier_list);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1191  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22 @1192  	pef2256->regs = devm_platform_ioremap_resource(pdev, 0);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1193  	if (IS_ERR(pef2256->regs))
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1194  		return PTR_ERR(pef2256->regs);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1195  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1196  	pef2256->mclk = devm_clk_get_enabled(&pdev->dev, "mclk");
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1197  	if (IS_ERR(pef2256->mclk))
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1198  		return PTR_ERR(pef2256->mclk);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1199  	dev_dbg(pef2256->dev, "mclk %lu Hz\n", clk_get_rate(pef2256->mclk));
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1200  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1201  	pef2256->sclkr = devm_clk_get_enabled(&pdev->dev, "sclkr");
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1202  	if (IS_ERR(pef2256->sclkr))
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1203  		return PTR_ERR(pef2256->sclkr);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1204  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1205  	pef2256->sclkx = devm_clk_get_enabled(&pdev->dev, "sclkx");
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1206  	if (IS_ERR(pef2256->sclkx))
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1207  		return PTR_ERR(pef2256->sclkx);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1208  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1209  	/*
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1210  	 * Both SCLKR (receive) and SCLKX (transmit) must have the same rate,
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1211  	 * stored as sysclk_rate.
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1212  	 * The exact value will be checked at pef2256_check_rates()
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1213  	 */
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1214  	sclkr_rate = clk_get_rate(pef2256->sclkr);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1215  	sclkx_rate = clk_get_rate(pef2256->sclkx);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1216  	dev_dbg(pef2256->dev, "sclkr %lu Hz\n", sclkr_rate);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1217  	dev_dbg(pef2256->dev, "sclkx %lu Hz\n", sclkx_rate);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1218  	if (sclkr_rate != sclkx_rate) {
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1219  		dev_err(pef2256->dev, "clk rate mismatch. sclkr %lu Hz, sclkx %lu Hz\n",
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1220  			sclkr_rate, sclkx_rate);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1221  		return -EINVAL;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1222  	}
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1223  	pef2256->sysclk_rate = sclkr_rate;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1224  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1225  	/* Reset the component. The MCLK clock must be active during reset */
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1226  	pef2256->reset_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1227  	if (IS_ERR(pef2256->reset_gpio))
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1228  		return PTR_ERR(pef2256->reset_gpio);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1229  	if (pef2256->reset_gpio) {
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1230  		gpiod_set_value_cansleep(pef2256->reset_gpio, 1);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1231  		udelay(10);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1232  		gpiod_set_value_cansleep(pef2256->reset_gpio, 0);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1233  		udelay(10);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1234  	}
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1235  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1236  	pef2256->version = pef2256_get_version(pef2256);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1237  	if (pef2256->version == PEF2256_VERSION_UNKNOWN)
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1238  		return -ENODEV;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1239  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1240  	ret = pef2556_of_parse(pef2256, np);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1241  	if (ret)
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1242  		return ret;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1243  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1244  	/* Disable interrupts */
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1245  	pef2256_write8(pef2256, PEF2256_IMR0, 0xff);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1246  	pef2256_write8(pef2256, PEF2256_IMR1, 0xff);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1247  	pef2256_write8(pef2256, PEF2256_IMR2, 0xff);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1248  	pef2256_write8(pef2256, PEF2256_IMR3, 0xff);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1249  	pef2256_write8(pef2256, PEF2256_IMR4, 0xff);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1250  	pef2256_write8(pef2256, PEF2256_IMR5, 0xff);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1251  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1252  	/* Clear any pending interrupts */
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1253  	pef2256_read8(pef2256, PEF2256_ISR0);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1254  	pef2256_read8(pef2256, PEF2256_ISR1);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1255  	pef2256_read8(pef2256, PEF2256_ISR2);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1256  	pef2256_read8(pef2256, PEF2256_ISR3);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1257  	pef2256_read8(pef2256, PEF2256_ISR4);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1258  	pef2256_read8(pef2256, PEF2256_ISR5);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1259  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1260  	irq = platform_get_irq(pdev, 0);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1261  	if (irq < 0)
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1262  		return irq;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1263  	ret = devm_request_irq(pef2256->dev, irq, pef2256_irq_handler, 0, "pef2256", pef2256);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1264  	if (ret < 0)
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1265  		return ret;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1266  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1267  	pef2256_reset_pinmux(pef2256);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1268  	ret = pef2256_register_pinctrl(pef2256);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1269  	if (ret)
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1270  		return ret;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1271  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1272  	/*
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1273  	 * We are going to reset the E1 lines during setup() call and the ISR2
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1274  	 * interrupt used to detect the carrier state changed is masked.
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1275  	 * It is time to initialize our internal carrier state flag.
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1276  	 */
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1277  	atomic_set(&pef2256->carrier, 0);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1278  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1279  	ret = pef2256_setup(pef2256);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1280  	if (ret)
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1281  		return ret;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1282  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1283  	platform_set_drvdata(pdev, pef2256);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1284  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1285  	ret = sysfs_create_group(&pef2256->dev->kobj, &pef2256_attribute_group);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1286  	if (ret < 0) {
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1287  		dev_err(pef2256->dev, "sysfs registration failed (%d)\n", ret);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1288  		platform_set_drvdata(pdev, NULL);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1289  		return ret;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1290  	}
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1291  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1292  	ret = devm_of_platform_populate(pef2256->dev);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1293  	if (ret < 0) {
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1294  		dev_err(pef2256->dev, "platform populate failed (%d)\n", ret);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1295  		platform_set_drvdata(pdev, NULL);
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1296  		return ret;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1297  	}
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1298  
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1299  	return 0;
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1300  }
d60948895815b5 Herve Codina via Alsa-devel 2023-03-22  1301  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2023-03-26 18:22 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-22 13:46 [PATCH v3 0/6] Add the Lantiq PEF2256 audio support Herve Codina
2023-03-22 13:46 ` [PATCH v3 1/6] dt-bindings: mfd: Add the Lantiq PEF2256 E1/T1/J1 framer Herve Codina
2023-03-22 21:58   ` Krzysztof Kozlowski
2023-03-22 13:46 ` Herve Codina via Alsa-devel
2023-03-22 13:46 ` [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer Herve Codina via Alsa-devel
2023-03-26 18:22   ` kernel test robot
2023-03-22 13:46 ` Herve Codina
2023-03-23  7:30   ` Krzysztof Kozlowski
2023-03-23  8:31     ` Herve Codina
2023-03-23  8:31     ` Herve Codina via Alsa-devel
2023-03-26 15:49   ` kernel test robot
2023-03-22 13:46 ` [PATCH v3 3/6] Documentation: sysfs: Document the Lantiq PEF2256 sysfs entry Herve Codina
2023-03-22 13:46 ` Herve Codina via Alsa-devel
2023-03-22 13:46 ` [PATCH v3 4/6] dt-bindings: sound: Add support for the Lantiq PEF2256 codec Herve Codina
2023-03-22 21:59   ` Krzysztof Kozlowski
2023-03-23  7:27     ` Herve Codina
2023-03-23  7:31       ` Krzysztof Kozlowski
2023-03-23  7:31         ` Krzysztof Kozlowski
2023-03-23  8:10         ` Herve Codina via Alsa-devel
2023-03-23  8:10         ` Herve Codina
2023-03-26 12:21           ` Krzysztof Kozlowski
2023-03-26 12:21             ` Krzysztof Kozlowski
2023-03-23  7:27     ` Herve Codina via Alsa-devel
2023-03-22 13:46 ` Herve Codina via Alsa-devel
2023-03-22 13:46 ` [PATCH v3 5/6] ASoC: codecs: " Herve Codina
2023-03-22 13:46 ` Herve Codina via Alsa-devel
2023-03-22 13:46 ` [PATCH v3 6/6] MAINTAINERS: Add the Lantiq PEF2256 driver entry Herve Codina
2023-03-22 13:46 ` Herve Codina via Alsa-devel
2023-03-24  5:28 [PATCH v3 2/6] mfd: Add support for the Lantiq PEF2256 framer kernel test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.