Skip to contentSkip to conversation

Add the Lantiq PEF2256 audio support

PATCH Superseded Herve Codina 6 participants 39 messages Mar 16, 2023 – Mar 22, 2023

Subsystems (4)

v2 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v2 cover Add the Lantiq PEF2256 audio support

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.

This v2 series fixes issues raised by the kernel test robot
- devm_platform_ioremap_resource symbol undefined
- duplicate const qualifier
- Block quote ends without a blank line

Best regards,
Herve Codina

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 (7):
dt-bindings: misc: Add the Lantiq PEF2466 E1/T1/J1 framer
drivers: misc: Add support for the Lantiq PEF2256 framer
Documentation: sysfs: Document the Lantiq PEF2256 sysfs entry
MAINTAINERS: Add the Lantiq PEF2256 driver 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 ASoC codec entry

 .../sysfs-bus-platform-devices-pef2256        |   12 +
 .../bindings/misc/lantiq,pef2256.yaml         |  190 +++
 .../bindings/sound/lantiq,pef2256-codec.yaml  |   57 +
 MAINTAINERS                                   |   15 +
 drivers/misc/Kconfig                          |   17 +
 drivers/misc/Makefile                         |    1 +
 drivers/misc/pef2256.c                        | 1441 +++++++++++++++++
 include/linux/pef2256.h                       |   36 +
 sound/soc/codecs/Kconfig                      |   14 +
 sound/soc/codecs/Makefile                     |    2 +
 sound/soc/codecs/pef2256-codec.c              |  395 +++++
 11 files changed, 2180 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256
 create mode 100644 Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
 create mode 100644 drivers/misc/pef2256.c
 create mode 100644 include/linux/pef2256.h
 create mode 100644 sound/soc/codecs/pef2256-codec.c
Signature · 1 line
2.39.2
#1 lore raw

PATCH v2 1/7 dt-bindings: misc: Add the Lantiq PEF2466 E1/T1/J1 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.

---
 .../bindings/misc/lantiq,pef2256.yaml         | 190 ++++++++++++++++++
 1 file changed, 190 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +190 -0
new file mode 100644
index 000000000000..1ba788d06a14
@@ -0,0 +1,190 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/misc/lantiq,pef2256.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Lantiq PEF2256
+
+maintainers:
+  - Herve Codina <[email protected]>
+
+description:
+  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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:
+    const: lantiq,pef2256
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Master clock
+
+  clock-names:
+    items:
+      - const: mclk
+
+  interrupts:
+    maxItems: 1
+
+  reset-gpios:
+    description:
+      GPIO used to reset the device.
+    maxItems: 1
+
+  pinctrl:
+    allOf:
+      - $ref: "/schemas/pinctrl/pinctrl.yaml#"
+
+    patternProperties:
+      '-pins$':
+        type: object
+        allOf:
+          - $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 ]
+
+        required:
+          - pins
+          - function
+
+  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,sysclk-rate-hz:
+    enum: [2048000, 4096000, 8192000, 16384000]
+    default: 2048000
+    description:
+      Clock rate (Hz) on the system highway.
+
+  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.
+
+allOf:
+  - if:
+      properties:
+        lantiq,line-interface:
+          contains:
+            const: e1
+    then:
+      properties:
+        lantiq,frame-format:
+          $ref: /schemas/types.yaml#/definitions/string
+          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:
+          $ref: /schemas/types.yaml#/definitions/string
+          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>
+    pef2256@2000000 {
+      compatible = "lantiq,pef2256";
+      reg = <0x2000000 0xFF>;
+      interrupts = <8 1>;
+      interrupt-parent = <&PIC>;
+      clocks = <&clk_mclk>;
+      clock-names = "mclk";
+      reset-gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
+      lantiq,sysclk-rate-hz = <8192000>;
+      lantiq,data-rate-bps = <4096000>;
+
+      pinctrl {
+        pef2256_rpa_sypr: rpa-pins {
+          pins = "RPA";
+          function = "SYPR";
+        };
+        pef2256_xpa_sypx: xpa-pins {
+          pins = "XPA";
+          function = "SYPX";
+        };
+      };
+    };
Signature · 1 line
2.39.2
#2 lore raw

Re: [PATCH v2 1/7] dt-bindings: misc: Add the Lantiq PEF2466 E1/T1/J1 framer

Quoted 48 lines · Herve Codina

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.

---
 .../bindings/misc/lantiq,pef2256.yaml         | 190 ++++++++++++++++++
 1 file changed, 190 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +32 -0
new file mode 100644
index 000000000000..1ba788d06a14
@@ -0,0 +1,190 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/misc/lantiq,pef2256.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Lantiq PEF2256
+
+maintainers:
+  - Herve Codina <[email protected]>
+
+description:
+  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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:
+    const: lantiq,pef2256
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Master clock
+
+  clock-names:
+    items:
+      - const: mclk
+
+  interrupts:

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 42

Quoted 10 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +10 -0
+    maxItems: 1
+
+  reset-gpios:
+    description:
+      GPIO used to reset the device.
+    maxItems: 1
+
+  pinctrl:
+    allOf:
+      - $ref: "/schemas/pinctrl/pinctrl.yaml#"

Drop quotes. Drop allOf, no need for it.

additionalProperties: false

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 48

Quoted 6 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +6 -0
+
+    patternProperties:
+      '-pins$':
+        type: object
+        allOf:
+          - $ref: "/schemas/pinctrl/pincfg-node.yaml#"

Drop quotes. Drop allOf, no need for it.

additionalProperties: false

Quoted 18 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +18 -0
+
+        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 ]
+
+        required:
+          - pins
+          - function
+
+  lantiq,line-interface:
+    $ref: /schemas/types.yaml#/definitions/string
+    enum: [e1, t1j1]
+    default: e1

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 76

Quoted 10 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +10 -0
+    description: |
+      The line interface type
+        - e1: E1 line
+        - t1j1: T1/J1 line
+
+  lantiq,sysclk-rate-hz:
+    enum: [2048000, 4096000, 8192000, 16384000]
+    default: 2048000
+    description:
+      Clock rate (Hz) on the system highway.

I am pretty sure we have discussions on sysclk for other drivers. First, why you cannot use assigned-clock-rates? Or clk_get_rate() if this is about being consumer?

Second, there is already system-clock-frequency property, so use it.

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 83

Quoted 7 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +7 -0
+
+  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.

Why do you need it? How is it different from clock? Do you expect some DDR here?

Quoted 39 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +39 -0
+
+  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.

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 132

Quoted 10 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +10 -0
+
+allOf:
+  - if:
+      properties:
+        lantiq,line-interface:
+          contains:
+            const: e1
+    then:
+      properties:
+        lantiq,frame-format:

Do not define properties in if:then, but in top-level. Disallow them or customize for the specific cases in if:then

Quoted 4 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +4 -0
+          $ref: /schemas/types.yaml#/definitions/string
+          enum: [doubleframe, crc4-multiframe, auto-multiframe]
+          default: doubleframe
+          description: |

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 146

Quoted 10 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +10 -0
+            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:

Same problem - definitions go to top level.

Quoted 13 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +13 -0
+          $ref: /schemas/types.yaml#/definitions/string
+          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

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 169

Quoted 10 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +10 -0
+  - clocks
+  - clock-names
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    pef2256@2000000 {

Figure out some generic node name.

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 171

Quoted 2 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +2 -0
+      compatible = "lantiq,pef2256";
+      reg = <0x2000000 0xFF>;

Lowercase hex

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 172

Quoted 1 line
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +1 -0
+      interrupts = <8 1>;

if 1 is interrupt flag, use proper defines.

Quoted 8 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +8 -0
+      interrupt-parent = <&PIC>;
+      clocks = <&clk_mclk>;
+      clock-names = "mclk";
+      reset-gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
+      lantiq,sysclk-rate-hz = <8192000>;
+      lantiq,data-rate-bps = <4096000>;
+
+      pinctrl {

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 190

Quoted 10 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +10 -0
+        pef2256_rpa_sypr: rpa-pins {
+          pins = "RPA";
+          function = "SYPR";
+        };
+        pef2256_xpa_sypx: xpa-pins {
+          pins = "XPA";
+          function = "SYPX";
+        };
+      };
+    };

Best regards,
Krzysztof

#3 lore raw

Re: [PATCH v2 1/7] dt-bindings: misc: Add the Lantiq PEF2466 E1/T1/J1 framer

Hi Krzysztof

Quoted 62 lines · On Fri, 17 Mar 2023 09:54:07 +0100 Krzysztof Kozlowski…
Quoted 48 lines · Herve Codina

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.

---
 .../bindings/misc/lantiq,pef2256.yaml         | 190 ++++++++++++++++++
 1 file changed, 190 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +32 -0
new file mode 100644
index 000000000000..1ba788d06a14
@@ -0,0 +1,190 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/misc/lantiq,pef2256.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Lantiq PEF2256
+
+maintainers:
+  - Herve Codina <[email protected]>
+
+description:
+  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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:
+    const: lantiq,pef2256
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Master clock
+
+  clock-names:
+    items:
+      - const: mclk
+
+  interrupts:

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 42

Quoted 10 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +10 -0
+    maxItems: 1
+
+  reset-gpios:
+    description:
+      GPIO used to reset the device.
+    maxItems: 1
+
+  pinctrl:
+    allOf:
+      - $ref: "/schemas/pinctrl/pinctrl.yaml#"  

Drop quotes. Drop allOf, no need for it.

Quoted 1 line

additionalProperties: false

Will be dropped and added in v3

Quoted 8 lines

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 48

Quoted 7 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +6 -0
+
+    patternProperties:
+      '-pins$':
+        type: object
+        allOf:
+          - $ref: "/schemas/pinctrl/pincfg-node.yaml#"  
Quoted 4 lines

Drop quotes. Drop allOf, no need for it.

additionalProperties: false

Will be dropped and added in v3

Quoted 34 lines
Quoted 19 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +18 -0
+
+        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 ]
+
+        required:
+          - pins
+          - function
+
+  lantiq,line-interface:
+    $ref: /schemas/types.yaml#/definitions/string
+    enum: [e1, t1j1]
+    default: e1

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 76

Quoted 10 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +10 -0
+    description: |
+      The line interface type
+        - e1: E1 line
+        - t1j1: T1/J1 line
+
+  lantiq,sysclk-rate-hz:
+    enum: [2048000, 4096000, 8192000, 16384000]
+    default: 2048000
+    description:
+      Clock rate (Hz) on the system highway.  

I am pretty sure we have discussions on sysclk for other drivers. First, why you cannot use assigned-clock-rates? Or clk_get_rate() if this is about being consumer?

Quoted 1 line

Second, there is already system-clock-frequency property, so use it.

Indeed, I will added the related clocks in the 'clocks' property and use clk_get_rate() in the driver.

Quoted 11 lines

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 83

Quoted 8 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +7 -0
+
+  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.  

Why do you need it? How is it different from clock? Do you expect some DDR here?

This is needed to set the data position on the data line.
If the data line clock (sysclk-rate-hz) is greater than 'data-rate-bps', the device interleaves some holes between data in the full frame.

The exact position of the data and the holes is defined by 'channel-phase'

