devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/9] Add Mobileye EyeQ system controller support (clk, reset, pinctrl)
@ 2024-06-20 17:30 Théo Lebrun
  2024-06-20 17:30 ` [PATCH v3 1/9] Revert "dt-bindings: clock: mobileye,eyeq5-clk: add bindings" Théo Lebrun
                   ` (8 more replies)
  0 siblings, 9 replies; 21+ messages in thread
From: Théo Lebrun @ 2024-06-20 17:30 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michael Turquette,
	Stephen Boyd, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Rafael J. Wysocki, Lee Jones, Thomas Bogendoerfer
  Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
	Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
	Tawfik Bayouk, Théo Lebrun

Hello,

This builds on previous Mobileye EyeQ system-controller revisions,
supporting EyeQ5, EyeQ6L and EyeQ6H. We expose a few OLB
system-controller features here:
 - Clocks: some read-only PLLs derived from main crystal and some
   divider clocks based on PLLs.
 - Resets.
 - Pin controller, only on EyeQ5 (others will use pinctrl-single).

EyeQ6H is special in that it has seven instances of this
system-controller. Those are spread around and cannot be seen as a
single device, hence are exposed as seven DT nodes and seven
unique compatibles.

Following feedback (that took time to reach my brain, sorry about that):
 - We expose each system-controller as a single devicetree node. This
   means reverting previously accepted dt-bindings that described a
   one-node-per-feature approach.
 - We use auxiliary devices infrastructure to split functionality into
   separate drivers. Clock is the platform driver that spawns child
   auxdevs. They get an iomem pointer to the OLB region as
   platform_data. They know which behavior to implement by matching
   compatible on their parent device's OF node.

Patches are targeting MIPS, clk, reset and pinctrl:

MIPS:
 - dt-bindings: soc: mobileye: add EyeQ OLB system controller
 - MIPS: mobileye: eyeq5: add OLB system-controller node

clk:
 - Revert "dt-bindings: clock: mobileye,eyeq5-clk: add bindings"
 - clk: divider: Introduce CLK_DIVIDER_EVEN_INTEGERS flag
 - clk: eyeq: add driver

reset:
 - Revert "dt-bindings: reset: mobileye,eyeq5-reset: add bindings"
 - reset: eyeq: add platform driver

pinctrl:
 - Revert "dt-bindings: pinctrl: mobileye,eyeq5-pinctrl: add bindings"
 - pinctrl: eyeq5: add platform driver

Have a nice day,
Théo

Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
---
Changes in v3:
- Drivers: Switch to using auxiliary devices. Drop the MFD patches.
  Consequent changes to the clk driver that now spawns its auxdevs.
  Reset and pinctrl switch from being platform driver to auxdevs.
- dt-bindings and EyeQ5 DTS: remove "simple-mfd" compatible from all OLB
  nodes.
- dt-bindings: rewrite commit title and messages. Title now takes the
  standard revert format.
- dt-bindings: revert pinctrl dt-bindings as well; this was forgotten in
  the previous revision.
- clk driver: fix overflow of factors; they get stored in 32-bit ints in
  fixed-factor which we overflowed when spread-spectrum is enabled.
- Link to v2: https://lore.kernel.org/r/20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com

Changes in v2:
- dt-bindings:
  - Drop mobileye,eyeq5-clk and mobileye,eyeq5-reset bindings.
  - Update OLB bindings to handle clk/reset/pinctrl from OLB node.
- MFD:
  - Add core driver and MFD patches to allow setting sub-devices names
    from MFD cell.
  - Add MFD OLB driver.
- clk:
  - Change type of eqc_pll->reg64 from u32 to unsigned int.
  - Use resource indexes rather than names for iomem resources.
  - Put early PLLs into a separate match data table. Also, have store
    number of late clocks in early match data to properly alloc cells.
  - Pre-acquire all divclk resources first, then register them.
    This simplifies code.
  - Extract PLLs and divclks init to two separate functions.
  - Avoid variable declarations in loop bodies.
  - Do not register match data table to platform driver. It gets probed
    as MFD sub-device matching on driver name. Match data table is
    matched against parent OF node compatible.
  - Fix ugly memory corruption bug when clk count == 1.
- reset:
  - EQR_EYEQ5_SARCR and EQR_EYEQ6H_SARCR did not use offset 0x0: do
    minus four to all their offsets and reduce resource sizes.
  - Remove resource names. Reset i uses iomem resource index i.
  - Simplify xlate: have two implementations for of_reset_n_cells==1 and
    of_reset_n_cells==2. Both call the same helper internal function.
  - Do not register match data table to platform driver. It gets probed
    as MFD sub-device matching on driver name. Match data table is
    matched against parent OF node compatible.
- pinctrl:
  - Remove match data table to platform driver. It gets probed as MFD
    sub-device matching on driver name. Driver has single compatible.
  - Drop "Reviewed-by: Linus Walleij" as driver changed approach.
- MIPS DTS:
  - Squash all commits together into a single one.
  - Adapt to new approach: OLB is now a single OF node.
- Link to v1: https://lore.kernel.org/r/20240410-mbly-olb-v1-0-335e496d7be3@bootlin.com

---
Théo Lebrun (9):
      Revert "dt-bindings: clock: mobileye,eyeq5-clk: add bindings"
      Revert "dt-bindings: reset: mobileye,eyeq5-reset: add bindings"
      Revert "dt-bindings: pinctrl: mobileye,eyeq5-pinctrl: add bindings"
      dt-bindings: soc: mobileye: add EyeQ OLB system controller
      clk: divider: Introduce CLK_DIVIDER_EVEN_INTEGERS flag
      clk: eyeq: add driver
      reset: eyeq: add platform driver
      pinctrl: eyeq5: add platform driver
      MIPS: mobileye: eyeq5: add OLB system-controller node

 .../bindings/clock/mobileye,eyeq5-clk.yaml         |  51 --
 .../bindings/reset/mobileye,eyeq5-reset.yaml       |  43 --
 .../mobileye/mobileye,eyeq5-olb.yaml}              | 168 ++++-
 MAINTAINERS                                        |   5 +
 .../{eyeq5-fixed-clocks.dtsi => eyeq5-clocks.dtsi} |  54 +-
 arch/mips/boot/dts/mobileye/eyeq5-pins.dtsi        | 125 ++++
 arch/mips/boot/dts/mobileye/eyeq5.dtsi             |  22 +-
 drivers/clk/Kconfig                                |  12 +
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk-divider.c                          |  12 +-
 drivers/clk/clk-eyeq.c                             | 789 +++++++++++++++++++++
 drivers/pinctrl/Kconfig                            |  15 +
 drivers/pinctrl/Makefile                           |   1 +
 drivers/pinctrl/pinctrl-eyeq5.c                    | 576 +++++++++++++++
 drivers/reset/Kconfig                              |  14 +
 drivers/reset/Makefile                             |   1 +
 drivers/reset/reset-eyeq.c                         | 563 +++++++++++++++
 include/dt-bindings/clock/mobileye,eyeq5-clk.h     |  21 +
 include/linux/clk-provider.h                       |  11 +-
 19 files changed, 2326 insertions(+), 158 deletions(-)
---
base-commit: 061f2865f17c038f04a71ccdd6c90746381d63a8
change-id: 20240408-mbly-olb-75a85f5cfde3

Best regards,
-- 
Théo Lebrun <theo.lebrun@bootlin.com>


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

* [PATCH v3 1/9] Revert "dt-bindings: clock: mobileye,eyeq5-clk: add bindings"
  2024-06-20 17:30 [PATCH v3 0/9] Add Mobileye EyeQ system controller support (clk, reset, pinctrl) Théo Lebrun
@ 2024-06-20 17:30 ` Théo Lebrun
  2024-06-24 20:55   ` Rob Herring (Arm)
  2024-06-20 17:30 ` [PATCH v3 2/9] Revert "dt-bindings: reset: mobileye,eyeq5-reset: " Théo Lebrun
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Théo Lebrun @ 2024-06-20 17:30 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michael Turquette,
	Stephen Boyd, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Rafael J. Wysocki, Lee Jones, Thomas Bogendoerfer
  Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
	Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
	Tawfik Bayouk, Théo Lebrun

Switch from one sub-node per functionality in the system-controller to a
single node representing the entire OLB instance. This is the
recommended approach for controllers handling many different
functionalities; it is a single controller and should be represented by
a single devicetree node.

The clock bindings is removed and all properties will be described by:
soc/mobileye/mobileye,eyeq5-olb.yaml

Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
---
 .../bindings/clock/mobileye,eyeq5-clk.yaml         | 51 ----------------------
 1 file changed, 51 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/mobileye,eyeq5-clk.yaml b/Documentation/devicetree/bindings/clock/mobileye,eyeq5-clk.yaml
deleted file mode 100644
index 2d4f2cde1e58..000000000000
--- a/Documentation/devicetree/bindings/clock/mobileye,eyeq5-clk.yaml
+++ /dev/null
@@ -1,51 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/clock/mobileye,eyeq5-clk.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Mobileye EyeQ5 clock controller
-
-description:
-  The EyeQ5 clock controller handles 10 read-only PLLs derived from the main
-  crystal clock. It also exposes one divider clock, a child of one of the PLLs.
-  Its registers live in a shared region called OLB.
-
-maintainers:
-  - Grégory Clement <gregory.clement@bootlin.com>
-  - Théo Lebrun <theo.lebrun@bootlin.com>
-  - Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
-
-properties:
-  compatible:
-    const: mobileye,eyeq5-clk
-
-  reg:
-    maxItems: 2
-
-  reg-names:
-    items:
-      - const: plls
-      - const: ospi
-
-  "#clock-cells":
-    const: 1
-
-  clocks:
-    maxItems: 1
-    description:
-      Input parent clock to all PLLs. Expected to be the main crystal.
-
-  clock-names:
-    items:
-      - const: ref
-
-required:
-  - compatible
-  - reg
-  - reg-names
-  - "#clock-cells"
-  - clocks
-  - clock-names
-
-additionalProperties: false

-- 
2.45.2


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

* [PATCH v3 2/9] Revert "dt-bindings: reset: mobileye,eyeq5-reset: add bindings"
  2024-06-20 17:30 [PATCH v3 0/9] Add Mobileye EyeQ system controller support (clk, reset, pinctrl) Théo Lebrun
  2024-06-20 17:30 ` [PATCH v3 1/9] Revert "dt-bindings: clock: mobileye,eyeq5-clk: add bindings" Théo Lebrun
@ 2024-06-20 17:30 ` Théo Lebrun
  2024-06-20 18:26   ` Rob Herring (Arm)
  2024-06-24 20:56   ` Rob Herring (Arm)
  2024-06-20 17:30 ` [PATCH v3 3/9] Revert "dt-bindings: pinctrl: mobileye,eyeq5-pinctrl: " Théo Lebrun
                   ` (6 subsequent siblings)
  8 siblings, 2 replies; 21+ messages in thread
From: Théo Lebrun @ 2024-06-20 17:30 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michael Turquette,
	Stephen Boyd, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Rafael J. Wysocki, Lee Jones, Thomas Bogendoerfer
  Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
	Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
	Tawfik Bayouk, Théo Lebrun

Switch from one sub-node per functionality in the system-controller to a
single node representing the entire OLB instance. This is the
recommended approach for controllers handling many different
functionalities; it is a single controller and should be represented by
a single devicetree node.

The reset bindings is removed and all properties will be described by:
soc/mobileye/mobileye,eyeq5-olb.yaml

Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
---
 .../bindings/reset/mobileye,eyeq5-reset.yaml       | 43 ----------------------
 1 file changed, 43 deletions(-)

diff --git a/Documentation/devicetree/bindings/reset/mobileye,eyeq5-reset.yaml b/Documentation/devicetree/bindings/reset/mobileye,eyeq5-reset.yaml
deleted file mode 100644
index 062b4518347b..000000000000
--- a/Documentation/devicetree/bindings/reset/mobileye,eyeq5-reset.yaml
+++ /dev/null
@@ -1,43 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/reset/mobileye,eyeq5-reset.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Mobileye EyeQ5 reset controller
-
-description:
-  The EyeQ5 reset driver handles three reset domains. Its registers live in a
-  shared region called OLB.
-
-maintainers:
-  - Grégory Clement <gregory.clement@bootlin.com>
-  - Théo Lebrun <theo.lebrun@bootlin.com>
-  - Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
-
-properties:
-  compatible:
-    const: mobileye,eyeq5-reset
-
-  reg:
-    maxItems: 3
-
-  reg-names:
-    items:
-      - const: d0
-      - const: d1
-      - const: d2
-
-  "#reset-cells":
-    const: 2
-    description:
-      The first cell is the domain (0 to 2 inclusive) and the second one is the
-      reset index inside that domain.
-
-required:
-  - compatible
-  - reg
-  - reg-names
-  - "#reset-cells"
-
-additionalProperties: false

-- 
2.45.2


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

* [PATCH v3 3/9] Revert "dt-bindings: pinctrl: mobileye,eyeq5-pinctrl: add bindings"
  2024-06-20 17:30 [PATCH v3 0/9] Add Mobileye EyeQ system controller support (clk, reset, pinctrl) Théo Lebrun
  2024-06-20 17:30 ` [PATCH v3 1/9] Revert "dt-bindings: clock: mobileye,eyeq5-clk: add bindings" Théo Lebrun
  2024-06-20 17:30 ` [PATCH v3 2/9] Revert "dt-bindings: reset: mobileye,eyeq5-reset: " Théo Lebrun
@ 2024-06-20 17:30 ` Théo Lebrun
  2024-06-24 20:56   ` Rob Herring (Arm)
  2024-06-26 11:53   ` Linus Walleij
  2024-06-20 17:30 ` [PATCH v3 4/9] dt-bindings: soc: mobileye: add EyeQ OLB system controller Théo Lebrun
                   ` (5 subsequent siblings)
  8 siblings, 2 replies; 21+ messages in thread
From: Théo Lebrun @ 2024-06-20 17:30 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michael Turquette,
	Stephen Boyd, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Rafael J. Wysocki, Lee Jones, Thomas Bogendoerfer
  Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
	Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
	Tawfik Bayouk, Théo Lebrun

Switch from one sub-node per functionality in the system-controller to a
single node representing the entire OLB instance. This is the
recommended approach for controllers handling many different
functionalities; it is a single controller and should be represented by
a single devicetree node.

The pinctrl bindings is removed and all properties will be described by:
soc/mobileye/mobileye,eyeq5-olb.yaml

Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
---
 .../bindings/pinctrl/mobileye,eyeq5-pinctrl.yaml   | 242 ---------------------
 1 file changed, 242 deletions(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/mobileye,eyeq5-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mobileye,eyeq5-pinctrl.yaml
deleted file mode 100644
index 5f00604bf48c..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/mobileye,eyeq5-pinctrl.yaml
+++ /dev/null
@@ -1,242 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/pinctrl/mobileye,eyeq5-pinctrl.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Mobileye EyeQ5 pin controller
-
-description: >
-  The EyeQ5 pin controller handles the two pin banks of the system. It belongs
-  to a system-controller block called OLB.
-
-  Pin control is about bias (pull-down, pull-up), drive strength and muxing. Pin
-  muxing supports two functions for each pin: first is GPIO, second is
-  pin-dependent.
-
-  Pins and groups are bijective.
-
-maintainers:
-  - Grégory Clement <gregory.clement@bootlin.com>
-  - Théo Lebrun <theo.lebrun@bootlin.com>
-  - Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
-
-$ref: pinctrl.yaml#
-
-properties:
-  compatible:
-    enum:
-      - mobileye,eyeq5-pinctrl
-
-  reg:
-    maxItems: 1
-
-patternProperties:
-  "-pins?$":
-    type: object
-    description: Pin muxing configuration.
-    $ref: pinmux-node.yaml#
-    additionalProperties: false
-    properties:
-      pins: true
-      function:
-        enum: [gpio,
-               # Bank A
-               timer0, timer1, timer2, timer5, uart0, uart1, can0, can1, spi0,
-               spi1, refclk0,
-               # Bank B
-               timer3, timer4, timer6, uart2, can2, spi2, spi3, mclk0]
-      bias-disable: true
-      bias-pull-down: true
-      bias-pull-up: true
-      drive-strength: true
-    required:
-      - pins
-      - function
-    allOf:
-      - if:
-          properties:
-            function:
-              const: gpio
-        then:
-          properties:
-            pins:
-              items: # PA0 - PA28, PB0 - PB22
-                pattern: '^(P(A|B)1?[0-9]|PA2[0-8]|PB2[0-2])$'
-      - if:
-          properties:
-            function:
-              const: timer0
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PA0, PA1]
-      - if:
-          properties:
-            function:
-              const: timer1
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PA2, PA3]
-      - if:
-          properties:
-            function:
-              const: timer2
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PA4, PA5]
-      - if:
-          properties:
-            function:
-              const: timer5
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PA6, PA7, PA8, PA9]
-      - if:
-          properties:
-            function:
-              const: uart0
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PA10, PA11]
-      - if:
-          properties:
-            function:
-              const: uart1
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PA12, PA13]
-      - if:
-          properties:
-            function:
-              const: can0
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PA14, PA15]
-      - if:
-          properties:
-            function:
-              const: can1
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PA16, PA17]
-      - if:
-          properties:
-            function:
-              const: spi0
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PA18, PA19, PA20, PA21, PA22]
-      - if:
-          properties:
-            function:
-              const: spi1
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PA23, PA24, PA25, PA26, PA27]
-      - if:
-          properties:
-            function:
-              const: refclk0
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PA28]
-      - if:
-          properties:
-            function:
-              const: timer3
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PB0, PB1]
-      - if:
-          properties:
-            function:
-              const: timer4
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PB2, PB3]
-      - if:
-          properties:
-            function:
-              const: timer6
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PB4, PB5, PB6, PB7]
-      - if:
-          properties:
-            function:
-              const: uart2
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PB8, PB9]
-      - if:
-          properties:
-            function:
-              const: can2
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PB10, PB11]
-      - if:
-          properties:
-            function:
-              const: spi2
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PB12, PB13, PB14, PB15, PB16]
-      - if:
-          properties:
-            function:
-              const: spi3
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PB17, PB18, PB19, PB20, PB21]
-      - if:
-          properties:
-            function:
-              const: mclk0
-        then:
-          properties:
-            pins:
-              items:
-                enum: [PB22]
-
-required:
-  - compatible
-  - reg
-
-additionalProperties: false

-- 
2.45.2


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

* [PATCH v3 4/9] dt-bindings: soc: mobileye: add EyeQ OLB system controller
  2024-06-20 17:30 [PATCH v3 0/9] Add Mobileye EyeQ system controller support (clk, reset, pinctrl) Théo Lebrun
                   ` (2 preceding siblings ...)
  2024-06-20 17:30 ` [PATCH v3 3/9] Revert "dt-bindings: pinctrl: mobileye,eyeq5-pinctrl: " Théo Lebrun
