From: Oleksij Rempel <o.rempel@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Oleksij Rempel <o.rempel@pengutronix.de>
Subject: [PATCH v1 08/10] reset: add Microchip sparx5 / LAN969X / LAN966X switch reset driver
Date: Fri, 12 Jun 2026 07:59:24 +0200 [thread overview]
Message-ID: <20260612055930.635833-8-o.rempel@pengutronix.de> (raw)
In-Reply-To: <20260612055930.635833-1-o.rempel@pengutronix.de>
Add the reset controller for the Microchip sparx5 / LAN969X / LAN966X
switch SoCs. The reset is asserted once at probe time so downstream
peripherals (SGPIO, MDIO, switch core) come up against a clean IP
state instead of inheriting whatever the previous boot stage left.
Ported from Linux drivers/reset/reset-microchip-sparx5.c at tag
v7.1-rc7
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
drivers/reset/Kconfig | 10 ++
drivers/reset/Makefile | 1 +
drivers/reset/reset-microchip-sparx5.c | 170 +++++++++++++++++++++++++
3 files changed, 181 insertions(+)
create mode 100644 drivers/reset/reset-microchip-sparx5.c
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index c3779f087490..1819da73b27f 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -63,4 +63,14 @@ config RESET_SOCFPGA32
help
This enables the reset controller driver for 32-bit SoCFPGA platforms.
+config RESET_MICROCHIP_SPARX5
+ bool "Microchip Sparx5 / LAN969X / LAN966X switch reset driver"
+ depends on OFDEVICE
+ select MFD_SYSCON
+ help
+ This enables the switch reset controller driver for the Microchip
+ Sparx5 / LAN969X / LAN966X switch SoCs. The reset is asserted once
+ at probe time so downstream peripherals (SGPIO, MDIO, switch core)
+ see a clean IP state.
+
endif
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index a446cb20d0b7..b5540252bc9a 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_RESET_SOCFPGA32) += reset-socfpga.o
obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
obj-$(CONFIG_RESET_STARFIVE) += reset-starfive-vic.o
obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
+obj-$(CONFIG_RESET_MICROCHIP_SPARX5) += reset-microchip-sparx5.o
diff --git a/drivers/reset/reset-microchip-sparx5.c b/drivers/reset/reset-microchip-sparx5.c
new file mode 100644
index 000000000000..8944e3fc1510
--- /dev/null
+++ b/drivers/reset/reset-microchip-sparx5.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Microchip Sparx5 / LAN969X / LAN966X Switch Reset driver
+ *
+ * Copyright (c) 2020 Microchip Technology Inc. and its subsidiaries.
+ *
+ * Ported from Linux drivers/reset/reset-microchip-sparx5.c. Identifiers,
+ * struct layouts and per-SoC props are kept aligned with Linux so future
+ * fixes can be backported with minimal context churn.
+ */
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <io.h>
+#include <of.h>
+#include <linux/err.h>
+#include <linux/iopoll.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <mfd/syscon.h>
+
+struct reset_props {
+ u32 protect_reg;
+ u32 protect_bit;
+ u32 reset_reg;
+ u32 reset_bit;
+};
+
+struct mchp_reset_context {
+ struct regmap *cpu_ctrl;
+ struct regmap *gcb_ctrl;
+ struct reset_controller_dev rcdev;
+ const struct reset_props *props;
+};
+
+static const struct regmap_config sparx5_reset_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static int sparx5_switch_reset(struct mchp_reset_context *ctx)
+{
+ u32 val;
+
+ /* Make sure the core is PROTECTED from reset */
+ regmap_update_bits(ctx->cpu_ctrl, ctx->props->protect_reg,
+ ctx->props->protect_bit, ctx->props->protect_bit);
+
+ /* Start soft reset */
+ regmap_write(ctx->gcb_ctrl, ctx->props->reset_reg,
+ ctx->props->reset_bit);
+
+ /* Wait for soft reset done */
+ return regmap_read_poll_timeout(ctx->gcb_ctrl, ctx->props->reset_reg,
+ val,
+ (val & ctx->props->reset_bit) == 0,
+ 100);
+}
+
+static int sparx5_reset_noop(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return 0;
+}
+
+static const struct reset_control_ops sparx5_reset_ops = {
+ .reset = sparx5_reset_noop,
+};
+
+static int mchp_sparx5_reset_probe(struct device *dev)
+{
+ struct device_node *dn = dev->of_node;
+ struct mchp_reset_context *ctx;
+ struct device_node *syscon_np;
+ struct resource *iores;
+ void __iomem *base;
+ int ret;
+
+ ctx = xzalloc(sizeof(*ctx));
+
+ syscon_np = of_parse_phandle(dn, "cpu-syscon", 0);
+ if (!syscon_np) {
+ dev_err(dev, "missing 'cpu-syscon' phandle\n");
+ ret = -ENODEV;
+ goto err;
+ }
+ ctx->cpu_ctrl = syscon_node_to_regmap(syscon_np);
+ if (IS_ERR(ctx->cpu_ctrl)) {
+ dev_err(dev, "failed to map cpu-syscon: %pe\n", ctx->cpu_ctrl);
+ ret = PTR_ERR(ctx->cpu_ctrl);
+ goto err;
+ }
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores)) {
+ ret = PTR_ERR(iores);
+ goto err;
+ }
+ base = IOMEM(iores->start);
+ ctx->gcb_ctrl = regmap_init_mmio(dev, base, &sparx5_reset_regmap_config);
+ if (IS_ERR(ctx->gcb_ctrl)) {
+ ret = PTR_ERR(ctx->gcb_ctrl);
+ goto err;
+ }
+
+ ctx->props = device_get_match_data(dev);
+ if (!ctx->props) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ctx->rcdev.nr_resets = 1;
+ ctx->rcdev.ops = &sparx5_reset_ops;
+ ctx->rcdev.of_node = dn;
+
+ /*
+ * Issue the reset very early; reset_control_reset() callers see a
+ * no-op afterwards.
+ */
+ ret = sparx5_switch_reset(ctx);
+ if (ret) {
+ dev_err(dev, "switch reset timed out: %d\n", ret);
+ goto err;
+ }
+
+ ret = reset_controller_register(&ctx->rcdev);
+ if (ret)
+ goto err;
+
+ dev_info(dev, "switch reset complete\n");
+ return 0;
+
+err:
+ free(ctx);
+ return ret;
+}
+
+static const struct reset_props reset_props_sparx5 = {
+ .protect_reg = 0x84,
+ .protect_bit = BIT(10),
+ .reset_reg = 0x0,
+ .reset_bit = BIT(1),
+};
+
+static const struct reset_props reset_props_lan966x = {
+ .protect_reg = 0x88,
+ .protect_bit = BIT(5),
+ .reset_reg = 0x0,
+ .reset_bit = BIT(1),
+};
+
+static const struct of_device_id mchp_sparx5_reset_of_match[] = {
+ { .compatible = "microchip,sparx5-switch-reset",
+ .data = &reset_props_sparx5 },
+ { .compatible = "microchip,lan966x-switch-reset",
+ .data = &reset_props_lan966x },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mchp_sparx5_reset_of_match);
+
+static struct driver mchp_sparx5_reset_driver = {
+ .name = "sparx5-switch-reset",
+ .probe = mchp_sparx5_reset_probe,
+ .of_compatible = DRV_OF_COMPAT(mchp_sparx5_reset_of_match),
+};
+/*
+ * Same rationale as Linux's postcore_initcall(): the switch IP must be
+ * reset before downstream consumers (SGPIO, MDIO, switch fabric) probe.
+ */
+coredevice_platform_driver(mchp_sparx5_reset_driver);
--
2.47.3
next prev parent reply other threads:[~2026-06-12 6:00 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-12 5:59 [PATCH v1 01/10] ARM: introduce ARCH_MICROCHIP for ARM64 Microchip SoCs Oleksij Rempel
2026-06-12 5:59 ` [PATCH v1 02/10] serial: atmel: add lan9696 (Microchip LAN969X) support Oleksij Rempel
2026-06-12 12:49 ` Marco Felsch
2026-06-12 5:59 ` [PATCH v1 03/10] clk: add Microchip LAN966X / LAN969X generic clock controller driver Oleksij Rempel
2026-06-12 12:58 ` Marco Felsch
2026-06-15 7:02 ` Sascha Hauer
2026-06-15 7:46 ` Sascha Hauer
2026-06-12 5:59 ` [PATCH v1 04/10] clk: tolerate clocks registered without a name Oleksij Rempel
2026-06-12 5:59 ` [PATCH v1 05/10] pinctrl: ocelot: port Microsemi/Microchip Ocelot pinctrl from Linux Oleksij Rempel
2026-06-12 5:59 ` [PATCH v1 06/10] mci: atmel-sdhci: add Microchip LAN9691 / LAN969X SDHCI support Oleksij Rempel
2026-06-15 6:17 ` Marco Felsch
2026-06-15 7:25 ` Sascha Hauer
2026-06-12 5:59 ` [PATCH v1 07/10] gpio: add Microchip SGPIO (serial GPIO) driver Oleksij Rempel
2026-06-15 7:32 ` Sascha Hauer
2026-06-12 5:59 ` Oleksij Rempel [this message]
2026-06-12 5:59 ` [PATCH v1 09/10] spi: atmel-quadspi: add Microchip LAN966X / LAN969X support Oleksij Rempel
2026-06-12 5:59 ` [PATCH v1 10/10] ARM: add Microchip LAN9696 (LAN969X) SoC and EV23X71A board Oleksij Rempel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260612055930.635833-8-o.rempel@pengutronix.de \
--to=o.rempel@pengutronix.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox