devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RESEND v2 0/2] Add Mobileye EyeQ reset support
@ 2024-07-30 16:06 Théo Lebrun
  2024-07-30 16:06 ` [PATCH RESEND v2 1/2] Revert "dt-bindings: reset: mobileye,eyeq5-reset: add bindings" Théo Lebrun
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Théo Lebrun @ 2024-07-30 16:06 UTC (permalink / raw)
  To: Philipp Zabel, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: devicetree, linux-kernel, Vladimir Kondratiev,
	Grégory Clement, Thomas Petazzoni, Tawfik Bayouk,
	Théo Lebrun

This is a new iteration on the Mobileye system-controller series. It
used to be sent as a single series [0], but has been split in the
previous revision (see [1], [2], [3], [4]) to faciliate merging.

This series adds a platform driver handling SoC controllers resets. It
is an auxiliary driver being instantiated by the platform clk driver.

We support EyeQ5, EyeQ6L and EyeQ6H SoCs. The last one is special in
that there are seven instances of this system-controller. Three of
those (west, east, acc) contain a reset section.

Related series are targeted at clk [5], pinctrl [6] and MIPS [4]. The
first two are receiving a second version. The last one has no change
and stays at its V1.

Have a nice day,
Théo

[0]: https://lore.kernel.org/lkml/20240620-mbly-olb-v3-0-5f29f8ca289c@bootlin.com/

[1]: https://lore.kernel.org/lkml/20240628-mbly-clk-v1-0-edb1e29ea4c1@bootlin.com/
[2]: https://lore.kernel.org/lkml/20240628-mbly-reset-v1-0-2a8294fd4392@bootlin.com/
[3]: https://lore.kernel.org/lkml/20240628-mbly-pinctrl-v1-0-c878192d6b0a@bootlin.com/
[4]: https://lore.kernel.org/lkml/20240628-mbly-mips-v1-0-f53f5e4c422b@bootlin.com/

[5]: https://lore.kernel.org/lkml/20240703-mbly-clk-v2-0-fe8c6199a579@bootlin.com/
[6]: https://lore.kernel.org/lkml/20240703-mbly-pinctrl-v2-0-eab5f69f1b01@bootlin.com/

Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
---
Changes in v2:
- Kconfig: replace "depends on AUXILIARY_BUS" by "select AUXILIARY_BUS".
- driver:
  - turn rcdev_to_priv() into a static function to avoid a gnarly
    container_of(rcdev, ..., rcdev) bug and use the typesystem.
  - eqr_busy_wait_locked():
    - assign values to base, sleep_us and timeout_us in the variable
      declaration block rather than later down the function.
    - fix indent of the conditional in the read_poll_timeout() call.
    - rename val0 to rst_status and val1 to clk_status.
  - eqr_status(): reorder variable declarations for offset and domain to
    be next to each other.
  - add comment expanding on usage of mutexes in the device private data.
  - add comments mentioning that both RST_REQUEST and CLK_REQUEST
    registers must be kept in sync, in both assert and deassert code.
- Link to v1: see [2]

Changes since OLB v3 [0]:
 - MAINTAINERS: Move changes into a separate commit to avoid merge
   conflicts. This commit is in the MIPS series [3].
 - dt-bindings: Take Reviewed-by: Rob Herring.
 - Kconfig: do not depend on COMMON_CLK_EYEQ. This symbol is not defined
   in this series, it is defined in the clk series [1].
 - Kconfig: do depend on AUXILIARY_BUS.
 - Kconfig: remove outdated "depends on MFD_SYSCON".
 - driver: remove "#include <linux/platform_device.h>".
 - driver: cast platdata to (void _iomem *) explicitely.

---
Théo Lebrun (2):
      Revert "dt-bindings: reset: mobileye,eyeq5-reset: add bindings"
      reset: eyeq: add platform driver

 .../bindings/reset/mobileye,eyeq5-reset.yaml       |  43 --
 drivers/reset/Kconfig                              |  13 +
 drivers/reset/Makefile                             |   1 +
 drivers/reset/reset-eyeq.c                         | 570 +++++++++++++++++++++
 4 files changed, 584 insertions(+), 43 deletions(-)
---
base-commit: f2661062f16b2de5d7b6a5c42a9a5c96326b8454
change-id: 20240628-mbly-reset-ac6c66d3bf95

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


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

* [PATCH RESEND v2 1/2] Revert "dt-bindings: reset: mobileye,eyeq5-reset: add bindings"
  2024-07-30 16:06 [PATCH RESEND v2 0/2] Add Mobileye EyeQ reset support Théo Lebrun
@ 2024-07-30 16:06 ` Théo Lebrun
  2024-07-30 16:06 ` [PATCH RESEND v2 2/2] reset: eyeq: add platform driver Théo Lebrun
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Théo Lebrun @ 2024-07-30 16:06 UTC (permalink / raw)
  To: Philipp Zabel, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: devicetree, linux-kernel, Vladimir Kondratiev,
	Grégory 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

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
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] 7+ messages in thread

* [PATCH RESEND v2 2/2] reset: eyeq: add platform driver
  2024-07-30 16:06 [PATCH RESEND v2 0/2] Add Mobileye EyeQ reset support Théo Lebrun
  2024-07-30 16:06 ` [PATCH RESEND v2 1/2] Revert "dt-bindings: reset: mobileye,eyeq5-reset: add bindings" Théo Lebrun