@ 2024-06-20 17:30 ` Théo Lebrun
  2024-06-20 18:26   ` Rob Herring (Arm)
  2024-06-24 20:56   ` Rob Herring (Arm)
  2024-06-20 17:30 ` [PATCH v3 5/9] clk: divider: Introduce CLK_DIVIDER_EVEN_INTEGERS flag Théo Lebrun
                   ` (4 subsequent siblings)
  8 siblings, 2 replies; 21+ messages in thread
From: Théo Lebrun @ 2024-06-20 17:30 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michael Turquette,
	Stephen Boyd, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Rafael J. Wysocki, Lee Jones, Thomas Bogendoerfer
  Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
	Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
	Tawfik Bayouk, Théo Lebrun

Add documentation to describe the "Other Logic Block" system-controller.
It deals with three platforms: EyeQ5, EyeQ6L and EyeQ6H. First two have
a single instance, whereas EyeQ6H has seven named instances.

Features provided are:
 - Clocks, children to main crystal. Some PLLs and divider clocks.
 - Resets. Some instances DO NOT have reset.
 - Pinctrl. Only EyeQ5 has such feature.

Those are NOT the only features exposed in OLB system-controllers! Many
individual registers, related to IP block integration, can be found.
Additional features will be exposed over time.

We simplify devicetree phandles to OLB in two ways:

 - Compatibles exposing a single clock do not ask for a index argument.
   This means we use EyeQ6H OLB south (it has four clocks):

      clocks = <&olb_south EQ6HC_SOUTH_PLL_PER>;

   But use EyeQ6H OLB east (it has one clock):

      clocks = <&olb_east>;

 - Compatibles exposing a single reset domain do not ask for a domain
   index, only a reset index.
   This means we use EyeQ5 OLB (it has three domains):

     resets = <&olb 0 10>;

   But use EyeQ6H west reset (it has one domain):

      resets = <&olb_west 3>;

About pinctrl subnodes: all pins have two functionality, either GPIO or
something-else. The latter is pin dependent, we express constraints
using many if-then.

Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
---
 .../bindings/soc/mobileye/mobileye,eyeq5-olb.yaml  | 374 +++++++++++++++++++++
 MAINTAINERS                                        |   2 +
 include/dt-bindings/clock/mobileye,eyeq5-clk.h     |  21 ++
 3 files changed, 397 insertions(+)

diff --git a/Documentation/devicetree/bindings/soc/mobileye/mobileye,eyeq5-olb.yaml b/Documentation/devicetree/bindings/soc/mobileye/mobileye,eyeq5-olb.yaml
new file mode 100644
index 000000000000..f7e606d45ebc
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mobileye/mobileye,eyeq5-olb.yaml
@@ -0,0 +1,374 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/mobileye/mobileye,eyeq5-olb.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mobileye EyeQ SoC system controller
+
+maintainers:
+  - Grégory Clement <gregory.clement@bootlin.com>
+  - Théo Lebrun <theo.lebrun@bootlin.com>
+  - Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
+
+description:
+  OLB ("Other Logic Block") is a hardware block grouping smaller blocks. Clocks,
+  resets, pinctrl are being handled from here. EyeQ5 and EyeQ6L host a single
+  instance. EyeQ6H hosts seven instances.
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - mobileye,eyeq5-olb
+          - mobileye,eyeq6l-olb
+          - mobileye,eyeq6h-acc-olb
+          - mobileye,eyeq6h-central-olb
+          - mobileye,eyeq6h-east-olb
+          - mobileye,eyeq6h-west-olb
+          - mobileye,eyeq6h-south-olb
+          - mobileye,eyeq6h-ddr0-olb
+          - mobileye,eyeq6h-ddr1-olb
+      - const: syscon
+
+  reg:
+    maxItems: 1
+
+  '#reset-cells':
+    description:
+      First cell is domain and optional if compatible has a single reset domain.
+      Second cell is reset index inside that domain.
+    enum: [ 1, 2 ]
+
+  '#clock-cells':
+    description:
+      Cell is clock index. Optional if compatible has a single clock.
+    enum: [ 0, 1 ]
+
+  clocks:
+    maxItems: 1
+    description:
+      Input parent clock to all PLLs. Expected to be the main crystal.
+
+  clock-names:
+    const: ref
+
+patternProperties:
+  '-pins?$':
+    type: object
+    description: Pin muxing configuration.
+    $ref: /schemas/pinctrl/pinmux-node.yaml#
+    additionalProperties: false
+    properties:
+      pins: true
+      function:
+        enum: [gpio,
+               # Bank A
+               timer0, timer1, timer2, timer5, uart0, uart1, can0, can1, spi0,
+               spi1, refclk0,
+               # Bank B
+               timer3, timer4, timer6, uart2, can2, spi2, spi3, mclk0]
+      bias-disable: true
+      bias-pull-down: true
+      bias-pull-up: true
+      drive-strength: true
+    required:
+      - pins
+      - function
+    allOf:
+      - if:
+          properties:
+            function:
+              const: gpio
+        then:
+          properties:
+            pins:
+              items: # PA0 - PA28, PB0 - PB22
+                pattern: '^(P(A|B)1?[0-9]|PA2[0-8]|PB2[0-2])$'
+      - if:
+          properties:
+            function:
+              const: timer0
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PA0, PA1]
+      - if:
+          properties:
+            function:
+              const: timer1
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PA2, PA3]
+      - if:
+          properties:
+            function:
+              const: timer2
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PA4, PA5]
+      - if:
+          properties:
+            function:
+              const: timer5
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PA6, PA7, PA8, PA9]
+      - if:
+          properties:
+            function:
+              const: uart0
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PA10, PA11]
+      - if:
+          properties:
+            function:
+              const: uart1
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PA12, PA13]
+      - if:
+          properties:
+            function:
+              const: can0
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PA14, PA15]
+      - if:
+          properties:
+            function:
+              const: can1
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PA16, PA17]
+      - if:
+          properties:
+            function:
+              const: spi0
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PA18, PA19, PA20, PA21, PA22]
+      - if:
+          properties:
+            function:
+              const: spi1
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PA23, PA24, PA25, PA26, PA27]
+      - if:
+          properties:
+            function:
+              const: refclk0
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PA28]
+      - if:
+          properties:
+            function:
+              const: timer3
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PB0, PB1]
+      - if:
+          properties:
+            function:
+              const: timer4
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PB2, PB3]
+      - if:
+          properties:
+            function:
+              const: timer6
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PB4, PB5, PB6, PB7]
+      - if:
+          properties:
+            function:
+              const: uart2
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PB8, PB9]
+      - if:
+          properties:
+            function:
+              const: can2
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PB10, PB11]
+      - if:
+          properties:
+            function:
+              const: spi2
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PB12, PB13, PB14, PB15, PB16]
+      - if:
+          properties:
+            function:
+              const: spi3
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PB17, PB18, PB19, PB20, PB21]
+      - if:
+          properties:
+            function:
+              const: mclk0
+        then:
+          properties:
+            pins:
+              items:
+                enum: [PB22]
+
+required:
+  - compatible
+  - reg
+  - '#clock-cells'
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+allOf:
+    # Compatibles exposing a single reset domain.
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - mobileye,eyeq6h-acc-olb
+              - mobileye,eyeq6h-east-olb
+              - mobileye,eyeq6h-west-olb
+    then:
+      properties:
+        '#reset-cells':
+          const: 1
+      required:
+        - '#reset-cells'
+
+    # Compatibles exposing two reset domains.
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - mobileye,eyeq5-olb
+              - mobileye,eyeq6l-olb
+    then:
+      properties:
+        '#reset-cells':
+          const: 2
+      required:
+        - '#reset-cells'
+
+    # Compatibles not exposing resets.
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - mobileye,eyeq6h-central-olb
+              - mobileye,eyeq6h-south-olb
+              - mobileye,eyeq6h-ddr0-olb
+              - mobileye,eyeq6h-ddr1-olb
+    then:
+      properties:
+        '#reset-cells': false
+
+    # Compatibles exposing a single clock.
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - mobileye,eyeq6h-central-olb
+              - mobileye,eyeq6h-east-olb
+              - mobileye,eyeq6h-west-olb
+              - mobileye,eyeq6h-ddr0-olb
+              - mobileye,eyeq6h-ddr1-olb
+    then:
+      properties:
+        '#clock-cells':
+          const: 0
+    else:
+      properties:
+        '#clock-cells':
+          const: 1
+
+    # Only EyeQ5 has pinctrl in OLB.
+  - if:
+      not:
+        properties:
+          compatible:
+            contains:
+              const: mobileye,eyeq5-olb
+    then:
+      patternProperties:
+        '-pins?$': false
+
+examples:
+  - |
+    soc {
+      #address-cells = <2>;
+      #size-cells = <2>;
+
+      system-controller@e00000 {
+        compatible = "mobileye,eyeq5-olb", "syscon";
+        reg = <0 0xe00000 0x0 0x400>;
+        #reset-cells = <2>;
+        #clock-cells = <1>;
+        clocks = <&xtal>;
+        clock-names = "ref";
+      };
+    };
+  - |
+    soc {
+      #address-cells = <2>;
+      #size-cells = <2>;
+
+      system-controller@d2003000 {
+        compatible = "mobileye,eyeq6h-acc-olb", "syscon";
+        reg = <0x0 0xd2003000 0x0 0x1000>;
+        #reset-cells = <1>;
+        #clock-cells = <1>;
+        clocks = <&xtal>;
+        clock-names = "ref";
+      };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index aa3b947fb080..fcc9f4364a5d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14926,9 +14926,11 @@ M:	Théo Lebrun <theo.lebrun@bootlin.com>
 L:	linux-mips@vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/mips/mobileye.yaml
+F:	Documentation/devicetree/bindings/soc/mobileye/
 F:	arch/mips/boot/dts/mobileye/
 F:	arch/mips/configs/eyeq5_defconfig
 F:	arch/mips/mobileye/board-epm5.its.S
+F:	include/dt-bindings/clock/mobileye,eyeq5-clk.h
 
 MODULE SUPPORT
 M:	Luis Chamberlain <mcgrof@kernel.org>
diff --git a/include/dt-bindings/clock/mobileye,eyeq5-clk.h b/include/dt-bindings/clock/mobileye,eyeq5-clk.h
index 26d8930335e4..b433c1772c28 100644
--- a/include/dt-bindings/clock/mobileye,eyeq5-clk.h
+++ b/include/dt-bindings/clock/mobileye,eyeq5-clk.h
@@ -19,4 +19,25 @@
 
 #define EQ5C_DIV_OSPI	10
 
+#define EQ6LC_PLL_DDR		0
+#define EQ6LC_PLL_CPU		1
+#define EQ6LC_PLL_PER		2
+#define EQ6LC_PLL_VDI		3
+
+#define EQ6HC_SOUTH_PLL_VDI		0
+#define EQ6HC_SOUTH_PLL_PCIE		1
+#define EQ6HC_SOUTH_PLL_PER		2
+#define EQ6HC_SOUTH_PLL_ISP		3
+
+#define EQ6HC_SOUTH_DIV_EMMC		4
+#define EQ6HC_SOUTH_DIV_OSPI_REF	5
+#define EQ6HC_SOUTH_DIV_OSPI_SYS	6
+#define EQ6HC_SOUTH_DIV_TSU		7
+
+#define EQ6HC_ACC_PLL_XNN		0
+#define EQ6HC_ACC_PLL_VMP		1
+#define EQ6HC_ACC_PLL_PMA		2
+#define EQ6HC_ACC_PLL_MPC		3
+#define EQ6HC_ACC_PLL_NOC		4
+
 #endif

-- 
2.45.2


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

* [PATCH v3 5/9] clk: divider: Introduce CLK_DIVIDER_EVEN_INTEGERS flag
  2024-06-20 17:30 [PATCH v3 0/9] Add Mobileye EyeQ system controller support (clk, reset, pinctrl) Théo Lebrun
                   ` (3 preceding siblings ...)
  2024-06-20 17:30 ` [PATCH v3 4/9] dt-bindings: soc: mobileye: add EyeQ OLB system controller Théo Lebrun
@ 2024-06-20 17:30 ` Théo Lebrun
  2024-06-20 17:30 ` [PATCH v3 6/9] clk: eyeq: add driver Théo Lebrun
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Théo Lebrun @ 2024-06-20 17:30 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michael Turquette,
	Stephen Boyd, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Rafael J. Wysocki, Lee Jones, Thomas Bogendoerfer
  Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
	Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
	Tawfik Bayouk, Théo Lebrun

Add CLK_DIVIDER_EVEN_INTEGERS flag to support divisor of 2, 4, 6, etc.
The same divisor can be done using a table, which would be big and
wasteful for a clock dividor of width 8 (256 entries).

Require increasing flags size from u8 to u16 because
CLK_DIVIDER_EVEN_INTEGERS is the eighth flag.

Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
---
 drivers/clk/clk-divider.c    | 12 +++++++++---
 include/linux/clk-provider.h | 11 +++++++----
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index a2c2b5203b0a..b6654c5c36d2 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -72,6 +72,8 @@ static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width,
 		return clk_div_mask(width);
 	if (flags & CLK_DIVIDER_POWER_OF_TWO)
 		return 1 << clk_div_mask(width);
+	if (flags & CLK_DIVIDER_EVEN_INTEGERS)
+		return 2 * (clk_div_mask(width) + 1);
 	if (table)
 		return _get_table_maxdiv(table, width);
 	return clk_div_mask(width) + 1;
@@ -97,6 +99,8 @@ static unsigned int _get_div(const struct clk_div_table *table,
 		return 1 << val;
 	if (flags & CLK_DIVIDER_MAX_AT_ZERO)
 		return val ? val : clk_div_mask(width) + 1;
+	if (flags & CLK_DIVIDER_EVEN_INTEGERS)
+		return 2 * (val + 1);
 	if (table)
 		return _get_table_div(table, val);
 	return val + 1;
@@ -122,6 +126,8 @@ static unsigned int _get_val(const struct clk_div_table *table,
 		return __ffs(div);
 	if (flags & CLK_DIVIDER_MAX_AT_ZERO)
 		return (div == clk_div_mask(width) + 1) ? 0 : div;
+	if (flags & CLK_DIVIDER_EVEN_INTEGERS)
+		return (div >> 1) - 1;
 	if (table)
 		return  _get_table_val(table, div);
 	return div - 1;
@@ -538,7 +544,7 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev,
 		struct device_node *np, const char *name,
 		const char *parent_name, const struct clk_hw *parent_hw,
 		const struct clk_parent_data *parent_data, unsigned long flags,
-		void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
+		void __iomem *reg, u8 shift, u8 width, u16 clk_divider_flags,
 		const struct clk_div_table *table, spinlock_t *lock)
 {
 	struct clk_divider *div;
@@ -610,7 +616,7 @@ EXPORT_SYMBOL_GPL(__clk_hw_register_divider);
 struct clk *clk_register_divider_table(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
-		u8 clk_divider_flags, const struct clk_div_table *table,
+		u16 clk_divider_flags, const struct clk_div_table *table,
 		spinlock_t *lock)
 {
 	struct clk_hw *hw;
@@ -664,7 +670,7 @@ struct clk_hw *__devm_clk_hw_register_divider(struct device *dev,
 		struct device_node *np, const char *name,
 		const char *parent_name, const struct clk_hw *parent_hw,
 		const struct clk_parent_data *parent_data, unsigned long flags,
-		void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
+		void __iomem *reg, u8 shift, u8 width, u16 clk_divider_flags,
 		const struct clk_div_table *table, spinlock_t *lock)
 {
 	struct clk_hw **ptr, *hw;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 4a537260f655..cb348e502e41 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -675,13 +675,15 @@ struct clk_div_table {
  * CLK_DIVIDER_BIG_ENDIAN - By default little endian register accesses are used
  *	for the divider register.  Setting this flag makes the register accesses
  *	big endian.
+ * CLK_DIVIDER_EVEN_INTEGERS - clock divisor is 2, 4, 6, 8, 10, etc.
+ *	Formula is 2 * (value read from hardware + 1).
  */
 struct clk_divider {
 	struct clk_hw	hw;
 	void __iomem	*reg;
 	u8		shift;
 	u8		width;
-	u8		flags;
+	u16		flags;
 	const struct clk_div_table	*table;
 	spinlock_t	*lock;
 };
@@ -697,6 +699,7 @@ struct clk_divider {
 #define CLK_DIVIDER_READ_ONLY		BIT(5)
 #define CLK_DIVIDER_MAX_AT_ZERO		BIT(6)
 #define CLK_DIVIDER_BIG_ENDIAN		BIT(7)
+#define CLK_DIVIDER_EVEN_INTEGERS	BIT(8)
 
 extern const struct clk_ops clk_divider_ops;
 extern const struct clk_ops clk_divider_ro_ops;
@@ -726,18 +729,18 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev,
 		struct device_node *np, const char *name,
 		const char *parent_name, const struct clk_hw *parent_hw,
 		const struct clk_parent_data *parent_data, unsigned long flags,
-		void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
+		void __iomem *reg, u8 shift, u8 width, u16 clk_divider_flags,
 		const struct clk_div_table *table, spinlock_t *lock);
 struct clk_hw *__devm_clk_hw_register_divider(struct device *dev,
 		struct device_node *np, const char *name,
 		const char *parent_name, const struct clk_hw *parent_hw,
 		const struct clk_parent_data *parent_data, unsigned long flags,
-		void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
+		void __iomem *reg, u8 shift, u8 width, u16 clk_divider_flags,
 		const struct clk_div_table *table, spinlock_t *lock);
 struct clk *clk_register_divider_table(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
-		u8 clk_divider_flags, const struct clk_div_table *table,
+		u16 clk_divider_flags, const struct clk_div_table *table,
 		spinlock_t *lock);
 /**
  * clk_register_divider - register a divider clock with the clock framework

-- 
2.45.2


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

* [PATCH v3 6/9] clk: eyeq: add driver
  2024-06-20 17:30 [PATCH v3 0/9] Add Mobileye EyeQ system controller support (clk, reset, pinctrl) Théo Lebrun
                   ` (4 preceding siblings ...)
  2024-06-20 17:30 ` [PATCH v3 5/9] clk: divider: Introduce CLK_DIVIDER_EVEN_INTEGERS flag Théo Lebrun
@ 2024-06-20 17:30 ` Théo Lebrun
  2024-06-20 17:30 ` [PATCH v3 7/9] reset: eyeq: add platform driver Théo Lebrun
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Théo Lebrun @ 2024-06-20 17:30 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michael Turquette,
	Stephen Boyd, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Rafael J. Wysocki, Lee Jones, Thomas Bogendoerfer
  Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
	Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
	Tawfik Bayouk, Théo Lebrun

Add Mobileye EyeQ5, EyeQ6L and EyeQ6H clock controller driver. It is
both a platform driver and a hook onto of_clk_init() used for clocks
required early (GIC timer, UARTs).

For some compatible, it is both at the same time. eqc_init() initialises
early PLLs and stores clock array in a static linked list. It marks
other clocks as deferred. eqc_probe() retrieves the clock array and
adds all remaining clocks.

It exposes read-only PLLs derived from the main crystal on board. It
also exposes another type of clocks: divider clocks. They always have
even divisors and have one PLL as parent.

This driver also bears the responsability for optional reset and pinctrl
auxiliary devices. The match data attached to the devicetree node
compatible indicate if such devices should be created. They all get
passed a pointer to the start of the OLB region.

Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
---
 MAINTAINERS            |   1 +
 drivers/clk/Kconfig    |  12 +
 drivers/clk/Makefile   |   1 +
 drivers/clk/clk-eyeq.c | 789 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 803 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index fcc9f4364a5d..f386e9da2cd0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14930,6 +14930,7 @@ F:	Documentation/devicetree/bindings/soc/mobileye/
 F:	arch/mips/boot/dts/mobileye/
 F:	arch/mips/configs/eyeq5_defconfig
 F:	arch/mips/mobileye/board-epm5.its.S
+F:	drivers/clk/clk-eyeq5.c
 F:	include/dt-bindings/clock/mobileye,eyeq5-clk.h
 
 MODULE SUPPORT
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 50af5fc7f570..c29615eec4af 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -218,6 +218,18 @@ config COMMON_CLK_EN7523
 	  This driver provides the fixed clocks and gates present on Airoha
 	  ARM silicon.
 
+config COMMON_CLK_EYEQ
+	bool "Clock driver for the Mobileye EyeQ platform"
+	depends on OF || COMPILE_TEST
+	depends on MACH_EYEQ5 || MACH_EYEQ6H || COMPILE_TEST
+	select AUXILIARY_BUS
+	default MACH_EYEQ5 || MACH_EYEQ6H
+	help
+	  This driver provides clocks found on Mobileye EyeQ5, EyeQ6L and Eye6H
+	  SoCs. Controllers live in shared register regions called OLB. Driver
+	  provides read-only PLLs, derived from the main crystal clock (which
+	  must be constant). It also exposes some divider clocks.
+
 config COMMON_CLK_FSL_FLEXSPI
 	tristate "Clock driver for FlexSPI on Layerscape SoCs"
 	depends on ARCH_LAYERSCAPE || COMPILE_TEST
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 14fa8d4ecc1f..52de92309aa8 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_ARCH_CLPS711X)		+= clk-clps711x.o
 obj-$(CONFIG_COMMON_CLK_CS2000_CP)	+= clk-cs2000-cp.o
 obj-$(CONFIG_ARCH_SPARX5)		+= clk-sparx5.o
 obj-$(CONFIG_COMMON_CLK_EN7523)		+= clk-en7523.o
+obj-$(CONFIG_COMMON_CLK_EYEQ)		+= clk-eyeq.o
 obj-$(CONFIG_COMMON_CLK_FIXED_MMIO)	+= clk-fixed-mmio.o
 obj-$(CONFIG_COMMON_CLK_FSL_FLEXSPI)	+= clk-fsl-flexspi.o
 obj-$(CONFIG_COMMON_CLK_FSL_SAI)	+= clk-fsl-sai.o
diff --git a/drivers/clk/clk-eyeq.c b/drivers/clk/clk-eyeq.c
new file mode 100644
index 000000000000..5b5b11a4edb2
--- /dev/null
+++ b/drivers/clk/clk-eyeq.c
@@ -0,0 +1,789 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * PLL clock driver for the Mobileye EyeQ5, EyeQ6L and EyeQ6H platforms.
+ *
+ * This controller handles read-only PLLs, all derived from the same main
+ * crystal clock. It also exposes divider clocks, those are children to PLLs.
+ * Parent clock is expected to be constant. This driver's registers live in
+ * a shared region called OLB. Some PLLs are initialised early by of_clk_init().
+ *
+ * We use eqc_ as prefix, as-in "EyeQ Clock", but way shorter.
+ *
+ * Copyright (C) 2024 Mobileye Vision Technologies Ltd.
+ */
+
+/*
+ * Set pr_fmt() for printing from eqc_init().
+ * It is called at of_clk_init() stage (read: really early).
+ */
+#define pr_fmt(fmt) "clk-eyeq: " fmt
+
+#include <linux/array_size.h>
+#include <linux/auxiliary_bus.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/overflow.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <dt-bindings/clock/mobileye,eyeq5-clk.h>
+
+#define EQC_MAX_DIV_COUNT		4
+
+/* In frac mode, it enables fractional noise canceling DAC. Else, no function. */
+#define PCSR0_DAC_EN			BIT(0)
+/* Fractional or integer mode */
+#define PCSR0_DSM_EN			BIT(1)
+#define PCSR0_PLL_EN			BIT(2)
+/* All clocks output held at 0 */
+#define PCSR0_FOUTPOSTDIV_EN		BIT(3)
+#define PCSR0_POST_DIV1			GENMASK(6, 4)
+#define PCSR0_POST_DIV2			GENMASK(9, 7)
+#define PCSR0_REF_DIV			GENMASK(15, 10)
+#define PCSR0_INTIN			GENMASK(27, 16)
+#define PCSR0_BYPASS			BIT(28)
+/* Bits 30..29 are reserved */
+#define PCSR0_PLL_LOCKED		BIT(31)
+
+#define PCSR1_RESET			BIT(0)
+#define PCSR1_SSGC_DIV			GENMASK(4, 1)
+/* Spread amplitude (% = 0.1 * SPREAD[4:0]) */
+#define PCSR1_SPREAD			GENMASK(9, 5)
+#define PCSR1_DIS_SSCG			BIT(10)
+/* Down-spread or center-spread */
+#define PCSR1_DOWN_SPREAD		BIT(11)
+#define PCSR1_FRAC_IN			GENMASK(31, 12)
+
+/*
+ * Driver might register clock provider from eqc_init() if PLLs are required
+ * early (before platform bus is ready). Store struct eqc_priv inside linked
+ * list to pass clock provider from eqc_init() to eqc_probe() and register
+ * remaining clocks from platform device probe.
+ *
+ * Clock provider is NOT created by eqc_init() if no early clock is required.
+ * Store as linked list because EyeQ6H has multiple clock controller instances.
+ * Matching is done based on devicetree node pointer.
+ */
+static DEFINE_SPINLOCK(eqc_list_slock);
+static LIST_HEAD(eqc_list);
+
+struct eqc_pll {
+	unsigned int	index;
+	const char	*name;
+	unsigned int	reg64;
+};
+
+/*
+ * Divider clock. Divider is 2*(v+1), with v the register value.
+ * Min divider is 2, max is 2*(2^width).
+ */
+struct eqc_div {
+	unsigned int	index;
+	const char	*name;
+	unsigned int	parent;
+	unsigned int	reg;
+	u8		shift;
+	u8		width;
+};
+
+struct eqc_match_data {
+	unsigned int		pll_count;
+	const struct eqc_pll	*plls;
+
+	unsigned int		div_count;
+	const struct eqc_div	*divs;
+
+	const char		*reset_auxdev_name;
+	const char		*pinctrl_auxdev_name;
+};
+
+struct eqc_early_match_data {
+	unsigned int		early_pll_count;
+	const struct eqc_pll	*early_plls;
+	/* Information required to init properly clk HW cells. */
+	unsigned int		nb_late_clks;
+};
+
+struct eqc_priv {
+	struct clk_hw_onecell_data	*cells;
+	const struct eqc_early_match_data *early_data;
+	const struct eqc_match_data	*data;
+	void __iomem			*base;
+	struct device_node		*np;
+	struct list_head		list;
+};
+
+/*
+ * Both factors (mult and div) must fit in 32 bits. When an operation overflows,
+ * this function throws away low bits so that factors still fit in 32 bits.
+ *
+ * Precision loss depends on amplitude of mult and div. Worst theorical
+ * loss is: (UINT_MAX+1) / UINT_MAX - 1 = 2.3e-10.
+ * This is 1Hz every 4.3GHz.
+ */
+static void eqc_pll_downshift_factors(unsigned long *mult, unsigned long *div)
+{
+	unsigned long biggest;
+	unsigned int shift;
+
+	/* This function can be removed if mult/div switch to unsigned long. */
+	static_assert(sizeof_field(struct clk_fixed_factor, mult) == sizeof(unsigned int));
+	static_assert(sizeof_field(struct clk_fixed_factor, div) == sizeof(unsigned int));
+
+	/* No overflow, nothing to be done. */
+	if (*mult <= UINT_MAX && *div <= UINT_MAX)
+		return;
+
+	/*
+	 * Compute the shift required to bring the biggest factor into unsigned
+	 * int range. That is, shift its highest set bit to the unsigned int
+	 * most significant bit.
+	 */
+	biggest = max(*mult, *div);
+	shift = __fls(biggest) - (BITS_PER_BYTE * sizeof(unsigned int)) + 1;
+
+	*mult >>= shift;
+	*div >>= shift;
+}
+
+static int eqc_pll_parse_registers(u32 r0, u32 r1, unsigned long *mult,
+				   unsigned long *div, unsigned long *acc)
+{
+	if (r0 & PCSR0_BYPASS) {
+		*mult = 1;
+		*div = 1;
+		*acc = 0;
+		return 0;
+	}
+
+	if (!(r0 & PCSR0_PLL_LOCKED))
+		return -EINVAL;
+
+	*mult = FIELD_GET(PCSR0_INTIN, r0);
+	*div = FIELD_GET(PCSR0_REF_DIV, r0);
+	if (r0 & PCSR0_FOUTPOSTDIV_EN)
+		*div *= FIELD_GET(PCSR0_POST_DIV1, r0) * FIELD_GET(PCSR0_POST_DIV2, r0);
+
+	/* Fractional mode, in 2^20 (0x100000) parts. */
+	if (r0 & PCSR0_DSM_EN) {
+		*div *= 0x100000;
+		*mult = *mult * 0x100000 + FIELD_GET(PCSR1_FRAC_IN, r1);
+	}
+
+	if (!*mult || !*div)
+		return -EINVAL;
+
+	/* Spread spectrum. */
+	if (!(r1 & (PCSR1_RESET | PCSR1_DIS_SSCG))) {
+		/*
+		 * Spread is 1/1000 parts of frequency, accuracy is half of
+		 * that. To get accuracy, convert to ppb (parts per billion).
+		 */
+		u32 spread = FIELD_GET(PCSR1_SPREAD, r1);
+
+		*acc = spread * 500000;
+		if (r1 & PCSR1_DOWN_SPREAD) {
+			/*
+			 * Downspreading: the central frequency is half a
+			 * spread lower.
+			 */
+			*mult *= 2000 - spread;
+			*div *= 2000;
+
+			/*
+			 * Previous operation might overflow 32 bits. If it
+			 * does, throw away the least amount of low bits.
+			 */
+			eqc_pll_downshift_factors(mult, div);
+		}
+	} else {
+		*acc = 0;
+	}
+
+	return 0;
+}
+
+static unsigned int eqc_compute_clock_count(const struct eqc_early_match_data *early_data,
+					    const struct eqc_match_data *data)
+{
+	unsigned int i, nb_clks = 0, sum = 0;
+
+	if (early_data) {
+		sum += early_data->early_pll_count;
+
+		for (i = 0; i < early_data->early_pll_count; i++)
+			if (early_data->early_plls[i].index >= nb_clks)
+				nb_clks = early_data->early_plls[i].index + 1;
+	}
+
+	if (data) {
+		sum += data->pll_count + data->div_count;
+
+		for (i = 0; i < data->pll_count; i++)
+			if (data->plls[i].index >= nb_clks)
+				nb_clks = data->plls[i].index + 1;
+
+		for (i = 0; i < data->div_count; i++)
+			if (data->divs[i].index >= nb_clks)
+				nb_clks = data->divs[i].index + 1;
+	}
+
+	/* We expect the biggest clock index to be 1 below the clock count. */
+	WARN_ON(nb_clks != sum);
+
+	return nb_clks;
+}
+
+static void eqc_probe_init_plls(struct device *dev, struct eqc_priv *priv)
+{
+	const struct eqc_match_data *data = priv->data;
+	unsigned long mult, div, acc;
+	const struct eqc_pll *pll;
+	struct clk_hw *hw;
+	unsigned int i;
+	u32 r0, r1;
+	u64 val;
+	int ret;
+
+	for (i = 0; i < data->pll_count; i++) {
+		pll = &data->plls[i];
+
+		val = readq(priv->base + pll->reg64);
+		r0 = val;
+		r1 = val >> 32;
+
+		ret = eqc_pll_parse_registers(r0, r1, &mult, &div, &acc);
+		if (ret) {
+			dev_warn(dev, "failed parsing state of %s\n", pll->name);
+			priv->cells->hws[pll->index] = ERR_PTR(ret);
+			continue;
+		}
+
+		hw = clk_hw_register_fixed_factor_with_accuracy_fwname(dev,
+				dev->of_node, pll->name, "ref", 0, mult, div, acc);
+		priv->cells->hws[pll->index] = hw;
+		if (IS_ERR(hw))
+			dev_warn(dev, "failed registering %s: %pe\n", pll->name, hw);
+	}
+}
+
+static void eqc_probe_init_divs(struct platform_device *pdev, struct device *dev,
+				struct eqc_priv *priv)
+{
+	const struct eqc_match_data *data = priv->data;
+	const struct eqc_div *div;
+	struct clk_hw *parent;
+	void __iomem *reg;
+	struct clk_hw *hw;
+	unsigned int i;
+
+	for (i = 0; i < data->div_count; i++) {
+		div = &data->divs[i];
+		reg = priv->base + div->reg;
+		parent = priv->cells->hws[div->parent];
+
+		hw = clk_hw_register_divider_table_parent_hw(dev, div->name,
+				parent, 0, reg, div->shift, div->width,
+				CLK_DIVIDER_EVEN_INTEGERS, NULL, NULL);
+		priv->cells->hws[div->index] = hw;
+		if (IS_ERR(hw))
+			dev_warn(dev, "failed registering %s: %pe\n",
+				 div->name, hw);
+	}
+}
+
+static void eqc_auxdev_release(struct device *dev)
+{
+	struct auxiliary_device *adev = to_auxiliary_dev(dev);
+
+	kfree(adev);
+}
+
+static void eqc_auxdev_unregister(void *arg)
+{
+	struct auxiliary_device *adev = arg;
+
+	auxiliary_device_delete(adev);
+	auxiliary_device_uninit(adev);
+}
+
+static int eqc_auxdev_create(struct device *dev, void __iomem *base,
+			     const char *name, u32 id)
+{
+	struct auxiliary_device *adev;
+	int ret;
+
+	adev = kzalloc(sizeof(*adev), GFP_KERNEL);
+	if (!adev)
+		return -ENOMEM;
+
+	adev->name = name;
+	adev->dev.parent = dev;
+	adev->dev.platform_data = base;
+	adev->dev.release = eqc_auxdev_release;
+	adev->id = id;
+
+	ret = auxiliary_device_init(adev);
+	if (ret)
+		return ret;
+
+	ret = auxiliary_device_add(adev);
+	if (ret) {
+		auxiliary_device_uninit(adev);
+		return ret;
+	}
+
+	return devm_add_action_or_reset(dev, eqc_auxdev_unregister, adev);
+}
+
+static int eqc_probe(struct platform_device *pdev)
+{
+	const struct eqc_match_data *data;
+	struct device *dev = &pdev->dev;
+	struct eqc_priv *priv = NULL;
+	struct eqc_priv *entry;
+	unsigned int nb_clks;
+	void __iomem *base;
+	int ret;
+
+	data = device_get_match_data(dev);
+	if (!data)
+		return 0; /* No clocks nor auxdevs, we are done. */
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	/* Init optional reset auxiliary device. */
+	if (data->reset_auxdev_name) {
+		ret = eqc_auxdev_create(dev, base, data->reset_auxdev_name, 0);
+		if (ret)
+			dev_warn(dev, "failed creating auxiliary device %s.%s: %d\n",
+				 KBUILD_MODNAME, data->reset_auxdev_name, ret);
+	}
+
+	/* Init optional pinctrl auxiliary device. */
+	if (data->pinctrl_auxdev_name) {
+		ret = eqc_auxdev_create(dev, base, data->pinctrl_auxdev_name, 0);
+		if (ret)
+			dev_warn(dev, "failed creating auxiliary device %s.%s: %d\n",
+				 KBUILD_MODNAME, data->pinctrl_auxdev_name, ret);
+	}
+
+	if (data->pll_count + data->div_count == 0)
+		return 0; /* Zero clocks, we are done. */
+
+	/* Try retrieving early init private data. */
+	spin_lock(&eqc_list_slock);
+	list_for_each_entry(entry, &eqc_list, list) {
+		if (entry->np == dev->of_node) {
+			priv = entry;
+			break;
+		}
+	}
+	spin_unlock(&eqc_list_slock);
+
+	if (!priv) {
+		/* Device did not get init early. Do it now. */
+
+		priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+		if (!priv)
+			return -ENOMEM;
+
+		priv->np = dev->of_node;
+
+		nb_clks = eqc_compute_clock_count(NULL, data);
+		priv->cells = devm_kzalloc(dev, struct_size(priv->cells, hws, nb_clks),
+					   GFP_KERNEL);
+		if (!priv->cells)
+			return -ENOMEM;
+
+		priv->cells->num = nb_clks;
+	} else {
+		/*
+		 * Device got init early. Check clock count.
+		 *
+		 * eqc_init() should already know the exact clk count using
+		 * nb_late_clks field. We ensure computation was right and fix
+		 * clk cells if not.
+		 */
+		nb_clks = eqc_compute_clock_count(priv->early_data, data);
+		if (WARN_ON(nb_clks != priv->cells->num))
+			priv->cells->num = nb_clks;
+	}
+
+	priv->base = base;
+	priv->data = data;
+
+	eqc_probe_init_plls(dev, priv);
+
+	eqc_probe_init_divs(pdev, dev, priv);
+
+	/* Clock provider has not been registered by eqc_init(). Do it now. */
+	if (!priv->early_data) {
+		/* When providing a single clock, require no cell. */
+		if (priv->cells->num == 1)
+			ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
+							  priv->cells->hws[0]);
+		else
+			ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+							  priv->cells);
+
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct eqc_pll eqc_eyeq5_plls[] = {
+	{ .index = EQ5C_PLL_VMP,  .name = "pll-vmp",  .reg64 = 0x034 },
+	{ .index = EQ5C_PLL_PMA,  .name = "pll-pma",  .reg64 = 0x03C },
+	{ .index = EQ5C_PLL_VDI,  .name = "pll-vdi",  .reg64 = 0x044 },
+	{ .index = EQ5C_PLL_DDR0, .name = "pll-ddr0", .reg64 = 0x04C },
+	{ .index = EQ5C_PLL_PCI,  .name = "pll-pci",  .reg64 = 0x054 },
+	{ .index = EQ5C_PLL_PMAC, .name = "pll-pmac", .reg64 = 0x064 },
+	{ .index = EQ5C_PLL_MPC,  .name = "pll-mpc",  .reg64 = 0x06C },
+	{ .index = EQ5C_PLL_DDR1, .name = "pll-ddr1", .reg64 = 0x074 },
+};
+
+static const struct eqc_div eqc_eyeq5_divs[] = {
+	{
+		.index = EQ5C_DIV_OSPI,
+		.name = "div-ospi",
+		.parent = EQ5C_PLL_PER,
+		.reg = 0x11C,
+		.shift = 0,
+		.width = 4,
+	},
+};
+
+static const struct eqc_match_data eqc_eyeq5_match_data = {
+	.pll_count	= ARRAY_SIZE(eqc_eyeq5_plls),
+	.plls		= eqc_eyeq5_plls,
+
+	.div_count	= ARRAY_SIZE(eqc_eyeq5_divs),
+	.divs		= eqc_eyeq5_divs,
+
+	.reset_auxdev_name = "reset",
+	.pinctrl_auxdev_name = "pinctrl",
+};
+
+static const struct eqc_pll eqc_eyeq6l_plls[] = {
+	{ .index = EQ6LC_PLL_DDR, .name = "pll-ddr", .reg64 = 0x02C },
+	{ .index = EQ6LC_PLL_CPU, .name = "pll-cpu", .reg64 = 0x034 }, /* also acc */
+	{ .index = EQ6LC_PLL_PER, .name = "pll-per", .reg64 = 0x03C },
+	{ .index = EQ6LC_PLL_VDI, .name = "pll-vdi", .reg64 = 0x044 },
+};
+
+static const struct eqc_match_data eqc_eyeq6l_match_data = {
+	.pll_count	= ARRAY_SIZE(eqc_eyeq6l_plls),
+	.plls		= eqc_eyeq6l_plls,
+
+	.reset_auxdev_name = "reset",
+};
+
+static const struct eqc_match_data eqc_eyeq6h_west_match_data = {
+	.reset_auxdev_name = "reset_west",
+};
+
+static const struct eqc_pll eqc_eyeq6h_east_plls[] = {
+	{ .index = 0, .name = "pll-east", .reg64 = 0x074 },
+};
+
+static const struct eqc_match_data eqc_eyeq6h_east_match_data = {
+	.pll_count	= ARRAY_SIZE(eqc_eyeq6h_east_plls),
+	.plls		= eqc_eyeq6h_east_plls,
+
+	.reset_auxdev_name = "reset_east",
+};
+
+static const struct eqc_pll eqc_eyeq6h_south_plls[] = {
+	{ .index = EQ6HC_SOUTH_PLL_VDI,  .name = "pll-vdi",  .reg64 = 0x000 },
+	{ .index = EQ6HC_SOUTH_PLL_PCIE, .name = "pll-pcie", .reg64 = 0x008 },
+	{ .index = EQ6HC_SOUTH_PLL_PER,  .name = "pll-per",  .reg64 = 0x010 },
+	{ .index = EQ6HC_SOUTH_PLL_ISP,  .name = "pll-isp",  .reg64 = 0x018 },
+};
+
+static const struct eqc_div eqc_eyeq6h_south_divs[] = {
+	{
+		.index = EQ6HC_SOUTH_DIV_EMMC,
+		.name = "div-emmc",
+		.parent = EQ6HC_SOUTH_PLL_PER,
+		.reg = 0x070,
+		.shift = 4,
+		.width = 4,
+	},
+	{
+		.index = EQ6HC_SOUTH_DIV_OSPI_REF,
+		.name = "div-ospi-ref",
+		.parent = EQ6HC_SOUTH_PLL_PER,
+		.reg = 0x090,
+		.shift = 4,
+		.width = 4,
+	},
+	{
+		.index = EQ6HC_SOUTH_DIV_OSPI_SYS,
+		.name = "div-ospi-sys",
+		.parent = EQ6HC_SOUTH_PLL_PER,
+		.reg = 0x090,
+		.shift = 8,
+		.width = 1,
+	},
+	{
+		.index = EQ6HC_SOUTH_DIV_TSU,
+		.name = "div-tsu",
+		.parent = EQ6HC_SOUTH_PLL_PCIE,
+		.reg = 0x098,
+		.shift = 4,
+		.width = 8,
+	},
+};
+
+static const struct eqc_match_data eqc_eyeq6h_south_match_data = {
+	.pll_count	= ARRAY_SIZE(eqc_eyeq6h_south_plls),
+	.plls		= eqc_eyeq6h_south_plls,
+
+	.div_count	= ARRAY_SIZE(eqc_eyeq6h_south_divs),
+	.divs		= eqc_eyeq6h_south_divs,
+};
+
+static const struct eqc_pll eqc_eyeq6h_ddr0_plls[] = {
+	{ .index = 0, .name = "pll-ddr0", .reg64 = 0x074 },
+};
+
+static const struct eqc_match_data eqc_eyeq6h_ddr0_match_data = {
+	.pll_count	= ARRAY_SIZE(eqc_eyeq6h_ddr0_plls),
+	.plls		= eqc_eyeq6h_ddr0_plls,
+};
+
+static const struct eqc_pll eqc_eyeq6h_ddr1_plls[] = {
+	{ .index = 0, .name = "pll-ddr1", .reg64 = 0x074 },
+};
+
+static const struct eqc_match_data eqc_eyeq6h_ddr1_match_data = {
+	.pll_count	= ARRAY_SIZE(eqc_eyeq6h_ddr1_plls),
+	.plls		= eqc_eyeq6h_ddr1_plls,
+};
+
+static const struct eqc_pll eqc_eyeq6h_acc_plls[] = {
+	{ .index = EQ6HC_ACC_PLL_XNN, .name = "pll-xnn", .reg64 = 0x040 },
+	{ .index = EQ6HC_ACC_PLL_VMP, .name = "pll-vmp", .reg64 = 0x050 },
+	{ .index = EQ6HC_ACC_PLL_PMA, .name = "pll-pma", .reg64 = 0x05C },
+	{ .index = EQ6HC_ACC_PLL_MPC, .name = "pll-mpc", .reg64 = 0x068 },
+	{ .index = EQ6HC_ACC_PLL_NOC, .name = "pll-noc", .reg64 = 0x070 },
+};
+
+static const struct eqc_match_data eqc_eyeq6h_acc_match_data = {
+	.pll_count	= ARRAY_SIZE(eqc_eyeq6h_acc_plls),
+	.plls		= eqc_eyeq6h_acc_plls,
+
+	.reset_auxdev_name = "reset_acc",
+};
+
+static const struct of_device_id eqc_match_table[] = {
+	{ .compatible = "mobileye,eyeq5-olb", .data = &eqc_eyeq5_match_data },
+	{ .compatible = "mobileye,eyeq6l-olb", .data = &eqc_eyeq6l_match_data },
+	{ .compatible = "mobileye,eyeq6h-west-olb", .data = &eqc_eyeq6h_west_match_data },
+	{ .compatible = "mobileye,eyeq6h-east-olb", .data = &eqc_eyeq6h_east_match_data },
+	{ .compatible = "mobileye,eyeq6h-south-olb", .data = &eqc_eyeq6h_south_match_data },
+	{ .compatible = "mobileye,eyeq6h-ddr0-olb", .data = &eqc_eyeq6h_ddr0_match_data },
+	{ .compatible = "mobileye,eyeq6h-ddr1-olb", .data = &eqc_eyeq6h_ddr1_match_data },
+	{ .compatible = "mobileye,eyeq6h-acc-olb", .data = &eqc_eyeq6h_acc_match_data },
+	{}
+};
+MODULE_DEVICE_TABLE(of, eqc_match_table);
+
+static struct platform_driver eqc_driver = {
+	.probe = eqc_probe,
+	.driver = {
+		.name = "clk-eyeq",
+		.of_match_table = eqc_match_table,
+	},
+};
+builtin_platform_driver(eqc_driver);
+
+/* Required early for GIC timer (pll-cpu) and UARTs (pll-per). */
+static const struct eqc_pll eqc_eyeq5_early_plls[] = {
+	{ .index = EQ5C_PLL_CPU, .name = "pll-cpu",  .reg64 = 0x02C },
+	{ .index = EQ5C_PLL_PER, .name = "pll-per",  .reg64 = 0x05C },
+};
+
+static const struct eqc_early_match_data eqc_eyeq5_early_match_data = {
+	.early_pll_count	= ARRAY_SIZE(eqc_eyeq5_early_plls),
+	.early_plls		= eqc_eyeq5_early_plls,
+	.nb_late_clks = eqc_eyeq5_match_data.pll_count + eqc_eyeq5_match_data.div_count,
+};
+
+/* Required early for GIC timer. */
+static const struct eqc_pll eqc_eyeq6h_central_early_plls[] = {
+	{ .index = 0, .name = "pll-cpu", .reg64 = 0x02C },
+};
+
+static const struct eqc_early_match_data eqc_eyeq6h_central_early_match_data = {
+	.early_pll_count	= ARRAY_SIZE(eqc_eyeq6h_central_early_plls),
+	.early_plls		= eqc_eyeq6h_central_early_plls,
+	.nb_late_clks = 0,
+};
+
+/* Required early for UART. */
+static const struct eqc_pll eqc_eyeq6h_west_early_plls[] = {
+	{ .index = 0, .name = "pll-west", .reg64 = 0x074 },
+};
+
+static const struct eqc_early_match_data eqc_eyeq6h_west_early_match_data = {
+	.early_pll_count	= ARRAY_SIZE(eqc_eyeq6h_west_early_plls),
+	.early_plls		= eqc_eyeq6h_west_early_plls,
+	.nb_late_clks = 0,
+};
+
+static const struct of_device_id eqc_early_match_table[] = {
+	{
+		.compatible = "mobileye,eyeq5-olb",
+		.data = &eqc_eyeq5_early_match_data,
+	},
+	{
+		.compatible = "mobileye,eyeq6h-central-olb",
+		.data = &eqc_eyeq6h_central_early_match_data,
+	},
+	{
+		.compatible = "mobileye,eyeq6h-west-olb",
+		.data = &eqc_eyeq6h_west_early_match_data,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, eqc_early_match_table);
+
+static void __init eqc_init(struct device_node *np)
+{
+	const struct eqc_early_match_data *early_data;
+	unsigned int nb_clks = 0;
+	struct eqc_priv *priv;
+	void __iomem *base;
+	unsigned int i;
+	int ret;
+
+	early_data = of_match_node(eqc_early_match_table, np)->data;
+
+	/* No reason to early init this clock provider. Delay until probe. */
+	if (!early_data || early_data->early_pll_count == 0)
+		return;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	priv->np = np;
+	priv->early_data = early_data;
+
+	nb_clks = early_data->early_pll_count + early_data->nb_late_clks;
+	priv->cells = kzalloc(struct_size(priv->cells, hws, nb_clks), GFP_KERNEL);
+	if (!priv->cells) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	priv->cells->num = nb_clks;
+
+	/*
+	 * Mark all clocks as deferred; some are registered here, the rest at
+	 * platform device probe.
+	 */
+	for (i = 0; i < nb_clks; i++)
+		priv->cells->hws[i] = ERR_PTR(-EPROBE_DEFER);
+
+	/* Offsets (reg64) of early PLLs are relative to OLB block. */
+	base = of_iomap(np, 0);
+	if (!base) {
+		ret = -ENODEV;
+		goto err;
+	}
+
+	for (i = 0; i < early_data->early_pll_count; i++) {
+		const struct eqc_pll *pll = &early_data->early_plls[i];
+		unsigned long mult, div, acc;
+		struct clk_hw *hw;
+		u32 r0, r1;
+		u64 val;
+
+		val = readq(base + pll->reg64);
+		r0 = val;
+		r1 = val >> 32;
+
+		ret = eqc_pll_parse_registers(r0, r1, &mult, &div, &acc);
+		if (ret) {
+			pr_err("failed parsing state of %s\n", pll->name);
+			goto err;
+		}
+
+		hw = clk_hw_register_fixed_factor_with_accuracy_fwname(NULL,
+				np, pll->name, "ref", 0, mult, div, acc);
+		priv->cells->hws[pll->index] = hw;
+		if (IS_ERR(hw)) {
+			pr_err("failed registering %s: %pe\n", pll->name, hw);
+			ret = PTR_ERR(hw);
+			goto err;
+		}
+	}
+
+	/* When providing a single clock, require no cell. */
+	if (nb_clks == 1)
+		ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, priv->cells->hws[0]);
+	else
+		ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, priv->cells);
+	if (ret) {
+		pr_err("failed registering clk provider: %d\n", ret);
+		goto err;
+	}
+
+	spin_lock(&eqc_list_slock);
+	list_add_tail(&priv->list, &eqc_list);
+	spin_unlock(&eqc_list_slock);
+
+	return;
+
+err:
+	/*
+	 * We are doomed. The system will not be able to boot.
+	 *
+	 * Let's still try to be good citizens by freeing resources and print
+	 * a last error message that might help debugging.
+	 */
+
+	if (priv && priv->cells) {
+		of_clk_del_provider(np);
+
+		for (i = 0; i < early_data->early_pll_count; i++) {
+			const struct eqc_pll *pll = &early_data->early_plls[i];
+			struct clk_hw *hw = priv->cells->hws[pll->index];
+
+			if (!IS_ERR_OR_NULL(hw))
+				clk_hw_unregister_fixed_factor(hw);
+		}
+
+		kfree(priv->cells);
+	}
+
+	kfree(priv);
+
+	pr_err("failed clk init: %d\n", ret);
+}
+
+CLK_OF_DECLARE_DRIVER(eqc_eyeq5, "mobileye,eyeq5-olb", eqc_init);
+CLK_OF_DECLARE_DRIVER(eqc_eyeq6h_central, "mobileye,eyeq6h-central-olb", eqc_init);
+CLK_OF_DECLARE_DRIVER(eqc_eyeq6h_west, "mobileye,eyeq6h-west-olb", eqc_init);

-- 
2.45.2


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

* [PATCH v3 7/9] reset: eyeq: add platform driver
  2024-06-20 17:30 [PATCH v3 0/9] Add Mobileye EyeQ system controller support (clk, reset, pinctrl) Théo Lebrun
                   ` (5 preceding siblings ...)
  2024-06-20 17:30 ` [PATCH v3 6/9] clk: eyeq: add driver Théo Lebrun
@ 2024-06-20 17:30 ` Théo Lebrun
  2024-06-25  9:17   ` Philipp Zabel
  2024-06-20 17:31 ` [PATCH v3 8/9] pinctrl: eyeq5: " Théo Lebrun
  2024-06-20 17:31 ` [PATCH v3 9/9] MIPS: mobileye: eyeq5: add OLB system-controller node Théo Lebrun
  8 siblings, 1 reply; 21+ messages in thread
From: Théo Lebrun @ 2024-06-20 17:30 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michael Turquette,
	Stephen Boyd, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Rafael J. Wysocki, Lee Jones, Thomas Bogendoerfer
  Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
	Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
	Tawfik Bayouk, Théo Lebrun

Add Mobileye EyeQ reset controller driver, for EyeQ5, EyeQ6L and EyeQ6H
SoCs. Instances belong to a shared register region called OLB and gets
spawned as auxiliary device to the platform driver for clock.

There is one OLB instance for EyeQ5 and EyeQ6L. There are seven OLB
instances on EyeQ6H; three have a reset controller embedded:
 - West and east get handled by the same compatible.
 - Acc (accelerator) is another one.

Each instance vary in the number and types of reset domains.
Instances with single domain expect a single cell, others two.

Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
---
 MAINTAINERS                |   1 +
 drivers/reset/Kconfig      |  14 ++
 drivers/reset/Makefile     |   1 +
 drivers/reset/reset-eyeq.c | 563 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 579 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index f386e9da2cd0..36f4001c7f51 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14931,6 +14931,7 @@ F:	arch/mips/boot/dts/mobileye/
 F:	arch/mips/configs/eyeq5_defconfig
 F:	arch/mips/mobileye/board-epm5.its.S
 F:	drivers/clk/clk-eyeq5.c
+F:	drivers/reset/reset-eyeq5.c
 F:	include/dt-bindings/clock/mobileye,eyeq5-clk.h
 
 MODULE SUPPORT
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 85b27c42cf65..b79c18b75674 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -66,6 +66,20 @@ config RESET_BRCMSTB_RESCAL
 	  This enables the RESCAL reset controller for SATA, PCIe0, or PCIe1 on
 	  BCM7216.
 
+config RESET_EYEQ
+	bool "Mobileye EyeQ reset controller"
+	depends on COMMON_CLK_EYEQ
+	depends on MFD_SYSCON
+	depends on MACH_EYEQ5 || MACH_EYEQ6H || COMPILE_TEST
+	default MACH_EYEQ5 || MACH_EYEQ6H
+	help
+	  This enables the Mobileye EyeQ reset controller, used in EyeQ5, EyeQ6L
+	  and EyeQ6H SoCs.
+
+	  It has one or more domains, with a varying number of resets in each.
+	  Registers are located in a shared register region called OLB. EyeQ6H
+	  has multiple reset instances.
+
 config RESET_GPIO
 	tristate "GPIO reset controller"
 	help
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index fd8b49fa46fc..a4e6fea29800 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o
 obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
 obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o
 obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o
+obj-$(CONFIG_RESET_EYEQ) += reset-eyeq.o
 obj-$(CONFIG_RESET_GPIO) += reset-gpio.o
 obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
 obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
diff --git a/drivers/reset/reset-eyeq.c b/drivers/reset/reset-eyeq.c
new file mode 100644
index 000000000000..03a3f2d06cff
--- /dev/null
+++ b/drivers/reset/reset-eyeq.c
@@ -0,0 +1,563 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Reset driver for the Mobileye EyeQ5, EyeQ6L and EyeQ6H platforms.
+ *
+ * Controllers live in a shared register region called OLB. EyeQ5 and EyeQ6L
+ * have a single OLB instance for a single reset controller. EyeQ6H has seven
+ * OLB instances; three host reset controllers.
+ *
+ * Each reset controller has one or more domain. Domains are of a given type
+ * (see enum eqr_domain_type), with a valid offset mask (up to 32 resets per
+ * domain).
+ *
+ * Domain types define expected behavior: one-register-per-reset,
+ * one-bit-per-reset, status detection method, busywait duration, etc.
+ *
+ * We use eqr_ as prefix, as-in "EyeQ Reset", but way shorter.
+ *
+ * Known resets in EyeQ5 domain 0 (type EQR_EYEQ5_SARCR):
+ *  3. CAN0	 4. CAN1	 5. CAN2	 6. SPI0
+ *  7. SPI1	 8. SPI2	 9. SPI3	10. UART0
+ * 11. UART1	12. UART2	13. I2C0	14. I2C1
+ * 15. I2C2	16. I2C3	17. I2C4	18. TIMER0
+ * 19. TIMER1	20. TIMER2	21. TIMER3	22. TIMER4
+ * 23. WD0	24. EXT0	25. EXT1	26. GPIO
+ * 27. WD1
+ *
+ * Known resets in EyeQ5 domain 1 (type EQR_EYEQ5_ACRP):
+ *  0. VMP0	 1. VMP1	 2. VMP2	 3. VMP3
+ *  4. PMA0	 5. PMA1	 6. PMAC0	 7. PMAC1
+ *  8. MPC0	 9. MPC1	10. MPC2	11. MPC3
+ * 12. MPC4
+ *
+ * Known resets in EyeQ5 domain 2 (type EQR_EYEQ5_PCIE):
+ *  0. PCIE0_CORE	 1. PCIE0_APB		 2. PCIE0_LINK_AXI	 3. PCIE0_LINK_MGMT
+ *  4. PCIE0_LINK_HOT	 5. PCIE0_LINK_PIPE	 6. PCIE1_CORE		 7. PCIE1_APB
+ *  8. PCIE1_LINK_AXI	 9. PCIE1_LINK_MGMT	10. PCIE1_LINK_HOT	11. PCIE1_LINK_PIPE
+ * 12. MULTIPHY		13. MULTIPHY_APB	15. PCIE0_LINK_MGMT	16. PCIE1_LINK_MGMT
+ * 17. PCIE0_LINK_PM	18. PCIE1_LINK_PM
+ *
+ * Known resets in EyeQ6L domain 0 (type EQR_EYEQ5_SARCR):
+ *  0. SPI0	 1. SPI1	 2. UART0	 3. I2C0
+ *  4. I2C1	 5. TIMER0	 6. TIMER1	 7. TIMER2
+ *  8. TIMER3	 9. WD0		10. WD1		11. EXT0
+ * 12. EXT1	13. GPIO
+ *
+ * Known resets in EyeQ6L domain 1 (type EQR_EYEQ5_ACRP):
+ *  0. VMP0	 1. VMP1	 2. VMP2	 3. VMP3
+ *  4. PMA0	 5. PMA1	 6. PMAC0	 7. PMAC1
+ *  8. MPC0	 9. MPC1	10. MPC2	11. MPC3
+ * 12. MPC4
+ *
+ * Known resets in EyeQ6H west/east (type EQR_EYEQ6H_SARCR):
+ *  0. CAN	 1. SPI0	 2. SPI1	 3. UART0
+ *  4. UART1	 5. I2C0	 6. I2C1	 7. -hole-
+ *  8. TIMER0	 9. TIMER1	10. WD		11. EXT TIMER
+ * 12. GPIO
+ *
+ * Known resets in EyeQ6H acc (type EQR_EYEQ5_ACRP):
+ *  1. XNN0	 2. XNN1	 3. XNN2	 4. XNN3
+ *  5. VMP0	 6. VMP1	 7. VMP2	 8. VMP3
+ *  9. PMA0	10. PMA1	11. MPC0	12. MPC1
+ * 13. MPC2	14. MPC3	15. PERIPH
+ *
+ * Abbreviations:
+ *  - PMA: Programmable Macro Array
+ *  - MPC: Multi-threaded Processing Clusters
+ *  - VMP: Vector Microcode Processors
+ *
+ * Copyright (C) 2024 Mobileye Vision Technologies Ltd.
+ */
+
+#include <linux/array_size.h>
+#include <linux/auxiliary_bus.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/bug.h>
+#include <linux/cleanup.h>
+#include <linux/container_of.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/lockdep.h>
+#include <linux/mod_devicetable.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+/*
+ * A reset ID, as returned by eqr_of_xlate_*(), is a (domain, offset) pair.
+ * Low byte is domain, rest is offset.
+ */
+#define ID_DOMAIN_MASK	GENMASK(7, 0)
+#define ID_OFFSET_MASK	GENMASK(31, 8)
+
+enum eqr_domain_type {
+	EQR_EYEQ5_SARCR,
+	EQR_EYEQ5_ACRP,
+	EQR_EYEQ5_PCIE,
+	EQR_EYEQ6H_SARCR,
+};
+
+/*
+ * Domain type EQR_EYEQ5_SARCR register offsets.
+ */
+#define EQR_EYEQ5_SARCR_REQUEST		(0x000)
+#define EQR_EYEQ5_SARCR_STATUS		(0x004)
+
+/*
+ * Domain type EQR_EYEQ5_ACRP register masks.
+ * Registers are: base + 4 * offset.
+ */
+#define EQR_EYEQ5_ACRP_PD_REQ		BIT(0)
+#define EQR_EYEQ5_ACRP_ST_POWER_DOWN	BIT(27)
+#define EQR_EYEQ5_ACRP_ST_ACTIVE	BIT(29)
+
+/*
+ * Domain type EQR_EYEQ6H_SARCR register offsets.
+ */
+#define EQR_EYEQ6H_SARCR_RST_REQUEST	(0x000)
+#define EQR_EYEQ6H_SARCR_CLK_STATUS	(0x004)
+#define EQR_EYEQ6H_SARCR_RST_STATUS	(0x008)
+#define EQR_EYEQ6H_SARCR_CLK_REQUEST	(0x00C)
+
+struct eqr_busy_wait_timings {
+	unsigned long sleep_us;
+	unsigned long timeout_us;
+};
+
+static const struct eqr_busy_wait_timings eqr_timings[] = {
+	[EQR_EYEQ5_SARCR]	= {1, 10},
+	[EQR_EYEQ5_ACRP]	= {1, 40 * USEC_PER_MSEC}, /* LBIST implies long timeout. */
+	/* EQR_EYEQ5_PCIE does no busy waiting. */
+	[EQR_EYEQ6H_SARCR]	= {1, 400},
+};
+
+#define EQR_MAX_DOMAIN_COUNT 3
+
+struct eqr_domain_descriptor {
+	enum eqr_domain_type	type;
+	u32			valid_mask;
+	unsigned int		offset;
+};
+
+struct eqr_match_data {
+	unsigned int				domain_count;
+	const struct eqr_domain_descriptor	*domains;
+};
+
+struct eqr_private {
+	struct mutex			mutexes[EQR_MAX_DOMAIN_COUNT];
+	void __iomem			*base;
+	const struct eqr_match_data	*data;
+	struct reset_controller_dev	rcdev;
+};
+
+#define rcdev_to_priv(rcdev) container_of(rcdev, struct eqr_private, rcdev)
+
+static u32 eqr_double_readl(void __iomem *addr_a, void __iomem *addr_b,
+			    u32 *dest_a, u32 *dest_b)
+{
+	*dest_a = readl(addr_a);
+	*dest_b = readl(addr_b);
+	return 0; /* read_poll_timeout() op argument must return something. */
+}
+
+static int eqr_busy_wait_locked(struct eqr_private *priv, struct device *dev,
+				u32 domain, u32 offset, bool assert)
+{
+	enum eqr_domain_type domain_type = priv->data->domains[domain].type;
+	unsigned long sleep_us, timeout_us;
+	u32 val, mask, val0, val1;
+	void __iomem *base, *reg;
+	int ret;
+
+	lockdep_assert_held(&priv->mutexes[domain]);
+
+	base = priv->base + priv->data->domains[domain].offset;
+	sleep_us = eqr_timings[domain_type].sleep_us;
+	timeout_us = eqr_timings[domain_type].timeout_us;
+
+	switch (domain_type) {
+	case EQR_EYEQ5_SARCR:
+		reg = base + EQR_EYEQ5_SARCR_STATUS;
+		mask = BIT(offset);
+
+		ret = readl_poll_timeout(reg, val, !(val & mask) == assert,
+					 sleep_us, timeout_us);
+		break;
+
+	case EQR_EYEQ5_ACRP:
+		reg = base + 4 * offset;
+		if (assert)
+			mask = EQR_EYEQ5_ACRP_ST_POWER_DOWN;
+		else
+			mask = EQR_EYEQ5_ACRP_ST_ACTIVE;
+
+		ret = readl_poll_timeout(reg, val, !!(val & mask),
+					 sleep_us, timeout_us);
+		break;
+
+	case EQR_EYEQ5_PCIE:
+		ret = 0; /* No busy waiting. */
+		break;
+
+	case EQR_EYEQ6H_SARCR:
+		/*
+		 * Wait until both bits change:
+		 *	readl(base + EQR_EYEQ6H_SARCR_RST_STATUS) & BIT(offset)
+		 *	readl(base + EQR_EYEQ6H_SARCR_CLK_STATUS) & BIT(offset)
+		 */
+		mask = BIT(offset);
+		ret = read_poll_timeout(eqr_double_readl, val,
+					(!(val0 & mask) == assert) &&
+						(!(val1 & mask) == assert),
+					sleep_us, timeout_us, false,
+					base + EQR_EYEQ6H_SARCR_RST_STATUS,
+					base + EQR_EYEQ6H_SARCR_CLK_STATUS,
+					&val0, &val1);
+		break;
+
+	default:
+		WARN_ON(1);
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret == -ETIMEDOUT)
+		dev_dbg(dev, "%u-%u: timeout\n", domain, offset);
+	return ret;
+}
+
+static void eqr_assert_locked(struct eqr_private *priv, u32 domain, u32 offset)
+{
+	enum eqr_domain_type domain_type = priv->data->domains[domain].type;
+	void __iomem *base, *reg;
+	u32 val;
+
+	lockdep_assert_held(&priv->mutexes[domain]);
+
+	base = priv->base + priv->data->domains[domain].offset;
+
+	switch (domain_type) {
+	case EQR_EYEQ5_SARCR:
+		reg = base + EQR_EYEQ5_SARCR_REQUEST;
+		writel(readl(reg) & ~BIT(offset), reg);
+		break;
+
+	case EQR_EYEQ5_ACRP:
+		reg = base + 4 * offset;
+		writel(readl(reg) | EQR_EYEQ5_ACRP_PD_REQ, reg);
+		break;
+
+	case EQR_EYEQ5_PCIE:
+		writel(readl(base) & ~BIT(offset), base);
+		break;
+
+	case EQR_EYEQ6H_SARCR:
+		val = readl(base + EQR_EYEQ6H_SARCR_RST_REQUEST);
+		val &= ~BIT(offset);
+		writel(val, base + EQR_EYEQ6H_SARCR_RST_REQUEST);
+		writel(val, base + EQR_EYEQ6H_SARCR_CLK_REQUEST);
+		break;
+
+	default:
+		WARN_ON(1);
+		break;
+	}
+}
+
+static int eqr_assert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	struct eqr_private *priv = rcdev_to_priv(rcdev);
+	u32 domain = FIELD_GET(ID_DOMAIN_MASK, id);
+	u32 offset = FIELD_GET(ID_OFFSET_MASK, id);
+
+	dev_dbg(rcdev->dev, "%u-%u: assert request\n", domain, offset);
+
+	guard(mutex)(&priv->mutexes[domain]);
+
+	eqr_assert_locked(priv, domain, offset);
+	return eqr_busy_wait_locked(priv, rcdev->dev, domain, offset, true);
+}
+
+static void eqr_deassert_locked(struct eqr_private *priv, u32 domain,
+				u32 offset)
+{
+	enum eqr_domain_type domain_type = priv->data->domains[domain].type;
+	void __iomem *base, *reg;
+	u32 val;
+
+	lockdep_assert_held(&priv->mutexes[domain]);
+
+	base = priv->base + priv->data->domains[domain].offset;
+
+	switch (domain_type) {
+	case EQR_EYEQ5_SARCR:
+		reg = base + EQR_EYEQ5_SARCR_REQUEST;
+		writel(readl(reg) | BIT(offset), reg);
+		break;
+
+	case EQR_EYEQ5_ACRP:
+		reg = base + 4 * offset;
+		writel(readl(reg) & ~EQR_EYEQ5_ACRP_PD_REQ, reg);
+		break;
+
+	case EQR_EYEQ5_PCIE:
+		writel(readl(base) | BIT(offset), base);
+		break;
+
+	case EQR_EYEQ6H_SARCR:
+		val = readl(base + EQR_EYEQ6H_SARCR_RST_REQUEST);
+		val |= BIT(offset);
+		writel(val, base + EQR_EYEQ6H_SARCR_RST_REQUEST);
+		writel(val, base + EQR_EYEQ6H_SARCR_CLK_REQUEST);
+		break;
+
+	default:
+		WARN_ON(1);
+		break;
+	}
+}
+
+static int eqr_deassert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	struct eqr_private *priv = rcdev_to_priv(rcdev);
+	u32 domain = FIELD_GET(ID_DOMAIN_MASK, id);
+	u32 offset = FIELD_GET(ID_OFFSET_MASK, id);
+
+	dev_dbg(rcdev->dev, "%u-%u: deassert request\n", domain, offset);
+
+	guard(mutex)(&priv->mutexes[domain]);
+
+	eqr_deassert_locked(priv, domain, offset);
+	return eqr_busy_wait_locked(priv, rcdev->dev, domain, offset, false);
+}
+
+static int eqr_status(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	u32 domain = FIELD_GET(ID_DOMAIN_MASK, id);
+	struct eqr_private *priv = rcdev_to_priv(rcdev);
+	enum eqr_domain_type domain_type = priv->data->domains[domain].type;
+	u32 offset = FIELD_GET(ID_OFFSET_MASK, id);
+	void __iomem *base, *reg;
+
+	dev_dbg(rcdev->dev, "%u-%u: status request\n", domain, offset);
+
+	guard(mutex)(&priv->mutexes[domain]);
+
+	base = priv->base + priv->data->domains[domain].offset;
+
+	switch (domain_type) {
+	case EQR_EYEQ5_SARCR:
+		reg = base + EQR_EYEQ5_SARCR_STATUS;
+		return !(readl(reg) & BIT(offset));
+	case EQR_EYEQ5_ACRP:
+		reg = base + 4 * offset;
+		return !(readl(reg) & EQR_EYEQ5_ACRP_ST_ACTIVE);
+	case EQR_EYEQ5_PCIE:
+		return !(readl(base) & BIT(offset));
+	case EQR_EYEQ6H_SARCR:
+		reg = base + EQR_EYEQ6H_SARCR_RST_STATUS;
+		return !(readl(reg) & BIT(offset));
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct reset_control_ops eqr_ops = {
+	.assert	  = eqr_assert,
+	.deassert = eqr_deassert,
+	.status	  = eqr_status,
+};
+
+static int eqr_of_xlate_internal(struct reset_controller_dev *rcdev,
+				 u32 domain, u32 offset)
+{
+	struct eqr_private *priv = rcdev_to_priv(rcdev);
+
+	if (domain >= priv->data->domain_count || offset > 31 ||
+	    !(priv->data->domains[domain].valid_mask & BIT(offset))) {
+		dev_err(rcdev->dev, "%u-%u: invalid reset\n", domain, offset);
+		return -EINVAL;
+	}
+
+	return FIELD_PREP(ID_DOMAIN_MASK, domain) | FIELD_PREP(ID_OFFSET_MASK, offset);
+}
+
+static int eqr_of_xlate_onecell(struct reset_controller_dev *rcdev,
+				const struct of_phandle_args *reset_spec)
+{
+	return eqr_of_xlate_internal(rcdev, 0, reset_spec->args[0]);
+}
+
+static int eqr_of_xlate_twocells(struct reset_controller_dev *rcdev,
+				 const struct of_phandle_args *reset_spec)
+{
+	return eqr_of_xlate_internal(rcdev, reset_spec->args[0], reset_spec->args[1]);
+}
+
+static int eqr_probe(struct auxiliary_device *adev,
+		     const struct auxiliary_device_id *id)
+{
+	const struct of_device_id *match;
+	struct device *dev = &adev->dev;
+	struct eqr_private *priv;
+	unsigned int i;
+	int ret;
+
+	/*
+	 * We are an auxiliary device of clk-eyeq. We do not have an OF node by
+	 * default; let's reuse our parent's OF node.
+	 */
+	WARN_ON(dev->of_node);
+	device_set_of_node_from_dev(dev, dev->parent);
+	if (!dev->of_node)
+		return -ENODEV;
+
+	/*
+	 * Using our newfound OF node, we can get match data. We cannot use
+	 * device_get_match_data() because it does not match reused OF nodes.
+	 */
+	match = of_match_node(dev->driver->of_match_table, dev->of_node);
+	if (!match || !match->data)
+		return -ENODEV;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->data = match->data;
+	priv->base = dev_get_platdata(dev);
+	priv->rcdev.ops = &eqr_ops;
+	priv->rcdev.owner = THIS_MODULE;
+	priv->rcdev.dev = dev;
+	priv->rcdev.of_node = dev->of_node;
+
+	if (priv->data->domain_count == 1) {
+		priv->rcdev.of_reset_n_cells = 1;
+		priv->rcdev.of_xlate = eqr_of_xlate_onecell;
+	} else {
+		priv->rcdev.of_reset_n_cells = 2;
+		priv->rcdev.of_xlate = eqr_of_xlate_twocells;
+	}
+
+	for (i = 0; i < priv->data->domain_count; i++)
+		mutex_init(&priv->mutexes[i]);
+
+	priv->rcdev.nr_resets = 0;
+	for (i = 0; i < priv->data->domain_count; i++)
+		priv->rcdev.nr_resets += hweight32(priv->data->domains[i].valid_mask);
+
+	ret = devm_reset_controller_register(dev, &priv->rcdev);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed registering reset controller\n");
+
+	return 0;
+}
+
+static const struct eqr_domain_descriptor eqr_eyeq5_domains[] = {
+	{
+		.type = EQR_EYEQ5_SARCR,
+		.valid_mask = 0xFFFFFF8,
+		.offset = 0x004,
+	},
+	{
+		.type = EQR_EYEQ5_ACRP,
+		.valid_mask = 0x0001FFF,
+		.offset = 0x200,
+	},
+	{
+		.type = EQR_EYEQ5_PCIE,
+		.valid_mask = 0x007BFFF,
+		.offset = 0x120,
+	},
+};
+
+static const struct eqr_match_data eqr_eyeq5_data = {
+	.domain_count	= ARRAY_SIZE(eqr_eyeq5_domains),
+	.domains	= eqr_eyeq5_domains,
+};
+
+static const struct eqr_domain_descriptor eqr_eyeq6l_domains[] = {
+	{
+		.type = EQR_EYEQ5_SARCR,
+		.valid_mask = 0x3FFF,
+		.offset = 0x004,
+	},
+	{
+		.type = EQR_EYEQ5_ACRP,
+		.valid_mask = 0x00FF,
+		.offset = 0x200,
+	},
+};
+
+static const struct eqr_match_data eqr_eyeq6l_data = {
+	.domain_count	= ARRAY_SIZE(eqr_eyeq6l_domains),
+	.domains	= eqr_eyeq6l_domains,
+};
+
+/* West and east OLBs each have an instance. */
+static const struct eqr_domain_descriptor eqr_eyeq6h_we_domains[] = {
+	{
+		.type = EQR_EYEQ6H_SARCR,
+		.valid_mask = 0x1F7F,
+		.offset = 0x004,
+	},
+};
+
+static const struct eqr_match_data eqr_eyeq6h_we_data = {
+	.domain_count	= ARRAY_SIZE(eqr_eyeq6h_we_domains),
+	.domains	= eqr_eyeq6h_we_domains,
+};
+
+static const struct eqr_domain_descriptor eqr_eyeq6h_acc_domains[] = {
+	{
+		.type = EQR_EYEQ5_ACRP,
+		.valid_mask = 0x7FFF,
+		.offset = 0x000,
+	},
+};
+
+static const struct eqr_match_data eqr_eyeq6h_acc_data = {
+	.domain_count	= ARRAY_SIZE(eqr_eyeq6h_acc_domains),
+	.domains	= eqr_eyeq6h_acc_domains,
+};
+
+/*
+ * Table describes OLB system-controller compatibles.
+ * It does not get used to match against devicetree node.
+ */
+static const struct of_device_id eqr_match_table[] = {
+	{ .compatible = "mobileye,eyeq5-olb", .data = &eqr_eyeq5_data },
+	{ .compatible = "mobileye,eyeq6l-olb", .data = &eqr_eyeq6l_data },
+	{ .compatible = "mobileye,eyeq6h-west-olb", .data = &eqr_eyeq6h_we_data },
+	{ .compatible = "mobileye,eyeq6h-east-olb", .data = &eqr_eyeq6h_we_data },
+	{ .compatible = "mobileye,eyeq6h-acc-olb", .data = &eqr_eyeq6h_acc_data },
+	{}
+};
+MODULE_DEVICE_TABLE(of, eqr_match_table);
+
+static const struct auxiliary_device_id eqr_id_table[] = {
+	{ .name = "clk_eyeq.reset" },
+	{ .name = "clk_eyeq.reset_west" },
+	{ .name = "clk_eyeq.reset_east" },
+	{ .name = "clk_eyeq.reset_acc" },
+	{}
+};
+MODULE_DEVICE_TABLE(auxiliary, eqr_id_table);
+
+static struct auxiliary_driver eqr_driver = {
+	.probe = eqr_probe,
+	.id_table = eqr_id_table,
+	.driver = {
+		.of_match_table = eqr_match_table,
+	}
+};
+module_auxiliary_driver(eqr_driver);

-- 
2.45.2


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

* [PATCH v3 8/9] pinctrl: eyeq5: add platform driver
  2024-06-20 17:30 [PATCH v3 0/9] Add Mobileye EyeQ system controller support (clk, reset, pinctrl) Théo Lebrun
                   ` (6 preceding siblings ...)
  2024-06-20 17:30 ` [PATCH v3 7/9] reset: eyeq: add platform driver Théo Lebrun
@ 2024-06-20 17:31 ` Théo Lebrun
  2024-06-20 17:31 ` [PATCH v3 9/9] MIPS: mobileye: eyeq5: add OLB system-controller node Théo Lebrun
  8 siblings, 0 replies; 21+ messages in thread
From: Théo Lebrun @ 2024-06-20 17:31 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michael Turquette,
	Stephen Boyd, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Rafael J. Wysocki, Lee Jones, Thomas Bogendoerfer
  Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
	Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
	Tawfik Bayouk, Théo Lebrun

Add the Mobileye EyeQ5 pin controller driver. It belongs to a syscon
region called OLB and gets spawned as auxiliary device to the platform
driver for clock.

Existing pins and their function live statically in the driver code
rather than in the devicetree, see compatible match data.

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
---
 MAINTAINERS                     |   1 +
 drivers/pinctrl/Kconfig         |  15 ++
 drivers/pinctrl/Makefile        |   1 +
 drivers/pinctrl/pinctrl-eyeq5.c | 576 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 593 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 36f4001c7f51..09c3b05035d2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14931,6 +14931,7 @@ F:	arch/mips/boot/dts/mobileye/
 F:	arch/mips/configs/eyeq5_defconfig
 F:	arch/mips/mobileye/board-epm5.its.S
 F:	drivers/clk/clk-eyeq5.c
+F:	drivers/pinctrl/pinctrl-eyeq5.c
 F:	drivers/reset/reset-eyeq5.c
 F:	include/dt-bindings/clock/mobileye,eyeq5-clk.h
 
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index d45657aa986a..de112a3ae079 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -213,6 +213,21 @@ config PINCTRL_EQUILIBRIUM
 	  desired pin functions, configure GPIO attributes for LGM SoC pins.
 	  Pin muxing and pin config settings are retrieved from device tree.
 
+config PINCTRL_EYEQ5
+	bool "Mobileye EyeQ5 pinctrl driver"
+	depends on COMMON_CLK_EYEQ
+	depends on MACH_EYEQ5 || COMPILE_TEST
+	select PINMUX
+	select GENERIC_PINCONF
+	select MFD_SYSCON
+	default MACH_EYEQ5
+	help
+	  Pin controller driver for the Mobileye EyeQ5 platform. It does both
+	  pin config & pin muxing. It does not handle GPIO.
+
+	  Pin muxing supports two functions for each pin: first is GPIO, second
+	  is pin-dependent. Pin config is about bias & drive strength.
+
 config PINCTRL_GEMINI
 	bool
 	depends on ARCH_GEMINI
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 2152539b53d5..6113e980cdb2 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_PINCTRL_DA850_PUPD) += pinctrl-da850-pupd.o
 obj-$(CONFIG_PINCTRL_DA9062)	+= pinctrl-da9062.o
 obj-$(CONFIG_PINCTRL_DIGICOLOR)	+= pinctrl-digicolor.o
 obj-$(CONFIG_PINCTRL_EQUILIBRIUM)   += pinctrl-equilibrium.o
+obj-$(CONFIG_PINCTRL_EYEQ5)	+= pinctrl-eyeq5.o
 obj-$(CONFIG_PINCTRL_GEMINI)	+= pinctrl-gemini.o
 obj-$(CONFIG_PINCTRL_INGENIC)	+= pinctrl-ingenic.o
 obj-$(CONFIG_PINCTRL_K210)	+= pinctrl-k210.o
diff --git a/drivers/pinctrl/pinctrl-eyeq5.c b/drivers/pinctrl/pinctrl-eyeq5.c
new file mode 100644
index 000000000000..bac2b5d74d7e
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-eyeq5.c
@@ -0,0 +1,576 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Pinctrl driver for the Mobileye EyeQ5 platform.
+ *
+ * The registers are located in a syscon region called OLB. There are two pin
+ * banks, each being controlled by 5 registers (see enum eq5p_regs) for
+ * pull-down, pull-up, drive strength and muxing.
+ *
+ * For each pin, muxing is between two functions: (0) GPIO or (1) another one
+ * that is pin-dependent. Functions are declared statically in this driver.
+ *
+ * We create pinctrl groups that are 1:1 equivalent to pins: each group has a
+ * single pin, and its index/selector is the pin number.
+ *
+ * We use eq5p_ as prefix, as-in "EyeQ5 Pinctrl", but way shorter.
+ *
+ * Copyright (C) 2024 Mobileye Vision Technologies Ltd.
+ */
+
+#include <linux/array_size.h>
+#include <linux/auxiliary_bus.h>
+#include <linux/bits.h>
+#include <linux/bug.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "core.h"
+#include "pinctrl-utils.h"
+
+struct eq5p_pinctrl {
+	struct pinctrl_desc	desc;
+	void __iomem		*base;
+};
+
+enum eq5p_bank {
+	EQ5P_BANK_A,
+	EQ5P_BANK_B,
+
+	EQ5P_BANK_COUNT,
+};
+
+enum eq5p_regs {
+	EQ5P_PD,
+	EQ5P_PU,
+	EQ5P_DS_LOW,
+	EQ5P_DS_HIGH,
+	EQ5P_IOCR,
+
+	EQ5P_REG_COUNT,
+};
+
+static const unsigned int eq5p_regs[EQ5P_BANK_COUNT][EQ5P_REG_COUNT] = {
+	[EQ5P_BANK_A] = {0x0C0, 0x0C4, 0x0D0, 0x0D4, 0x0B0},
+	[EQ5P_BANK_B] = {0x0C8, 0x0CC, 0x0D8, 0x0DC, 0x0B4},
+};
+
+/*
+ * Drive strength; two bits per pin.
+ */
+#define EQ5P_DS_MASK	GENMASK(1, 0)
+
+/*
+ * Comments to the right of each pin are the "signal name" in the datasheet.
+ */
+static const struct pinctrl_pin_desc eq5p_pins[] = {
+	/* Bank A */
+	PINCTRL_PIN(0,  "PA0"),  /* A0_TIMER0_CK */
+	PINCTRL_PIN(1,  "PA1"),  /* A1_TIMER0_EOC */
+	PINCTRL_PIN(2,  "PA2"),  /* A2_TIMER1_CK */
+	PINCTRL_PIN(3,  "PA3"),  /* A3_TIMER1_EOC */
+	PINCTRL_PIN(4,  "PA4"),  /* A4_TIMER2_CK */
+	PINCTRL_PIN(5,  "PA5"),  /* A5_TIMER2_EOC */
+	PINCTRL_PIN(6,  "PA6"),  /* A6_TIMER5_EXT_INCAP1 */
+	PINCTRL_PIN(7,  "PA7"),  /* A7_TIMER5_EXT_INCAP2 */
+	PINCTRL_PIN(8,  "PA8"),  /* A8_TIMER5_EXT_OUTCMP1 */
+	PINCTRL_PIN(9,  "PA9"),  /* A9_TIMER5_EXT_OUTCMP2 */
+	PINCTRL_PIN(10, "PA10"), /* A10_UART_0_TX */
+	PINCTRL_PIN(11, "PA11"), /* A11_UART_0_RX */
+	PINCTRL_PIN(12, "PA12"), /* A12_UART_1_TX */
+	PINCTRL_PIN(13, "PA13"), /* A13_UART_1_RX */
+	PINCTRL_PIN(14, "PA14"), /* A14_CAN_0_TX */
+	PINCTRL_PIN(15, "PA15"), /* A15_CAN_0_RX */
+	PINCTRL_PIN(16, "PA16"), /* A16_CAN_1_TX */
+	PINCTRL_PIN(17, "PA17"), /* A17_CAN_1_RX */
+	PINCTRL_PIN(18, "PA18"), /* A18_SPI_0_DO */
+	PINCTRL_PIN(19, "PA19"), /* A19_SPI_0_DI */
+	PINCTRL_PIN(20, "PA20"), /* A20_SPI_0_CK */
+	PINCTRL_PIN(21, "PA21"), /* A21_SPI_0_CS0 */
+	PINCTRL_PIN(22, "PA22"), /* A22_SPI_0_CS1 */
+	PINCTRL_PIN(23, "PA23"), /* A23_SPI_1_DO */
+	PINCTRL_PIN(24, "PA24"), /* A24_SPI_1_DI */
+	PINCTRL_PIN(25, "PA25"), /* A25_SPI_1_CK */
+	PINCTRL_PIN(26, "PA26"), /* A26_SPI_1_CS0 */
+	PINCTRL_PIN(27, "PA27"), /* A27_SPI_1_CS1 */
+	PINCTRL_PIN(28, "PA28"), /* A28_REF_CLK0 */
+
+#define EQ5P_PIN_OFFSET_BANK_B	29
+
+	/* Bank B */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 0,  "PB0"),  /* B0_TIMER3_CK */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 1,  "PB1"),  /* B1_TIMER3_EOC */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 2,  "PB2"),  /* B2_TIMER4_CK */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 3,  "PB3"),  /* B3_TIMER4_EOC */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 4,  "PB4"),  /* B4_TIMER6_EXT_INCAP1 */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 5,  "PB5"),  /* B5_TIMER6_EXT_INCAP2 */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 6,  "PB6"),  /* B6_TIMER6_EXT_OUTCMP1 */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 7,  "PB7"),  /* B7_TIMER6_EXT_OUTCMP2 */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 8,  "PB8"),  /* B8_UART_2_TX */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 9,  "PB9"),  /* B9_UART_2_RX */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 10, "PB10"), /* B10_CAN_2_TX */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 11, "PB11"), /* B11_CAN_2_RX */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 12, "PB12"), /* B12_SPI_2_DO */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 13, "PB13"), /* B13_SPI_2_DI */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 14, "PB14"), /* B14_SPI_2_CK */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 15, "PB15"), /* B15_SPI_2_CS0 */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 16, "PB16"), /* B16_SPI_2_CS1 */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 17, "PB17"), /* B17_SPI_3_DO */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 18, "PB18"), /* B18_SPI_3_DI */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 19, "PB19"), /* B19_SPI_3_CK */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 20, "PB20"), /* B20_SPI_3_CS0 */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 21, "PB21"), /* B21_SPI_3_CS1 */
+	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 22, "PB22"), /* B22_MCLK0 */
+};
+
+static const char * const gpio_groups[] = {
+	/* Bank A */
+	"PA0",  "PA1",  "PA2",  "PA3",  "PA4",  "PA5",  "PA6",  "PA7",
+	"PA8",  "PA9",  "PA10", "PA11", "PA12", "PA13", "PA14", "PA15",
+	"PA16", "PA17", "PA18", "PA19", "PA20", "PA21", "PA22", "PA23",
+	"PA24", "PA25", "PA26", "PA27", "PA28",
+
+	/* Bank B */
+	"PB0",  "PB1",  "PB2",  "PB3",  "PB4",  "PB5",  "PB6",  "PB7",
+	"PB8",  "PB9",  "PB10", "PB11", "PB12", "PB13", "PB14", "PB15",
+	"PB16", "PB17", "PB18", "PB19", "PB20", "PB21", "PB22",
+};
+
+/* Groups of functions on bank A */
+static const char * const timer0_groups[] = { "PA0", "PA1" };
+static const char * const timer1_groups[] = { "PA2", "PA3" };
+static const char * const timer2_groups[] = { "PA4", "PA5" };
+static const char * const timer5_groups[] = { "PA6", "PA7", "PA8", "PA9" };
+static const char * const uart0_groups[] = { "PA10", "PA11" };
+static const char * const uart1_groups[] = { "PA12", "PA13" };
+static const char * const can0_groups[] = { "PA14", "PA15" };
+static const char * const can1_groups[] = { "PA16", "PA17" };
+static const char * const spi0_groups[] = { "PA18", "PA19", "PA20", "PA21", "PA22" };
+static const char * const spi1_groups[] = { "PA23", "PA24", "PA25", "PA26", "PA27" };
+static const char * const refclk0_groups[] = { "PA28" };
+
+/* Groups of functions on bank B */
+static const char * const timer3_groups[] = { "PB0", "PB1" };
+static const char * const timer4_groups[] = { "PB2", "PB3" };
+static const char * const timer6_groups[] = { "PB4", "PB5", "PB6", "PB7" };
+static const char * const uart2_groups[] = { "PB8", "PB9" };
+static const char * const can2_groups[] = { "PB10", "PB11" };
+static const char * const spi2_groups[] = { "PB12", "PB13", "PB14", "PB15", "PB16" };
+static const char * const spi3_groups[] = { "PB17", "PB18", "PB19", "PB20", "PB21" };
+static const char * const mclk0_groups[] = { "PB22" };
+
+static const struct pinfunction eq5p_functions[] = {
+	/* GPIO having a fixed index is depended upon, see GPIO_FUNC_SELECTOR. */
+	PINCTRL_PINFUNCTION("gpio", gpio_groups, ARRAY_SIZE(gpio_groups)),
+#define GPIO_FUNC_SELECTOR 0
+
+	/* Bank A functions */
+	PINCTRL_PINFUNCTION("timer0", timer0_groups, ARRAY_SIZE(timer0_groups)),
+	PINCTRL_PINFUNCTION("timer1", timer1_groups, ARRAY_SIZE(timer1_groups)),
+	PINCTRL_PINFUNCTION("timer2", timer2_groups, ARRAY_SIZE(timer2_groups)),
+	PINCTRL_PINFUNCTION("timer5", timer5_groups, ARRAY_SIZE(timer5_groups)),
+	PINCTRL_PINFUNCTION("uart0", uart0_groups, ARRAY_SIZE(uart0_groups)),
+	PINCTRL_PINFUNCTION("uart1", uart1_groups, ARRAY_SIZE(uart1_groups)),
+	PINCTRL_PINFUNCTION("can0", can0_groups, ARRAY_SIZE(can0_groups)),
+	PINCTRL_PINFUNCTION("can1", can1_groups, ARRAY_SIZE(can1_groups)),
+	PINCTRL_PINFUNCTION("spi0", spi0_groups, ARRAY_SIZE(spi0_groups)),
+	PINCTRL_PINFUNCTION("spi1", spi1_groups, ARRAY_SIZE(spi1_groups)),
+	PINCTRL_PINFUNCTION("refclk0", refclk0_groups, ARRAY_SIZE(refclk0_groups)),
+
+	/* Bank B functions */
+	PINCTRL_PINFUNCTION("timer3", timer3_groups, ARRAY_SIZE(timer3_groups)),
+	PINCTRL_PINFUNCTION("timer4", timer4_groups, ARRAY_SIZE(timer4_groups)),
+	PINCTRL_PINFUNCTION("timer6", timer6_groups, ARRAY_SIZE(timer6_groups)),
+	PINCTRL_PINFUNCTION("uart2", uart2_groups, ARRAY_SIZE(uart2_groups)),
+	PINCTRL_PINFUNCTION("can2", can2_groups, ARRAY_SIZE(can2_groups)),
+	PINCTRL_PINFUNCTION("spi2", spi2_groups, ARRAY_SIZE(spi2_groups)),
+	PINCTRL_PINFUNCTION("spi3", spi3_groups, ARRAY_SIZE(spi3_groups)),
+	PINCTRL_PINFUNCTION("mclk0", mclk0_groups, ARRAY_SIZE(mclk0_groups)),
+};
+
+static void eq5p_update_bits(const struct eq5p_pinctrl *pctrl,
+			     enum eq5p_bank bank, enum eq5p_regs reg,
+			     u32 mask, u32 val)
+{
+	void __iomem *ptr = pctrl->base + eq5p_regs[bank][reg];
+
+	writel((readl(ptr) & ~mask) | (val & mask), ptr);
+}
+
+static bool eq5p_test_bit(const struct eq5p_pinctrl *pctrl,
+			  enum eq5p_bank bank, enum eq5p_regs reg, int offset)
+{
+	u32 val = readl(pctrl->base + eq5p_regs[bank][reg]);
+
+	if (WARN_ON(offset > 31))
+		return false;
+
+	return (val & BIT(offset)) != 0;
+}
+
+static enum eq5p_bank eq5p_pin_to_bank(unsigned int pin)
+{
+	if (pin < EQ5P_PIN_OFFSET_BANK_B)
+		return EQ5P_BANK_A;
+	else
+		return EQ5P_BANK_B;
+}
+
+static unsigned int eq5p_pin_to_offset(unsigned int pin)
+{
+	if (pin < EQ5P_PIN_OFFSET_BANK_B)
+		return pin;
+	else
+		return pin - EQ5P_PIN_OFFSET_BANK_B;
+}
+
+static int eq5p_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	return ARRAY_SIZE(eq5p_pins);
+}
+
+static const char *eq5p_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+					       unsigned int selector)
+{
+	return pctldev->desc->pins[selector].name;
+}
+
+static int eq5p_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+				       unsigned int selector,
+				       const unsigned int **pins,
+				       unsigned int *num_pins)
+{
+	*pins = &pctldev->desc->pins[selector].number;
+	*num_pins = 1;
+	return 0;
+}
+
+static int eq5p_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
+			    unsigned long *config)
+{
+	enum pin_config_param param = pinconf_to_config_param(*config);
+	struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	unsigned int offset = eq5p_pin_to_offset(pin);
+	enum eq5p_bank bank = eq5p_pin_to_bank(pin);
+	u32 val_ds, arg;
+	bool pd, pu;
+
+	pd = eq5p_test_bit(pctrl, bank, EQ5P_PD, offset);
+	pu = eq5p_test_bit(pctrl, bank, EQ5P_PU, offset);
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		arg = !(pd || pu);
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		arg = pd;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		arg = pu;
+		break;
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		offset *= 2; /* two bits per pin */
+		if (offset >= 32) {
+			val_ds = readl(pctrl->base + eq5p_regs[bank][EQ5P_DS_HIGH]);
+			offset -= 32;
+		} else {
+			val_ds = readl(pctrl->base + eq5p_regs[bank][EQ5P_DS_LOW]);
+		}
+		arg = (val_ds >> offset) & EQ5P_DS_MASK;
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	*config = pinconf_to_config_packed(param, arg);
+	return 0;
+}
+
+static void eq5p_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
+				      struct seq_file *s,
+				      unsigned int pin)
+{
+	struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	const char *pin_name = pctrl->desc.pins[pin].name;
+	unsigned int offset = eq5p_pin_to_offset(pin);
+	enum eq5p_bank bank = eq5p_pin_to_bank(pin);
+	const char *func_name, *bias;
+	unsigned long ds_config;
+	u32 drive_strength;
+	bool pd, pu;
+	int i, j;
+
+	/*
+	 * First, let's get the function name. All pins have only two functions:
+	 * GPIO (IOCR == 0) and something else (IOCR == 1).
+	 */
+	if (eq5p_test_bit(pctrl, bank, EQ5P_IOCR, offset)) {
+		func_name = NULL;
+		for (i = 0; i < ARRAY_SIZE(eq5p_functions); i++) {
+			if (i == GPIO_FUNC_SELECTOR)
+				continue;
+
+			for (j = 0; j < eq5p_functions[i].ngroups; j++) {
+				/* Groups and pins are the same thing for us. */
+				const char *x = eq5p_functions[i].groups[j];
+
+				if (strcmp(x, pin_name) == 0) {
+					func_name = eq5p_functions[i].name;
+					break;
+				}
+			}
+
+			if (func_name)
+				break;
+		}
+
+		/*
+		 * We have not found the function attached to this pin, this
+		 * should never occur as all pins have exactly two functions.
+		 */
+		if (!func_name)
+			func_name = "unknown";
+	} else {
+		func_name = eq5p_functions[GPIO_FUNC_SELECTOR].name;
+	}
+
+	/* Second, we retrieve the bias. */
+	pd = eq5p_test_bit(pctrl, bank, EQ5P_PD, offset);
+	pu = eq5p_test_bit(pctrl, bank, EQ5P_PU, offset);
+	if (pd && pu)
+		bias = "both";
+	else if (pd && !pu)
+		bias = "pulldown";
+	else if (!pd && pu)
+		bias = "pullup";
+	else
+		bias = "none";
+
+	/* Third, we get the drive strength. */
+	ds_config = pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH, 0);
+	eq5p_pinconf_get(pctldev, pin, &ds_config);
+	drive_strength = pinconf_to_config_argument(ds_config);
+
+	seq_printf(s, "function=%s bias=%s drive_strength=%d",
+		   func_name, bias, drive_strength);
+}
+
+static const struct pinctrl_ops eq5p_pinctrl_ops = {
+	.get_groups_count	= eq5p_pinctrl_get_groups_count,
+	.get_group_name		= eq5p_pinctrl_get_group_name,
+	.get_group_pins		= eq5p_pinctrl_get_group_pins,
+	.pin_dbg_show		= eq5p_pinctrl_pin_dbg_show,
+	.dt_node_to_map		= pinconf_generic_dt_node_to_map_pin,
+	.dt_free_map		= pinctrl_utils_free_map,
+};
+
+static int eq5p_pinmux_get_functions_count(struct pinctrl_dev *pctldev)
+{
+	return ARRAY_SIZE(eq5p_functions);
+}
+
+static const char *eq5p_pinmux_get_function_name(struct pinctrl_dev *pctldev,
+						 unsigned int selector)
+{
+	return eq5p_functions[selector].name;
+}
+
+static int eq5p_pinmux_get_function_groups(struct pinctrl_dev *pctldev,
+					   unsigned int selector,
+					   const char * const **groups,
+					   unsigned int *num_groups)
+{
+	*groups = eq5p_functions[selector].groups;
+	*num_groups = eq5p_functions[selector].ngroups;
+	return 0;
+}
+
+static int eq5p_pinmux_set_mux(struct pinctrl_dev *pctldev,
+			       unsigned int func_selector, unsigned int pin)
+{
+	struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	const char *func_name = eq5p_functions[func_selector].name;
+	const char *group_name = pctldev->desc->pins[pin].name;
+	bool is_gpio = func_selector == GPIO_FUNC_SELECTOR;
+	unsigned int offset = eq5p_pin_to_offset(pin);
+	enum eq5p_bank bank = eq5p_pin_to_bank(pin);
+	u32 mask, val;
+
+	dev_dbg(pctldev->dev, "func=%s group=%s\n", func_name, group_name);
+
+	mask = BIT(offset);
+	val = is_gpio ? 0 : mask;
+	eq5p_update_bits(pctrl, bank, EQ5P_IOCR, mask, val);
+	return 0;
+}
+
+static int eq5p_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
+					   struct pinctrl_gpio_range *range,
+					   unsigned int pin)
+{
+	/* Pin numbers and group selectors are the same thing in our case. */
+	return eq5p_pinmux_set_mux(pctldev, GPIO_FUNC_SELECTOR, pin);
+}
+
+static const struct pinmux_ops eq5p_pinmux_ops = {
+	.get_functions_count	= eq5p_pinmux_get_functions_count,
+	.get_function_name	= eq5p_pinmux_get_function_name,
+	.get_function_groups	= eq5p_pinmux_get_function_groups,
+	.set_mux		= eq5p_pinmux_set_mux,
+	.gpio_request_enable	= eq5p_pinmux_gpio_request_enable,
+	.strict			= true,
+};
+
+static int eq5p_pinconf_set_drive_strength(struct pinctrl_dev *pctldev,
+					   unsigned int pin, u32 arg)
+{
+	struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	unsigned int offset = eq5p_pin_to_offset(pin);
+	enum eq5p_bank bank = eq5p_pin_to_bank(pin);
+	unsigned int reg;
+	u32 mask, val;
+
+	if (arg & ~EQ5P_DS_MASK) {
+		dev_err(pctldev->dev, "Unsupported drive strength: %u\n", arg);
+		return -EINVAL;
+	}
+
+	offset *= 2; /* two bits per pin */
+
+	if (offset >= 32) {
+		reg = EQ5P_DS_HIGH;
+		offset -= 32;
+	} else {
+		reg = EQ5P_DS_LOW;
+	}
+
+	mask = EQ5P_DS_MASK << offset;
+	val = arg << offset;
+	eq5p_update_bits(pctrl, bank, reg, mask, val);
+	return 0;
+}
+
+static int eq5p_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+			    unsigned long *configs, unsigned int num_configs)
+{
+	struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	const char *pin_name = pctldev->desc->pins[pin].name;
+	unsigned int offset = eq5p_pin_to_offset(pin);
+	enum eq5p_bank bank = eq5p_pin_to_bank(pin);
+	struct device *dev = pctldev->dev;
+	u32 val = BIT(offset);
+	unsigned int i;
+
+	for (i = 0; i < num_configs; i++) {
+		enum pin_config_param param = pinconf_to_config_param(configs[i]);
+		u32 arg = pinconf_to_config_argument(configs[i]);
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_DISABLE:
+			dev_dbg(dev, "pin=%s bias_disable\n", pin_name);
+
+			eq5p_update_bits(pctrl, bank, EQ5P_PD, val, 0);
+			eq5p_update_bits(pctrl, bank, EQ5P_PU, val, 0);
+			break;
+
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			dev_dbg(dev, "pin=%s bias_pull_down arg=%u\n",
+				pin_name, arg);
+
+			if (arg == 0) /* cannot connect to GND */
+				return -ENOTSUPP;
+
+			eq5p_update_bits(pctrl, bank, EQ5P_PD, val, val);
+			eq5p_update_bits(pctrl, bank, EQ5P_PU, val, 0);
+			break;
+
+		case PIN_CONFIG_BIAS_PULL_UP:
+			dev_dbg(dev, "pin=%s bias_pull_up arg=%u\n",
+				pin_name, arg);
+
+			if (arg == 0) /* cannot connect to VDD */
+				return -ENOTSUPP;
+
+			eq5p_update_bits(pctrl, bank, EQ5P_PD, val, 0);
+			eq5p_update_bits(pctrl, bank, EQ5P_PU, val, val);
+			break;
+
+		case PIN_CONFIG_DRIVE_STRENGTH:
+			dev_dbg(dev, "pin=%s drive_strength arg=%u\n",
+				pin_name, arg);
+
+			eq5p_pinconf_set_drive_strength(pctldev, pin, arg);
+			break;
+
+		default:
+			dev_err(dev, "Unsupported pinconf %u\n", param);
+			return -ENOTSUPP;
+		}
+	}
+
+	return 0;
+}
+
+static const struct pinconf_ops eq5p_pinconf_ops = {
+	.is_generic = true,
+	.pin_config_get = eq5p_pinconf_get,
+	.pin_config_set = eq5p_pinconf_set,
+	/* Pins and groups are equivalent in this driver. */
+	.pin_config_group_get = eq5p_pinconf_get,
+	.pin_config_group_set = eq5p_pinconf_set,
+};
+
+static int eq5p_probe(struct auxiliary_device *adev,
+		      const struct auxiliary_device_id *id)
+{
+	struct device *dev = &adev->dev;
+	struct pinctrl_dev *pctldev;
+	struct eq5p_pinctrl *pctrl;
+	int ret;
+
+	pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
+	if (!pctrl)
+		return -ENOMEM;
+
+	pctrl->base = dev_get_platdata(dev);
+	pctrl->desc.name = dev_name(dev);
+	pctrl->desc.pins = eq5p_pins;
+	pctrl->desc.npins = ARRAY_SIZE(eq5p_pins);
+	pctrl->desc.pctlops = &eq5p_pinctrl_ops;
+	pctrl->desc.pmxops = &eq5p_pinmux_ops;
+	pctrl->desc.confops = &eq5p_pinconf_ops;
+	pctrl->desc.owner = THIS_MODULE;
+
+	ret = devm_pinctrl_register_and_init(dev, &pctrl->desc, pctrl, &pctldev);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed registering pinctrl device\n");
+
+	ret = pinctrl_enable(pctldev);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed enabling pinctrl device\n");
+
+	return 0;
+}
+
+static const struct auxiliary_device_id eq5p_id_table[] = {
+	{ .name = "clk_eyeq.pinctrl" },
+	{}
+};
+MODULE_DEVICE_TABLE(auxiliary, eq5p_id_table);
+
+static struct auxiliary_driver eq5p_driver = {
+	.probe = eq5p_probe,
+	.id_table = eq5p_id_table,
+};
+module_auxiliary_driver(eq5p_driver);

-- 
2.45.2


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

* [PATCH v3 9/9] MIPS: mobileye: eyeq5: add OLB system-controller node
  2024-06-20 17:30 [PATCH v3 0/9] Add Mobileye EyeQ system controller support (clk, reset, pinctrl) Théo Lebrun
                   ` (7 preceding siblings ...)
  2024-06-20 17:31 ` [PATCH v3 8/9] pinctrl: eyeq5: " Théo Lebrun
@ 2024-06-20 17:31 ` Théo Lebrun
  8 siblings, 0 replies; 21+ messages in thread