So, two information are needed:
- The number of slots available (deduced from 'lantiq,data-rate-bps')
- The slot to use in the available slots ('lantiq,channel-phase" property

lantiq,data-rate-bps is not a clock but a property used to set the frame physical setting. ie the correct data position in the frame.

Quoted 45 lines
Quoted 45 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +44 -0
+
+  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.
+
+allOf:
+  - if:
+      properties:
+        lantiq,line-interface:
Quoted 8 lines

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 132

Quoted 5 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +5 -0
+          contains:
+            const: e1
+    then:
+      properties:
+        lantiq,frame-format:  

Do not define properties in if:then, but in top-level. Disallow them or customize for the specific cases in if:then

Will be changed in v3.

Quoted 16 lines
Quoted 5 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +4 -0
+          $ref: /schemas/types.yaml#/definitions/string
+          enum: [doubleframe, crc4-multiframe, auto-multiframe]
+          default: doubleframe
+          description: |

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 146

Quoted 10 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +10 -0
+            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:  
Quoted 1 line

Same problem - definitions go to top level.

Will be changed in v3

Quoted 18 lines
Quoted 18 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +17 -0
+          $ref: /schemas/types.yaml#/definitions/string
+          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
+
Quoted 8 lines

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 169

Quoted 6 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +6 -0
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    pef2256@2000000 {  

Figure out some generic node name.

What do you think about 'framer' ?

Quoted 5 lines

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 171

Quoted 3 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +2 -0
+      compatible = "lantiq,pef2256";
+      reg = <0x2000000 0xFF>;  

Lowercase hex

Will be changed in v3.

Quoted 4 lines

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 172

Quoted 2 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +1 -0
+      interrupts = <8 1>;  

if 1 is interrupt flag, use proper defines.

Will be replaced by 'interrupts = <8 IRQ_TYPE_LEVEL_LOW>'
I will also change the interrupt-parent to interrupt-parent = <&intc> to avoid mentioning PIC and avoid any misunderstanding as the PIC we use does not follow the standard IRQ_TYPE_* flags.

Quoted 20 lines
Quoted 9 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +8 -0
+      interrupt-parent = <&PIC>;
+      clocks = <&clk_mclk>;
+      clock-names = "mclk";
+      reset-gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
+      lantiq,sysclk-rate-hz = <8192000>;
+      lantiq,data-rate-bps = <4096000>;
+
+      pinctrl {

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 190

Quoted 10 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +10 -0
+        pef2256_rpa_sypr: rpa-pins {
+          pins = "RPA";
+          function = "SYPR";
+        };
+        pef2256_xpa_sypx: xpa-pins {
+          pins = "XPA";
+          function = "SYPX";
+        };
+      };
+    };  
Quoted 3 lines

Best regards,
Krzysztof

Thanks for the review.

Best regards,
Hervé

Signature · 3 lines
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
#4 lore raw

Re: [PATCH v2 1/7] dt-bindings: misc: Add the Lantiq PEF2466 E1/T1/J1 framer

Quoted 16 lines · Herve Codina
Quoted 11 lines

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 83

Quoted 8 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +7 -0
+
+  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.  

Why do you need it? How is it different from clock? Do you expect some DDR here?

This is needed to set the data position on the data line.
If the data line clock (sysclk-rate-hz) is greater than 'data-rate-bps', the device interleaves some holes between data in the full frame.

Quoted 8 lines

The exact position of the data and the holes is defined by 'channel-phase'

So, two information are needed:
- The number of slots available (deduced from 'lantiq,data-rate-bps')
- The slot to use in the available slots ('lantiq,channel-phase" property

lantiq,data-rate-bps is not a clock but a property used to set the frame physical setting. ie the correct data position in the frame.

OK

(...)

Quoted 10 lines
Quoted 8 lines

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 169

Quoted 6 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +6 -0
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    pef2256@2000000 {  

Figure out some generic node name.

What do you think about 'framer' ?

Sure, I don't have particular proposal.

Best regards,
Krzysztof

#5 lore raw

Re: [PATCH v2 1/7] dt-bindings: misc: Add the Lantiq PEF2466 E1/T1/J1 framer

In reply to Krzysztof Kozlowski

Hi Krzysztof

Quoted 62 lines · On Fri, 17 Mar 2023 09:54:07 +0100 Krzysztof Kozlowski…
Quoted 48 lines · Herve Codina

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.

---
 .../bindings/misc/lantiq,pef2256.yaml         | 190 ++++++++++++++++++
 1 file changed, 190 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +32 -0
new file mode 100644
index 000000000000..1ba788d06a14
@@ -0,0 +1,190 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/misc/lantiq,pef2256.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Lantiq PEF2256
+
+maintainers:
+  - Herve Codina <[email protected]>
+
+description:
+  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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:
+    const: lantiq,pef2256
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Master clock
+
+  clock-names:
+    items:
+      - const: mclk
+
+  interrupts:

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 42

Quoted 10 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +10 -0
+    maxItems: 1
+
+  reset-gpios:
+    description:
+      GPIO used to reset the device.
+    maxItems: 1
+
+  pinctrl:
+    allOf:
+      - $ref: "/schemas/pinctrl/pinctrl.yaml#"  

Drop quotes. Drop allOf, no need for it.

Quoted 1 line

additionalProperties: false

Will be dropped and added in v3

Quoted 8 lines

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 48

Quoted 7 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +6 -0
+
+    patternProperties:
+      '-pins$':
+        type: object
+        allOf:
+          - $ref: "/schemas/pinctrl/pincfg-node.yaml#"  
Quoted 4 lines

Drop quotes. Drop allOf, no need for it.

additionalProperties: false

Will be dropped and added in v3

Quoted 34 lines
Quoted 19 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +18 -0
+
+        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 ]
+
+        required:
+          - pins
+          - function
+
+  lantiq,line-interface:
+    $ref: /schemas/types.yaml#/definitions/string
+    enum: [e1, t1j1]
+    default: e1

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 76

Quoted 10 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +10 -0
+    description: |
+      The line interface type
+        - e1: E1 line
+        - t1j1: T1/J1 line
+
+  lantiq,sysclk-rate-hz:
+    enum: [2048000, 4096000, 8192000, 16384000]
+    default: 2048000
+    description:
+      Clock rate (Hz) on the system highway.  

I am pretty sure we have discussions on sysclk for other drivers. First, why you cannot use assigned-clock-rates? Or clk_get_rate() if this is about being consumer?

Quoted 1 line

Second, there is already system-clock-frequency property, so use it.

Indeed, I will added the related clocks in the 'clocks' property and use clk_get_rate() in the driver.

Quoted 11 lines

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 83

Quoted 8 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +7 -0
+
+  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.  

Why do you need it? How is it different from clock? Do you expect some DDR here?

This is needed to set the data position on the data line.
If the data line clock (sysclk-rate-hz) is greater than 'data-rate-bps', the device interleaves some holes between data in the full frame.

The exact position of the data and the holes is defined by 'channel-phase'

So, two information are needed:
- The number of slots available (deduced from 'lantiq,data-rate-bps')
- The slot to use in the available slots ('lantiq,channel-phase" property

lantiq,data-rate-bps is not a clock but a property used to set the frame physical setting. ie the correct data position in the frame.

Quoted 45 lines
Quoted 45 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +44 -0
+
+  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.
+
+allOf:
+  - if:
+      properties:
+        lantiq,line-interface:
Quoted 8 lines

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 132

Quoted 5 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +5 -0
+          contains:
+            const: e1
+    then:
+      properties:
+        lantiq,frame-format:  

Do not define properties in if:then, but in top-level. Disallow them or customize for the specific cases in if:then

Will be changed in v3.

Quoted 16 lines
Quoted 5 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +4 -0
+          $ref: /schemas/types.yaml#/definitions/string
+          enum: [doubleframe, crc4-multiframe, auto-multiframe]
+          default: doubleframe
+          description: |

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 146

Quoted 10 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +10 -0
+            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:  
Quoted 1 line

Same problem - definitions go to top level.

Will be changed in v3

Quoted 18 lines
Quoted 18 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +17 -0
+          $ref: /schemas/types.yaml#/definitions/string
+          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
+
Quoted 8 lines

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 169

Quoted 6 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +6 -0
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    pef2256@2000000 {  

Figure out some generic node name.

What do you think about 'framer' ?

Quoted 5 lines

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 171

Quoted 3 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +2 -0
+      compatible = "lantiq,pef2256";
+      reg = <0x2000000 0xFF>;  

Lowercase hex

Will be changed in v3.

Quoted 4 lines

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 172

Quoted 2 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +1 -0
+      interrupts = <8 1>;  

if 1 is interrupt flag, use proper defines.

Will be replaced by 'interrupts = <8 IRQ_TYPE_LEVEL_LOW>'
I will also change the interrupt-parent to interrupt-parent = <&intc> to avoid mentioning PIC and avoid any misunderstanding as the PIC we use does not follow the standard IRQ_TYPE_* flags.

Quoted 20 lines
Quoted 9 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +8 -0
+      interrupt-parent = <&PIC>;
+      clocks = <&clk_mclk>;
+      clock-names = "mclk";
+      reset-gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
+      lantiq,sysclk-rate-hz = <8192000>;
+      lantiq,data-rate-bps = <4096000>;
+
+      pinctrl {

Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml line 190

Quoted 10 lines
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +10 -0
+        pef2256_rpa_sypr: rpa-pins {
+          pins = "RPA";
+          function = "SYPR";
+        };
+        pef2256_xpa_sypx: xpa-pins {
+          pins = "XPA";
+          function = "SYPX";
+        };
+      };
+    };  
Quoted 3 lines

Best regards,
Krzysztof

Thanks for the review.

Best regards,
Hervé

Signature · 3 lines
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
maintainer
#6 lore raw

Re: [PATCH v2 1/7] dt-bindings: misc: Add the Lantiq PEF2466 E1/T1/J1 framer

Quoted 68 lines · Herve Codina via Alsa-devel

Received: by alsa1.perex.cz (Postfix, from userid 50401) id 16494F8027B;
Mon, 20 Mar 2023 10:46:37 +0100 (CET)
X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on alsa1.perex.cz X-Spam-Level:
X-Spam-Status: No, score=-5.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID,
DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6
Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net
[217.70.183.198]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 3FF5FF80105 for <[email protected]>; Mon, 20 Mar 2023 10:46:22 +0100 (CET)
DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 3FF5FF80105
Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key,
unprotected) header.d=bootlin.com [email protected] header.a=rsa-sha256 header.s=gm1 header.b=m4O7nLC1
Received: (Authenticated sender: [email protected]) by
mail.gandi.net (Postfix) with ESMTPSA id 40453C0009; Mon, 20 Mar 2023 09:46:20 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1;
t=1679305582; h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
to:to:cc:cc:mime-version:mime-version:content-type:content-type:
content-transfer-encoding:content-transfer-encoding:
in-reply-to:in-reply-to:references:references;
bh=Ieu9Fv38se4lD4z/BVXUHLrVJL9Tx5iKWZgvO8X+VoY=; b=m4O7nLC1LPZDOI5eM/hmgqouxdkin2veA6CvJhT9kU9rGQALB3ya2fuybMfDvrkTqqBjEd j6DAxXMgOKgwuUfEsZsp3BFJpoii00hSaf0r2uIbnnGcUrDGVQqUQVEqv51O6VBqnrViQk PstlJM0lcE9R/AFASd5D/HQGoYYyRY+NKT7xt8g1Ax23Yk/tUG59LXku/skn/4faSLodnU vV2ng3VMUcoLuvSMJtdYY3hrXEWqUrW1ZogxAFHJNiKuyOELmqZGmNo4B4yAFOEcqqyano /f4m/7BtT7X1wwPvGu29gg+0aOFrGQq5kb4UNrMoriSQyKnxPRha8zL3J2Jckw==
Date: Mon, 20 Mar 2023 10:46:19 +0100
From: Herve Codina <[email protected]>
To: Krzysztof Kozlowski <[email protected]>
Subject: Re: [PATCH v2 1/7] dt-bindings: misc: Add the Lantiq PEF2466
E1/T1/J1 framer
Message-ID: <[email protected]>
In-Reply-To: <[email protected]>
References: <[email protected]>
<[email protected]> <[email protected]>
Organization: Bootlin
X-Mailer: Claws Mail 4.1.1 (GTK 3.24.37; x86_64-redhat-linux-gnu)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Message-ID-Hash: AJZF4VHU24ASVVBCPRMLJCDG4ZDX55LB
X-Message-ID-Hash: AJZF4VHU24ASVVBCPRMLJCDG4ZDX55LB
X-MailFrom: [email protected]
X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency;
loop; banned-address; member-moderation; header-match-alsa-devel.alsa-project.org-0; header-match-alsa-devel.alsa-project.org-1; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header
CC: Rob Herring <[email protected]>, Krzysztof Kozlowski
<[email protected]>, Liam Girdwood <[email protected]>, Mark Brown <[email protected]>, Derek Kiernan <[email protected]>, Dragan Cvetic <[email protected]>, Arnd Bergmann <[email protected]>, Greg Kroah-Hartman <[email protected]>, Takashi Iwai <[email protected]>, [email protected], [email protected], [email protected], Christophe Leroy <[email protected]>, Thomas Petazzoni <[email protected]>
X-Mailman-Version: 3.3.8
Precedence: list
List-Id: "Alsa-devel mailing list for ALSA developers -

Quoted 8 lines

http://www.alsa-project.org" <alsa-devel.alsa-project.org>
Archived-At: <https://mailman.alsa-project.org/hyperkitty/list/[email protected]/message/AJZF4VHU24ASVVBCPRMLJCDG4ZDX55LB/>
List-Archive: <https://mailman.alsa-project.org/hyperkitty/list/[email protected]/>
List-Help: <mailto:[email protected]?subject=help>
List-Owner: <mailto:[email protected]>
List-Post: <mailto:[email protected]>
List-Subscribe: <mailto:[email protected]>
List-Unsubscribe: <mailto:[email protected]>

The alsa-devel list doesn't seem to like your emails. The archives (lore) has 2 copies with the 2nd having the original headers in the body. I'm seeing this recently on other senders too. Best I can tell is you sent this as quoted-printable.

Rob

#7 lore raw

Re: [PATCH v2 1/7] dt-bindings: misc: Add the Lantiq PEF2466 E1/T1/J1 framer

Hi Rob,

Quoted 78 lines · On Mon, 20 Mar 2023 13:51:27 -0500 Rob Herring <[email protected]> wrote:
Quoted 68 lines · Herve Codina via Alsa-devel

Received: by alsa1.perex.cz (Postfix, from userid 50401) id 16494F8027B;
Mon, 20 Mar 2023 10:46:37 +0100 (CET)
X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on alsa1.perex.cz X-Spam-Level:
X-Spam-Status: No, score=-5.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID,
DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6
Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net
[217.70.183.198]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 3FF5FF80105 for <[email protected]>; Mon, 20 Mar 2023 10:46:22 +0100 (CET)
DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 3FF5FF80105
Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key,
unprotected) header.d=bootlin.com [email protected] header.a=rsa-sha256 header.s=gm1 header.b=m4O7nLC1
Received: (Authenticated sender: [email protected]) by
mail.gandi.net (Postfix) with ESMTPSA id 40453C0009; Mon, 20 Mar 2023 09:46:20 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1;
t=1679305582; h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
to:to:cc:cc:mime-version:mime-version:content-type:content-type:
content-transfer-encoding:content-transfer-encoding:
in-reply-to:in-reply-to:references:references;
bh=Ieu9Fv38se4lD4z/BVXUHLrVJL9Tx5iKWZgvO8X+VoY=; b=m4O7nLC1LPZDOI5eM/hmgqouxdkin2veA6CvJhT9kU9rGQALB3ya2fuybMfDvrkTqqBjEd j6DAxXMgOKgwuUfEsZsp3BFJpoii00hSaf0r2uIbnnGcUrDGVQqUQVEqv51O6VBqnrViQk PstlJM0lcE9R/AFASd5D/HQGoYYyRY+NKT7xt8g1Ax23Yk/tUG59LXku/skn/4faSLodnU vV2ng3VMUcoLuvSMJtdYY3hrXEWqUrW1ZogxAFHJNiKuyOELmqZGmNo4B4yAFOEcqqyano /f4m/7BtT7X1wwPvGu29gg+0aOFrGQq5kb4UNrMoriSQyKnxPRha8zL3J2Jckw==
Date: Mon, 20 Mar 2023 10:46:19 +0100
From: Herve Codina <[email protected]>
To: Krzysztof Kozlowski <[email protected]>
Subject: Re: [PATCH v2 1/7] dt-bindings: misc: Add the Lantiq PEF2466
E1/T1/J1 framer
Message-ID: <[email protected]>
In-Reply-To: <[email protected]>
References: <[email protected]>
<[email protected]> <[email protected]>
Organization: Bootlin
X-Mailer: Claws Mail 4.1.1 (GTK 3.24.37; x86_64-redhat-linux-gnu)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Message-ID-Hash: AJZF4VHU24ASVVBCPRMLJCDG4ZDX55LB
X-Message-ID-Hash: AJZF4VHU24ASVVBCPRMLJCDG4ZDX55LB
X-MailFrom: [email protected]
X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency;
loop; banned-address; member-moderation; header-match-alsa-devel.alsa-project.org-0; header-match-alsa-devel.alsa-project.org-1; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header
CC: Rob Herring <[email protected]>, Krzysztof Kozlowski
<[email protected]>, Liam Girdwood <[email protected]>, Mark Brown <[email protected]>, Derek Kiernan <[email protected]>, Dragan Cvetic <[email protected]>, Arnd Bergmann <[email protected]>, Greg Kroah-Hartman <[email protected]>, Takashi Iwai <[email protected]>, [email protected], [email protected], [email protected], Christophe Leroy <[email protected]>, Thomas Petazzoni <[email protected]>
X-Mailman-Version: 3.3.8
Precedence: list
List-Id: "Alsa-devel mailing list for ALSA developers -

Quoted 8 lines

http://www.alsa-project.org" <alsa-devel.alsa-project.org>
Archived-At: <https://mailman.alsa-project.org/hyperkitty/list/[email protected]/message/AJZF4VHU24ASVVBCPRMLJCDG4ZDX55LB/>
List-Archive: <https://mailman.alsa-project.org/hyperkitty/list/[email protected]/>
List-Help: <mailto:[email protected]?subject=help>
List-Owner: <mailto:[email protected]>
List-Post: <mailto:[email protected]>
List-Subscribe: <mailto:[email protected]>
List-Unsubscribe: <mailto:[email protected]>

Quoted 6 lines

The alsa-devel list doesn't seem to like your emails. The archives (lore) has 2 copies with the 2nd having the original headers in the body. I'm seeing this recently on other senders too. Best I can tell is you sent this as quoted-printable.

Rob

I don't known what happened with alsa-devel list.

For this answer, I tried to force '8bit' encoding instead of quoted-printable. Let me know if it is better.

Regards,
Hervé

Signature · 3 lines
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
maintainer
#8 lore raw

Re: [PATCH v2 1/7] dt-bindings: misc: Add the Lantiq PEF2466 E1/T1/J1 framer

Quoted 89 lines · Herve Codina

Hi Rob,

Quoted 83 lines · On Mon, 20 Mar 2023 13:51:27 -0500 Rob Herring <[email protected]> wrote:
Quoted 68 lines · Herve Codina via Alsa-devel

Received: by alsa1.perex.cz (Postfix, from userid 50401) id 16494F8027B;
Mon, 20 Mar 2023 10:46:37 +0100 (CET)
X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on alsa1.perex.cz X-Spam-Level:
X-Spam-Status: No, score=-5.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID,
DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6
Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net
[217.70.183.198]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 3FF5FF80105 for <[email protected]>; Mon, 20 Mar 2023 10:46:22 +0100 (CET)
DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 3FF5FF80105
Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key,
unprotected) header.d=bootlin.com [email protected] header.a=rsa-sha256 header.s=gm1 header.b=m4O7nLC1
Received: (Authenticated sender: [email protected]) by
mail.gandi.net (Postfix) with ESMTPSA id 40453C0009; Mon, 20 Mar 2023 09:46:20 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1;
t=1679305582; h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
to:to:cc:cc:mime-version:mime-version:content-type:content-type:
content-transfer-encoding:content-transfer-encoding:
in-reply-to:in-reply-to:references:references;
bh=Ieu9Fv38se4lD4z/BVXUHLrVJL9Tx5iKWZgvO8X+VoY=; b=m4O7nLC1LPZDOI5eM/hmgqouxdkin2veA6CvJhT9kU9rGQALB3ya2fuybMfDvrkTqqBjEd j6DAxXMgOKgwuUfEsZsp3BFJpoii00hSaf0r2uIbnnGcUrDGVQqUQVEqv51O6VBqnrViQk PstlJM0lcE9R/AFASd5D/HQGoYYyRY+NKT7xt8g1Ax23Yk/tUG59LXku/skn/4faSLodnU vV2ng3VMUcoLuvSMJtdYY3hrXEWqUrW1ZogxAFHJNiKuyOELmqZGmNo4B4yAFOEcqqyano /f4m/7BtT7X1wwPvGu29gg+0aOFrGQq5kb4UNrMoriSQyKnxPRha8zL3J2Jckw==
Date: Mon, 20 Mar 2023 10:46:19 +0100
From: Herve Codina <[email protected]>
To: Krzysztof Kozlowski <[email protected]>
Subject: Re: [PATCH v2 1/7] dt-bindings: misc: Add the Lantiq PEF2466
E1/T1/J1 framer
Message-ID: <[email protected]>
In-Reply-To: <[email protected]>
References: <[email protected]>
<[email protected]> <[email protected]>
Organization: Bootlin
X-Mailer: Claws Mail 4.1.1 (GTK 3.24.37; x86_64-redhat-linux-gnu)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Message-ID-Hash: AJZF4VHU24ASVVBCPRMLJCDG4ZDX55LB
X-Message-ID-Hash: AJZF4VHU24ASVVBCPRMLJCDG4ZDX55LB
X-MailFrom: [email protected]
X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency;
loop; banned-address; member-moderation; header-match-alsa-devel.alsa-project.org-0; header-match-alsa-devel.alsa-project.org-1; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header
CC: Rob Herring <[email protected]>, Krzysztof Kozlowski
<[email protected]>, Liam Girdwood <[email protected]>, Mark Brown <[email protected]>, Derek Kiernan <[email protected]>, Dragan Cvetic <[email protected]>, Arnd Bergmann <[email protected]>, Greg Kroah-Hartman <[email protected]>, Takashi Iwai <[email protected]>, [email protected], [email protected], [email protected], Christophe Leroy <[email protected]>, Thomas Petazzoni <[email protected]>
X-Mailman-Version: 3.3.8
Precedence: list
List-Id: "Alsa-devel mailing list for ALSA developers -

Quoted 8 lines

http://www.alsa-project.org" <alsa-devel.alsa-project.org>
Archived-At: <https://mailman.alsa-project.org/hyperkitty/list/[email protected]/message/AJZF4VHU24ASVVBCPRMLJCDG4ZDX55LB/>
List-Archive: <https://mailman.alsa-project.org/hyperkitty/list/[email protected]/>
List-Help: <mailto:[email protected]?subject=help>
List-Owner: <mailto:[email protected]>
List-Post: <mailto:[email protected]>
List-Subscribe: <mailto:[email protected]>
List-Unsubscribe: <mailto:[email protected]>

The alsa-devel list doesn't seem to like your emails. The archives (lore) has 2 copies with the 2nd having the original headers in the body. I'm seeing this recently on other senders too. Best I can tell is you sent this as quoted-printable.

Quoted 6 lines
Quoted 1 line

Rob

I don't known what happened with alsa-devel list.

For this answer, I tried to force '8bit' encoding instead of quoted-printable. Let me know if it is better.

Nope, still the same issue:

https://lore.kernel.org/all/167948048307.26.16805930109507404147@mailman-core.alsa-project.org/

I added the alsa-devel owner. Maybe they know what's happening.

Rob

maintainer
#9 lore raw

Re: [PATCH v2 1/7] dt-bindings: misc: Add the Lantiq PEF2466 E1/T1/J1 framer

Quoted 95 lines · Rob Herring
Quoted 93 lines · Herve Codina

Hi Rob,

