[U-Boot] [PATCH 1/2] MSCC: Add sysreset drivers for MSCC Socs

Horatiu Vultur horatiu.vultur at microchip.com
Tue Jan 15 16:33:52 UTC 2019


Add sysreset driver for Luton, Ocelot and Jaguar2 SoCs.

Signed-off-by: Horatiu Vultur <horatiu.vultur at microchip.com>
---
 MAINTAINERS                      |   1 +
 arch/mips/dts/mscc,jr2.dtsi      |   7 +-
 arch/mips/dts/mscc,luton.dtsi    |  10 +++
 arch/mips/dts/mscc,ocelot.dtsi   |   5 ++
 board/mscc/ocelot/ocelot.c       |  20 +++++
 configs/mscc_jr2_defconfig       |   2 +
 configs/mscc_luton_defconfig     |   2 +
 configs/mscc_ocelot_defconfig    |   2 +
 drivers/sysreset/Kconfig         |   6 ++
 drivers/sysreset/Makefile        |   1 +
 drivers/sysreset/sysreset_mscc.c | 157 +++++++++++++++++++++++++++++++++++++++
 11 files changed, 212 insertions(+), 1 deletion(-)
 create mode 100644 drivers/sysreset/sysreset_mscc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 3fa5d3e..fb1b69b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -527,6 +527,7 @@ F:	board/mscc/
 F:	configs/mscc*
 F:	drivers/gpio/mscc_sgpio.c
 F:	drivers/spi/mscc_bb_spi.c
+F:	drivers/sysreset/sysreset_mscc.c
 F:	include/configs/vcoreiii.h
 F:	drivers/pinctrl/mscc/
 
diff --git a/arch/mips/dts/mscc,jr2.dtsi b/arch/mips/dts/mscc,jr2.dtsi
index 0900926..86d1378 100644
--- a/arch/mips/dts/mscc,jr2.dtsi
+++ b/arch/mips/dts/mscc,jr2.dtsi
@@ -52,7 +52,12 @@
 		interrupt-parent = <&intc>;
 
 		cpu_ctrl: syscon at 0 {
-			compatible = "mscc,jr2-cpu-syscon", "syscon";
+			compatible = "mscc,jaguar2-cpu-syscon", "syscon";
+			reg = <0x0 0x2c>;
+		};
+
+		sysreset: sysreset at 0 {
+			compatible = "mscc,jaguar2-chip-reset";
 			reg = <0x0 0x2c>;
 		};
 
diff --git a/arch/mips/dts/mscc,luton.dtsi b/arch/mips/dts/mscc,luton.dtsi
index d11ec48..7cbb53b 100644
--- a/arch/mips/dts/mscc,luton.dtsi
+++ b/arch/mips/dts/mscc,luton.dtsi
@@ -42,6 +42,16 @@
 		#size-cells = <1>;
 		ranges = <0 0x60000000 0x10200000>;
 
+		cpu_ctrl: syscon at 0 {
+			compatible = "mscc,luton-cpu-syscon", "syscon";
+			reg = <0x0 0x2c>;
+		};
+
+		sysreset: sysreset at 70090 {
+			compatible = "mscc,luton-chip-reset";
+			reg = <0x70090 0x2c>;
+		};
+
 		uart0: serial at 10100000 {
 			pinctrl-0 = <&uart_pins>;
 			pinctrl-names = "default";
diff --git a/arch/mips/dts/mscc,ocelot.dtsi b/arch/mips/dts/mscc,ocelot.dtsi
index 2592003..4287117 100644
--- a/arch/mips/dts/mscc,ocelot.dtsi
+++ b/arch/mips/dts/mscc,ocelot.dtsi
@@ -62,6 +62,11 @@
 			reg = <0x0 0x2c>;
 		};
 
+		sysreset: sysreset at 1070008 {
+			compatible = "mscc,ocelot-chip-reset";
+			reg = <0x1070008 0x4>;
+		};
+
 		intc: interrupt-controller at 70 {
 			compatible = "mscc,ocelot-icpu-intr";
 			reg = <0x70 0x70>;
diff --git a/board/mscc/ocelot/ocelot.c b/board/mscc/ocelot/ocelot.c
index 0f7a532..ae5eb4d 100644
--- a/board/mscc/ocelot/ocelot.c
+++ b/board/mscc/ocelot/ocelot.c
@@ -10,6 +10,7 @@
 #include <environment.h>
 #include <spi.h>
 #include <led.h>
+#include <sysreset.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -25,6 +26,25 @@ void board_debug_uart_init(void)
 	mscc_gpio_set_alternate(7, 1);
 }
 