From: Théo Lebrun @ 2024-06-20 17:31 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michael Turquette,
	Stephen Boyd, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Rafael J. Wysocki, Lee Jones, Thomas Bogendoerfer
  Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
	Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
	Tawfik Bayouk, Théo Lebrun

The OLB ("Other Logic Block") is a system-controller region hosting
clock, reset and pin controllers. It contains registers such as I2C
speed mode that need to be accessible by other nodes.

Remove fixed-clocks previously used; replace references.
Add parent crystal clock, fixed at 30MHz.
Add pin nodes for all functions.
Add mobileye,eyeq5-olb compatible node, hosting clk, reset and pinctrl.
Add reset and pinctrl references to UART nodes.

Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
---
 .../{eyeq5-fixed-clocks.dtsi => eyeq5-clocks.dtsi} |  54 +++------
 arch/mips/boot/dts/mobileye/eyeq5-pins.dtsi        | 125 +++++++++++++++++++++
 arch/mips/boot/dts/mobileye/eyeq5.dtsi             |  22 +++-
 3 files changed, 162 insertions(+), 39 deletions(-)

diff --git a/arch/mips/boot/dts/mobileye/eyeq5-fixed-clocks.dtsi b/arch/mips/boot/dts/mobileye/eyeq5-clocks.dtsi
similarity index 88%
rename from arch/mips/boot/dts/mobileye/eyeq5-fixed-clocks.dtsi
rename to arch/mips/boot/dts/mobileye/eyeq5-clocks.dtsi
index 78f5533a95c6..17a342cc744e 100644
--- a/arch/mips/boot/dts/mobileye/eyeq5-fixed-clocks.dtsi
+++ b/arch/mips/boot/dts/mobileye/eyeq5-clocks.dtsi
@@ -3,42 +3,20 @@
  * Copyright 2023 Mobileye Vision Technologies Ltd.
  */
 