Quoted 78 lines · On Mon, 20 Mar 2023 13:51:27 -0500 Rob Herring <[email protected]> wrote:
Quoted 68 lines · Herve Codina via Alsa-devel

Received: by alsa1.perex.cz (Postfix, from userid 50401) id 16494F8027B;
Mon, 20 Mar 2023 10:46:37 +0100 (CET)
X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on alsa1.perex.cz X-Spam-Level:
X-Spam-Status: No, score=-5.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID,
DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6
Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net
[217.70.183.198]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 3FF5FF80105 for <[email protected]>; Mon, 20 Mar 2023 10:46:22 +0100 (CET)
DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 3FF5FF80105
Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key,
unprotected) header.d=bootlin.com [email protected] header.a=rsa-sha256 header.s=gm1 header.b=m4O7nLC1
Received: (Authenticated sender: [email protected]) by
mail.gandi.net (Postfix) with ESMTPSA id 40453C0009; Mon, 20 Mar 2023 09:46:20 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1;
t=1679305582; h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
to:to:cc:cc:mime-version:mime-version:content-type:content-type:
content-transfer-encoding:content-transfer-encoding:
in-reply-to:in-reply-to:references:references;
bh=Ieu9Fv38se4lD4z/BVXUHLrVJL9Tx5iKWZgvO8X+VoY=; b=m4O7nLC1LPZDOI5eM/hmgqouxdkin2veA6CvJhT9kU9rGQALB3ya2fuybMfDvrkTqqBjEd j6DAxXMgOKgwuUfEsZsp3BFJpoii00hSaf0r2uIbnnGcUrDGVQqUQVEqv51O6VBqnrViQk PstlJM0lcE9R/AFASd5D/HQGoYYyRY+NKT7xt8g1Ax23Yk/tUG59LXku/skn/4faSLodnU vV2ng3VMUcoLuvSMJtdYY3hrXEWqUrW1ZogxAFHJNiKuyOELmqZGmNo4B4yAFOEcqqyano /f4m/7BtT7X1wwPvGu29gg+0aOFrGQq5kb4UNrMoriSQyKnxPRha8zL3J2Jckw==
Date: Mon, 20 Mar 2023 10:46:19 +0100
From: Herve Codina <[email protected]>
To: Krzysztof Kozlowski <[email protected]>
Subject: Re: [PATCH v2 1/7] dt-bindings: misc: Add the Lantiq PEF2466
E1/T1/J1 framer
Message-ID: <[email protected]>
In-Reply-To: <[email protected]>
References: <[email protected]>
<[email protected]> <[email protected]>
Organization: Bootlin
X-Mailer: Claws Mail 4.1.1 (GTK 3.24.37; x86_64-redhat-linux-gnu)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Message-ID-Hash: AJZF4VHU24ASVVBCPRMLJCDG4ZDX55LB
X-Message-ID-Hash: AJZF4VHU24ASVVBCPRMLJCDG4ZDX55LB
X-MailFrom: [email protected]
X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency;
loop; banned-address; member-moderation; header-match-alsa-devel.alsa-project.org-0; header-match-alsa-devel.alsa-project.org-1; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header
CC: Rob Herring <[email protected]>, Krzysztof Kozlowski
<[email protected]>, Liam Girdwood <[email protected]>, Mark Brown <[email protected]>, Derek Kiernan <[email protected]>, Dragan Cvetic <[email protected]>, Arnd Bergmann <[email protected]>, Greg Kroah-Hartman <[email protected]>, Takashi Iwai <[email protected]>, [email protected], [email protected], [email protected], Christophe Leroy <[email protected]>, Thomas Petazzoni <[email protected]>
X-Mailman-Version: 3.3.8
Precedence: list
List-Id: "Alsa-devel mailing list for ALSA developers -

Quoted 8 lines

http://www.alsa-project.org" <alsa-devel.alsa-project.org>
Archived-At: <https://mailman.alsa-project.org/hyperkitty/list/[email protected]/message/AJZF4VHU24ASVVBCPRMLJCDG4ZDX55LB/>
List-Archive: <https://mailman.alsa-project.org/hyperkitty/list/[email protected]/>
List-Help: <mailto:[email protected]?subject=help>
List-Owner: <mailto:[email protected]>
List-Post: <mailto:[email protected]>
List-Subscribe: <mailto:[email protected]>
List-Unsubscribe: <mailto:[email protected]>

Quoted 6 lines

The alsa-devel list doesn't seem to like your emails. The archives (lore) has 2 copies with the 2nd having the original headers in the body. I'm seeing this recently on other senders too. Best I can tell is you sent this as quoted-printable.

Rob

I don't known what happened with alsa-devel list.

Quoted 8 lines
Quoted 2 lines

For this answer, I tried to force '8bit' encoding instead of quoted-printable. Let me know if it is better.

Nope, still the same issue:

https://lore.kernel.org/all/167948048307.26.16805930109507404147@mailman-core.alsa-project.org/

I added the alsa-devel owner. Maybe they know what's happening.

Here's the answer:

https://lore.kernel.org/alsa-devel/[email protected]/

Something about DMARC and your domain. But some reason git-send-email doesn't have the issue sending.

Rob

#10 lore raw

Re: [PATCH v2 1/7] dt-bindings: misc: Add the Lantiq PEF2466 E1/T1/J1 framer

In reply to Rob Herring

Hi Rob,

Quoted 78 lines · On Mon, 20 Mar 2023 13:51:27 -0500 Rob Herring <[email protected]> wrote:
Quoted 68 lines · Herve Codina via Alsa-devel

Received: by alsa1.perex.cz (Postfix, from userid 50401) id 16494F8027B;
Mon, 20 Mar 2023 10:46:37 +0100 (CET)
X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on alsa1.perex.cz X-Spam-Level:
X-Spam-Status: No, score=-5.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID,
DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6
Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net
[217.70.183.198]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 3FF5FF80105 for <[email protected]>; Mon, 20 Mar 2023 10:46:22 +0100 (CET)
DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 3FF5FF80105
Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key,
unprotected) header.d=bootlin.com [email protected] header.a=rsa-sha256 header.s=gm1 header.b=m4O7nLC1
Received: (Authenticated sender: [email protected]) by
mail.gandi.net (Postfix) with ESMTPSA id 40453C0009; Mon, 20 Mar 2023 09:46:20 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1;
t=1679305582; h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
to:to:cc:cc:mime-version:mime-version:content-type:content-type:
content-transfer-encoding:content-transfer-encoding:
in-reply-to:in-reply-to:references:references;
bh=Ieu9Fv38se4lD4z/BVXUHLrVJL9Tx5iKWZgvO8X+VoY=; b=m4O7nLC1LPZDOI5eM/hmgqouxdkin2veA6CvJhT9kU9rGQALB3ya2fuybMfDvrkTqqBjEd j6DAxXMgOKgwuUfEsZsp3BFJpoii00hSaf0r2uIbnnGcUrDGVQqUQVEqv51O6VBqnrViQk PstlJM0lcE9R/AFASd5D/HQGoYYyRY+NKT7xt8g1Ax23Yk/tUG59LXku/skn/4faSLodnU vV2ng3VMUcoLuvSMJtdYY3hrXEWqUrW1ZogxAFHJNiKuyOELmqZGmNo4B4yAFOEcqqyano /f4m/7BtT7X1wwPvGu29gg+0aOFrGQq5kb4UNrMoriSQyKnxPRha8zL3J2Jckw==
Date: Mon, 20 Mar 2023 10:46:19 +0100
From: Herve Codina <[email protected]>
To: Krzysztof Kozlowski <[email protected]>
Subject: Re: [PATCH v2 1/7] dt-bindings: misc: Add the Lantiq PEF2466
E1/T1/J1 framer
Message-ID: <[email protected]>
In-Reply-To: <[email protected]>
References: <[email protected]>
<[email protected]> <[email protected]>
Organization: Bootlin
X-Mailer: Claws Mail 4.1.1 (GTK 3.24.37; x86_64-redhat-linux-gnu)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Message-ID-Hash: AJZF4VHU24ASVVBCPRMLJCDG4ZDX55LB
X-Message-ID-Hash: AJZF4VHU24ASVVBCPRMLJCDG4ZDX55LB
X-MailFrom: [email protected]
X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency;
loop; banned-address; member-moderation; header-match-alsa-devel.alsa-project.org-0; header-match-alsa-devel.alsa-project.org-1; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header
CC: Rob Herring <[email protected]>, Krzysztof Kozlowski
<[email protected]>, Liam Girdwood <[email protected]>, Mark Brown <[email protected]>, Derek Kiernan <[email protected]>, Dragan Cvetic <[email protected]>, Arnd Bergmann <[email protected]>, Greg Kroah-Hartman <[email protected]>, Takashi Iwai <[email protected]>, [email protected], [email protected], [email protected], Christophe Leroy <[email protected]>, Thomas Petazzoni <[email protected]>
X-Mailman-Version: 3.3.8
Precedence: list
List-Id: "Alsa-devel mailing list for ALSA developers -

Quoted 8 lines

http://www.alsa-project.org" <alsa-devel.alsa-project.org>
Archived-At: <https://mailman.alsa-project.org/hyperkitty/list/[email protected]/message/AJZF4VHU24ASVVBCPRMLJCDG4ZDX55LB/>
List-Archive: <https://mailman.alsa-project.org/hyperkitty/list/[email protected]/>
List-Help: <mailto:[email protected]?subject=help>
List-Owner: <mailto:[email protected]>
List-Post: <mailto:[email protected]>
List-Subscribe: <mailto:[email protected]>
List-Unsubscribe: <mailto:[email protected]>

Quoted 6 lines

The alsa-devel list doesn't seem to like your emails. The archives (lore) has 2 copies with the 2nd having the original headers in the body. I'm seeing this recently on other senders too. Best I can tell is you sent this as quoted-printable.

Rob

I don't known what happened with alsa-devel list.

For this answer, I tried to force '8bit' encoding instead of quoted-printable. Let me know if it is better.

Regards,
Hervé

Signature · 3 lines
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
#11 lore raw

Re: [PATCH v2 1/7] dt-bindings: misc: Add the Lantiq PEF2466 E1/T1/J1 framer

In reply to Herve Codina
Quoted 1 line · Herve Codina

The Lantiq PEF2256 is a framer and line interface component designed to

Your subject says PEF2466, commit msg and code say something different.

Quoted 5 lines

fulfill all required interfacing between an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.

---

Best regards,
Krzysztof

#12 lore raw

PATCH v2 2/7 drivers: misc: Add support for the Lantiq PEF2256 framer

In reply to Herve Codina

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.

---
 drivers/misc/Kconfig    |   17 +
 drivers/misc/Makefile   |    1 +
 drivers/misc/pef2256.c  | 1441 +++++++++++++++++++++++++++++++++++++++
 include/linux/pef2256.h |   36 +
 4 files changed, 1495 insertions(+)
 create mode 100644 drivers/misc/pef2256.c
 create mode 100644 include/linux/pef2256.h
drivers/misc/Kconfig +17 -0
index 433aa4197785..f03739163c53 100644
@@ -376,6 +376,23 @@ config HMC6352
 	  This driver provides support for the Honeywell HMC6352 compass,
 	  providing configuration and heading data via sysfs.
 
+config PEF2256
+	tristate "Lantiq PEF2256 (FALC56) framer"
+	depends on HAS_IOMEM
+	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 DS1682
 	tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
 	depends on I2C
drivers/misc/Makefile +1 -0
index 56de43943cd5..a26f044ab9dd 100644
@@ -35,6 +35,7 @@ obj-$(CONFIG_SENSORS_TSL2550)	+= tsl2550.o
 obj-$(CONFIG_DS1682)		+= ds1682.o
 obj-$(CONFIG_C2PORT)		+= c2port/
 obj-$(CONFIG_HMC6352)		+= hmc6352.o
+obj-$(CONFIG_PEF2256)		+= pef2256.o
 obj-y				+= eeprom/
 obj-y				+= cb710/
 obj-$(CONFIG_VMWARE_BALLOON)	+= vmw_balloon.o
drivers/misc/pef2256.c new file +1441 -0

1,441 lines not on this page · raw message

include/linux/pef2256.h new file +36 -0
new file mode 100644
index 000000000000..6c8d173595b1
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * PEF2256 management
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina <[email protected]>
+ */
+#ifndef __PEF2256_H__
+#define __PEF2256_H__
+
+#include <linux/types.h>
+
+struct pef2256;
+struct device_node;
+struct device;
+struct notifier_block;
+
+struct pef2256 *pef2256_get_byphandle(struct device_node *np, const char *phandle_name);
+void pef2256_put(struct pef2256 *pef2256);
+struct pef2256 *devm_pef2256_get_byphandle(struct device *dev, struct device_node *np,
+					   const char *phandle_name);
+
+
+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__ */
Signature · 1 line
2.39.2
#13 lore raw

Re: [PATCH v2 2/7] drivers: misc: Add support for the Lantiq PEF2256 framer

Quoted 1 line · Herve Codina

+EXPORT_SYMBOL(pef2256_get_byphandle);

You have a mixture of EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL() in the same file here. As this one:

drivers/misc/pef2256.c line 1383

Quoted 6 lines
drivers/misc/pef2256.c new file +6 -0
+
+void pef2256_put(struct pef2256 *pef2256)
+{
+	put_device(pef2256->dev);
+}
+EXPORT_SYMBOL(pef2256_put);

Is just a wrapper around a EXPORT_SYMBOL_GPL() function, please revisit and perhaps make them all EXPORT_SYMBOL_GPL() calls?

thanks,

greg k-h

#14 lore raw

Re: [PATCH v2 2/7] drivers: misc: Add support for the Lantiq PEF2256 framer

Hi Greg,

Quoted 6 lines · On Thu, 16 Mar 2023 13:49:19 +0100 Greg Kroah-Hartman…
Quoted 1 line · Herve Codina

+EXPORT_SYMBOL(pef2256_get_byphandle);

You have a mixture of EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL() in the same file here. As this one:

Quoted 10 lines

drivers/misc/pef2256.c line 1383

Quoted 6 lines
drivers/misc/pef2256.c new file +6 -0
+
+void pef2256_put(struct pef2256 *pef2256)
+{
+	put_device(pef2256->dev);
+}
+EXPORT_SYMBOL(pef2256_put);  

Is just a wrapper around a EXPORT_SYMBOL_GPL() function, please revisit and perhaps make them all EXPORT_SYMBOL_GPL() calls?

Indeed.
I will make them consistent in the v3 series.

Thanks for pointing that out.
Hervé

Signature · 3 lines
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
#15 lore raw

Re: [PATCH v2 2/7] drivers: misc: Add support for the Lantiq PEF2256 framer

In reply to Greg Kroah-Hartman

Hi Greg,

Quoted 6 lines · On Thu, 16 Mar 2023 13:49:19 +0100 Greg Kroah-Hartman…
Quoted 1 line · Herve Codina

+EXPORT_SYMBOL(pef2256_get_byphandle);

You have a mixture of EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL() in the same file here. As this one:

Quoted 10 lines

drivers/misc/pef2256.c line 1383

Quoted 6 lines
drivers/misc/pef2256.c new file +6 -0
+
+void pef2256_put(struct pef2256 *pef2256)
+{
+	put_device(pef2256->dev);
+}
+EXPORT_SYMBOL(pef2256_put);  

Is just a wrapper around a EXPORT_SYMBOL_GPL() function, please revisit and perhaps make them all EXPORT_SYMBOL_GPL() calls?

Indeed.
I will make them consistent in the v3 series.

Thanks for pointing that out.
Hervé

Signature · 3 lines
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
#16 lore raw

Re: [PATCH v2 2/7] drivers: misc: Add support for the Lantiq PEF2256 framer

In reply to Herve Codina

Le 16/03/2023 à 13:27, Herve Codina a écrit :

Quoted 261 lines

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.

---
  drivers/misc/Kconfig    |   17 +
  drivers/misc/Makefile   |    1 +
  drivers/misc/pef2256.c  | 1441 +++++++++++++++++++++++++++++++++++++++
  include/linux/pef2256.h |   36 +
  4 files changed, 1495 insertions(+)

create mode 100644 drivers/misc/pef2256.c
create mode 100644 include/linux/pef2256.h

drivers/misc/Kconfig +17 -0
index 433aa4197785..f03739163c53 100644
@@ -376,6 +376,23 @@ config HMC6352
  	  This driver provides support for the Honeywell HMC6352 compass,
  	  providing configuration and heading data via sysfs.
 
+config PEF2256
+	tristate "Lantiq PEF2256 (FALC56) framer"
+	depends on HAS_IOMEM
+	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 DS1682
  	tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
  	depends on I2C
drivers/misc/Makefile +1 -0
index 56de43943cd5..a26f044ab9dd 100644
@@ -35,6 +35,7 @@ obj-$(CONFIG_SENSORS_TSL2550)	+= tsl2550.o
  obj-$(CONFIG_DS1682)		+= ds1682.o
  obj-$(CONFIG_C2PORT)		+= c2port/
  obj-$(CONFIG_HMC6352)		+= hmc6352.o
+obj-$(CONFIG_PEF2256)		+= pef2256.o
  obj-y				+= eeprom/
  obj-y				+= cb710/
  obj-$(CONFIG_VMWARE_BALLOON)	+= vmw_balloon.o
drivers/misc/pef2256.c new file +201 -0
new file mode 100644
index 000000000000..b21586084408
@@ -0,0 +1,1441 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PEF2256 also known as FALC56 driver
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina <[email protected]>
+ */
+
+#include <linux/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)

drivers/misc/pef2256.c line 211

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -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 */

Should be (0x92 + (_n) - 1) to avoid any risk.

Quoted 15 lines
drivers/misc/pef2256.c new file +15 -0
+#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)

drivers/misc/pef2256.c line 236

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+#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))