@ 2024-07-30 16:06 ` Théo Lebrun
  2024-09-02 10:15   ` Philipp Zabel
  2024-07-30 16:07 ` [PATCH RESEND v2 0/2] Add Mobileye EyeQ reset support Théo Lebrun
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 7+ messages in thread
From: Théo Lebrun @ 2024-07-30 16:06 UTC (permalink / raw)
  To: Philipp Zabel, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: devicetree, linux-kernel, Vladimir Kondratiev,
	Grégory 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>
---
 drivers/reset/Kconfig      |  13 ++
 drivers/reset/Makefile     |   1 +
 drivers/reset/reset-eyeq.c | 570 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 584 insertions(+)

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 7112f5932609..c9786c79b091 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -66,6 +66,19 @@ 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 MACH_EYEQ5 || MACH_EYEQ6H || COMPILE_TEST
+	select AUXILIARY_BUS
+	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..02d50041048b
--- /dev/null
+++ b/drivers/reset/reset-eyeq.c
@@ -0,0 +1,570 @@
+// 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/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 {
+	/*
+	 * One mutex per domain for read-modify-write operations on registers.
+	 * Some domains can be involved in LBIST which implies long critical
+	 * sections; we wouldn't want other domains to be impacted by that.
+	 */
+	struct mutex			mutexes[EQR_MAX_DOMAIN_COUNT];
+	void __iomem			*base;
+	const struct eqr_match_data	*data;
+	struct reset_controller_dev	rcdev;
+};
+
+static inline struct eqr_private *eqr_rcdev_to_priv(struct reset_controller_dev *x)
+{
+	return container_of(x, 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)
+{
+	void __iomem *base = priv->base + priv->data->domains[domain].offset;
+	enum eqr_domain_type domain_type = priv->data->domains[domain].type;
+	unsigned long timeout_us = eqr_timings[domain_type].timeout_us;
+	unsigned long sleep_us = eqr_timings[domain_type].sleep_us;
+	u32 val, mask, rst_status, clk_status;
+	void __iomem *reg;
+	int ret;
+
+	lockdep_assert_held(&priv->mutexes[domain]);
+
+	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,
+					(!(rst_status & mask) == assert) &&
+					(!(clk_status & mask) == assert),
+					sleep_us, timeout_us, false,
+					base + EQR_EYEQ6H_SARCR_RST_STATUS,
+					base + EQR_EYEQ6H_SARCR_CLK_STATUS,
+					&rst_status, &clk_status);
+		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:
+		/* RST_REQUEST and CLK_REQUEST must be kept in sync. */
+		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 = eqr_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:
+		/* RST_REQUEST and CLK_REQUEST must be kept in sync. */
+		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 = eqr_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);
+	u32 offset = FIELD_GET(ID_OFFSET_MASK, id);
+	struct eqr_private *priv = eqr_rcdev_to_priv(rcdev);
+	enum eqr_domain_type domain_type = priv->data->domains[domain].type;
+	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 = eqr_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 = (void __iomem *)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] 7+ messages in thread

* Re: [PATCH RESEND v2 0/2] Add Mobileye EyeQ reset support
  2024-07-30 16:06 [PATCH RESEND v2 0/2] Add Mobileye EyeQ reset support Théo Lebrun
  2024-07-30 16:06 ` [PATCH RESEND v2 1/2] Revert "dt-bindings: reset: mobileye,eyeq5-reset: add bindings" Théo Lebrun
  2024-07-30 16:06 ` [PATCH RESEND v2 2/2] reset: eyeq: add platform driver Théo Lebrun
@ 2024-07-30 16:07 ` Théo Lebrun
  2024-08-28 15:17 ` Théo Lebrun
  2024-09-02 10:16 ` Philipp Zabel
  4 siblings, 0 replies; 7+ messages in thread
From: Théo Lebrun @ 2024-07-30 16:07 UTC (permalink / raw)
  To: Théo Lebrun, Philipp Zabel, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: devicetree, linux-kernel, Vladimir Kondratiev,
	Grégory Clement, Thomas Petazzoni, Tawfik Bayouk

Hello all,

On Tue Jul 30, 2024 at 6:06 PM CEST, Théo Lebrun wrote:
> This is a new iteration on the Mobileye system-controller series. It
> used to be sent as a single series [0], but has been split in the
> previous revision (see [1], [2], [3], [4]) to faciliate merging.