+#include <dt-bindings/clock/mobileye,eyeq5-clk.h>
+
 / {
 	/* Fixed clock */
-	pll_cpu: pll-cpu {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <1500000000>;
-	};
-
-	pll_vdi: pll-vdi {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <1280000000>;
-	};
-
-	pll_per: pll-per {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <2000000000>;
-	};
-
-	pll_ddr0: pll-ddr0 {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <1857210000>;
-	};
-
-	pll_ddr1: pll-ddr1 {
+	xtal: xtal {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
-		clock-frequency = <1857210000>;
+		clock-frequency = <30000000>;
 	};
 
 /* PLL_CPU derivatives */
 	occ_cpu: occ-cpu {
 		compatible = "fixed-factor-clock";
-		clocks = <&pll_cpu>;
+		clocks = <&olb EQ5C_PLL_CPU>;
 		#clock-cells = <0>;
 		clock-div = <1>;
 		clock-mult = <1>;
@@ -101,7 +79,7 @@ mem_clk: mem-clk {
 	};
 	occ_isram: occ-isram {
 		compatible = "fixed-factor-clock";
-		clocks = <&pll_cpu>;
+		clocks = <&olb EQ5C_PLL_CPU>;
 		#clock-cells = <0>;
 		clock-div = <2>;
 		clock-mult = <1>;
@@ -115,7 +93,7 @@ isram_clk: isram-clk { /* gate ClkRstGen_isram */
 	};
 	occ_dbu: occ-dbu {
 		compatible = "fixed-factor-clock";
-		clocks = <&pll_cpu>;
+		clocks = <&olb EQ5C_PLL_CPU>;
 		#clock-cells = <0>;
 		clock-div = <10>;
 		clock-mult = <1>;
@@ -130,7 +108,7 @@ si_dbu_tp_pclk: si-dbu-tp-pclk { /* gate ClkRstGen_dbu */
 /* PLL_VDI derivatives */
 	occ_vdi: occ-vdi {
 		compatible = "fixed-factor-clock";
-		clocks = <&pll_vdi>;
+		clocks = <&olb EQ5C_PLL_VDI>;
 		#clock-cells = <0>;
 		clock-div = <2>;
 		clock-mult = <1>;
@@ -144,7 +122,7 @@ vdi_clk: vdi-clk { /* gate ClkRstGen_vdi */
 	};
 	occ_can_ser: occ-can-ser {
 		compatible = "fixed-factor-clock";
-		clocks = <&pll_vdi>;
+		clocks = <&olb EQ5C_PLL_VDI>;
 		#clock-cells = <0>;
 		clock-div = <16>;
 		clock-mult = <1>;
@@ -158,7 +136,7 @@ can_ser_clk: can-ser-clk { /* gate ClkRstGen_can_ser */
 	};
 	i2c_ser_clk: i2c-ser-clk {
 		compatible = "fixed-factor-clock";
-		clocks = <&pll_vdi>;
+		clocks = <&olb EQ5C_PLL_VDI>;
 		#clock-cells = <0>;
 		clock-div = <20>;
 		clock-mult = <1>;
@@ -166,7 +144,7 @@ i2c_ser_clk: i2c-ser-clk {
 /* PLL_PER derivatives */
 	occ_periph: occ-periph {
 		compatible = "fixed-factor-clock";
-		clocks = <&pll_per>;
+		clocks = <&olb EQ5C_PLL_PER>;
 		#clock-cells = <0>;
 		clock-div = <16>;
 		clock-mult = <1>;
@@ -225,7 +203,7 @@ gpio_clk: gpio-clk {
 	};
 	emmc_sys_clk: emmc-sys-clk {
 		compatible = "fixed-factor-clock";
-		clocks = <&pll_per>;
+		clocks = <&olb EQ5C_PLL_PER>;
 		#clock-cells = <0>;
 		clock-div = <10>;
 		clock-mult = <1>;
@@ -233,7 +211,7 @@ emmc_sys_clk: emmc-sys-clk {
 	};
 	ccf_ctrl_clk: ccf-ctrl-clk {
 		compatible = "fixed-factor-clock";
-		clocks = <&pll_per>;
+		clocks = <&olb EQ5C_PLL_PER>;
 		#clock-cells = <0>;
 		clock-div = <4>;
 		clock-mult = <1>;
@@ -241,7 +219,7 @@ ccf_ctrl_clk: ccf-ctrl-clk {
 	};
 	occ_mjpeg_core: occ-mjpeg-core {
 		compatible = "fixed-factor-clock";
-		clocks = <&pll_per>;
+		clocks = <&olb EQ5C_PLL_PER>;
 		#clock-cells = <0>;
 		clock-div = <2>;
 		clock-mult = <1>;
@@ -265,7 +243,7 @@ mjpeg_core_clk: mjpeg-core-clk { /* gate ClkRstGen_mjpeg_gen */
 	};
 	fcmu_a_clk: fcmu-a-clk {
 		compatible = "fixed-factor-clock";
-		clocks = <&pll_per>;
+		clocks = <&olb EQ5C_PLL_PER>;
 		#clock-cells = <0>;
 		clock-div = <20>;
 		clock-mult = <1>;
@@ -273,7 +251,7 @@ fcmu_a_clk: fcmu-a-clk {
 	};
 	occ_pci_sys: occ-pci-sys {
 		compatible = "fixed-factor-clock";
-		clocks = <&pll_per>;
+		clocks = <&olb EQ5C_PLL_PER>;
 		#clock-cells = <0>;
 		clock-div = <8>;
 		clock-mult = <1>;
diff --git a/arch/mips/boot/dts/mobileye/eyeq5-pins.dtsi b/arch/mips/boot/dts/mobileye/eyeq5-pins.dtsi
new file mode 100644
index 000000000000..0b3671013ab4
--- /dev/null
+++ b/arch/mips/boot/dts/mobileye/eyeq5-pins.dtsi
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+/*
+ * Default pin configuration for Mobileye EyeQ5 boards. We mostly create one
+ * pin configuration node per function.
+ */
+
+&olb {
+	timer0_pins: timer0-pins {
+		function = "timer0";
+		pins = "PA0", "PA1";
+	};
+	timer1_pins: timer1-pins {
+		function = "timer1";
+		pins = "PA2", "PA3";
+	};
+	timer2_pins: timer2-pins {
+		function = "timer2";
+		pins = "PA4", "PA5";
+	};
+	pps0_pins: pps0-pin {
+		function = "timer2";
+		pins = "PA4";
+	};
+	pps1_pins: pps1-pin {
+		function = "timer2";
+		pins = "PA5";
+	};
+	timer5_ext_pins: timer5-ext-pins {
+		function = "timer5";
+		pins = "PA6", "PA7", "PA8", "PA9";
+	};
+	timer5_ext_input_pins: timer5-ext-input-pins {
+		function = "timer5";
+		pins = "PA6", "PA7";
+	};
+	timer5_ext_incap_a_pins: timer5-ext-incap-a-pin {
+		function = "timer5";
+		pins = "PA6";
+	};
+	timer5_ext_incap_b_pins: timer5-ext-incap-b-pin {
+		function = "timer5";
+		pins = "PA7";
+	};
+	can0_pins: can0-pins {
+		function = "can0";
+		pins = "PA14", "PA15";
+	};
+	can1_pins: can1-pins {
+		function = "can1";
+		pins = "PA16", "PA17";
+	};
+	uart0_pins: uart0-pins {
+		function = "uart0";
+		pins = "PA10", "PA11";
+	};
+	uart1_pins: uart1-pins {
+		function = "uart1";
+		pins = "PA12", "PA13";
+	};
+	spi0_pins: spi0-pins {
+		function = "spi0";
+		pins = "PA18", "PA19", "PA20", "PA21", "PA22";
+	};
+	spi1_pins: spi1-pins {
+		function = "spi1";
+		pins = "PA23", "PA24", "PA25", "PA26", "PA27";
+	};
+	spi1_slave_pins: spi1-slave-pins {
+		function = "spi1";
+		pins = "PA24", "PA25", "PA26";
+	};
+	refclk0_pins: refclk0-pin {
+		function = "refclk0";
+		pins = "PA28";
+	};
+	timer3_pins: timer3-pins {
+		function = "timer3";
+		pins = "PB0", "PB1";
+	};
+	timer4_pins: timer4-pins {
+		function = "timer4";
+		pins = "PB2", "PB3";
+	};
+	timer6_ext_pins: timer6-ext-pins {
+		function = "timer6";
+		pins = "PB4", "PB5", "PB6", "PB7";
+	};
+	timer6_ext_input_pins: timer6-ext-input-pins {
+		function = "timer6";
+		pins = "PB4", "PB5";
+	};
+	timer6_ext_incap_a_pins: timer6-ext-incap-a-pin {
+		function = "timer6";
+		pins = "PB4";
+	};
+	timer6_ext_incap_b_pins: timer6-ext-incap-b-pin {
+		function = "timer6";
+		pins = "PB5";
+	};
+	can2_pins: can2-pins {
+		function = "can2";
+		pins = "PB10", "PB11";
+	};
+	uart2_pins: uart2-pins {
+		function = "uart2";
+		pins = "PB8", "PB9";
+	};
+	spi2_pins: spi2-pins {
+		function = "spi2";
+		pins = "PB12", "PB13", "PB14", "PB15", "PB16";
+	};
+	spi3_pins: spi3-pins {
+		function = "spi3";
+		pins = "PB17", "PB18", "PB19", "PB20", "PB21";
+	};
+	spi3_slave_pins: spi3-slave-pins {
+		function = "spi3";
+		pins = "PB18", "PB19", "PB20";
+	};
+	mclk0_pins: mclk0-pin {
+		function = "mclk0";
+		pins = "PB22";
+	};
+};
diff --git a/arch/mips/boot/dts/mobileye/eyeq5.dtsi b/arch/mips/boot/dts/mobileye/eyeq5.dtsi
index 6cc5980e2fa1..0708771c193d 100644
--- a/arch/mips/boot/dts/mobileye/eyeq5.dtsi
+++ b/arch/mips/boot/dts/mobileye/eyeq5.dtsi
@@ -5,7 +5,7 @@
 
 #include <dt-bindings/interrupt-controller/mips-gic.h>
 
-#include "eyeq5-fixed-clocks.dtsi"
+#include "eyeq5-clocks.dtsi"
 
 / {
 	#address-cells = <2>;
@@ -78,6 +78,9 @@ uart0: serial@800000 {
 			interrupts = <GIC_SHARED 6 IRQ_TYPE_LEVEL_HIGH>;
 			clocks  = <&uart_clk>, <&occ_periph>;
 			clock-names = "uartclk", "apb_pclk";
+			resets = <&olb 0 10>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart0_pins>;
 		};
 
 		uart1: serial@900000 {
@@ -88,6 +91,9 @@ uart1: serial@900000 {
 			interrupts = <GIC_SHARED 6 IRQ_TYPE_LEVEL_HIGH>;
 			clocks  = <&uart_clk>, <&occ_periph>;
 			clock-names = "uartclk", "apb_pclk";
+			resets = <&olb 0 11>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart1_pins>;
 		};
 
 		uart2: serial@a00000 {
@@ -98,6 +104,18 @@ uart2: serial@a00000 {
 			interrupts = <GIC_SHARED 6 IRQ_TYPE_LEVEL_HIGH>;
 			clocks  = <&uart_clk>, <&occ_periph>;
 			clock-names = "uartclk", "apb_pclk";
+			resets = <&olb 0 12>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart2_pins>;
+		};
+
+		olb: system-controller@e00000 {
+			compatible = "mobileye,eyeq5-olb", "syscon";
+			reg = <0 0xe00000 0x0 0x400>;
+			#reset-cells = <2>;
+			#clock-cells = <1>;
+			clocks = <&xtal>;
+			clock-names = "ref";
 		};
 
 		gic: interrupt-controller@140000 {
@@ -122,3 +140,5 @@ timer {
 		};
 	};
 };
+
+#include "eyeq5-pins.dtsi"

-- 
2.45.2


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

* Re: [PATCH v3 2/9] Revert "dt-bindings: reset: mobileye,eyeq5-reset: add bindings"
  2024-06-20 17:30 ` [PATCH v3 2/9] Revert "dt-bindings: reset: mobileye,eyeq5-reset: " Théo Lebrun
@ 2024-06-20 18:26   ` Rob Herring (Arm)
  2024-06-24 20:20     ` Rob Herring
  2024-06-24 20:56   ` Rob Herring (Arm)
  1 sibling, 1 reply; 21+ messages in thread
From: Rob Herring (Arm) @ 2024-06-20 18:26 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Thomas Petazzoni, Linus Walleij, Rafael J. Wysocki, Conor Dooley,
	Krzysztof Kozlowski, Stephen Boyd, Gregory CLEMENT,
	Michael Turquette, Vladimir Kondratiev, linux-gpio, Lee Jones,
	linux-clk, linux-mips, Tawfik Bayouk, Philipp Zabel, linux-kernel,
	Thomas Bogendoerfer, Greg Kroah-Hartman, devicetree


On Thu, 20 Jun 2024 19:30:54 +0200, Théo Lebrun wrote:
> Switch from one sub-node per functionality in the system-controller to a
> single node representing the entire OLB instance. This is the
> recommended approach for controllers handling many different
> functionalities; it is a single controller and should be represented by
> a single devicetree node.
> 
> The reset bindings is removed and all properties will be described by:
> soc/mobileye/mobileye,eyeq5-olb.yaml
> 
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  .../bindings/reset/mobileye,eyeq5-reset.yaml       | 43 ----------------------
>  1 file changed, 43 deletions(-)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/sound/st,stm32-sai.example.dtb: /example-0/sai@4400b000/audio-controller@4400b004: failed to match any schema with compatible: ['st,stm32-sai-sub-a']
Documentation/devicetree/bindings/net/wireless/qcom,ath11k.example.dtb: /example-0/remoteproc@cd00000: failed to match any schema with compatible: ['qcom,ipq8074-wcss-pil']
Documentation/devicetree/bindings/thermal/brcm,avs-ro-thermal.example.dtb: /example-0/avs-monitor@7d5d2000: failed to match any schema with compatible: ['brcm,bcm2711-avs-monitor', 'syscon', 'simple-mfd']
Documentation/devicetree/bindings/clock/sprd,sc9863a-clk.example.dtb: /example-1/syscon@20e00000: failed to match any schema with compatible: ['sprd,sc9863a-glbregs', 'syscon', 'simple-mfd']
Documentation/devicetree/bindings/clock/milbeaut-clock.example.dtb: /example-2/serial@1e700010: failed to match any schema with compatible: ['socionext,milbeaut-usio-uart']
Documentation/devicetree/bindings/arm/hisilicon/controller/hi3798cv200-perictrl.example.dtb: /example-0/peripheral-controller@8a20000/phy@850: failed to match any schema with compatible: ['hisilicon,hi3798cv200-combphy']
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/arm/stm32/st,mlahb.example.dtb: ahb@38000000: Unevaluated properties are not allowed ('reg' was unexpected)
	from schema $id: http://devicetree.org/schemas/arm/stm32/st,mlahb.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240620-mbly-olb-v3-2-5f29f8ca289c@bootlin.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


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

* Re: [PATCH v3 4/9] dt-bindings: soc: mobileye: add EyeQ OLB system controller
  2024-06-20 17:30 ` [PATCH v3 4/9] dt-bindings: soc: mobileye: add EyeQ OLB system controller Théo Lebrun
@ 2024-06-20 18:26   ` Rob Herring (Arm)
  2024-06-24 20:56   ` Rob Herring (Arm)
  1 sibling, 0 replies; 21+ messages in thread
From: Rob Herring (Arm) @ 2024-06-20 18:26 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Rafael J. Wysocki, Tawfik Bayouk, Philipp Zabel, Gregory CLEMENT,
	linux-clk, Thomas Petazzoni, Krzysztof Kozlowski,
	Thomas Bogendoerfer, Greg Kroah-Hartman, Conor Dooley,
	Michael Turquette, Lee Jones, Linus Walleij, linux-gpio,
	devicetree, Stephen Boyd, Vladimir Kondratiev, linux-kernel,
	linux-mips


On Thu, 20 Jun 2024 19:30:56 +0200, Théo Lebrun wrote:
> Add documentation to describe the "Other Logic Block" system-controller.
> It deals with three platforms: EyeQ5, EyeQ6L and EyeQ6H. First two have
> a single instance, whereas EyeQ6H has seven named instances.
> 
> Features provided are:
>  - Clocks, children to main crystal. Some PLLs and divider clocks.
>  - Resets. Some instances DO NOT have reset.
>  - Pinctrl. Only EyeQ5 has such feature.
> 
> Those are NOT the only features exposed in OLB system-controllers! Many
> individual registers, related to IP block integration, can be found.
> Additional features will be exposed over time.
> 
> We simplify devicetree phandles to OLB in two ways:
> 
>  - Compatibles exposing a single clock do not ask for a index argument.
>    This means we use EyeQ6H OLB south (it has four clocks):
> 
>       clocks = <&olb_south EQ6HC_SOUTH_PLL_PER>;
> 
>    But use EyeQ6H OLB east (it has one clock):
> 
>       clocks = <&olb_east>;
> 
>  - Compatibles exposing a single reset domain do not ask for a domain
>    index, only a reset index.
>    This means we use EyeQ5 OLB (it has three domains):
> 
>      resets = <&olb 0 10>;
> 
>    But use EyeQ6H west reset (it has one domain):
> 
>       resets = <&olb_west 3>;
> 
> About pinctrl subnodes: all pins have two functionality, either GPIO or
> something-else. The latter is pin dependent, we express constraints
> using many if-then.
> 
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  .../bindings/soc/mobileye/mobileye,eyeq5-olb.yaml  | 374 +++++++++++++++++++++
>  MAINTAINERS                                        |   2 +
>  include/dt-bindings/clock/mobileye,eyeq5-clk.h     |  21 ++
>  3 files changed, 397 insertions(+)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/usb/realtek,rts5411.yaml: ^.*@[1-4]$: Missing additionalProperties/unevaluatedProperties constraint

/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/pci/qcom,pcie-sm8350.yaml: oneOf: Missing additionalProperties/unevaluatedProperties constraint

/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/pci/qcom,pcie-sm8350.yaml: oneOf: Missing additionalProperties/unevaluatedProperties constraint

/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml: ^.*@[0-9a-f]+$: Missing additionalProperties/unevaluatedProperties constraint

Documentation/devicetree/bindings/sound/st,stm32-sai.example.dtb: /example-0/sai@4400b000/audio-controller@4400b004: failed to match any schema with compatible: ['st,stm32-sai-sub-a']
Documentation/devicetree/bindings/net/wireless/qcom,ath11k.example.dtb: /example-0/remoteproc@cd00000: failed to match any schema with compatible: ['qcom,ipq8074-wcss-pil']
Documentation/devicetree/bindings/thermal/brcm,avs-ro-thermal.example.dtb: /example-0/avs-monitor@7d5d2000: failed to match any schema with compatible: ['brcm,bcm2711-avs-monitor', 'syscon', 'simple-mfd']
Documentation/devicetree/bindings/clock/sprd,sc9863a-clk.example.dtb: /example-1/syscon@20e00000: failed to match any schema with compatible: ['sprd,sc9863a-glbregs', 'syscon', 'simple-mfd']
Documentation/devicetree/bindings/clock/milbeaut-clock.example.dtb: /example-2/serial@1e700010: failed to match any schema with compatible: ['socionext,milbeaut-usio-uart']
Documentation/devicetree/bindings/arm/hisilicon/controller/hi3798cv200-perictrl.example.dtb: /example-0/peripheral-controller@8a20000/phy@850: failed to match any schema with compatible: ['hisilicon,hi3798cv200-combphy']
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/arm/stm32/st,mlahb.example.dtb: ahb@38000000: Unevaluated properties are not allowed ('reg' was unexpected)
	from schema $id: http://devicetree.org/schemas/arm/stm32/st,mlahb.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240620-mbly-olb-v3-4-5f29f8ca289c@bootlin.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


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

* Re: [PATCH v3 2/9] Revert "dt-bindings: reset: mobileye,eyeq5-reset: add bindings"
  2024-06-20 18:26   ` Rob Herring (Arm)
@ 2024-06-24 20:20     ` Rob Herring
  0 siblings, 0 replies; 21+ messages in thread
From: Rob Herring @ 2024-06-24 20:20 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Thomas Petazzoni, Linus Walleij, Rafael J. Wysocki, Conor Dooley,
	Krzysztof Kozlowski, Stephen Boyd, Gregory CLEMENT,
	Michael Turquette, Vladimir Kondratiev, linux-gpio, Lee Jones,
	linux-clk, linux-mips, Tawfik Bayouk, Philipp Zabel, linux-kernel,
	Thomas Bogendoerfer, Greg Kroah-Hartman, devicetree

On Thu, Jun 20, 2024 at 12:26:57PM -0600, Rob Herring (Arm) wrote:
> 
> On Thu, 20 Jun 2024 19:30:54 +0200, Théo Lebrun wrote:
> > Switch from one sub-node per functionality in the system-controller to a
> > single node representing the entire OLB instance. This is the
> > recommended approach for controllers handling many different
> > functionalities; it is a single controller and should be represented by
> > a single devicetree node.
> > 
> > The reset bindings is removed and all properties will be described by:
> > soc/mobileye/mobileye,eyeq5-olb.yaml
> > 
> > Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> > ---
> >  .../bindings/reset/mobileye,eyeq5-reset.yaml       | 43 ----------------------
> >  1 file changed, 43 deletions(-)
> > 
> 
> My bot found errors running 'make dt_binding_check' on your patch:
> 
> yamllint warnings/errors:
> 
> dtschema/dtc warnings/errors:
> Documentation/devicetree/bindings/sound/st,stm32-sai.example.dtb: /example-0/sai@4400b000/audio-controller@4400b004: failed to match any schema with compatible: ['st,stm32-sai-sub-a']
> Documentation/devicetree/bindings/net/wireless/qcom,ath11k.example.dtb: /example-0/remoteproc@cd00000: failed to match any schema with compatible: ['qcom,ipq8074-wcss-pil']
> Documentation/devicetree/bindings/thermal/brcm,avs-ro-thermal.example.dtb: /example-0/avs-monitor@7d5d2000: failed to match any schema with compatible: ['brcm,bcm2711-avs-monitor', 'syscon', 'simple-mfd']
> Documentation/devicetree/bindings/clock/sprd,sc9863a-clk.example.dtb: /example-1/syscon@20e00000: failed to match any schema with compatible: ['sprd,sc9863a-glbregs', 'syscon', 'simple-mfd']
> Documentation/devicetree/bindings/clock/milbeaut-clock.example.dtb: /example-2/serial@1e700010: failed to match any schema with compatible: ['socionext,milbeaut-usio-uart']
> Documentation/devicetree/bindings/arm/hisilicon/controller/hi3798cv200-perictrl.example.dtb: /example-0/peripheral-controller@8a20000/phy@850: failed to match any schema with compatible: ['hisilicon,hi3798cv200-combphy']
> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/arm/stm32/st,mlahb.example.dtb: ahb@38000000: Unevaluated properties are not allowed ('reg' was unexpected)
> 	from schema $id: http://devicetree.org/schemas/arm/stm32/st,mlahb.yaml#

Not sure what happened here, but this can be ignored.

Rob

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

* Re: [PATCH v3 1/9] Revert "dt-bindings: clock: mobileye,eyeq5-clk: add bindings"
  2024-06-20 17:30 ` [PATCH v3 1/9] Revert "dt-bindings: clock: mobileye,eyeq5-clk: add bindings" Théo Lebrun
@ 2024-06-24 20:55   ` Rob Herring (Arm)
  0 siblings, 0 replies; 21+ messages in thread
From: Rob Herring (Arm) @ 2024-06-24 20:55 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Stephen Boyd, Thomas Petazzoni, Michael Turquette, linux-clk,
	linux-mips, devicetree, Tawfik Bayouk, Lee Jones,
	Thomas Bogendoerfer, Rafael J. Wysocki, Philipp Zabel,
	Vladimir Kondratiev, linux-gpio, Gregory CLEMENT,
	Greg Kroah-Hartman, Krzysztof Kozlowski, Linus Walleij,
	linux-kernel, Conor Dooley


On Thu, 20 Jun 2024 19:30:53 +0200, Théo Lebrun wrote:
> Switch from one sub-node per functionality in the system-controller to a
> single node representing the entire OLB instance. This is the
> recommended approach for controllers handling many different
> functionalities; it is a single controller and should be represented by
> a single devicetree node.
> 
> The clock bindings is removed and all properties will be described by:
> soc/mobileye/mobileye,eyeq5-olb.yaml
> 
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  .../bindings/clock/mobileye,eyeq5-clk.yaml         | 51 ----------------------
>  1 file changed, 51 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>


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

* Re: [PATCH v3 2/9] Revert "dt-bindings: reset: mobileye,eyeq5-reset: add bindings"
  2024-06-20 17:30 ` [PATCH v3 2/9] Revert "dt-bindings: reset: mobileye,eyeq5-reset: " Théo Lebrun
  2024-06-20 18:26   ` Rob Herring (Arm)
@ 2024-06-24 20:56   ` Rob Herring (Arm)
  1 sibling, 0 replies; 21+ messages in thread
From: Rob Herring (Arm) @ 2024-06-24 20:56 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Greg Kroah-Hartman, linux-gpio, linux-clk, linux-kernel,
	linux-mips, Michael Turquette, Tawfik Bayouk, Conor Dooley,
	Linus Walleij, Thomas Petazzoni, Vladimir Kondratiev,
	Gregory CLEMENT, Philipp Zabel, Thomas Bogendoerfer, Stephen Boyd,
	Lee Jones, Rafael J. Wysocki, Krzysztof Kozlowski, devicetree


On Thu, 20 Jun 2024 19:30:54 +0200, Théo Lebrun wrote:
> Switch from one sub-node per functionality in the system-controller to a
> single node representing the entire OLB instance. This is the
> recommended approach for controllers handling many different
> functionalities; it is a single controller and should be represented by
> a single devicetree node.
> 
> The reset bindings is removed and all properties will be described by:
> soc/mobileye/mobileye,eyeq5-olb.yaml
> 
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  .../bindings/reset/mobileye,eyeq5-reset.yaml       | 43 ----------------------
>  1 file changed, 43 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>


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

* Re: [PATCH v3 3/9] Revert "dt-bindings: pinctrl: mobileye,eyeq5-pinctrl: add bindings"
  2024-06-20 17:30 ` [PATCH v3 3/9] Revert "dt-bindings: pinctrl: mobileye,eyeq5-pinctrl: " Théo Lebrun
@ 2024-06-24 20:56   ` Rob Herring (Arm)
  2024-06-26 11:53   ` Linus Walleij
  1 sibling, 0 replies; 21+ messages in thread
From: Rob Herring (Arm) @ 2024-06-24 20:56 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: linux-gpio, Greg Kroah-Hartman, Gregory CLEMENT, linux-clk,
	Rafael J. Wysocki, Thomas Petazzoni, Krzysztof Kozlowski,
	linux-kernel, Vladimir Kondratiev, Lee Jones, Linus Walleij,
	Philipp Zabel, devicetree, Conor Dooley, Tawfik Bayouk,
	Thomas Bogendoerfer, Stephen Boyd, linux-mips, Michael Turquette


On Thu, 20 Jun 2024 19:30:55 +0200, Théo Lebrun wrote:
> Switch from one sub-node per functionality in the system-controller to a
> single node representing the entire OLB instance. This is the
> recommended approach for controllers handling many different
> functionalities; it is a single controller and should be represented by
> a single devicetree node.
> 
> The pinctrl bindings is removed and all properties will be described by:
> soc/mobileye/mobileye,eyeq5-olb.yaml
> 
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  .../bindings/pinctrl/mobileye,eyeq5-pinctrl.yaml   | 242 ---------------------
>  1 file changed, 242 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>


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

* Re: [PATCH v3 4/9] dt-bindings: soc: mobileye: add EyeQ OLB system controller
  2024-06-20 17:30 ` [PATCH v3 4/9] dt-bindings: soc: mobileye: add EyeQ OLB system controller Théo Lebrun
  2024-06-20 18:26   ` Rob Herring (Arm)
@ 2024-06-24 20:56   ` Rob Herring (Arm)
  1 sibling, 0 replies; 21+ messages in thread
From: Rob Herring (Arm) @ 2024-06-24 20:56 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Thomas Petazzoni, Linus Walleij, Stephen Boyd, Michael Turquette,
	linux-mips, linux-kernel, Vladimir Kondratiev, linux-gpio,
	Thomas Bogendoerfer, linux-clk, Rafael J. Wysocki, Tawfik Bayouk,
	Lee Jones, Conor Dooley, Greg Kroah-Hartman, devicetree,
	Philipp Zabel, Krzysztof Kozlowski, Gregory CLEMENT


On Thu, 20 Jun 2024 19:30:56 +0200, Théo Lebrun wrote:
> Add documentation to describe the "Other Logic Block" system-controller.
> It deals with three platforms: EyeQ5, EyeQ6L and EyeQ6H. First two have
> a single instance, whereas EyeQ6H has seven named instances.
> 
> Features provided are:
>  - Clocks, children to main crystal. Some PLLs and divider clocks.
>  - Resets. Some instances DO NOT have reset.
>  - Pinctrl. Only EyeQ5 has such feature.
> 
> Those are NOT the only features exposed in OLB system-controllers! Many
> individual registers, related to IP block integration, can be found.
> Additional features will be exposed over time.
> 
> We simplify devicetree phandles to OLB in two ways:
> 
>  - Compatibles exposing a single clock do not ask for a index argument.
>    This means we use EyeQ6H OLB south (it has four clocks):
> 
>       clocks = <&olb_south EQ6HC_SOUTH_PLL_PER>;
> 
>    But use EyeQ6H OLB east (it has one clock):
> 
>       clocks = <&olb_east>;
> 
>  - Compatibles exposing a single reset domain do not ask for a domain
>    index, only a reset index.
>    This means we use EyeQ5 OLB (it has three domains):
> 
>      resets = <&olb 0 10>;
> 
>    But use EyeQ6H west reset (it has one domain):
> 
>       resets = <&olb_west 3>;
> 
> About pinctrl subnodes: all pins have two functionality, either GPIO or
> something-else. The latter is pin dependent, we express constraints
> using many if-then.
> 
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  .../bindings/soc/mobileye/mobileye,eyeq5-olb.yaml  | 374 +++++++++++++++++++++
>  MAINTAINERS                                        |   2 +
>  include/dt-bindings/clock/mobileye,eyeq5-clk.h     |  21 ++
>  3 files changed, 397 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>


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

* Re: [PATCH v3 7/9] reset: eyeq: add platform driver
  2024-06-20 17:30 ` [PATCH v3 7/9] reset: eyeq: add platform driver Théo Lebrun
@ 2024-06-25  9:17   ` Philipp Zabel
  2024-06-26 13:55     ` Théo Lebrun
  0 siblings, 1 reply; 21+ messages in thread
From: Philipp Zabel @ 2024-06-25  9:17 UTC (permalink / raw)
  To: Théo Lebrun, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Linus Walleij,
	Greg Kroah-Hartman, Rafael J. Wysocki, Lee Jones,
	Thomas Bogendoerfer
  Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
	Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
	Tawfik Bayouk

Hi,

On Do, 2024-06-20 at 19:30 +0200, Théo Lebrun wrote:
> Add Mobileye EyeQ reset controller driver, for EyeQ5, EyeQ6L and EyeQ6H
> SoCs. Instances belong to a shared register region called OLB and gets
> spawned as auxiliary device to the platform driver for clock.
> 
> There is one OLB instance for EyeQ5 and EyeQ6L. There are seven OLB
> instances on EyeQ6H; three have a reset controller embedded:
>  - West and east get handled by the same compatible.
>  - Acc (accelerator) is another one.
> 
> Each instance vary in the number and types of reset domains.
> Instances with single domain expect a single cell, others two.
> 
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  MAINTAINERS                |   1 +
>  drivers/reset/Kconfig      |  14 ++
>  drivers/reset/Makefile     |   1 +
>  drivers/reset/reset-eyeq.c | 563 +++++++++++++++++++++++++++++++++++++++++++++

Should this be called reset-eyeq-olb or reset-eyeq5, in case a
different eyeq driver will have to be added in the future?

>  4 files changed, 579 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index f386e9da2cd0..36f4001c7f51 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -14931,6 +14931,7 @@ F:	arch/mips/boot/dts/mobileye/
>  F:	arch/mips/configs/eyeq5_defconfig
>  F:	arch/mips/mobileye/board-epm5.its.S
>  F:	drivers/clk/clk-eyeq5.c
> +F:	drivers/reset/reset-eyeq5.c

See above, and this should match the actual file name.

Adding the MAINTAINERS change in the driver patches makes these patches
depend on each other. Otherwise they could be applied independently. Do
you intend this series to be merged together in one tree?

>  F:	include/dt-bindings/clock/mobileye,eyeq5-clk.h
>  
>  MODULE SUPPORT
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index 85b27c42cf65..b79c18b75674 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -66,6 +66,20 @@ config RESET_BRCMSTB_RESCAL
>  	  This enables the RESCAL reset controller for SATA, PCIe0, or PCIe1 on
>  	  BCM7216.
>  
> +config RESET_EYEQ
> +	bool "Mobileye EyeQ reset controller"
> +	depends on COMMON_CLK_EYEQ

Is this a real dependency? It seems to compile just fine without it.
Please allow building under COMPILE_TEST without COMMON_CLK_EYEQ set.

> +	depends on MFD_SYSCON
> +	depends on MACH_EYEQ5 || MACH_EYEQ6H || COMPILE_TEST
> +	default MACH_EYEQ5 || MACH_EYEQ6H
> +	help
> +	  This enables the Mobileye EyeQ reset controller, used in EyeQ5, EyeQ6L
> +	  and EyeQ6H SoCs.
> +
> +	  It has one or more domains, with a varying number of resets in each.
> +	  Registers are located in a shared register region called OLB. EyeQ6H
> +	  has multiple reset instances.
> +
>  config RESET_GPIO
>  	tristate "GPIO reset controller"
>  	help
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index fd8b49fa46fc..a4e6fea29800 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -11,6 +11,7 @@ obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o
>  obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
>  obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o
>  obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o
> +obj-$(CONFIG_RESET_EYEQ) += reset-eyeq.o
>  obj-$(CONFIG_RESET_GPIO) += reset-gpio.o
>  obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
>  obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
> diff --git a/drivers/reset/reset-eyeq.c b/drivers/reset/reset-eyeq.c
> new file mode 100644
> index 000000000000..03a3f2d06cff
> --- /dev/null
> +++ b/drivers/reset/reset-eyeq.c
> @@ -0,0 +1,563 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Reset driver for the Mobileye EyeQ5, EyeQ6L and EyeQ6H platforms.
> + *
> + * Controllers live in a shared register region called OLB. EyeQ5 and EyeQ6L
> + * have a single OLB instance for a single reset controller. EyeQ6H has seven
> + * OLB instances; three host reset controllers.
> + *
> + * Each reset controller has one or more domain. Domains are of a given type
> + * (see enum eqr_domain_type), with a valid offset mask (up to 32 resets per
> + * domain).
> + *
> + * Domain types define expected behavior: one-register-per-reset,
> + * one-bit-per-reset, status detection method, busywait duration, etc.
> + *
> + * We use eqr_ as prefix, as-in "EyeQ Reset", but way shorter.
> + *
> + * Known resets in EyeQ5 domain 0 (type EQR_EYEQ5_SARCR):
> + *  3. CAN0	 4. CAN1	 5. CAN2	 6. SPI0
> + *  7. SPI1	 8. SPI2	 9. SPI3	10. UART0
> + * 11. UART1	12. UART2	13. I2C0	14. I2C1
> + * 15. I2C2	16. I2C3	17. I2C4	18. TIMER0
> + * 19. TIMER1	20. TIMER2	21. TIMER3	22. TIMER4
> + * 23. WD0	24. EXT0	25. EXT1	26. GPIO
> + * 27. WD1
> + *
> + * Known resets in EyeQ5 domain 1 (type EQR_EYEQ5_ACRP):
> + *  0. VMP0	 1. VMP1	 2. VMP2	 3. VMP3
> + *  4. PMA0	 5. PMA1	 6. PMAC0	 7. PMAC1
> + *  8. MPC0	 9. MPC1	10. MPC2	11. MPC3
> + * 12. MPC4
> + *
> + * Known resets in EyeQ5 domain 2 (type EQR_EYEQ5_PCIE):
> + *  0. PCIE0_CORE	 1. PCIE0_APB		 2. PCIE0_LINK_AXI	 3. PCIE0_LINK_MGMT
> + *  4. PCIE0_LINK_HOT	 5. PCIE0_LINK_PIPE	 6. PCIE1_CORE		 7. PCIE1_APB
> + *  8. PCIE1_LINK_AXI	 9. PCIE1_LINK_MGMT	10. PCIE1_LINK_HOT	11. PCIE1_LINK_PIPE
> + * 12. MULTIPHY		13. MULTIPHY_APB	15. PCIE0_LINK_MGMT	16. PCIE1_LINK_MGMT
> + * 17. PCIE0_LINK_PM	18. PCIE1_LINK_PM
> + *
> + * Known resets in EyeQ6L domain 0 (type EQR_EYEQ5_SARCR):
> + *  0. SPI0	 1. SPI1	 2. UART0	 3. I2C0
> + *  4. I2C1	 5. TIMER0	 6. TIMER1	 7. TIMER2
> + *  8. TIMER3	 9. WD0		10. WD1		11. EXT0
> + * 12. EXT1	13. GPIO
> + *
> + * Known resets in EyeQ6L domain 1 (type EQR_EYEQ5_ACRP):
> + *  0. VMP0	 1. VMP1	 2. VMP2	 3. VMP3
> + *  4. PMA0	 5. PMA1	 6. PMAC0	 7. PMAC1
> + *  8. MPC0	 9. MPC1	10. MPC2	11. MPC3
> + * 12. MPC4
> + *
> + * Known resets in EyeQ6H west/east (type EQR_EYEQ6H_SARCR):
> + *  0. CAN	 1. SPI0	 2. SPI1	 3. UART0
> + *  4. UART1	 5. I2C0	 6. I2C1	 7. -hole-
> + *  8. TIMER0	 9. TIMER1	10. WD		11. EXT TIMER
> + * 12. GPIO
> + *
> + * Known resets in EyeQ6H acc (type EQR_EYEQ5_ACRP):
> + *  1. XNN0	 2. XNN1	 3. XNN2	 4. XNN3
> + *  5. VMP0	 6. VMP1	 7. VMP2	 8. VMP3
> + *  9. PMA0	10. PMA1	11. MPC0	12. MPC1
> + * 13. MPC2	14. MPC3	15. PERIPH
> + *
> + * Abbreviations:
> + *  - PMA: Programmable Macro Array
> + *  - MPC: Multi-threaded Processing Clusters
> + *  - VMP: Vector Microcode Processors
> + *
> + * Copyright (C) 2024 Mobileye Vision Technologies Ltd.
> + */
> +
> +#include <linux/array_size.h>
> +#include <linux/auxiliary_bus.h>
> +#include <linux/bitfield.h>
> +#include <linux/bits.h>
> +#include <linux/bug.h>
> +#include <linux/cleanup.h>
> +#include <linux/container_of.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/errno.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/lockdep.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/mutex.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>

Not needed, this being an aux driver now. Please check the other
headers as well.

> +#include <linux/reset-controller.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +
> +/*
> + * A reset ID, as returned by eqr_of_xlate_*(), is a (domain, offset) pair.
> + * Low byte is domain, rest is offset.
> + */
> +#define ID_DOMAIN_MASK	GENMASK(7, 0)
> +#define ID_OFFSET_MASK	GENMASK(31, 8)
> +
> +enum eqr_domain_type {
> +	EQR_EYEQ5_SARCR,
> +	EQR_EYEQ5_ACRP,
> +	EQR_EYEQ5_PCIE,
> +	EQR_EYEQ6H_SARCR,
> +};
> +
> +/*
> + * Domain type EQR_EYEQ5_SARCR register offsets.
> + */
> +#define EQR_EYEQ5_SARCR_REQUEST		(0x000)
> +#define EQR_EYEQ5_SARCR_STATUS		(0x004)
> +
> +/*
> + * Domain type EQR_EYEQ5_ACRP register masks.
> + * Registers are: base + 4 * offset.
> + */
> +#define EQR_EYEQ5_ACRP_PD_REQ		BIT(0)
> +#define EQR_EYEQ5_ACRP_ST_POWER_DOWN	BIT(27)
> +#define EQR_EYEQ5_ACRP_ST_ACTIVE	BIT(29)
> +
> +/*
> + * Domain type EQR_EYEQ6H_SARCR register offsets.
> + */
> +#define EQR_EYEQ6H_SARCR_RST_REQUEST	(0x000)
> +#define EQR_EYEQ6H_SARCR_CLK_STATUS	(0x004)
> +#define EQR_EYEQ6H_SARCR_RST_STATUS	(0x008)
> +#define EQR_EYEQ6H_SARCR_CLK_REQUEST	(0x00C)
> +
> +struct eqr_busy_wait_timings {
> +	unsigned long sleep_us;
> +	unsigned long timeout_us;
> +};
> +
> +static const struct eqr_busy_wait_timings eqr_timings[] = {
> +	[EQR_EYEQ5_SARCR]	= {1, 10},
> +	[EQR_EYEQ5_ACRP]	= {1, 40 * USEC_PER_MSEC}, /* LBIST implies long timeout. */
> +	/* EQR_EYEQ5_PCIE does no busy waiting. */
> +	[EQR_EYEQ6H_SARCR]	= {1, 400},
> +};
> +
> +#define EQR_MAX_DOMAIN_COUNT 3
> +
> +struct eqr_domain_descriptor {
> +	enum eqr_domain_type	type;
> +	u32			valid_mask;
> +	unsigned int		offset;
> +};
> +
> +struct eqr_match_data {
> +	unsigned int				domain_count;
> +	const struct eqr_domain_descriptor	*domains;
> +};
> +
> +struct eqr_private {
> +	struct mutex			mutexes[EQR_MAX_DOMAIN_COUNT];
> +	void __iomem			*base;
> +	const struct eqr_match_data	*data;
> +	struct reset_controller_dev	rcdev;
> +};
> +
> +#define rcdev_to_priv(rcdev) container_of(rcdev, struct eqr_private, rcdev)
> +
> +static u32 eqr_double_readl(void __iomem *addr_a, void __iomem *addr_b,
> +			    u32 *dest_a, u32 *dest_b)
> +{
> +	*dest_a = readl(addr_a);
> +	*dest_b = readl(addr_b);
> +	return 0; /* read_poll_timeout() op argument must return something. */
> +}
> +
> +static int eqr_busy_wait_locked(struct eqr_private *priv, struct device *dev,
> +				u32 domain, u32 offset, bool assert)
> +{
> +	enum eqr_domain_type domain_type = priv->data->domains[domain].type;
> +	unsigned long sleep_us, timeout_us;
> +	u32 val, mask, val0, val1;
> +	void __iomem *base, *reg;
> +	int ret;
> +
> +	lockdep_assert_held(&priv->mutexes[domain]);
> +
> +	base = priv->base + priv->data->domains[domain].offset;
> +	sleep_us = eqr_timings[domain_type].sleep_us;
> +	timeout_us = eqr_timings[domain_type].timeout_us;
> +
> +	switch (domain_type) {
> +	case EQR_EYEQ5_SARCR:
> +		reg = base + EQR_EYEQ5_SARCR_STATUS;
> +		mask = BIT(offset);
> +
> +		ret = readl_poll_timeout(reg, val, !(val & mask) == assert,
> +					 sleep_us, timeout_us);
> +		break;
> +
> +	case EQR_EYEQ5_ACRP:
> +		reg = base + 4 * offset;
> +		if (assert)
> +			mask = EQR_EYEQ5_ACRP_ST_POWER_DOWN;
> +		else
> +			mask = EQR_EYEQ5_ACRP_ST_ACTIVE;
> +
> +		ret = readl_poll_timeout(reg, val, !!(val & mask),
> +					 sleep_us, timeout_us);
> +		break;
> +
> +	case EQR_EYEQ5_PCIE:
> +		ret = 0; /* No busy waiting. */
> +		break;
> +
> +	case EQR_EYEQ6H_SARCR:
> +		/*
> +		 * Wait until both bits change:
> +		 *	readl(base + EQR_EYEQ6H_SARCR_RST_STATUS) & BIT(offset)
> +		 *	readl(base + EQR_EYEQ6H_SARCR_CLK_STATUS) & BIT(offset)
> +		 */
> +		mask = BIT(offset);
> +		ret = read_poll_timeout(eqr_double_readl, val,
> +					(!(val0 & mask) == assert) &&
> +						(!(val1 & mask) == assert),
> +					sleep_us, timeout_us, false,
> +					base + EQR_EYEQ6H_SARCR_RST_STATUS,
> +					base + EQR_EYEQ6H_SARCR_CLK_STATUS,
> +					&val0, &val1);
> +		break;
> +
> +	default:
> +		WARN_ON(1);
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	if (ret == -ETIMEDOUT)
> +		dev_dbg(dev, "%u-%u: timeout\n", domain, offset);
> +	return ret;
> +}
> +
> +static void eqr_assert_locked(struct eqr_private *priv, u32 domain, u32 offset)
> +{
> +	enum eqr_domain_type domain_type = priv->data->domains[domain].type;
> +	void __iomem *base, *reg;
> +	u32 val;
> +
> +	lockdep_assert_held(&priv->mutexes[domain]);
> +
> +	base = priv->base + priv->data->domains[domain].offset;
> +
> +	switch (domain_type) {
> +	case EQR_EYEQ5_SARCR:
> +		reg = base + EQR_EYEQ5_SARCR_REQUEST;
> +		writel(readl(reg) & ~BIT(offset), reg);
> +		break;
> +
> +	case EQR_EYEQ5_ACRP:
> +		reg = base + 4 * offset;
> +		writel(readl(reg) | EQR_EYEQ5_ACRP_PD_REQ, reg);
> +		break;
> +
> +	case EQR_EYEQ5_PCIE:
> +		writel(readl(base) & ~BIT(offset), base);
> +		break;
> +
> +	case EQR_EYEQ6H_SARCR:
> +		val = readl(base + EQR_EYEQ6H_SARCR_RST_REQUEST);
> +		val &= ~BIT(offset);
> +		writel(val, base + EQR_EYEQ6H_SARCR_RST_REQUEST);
> +		writel(val, base + EQR_EYEQ6H_SARCR_CLK_REQUEST);
> +		break;
> +
> +	default:
> +		WARN_ON(1);
> +		break;
> +	}
> +}
> +
> +static int eqr_assert(struct reset_controller_dev *rcdev, unsigned long id)
> +{
> +	struct eqr_private *priv = rcdev_to_priv(rcdev);
> +	u32 domain = FIELD_GET(ID_DOMAIN_MASK, id);
> +	u32 offset = FIELD_GET(ID_OFFSET_MASK, id);
> +
> +	dev_dbg(rcdev->dev, "%u-%u: assert request\n", domain, offset);
> +
> +	guard(mutex)(&priv->mutexes[domain]);
> +
> +	eqr_assert_locked(priv, domain, offset);
> +	return eqr_busy_wait_locked(priv, rcdev->dev, domain, offset, true);
> +}
> +
> +static void eqr_deassert_locked(struct eqr_private *priv, u32 domain,
> +				u32 offset)
> +{
> +	enum eqr_domain_type domain_type = priv->data->domains[domain].type;
> +	void __iomem *base, *reg;
> +	u32 val;
> +
> +	lockdep_assert_held(&priv->mutexes[domain]);
> +
> +	base = priv->base + priv->data->domains[domain].offset;
> +
> +	switch (domain_type) {
> +	case EQR_EYEQ5_SARCR:
> +		reg = base + EQR_EYEQ5_SARCR_REQUEST;
> +		writel(readl(reg) | BIT(offset), reg);
> +		break;
> +
> +	case EQR_EYEQ5_ACRP:
> +		reg = base + 4 * offset;
> +		writel(readl(reg) & ~EQR_EYEQ5_ACRP_PD_REQ, reg);
> +		break;
> +
> +	case EQR_EYEQ5_PCIE:
> +		writel(readl(base) | BIT(offset), base);
> +		break;
> +
> +	case EQR_EYEQ6H_SARCR:
> +		val = readl(base + EQR_EYEQ6H_SARCR_RST_REQUEST);
> +		val |= BIT(offset);
> +		writel(val, base + EQR_EYEQ6H_SARCR_RST_REQUEST);
> +		writel(val, base + EQR_EYEQ6H_SARCR_CLK_REQUEST);
> +		break;
> +
> +	default:
> +		WARN_ON(1);
> +		break;
> +	}
> +}
> +
> +static int eqr_deassert(struct reset_controller_dev *rcdev, unsigned long id)
> +{
> +	struct eqr_private *priv = rcdev_to_priv(rcdev);
> +	u32 domain = FIELD_GET(ID_DOMAIN_MASK, id);
> +	u32 offset = FIELD_GET(ID_OFFSET_MASK, id);
> +
> +	dev_dbg(rcdev->dev, "%u-%u: deassert request\n", domain, offset);
> +
> +	guard(mutex)(&priv->mutexes[domain]);
> +
> +	eqr_deassert_locked(priv, domain, offset);
> +	return eqr_busy_wait_locked(priv, rcdev->dev, domain, offset, false);
> +}
> +
> +static int eqr_status(struct reset_controller_dev *rcdev, unsigned long id)
> +{
> +	u32 domain = FIELD_GET(ID_DOMAIN_MASK, id);
> +	struct eqr_private *priv = rcdev_to_priv(rcdev);
> +	enum eqr_domain_type domain_type = priv->data->domains[domain].type;
> +	u32 offset = FIELD_GET(ID_OFFSET_MASK, id);
> +	void __iomem *base, *reg;
> +
> +	dev_dbg(rcdev->dev, "%u-%u: status request\n", domain, offset);
> +
> +	guard(mutex)(&priv->mutexes[domain]);
> +
> +	base = priv->base + priv->data->domains[domain].offset;
> +
> +	switch (domain_type) {
> +	case EQR_EYEQ5_SARCR:
> +		reg = base + EQR_EYEQ5_SARCR_STATUS;
> +		return !(readl(reg) & BIT(offset));
> +	case EQR_EYEQ5_ACRP:
> +		reg = base + 4 * offset;
> +		return !(readl(reg) & EQR_EYEQ5_ACRP_ST_ACTIVE);
> +	case EQR_EYEQ5_PCIE:
> +		return !(readl(base) & BIT(offset));
> +	case EQR_EYEQ6H_SARCR:
> +		reg = base + EQR_EYEQ6H_SARCR_RST_STATUS;
> +		return !(readl(reg) & BIT(offset));
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static const struct reset_control_ops eqr_ops = {
> +	.assert	  = eqr_assert,
> +	.deassert = eqr_deassert,
> +	.status	  = eqr_status,
> +};
> +
> +static int eqr_of_xlate_internal(struct reset_controller_dev *rcdev,
> +				 u32 domain, u32 offset)
> +{
> +	struct eqr_private *priv = rcdev_to_priv(rcdev);
> +
> +	if (domain >= priv->data->domain_count || offset > 31 ||
> +	    !(priv->data->domains[domain].valid_mask & BIT(offset))) {
> +		dev_err(rcdev->dev, "%u-%u: invalid reset\n", domain, offset);
> +		return -EINVAL;
> +	}
> +
> +	return FIELD_PREP(ID_DOMAIN_MASK, domain) | FIELD_PREP(ID_OFFSET_MASK, offset);
> +}
> +
> +static int eqr_of_xlate_onecell(struct reset_controller_dev *rcdev,
> +				const struct of_phandle_args *reset_spec)
> +{
> +	return eqr_of_xlate_internal(rcdev, 0, reset_spec->args[0]);
> +}
> +
> +static int eqr_of_xlate_twocells(struct reset_controller_dev *rcdev,
> +				 const struct of_phandle_args *reset_spec)
> +{
> +	return eqr_of_xlate_internal(rcdev, reset_spec->args[0], reset_spec->args[1]);
> +}
> +
> +static int eqr_probe(struct auxiliary_device *adev,
> +		     const struct auxiliary_device_id *id)
> +{
> +	const struct of_device_id *match;
> +	struct device *dev = &adev->dev;
> +	struct eqr_private *priv;
> +	unsigned int i;
> +	int ret;
> +
> +	/*
> +	 * We are an auxiliary device of clk-eyeq. We do not have an OF node by
> +	 * default; let's reuse our parent's OF node.
> +	 */
> +	WARN_ON(dev->of_node);
> +	device_set_of_node_from_dev(dev, dev->parent);
> +	if (!dev->of_node)
> +		return -ENODEV;
> +
> +	/*
> +	 * Using our newfound OF node, we can get match data. We cannot use
> +	 * device_get_match_data() because it does not match reused OF nodes.
> +	 */
> +	match = of_match_node(dev->driver->of_match_table, dev->of_node);
> +	if (!match || !match->data)
> +		return -ENODEV;
> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->data = match->data;
> +	priv->base = dev_get_platdata(dev);

  drivers/reset/reset-eyeq.c:437:20: warning: incorrect type in assignment (different address spaces)
  drivers/reset/reset-eyeq.c:437:20:    expected void [noderef] __iomem *base
  drivers/reset/reset-eyeq.c:437:20:    got void *

I'd wrap this in a struct or explicitly cast to (void __iomem *) here.

> +	priv->rcdev.ops = &eqr_ops;
> +	priv->rcdev.owner = THIS_MODULE;
> +	priv->rcdev.dev = dev;
> +	priv->rcdev.of_node = dev->of_node;
> +
> +	if (priv->data->domain_count == 1) {
> +		priv->rcdev.of_reset_n_cells = 1;
> +		priv->rcdev.of_xlate = eqr_of_xlate_onecell;
> +	} else {
> +		priv->rcdev.of_reset_n_cells = 2;
> +		priv->rcdev.of_xlate = eqr_of_xlate_twocells;
> +	}
> +
> +	for (i = 0; i < priv->data->domain_count; i++)
> +		mutex_init(&priv->mutexes[i]);
> +
> +	priv->rcdev.nr_resets = 0;
> +	for (i = 0; i < priv->data->domain_count; i++)
> +		priv->rcdev.nr_resets += hweight32(priv->data->domains[i].valid_mask);
> +
> +	ret = devm_reset_controller_register(dev, &priv->rcdev);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "failed registering reset controller\n");
> +
> +	return 0;
> +}
> +
> +static const struct eqr_domain_descriptor eqr_eyeq5_domains[] = {
> +	{
> +		.type = EQR_EYEQ5_SARCR,
> +		.valid_mask = 0xFFFFFF8,
> +		.offset = 0x004,
> +	},
> +	{
> +		.type = EQR_EYEQ5_ACRP,
> +		.valid_mask = 0x0001FFF,
> +		.offset = 0x200,
> +	},
> +	{
> +		.type = EQR_EYEQ5_PCIE,
> +		.valid_mask = 0x007BFFF,
> +		.offset = 0x120,
> +	},
> +};
> +
> +static const struct eqr_match_data eqr_eyeq5_data = {
> +	.domain_count	= ARRAY_SIZE(eqr_eyeq5_domains),
> +	.domains	= eqr_eyeq5_domains,
> +};
> +
> +static const struct eqr_domain_descriptor eqr_eyeq6l_domains[] = {
> +	{
> +		.type = EQR_EYEQ5_SARCR,
> +		.valid_mask = 0x3FFF,
> +		.offset = 0x004,
> +	},
> +	{
> +		.type = EQR_EYEQ5_ACRP,
> +		.valid_mask = 0x00FF,
> +		.offset = 0x200,
> +	},
> +};
> +
> +static const struct eqr_match_data eqr_eyeq6l_data = {
> +	.domain_count	= ARRAY_SIZE(eqr_eyeq6l_domains),
> +	.domains	= eqr_eyeq6l_domains,
> +};
> +
> +/* West and east OLBs each have an instance. */
> +static const struct eqr_domain_descriptor eqr_eyeq6h_we_domains[] = {
> +	{
> +		.type = EQR_EYEQ6H_SARCR,
> +		.valid_mask = 0x1F7F,
> +		.offset = 0x004,
> +	},
> +};
> +
> +static const struct eqr_match_data eqr_eyeq6h_we_data = {
> +	.domain_count	= ARRAY_SIZE(eqr_eyeq6h_we_domains),
> +	.domains	= eqr_eyeq6h_we_domains,
> +};
> +
> +static const struct eqr_domain_descriptor eqr_eyeq6h_acc_domains[] = {
> +	{
> +		.type = EQR_EYEQ5_ACRP,
> +		.valid_mask = 0x7FFF,
> +		.offset = 0x000,
> +	},
> +};
> +
> +static const struct eqr_match_data eqr_eyeq6h_acc_data = {
> +	.domain_count	= ARRAY_SIZE(eqr_eyeq6h_acc_domains),
> +	.domains	= eqr_eyeq6h_acc_domains,
> +};
> +
> +/*
> + * Table describes OLB system-controller compatibles.
> + * It does not get used to match against devicetree node.
> + */
> +static const struct of_device_id eqr_match_table[] = {
> +	{ .compatible = "mobileye,eyeq5-olb", .data = &eqr_eyeq5_data },
> +	{ .compatible = "mobileye,eyeq6l-olb", .data = &eqr_eyeq6l_data },
> +	{ .compatible = "mobileye,eyeq6h-west-olb", .data = &eqr_eyeq6h_we_data },
> +	{ .compatible = "mobileye,eyeq6h-east-olb", .data = &eqr_eyeq6h_we_data },
> +	{ .compatible = "mobileye,eyeq6h-acc-olb", .data = &eqr_eyeq6h_acc_data },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, eqr_match_table);
> +
> +static const struct auxiliary_device_id eqr_id_table[] = {
> +	{ .name = "clk_eyeq.reset" },
> +	{ .name = "clk_eyeq.reset_west" },
> +	{ .name = "clk_eyeq.reset_east" },
> +	{ .name = "clk_eyeq.reset_acc" },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(auxiliary, eqr_id_table);
> +
> +static struct auxiliary_driver eqr_driver = {
> +	.probe = eqr_probe,
> +	.id_table = eqr_id_table,
> +	.driver = {
> +		.of_match_table = eqr_match_table,
> +	}
> +};
> +module_auxiliary_driver(eqr_driver);

regards
Philipp

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

* Re: [PATCH v3 3/9] Revert "dt-bindings: pinctrl: mobileye,eyeq5-pinctrl: add bindings"
  2024-06-20 17:30 ` [PATCH v3 3/9] Revert "dt-bindings: pinctrl: mobileye,eyeq5-pinctrl: " Théo Lebrun
  2024-06-24 20:56   ` Rob Herring (Arm)
@ 2024-06-26 11:53   ` Linus Walleij
  1 sibling, 0 replies; 21+ messages in thread
From: Linus Walleij @ 2024-06-26 11:53 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michael Turquette,
	Stephen Boyd, Philipp Zabel, Greg Kroah-Hartman,
	Rafael J. Wysocki, Lee Jones, Thomas Bogendoerfer, linux-mips,
	devicetree, linux-kernel, linux-clk, linux-gpio,
	Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
	Tawfik Bayouk

On Thu, Jun 20, 2024 at 7:31 PM Théo Lebrun <theo.lebrun@bootlin.com> wrote:

> Switch from one sub-node per functionality in the system-controller to a
> single node representing the entire OLB instance. This is the
> recommended approach for controllers handling many different
> functionalities; it is a single controller and should be represented by
> a single devicetree node.
>
> The pinctrl bindings is removed and all properties will be described by:
> soc/mobileye/mobileye,eyeq5-olb.yaml
>
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

* Re: [PATCH v3 7/9] reset: eyeq: add platform driver
  2024-06-25  9:17   ` Philipp Zabel
@ 2024-06-26 13:55     ` Théo Lebrun
  2024-06-26 14:10       ` Philipp Zabel
  0 siblings, 1 reply; 21+ messages in thread
From: Théo Lebrun @ 2024-06-26 13:55 UTC (permalink / raw)
  To: Philipp Zabel, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Linus Walleij,
	Greg Kroah-Hartman, Rafael J. Wysocki, Lee Jones,
	Thomas Bogendoerfer
  Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
	Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
	Tawfik Bayouk

Hello Philipp,

On Tue Jun 25, 2024 at 11:17 AM CEST, Philipp Zabel wrote:
> On Do, 2024-06-20 at 19:30 +0200, Théo Lebrun wrote:
> > Add Mobileye EyeQ reset controller driver, for EyeQ5, EyeQ6L and EyeQ6H
> > SoCs. Instances belong to a shared register region called OLB and gets
> > spawned as auxiliary device to the platform driver for clock.
> > 
> > There is one OLB instance for EyeQ5 and EyeQ6L. There are seven OLB
> > instances on EyeQ6H; three have a reset controller embedded:
> >  - West and east get handled by the same compatible.
> >  - Acc (accelerator) is another one.
> > 
> > Each instance vary in the number and types of reset domains.
> > Instances with single domain expect a single cell, others two.
> > 
> > Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> > ---
> >  MAINTAINERS                |   1 +
> >  drivers/reset/Kconfig      |  14 ++
> >  drivers/reset/Makefile     |   1 +
> >  drivers/reset/reset-eyeq.c | 563 +++++++++++++++++++++++++++++++++++++++++++++
>
> Should this be called reset-eyeq-olb or reset-eyeq5, in case a
> different eyeq driver will have to be added in the future?

What about keeping reset-eyeq for the simplicity of it and using
reset-eyeq7 for a theoretical future driver that gets used by EyeQ7 and
above? Or any other revision.

Else it can be reset-eyeq5. OLB might be a concept that gets reused with
different reset blocks inside (meaning reset-eyeq-olb wouldn't
distinguish). You tell me if keeping *-eyeq is fine.

> >  4 files changed, 579 insertions(+)
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index f386e9da2cd0..36f4001c7f51 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -14931,6 +14931,7 @@ F:	arch/mips/boot/dts/mobileye/
> >  F:	arch/mips/configs/eyeq5_defconfig
> >  F:	arch/mips/mobileye/board-epm5.its.S
> >  F:	drivers/clk/clk-eyeq5.c
> > +F:	drivers/reset/reset-eyeq5.c
>
> See above, and this should match the actual file name.
>
> Adding the MAINTAINERS change in the driver patches makes these patches
> depend on each other. Otherwise they could be applied independently. Do
> you intend this series to be merged together in one tree?

I'd prefer splitting it indeed.

I had thought there were two reasons the patches were interdependent:
1. MAINTAINERS file entries.
2. Kconfig: "depends on COMMON_CLK_EYEQ".

About (1): what about creating a new patch that only touches
MAINTAINERS? It would be taken as part of clk maybe (it contains the
platform driver that instantiates the other auxdevs)?

About (2): Kconfig doesn't complain the symbol doesn't exist so it looks
like a non-issue.

> >  F:	include/dt-bindings/clock/mobileye,eyeq5-clk.h
> >  
> >  MODULE SUPPORT
> > diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> > index 85b27c42cf65..b79c18b75674 100644
> > --- a/drivers/reset/Kconfig
> > +++ b/drivers/reset/Kconfig
> > @@ -66,6 +66,20 @@ config RESET_BRCMSTB_RESCAL
> >  	  This enables the RESCAL reset controller for SATA, PCIe0, or PCIe1 on
> >  	  BCM7216.
> >  
> > +config RESET_EYEQ
> > +	bool "Mobileye EyeQ reset controller"
> > +	depends on COMMON_CLK_EYEQ
>
> Is this a real dependency? It seems to compile just fine without it.
> Please allow building under COMPILE_TEST without COMMON_CLK_EYEQ set.

Not really. This made potential users notice they want the
clk driver if they want this reset driver. I forgot
handling test builds (ie COMPILE_TEST).

Next revision will look like:

config RESET_EYEQ
	bool "Mobileye EyeQ reset controller"
	depends on AUXILIARY_BUS
	depends on MACH_EYEQ5 || MACH_EYEQ6H || COMPILE_TEST
	default MACH_EYEQ5 || MACH_EYEQ6H
	help: ...

[...]

> > +
> > +#include <linux/array_size.h>
> > +#include <linux/auxiliary_bus.h>
> > +#include <linux/bitfield.h>
> > +#include <linux/bits.h>
> > +#include <linux/bug.h>
> > +#include <linux/cleanup.h>
> > +#include <linux/container_of.h>
> > +#include <linux/device.h>
> > +#include <linux/err.h>
> > +#include <linux/errno.h>
> > +#include <linux/init.h>
> > +#include <linux/io.h>
> > +#include <linux/iopoll.h>
> > +#include <linux/lockdep.h>
> > +#include <linux/mod_devicetable.h>
> > +#include <linux/mutex.h>
> > +#include <linux/of.h>
> > +#include <linux/platform_device.h>
>
> Not needed, this being an aux driver now. Please check the other
> headers as well.

Looking at the diff, <linux/platform_device.h> is the only one.

[...]

> > +static int eqr_probe(struct auxiliary_device *adev,
> > +		     const struct auxiliary_device_id *id)
> > +{
> > +	const struct of_device_id *match;
> > +	struct device *dev = &adev->dev;
> > +	struct eqr_private *priv;
> > +	unsigned int i;
> > +	int ret;
> > +
> > +	/*
> > +	 * We are an auxiliary device of clk-eyeq. We do not have an OF node by
> > +	 * default; let's reuse our parent's OF node.
> > +	 */
> > +	WARN_ON(dev->of_node);
> > +	device_set_of_node_from_dev(dev, dev->parent);
> > +	if (!dev->of_node)
> > +		return -ENODEV;
> > +
> > +	/*
> > +	 * Using our newfound OF node, we can get match data. We cannot use
> > +	 * device_get_match_data() because it does not match reused OF nodes.
> > +	 */
> > +	match = of_match_node(dev->driver->of_match_table, dev->of_node);
> > +	if (!match || !match->data)
> > +		return -ENODEV;
> > +
> > +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> > +	if (!priv)
> > +		return -ENOMEM;
> > +
> > +	priv->data = match->data;
> > +	priv->base = dev_get_platdata(dev);
>
>   drivers/reset/reset-eyeq.c:437:20: warning: incorrect type in assignment (different address spaces)
>   drivers/reset/reset-eyeq.c:437:20:    expected void [noderef] __iomem *base
>   drivers/reset/reset-eyeq.c:437:20:    got void *
>
> I'd wrap this in a struct or explicitly cast to (void __iomem *) here.

I'll cast to void iomem pointer explicitely.

Thanks for the review Philipp,

--
Théo Lebrun, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


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

* Re: [PATCH v3 7/9] reset: eyeq: add platform driver
  2024-06-26 13:55     ` Théo Lebrun
@ 2024-06-26 14:10       ` Philipp Zabel
  0 siblings, 0 replies; 21+ messages in thread
From: Philipp Zabel @ 2024-06-26 14:10 UTC (permalink / raw)
  To: Théo Lebrun, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Linus Walleij,
	Greg Kroah-Hartman, Rafael J. Wysocki, Lee Jones,
	Thomas Bogendoerfer
  Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
	Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
	Tawfik Bayouk

Hi Théo,

On Mi, 2024-06-26 at 15:55 +0200, Théo Lebrun wrote:
> Hello Philipp,
> 
> On Tue Jun 25, 2024 at 11:17 AM CEST, Philipp Zabel wrote:
> > On Do, 2024-06-20 at 19:30 +0200, Théo Lebrun wrote:
> > > Add Mobileye EyeQ reset controller driver, for EyeQ5, EyeQ6L and EyeQ6H
> > > SoCs. Instances belong to a shared register region called OLB and gets
> > > spawned as auxiliary device to the platform driver for clock.
> > > 
> > > There is one OLB instance for EyeQ5 and EyeQ6L. There are seven OLB
> > > instances on EyeQ6H; three have a reset controller embedded:
> > >  - West and east get handled by the same compatible.
> > >  - Acc (accelerator) is another one.
> > > 
> > > Each instance vary in the number and types of reset domains.
> > > Instances with single domain expect a single cell, others two.
> > > 
> > > Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> > > ---
> > >  MAINTAINERS                |   1 +
> > >  drivers/reset/Kconfig      |  14 ++
> > >  drivers/reset/Makefile     |   1 +
> > >  drivers/reset/reset-eyeq.c | 563 +++++++++++++++++++++++++++++++++++++++++++++
> > 
> > Should this be called reset-eyeq-olb or reset-eyeq5, in case a
> > different eyeq driver will have to be added in the future?
> 
> What about keeping reset-eyeq for the simplicity of it and using
> reset-eyeq7 for a theoretical future driver that gets used by EyeQ7 and
> above? Or any other revision.
> 
> Else it can be reset-eyeq5. OLB might be a concept that gets reused with
> different reset blocks inside (meaning reset-eyeq-olb wouldn't
> distinguish). You tell me if keeping *-eyeq is fine.

Either is fine by me. I just wanted to make sure this was given some
consideration after noticing the reset-eyeq5.c remnant in MAINTAINERS.

regards
Philipp

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

end of thread, other threads:[~2024-06-26 14:10 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-20 17:30 [PATCH v3 0/9] Add Mobileye EyeQ system controller support (clk, reset, pinctrl) Théo Lebrun
2024-06-20 17:30 ` [PATCH v3 1/9] Revert "dt-bindings: clock: mobileye,eyeq5-clk: add bindings" Théo Lebrun
2024-06-24 20:55   ` Rob Herring (Arm)
2024-06-20 17:30 ` [PATCH v3 2/9] Revert "dt-bindings: reset: mobileye,eyeq5-reset: " Théo Lebrun
2024-06-20 18:26   ` Rob Herring (Arm)
2024-06-24 20:20     ` Rob Herring
2024-06-24 20:56   ` Rob Herring (Arm)
2024-06-20 17:30 ` [PATCH v3 3/9] Revert "dt-bindings: pinctrl: mobileye,eyeq5-pinctrl: " Théo Lebrun
2024-06-24 20:56   ` Rob Herring (Arm)
2024-06-26 11:53   ` Linus Walleij
2024-06-20 17:30 ` [PATCH v3 4/9] dt-bindings: soc: mobileye: add EyeQ OLB system controller Théo Lebrun
2024-06-20 18:26   ` Rob Herring (Arm)
2024-06-24 20:56   ` Rob Herring (Arm)
2024-06-20 17:30 ` [PATCH v3 5/9] clk: divider: Introduce CLK_DIVIDER_EVEN_INTEGERS flag Théo Lebrun
2024-06-20 17:30 ` [PATCH v3 6/9] clk: eyeq: add driver Théo Lebrun
2024-06-20 17:30 ` [PATCH v3 7/9] reset: eyeq: add platform driver Théo Lebrun
2024-06-25  9:17   ` Philipp Zabel
2024-06-26 13:55     ` Théo Lebrun
2024-06-26 14:10       ` Philipp Zabel
2024-06-20 17:31 ` [PATCH v3 8/9] pinctrl: eyeq5: " Théo Lebrun
2024-06-20 17:31 ` [PATCH v3 9/9] MIPS: mobileye: eyeq5: add OLB system-controller node Théo Lebrun

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).