_n or n ?

Quoted 71 lines
drivers/misc/pef2256.c new file +71 -0
+#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;
+	spinlock_t lock;
+	struct clk *mclk;
+	struct gpio_desc *reset_gpio;
+	struct {
+		struct pinctrl_desc pctrl_desc;
+		const struct pef2256_function_desc *functions;
+		unsigned int nfunctions;
+	} pinctrl;
+	bool is_e1;
+	u32 sysclk_rate;
+	u32 data_rate;
+	bool is_tx_falling_edge;
+	bool is_subordinate;
+	enum pef2256_frame_type frame_type;
+	u8 channel_phase;
+	bool is_carrier_on;
+	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);

drivers/misc/pef2256.c line 317

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+}
+
+static inline void pef2256_clrbits8(struct pef2256 *pef2256, int offset, u8 clr)
+{
+	u8 v;
+
+	v = pef2256_read8(pef2256, offset);
+	v &= ~clr;
+	pef2256_write8(pef2256, offset, v);
+}

Not sure it is worth the number of lines.

Would liekly be as good with just:

	pef2256_write8(pef2256, offset, pef2256_read8(pef2256, offset) & ~clr);

Same for all.

Also, it shouldn't need to be flagged 'inline' as it is defined in the C file it is used. GCC will decide by itself if it is worth inlining.

Quoted 48 lines
drivers/misc/pef2256.c new file +48 -0
+
+static inline void pef2256_setbits8(struct pef2256 *pef2256, int offset, u8 set)
+{
+	u8 v;
+
+	v = pef2256_read8(pef2256, offset);
+	v |= set;
+	pef2256_write8(pef2256, offset, v);
+}
+
+
+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;
+	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;
+			goto end;
+		}
+		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;
+			goto end;
+		case PEF2256_2X_WID_VERSION_22:
+			version_txt = "2.2 (2.x)";
+			version = PEF2256_VERSION_2_2;
+			goto end;

drivers/misc/pef2256.c line 375

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+		default:
+			break;
+		}
+		break;
+	case PEF2256_VSTR_VERSION_21:
+		version_txt = "2.1";
+		version = PEF2256_VERSION_2_1;
+		goto end;
+	default:
+		break;

A default doing nothing is not needed unless the switch handles a enum and you have not covered all possible values.

My preference would be that you use the default to set:
version = PEF2256_VERSION_UNKNOWN;

then use an if (version == PEF2256_VERSION_UNKNOWN) / else below for the dev_err/dev_info.

Quoted 83 lines
drivers/misc/pef2256.c new file +83 -0
+	}
+
+	dev_err(pef2256->dev, "Unknown version (0x%02x, 0x%02x)\n", vstr, wid);
+	return PEF2256_VERSION_UNKNOWN;
+
+end:
+	dev_info(pef2256->dev, "Version %s detected\n", version_txt);
+	return version;
+}
+
+static int pef2256_12_setup_gcm(struct pef2256 *pef2256)
+{
+	static const u8 gcm_1544000[6] = {0xF0, 0x51, 0x00, 0x80, 0x00, 0x15};
+	static const u8 gcm_2048000[6] = {0x00, 0x58, 0xD2, 0xC2, 0x00, 0x10};
+	static const u8 gcm_8192000[6] = {0x00, 0x58, 0xD2, 0xC2, 0x03, 0x10};
+	static const u8 gcm_10000000[6] = {0x90, 0x51, 0x81, 0x8F, 0x04, 0x10};
+	static const u8 gcm_12352000[6] = {0xF0, 0x51, 0x00, 0x80, 0x07, 0x15};
+	static const u8 gcm_16384000[6] = {0x00, 0x58, 0xD2, 0xC2, 0x07, 0x10};
+	unsigned long mclk_rate;
+	const u8 *gcm;
+	int i;
+
+	mclk_rate = clk_get_rate(pef2256->mclk);
+	switch (mclk_rate) {
+	case 1544000:
+		gcm = gcm_1544000;
+		break;
+	case 2048000:
+		gcm = gcm_2048000;
+		break;
+	case 8192000:
+		gcm = gcm_8192000;
+		break;
+	case 10000000:
+		gcm = gcm_10000000;
+		break;
+	case 12352000:
+		gcm = gcm_12352000;
+		break;
+	case 16384000:
+		gcm = gcm_16384000;
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported v1.2 MCLK rate %lu\n", mclk_rate);
+		return -EINVAL;
+	}
+	for (i = 0; i < 6; i++)
+		pef2256_write8(pef2256, PEF2256_GCM(i+1), gcm[i]);
+
+	return 0;
+}
+
+static int pef2256_2x_setup_gcm(struct pef2256 *pef2256)
+{
+	static const u8 gcm_1544000[8] = {0x00, 0x15, 0x00, 0x08, 0x00, 0x3F, 0x9C, 0xDF};
+	static const u8 gcm_2048000[8] = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x2F, 0xDB, 0xDF};
+	static const u8 gcm_8192000[8] = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x0B, 0xDB, 0xDF};
+	static const u8 gcm_10000000[8] = {0x40, 0x1B, 0x3D, 0x0A, 0x00, 0x07, 0xC9, 0xDC};
+	static const u8 gcm_12352000[8] = {0x00, 0x19, 0x00, 0x08, 0x01, 0x0A, 0x98, 0xDA};
+	static const u8 gcm_16384000[8] = {0x00, 0x18, 0xFB, 0x0B, 0x01, 0x0B, 0xDB, 0xDF};
+	unsigned long mclk_rate;
+	const u8 *gcm;
+	int i;
+
+	mclk_rate = clk_get_rate(pef2256->mclk);
+	switch (mclk_rate) {
+	case 1544000:
+		gcm = gcm_1544000;
+		break;
+	case 2048000:
+		gcm = gcm_2048000;
+		break;
+	case 8192000:
+		gcm = gcm_8192000;
+		break;
+	case 10000000:
+		gcm = gcm_10000000;
+		break;
+	case 12352000:
+		gcm = gcm_12352000;
+		break;
+	case 16384000:
+		gcm = gcm_16384000;

drivers/misc/pef2256.c line 468

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported v2.x MCLK rate %lu\n", mclk_rate);
+		return -EINVAL;
+	}
+	for (i = 0; i < 8; i++)
+		pef2256_write8(pef2256, PEF2256_GCM(i+1), gcm[i]);
+
+	return 0;
+}

This function and the previous one look very similar, can we merge them ?

Quoted 123 lines
drivers/misc/pef2256.c new file +123 -0
+
+static int pef2256_setup_gcm(struct pef2256 *pef2256)
+{
+	return (pef2256->version == PEF2256_VERSION_1_2) ?
+		pef2256_12_setup_gcm(pef2256) : pef2256_2x_setup_gcm(pef2256);
+}
+
+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

drivers/misc/pef2256.c line 601

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+	 */
+	if (pef2256->version == PEF2256_VERSION_1_2) {
+		pef2256_write8(pef2256, PEF2256_XPM0, 0x7B);
+		pef2256_write8(pef2256, PEF2256_XPM1, 0x03);
+		pef2256_write8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT | 0x00);
+	} else {
+		pef2256_write8(pef2256, PEF2256_XPM0, 0x9C);
+		pef2256_write8(pef2256, PEF2256_XPM1, 0x03);
+		pef2256_write8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT | 0x00);
+	}

Only first line seem different, could XPM1 and XPM2 be outside the if/else ?

Quoted 4 lines
drivers/misc/pef2256.c new file +4 -0
+
+	/* "master" mode */
+	if (!pef2256->is_subordinate)
+		pef2256_setbits8(pef2256, PEF2256_LIM0, PEF2256_LIM0_MAS);

drivers/misc/pef2256.c line 615

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+
+	/* transmit line in normal operation */
+	pef2256_clrbits8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT);
+
+	if (pef2256->version == PEF2256_VERSION_1_2) {
+		/* receive input threshold = 0,21V */
+		pef2256_clrsetbits8(pef2256, PEF2256_LIM1, PEF2256_12_LIM1_RIL_MASK,
+				    PEF2256_12_LIM1_RIL_210);
+	} else {
+		/* receive input threshold = 0,21V */

Same comment twice, could be before the 'if' and remove the { } then ?

drivers/misc/pef2256.c line 621

Quoted 6 lines
drivers/misc/pef2256.c new file +6 -0
+		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);

Wouldn't that fit in a single line with the new recommended 100 char max line length ? I thing it would be more readable as a single line.

Quoted 11 lines
drivers/misc/pef2256.c new file +11 -0
+
+	/* 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);
+

drivers/misc/pef2256.c line 642

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+	/* DCO-X center frequency enabled */
+	pef2256_setbits8(pef2256, PEF2256_CMR2, PEF2256_CMR2_DCOXC);
+
+	if (pef2256->is_subordinate) {
+		/* select RCLK source = 2M */
+		pef2256_clrsetbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_RS_MASK,
+				    PEF2256_CMR1_RS_DCOR_2048);
+		/* disable switching from RCLK to SYNC */
+		pef2256_setbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_DCS);
+	}

I'd move the comments into a single one before the 'if', the two comments are related.

drivers/misc/pef2256.c line 647

Quoted 5 lines
drivers/misc/pef2256.c new file +5 -0
+
+	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);
+	}

I'd put the comment before the 'if' and remove the { }

drivers/misc/pef2256.c line 650

Quoted 3 lines
drivers/misc/pef2256.c new file +3 -0
+
+	if (!pef2256->is_tx_falling_edge) {
+		/* rising edge sync pulse transmit */

This comment doesn't seem to match the condition (rising versus falling).

drivers/misc/pef2256.c line 654

Quoted 4 lines
drivers/misc/pef2256.c new file +4 -0
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC3,
+				    PEF2256_SIC3_RESR, PEF2256_SIC3_RESX);
+	} else {
+		/* rising edge sync pulse receive */

This comment doesn't seem to match the condition (receive versus tx).

Quoted 57 lines
drivers/misc/pef2256.c new file +57 -0
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC3,
+				    PEF2256_SIC3_RESX, PEF2256_SIC3_RESR);
+	}
+
+	/* 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 %u\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 */

drivers/misc/pef2256.c line 721

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+	pef2256_clrsetbits8(pef2256, PEF2256_SIC2, PEF2256_SIC2_SICS_MASK,
+			    PEF2256_SIC2_SICS(pef2256->channel_phase));
+
+	if (pef2256->is_subordinate) {
+		/* transmit buffer size = 2 frames */
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_XBS_MASK,
+				    PEF2256_SIC1_XBS_2FRAMES);
+		/* transmit transparent mode */
+		pef2256_setbits8(pef2256, PEF2256_XSW, PEF2256_XSW_XTM);
+	}

Could this block get regrouped with the RX block depending on is_subordinate ?

Quoted 25 lines
drivers/misc/pef2256.c new file +25 -0
+
+	/* 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;

drivers/misc/pef2256.c line 756

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+}
+
+static int pef2256_setup(struct pef2256 *pef2256)
+{
+	if (!pef2256->is_e1) {
+		dev_err(pef2256->dev, "Only E1 line is currently supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	return pef2256_setup_e1(pef2256);

In order to use future addition of other modes, I'd do:

	if (!pef2256->is_e1)
		return pef2256_setup_e1(pef2256);

	dev_err(pef2256->dev, "Only E1 line is currently supported\n");
	return -EOPNOTSUPP;
Quoted 22 lines
drivers/misc/pef2256.c new file +22 -0
+}
+
+
+
+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 is_changed = false;
+	unsigned long flags;
+	bool is_carrier_on;

drivers/misc/pef2256.c line 788

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+
+	if (isr & (PEF2256_INT2_LOS | PEF2256_INT2_AIS)) {
+
+		spin_lock_irqsave(&pef2256->lock, flags);
+		is_carrier_on = pef2256_is_carrier_on(pef2256);
+		if (is_carrier_on != pef2256->is_carrier_on) {
+			pef2256->is_carrier_on = is_carrier_on;
+			is_changed = true;
+		}
+		spin_unlock_irqrestore(&pef2256->lock, flags);

Do we really need spin_locks for that ?
If atomicity is really an issue, may we use atomic operations instead ?

Quoted 695 lines
drivers/misc/pef2256.c new file +653 -0
+
+		if (is_changed)
+			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->sysclk_rate = 2048000;
+	ret = of_property_read_u32(np, "lantiq,sysclk-rate-hz", &pef2256->sysclk_rate);
+	if (ret && ret != -EINVAL) {
+		dev_err(pef2256->dev, "%pOF: failed to read lantiq,sysclk-rate-hz\n", np);
+		return ret;
+	}
+	dev_dbg(pef2256->dev, "config: sysclk %u Hz\n", pef2256->sysclk_rate);
+
+	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;
+	struct pef2256 *pef2256;
+	int ret;
+	int irq;
+
+	pef2256 = devm_kzalloc(&pdev->dev, sizeof(*pef2256), GFP_KERNEL);
+	if (!pef2256)
+		return -ENOMEM;
+
+	pef2256->dev = &pdev->dev;
+	spin_lock_init(&pef2256->lock);
+	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));
+
+	/* 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.
+	 */
+	pef2256->is_carrier_on = false;
+
+	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;
+	}
+
+	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);
+
+struct pef2256 *pef2256_get_byphandle(struct device_node *np, const char *phandle_name)
+{
+	struct device_node *pef2256_np;
+	struct platform_device *pdev;
+	struct pef2256 *pef2256;
+
+	pef2256_np = of_parse_phandle(np, phandle_name, 0);
+	if (!pef2256_np)
+		return ERR_PTR(-EINVAL);
+
+	if (!of_match_node(pef2256_driver.driver.of_match_table, pef2256_np)) {
+		of_node_put(pef2256_np);
+		return ERR_PTR(-EINVAL);
+	}
+
+	pdev = of_find_device_by_node(pef2256_np);
+	of_node_put(pef2256_np);
+	if (!pdev)
+		return ERR_PTR(-ENODEV);
+
+	pef2256 = platform_get_drvdata(pdev);
+	if (!pef2256) {
+		platform_device_put(pdev);
+		return ERR_PTR(-EPROBE_DEFER);
+	}
+
+	return pef2256;
+}
+EXPORT_SYMBOL(pef2256_get_byphandle);
+
+void pef2256_put(struct pef2256 *pef2256)
+{
+	put_device(pef2256->dev);
+}
+EXPORT_SYMBOL(pef2256_put);
+
+static void devm_pef2256_release(struct device *dev, void *res)
+{
+	struct pef2256 **pef2256 = res;
+
+	pef2256_put(*pef2256);
+}
+
+struct pef2256 *devm_pef2256_get_byphandle(struct device *dev, struct device_node *np,
+					   const char *phandle_name)
+{
+	struct pef2256 *pef2256;
+	struct pef2256 **dr;
+
+	dr = devres_alloc(devm_pef2256_release, sizeof(*dr), GFP_KERNEL);
+	if (!dr)
+		return ERR_PTR(-ENOMEM);
+
+	pef2256 = pef2256_get_byphandle(np, phandle_name);
+	if (!IS_ERR(pef2256)) {
+		*dr = pef2256;
+		devres_add(dev, dr);
+	} else {
+		devres_free(dr);
+	}
+
+	return pef2256;
+}
+EXPORT_SYMBOL(devm_pef2256_get_byphandle);
+
+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)
+{
+	unsigned long flags;
+	bool is_carrier_on;
+
+	spin_lock_irqsave(&pef2256->lock, flags);
+	is_carrier_on = pef2256->is_carrier_on;
+	spin_unlock_irqrestore(&pef2256->lock, flags);
+
+	return is_carrier_on;
+}
+EXPORT_SYMBOL_GPL(pef2256_get_carrier);
+
+MODULE_AUTHOR("Herve Codina <[email protected]>");
+MODULE_DESCRIPTION("PEF2256 driver");
+MODULE_LICENSE("GPL");
include/linux/pef2256.h new file +36 -0
new file mode 100644
index 000000000000..6c8d173595b1
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * PEF2256 management
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina <[email protected]>
+ */
+#ifndef __PEF2256_H__
+#define __PEF2256_H__
+
+#include <linux/types.h>
+
+struct pef2256;
+struct device_node;
+struct device;
+struct notifier_block;
+
+struct pef2256 *pef2256_get_byphandle(struct device_node *np, const char *phandle_name);
+void pef2256_put(struct pef2256 *pef2256);
+struct pef2256 *devm_pef2256_get_byphandle(struct device *dev, struct device_node *np,
+					   const char *phandle_name);
+
+
+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__ */
#17 lore raw

Re: [PATCH v2 2/7] drivers: misc: Add support for the Lantiq PEF2256 framer

Hi Christophe,

On Thu, 16 Mar 2023 14:00:42 +0000
Christophe Leroy <[email protected]> wrote:

[...]

Quoted 4 lines

drivers/misc/pef2256.c line 211

Quoted 2 lines
drivers/misc/pef2256.c new file +2 -0
+#define PEF2256_PC6	        0x86 /* Port Configuration 6 */
+#define PEF2256_GCM(_n)         (0x92 + _n - 1) /* Global Counter Mode n=1..8 */  

Should be (0x92 + (_n) - 1) to avoid any risk.

Yes definitively.
Will be updated in v3.

Quoted 2 lines
Quoted 2 lines

+#define PEF2256_GCM1 0x92 /* Global Counter Mode 1 */

[...]

Quoted 3 lines
Quoted 1 line

+#define PEF2256_GIS_ISR(_n) (1<<(n))

_n or n ?

Should be (1 << (_n))
Will be updated in v3.

Quoted 2 lines
Quoted 2 lines

+#define PEF2256_WID 0xEC /* Wafer Identification Register */

[...]

Quoted 11 lines

drivers/misc/pef2256.c line 317