This is a friendly RESEND of the Mobileye system-controller reset
series. It rebases with no issue on v6.11-rc1, and works as expected on
real hardware.

Thanks,

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


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

* Re: [PATCH RESEND v2 0/2] Add Mobileye EyeQ reset support
  2024-07-30 16:06 [PATCH RESEND v2 0/2] Add Mobileye EyeQ reset support Théo Lebrun
                   ` (2 preceding siblings ...)
  2024-07-30 16:07 ` [PATCH RESEND v2 0/2] Add Mobileye EyeQ reset support Théo Lebrun
@ 2024-08-28 15:17 ` Théo Lebrun
  2024-09-02 10:16 ` Philipp Zabel
  4 siblings, 0 replies; 7+ messages in thread
From: Théo Lebrun @ 2024-08-28 15:17 UTC (permalink / raw)
  To: Théo Lebrun, Philipp Zabel, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: devicetree, linux-kernel, Vladimir Kondratiev,
	Grégory Clement, Thomas Petazzoni, Tawfik Bayouk

Hello Philipp,

On Tue Jul 30, 2024 at 6:06 PM CEST, Théo Lebrun wrote:
> This is a new iteration on the Mobileye system-controller series. It
> used to be sent as a single series [0], but has been split in the
> previous revision (see [1], [2], [3], [4]) to faciliate merging.
>
> This series adds a platform driver handling SoC controllers resets. It
> is an auxiliary driver being instantiated by the platform clk driver.

What's your state of mind on this series? I am happy at how it turned
out and believe the whole system-controller for the platform is modeled
properly now. It works as expected on real hardware. Pinctrl got in.

Thanks,

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


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

* Re: [PATCH RESEND v2 2/2] reset: eyeq: add platform driver
  2024-07-30 16:06 ` [PATCH RESEND v2 2/2] reset: eyeq: add platform driver Théo Lebrun
@ 2024-09-02 10:15   ` Philipp Zabel
  0 siblings, 0 replies; 7+ messages in thread
From: Philipp Zabel @ 2024-09-02 10:15 UTC (permalink / raw)
  To: Théo Lebrun, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: devicetree, linux-kernel, Vladimir Kondratiev,
	Grégory Clement, Thomas Petazzoni, Tawfik Bayouk

On Di, 2024-07-30 at 18:06 +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>

Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>

regards
Philipp

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

* Re: [PATCH RESEND v2 0/2] Add Mobileye EyeQ reset support
  2024-07-30 16:06 [PATCH RESEND v2 0/2] Add Mobileye EyeQ reset support Théo Lebrun
                   ` (3 preceding siblings ...)
  2024-08-28 15:17 ` Théo Lebrun
@ 2024-09-02 10:16 ` Philipp Zabel
  4 siblings, 0 replies; 7+ messages in thread
From: Philipp Zabel @ 2024-09-02 10:16 UTC (permalink / raw)
  To: Théo Lebrun, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: devicetree, linux-kernel, Vladimir Kondratiev,
	Grégory Clement, Thomas Petazzoni, Tawfik Bayouk

On Di, 2024-07-30 at 18:06 +0200, Théo Lebrun wrote:
> This is a new iteration on the Mobileye system-controller series. It
> used to be sent as a single series [0], but has been split in the
> previous revision (see [1], [2], [3], [4]) to faciliate merging.
> 
> This series adds a platform driver handling SoC controllers resets. It
> is an auxiliary driver being instantiated by the platform clk driver.
> 
> We support EyeQ5, EyeQ6L and EyeQ6H SoCs. The last one is special in
> that there are seven instances of this system-controller. Three of
> those (west, east, acc) contain a reset section.
> 
> Related series are targeted at clk [5], pinctrl [6] and MIPS [4]. The
> first two are receiving a second version. The last one has no change
> and stays at its V1.
> 
> Have a nice day,
> Théo

Thank you, applied to reset/next.

regards
Philipp

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

end of thread, other threads:[~2024-09-02 10:16 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-30 16:06 [PATCH RESEND v2 0/2] Add Mobileye EyeQ reset support Théo Lebrun
2024-07-30 16:06 ` [PATCH RESEND v2 1/2] Revert "dt-bindings: reset: mobileye,eyeq5-reset: add bindings" Théo Lebrun
2024-07-30 16:06 ` [PATCH RESEND v2 2/2] reset: eyeq: add platform driver Théo Lebrun
2024-09-02 10:15   ` Philipp Zabel
2024-07-30 16:07 ` [PATCH RESEND v2 0/2] Add Mobileye EyeQ reset support Théo Lebrun
2024-08-28 15:17 ` Théo Lebrun
2024-09-02 10:16 ` Philipp Zabel

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).