+__weak int ocelot_sysreset_request(struct udevice *dev,
+				   enum sysreset_t type)
+{
+	u32 resetbits = PERF_SOFT_RST_SOFT_CHIP_RST;
+	(void)readl(BASE_DEVCPU_GCB + PERF_SOFT_RST);
+
+	/* Make sure VCore is NOT protected from reset */
+	clrbits_le32(BASE_CFG + ICPU_RESET, ICPU_RESET_CORE_RST_PROTECT);
+
+	/* Change to SPI bitbang for SPI reset workaround... */
+	writel(ICPU_SW_MODE_SW_SPI_CS_OE(1) | ICPU_SW_MODE_SW_SPI_CS(1) |
+	       ICPU_SW_MODE_SW_PIN_CTRL_MODE, BASE_CFG + ICPU_SW_MODE);
+
+	/* Do the global reset */
+	writel(resetbits, BASE_DEVCPU_GCB + PERF_SOFT_RST);
+
+	return -EINPROGRESS;
+}
+
 int board_early_init_r(void)
 {
 	/* Prepare SPI controller to be used in master mode */
diff --git a/configs/mscc_jr2_defconfig b/configs/mscc_jr2_defconfig
index b215754..0992185 100644
--- a/configs/mscc_jr2_defconfig
+++ b/configs/mscc_jr2_defconfig
@@ -57,3 +57,5 @@ CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_LZMA=y
 CONFIG_XZ=y
+CONFIG_SYSRESET=y
+CONFIG_SYSRESET_MSCC=y
diff --git a/configs/mscc_luton_defconfig b/configs/mscc_luton_defconfig
index 7154e97..7c94a76 100644
--- a/configs/mscc_luton_defconfig
+++ b/configs/mscc_luton_defconfig
@@ -69,3 +69,5 @@ CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_MSCC_BB_SPI=y
 CONFIG_LZMA=y
+CONFIG_SYSRESET=y
+CONFIG_SYSRESET_MSCC=y
diff --git a/configs/mscc_ocelot_defconfig b/configs/mscc_ocelot_defconfig
index fb6a5bd..7d9abb6 100644
--- a/configs/mscc_ocelot_defconfig
+++ b/configs/mscc_ocelot_defconfig
@@ -69,3 +69,5 @@ CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_LZMA=y
+CONFIG_SYSRESET=y
+CONFIG_SYSRESET_MSCC=y
diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig
index 8ce3e2e..e25b3cb 100644
--- a/drivers/sysreset/Kconfig
+++ b/drivers/sysreset/Kconfig
@@ -43,6 +43,12 @@ config SYSRESET_TI_SCI
 	  This enables the system reset driver support over TI System Control
 	  Interface available on some new TI's SoCs.
 
+config SYSRESET_MSCC
+	bool "Enable support for Ocelot soft reset"
+	depends on ARCH_MSCC
+	help
+	  This is soft reset on Ocelot.
+
 endif
 
 config SYSRESET_SYSCON
diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile
index b3728ac..a7f2a73 100644
--- a/drivers/sysreset/Makefile
+++ b/drivers/sysreset/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_SYSRESET_SYSCON) += sysreset_syscon.o
 obj-$(CONFIG_SYSRESET_WATCHDOG) += sysreset_watchdog.o
 obj-$(CONFIG_SYSRESET_X86) += sysreset_x86.o
 obj-$(CONFIG_TARGET_XTFPGA) += sysreset_xtfpga.o