Quoted 8 lines
drivers/misc/pef2256.c new file +8 -0
+static inline void pef2256_clrbits8(struct pef2256 *pef2256, int offset, u8 clr)
+{
+	u8 v;
+
+	v = pef2256_read8(pef2256, offset);
+	v &= ~clr;
+	pef2256_write8(pef2256, offset, v);
+}  

Not sure it is worth the number of lines.

Quoted 5 lines

Would liekly be as good with just:

	pef2256_write8(pef2256, offset, pef2256_read8(pef2256, offset) & ~clr);

Same for all.

Will be updated in v3.

Quoted 4 lines

Also, it shouldn't need to be flagged 'inline' as it is defined in the C file it is used. GCC will decide by itself if it is worth inlining.

In the kernel register accessor helpers are traditionally inline.

  # git grep 'static .* u32 .*read.*(' drivers/*.c | grep inline | wc -l
  432
  # git grep 'static .* u32 .*read.*(' drivers/*.c | grep -v inline | wc -l
  1
Sure, my git grep is not accurate but it gives ideas of the quantities.

I prefer to keep the inline for the register accessor helpers.

Quoted 63 lines
Quoted 49 lines
drivers/misc/pef2256.c new file +48 -0
+
+static inline void pef2256_setbits8(struct pef2256 *pef2256, int offset, u8 set)
+{
+	u8 v;
+
+	v = pef2256_read8(pef2256, offset);
+	v |= set;
+	pef2256_write8(pef2256, offset, v);
+}
+
+
+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;
+	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;
+			goto end;
+		}
+		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;
+			goto end;
+		case PEF2256_2X_WID_VERSION_22:
+			version_txt = "2.2 (2.x)";
+			version = PEF2256_VERSION_2_2;
+			goto end;

drivers/misc/pef2256.c line 375

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+		default:
+			break;
+		}
+		break;
+	case PEF2256_VSTR_VERSION_21:
+		version_txt = "2.1";
+		version = PEF2256_VERSION_2_1;
+		goto end;
+	default:
+		break;  

A default doing nothing is not needed unless the switch handles a enum and you have not covered all possible values.

Quoted 5 lines

My preference would be that you use the default to set:
version = PEF2256_VERSION_UNKNOWN;

then use an if (version == PEF2256_VERSION_UNKNOWN) / else below for the dev_err/dev_info.

The function will be reworked in v3

Quoted 88 lines
Quoted 88 lines
drivers/misc/pef2256.c new file +87 -0
+	}
+
+	dev_err(pef2256->dev, "Unknown version (0x%02x, 0x%02x)\n", vstr, wid);
+	return PEF2256_VERSION_UNKNOWN;
+
+end:
+	dev_info(pef2256->dev, "Version %s detected\n", version_txt);
+	return version;
+}
+
+static int pef2256_12_setup_gcm(struct pef2256 *pef2256)
+{
+	static const u8 gcm_1544000[6] = {0xF0, 0x51, 0x00, 0x80, 0x00, 0x15};
+	static const u8 gcm_2048000[6] = {0x00, 0x58, 0xD2, 0xC2, 0x00, 0x10};
+	static const u8 gcm_8192000[6] = {0x00, 0x58, 0xD2, 0xC2, 0x03, 0x10};
+	static const u8 gcm_10000000[6] = {0x90, 0x51, 0x81, 0x8F, 0x04, 0x10};
+	static const u8 gcm_12352000[6] = {0xF0, 0x51, 0x00, 0x80, 0x07, 0x15};
+	static const u8 gcm_16384000[6] = {0x00, 0x58, 0xD2, 0xC2, 0x07, 0x10};
+	unsigned long mclk_rate;
+	const u8 *gcm;
+	int i;
+
+	mclk_rate = clk_get_rate(pef2256->mclk);
+	switch (mclk_rate) {
+	case 1544000:
+		gcm = gcm_1544000;
+		break;
+	case 2048000:
+		gcm = gcm_2048000;
+		break;
+	case 8192000:
+		gcm = gcm_8192000;
+		break;
+	case 10000000:
+		gcm = gcm_10000000;
+		break;
+	case 12352000:
+		gcm = gcm_12352000;
+		break;
+	case 16384000:
+		gcm = gcm_16384000;
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported v1.2 MCLK rate %lu\n", mclk_rate);
+		return -EINVAL;
+	}
+	for (i = 0; i < 6; i++)
+		pef2256_write8(pef2256, PEF2256_GCM(i+1), gcm[i]);
+
+	return 0;
+}
+
+static int pef2256_2x_setup_gcm(struct pef2256 *pef2256)
+{
+	static const u8 gcm_1544000[8] = {0x00, 0x15, 0x00, 0x08, 0x00, 0x3F, 0x9C, 0xDF};
+	static const u8 gcm_2048000[8] = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x2F, 0xDB, 0xDF};
+	static const u8 gcm_8192000[8] = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x0B, 0xDB, 0xDF};
+	static const u8 gcm_10000000[8] = {0x40, 0x1B, 0x3D, 0x0A, 0x00, 0x07, 0xC9, 0xDC};
+	static const u8 gcm_12352000[8] = {0x00, 0x19, 0x00, 0x08, 0x01, 0x0A, 0x98, 0xDA};
+	static const u8 gcm_16384000[8] = {0x00, 0x18, 0xFB, 0x0B, 0x01, 0x0B, 0xDB, 0xDF};
+	unsigned long mclk_rate;
+	const u8 *gcm;
+	int i;
+
+	mclk_rate = clk_get_rate(pef2256->mclk);
+	switch (mclk_rate) {
+	case 1544000:
+		gcm = gcm_1544000;
+		break;
+	case 2048000:
+		gcm = gcm_2048000;
+		break;
+	case 8192000:
+		gcm = gcm_8192000;
+		break;
+	case 10000000:
+		gcm = gcm_10000000;
+		break;
+	case 12352000:
+		gcm = gcm_12352000;
+		break;
+	case 16384000:
+		gcm = gcm_16384000;
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported v2.x MCLK rate %lu\n", mclk_rate);
+		return -EINVAL;
Quoted 8 lines

drivers/misc/pef2256.c line 468

Quoted 6 lines
drivers/misc/pef2256.c new file +6 -0
+	}
+	for (i = 0; i < 8; i++)
+		pef2256_write8(pef2256, PEF2256_GCM(i+1), gcm[i]);
+
+	return 0;
+}  

This function and the previous one look very similar, can we merge them ?

Yes, will be merged in v3.

Quoted 128 lines
Quoted 128 lines
drivers/misc/pef2256.c new file +127 -0
+
+static int pef2256_setup_gcm(struct pef2256 *pef2256)
+{
+	return (pef2256->version == PEF2256_VERSION_1_2) ?
+		pef2256_12_setup_gcm(pef2256) : pef2256_2x_setup_gcm(pef2256);
+}
+
+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);
+		pef2256_write8(pef2256, PEF2256_XPM1, 0x03);
Quoted 8 lines

drivers/misc/pef2256.c line 601

Quoted 6 lines
drivers/misc/pef2256.c new file +6 -0
+		pef2256_write8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT | 0x00);
+	} else {
+		pef2256_write8(pef2256, PEF2256_XPM0, 0x9C);
+		pef2256_write8(pef2256, PEF2256_XPM1, 0x03);
+		pef2256_write8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT | 0x00);
+	}  

Only first line seem different, could XPM1 and XPM2 be outside the if/else ?

Sure.
Will be updated in v3.

Quoted 17 lines
Quoted 5 lines
drivers/misc/pef2256.c new file +4 -0
+
+	/* "master" mode */
+	if (!pef2256->is_subordinate)
+		pef2256_setbits8(pef2256, PEF2256_LIM0, PEF2256_LIM0_MAS);

drivers/misc/pef2256.c line 615

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+
+	/* transmit line in normal operation */
+	pef2256_clrbits8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT);
+
+	if (pef2256->version == PEF2256_VERSION_1_2) {
+		/* receive input threshold = 0,21V */
+		pef2256_clrsetbits8(pef2256, PEF2256_LIM1, PEF2256_12_LIM1_RIL_MASK,
+				    PEF2256_12_LIM1_RIL_210);
+	} else {
+		/* receive input threshold = 0,21V */  

Same comment twice, could be before the 'if' and remove the { } then ?

Will be updated in v3.

Quoted 10 lines

drivers/misc/pef2256.c line 621

Quoted 7 lines
drivers/misc/pef2256.c new file +6 -0
+		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);  

Wouldn't that fit in a single line with the new recommended 100 char max line length ? I thing it would be more readable as a single line.

Will be updated in v3 if it fits in 100 chars. Same for the line right below related to the receive part.

Quoted 17 lines
Quoted 17 lines
drivers/misc/pef2256.c new file +16 -0
+
+	/* 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 */
Quoted 8 lines

drivers/misc/pef2256.c line 642

Quoted 5 lines
drivers/misc/pef2256.c new file +5 -0
+		pef2256_clrsetbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_RS_MASK,
+				    PEF2256_CMR1_RS_DCOR_2048);
+		/* disable switching from RCLK to SYNC */
+		pef2256_setbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_DCS);
+	}  

I'd move the comments into a single one before the 'if', the two comments are related.

I will change to a single line comment but not before the 'if'. The comment is related to the subordinate case and not global for 'all' cases.

Quoted 8 lines

drivers/misc/pef2256.c line 647

Quoted 6 lines
drivers/misc/pef2256.c new file +5 -0
+
+	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);
+	}  

I'd put the comment before the 'if' and remove the { }

Same reason to keep as it.
The comment is specific to the if content.

Quoted 6 lines

drivers/misc/pef2256.c line 650

Quoted 4 lines
drivers/misc/pef2256.c new file +3 -0
+
+	if (!pef2256->is_tx_falling_edge) {
+		/* rising edge sync pulse transmit */  

This comment doesn't seem to match the condition (rising versus falling).

if not falling, it is rising.

I will update in v3 to invert the condition and improve the comment by mentioning transmit and receive in each cases.

Quoted 70 lines

drivers/misc/pef2256.c line 654

Quoted 5 lines
drivers/misc/pef2256.c new file +4 -0
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC3,
+				    PEF2256_SIC3_RESR, PEF2256_SIC3_RESX);
+	} else {
+		/* rising edge sync pulse receive */  

This comment doesn't seem to match the condition (receive versus tx).

Quoted 62 lines
drivers/misc/pef2256.c new file +62 -0
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC3,
+				    PEF2256_SIC3_RESX, PEF2256_SIC3_RESR);
+	}
+
+	/* 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 %u\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));
+
+	if (pef2256->is_subordinate) {
+		/* transmit buffer size = 2 frames */
Quoted 8 lines

drivers/misc/pef2256.c line 721

Quoted 5 lines
drivers/misc/pef2256.c new file +5 -0
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_XBS_MASK,
+				    PEF2256_SIC1_XBS_2FRAMES);
+		/* transmit transparent mode */
+		pef2256_setbits8(pef2256, PEF2256_XSW, PEF2256_XSW_XTM);
+	}  

Could this block get regrouped with the RX block depending on is_subordinate ?

Yes,
Will be done in v3.

Quoted 39 lines
Quoted 26 lines
drivers/misc/pef2256.c new file +25 -0
+
+	/* 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;

drivers/misc/pef2256.c line 756

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+}
+
+static int pef2256_setup(struct pef2256 *pef2256)
+{
+	if (!pef2256->is_e1) {
+		dev_err(pef2256->dev, "Only E1 line is currently supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	return pef2256_setup_e1(pef2256);  

In order to use future addition of other modes, I'd do:

Quoted 6 lines
	if (!pef2256->is_e1)
		return pef2256_setup_e1(pef2256);

	dev_err(pef2256->dev, "Only E1 line is currently supported\n");
	return -EOPNOTSUPP;

Will be changed in v3 using your proposition (with 'if' condition fixed).

Quoted 27 lines
Quoted 27 lines
drivers/misc/pef2256.c new file +27 -0
+}
+
+
+
+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 is_changed = false;
+	unsigned long flags;
+	bool is_carrier_on;
+
+	if (isr & (PEF2256_INT2_LOS | PEF2256_INT2_AIS)) {
+
+		spin_lock_irqsave(&pef2256->lock, flags);
+		is_carrier_on = pef2256_is_carrier_on(pef2256);
Quoted 8 lines

drivers/misc/pef2256.c line 788

Quoted 5 lines
drivers/misc/pef2256.c new file +5 -0
+		if (is_carrier_on != pef2256->is_carrier_on) {
+			pef2256->is_carrier_on = is_carrier_on;
+			is_changed = true;
+		}
+		spin_unlock_irqrestore(&pef2256->lock, flags);  

Do we really need spin_locks for that ?
If atomicity is really an issue, may we use atomic operations instead ?

Indeed, I can use atomic ops here.
Will be changed in v3.

Quoted 8 lines

drivers/misc/pef2256.c line 795

Quoted 8 lines
drivers/misc/pef2256.c new file +7 -0
+
+		if (is_changed)
+			atomic_notifier_call_chain(&pef2256->event_notifier_list,
+						   PEF2256_EVENT_CARRIER, NULL);
+	}
+}
+

Thanks for the review.

Regards,
Hervé

Signature · 3 lines
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
#18 lore raw

Re: [PATCH v2 2/7] drivers: misc: Add support for the Lantiq PEF2256 framer

In reply to Christophe Leroy

Hi Christophe,

On Thu, 16 Mar 2023 14:00:42 +0000
Christophe Leroy <[email protected]> wrote:

[...]

Quoted 4 lines

drivers/misc/pef2256.c line 211

Quoted 2 lines
drivers/misc/pef2256.c new file +2 -0
+#define PEF2256_PC6	        0x86 /* Port Configuration 6 */
+#define PEF2256_GCM(_n)         (0x92 + _n - 1) /* Global Counter Mode n=1..8 */  

Should be (0x92 + (_n) - 1) to avoid any risk.

Yes definitively.
Will be updated in v3.

Quoted 2 lines
Quoted 2 lines

+#define PEF2256_GCM1 0x92 /* Global Counter Mode 1 */

[...]

Quoted 3 lines
Quoted 1 line

+#define PEF2256_GIS_ISR(_n) (1<<(n))

_n or n ?

Should be (1 << (_n))
Will be updated in v3.

Quoted 2 lines
Quoted 2 lines

+#define PEF2256_WID 0xEC /* Wafer Identification Register */

[...]

Quoted 11 lines

drivers/misc/pef2256.c line 317

Quoted 8 lines
drivers/misc/pef2256.c new file +8 -0
+static inline void pef2256_clrbits8(struct pef2256 *pef2256, int offset, u8 clr)
+{
+	u8 v;
+
+	v = pef2256_read8(pef2256, offset);
+	v &= ~clr;
+	pef2256_write8(pef2256, offset, v);
+}  

Not sure it is worth the number of lines.

Quoted 5 lines

Would liekly be as good with just:

	pef2256_write8(pef2256, offset, pef2256_read8(pef2256, offset) & ~clr);

Same for all.

Will be updated in v3.

Quoted 4 lines

Also, it shouldn't need to be flagged 'inline' as it is defined in the C file it is used. GCC will decide by itself if it is worth inlining.

In the kernel register accessor helpers are traditionally inline.

  # git grep 'static .* u32 .*read.*(' drivers/*.c | grep inline | wc -l
  432
  # git grep 'static .* u32 .*read.*(' drivers/*.c | grep -v inline | wc -l
  1
Sure, my git grep is not accurate but it gives ideas of the quantities.

I prefer to keep the inline for the register accessor helpers.

Quoted 63 lines
Quoted 49 lines
drivers/misc/pef2256.c new file +48 -0
+
+static inline void pef2256_setbits8(struct pef2256 *pef2256, int offset, u8 set)
+{
+	u8 v;
+
+	v = pef2256_read8(pef2256, offset);
+	v |= set;
+	pef2256_write8(pef2256, offset, v);
+}
+
+
+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;
+	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;
+			goto end;
+		}
+		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;
+			goto end;
+		case PEF2256_2X_WID_VERSION_22:
+			version_txt = "2.2 (2.x)";
+			version = PEF2256_VERSION_2_2;
+			goto end;

drivers/misc/pef2256.c line 375

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+		default:
+			break;
+		}
+		break;
+	case PEF2256_VSTR_VERSION_21:
+		version_txt = "2.1";
+		version = PEF2256_VERSION_2_1;
+		goto end;
+	default:
+		break;  

A default doing nothing is not needed unless the switch handles a enum and you have not covered all possible values.

Quoted 5 lines

My preference would be that you use the default to set:
version = PEF2256_VERSION_UNKNOWN;

then use an if (version == PEF2256_VERSION_UNKNOWN) / else below for the dev_err/dev_info.

The function will be reworked in v3

Quoted 88 lines
Quoted 88 lines
drivers/misc/pef2256.c new file +87 -0
+	}
+
+	dev_err(pef2256->dev, "Unknown version (0x%02x, 0x%02x)\n", vstr, wid);
+	return PEF2256_VERSION_UNKNOWN;
+
+end:
+	dev_info(pef2256->dev, "Version %s detected\n", version_txt);
+	return version;
+}
+
+static int pef2256_12_setup_gcm(struct pef2256 *pef2256)
+{
+	static const u8 gcm_1544000[6] = {0xF0, 0x51, 0x00, 0x80, 0x00, 0x15};
+	static const u8 gcm_2048000[6] = {0x00, 0x58, 0xD2, 0xC2, 0x00, 0x10};
+	static const u8 gcm_8192000[6] = {0x00, 0x58, 0xD2, 0xC2, 0x03, 0x10};
+	static const u8 gcm_10000000[6] = {0x90, 0x51, 0x81, 0x8F, 0x04, 0x10};
+	static const u8 gcm_12352000[6] = {0xF0, 0x51, 0x00, 0x80, 0x07, 0x15};
+	static const u8 gcm_16384000[6] = {0x00, 0x58, 0xD2, 0xC2, 0x07, 0x10};
+	unsigned long mclk_rate;
+	const u8 *gcm;
+	int i;
+
+	mclk_rate = clk_get_rate(pef2256->mclk);
+	switch (mclk_rate) {
+	case 1544000:
+		gcm = gcm_1544000;
+		break;
+	case 2048000:
+		gcm = gcm_2048000;
+		break;
+	case 8192000:
+		gcm = gcm_8192000;
+		break;
+	case 10000000:
+		gcm = gcm_10000000;
+		break;
+	case 12352000:
+		gcm = gcm_12352000;
+		break;
+	case 16384000:
+		gcm = gcm_16384000;
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported v1.2 MCLK rate %lu\n", mclk_rate);
+		return -EINVAL;
+	}
+	for (i = 0; i < 6; i++)
+		pef2256_write8(pef2256, PEF2256_GCM(i+1), gcm[i]);
+
+	return 0;
+}
+
+static int pef2256_2x_setup_gcm(struct pef2256 *pef2256)
+{
+	static const u8 gcm_1544000[8] = {0x00, 0x15, 0x00, 0x08, 0x00, 0x3F, 0x9C, 0xDF};
+	static const u8 gcm_2048000[8] = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x2F, 0xDB, 0xDF};
+	static const u8 gcm_8192000[8] = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x0B, 0xDB, 0xDF};
+	static const u8 gcm_10000000[8] = {0x40, 0x1B, 0x3D, 0x0A, 0x00, 0x07, 0xC9, 0xDC};
+	static const u8 gcm_12352000[8] = {0x00, 0x19, 0x00, 0x08, 0x01, 0x0A, 0x98, 0xDA};
+	static const u8 gcm_16384000[8] = {0x00, 0x18, 0xFB, 0x0B, 0x01, 0x0B, 0xDB, 0xDF};
+	unsigned long mclk_rate;
+	const u8 *gcm;
+	int i;
+
+	mclk_rate = clk_get_rate(pef2256->mclk);
+	switch (mclk_rate) {
+	case 1544000:
+		gcm = gcm_1544000;
+		break;
+	case 2048000:
+		gcm = gcm_2048000;
+		break;
+	case 8192000:
+		gcm = gcm_8192000;
+		break;
+	case 10000000:
+		gcm = gcm_10000000;
+		break;
+	case 12352000:
+		gcm = gcm_12352000;
+		break;
+	case 16384000:
+		gcm = gcm_16384000;
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported v2.x MCLK rate %lu\n", mclk_rate);
+		return -EINVAL;
Quoted 8 lines

drivers/misc/pef2256.c line 468

Quoted 6 lines
drivers/misc/pef2256.c new file +6 -0
+	}
+	for (i = 0; i < 8; i++)
+		pef2256_write8(pef2256, PEF2256_GCM(i+1), gcm[i]);
+
+	return 0;
+}  

This function and the previous one look very similar, can we merge them ?

Yes, will be merged in v3.

Quoted 128 lines
Quoted 128 lines
drivers/misc/pef2256.c new file +127 -0
+
+static int pef2256_setup_gcm(struct pef2256 *pef2256)
+{
+	return (pef2256->version == PEF2256_VERSION_1_2) ?
+		pef2256_12_setup_gcm(pef2256) : pef2256_2x_setup_gcm(pef2256);
+}
+
+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);
+		pef2256_write8(pef2256, PEF2256_XPM1, 0x03);
Quoted 8 lines

drivers/misc/pef2256.c line 601

Quoted 6 lines
drivers/misc/pef2256.c new file +6 -0
+		pef2256_write8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT | 0x00);
+	} else {
+		pef2256_write8(pef2256, PEF2256_XPM0, 0x9C);
+		pef2256_write8(pef2256, PEF2256_XPM1, 0x03);
+		pef2256_write8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT | 0x00);
+	}  

Only first line seem different, could XPM1 and XPM2 be outside the if/else ?

Sure.
Will be updated in v3.

Quoted 17 lines
Quoted 5 lines
drivers/misc/pef2256.c new file +4 -0
+
+	/* "master" mode */
+	if (!pef2256->is_subordinate)
+		pef2256_setbits8(pef2256, PEF2256_LIM0, PEF2256_LIM0_MAS);

drivers/misc/pef2256.c line 615

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+
+	/* transmit line in normal operation */
+	pef2256_clrbits8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT);
+
+	if (pef2256->version == PEF2256_VERSION_1_2) {
+		/* receive input threshold = 0,21V */
+		pef2256_clrsetbits8(pef2256, PEF2256_LIM1, PEF2256_12_LIM1_RIL_MASK,
+				    PEF2256_12_LIM1_RIL_210);
+	} else {
+		/* receive input threshold = 0,21V */  

Same comment twice, could be before the 'if' and remove the { } then ?

Will be updated in v3.

Quoted 10 lines

drivers/misc/pef2256.c line 621

Quoted 7 lines
drivers/misc/pef2256.c new file +6 -0
+		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);  

Wouldn't that fit in a single line with the new recommended 100 char max line length ? I thing it would be more readable as a single line.

Will be updated in v3 if it fits in 100 chars. Same for the line right below related to the receive part.

Quoted 17 lines
Quoted 17 lines
drivers/misc/pef2256.c new file +16 -0
+
+	/* 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 */
Quoted 8 lines

drivers/misc/pef2256.c line 642

Quoted 5 lines
drivers/misc/pef2256.c new file +5 -0
+		pef2256_clrsetbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_RS_MASK,
+				    PEF2256_CMR1_RS_DCOR_2048);
+		/* disable switching from RCLK to SYNC */
+		pef2256_setbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_DCS);
+	}  

I'd move the comments into a single one before the 'if', the two comments are related.

I will change to a single line comment but not before the 'if'. The comment is related to the subordinate case and not global for 'all' cases.

Quoted 8 lines

drivers/misc/pef2256.c line 647

Quoted 6 lines
drivers/misc/pef2256.c new file +5 -0
+
+	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);
+	}  

I'd put the comment before the 'if' and remove the { }

Same reason to keep as it.
The comment is specific to the if content.

Quoted 6 lines

drivers/misc/pef2256.c line 650

Quoted 4 lines
drivers/misc/pef2256.c new file +3 -0
+
+	if (!pef2256->is_tx_falling_edge) {
+		/* rising edge sync pulse transmit */  

This comment doesn't seem to match the condition (rising versus falling).

if not falling, it is rising.

I will update in v3 to invert the condition and improve the comment by mentioning transmit and receive in each cases.

Quoted 70 lines

drivers/misc/pef2256.c line 654

Quoted 5 lines
drivers/misc/pef2256.c new file +4 -0
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC3,
+				    PEF2256_SIC3_RESR, PEF2256_SIC3_RESX);
+	} else {
+		/* rising edge sync pulse receive */  

This comment doesn't seem to match the condition (receive versus tx).

Quoted 62 lines
drivers/misc/pef2256.c new file +62 -0
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC3,
+				    PEF2256_SIC3_RESX, PEF2256_SIC3_RESR);
+	}
+
+	/* 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 %u\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));
+
+	if (pef2256->is_subordinate) {
+		/* transmit buffer size = 2 frames */
Quoted 8 lines

drivers/misc/pef2256.c line 721

Quoted 5 lines
drivers/misc/pef2256.c new file +5 -0
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_XBS_MASK,
+				    PEF2256_SIC1_XBS_2FRAMES);
+		/* transmit transparent mode */
+		pef2256_setbits8(pef2256, PEF2256_XSW, PEF2256_XSW_XTM);
+	}  

Could this block get regrouped with the RX block depending on is_subordinate ?

Yes,
Will be done in v3.

Quoted 39 lines
Quoted 26 lines
drivers/misc/pef2256.c new file +25 -0
+
+	/* 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;

drivers/misc/pef2256.c line 756

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+}
+
+static int pef2256_setup(struct pef2256 *pef2256)
+{
+	if (!pef2256->is_e1) {
+		dev_err(pef2256->dev, "Only E1 line is currently supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	return pef2256_setup_e1(pef2256);  

In order to use future addition of other modes, I'd do:

Quoted 6 lines
	if (!pef2256->is_e1)
		return pef2256_setup_e1(pef2256);

	dev_err(pef2256->dev, "Only E1 line is currently supported\n");
	return -EOPNOTSUPP;

Will be changed in v3 using your proposition (with 'if' condition fixed).

Quoted 27 lines
Quoted 27 lines
drivers/misc/pef2256.c new file +27 -0
+}
+
+
+
+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 is_changed = false;
+	unsigned long flags;
+	bool is_carrier_on;
+
+	if (isr & (PEF2256_INT2_LOS | PEF2256_INT2_AIS)) {
+
+		spin_lock_irqsave(&pef2256->lock, flags);
+		is_carrier_on = pef2256_is_carrier_on(pef2256);
Quoted 8 lines

drivers/misc/pef2256.c line 788

Quoted 5 lines
drivers/misc/pef2256.c new file +5 -0
+		if (is_carrier_on != pef2256->is_carrier_on) {
+			pef2256->is_carrier_on = is_carrier_on;
+			is_changed = true;
+		}
+		spin_unlock_irqrestore(&pef2256->lock, flags);  

Do we really need spin_locks for that ?
If atomicity is really an issue, may we use atomic operations instead ?

Indeed, I can use atomic ops here.
Will be changed in v3.

Quoted 8 lines

drivers/misc/pef2256.c line 795

Quoted 8 lines
drivers/misc/pef2256.c new file +7 -0
+
+		if (is_changed)
+			atomic_notifier_call_chain(&pef2256->event_notifier_list,
+						   PEF2256_EVENT_CARRIER, NULL);
+	}
+}
+

Thanks for the review.

Regards,
Hervé

Signature · 3 lines
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
#19 lore raw

Re: [PATCH v2 2/7] drivers: misc: Add support for the Lantiq PEF2256 framer

In reply to Herve Codina

Le 16/03/2023 à 13:27, Herve Codina a écrit :

Quoted 261 lines

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.

---
  drivers/misc/Kconfig    |   17 +
  drivers/misc/Makefile   |    1 +
  drivers/misc/pef2256.c  | 1441 +++++++++++++++++++++++++++++++++++++++
  include/linux/pef2256.h |   36 +
  4 files changed, 1495 insertions(+)

create mode 100644 drivers/misc/pef2256.c
create mode 100644 include/linux/pef2256.h

drivers/misc/Kconfig +17 -0
index 433aa4197785..f03739163c53 100644
@@ -376,6 +376,23 @@ config HMC6352
  	  This driver provides support for the Honeywell HMC6352 compass,
  	  providing configuration and heading data via sysfs.
 
+config PEF2256
+	tristate "Lantiq PEF2256 (FALC56) framer"
+	depends on HAS_IOMEM
+	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 DS1682
  	tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
  	depends on I2C
drivers/misc/Makefile +1 -0
index 56de43943cd5..a26f044ab9dd 100644
@@ -35,6 +35,7 @@ obj-$(CONFIG_SENSORS_TSL2550)	+= tsl2550.o
  obj-$(CONFIG_DS1682)		+= ds1682.o
  obj-$(CONFIG_C2PORT)		+= c2port/
  obj-$(CONFIG_HMC6352)		+= hmc6352.o
+obj-$(CONFIG_PEF2256)		+= pef2256.o
  obj-y				+= eeprom/
  obj-y				+= cb710/
  obj-$(CONFIG_VMWARE_BALLOON)	+= vmw_balloon.o
drivers/misc/pef2256.c new file +201 -0
new file mode 100644
index 000000000000..b21586084408
@@ -0,0 +1,1441 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PEF2256 also known as FALC56 driver
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina <[email protected]>
+ */
+
+#include <linux/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)

drivers/misc/pef2256.c line 211

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -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 */

Should be (0x92 + (_n) - 1) to avoid any risk.

Quoted 15 lines
drivers/misc/pef2256.c new file +15 -0
+#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)

drivers/misc/pef2256.c line 236

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+#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))

_n or n ?

Quoted 71 lines
drivers/misc/pef2256.c new file +71 -0
+#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;
+	spinlock_t lock;
+	struct clk *mclk;
+	struct gpio_desc *reset_gpio;
+	struct {
+		struct pinctrl_desc pctrl_desc;
+		const struct pef2256_function_desc *functions;
+		unsigned int nfunctions;
+	} pinctrl;
+	bool is_e1;
+	u32 sysclk_rate;
+	u32 data_rate;
+	bool is_tx_falling_edge;
+	bool is_subordinate;
+	enum pef2256_frame_type frame_type;
+	u8 channel_phase;
+	bool is_carrier_on;
+	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);

drivers/misc/pef2256.c line 317

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+}
+
+static inline void pef2256_clrbits8(struct pef2256 *pef2256, int offset, u8 clr)
+{
+	u8 v;
+
+	v = pef2256_read8(pef2256, offset);
+	v &= ~clr;
+	pef2256_write8(pef2256, offset, v);
+}

Not sure it is worth the number of lines.

Would liekly be as good with just:

	pef2256_write8(pef2256, offset, pef2256_read8(pef2256, offset) & ~clr);

Same for all.

Also, it shouldn't need to be flagged 'inline' as it is defined in the C file it is used. GCC will decide by itself if it is worth inlining.

Quoted 48 lines
drivers/misc/pef2256.c new file +48 -0
+
+static inline void pef2256_setbits8(struct pef2256 *pef2256, int offset, u8 set)
+{
+	u8 v;
+
+	v = pef2256_read8(pef2256, offset);
+	v |= set;
+	pef2256_write8(pef2256, offset, v);
+}
+
+
+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;
+	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;
+			goto end;
+		}
+		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;
+			goto end;
+		case PEF2256_2X_WID_VERSION_22:
+			version_txt = "2.2 (2.x)";
+			version = PEF2256_VERSION_2_2;
+			goto end;

drivers/misc/pef2256.c line 375

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+		default:
+			break;
+		}
+		break;
+	case PEF2256_VSTR_VERSION_21:
+		version_txt = "2.1";
+		version = PEF2256_VERSION_2_1;
+		goto end;
+	default:
+		break;

A default doing nothing is not needed unless the switch handles a enum and you have not covered all possible values.

My preference would be that you use the default to set:
version = PEF2256_VERSION_UNKNOWN;

then use an if (version == PEF2256_VERSION_UNKNOWN) / else below for the dev_err/dev_info.

Quoted 83 lines
drivers/misc/pef2256.c new file +83 -0
+	}
+
+	dev_err(pef2256->dev, "Unknown version (0x%02x, 0x%02x)\n", vstr, wid);
+	return PEF2256_VERSION_UNKNOWN;
+
+end:
+	dev_info(pef2256->dev, "Version %s detected\n", version_txt);
+	return version;
+}
+
+static int pef2256_12_setup_gcm(struct pef2256 *pef2256)
+{
+	static const u8 gcm_1544000[6] = {0xF0, 0x51, 0x00, 0x80, 0x00, 0x15};
+	static const u8 gcm_2048000[6] = {0x00, 0x58, 0xD2, 0xC2, 0x00, 0x10};
+	static const u8 gcm_8192000[6] = {0x00, 0x58, 0xD2, 0xC2, 0x03, 0x10};
+	static const u8 gcm_10000000[6] = {0x90, 0x51, 0x81, 0x8F, 0x04, 0x10};
+	static const u8 gcm_12352000[6] = {0xF0, 0x51, 0x00, 0x80, 0x07, 0x15};
+	static const u8 gcm_16384000[6] = {0x00, 0x58, 0xD2, 0xC2, 0x07, 0x10};
+	unsigned long mclk_rate;
+	const u8 *gcm;
+	int i;
+
+	mclk_rate = clk_get_rate(pef2256->mclk);
+	switch (mclk_rate) {
+	case 1544000:
+		gcm = gcm_1544000;
+		break;
+	case 2048000:
+		gcm = gcm_2048000;
+		break;
+	case 8192000:
+		gcm = gcm_8192000;
+		break;
+	case 10000000:
+		gcm = gcm_10000000;
+		break;
+	case 12352000:
+		gcm = gcm_12352000;
+		break;
+	case 16384000:
+		gcm = gcm_16384000;
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported v1.2 MCLK rate %lu\n", mclk_rate);
+		return -EINVAL;
+	}
+	for (i = 0; i < 6; i++)
+		pef2256_write8(pef2256, PEF2256_GCM(i+1), gcm[i]);
+
+	return 0;
+}
+
+static int pef2256_2x_setup_gcm(struct pef2256 *pef2256)
+{
+	static const u8 gcm_1544000[8] = {0x00, 0x15, 0x00, 0x08, 0x00, 0x3F, 0x9C, 0xDF};
+	static const u8 gcm_2048000[8] = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x2F, 0xDB, 0xDF};
+	static const u8 gcm_8192000[8] = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x0B, 0xDB, 0xDF};
+	static const u8 gcm_10000000[8] = {0x40, 0x1B, 0x3D, 0x0A, 0x00, 0x07, 0xC9, 0xDC};
+	static const u8 gcm_12352000[8] = {0x00, 0x19, 0x00, 0x08, 0x01, 0x0A, 0x98, 0xDA};
+	static const u8 gcm_16384000[8] = {0x00, 0x18, 0xFB, 0x0B, 0x01, 0x0B, 0xDB, 0xDF};
+	unsigned long mclk_rate;
+	const u8 *gcm;
+	int i;
+
+	mclk_rate = clk_get_rate(pef2256->mclk);
+	switch (mclk_rate) {
+	case 1544000:
+		gcm = gcm_1544000;
+		break;
+	case 2048000:
+		gcm = gcm_2048000;
+		break;
+	case 8192000:
+		gcm = gcm_8192000;
+		break;
+	case 10000000:
+		gcm = gcm_10000000;
+		break;
+	case 12352000:
+		gcm = gcm_12352000;
+		break;
+	case 16384000:
+		gcm = gcm_16384000;

drivers/misc/pef2256.c line 468

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+		break;
+	default:
+		dev_err(pef2256->dev, "Unsupported v2.x MCLK rate %lu\n", mclk_rate);
+		return -EINVAL;
+	}
+	for (i = 0; i < 8; i++)
+		pef2256_write8(pef2256, PEF2256_GCM(i+1), gcm[i]);
+
+	return 0;
+}

This function and the previous one look very similar, can we merge them ?

Quoted 123 lines
drivers/misc/pef2256.c new file +123 -0
+
+static int pef2256_setup_gcm(struct pef2256 *pef2256)
+{
+	return (pef2256->version == PEF2256_VERSION_1_2) ?
+		pef2256_12_setup_gcm(pef2256) : pef2256_2x_setup_gcm(pef2256);
+}
+
+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

drivers/misc/pef2256.c line 601

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+	 */
+	if (pef2256->version == PEF2256_VERSION_1_2) {
+		pef2256_write8(pef2256, PEF2256_XPM0, 0x7B);
+		pef2256_write8(pef2256, PEF2256_XPM1, 0x03);
+		pef2256_write8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT | 0x00);
+	} else {
+		pef2256_write8(pef2256, PEF2256_XPM0, 0x9C);
+		pef2256_write8(pef2256, PEF2256_XPM1, 0x03);
+		pef2256_write8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT | 0x00);
+	}

Only first line seem different, could XPM1 and XPM2 be outside the if/else ?

Quoted 4 lines
drivers/misc/pef2256.c new file +4 -0
+
+	/* "master" mode */
+	if (!pef2256->is_subordinate)
+		pef2256_setbits8(pef2256, PEF2256_LIM0, PEF2256_LIM0_MAS);

drivers/misc/pef2256.c line 615

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+
+	/* transmit line in normal operation */
+	pef2256_clrbits8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT);
+
+	if (pef2256->version == PEF2256_VERSION_1_2) {
+		/* receive input threshold = 0,21V */
+		pef2256_clrsetbits8(pef2256, PEF2256_LIM1, PEF2256_12_LIM1_RIL_MASK,
+				    PEF2256_12_LIM1_RIL_210);
+	} else {
+		/* receive input threshold = 0,21V */

Same comment twice, could be before the 'if' and remove the { } then ?

drivers/misc/pef2256.c line 621

Quoted 6 lines
drivers/misc/pef2256.c new file +6 -0
+		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);

Wouldn't that fit in a single line with the new recommended 100 char max line length ? I thing it would be more readable as a single line.

Quoted 11 lines
drivers/misc/pef2256.c new file +11 -0
+
+	/* 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);
+

drivers/misc/pef2256.c line 642

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+	/* DCO-X center frequency enabled */
+	pef2256_setbits8(pef2256, PEF2256_CMR2, PEF2256_CMR2_DCOXC);
+
+	if (pef2256->is_subordinate) {
+		/* select RCLK source = 2M */
+		pef2256_clrsetbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_RS_MASK,
+				    PEF2256_CMR1_RS_DCOR_2048);
+		/* disable switching from RCLK to SYNC */
+		pef2256_setbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_DCS);
+	}

I'd move the comments into a single one before the 'if', the two comments are related.

drivers/misc/pef2256.c line 647

Quoted 5 lines
drivers/misc/pef2256.c new file +5 -0
+
+	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);
+	}

I'd put the comment before the 'if' and remove the { }

drivers/misc/pef2256.c line 650

Quoted 3 lines
drivers/misc/pef2256.c new file +3 -0
+
+	if (!pef2256->is_tx_falling_edge) {
+		/* rising edge sync pulse transmit */

This comment doesn't seem to match the condition (rising versus falling).

drivers/misc/pef2256.c line 654

Quoted 4 lines
drivers/misc/pef2256.c new file +4 -0
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC3,
+				    PEF2256_SIC3_RESR, PEF2256_SIC3_RESX);
+	} else {
+		/* rising edge sync pulse receive */

This comment doesn't seem to match the condition (receive versus tx).

Quoted 57 lines
drivers/misc/pef2256.c new file +57 -0
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC3,
+				    PEF2256_SIC3_RESX, PEF2256_SIC3_RESR);
+	}
+
+	/* 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 %u\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 */

drivers/misc/pef2256.c line 721

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+	pef2256_clrsetbits8(pef2256, PEF2256_SIC2, PEF2256_SIC2_SICS_MASK,
+			    PEF2256_SIC2_SICS(pef2256->channel_phase));
+
+	if (pef2256->is_subordinate) {
+		/* transmit buffer size = 2 frames */
+		pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_XBS_MASK,
+				    PEF2256_SIC1_XBS_2FRAMES);
+		/* transmit transparent mode */
+		pef2256_setbits8(pef2256, PEF2256_XSW, PEF2256_XSW_XTM);
+	}

Could this block get regrouped with the RX block depending on is_subordinate ?

Quoted 25 lines
drivers/misc/pef2256.c new file +25 -0
+
+	/* 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;

drivers/misc/pef2256.c line 756

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+}
+
+static int pef2256_setup(struct pef2256 *pef2256)
+{
+	if (!pef2256->is_e1) {
+		dev_err(pef2256->dev, "Only E1 line is currently supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	return pef2256_setup_e1(pef2256);

In order to use future addition of other modes, I'd do:

	if (!pef2256->is_e1)
		return pef2256_setup_e1(pef2256);

	dev_err(pef2256->dev, "Only E1 line is currently supported\n");
	return -EOPNOTSUPP;
Quoted 22 lines
drivers/misc/pef2256.c new file +22 -0
+}
+
+
+
+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 is_changed = false;
+	unsigned long flags;
+	bool is_carrier_on;

drivers/misc/pef2256.c line 788

Quoted 10 lines
drivers/misc/pef2256.c new file +10 -0
+
+	if (isr & (PEF2256_INT2_LOS | PEF2256_INT2_AIS)) {
+
+		spin_lock_irqsave(&pef2256->lock, flags);
+		is_carrier_on = pef2256_is_carrier_on(pef2256);
+		if (is_carrier_on != pef2256->is_carrier_on) {
+			pef2256->is_carrier_on = is_carrier_on;
+			is_changed = true;
+		}
+		spin_unlock_irqrestore(&pef2256->lock, flags);

Do we really need spin_locks for that ?
If atomicity is really an issue, may we use atomic operations instead ?

Quoted 695 lines
drivers/misc/pef2256.c new file +653 -0
+
+		if (is_changed)
+			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->sysclk_rate = 2048000;
+	ret = of_property_read_u32(np, "lantiq,sysclk-rate-hz", &pef2256->sysclk_rate);
+	if (ret && ret != -EINVAL) {
+		dev_err(pef2256->dev, "%pOF: failed to read lantiq,sysclk-rate-hz\n", np);
+		return ret;
+	}
+	dev_dbg(pef2256->dev, "config: sysclk %u Hz\n", pef2256->sysclk_rate);
+
+	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;
+	struct pef2256 *pef2256;
+	int ret;
+	int irq;
+
+	pef2256 = devm_kzalloc(&pdev->dev, sizeof(*pef2256), GFP_KERNEL);
+	if (!pef2256)
+		return -ENOMEM;
+
+	pef2256->dev = &pdev->dev;
+	spin_lock_init(&pef2256->lock);
+	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));
+
+	/* 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.
+	 */
+	pef2256->is_carrier_on = false;
+
+	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;
+	}
+
+	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);
+
+struct pef2256 *pef2256_get_byphandle(struct device_node *np, const char *phandle_name)
+{
+	struct device_node *pef2256_np;
+	struct platform_device *pdev;
+	struct pef2256 *pef2256;
+
+	pef2256_np = of_parse_phandle(np, phandle_name, 0);
+	if (!pef2256_np)
+		return ERR_PTR(-EINVAL);
+
+	if (!of_match_node(pef2256_driver.driver.of_match_table, pef2256_np)) {
+		of_node_put(pef2256_np);
+		return ERR_PTR(-EINVAL);
+	}
+
+	pdev = of_find_device_by_node(pef2256_np);
+	of_node_put(pef2256_np);
+	if (!pdev)
+		return ERR_PTR(-ENODEV);
+
+	pef2256 = platform_get_drvdata(pdev);
+	if (!pef2256) {
+		platform_device_put(pdev);
+		return ERR_PTR(-EPROBE_DEFER);
+	}
+
+	return pef2256;
+}
+EXPORT_SYMBOL(pef2256_get_byphandle);
+
+void pef2256_put(struct pef2256 *pef2256)
+{
+	put_device(pef2256->dev);
+}
+EXPORT_SYMBOL(pef2256_put);
+
+static void devm_pef2256_release(struct device *dev, void *res)
+{
+	struct pef2256 **pef2256 = res;
+
+	pef2256_put(*pef2256);
+}
+
+struct pef2256 *devm_pef2256_get_byphandle(struct device *dev, struct device_node *np,
+					   const char *phandle_name)
+{
+	struct pef2256 *pef2256;
+	struct pef2256 **dr;
+
+	dr = devres_alloc(devm_pef2256_release, sizeof(*dr), GFP_KERNEL);
+	if (!dr)
+		return ERR_PTR(-ENOMEM);
+
+	pef2256 = pef2256_get_byphandle(np, phandle_name);
+	if (!IS_ERR(pef2256)) {
+		*dr = pef2256;
+		devres_add(dev, dr);
+	} else {
+		devres_free(dr);
+	}
+
+	return pef2256;
+}
+EXPORT_SYMBOL(devm_pef2256_get_byphandle);
+
+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)
+{
+	unsigned long flags;
+	bool is_carrier_on;
+
+	spin_lock_irqsave(&pef2256->lock, flags);
+	is_carrier_on = pef2256->is_carrier_on;
+	spin_unlock_irqrestore(&pef2256->lock, flags);
+
+	return is_carrier_on;
+}
+EXPORT_SYMBOL_GPL(pef2256_get_carrier);
+
+MODULE_AUTHOR("Herve Codina <[email protected]>");
+MODULE_DESCRIPTION("PEF2256 driver");
+MODULE_LICENSE("GPL");
include/linux/pef2256.h new file +36 -0
new file mode 100644
index 000000000000..6c8d173595b1
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * PEF2256 management
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina <[email protected]>
+ */
+#ifndef __PEF2256_H__
+#define __PEF2256_H__
+
+#include <linux/types.h>
+
+struct pef2256;
+struct device_node;
+struct device;
+struct notifier_block;
+
+struct pef2256 *pef2256_get_byphandle(struct device_node *np, const char *phandle_name);
+void pef2256_put(struct pef2256 *pef2256);
+struct pef2256 *devm_pef2256_get_byphandle(struct device *dev, struct device_node *np,
+					   const char *phandle_name);
+
+
+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__ */
#20 lore raw

PATCH v2 3/7 Documentation: sysfs: Document the Lantiq PEF2256 sysfs entry

In reply to Herve Codina

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