+obj-$(CONFIG_SYSRESET_MSCC) += sysreset_mscc.o
diff --git a/drivers/sysreset/sysreset_mscc.c b/drivers/sysreset/sysreset_mscc.c
new file mode 100644
index 0000000..ea3757f
--- /dev/null
+++ b/drivers/sysreset/sysreset_mscc.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Microsemi SoCs sysreset driver
+ *
+ * Author: <horatiu.vultur at microchip.com>
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <sysreset.h>
+#include <linux/err.h>
+#include <asm/io.h>
+
+struct mscc_sysreset_priv {
+	u32 __iomem *regs;
+	u32 cpu;
+};
+
+enum {
+	REG_GCB_SOFT_RST,
+	REG_ICPU_RESET,
+	REG_ICPU_GENERAL_CTRL,
+	MAXREG,
+};
+
+struct mscc_sysreset_bf {
+	u8 beg;
+	u8 end;
+};
+
+struct mscc_sysreset_data {
+	u8 regoff[MAXREG];
+	struct mscc_sysreset_bf cpu_ctrl_si_owner;
+	int (*request_func)(struct udevice *dev, enum sysreset_t type);
+};
+
+#define __M(bf)		GENMASK((bf).end, (bf).beg)
+#define __F(bf, x)	(__M(bf) & ((x) << (bf).beg))
+
+#define MSCC_F_CPU_CTRL_SI_OWNER(d, x)	__F(d->cpu_ctrl_si_owner, x)
+
+__weak int ocelot_sysreset_request(struct udevice *dev,
+				   enum sysreset_t type)
+{
+	const struct mscc_sysreset_priv *priv = dev_get_priv(dev);
+	const struct mscc_sysreset_data *data =
+		(const struct mscc_sysreset_data *)dev_get_driver_data(dev);
+	void __iomem *cpu = (void __iomem *)priv->cpu;
+
+	(void)readl(priv->regs + data->regoff[REG_GCB_SOFT_RST]);
+
+	/* Make sure VCore is NOT protected from reset */
+	clrbits_le32(cpu + data->regoff[REG_ICPU_RESET],
+		     ICPU_RESET_CORE_RST_PROTECT);
+
+	/* Do the global reset */
+	writel(PERF_SOFT_RST_SOFT_CHIP_RST,
+	       priv->regs + data->regoff[REG_GCB_SOFT_RST]);
+
+	return -EINPROGRESS;
+}
+
+int jr2_sysreset_request(struct udevice *dev,
+			 enum sysreset_t type)
+{
+	const struct mscc_sysreset_priv *priv = dev_get_priv(dev);
+	const struct mscc_sysreset_data *data =
+		(const struct mscc_sysreset_data *)dev_get_driver_data(dev);
+	void __iomem *cpu = (void __iomem *)priv->cpu;
+
+	u32 reg = readl(cpu + data->regoff[REG_ICPU_GENERAL_CTRL]);
+
+	/* Set owner and boot mode */
+	reg |= MSCC_F_CPU_CTRL_SI_OWNER(data, 1) |
+		ICPU_GENERAL_CTRL_BOOT_MODE_ENA;
+	writel(reg, cpu + data->regoff[REG_ICPU_GENERAL_CTRL]);
+
+	/* Read back in order to make BOOT mode setting active */
+	(void)readl(cpu + data->regoff[REG_ICPU_GENERAL_CTRL]);
+
+	/* Reset CPU only - still executing _here_. but from cache */
+	writel(readl(cpu + data->regoff[REG_ICPU_RESET]) |
+	       ICPU_RESET_CORE_RST_CPU_ONLY |
+	       ICPU_RESET_CORE_RST_FORCE,
+	       cpu + data->regoff[REG_ICPU_RESET]);
+
+	return -EINPROGRESS;
+}
+
+static const struct mscc_sysreset_data ocelot_sysreset_data = {
+	.regoff = {0x08, 0x20, 0x24},
+	.cpu_ctrl_si_owner = { 4, 5 },
+	.request_func = ocelot_sysreset_request,
+};
+
+static const struct mscc_sysreset_data luton_sysreset_data = {
+	.regoff = {0x00, 0x20, 0x24},
+	.cpu_ctrl_si_owner = { 0, 0 },
+	.request_func = ocelot_sysreset_request,
+};
+
+static const struct mscc_sysreset_data jr2_sysreset_data = {
+	.regoff = {0x08, 0x20, 0x24},
+	.cpu_ctrl_si_owner = { 6, 7 },
+	.request_func = jr2_sysreset_request,
+};
+
+static int mscc_sysreset_request(struct udevice *dev,
+				 enum sysreset_t type)
+{
+	const struct mscc_sysreset_data *data =
+		(const struct mscc_sysreset_data *)dev_get_driver_data(dev);
+	return data->request_func(dev, type);
+}
+
+static int mscc_probe(struct udevice *dev)
+{
+	struct mscc_sysreset_priv *priv = dev_get_priv(dev);
+	int node;
+
+	priv->regs = (u32 __iomem *)dev_read_addr(dev);
+	node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "syscon");
+	priv->cpu = ofnode_get_addr(offset_to_ofnode(node));
+
+	return 0;
+}
+
+static const struct sysreset_ops mscc_sysreset = {
+	.request = mscc_sysreset_request,
+};
+
+static const struct udevice_id mscc_sysreset_ids[] = {
+	{
+		.compatible = "mscc,ocelot-chip-reset",
+		.data = (ulong)&ocelot_sysreset_data
+	},
+	{
+		.compatible = "mscc,luton-chip-reset",
+		.data = (ulong)&luton_sysreset_data
+	},
+	{
+		.compatible = "mscc,jaguar2-chip-reset",
+		.data = (ulong)&jr2_sysreset_data
+	},
+	{ }
+};
+
+U_BOOT_DRIVER(sysreset_ocelot) = {
+	.name			= "mscc-chip-reset",
+	.id			= UCLASS_SYSRESET,
+	.of_match		= mscc_sysreset_ids,
+	.ops			= &mscc_sysreset,
+	.probe			= mscc_probe,
+	.priv_auto_alloc_size	= sizeof(struct mscc_sysreset_priv),
+};
-- 
2.7.4



More information about the U-Boot mailing list