---
 .../ABI/testing/sysfs-bus-platform-devices-pef2256   | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256
Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256 new file +12 -0
new file mode 100644
index 000000000000..95ba1ae55daf
@@ -0,0 +1,12 @@
+What:		/sys/bus/platform/devices/*.pef2256/subordinate
+KernelVersion:	6.4
+Contact:	Herve Codina <[email protected]>
+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.
Signature · 1 line
2.39.2
#21 lore raw

PATCH v2 4/7 MAINTAINERS: Add the Lantiq PEF2256 driver entry

In reply to Herve Codina

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

---
 MAINTAINERS | 8 ++++++++
 1 file changed, 8 insertions(+)
MAINTAINERS +8 -0
index fcb69242cd19..b258498aa8ac 100644
@@ -11651,6 +11651,14 @@ S:	Maintained
 F:	arch/mips/lantiq
 F:	drivers/soc/lantiq
 
+LANTIQ PEF2256 DRIVER
+M:	Herve Codina <[email protected]>
+S:	Maintained
+F:	Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256
+F:	Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml
+F:	drivers/misc/pef2256.c
+F:	include/linux/pef2256.h
+
 LASI 53c700 driver for PARISC
 M:	"James E.J. Bottomley" <[email protected]>
 L:	[email protected]
Signature · 1 line
2.39.2
#22 lore raw

PATCH v2 5/7 dt-bindings: sound: Add support for the Lantiq PEF2256 codec

In reply to Herve Codina

The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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.

---
 .../bindings/sound/lantiq,pef2256-codec.yaml  | 57 +++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +57 -0
new file mode 100644
index 000000000000..acba3a0ccd1b
@@ -0,0 +1,57 @@
+# 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 device
+
+maintainers:
+  - Herve Codina <[email protected]>
+
+description: |
+  Codec support for PEF2256.
+
+  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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.
+
+allOf:
+  - $ref: /schemas/spi/spi-peripheral-props.yaml#
+  - $ref: dai-common.yaml#
+
+properties:
+  compatible:
+    const: lantiq,pef2256-codec
+
+  lantiq,pef2256:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      phandle to the PEF2256
+
+  '#sound-dai-cells':
+    const: 0
+
+required:
+  - compatible
+  - lantiq,pef2256
+  - '#sound-dai-cells'
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    audio-codec {
+        compatible = "lantiq,pef2256-codec";
+        lantiq,pef2256 = <&pef2256>;
+        #sound-dai-cells = <0>;
+    };
Signature · 1 line
2.39.2
#23 lore raw

Re: [PATCH v2 5/7] dt-bindings: sound: Add support for the Lantiq PEF2256 codec

Quoted 9 lines · Herve Codina

The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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.

Your other file should also have specific compatible, unless this codec is actually part of the framer. Did not look like this in the binding - not $ref.

Quoted 12 lines
---
 .../bindings/sound/lantiq,pef2256-codec.yaml  | 57 +++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +0 -0
new file mode 100644
index 000000000000..acba3a0ccd1b

Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml line 7

Quoted 7 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +7 -0
@@ -0,0 +1,57 @@
+# 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 device

Drop "device". Everything is "device".

Quoted 22 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +22 -0
+
+maintainers:
+  - Herve Codina <[email protected]>
+
+description: |
+  Codec support for PEF2256.
+
+  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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.
+
+allOf:
+  - $ref: /schemas/spi/spi-peripheral-props.yaml#

Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml line 39

Quoted 10 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +10 -0
+  - $ref: dai-common.yaml#
+
+properties:
+  compatible:
+    const: lantiq,pef2256-codec
+
+  lantiq,pef2256:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      phandle to the PEF2256

Why not its child? Why this is in parallel ?

Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml line 43

Quoted 4 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +4 -0
+
+  '#sound-dai-cells':
+    const: 0
+

Best regards,
Krzysztof

#24 lore raw

Re: [PATCH v2 5/7] dt-bindings: sound: Add support for the Lantiq PEF2256 codec

Hi Krzysztof

Quoted 6 lines · On Fri, 17 Mar 2023 09:57:11 +0100 Krzysztof Kozlowski…
Quoted 5 lines · Herve Codina

The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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.

Quoted 8 lines
Quoted 4 lines

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.

Your other file should also have specific compatible, unless this codec is actually part of the framer. Did not look like this in the binding - not $ref.

No sure to understand what you mean.

Anyway, I plan to use a MFD device for pef2256 and reference this yaml from the lantiq,pef2256.yaml in the node related to the codec.

One question related to bindings and related checks:
Is there a way to check the compatible property of the parent node. I mean, here is the binding of a child node of a MFD node. From this binding, I would like to be sure that the parent is really a pef2256 MFD node.

May be something like:
parent-properties:

    allOf:
      compatible:
        contains:
          const: lantiq,pef2256

The idea is to have dtbs_check raise an error if the parent's compatible property is not 'lantiq,pef2256'.

From parent, the link is checked using:
properties:

    codec:
      $ref: /schemas/sound/lantiq,pef2256-codec.yaml

but nothing prevent to use this 'lantiq,pef2256-codec' binding from a node that has nothing to do with pef2256.

Quoted 7 lines
Quoted 7 lines
---
 .../bindings/sound/lantiq,pef2256-codec.yaml  | 57 +++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
Quoted 15 lines

Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml line 7

Quoted 13 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +7 -0
new file mode 100644
index 000000000000..acba3a0ccd1b
@@ -0,0 +1,57 @@
+# 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 device  

Drop "device". Everything is "device".

Will be dropped in v3 series.

Quoted 15 lines
Quoted 15 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +14 -0
+
+maintainers:
+  - Herve Codina <[email protected]>
+
+description: |
+  Codec support for PEF2256.
+
+  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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.
+
Quoted 8 lines

Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml line 29

Quoted 8 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +8 -0
+  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.
+
+allOf:
+  - $ref: /schemas/spi/spi-peripheral-props.yaml#

Oups,
This device is not on a SPI bus -> will be dropped in v3 series.

Quoted 4 lines
Quoted 4 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +4 -0
+  - $ref: dai-common.yaml#
+
+properties:
+  compatible:
Quoted 8 lines

Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml line 39

Quoted 6 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +6 -0
+    const: lantiq,pef2256-codec
+
+  lantiq,pef2256:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      phandle to the PEF2256  

Why not its child? Why this is in parallel ?

Indeed,
I will move to MFD, remove this phandle and use the lantiq,pef2256-codec node as a child node of lantiq,pef2256.

Quoted 10 lines

Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml line 43

Quoted 5 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +4 -0
+
+  '#sound-dai-cells':
+    const: 0
+  

Best regards,
Krzysztof

Thanks for the review,

Best regards,
Hervé

Signature · 3 lines
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
#25 lore raw

Re: [PATCH v2 5/7] dt-bindings: sound: Add support for the Lantiq PEF2256 codec

In reply to Krzysztof Kozlowski

Hi Krzysztof

Quoted 6 lines · On Fri, 17 Mar 2023 09:57:11 +0100 Krzysztof Kozlowski…
Quoted 5 lines · Herve Codina

The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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.

Quoted 8 lines
Quoted 4 lines

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.

Your other file should also have specific compatible, unless this codec is actually part of the framer. Did not look like this in the binding - not $ref.

No sure to understand what you mean.

Anyway, I plan to use a MFD device for pef2256 and reference this yaml from the lantiq,pef2256.yaml in the node related to the codec.

One question related to bindings and related checks:
Is there a way to check the compatible property of the parent node. I mean, here is the binding of a child node of a MFD node. From this binding, I would like to be sure that the parent is really a pef2256 MFD node.

May be something like:
parent-properties:

    allOf:
      compatible:
        contains:
          const: lantiq,pef2256

The idea is to have dtbs_check raise an error if the parent's compatible property is not 'lantiq,pef2256'.

From parent, the link is checked using:
properties:

    codec:
      $ref: /schemas/sound/lantiq,pef2256-codec.yaml

but nothing prevent to use this 'lantiq,pef2256-codec' binding from a node that has nothing to do with pef2256.

Quoted 7 lines
Quoted 7 lines
---
 .../bindings/sound/lantiq,pef2256-codec.yaml  | 57 +++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
Quoted 15 lines

Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml line 7

Quoted 13 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +7 -0
new file mode 100644
index 000000000000..acba3a0ccd1b
@@ -0,0 +1,57 @@
+# 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 device  

Drop "device". Everything is "device".

Will be dropped in v3 series.

Quoted 15 lines
Quoted 15 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +14 -0
+
+maintainers:
+  - Herve Codina <[email protected]>
+
+description: |
+  Codec support for PEF2256.
+
+  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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.
+
Quoted 8 lines

Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml line 29

Quoted 8 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +8 -0
+  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.
+
+allOf:
+  - $ref: /schemas/spi/spi-peripheral-props.yaml#

Oups,
This device is not on a SPI bus -> will be dropped in v3 series.

Quoted 4 lines
Quoted 4 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +4 -0
+  - $ref: dai-common.yaml#
+
+properties:
+  compatible:
Quoted 8 lines

Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml line 39

Quoted 6 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +6 -0
+    const: lantiq,pef2256-codec
+
+  lantiq,pef2256:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      phandle to the PEF2256  

Why not its child? Why this is in parallel ?

Indeed,
I will move to MFD, remove this phandle and use the lantiq,pef2256-codec node as a child node of lantiq,pef2256.

Quoted 10 lines

Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml line 43

Quoted 5 lines
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +4 -0
+
+  '#sound-dai-cells':
+    const: 0
+  

Best regards,
Krzysztof

Thanks for the review,

Best regards,
Hervé

Signature · 3 lines
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
#26 lore raw

Re: [PATCH v2 5/7] dt-bindings: sound: Add support for the Lantiq PEF2256 codec

Quoted 16 lines · Herve Codina

Hi Krzysztof

Quoted 11 lines · On Fri, 17 Mar 2023 09:57:11 +0100 Krzysztof Kozlowski…
Quoted 9 lines · Herve Codina

The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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.

Quoted 5 lines
Quoted 3 lines

Your other file should also have specific compatible, unless this codec is actually part of the framer. Did not look like this in the binding - not $ref.

No sure to understand what you mean.

Compatible "lantiq,pef2256" in the context of this file is confusing. Two devices without parent-child having similar but different compatibles, of which one is generic (covers entire device) and one is function (codec) specific.

Quoted 3 lines

Anyway, I plan to use a MFD device for pef2256 and reference this yaml from the lantiq,pef2256.yaml in the node related to the codec.

It should be part of these series. Submit complete bindings.

Quoted 6 lines

One question related to bindings and related checks:
Is there a way to check the compatible property of the parent node. I mean, here is the binding of a child node of a MFD node. From this binding, I would like to be sure that the parent is really a pef2256 MFD node.

You cannot and you shouldn't. Parent checks children, not vice-versa.

Quoted 10 lines

May be something like:
parent-properties:

    allOf:
      compatible:
        contains:
          const: lantiq,pef2256

The idea is to have dtbs_check raise an error if the parent's compatible property is not 'lantiq,pef2256'.

But it does not matter. Why your device cannot be used in lantiq,foobar-9999?

Best regards,
Krzysztof

#27 lore raw

PATCH v2 6/7 ASoC: codecs: Add support for the Lantiq PEF2256 codec

In reply to Herve Codina

The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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.

---
 sound/soc/codecs/Kconfig         |  14 ++
 sound/soc/codecs/Makefile        |   2 +
 sound/soc/codecs/pef2256-codec.c | 395 +++++++++++++++++++++++++++++++
 3 files changed, 411 insertions(+)
 create mode 100644 sound/soc/codecs/pef2256-codec.c
sound/soc/codecs/Kconfig +14 -0
index 0be061953e9a..bec4f9200072 100644
@@ -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 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
sound/soc/codecs/Makefile +2 -0
index 20b388b77f1f..11bd66d46f7b 100644
@@ -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
sound/soc/codecs/pef2256-codec.c new file +395 -0

395 lines not on this page · raw message

Signature · 1 line
2.39.2
#28 lore raw

Re: [PATCH v2 6/7] ASoC: codecs: Add support for the Lantiq PEF2256 codec

Le 16/03/2023 à 13:27, Herve Codina a écrit :

Quoted 1 line

The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, is a

s/FALC256/FALC56

Quoted 9 lines

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.

Quoted 8 lines
---
  sound/soc/codecs/Kconfig         |  14 ++
  sound/soc/codecs/Makefile        |   2 +
  sound/soc/codecs/pef2256-codec.c | 395 +++++++++++++++++++++++++++++++
  3 files changed, 411 insertions(+)

create mode 100644 sound/soc/codecs/pef2256-codec.c

No other comment.

Christophe

#29 lore raw

Re: [PATCH v2 6/7] ASoC: codecs: Add support for the Lantiq PEF2256 codec

In reply to Herve Codina

Le 16/03/2023 à 13:27, Herve Codina a écrit :

Quoted 1 line

The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, is a

s/FALC256/FALC56

Quoted 9 lines

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.

Quoted 8 lines
---
  sound/soc/codecs/Kconfig         |  14 ++
  sound/soc/codecs/Makefile        |   2 +
  sound/soc/codecs/pef2256-codec.c | 395 +++++++++++++++++++++++++++++++
  3 files changed, 411 insertions(+)

create mode 100644 sound/soc/codecs/pef2256-codec.c

No other comment.

Christophe

#30 lore raw

PATCH v2 7/7 MAINTAINERS: Add the Lantiq PEF2256 ASoC codec entry

In reply to Herve Codina

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

---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)
MAINTAINERS +7 -0
index b258498aa8ac..81c17580b402 100644
@@ -11651,6 +11651,13 @@ S:	Maintained
 F:	arch/mips/lantiq
 F:	drivers/soc/lantiq
 
+LANTIQ PEF2256 ASoC CODEC
+M:	Herve Codina <[email protected]>
+L:	[email protected] (moderated for non-subscribers)
+S:	Maintained
+F:	Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
+F:	sound/soc/codecs/pef2256-codec.c
+
 LANTIQ PEF2256 DRIVER
 M:	Herve Codina <[email protected]>
 S:	Maintained
Signature · 1 line
2.39.2
#31 lore raw

Re: [PATCH v2 7/7] MAINTAINERS: Add the Lantiq PEF2256 ASoC codec entry

Quoted 13 lines · Herve Codina

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

---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)
MAINTAINERS +0 -0
index b258498aa8ac..81c17580b402 100644

MAINTAINERS S: Maintained · line 11659

Quoted 9 lines
MAINTAINERS +6 -0
@@ -11651,6 +11651,13 @@ S:	Maintained
 F:	arch/mips/lantiq
 F:	drivers/soc/lantiq
 
+LANTIQ PEF2256 ASoC CODEC
+M:	Herve Codina <[email protected]>
+L:	[email protected] (moderated for non-subscribers)
+S:	Maintained
+F:	Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
+F:	sound/soc/codecs/pef2256-codec.c

I don't think there is need for two entries at all. For all such more complex devices we keep one entry, this should not be special. Look at Maxim PMICs/MFD for example.

Best regards,
Krzysztof

#32 lore raw

PATCH v2 1/7 dt-bindings: misc: Add the Lantiq PEF2466 E1/T1/J1 framer

In reply to Herve Codina

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.

---
 .../bindings/misc/lantiq,pef2256.yaml         | 190 ++++++++++++++++++
 1 file changed, 190 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml
Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml new file +190 -0
new file mode 100644
index 000000000000..1ba788d06a14
@@ -0,0 +1,190 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/misc/lantiq,pef2256.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Lantiq PEF2256
+
+maintainers:
+  - Herve Codina <[email protected]>
+
+description:
+  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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:
+    const: lantiq,pef2256
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Master clock
+
+  clock-names:
+    items:
+      - const: mclk
+
+  interrupts:
+    maxItems: 1
+
+  reset-gpios:
+    description:
+      GPIO used to reset the device.
+    maxItems: 1
+
+  pinctrl:
+    allOf:
+      - $ref: "/schemas/pinctrl/pinctrl.yaml#"
+
+    patternProperties:
+      '-pins$':
+        type: object
+        allOf:
+          - $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 ]
+
+        required:
+          - pins
+          - function
+
+  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,sysclk-rate-hz:
+    enum: [2048000, 4096000, 8192000, 16384000]
+    default: 2048000
+    description:
+      Clock rate (Hz) on the system highway.
+
+  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.
+
+allOf:
+  - if:
+      properties:
+        lantiq,line-interface:
+          contains:
+            const: e1
+    then:
+      properties:
+        lantiq,frame-format:
+          $ref: /schemas/types.yaml#/definitions/string
+          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:
+          $ref: /schemas/types.yaml#/definitions/string
+          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>
+    pef2256@2000000 {
+      compatible = "lantiq,pef2256";
+      reg = <0x2000000 0xFF>;
+      interrupts = <8 1>;
+      interrupt-parent = <&PIC>;
+      clocks = <&clk_mclk>;
+      clock-names = "mclk";
+      reset-gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
+      lantiq,sysclk-rate-hz = <8192000>;
+      lantiq,data-rate-bps = <4096000>;
+
+      pinctrl {
+        pef2256_rpa_sypr: rpa-pins {
+          pins = "RPA";
+          function = "SYPR";
+        };
+        pef2256_xpa_sypx: xpa-pins {
+          pins = "XPA";
+          function = "SYPX";
+        };
+      };
+    };
Signature · 1 line
2.39.2
#33 lore raw

PATCH v2 2/7 drivers: misc: Add support for the Lantiq PEF2256 framer

In reply to Herve Codina

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.

---
 drivers/misc/Kconfig    |   17 +
 drivers/misc/Makefile   |    1 +
 drivers/misc/pef2256.c  | 1441 +++++++++++++++++++++++++++++++++++++++
 include/linux/pef2256.h |   36 +
 4 files changed, 1495 insertions(+)
 create mode 100644 drivers/misc/pef2256.c
 create mode 100644 include/linux/pef2256.h
drivers/misc/Kconfig +17 -0
index 433aa4197785..f03739163c53 100644
@@ -376,6 +376,23 @@ config HMC6352
 	  This driver provides support for the Honeywell HMC6352 compass,
 	  providing configuration and heading data via sysfs.
 
+config PEF2256
+	tristate "Lantiq PEF2256 (FALC56) framer"
+	depends on HAS_IOMEM
+	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 DS1682
 	tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
 	depends on I2C
drivers/misc/Makefile +1 -0
index 56de43943cd5..a26f044ab9dd 100644
@@ -35,6 +35,7 @@ obj-$(CONFIG_SENSORS_TSL2550)	+= tsl2550.o
 obj-$(CONFIG_DS1682)		+= ds1682.o
 obj-$(CONFIG_C2PORT)		+= c2port/
 obj-$(CONFIG_HMC6352)		+= hmc6352.o
+obj-$(CONFIG_PEF2256)		+= pef2256.o
 obj-y				+= eeprom/
 obj-y				+= cb710/
 obj-$(CONFIG_VMWARE_BALLOON)	+= vmw_balloon.o
drivers/misc/pef2256.c new file +1441 -0

1,441 lines not on this page · raw message

include/linux/pef2256.h new file +36 -0
new file mode 100644
index 000000000000..6c8d173595b1
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * PEF2256 management
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina <[email protected]>
+ */
+#ifndef __PEF2256_H__
+#define __PEF2256_H__
+
+#include <linux/types.h>
+
+struct pef2256;
+struct device_node;
+struct device;
+struct notifier_block;
+
+struct pef2256 *pef2256_get_byphandle(struct device_node *np, const char *phandle_name);
+void pef2256_put(struct pef2256 *pef2256);
+struct pef2256 *devm_pef2256_get_byphandle(struct device *dev, struct device_node *np,
+					   const char *phandle_name);
+
+
+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__ */
Signature · 1 line
2.39.2
#34 lore raw

PATCH v2 3/7 Documentation: sysfs: Document the Lantiq PEF2256 sysfs entry

In reply to Herve Codina

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

---
 .../ABI/testing/sysfs-bus-platform-devices-pef2256   | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256
Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256 new file +12 -0
new file mode 100644
index 000000000000..95ba1ae55daf
@@ -0,0 +1,12 @@
+What:		/sys/bus/platform/devices/*.pef2256/subordinate
+KernelVersion:	6.4
+Contact:	Herve Codina <[email protected]>
+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.
Signature · 1 line
2.39.2
#35 lore raw

PATCH v2 4/7 MAINTAINERS: Add the Lantiq PEF2256 driver entry

In reply to Herve Codina

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

---
 MAINTAINERS | 8 ++++++++
 1 file changed, 8 insertions(+)
MAINTAINERS +8 -0
index fcb69242cd19..b258498aa8ac 100644
@@ -11651,6 +11651,14 @@ S:	Maintained
 F:	arch/mips/lantiq
 F:	drivers/soc/lantiq
 
+LANTIQ PEF2256 DRIVER
+M:	Herve Codina <[email protected]>
+S:	Maintained
+F:	Documentation/ABI/testing/sysfs-bus-platform-devices-pef2256
+F:	Documentation/devicetree/bindings/misc/lantiq,pef2256.yaml
+F:	drivers/misc/pef2256.c
+F:	include/linux/pef2256.h
+
 LASI 53c700 driver for PARISC
 M:	"James E.J. Bottomley" <[email protected]>
 L:	[email protected]
Signature · 1 line
2.39.2
#36 lore raw

PATCH v2 5/7 dt-bindings: sound: Add support for the Lantiq PEF2256 codec

In reply to Herve Codina

The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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.

---
 .../bindings/sound/lantiq,pef2256-codec.yaml  | 57 +++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml new file +57 -0
new file mode 100644
index 000000000000..acba3a0ccd1b
@@ -0,0 +1,57 @@
+# 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 device
+
+maintainers:
+  - Herve Codina <[email protected]>
+
+description: |
+  Codec support for PEF2256.
+
+  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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.
+
+allOf:
+  - $ref: /schemas/spi/spi-peripheral-props.yaml#
+  - $ref: dai-common.yaml#
+
+properties:
+  compatible:
+    const: lantiq,pef2256-codec
+
+  lantiq,pef2256:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      phandle to the PEF2256
+
+  '#sound-dai-cells':
+    const: 0
+
+required:
+  - compatible
+  - lantiq,pef2256
+  - '#sound-dai-cells'
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    audio-codec {
+        compatible = "lantiq,pef2256-codec";
+        lantiq,pef2256 = <&pef2256>;
+        #sound-dai-cells = <0>;
+    };
Signature · 1 line
2.39.2
#37 lore raw

PATCH v2 6/7 ASoC: codecs: Add support for the Lantiq PEF2256 codec

In reply to Herve Codina

The Lantiq PEF2256, also known as Infineon PEF2256 or FALC256, 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.

---
 sound/soc/codecs/Kconfig         |  14 ++
 sound/soc/codecs/Makefile        |   2 +
 sound/soc/codecs/pef2256-codec.c | 395 +++++++++++++++++++++++++++++++
 3 files changed, 411 insertions(+)
 create mode 100644 sound/soc/codecs/pef2256-codec.c
sound/soc/codecs/Kconfig +14 -0
index 0be061953e9a..bec4f9200072 100644
@@ -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 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
sound/soc/codecs/Makefile +2 -0
index 20b388b77f1f..11bd66d46f7b 100644
@@ -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
sound/soc/codecs/pef2256-codec.c new file +395 -0

395 lines not on this page · raw message

Signature · 1 line
2.39.2
#38 lore raw

PATCH v2 7/7 MAINTAINERS: Add the Lantiq PEF2256 ASoC codec entry

In reply to Herve Codina

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

---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)
MAINTAINERS +7 -0
index b258498aa8ac..81c17580b402 100644
@@ -11651,6 +11651,13 @@ S:	Maintained
 F:	arch/mips/lantiq
 F:	drivers/soc/lantiq
 
+LANTIQ PEF2256 ASoC CODEC
+M:	Herve Codina <[email protected]>
+L:	[email protected] (moderated for non-subscribers)
+S:	Maintained
+F:	Documentation/devicetree/bindings/sound/lantiq,pef2256-codec.yaml
+F:	sound/soc/codecs/pef2256-codec.c
+
 LANTIQ PEF2256 DRIVER
 M:	Herve Codina <[email protected]>
 S:	Maintained
Signature · 1 line
2.39.2