* [RFC 1/6] dt-bindings: clk: microchip: mpfs: add reset controller support
2022-06-19 16:49 [RFC 0/6] PolarFire SoC Reset controller Conor Dooley
@ 2022-06-19 16:49 ` Conor Dooley
2022-06-19 16:49 ` [RFC 2/6] dt-bindings: net: cdns,macb: document polarfire soc's macb Conor Dooley
` (4 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Conor Dooley @ 2022-06-19 16:49 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Conor Dooley, Philipp Zabel,
Geert Uytterhoeven
Cc: Daire McNamara, linux-clk, linux-kernel, linux-riscv
From: Conor Dooley <conor.dooley@microchip.com>
The "peripheral" devices on PolarFire SoC can be put into reset, so
update the device tree binding to reflect the presence of a reset
controller.
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
.../bindings/clock/microchip,mpfs.yaml | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/microchip,mpfs.yaml b/Documentation/devicetree/bindings/clock/microchip,mpfs.yaml
index 016a4f378b9b..1d0b6a4fda42 100644
--- a/Documentation/devicetree/bindings/clock/microchip,mpfs.yaml
+++ b/Documentation/devicetree/bindings/clock/microchip,mpfs.yaml
@@ -40,8 +40,21 @@ properties:
const: 1
description: |
The clock consumer should specify the desired clock by having the clock
- ID in its "clocks" phandle cell. See include/dt-bindings/clock/microchip,mpfs-clock.h
- for the full list of PolarFire clock IDs.
+ ID in its "clocks" phandle cell.
+ See include/dt-bindings/clock/microchip,mpfs-clock.h for the full list of
+ PolarFire clock IDs.
+
+ resets:
+ maxItems: 1
+
+ '#reset-cells':
+ description:
+ The AHB/AXI peripherals on the PolarFire SoC have reset support, so from
+ CLK_ENVM to CLK_CFM. The reset consumer should specify the desired
+ peripheral via the clock ID in its "resets" phandle cell.
+ See include/dt-bindings/clock/microchip,mpfs-clock.h for the full list of
+ PolarFire clock IDs.
+ const: 1
required:
- compatible
--
2.36.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [RFC 2/6] dt-bindings: net: cdns,macb: document polarfire soc's macb
2022-06-19 16:49 [RFC 0/6] PolarFire SoC Reset controller Conor Dooley
2022-06-19 16:49 ` [RFC 1/6] dt-bindings: clk: microchip: mpfs: add reset controller support Conor Dooley
@ 2022-06-19 16:49 ` Conor Dooley
2022-06-19 16:49 ` [RFC 3/6] clk: microchip: mpfs: add reset controller Conor Dooley
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Conor Dooley @ 2022-06-19 16:49 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Conor Dooley, Philipp Zabel,
Geert Uytterhoeven
Cc: Daire McNamara, linux-clk, linux-kernel, linux-riscv
From: Conor Dooley <conor.dooley@microchip.com>
Until now the PolarFire SoC (MPFS) has been using the generic
"cdns,macb" compatible but has optional reset support. Add a specific
compatible which falls back to the currently used generic binding.
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
Documentation/devicetree/bindings/net/cdns,macb.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/net/cdns,macb.yaml b/Documentation/devicetree/bindings/net/cdns,macb.yaml
index 86fc31c2d91b..9c92156869b2 100644
--- a/Documentation/devicetree/bindings/net/cdns,macb.yaml
+++ b/Documentation/devicetree/bindings/net/cdns,macb.yaml
@@ -28,6 +28,7 @@ properties:
- enum:
- cdns,at91sam9260-macb # Atmel at91sam9 SoCs
- cdns,sam9x60-macb # Microchip sam9x60 SoC
+ - microchip,mpfs-macb # Microchip PolarFire SoC
- const: cdns,macb # Generic
- items:
--
2.36.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [RFC 3/6] clk: microchip: mpfs: add reset controller
2022-06-19 16:49 [RFC 0/6] PolarFire SoC Reset controller Conor Dooley
2022-06-19 16:49 ` [RFC 1/6] dt-bindings: clk: microchip: mpfs: add reset controller support Conor Dooley
2022-06-19 16:49 ` [RFC 2/6] dt-bindings: net: cdns,macb: document polarfire soc's macb Conor Dooley
@ 2022-06-19 16:49 ` Conor Dooley
2022-06-19 17:19 ` Christophe JAILLET
2022-06-19 16:49 ` [RFC 4/6] reset: add polarfire soc reset support Conor Dooley
` (2 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Conor Dooley @ 2022-06-19 16:49 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Conor Dooley, Philipp Zabel,
Geert Uytterhoeven
Cc: Daire McNamara, linux-clk, linux-kernel, linux-riscv
From: Conor Dooley <conor.dooley@microchip.com>
Add a reset controller to PolarFire SoC's clock driver. This reset
controller is registered as an aux device and read/write functions
exported to the drivers namespace so that the reset controller can
access the peripheral device reset register.
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/clk/microchip/Kconfig | 1 +
drivers/clk/microchip/clk-mpfs.c | 118 ++++++++++++++++++++++++++++---
include/soc/microchip/mpfs.h | 8 +++
3 files changed, 116 insertions(+), 11 deletions(-)
diff --git a/drivers/clk/microchip/Kconfig b/drivers/clk/microchip/Kconfig
index a5a99873c4f5..b46e864b3bd8 100644
--- a/drivers/clk/microchip/Kconfig
+++ b/drivers/clk/microchip/Kconfig
@@ -6,5 +6,6 @@ config COMMON_CLK_PIC32
config MCHP_CLK_MPFS
bool "Clk driver for PolarFire SoC"
depends on (RISCV && SOC_MICROCHIP_POLARFIRE) || COMPILE_TEST
+ select AUXILIARY_BUS
help
Supports Clock Configuration for PolarFire SoC
diff --git a/drivers/clk/microchip/clk-mpfs.c b/drivers/clk/microchip/clk-mpfs.c
index 070c3b896559..19a9f8cd12ff 100644
--- a/drivers/clk/microchip/clk-mpfs.c
+++ b/drivers/clk/microchip/clk-mpfs.c
@@ -3,12 +3,15 @@
* Daire McNamara,<daire.mcnamara@microchip.com>
* Copyright (C) 2020 Microchip Technology Inc. All rights reserved.
*/
+#include "linux/device.h"
+#include <linux/auxiliary_bus.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <dt-bindings/clock/microchip,mpfs-clock.h>
+#include <soc/microchip/mpfs.h>
/* address offset of control registers */
#define REG_MSSPLL_REF_CR 0x08u
@@ -28,6 +31,7 @@
#define MSSPLL_FIXED_DIV 4u
struct mpfs_clock_data {
+ struct device *dev;
void __iomem *base;
void __iomem *msspll_base;
struct clk_hw_onecell_data hw_data;
@@ -302,10 +306,6 @@ static int mpfs_periph_clk_enable(struct clk_hw *hw)
spin_lock_irqsave(&mpfs_clk_lock, flags);
- reg = readl_relaxed(base_addr + REG_SUBBLK_RESET_CR);
- val = reg & ~(1u << periph->shift);
- writel_relaxed(val, base_addr + REG_SUBBLK_RESET_CR);
-
reg = readl_relaxed(base_addr + REG_SUBBLK_CLOCK_CR);
val = reg | (1u << periph->shift);
writel_relaxed(val, base_addr + REG_SUBBLK_CLOCK_CR);
@@ -339,12 +339,9 @@ static int mpfs_periph_clk_is_enabled(struct clk_hw *hw)
void __iomem *base_addr = periph_hw->sys_base;
u32 reg;
- reg = readl_relaxed(base_addr + REG_SUBBLK_RESET_CR);
- if ((reg & (1u << periph->shift)) == 0u) {
- reg = readl_relaxed(base_addr + REG_SUBBLK_CLOCK_CR);
- if (reg & (1u << periph->shift))
- return 1;
- }
+ reg = readl_relaxed(base_addr + REG_SUBBLK_CLOCK_CR);
+ if (reg & (1u << periph->shift))
+ return 1;
return 0;
}
@@ -438,6 +435,99 @@ static int mpfs_clk_register_periphs(struct device *dev, struct mpfs_periph_hw_c
return 0;
}
+/*
+ * Peripheral clock resets
+ */
+
+#if IS_ENABLED(CONFIG_RESET_CONTROLLER)
+
+u32 mpfs_reset_read(struct device *dev)
+{
+ struct mpfs_clock_data *clock_data = dev_get_drvdata(dev->parent);
+
+ return readl_relaxed(clock_data->base + REG_SUBBLK_RESET_CR);
+}
+EXPORT_SYMBOL_NS_GPL(mpfs_reset_read, MCHP_CLK_MPFS);
+
+void mpfs_reset_write(struct device *dev, u32 val)
+{
+ struct mpfs_clock_data *clock_data = dev_get_drvdata(dev->parent);
+
+ writel_relaxed(val, clock_data->base + REG_SUBBLK_RESET_CR);
+}
+EXPORT_SYMBOL_NS_GPL(mpfs_reset_write, MCHP_CLK_MPFS);
+
+static void mpfs_reset_unregister_adev(void *_adev)
+{
+ struct auxiliary_device *adev = _adev;
+
+ auxiliary_device_delete(adev);
+}
+
+static void mpfs_reset_adev_release(struct device *dev)
+{
+ struct auxiliary_device *adev = to_auxiliary_dev(dev);
+
+ auxiliary_device_uninit(adev);
+
+ kfree(adev->name);
+ kfree(adev);
+}
+
+static struct auxiliary_device *mpfs_reset_adev_alloc(struct mpfs_clock_data *clk_data)
+{
+ struct auxiliary_device *adev;
+ int ret;
+
+ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
+ if (!adev)
+ return ERR_PTR(-ENOMEM);
+
+ adev->name = "reset-mpfs";
+ adev->dev.parent = clk_data->dev;
+ adev->dev.release = mpfs_reset_adev_release;
+ adev->id = 666u;
+
+ ret = auxiliary_device_init(adev);
+ if (ret) {
+ kfree(adev);
+ return ERR_PTR(ret);
+ }
+
+ return adev;
+}
+
+static int mpfs_reset_controller_register(struct mpfs_clock_data *clk_data)
+{
+ struct auxiliary_device *adev;
+ int ret;
+
+ adev = mpfs_reset_adev_alloc(clk_data);
+ if (IS_ERR(adev))
+ return PTR_ERR(adev);
+
+ ret = auxiliary_device_add(adev);
+ if (ret) {
+ auxiliary_device_uninit(adev);
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(clk_data->dev, mpfs_reset_unregister_adev, adev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+#else /* !CONFIG_RESET_CONTROLLER */
+
+static int mpfs_reset_controller_register(struct mpfs_clock_data *clk_data)
+{
+ return 0;
+}
+
+#endif /* !CONFIG_RESET_CONTROLLER */
+
static int mpfs_clk_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -462,6 +552,8 @@ static int mpfs_clk_probe(struct platform_device *pdev)
return PTR_ERR(clk_data->msspll_base);
clk_data->hw_data.num = num_clks;
+ clk_data->dev = dev;
+ dev_set_drvdata(dev, clk_data);
ret = mpfs_clk_register_mssplls(dev, mpfs_msspll_clks, ARRAY_SIZE(mpfs_msspll_clks),
clk_data);
@@ -481,6 +573,10 @@ static int mpfs_clk_probe(struct platform_device *pdev)
if (ret)
return ret;
+ ret = mpfs_reset_controller_register(clk_data);
+ if (ret)
+ return ret;
+
return ret;
}
@@ -488,7 +584,7 @@ static const struct of_device_id mpfs_clk_of_match_table[] = {
{ .compatible = "microchip,mpfs-clkcfg", },
{}
};
-MODULE_DEVICE_TABLE(of, mpfs_clk_match_table);
+MODULE_DEVICE_TABLE(of, mpfs_clk_of_match_table);
static struct platform_driver mpfs_clk_driver = {
.probe = mpfs_clk_probe,
diff --git a/include/soc/microchip/mpfs.h b/include/soc/microchip/mpfs.h
index 6466515262bd..f916dcde457f 100644
--- a/include/soc/microchip/mpfs.h
+++ b/include/soc/microchip/mpfs.h
@@ -40,4 +40,12 @@ struct mpfs_sys_controller *mpfs_sys_controller_get(struct device *dev);
#endif /* if IS_ENABLED(CONFIG_POLARFIRE_SOC_SYS_CTRL) */
+#if IS_ENABLED(CONFIG_MCHP_CLK_MPFS)
+
+u32 mpfs_reset_read(struct device *dev);
+
+void mpfs_reset_write(struct device *dev, u32 val);
+
+#endif /* if IS_ENABLED(CONFIG_MCHP_CLK_MPFS) */
+
#endif /* __SOC_MPFS_H__ */
--
2.36.1
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [RFC 3/6] clk: microchip: mpfs: add reset controller
2022-06-19 16:49 ` [RFC 3/6] clk: microchip: mpfs: add reset controller Conor Dooley
@ 2022-06-19 17:19 ` Christophe JAILLET
2022-06-19 17:58 ` Conor Dooley
0 siblings, 1 reply; 10+ messages in thread
From: Christophe JAILLET @ 2022-06-19 17:19 UTC (permalink / raw)
To: Conor Dooley, Michael Turquette, Stephen Boyd, Conor Dooley,
Philipp Zabel, Geert Uytterhoeven
Cc: Daire McNamara, linux-clk, linux-kernel, linux-riscv
Le 19/06/2022 à 18:49, Conor Dooley a écrit :
> From: Conor Dooley <conor.dooley@microchip.com>
>
> Add a reset controller to PolarFire SoC's clock driver. This reset
> controller is registered as an aux device and read/write functions
> exported to the drivers namespace so that the reset controller can
> access the peripheral device reset register.
>
> Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
[...]
> +static void mpfs_reset_adev_release(struct device *dev)
> +{
> + struct auxiliary_device *adev = to_auxiliary_dev(dev);
> +
> + auxiliary_device_uninit(adev);
> +
> + kfree(adev->name);
?
Below we have:
adev->name = "reset-mpfs";
> + kfree(adev);
> +}
> +
> +static struct auxiliary_device *mpfs_reset_adev_alloc(struct mpfs_clock_data *clk_data)
> +{
> + struct auxiliary_device *adev;
> + int ret;
> +
> + adev = kzalloc(sizeof(*adev), GFP_KERNEL);
> + if (!adev)
> + return ERR_PTR(-ENOMEM);
> +
> + adev->name = "reset-mpfs";
> + adev->dev.parent = clk_data->dev;
> + adev->dev.release = mpfs_reset_adev_release;
> + adev->id = 666u;
> +
> + ret = auxiliary_device_init(adev);
> + if (ret) {
> + kfree(adev);
> + return ERR_PTR(ret);
> + }
> +
> + return adev;
> +}
[...]
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [RFC 3/6] clk: microchip: mpfs: add reset controller
2022-06-19 17:19 ` Christophe JAILLET
@ 2022-06-19 17:58 ` Conor Dooley
0 siblings, 0 replies; 10+ messages in thread
From: Conor Dooley @ 2022-06-19 17:58 UTC (permalink / raw)
To: Christophe JAILLET, Michael Turquette, Stephen Boyd,
Conor Dooley, Philipp Zabel, Geert Uytterhoeven
Cc: Daire McNamara, linux-clk, linux-kernel, linux-riscv
On 19/06/2022 18:19, Christophe JAILLET wrote:
> Le 19/06/2022 à 18:49, Conor Dooley a écrit :
>> From: Conor Dooley <conor.dooley@microchip.com>
>>
>> Add a reset controller to PolarFire SoC's clock driver. This reset
>> controller is registered as an aux device and read/write functions
>> exported to the drivers namespace so that the reset controller can
>> access the peripheral device reset register.
>>
>> Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
>
> [...]
>
>> +static void mpfs_reset_adev_release(struct device *dev)
>> +{
>> + struct auxiliary_device *adev = to_auxiliary_dev(dev);
>> +
>> + auxiliary_device_uninit(adev);
>> +
>> + kfree(adev->name);
>
> ?
>
> Below we have:
> adev->name = "reset-mpfs";
Aye, good spot thanks.
Was a hangover from me trying to figure out the auxiliary device
naming scheme.
Conor.
>
>
>> + kfree(adev);
>> +}
>> +
>> +static struct auxiliary_device *mpfs_reset_adev_alloc(struct mpfs_clock_data *clk_data)
>> +{
>> + struct auxiliary_device *adev;
>> + int ret;
>> +
>> + adev = kzalloc(sizeof(*adev), GFP_KERNEL);
>> + if (!adev)
>> + return ERR_PTR(-ENOMEM);
>> +
>> + adev->name = "reset-mpfs";
>> + adev->dev.parent = clk_data->dev;
>> + adev->dev.release = mpfs_reset_adev_release;
>> + adev->id = 666u;
>> +
>> + ret = auxiliary_device_init(adev);
>> + if (ret) {
>> + kfree(adev);
>> + return ERR_PTR(ret);
>> + }
>> +
>> + return adev;
>> +}
>
> [...]
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC 4/6] reset: add polarfire soc reset support
2022-06-19 16:49 [RFC 0/6] PolarFire SoC Reset controller Conor Dooley
` (2 preceding siblings ...)
2022-06-19 16:49 ` [RFC 3/6] clk: microchip: mpfs: add reset controller Conor Dooley
@ 2022-06-19 16:49 ` Conor Dooley
2022-06-19 19:06 ` Conor Dooley
2022-06-19 16:49 ` [RFC 5/6] net: macb: " Conor Dooley
2022-06-19 16:49 ` [RFC 6/6] riscv: dts: microchip: add mpfs specific macb " Conor Dooley
5 siblings, 1 reply; 10+ messages in thread
From: Conor Dooley @ 2022-06-19 16:49 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Conor Dooley, Philipp Zabel,
Geert Uytterhoeven
Cc: Daire McNamara, linux-clk, linux-kernel, linux-riscv
From: Conor Dooley <conor.dooley@microchip.com>
Add support for the resets on Microchip's PolarFire SoC (MPFS).
Reset control is a single register, wedged in between registers for
clock control. To fit with existed DT etc, the reset controller is
created using the aux device framework & set up in the clock driver.
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/reset/Kconfig | 9 +++
drivers/reset/Makefile | 2 +-
drivers/reset/reset-mpfs.c | 155 +++++++++++++++++++++++++++++++++++++
3 files changed, 165 insertions(+), 1 deletion(-)
create mode 100644 drivers/reset/reset-mpfs.c
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 93c8d07ee328..8f7d7cda690d 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -122,6 +122,15 @@ config RESET_MCHP_SPARX5
help
This driver supports switch core reset for the Microchip Sparx5 SoC.
+config RESET_POLARFIRE_SOC
+ bool "Microchip PolarFire SoC (MPFS) Reset Driver"
+ depends on AUXILIARY_BUS
+ default MCHP_CLK_MPFS
+ help
+ This driver supports switch core reset for the Microchip PolarFire SoC
+
+ CONFIG_RESET_MPFS
+
config RESET_MESON
tristate "Meson Reset Driver"
depends on ARCH_MESON || COMPILE_TEST
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index a80a9c4008a7..5fac3a753858 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_RESET_K210) += reset-k210.o
obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o
obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
obj-$(CONFIG_RESET_MCHP_SPARX5) += reset-microchip-sparx5.o
+obj-$(CONFIG_RESET_POLARFIRE_SOC) += reset-mpfs.o
obj-$(CONFIG_RESET_MESON) += reset-meson.o
obj-$(CONFIG_RESET_MESON_AUDIO_ARB) += reset-meson-audio-arb.o
obj-$(CONFIG_RESET_NPCM) += reset-npcm.o
@@ -38,4 +39,3 @@ obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
obj-$(CONFIG_ARCH_ZYNQMP) += reset-zynqmp.o
-
diff --git a/drivers/reset/reset-mpfs.c b/drivers/reset/reset-mpfs.c
new file mode 100644
index 000000000000..6c9c10cd9077
--- /dev/null
+++ b/drivers/reset/reset-mpfs.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * PolarFire SoC (MPFS) Peripheral Clock Reset Controller
+ *
+ * Author: Conor Dooley <conor.dooley@microchip.com>
+ * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
+ *
+ */
+#include <linux/auxiliary_bus.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <dt-bindings/clock/microchip,mpfs-clock.h>
+#include <soc/microchip/mpfs.h>
+
+/*
+ * The ENVM reset is the lowest bit in the register & I am using the CLK_FOO
+ * defines in the dt to make things easier to configure - so this is accounting
+ * for the offset of 3 there.
+ */
+#define MPFS_PERIPH_OFFSET CLK_ENVM
+#define MPFS_NUM_RESETS 30u
+
+/*
+ * Peripheral clock resets
+ */
+
+static int mpfs_assert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ u32 reg;
+
+ reg = mpfs_reset_read(rcdev->dev);
+ reg |= (1u << id);
+ mpfs_reset_write(rcdev->dev, reg);
+
+ dev_dbg(rcdev->dev,
+ "Asserting reset for device with REG_SUBBLK_RESET_CR index: %u\n",
+ id);
+ return 0;
+}
+
+static int mpfs_deassert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ u32 reg, val;
+
+ reg = mpfs_reset_read(rcdev->dev);
+ val = reg & ~(1u << id);
+ mpfs_reset_write(rcdev->dev, val);
+
+ dev_dbg(rcdev->dev,
+ "Deasserting device with REG_SUBBLK_RESET_CR index: %u\n",
+ id);
+
+ return 0;
+}
+
+static int mpfs_status(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ u32 reg = mpfs_reset_read(rcdev->dev);
+
+ return (reg & (1u << id));
+}
+
+static int mpfs_reset(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ dev_dbg(rcdev->dev,
+ "Resetting device with REG_SUBBLK_RESET_CR index: %u\n",
+ id);
+
+ mpfs_assert(rcdev, id);
+
+ /* Value is stolen from the rcar reset driver, will need changing after RFC */
+ udelay(35);
+
+ mpfs_deassert(rcdev, id);
+
+ return 0;
+}
+
+static const struct reset_control_ops mpfs_reset_ops = {
+ .reset = mpfs_reset,
+ .assert = mpfs_assert,
+ .deassert = mpfs_deassert,
+ .status = mpfs_status,
+};
+
+static int mpfs_reset_xlate(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *reset_spec)
+{
+ unsigned int index = reset_spec->args[0];
+
+ /*
+ * CLK_RESERVED does not map to a clock, but it does map to a reset,
+ * so it has to be accounted for here. It is the reset for the fabric,
+ * so if this reset gets called - do not reset it.
+ */
+ if (index == CLK_RESERVED) {
+ dev_err(rcdev->dev, "Resetting the fabric is not supported\n");
+ return -EINVAL;
+ }
+
+ if (index < MPFS_PERIPH_OFFSET || index >= (MPFS_PERIPH_OFFSET + rcdev->nr_resets)) {
+ dev_err(rcdev->dev, "Invalid reset index %u\n", reset_spec->args[0]);
+ return -EINVAL;
+ }
+
+ return index - MPFS_PERIPH_OFFSET;
+}
+
+static int mpfs_reset_probe(struct auxiliary_device *adev,
+ const struct auxiliary_device_id *id)
+{
+ struct device *dev = &adev->dev;
+ struct reset_controller_dev *rcdev;
+ int ret;
+
+ rcdev = devm_kzalloc(dev, sizeof(*rcdev), GFP_KERNEL);
+ if (!rcdev)
+ return -ENOMEM;
+
+ rcdev->dev = dev;
+ rcdev->dev->parent = adev->dev.parent;
+ rcdev->ops = &mpfs_reset_ops;
+ rcdev->of_node = adev->dev.parent->of_node;
+ rcdev->of_reset_n_cells = 1;
+ rcdev->of_xlate = mpfs_reset_xlate;
+ rcdev->nr_resets = MPFS_NUM_RESETS;
+
+ ret = devm_reset_controller_register(dev, rcdev);
+ if (!ret)
+ dev_info(dev, "Registered MPFS reset controller\n");
+
+ return ret;
+}
+
+static const struct auxiliary_device_id mpfs_reset_ids[] = {
+ {
+ .name = "clk_mpfs.reset-mpfs",
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(auxiliary, mpfs_reset_ids);
+
+static struct auxiliary_driver mpfs_reset_driver = {
+ .probe = mpfs_reset_probe,
+ .id_table = mpfs_reset_ids,
+};
+
+module_auxiliary_driver(mpfs_reset_driver);
+
+MODULE_DESCRIPTION("Microchip PolarFire SoC Reset Driver");
+MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(MCHP_CLK_MPFS);
--
2.36.1
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [RFC 4/6] reset: add polarfire soc reset support
2022-06-19 16:49 ` [RFC 4/6] reset: add polarfire soc reset support Conor Dooley
@ 2022-06-19 19:06 ` Conor Dooley
0 siblings, 0 replies; 10+ messages in thread
From: Conor Dooley @ 2022-06-19 19:06 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Conor Dooley, Philipp Zabel,
Geert Uytterhoeven
Cc: Daire McNamara, linux-clk, linux-kernel, linux-riscv
On 19/06/2022 17:49, Conor Dooley wrote:
> From: Conor Dooley <conor.dooley@microchip.com>
>
> Add support for the resets on Microchip's PolarFire SoC (MPFS).
> Reset control is a single register, wedged in between registers for
> clock control. To fit with existed DT etc, the reset controller is
> created using the aux device framework & set up in the clock driver.
>
> Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
> ---
> drivers/reset/Kconfig | 9 +++
> drivers/reset/Makefile | 2 +-
> drivers/reset/reset-mpfs.c | 155 +++++++++++++++++++++++++++++++++++++
> 3 files changed, 165 insertions(+), 1 deletion(-)
> create mode 100644 drivers/reset/reset-mpfs.c
>
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index 93c8d07ee328..8f7d7cda690d 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -122,6 +122,15 @@ config RESET_MCHP_SPARX5
> help
> This driver supports switch core reset for the Microchip Sparx5 SoC.
>
> +config RESET_POLARFIRE_SOC
> + bool "Microchip PolarFire SoC (MPFS) Reset Driver"
> + depends on AUXILIARY_BUS
(Correctly) According to lkp I screwed this up, needs to depend on
MCHP_CLK_MPFS.
> + default MCHP_CLK_MPFS
> + help
> + This driver supports switch core reset for the Microchip PolarFire SoC
> +
> + CONFIG_RESET_MPFS
> +
> config RESET_MESON
> tristate "Meson Reset Driver"
> depends on ARCH_MESON || COMPILE_TEST
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index a80a9c4008a7..5fac3a753858 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_RESET_K210) += reset-k210.o
> obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o
> obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
> obj-$(CONFIG_RESET_MCHP_SPARX5) += reset-microchip-sparx5.o
> +obj-$(CONFIG_RESET_POLARFIRE_SOC) += reset-mpfs.o
> obj-$(CONFIG_RESET_MESON) += reset-meson.o
> obj-$(CONFIG_RESET_MESON_AUDIO_ARB) += reset-meson-audio-arb.o
> obj-$(CONFIG_RESET_NPCM) += reset-npcm.o
> @@ -38,4 +39,3 @@ obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
> obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
> obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
> obj-$(CONFIG_ARCH_ZYNQMP) += reset-zynqmp.o
> -
> diff --git a/drivers/reset/reset-mpfs.c b/drivers/reset/reset-mpfs.c
> new file mode 100644
> index 000000000000..6c9c10cd9077
> --- /dev/null
> +++ b/drivers/reset/reset-mpfs.c
> @@ -0,0 +1,155 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * PolarFire SoC (MPFS) Peripheral Clock Reset Controller
> + *
> + * Author: Conor Dooley <conor.dooley@microchip.com>
> + * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
> + *
> + */
> +#include <linux/auxiliary_bus.h>
> +#include <linux/delay.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset-controller.h>
> +#include <dt-bindings/clock/microchip,mpfs-clock.h>
> +#include <soc/microchip/mpfs.h>
> +
> +/*
> + * The ENVM reset is the lowest bit in the register & I am using the CLK_FOO
> + * defines in the dt to make things easier to configure - so this is accounting
> + * for the offset of 3 there.
> + */
> +#define MPFS_PERIPH_OFFSET CLK_ENVM
> +#define MPFS_NUM_RESETS 30u
> +
> +/*
> + * Peripheral clock resets
> + */
> +
> +static int mpfs_assert(struct reset_controller_dev *rcdev, unsigned long id)
> +{
> + u32 reg;
> +
> + reg = mpfs_reset_read(rcdev->dev);
> + reg |= (1u << id);
> + mpfs_reset_write(rcdev->dev, reg);
> +
> + dev_dbg(rcdev->dev,
> + "Asserting reset for device with REG_SUBBLK_RESET_CR index: %u\n",
> + id);
> + return 0;
> +}
> +
> +static int mpfs_deassert(struct reset_controller_dev *rcdev, unsigned long id)
> +{
> + u32 reg, val;
> +
> + reg = mpfs_reset_read(rcdev->dev);
> + val = reg & ~(1u << id);
> + mpfs_reset_write(rcdev->dev, val);
> +
> + dev_dbg(rcdev->dev,
> + "Deasserting device with REG_SUBBLK_RESET_CR index: %u\n",
> + id);
> +
> + return 0;
> +}
> +
> +static int mpfs_status(struct reset_controller_dev *rcdev, unsigned long id)
> +{
> + u32 reg = mpfs_reset_read(rcdev->dev);
> +
> + return (reg & (1u << id));
> +}
> +
> +static int mpfs_reset(struct reset_controller_dev *rcdev, unsigned long id)
> +{
> + dev_dbg(rcdev->dev,
> + "Resetting device with REG_SUBBLK_RESET_CR index: %u\n",
> + id);
> +
> + mpfs_assert(rcdev, id);
> +
> + /* Value is stolen from the rcar reset driver, will need changing after RFC */
> + udelay(35);
> +
> + mpfs_deassert(rcdev, id);
> +
> + return 0;
> +}
> +
> +static const struct reset_control_ops mpfs_reset_ops = {
> + .reset = mpfs_reset,
> + .assert = mpfs_assert,
> + .deassert = mpfs_deassert,
> + .status = mpfs_status,
> +};
> +
> +static int mpfs_reset_xlate(struct reset_controller_dev *rcdev,
> + const struct of_phandle_args *reset_spec)
> +{
> + unsigned int index = reset_spec->args[0];
> +
> + /*
> + * CLK_RESERVED does not map to a clock, but it does map to a reset,
> + * so it has to be accounted for here. It is the reset for the fabric,
> + * so if this reset gets called - do not reset it.
> + */
> + if (index == CLK_RESERVED) {
> + dev_err(rcdev->dev, "Resetting the fabric is not supported\n");
> + return -EINVAL;
> + }
> +
> + if (index < MPFS_PERIPH_OFFSET || index >= (MPFS_PERIPH_OFFSET + rcdev->nr_resets)) {
> + dev_err(rcdev->dev, "Invalid reset index %u\n", reset_spec->args[0]);
> + return -EINVAL;
> + }
> +
> + return index - MPFS_PERIPH_OFFSET;
> +}
> +
> +static int mpfs_reset_probe(struct auxiliary_device *adev,
> + const struct auxiliary_device_id *id)
> +{
> + struct device *dev = &adev->dev;
> + struct reset_controller_dev *rcdev;
> + int ret;
> +
> + rcdev = devm_kzalloc(dev, sizeof(*rcdev), GFP_KERNEL);
> + if (!rcdev)
> + return -ENOMEM;
> +
> + rcdev->dev = dev;
> + rcdev->dev->parent = adev->dev.parent;
> + rcdev->ops = &mpfs_reset_ops;
> + rcdev->of_node = adev->dev.parent->of_node;
> + rcdev->of_reset_n_cells = 1;
> + rcdev->of_xlate = mpfs_reset_xlate;
> + rcdev->nr_resets = MPFS_NUM_RESETS;
> +
> + ret = devm_reset_controller_register(dev, rcdev);
> + if (!ret)
> + dev_info(dev, "Registered MPFS reset controller\n");
> +
> + return ret;
> +}
> +
> +static const struct auxiliary_device_id mpfs_reset_ids[] = {
> + {
> + .name = "clk_mpfs.reset-mpfs",
> + },
> + { }
> +};
> +MODULE_DEVICE_TABLE(auxiliary, mpfs_reset_ids);
> +
> +static struct auxiliary_driver mpfs_reset_driver = {
> + .probe = mpfs_reset_probe,
> + .id_table = mpfs_reset_ids,
> +};
> +
> +module_auxiliary_driver(mpfs_reset_driver);
> +
> +MODULE_DESCRIPTION("Microchip PolarFire SoC Reset Driver");
> +MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS(MCHP_CLK_MPFS);
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC 5/6] net: macb: add polarfire soc reset support
2022-06-19 16:49 [RFC 0/6] PolarFire SoC Reset controller Conor Dooley
` (3 preceding siblings ...)
2022-06-19 16:49 ` [RFC 4/6] reset: add polarfire soc reset support Conor Dooley
@ 2022-06-19 16:49 ` Conor Dooley
2022-06-19 16:49 ` [RFC 6/6] riscv: dts: microchip: add mpfs specific macb " Conor Dooley
5 siblings, 0 replies; 10+ messages in thread
From: Conor Dooley @ 2022-06-19 16:49 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Conor Dooley, Philipp Zabel,
Geert Uytterhoeven
Cc: Daire McNamara, linux-clk, linux-kernel, linux-riscv
From: Conor Dooley <conor.dooley@microchip.com>
To date, the Microchip PolarFire SoC (MPFS) has been using the
cdns,macb compatible, however the generic device does not have reset
support. Add a new compatible & .data for MPFS to hook into the reset
functionality added for zynqmp support (and make the zynqmp init
function generic in the process).
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/net/ethernet/cadence/macb_main.c | 25 +++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index d89098f4ede8..325f0463fd42 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -4689,33 +4689,32 @@ static const struct macb_config np4_config = {
.usrio = &macb_default_usrio,
};
-static int zynqmp_init(struct platform_device *pdev)
+static int init_reset_optional(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct macb *bp = netdev_priv(dev);
int ret;
if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) {
- /* Ensure PS-GTR PHY device used in SGMII mode is ready */
+ /* Ensure PHY device used in SGMII mode is ready */
bp->sgmii_phy = devm_phy_optional_get(&pdev->dev, NULL);
if (IS_ERR(bp->sgmii_phy)) {
ret = PTR_ERR(bp->sgmii_phy);
dev_err_probe(&pdev->dev, ret,
- "failed to get PS-GTR PHY\n");
+ "failed to get SGMII PHY\n");
return ret;
}
ret = phy_init(bp->sgmii_phy);
if (ret) {
- dev_err(&pdev->dev, "failed to init PS-GTR PHY: %d\n",
+ dev_err(&pdev->dev, "failed to init SGMII PHY: %d\n",
ret);
return ret;
}
}
- /* Fully reset GEM controller at hardware level using zynqmp-reset driver,
- * if mapped in device tree.
+ /* Fully reset controller at hardware level if mapped in device tree
*/
ret = device_reset_optional(&pdev->dev);
if (ret) {
@@ -4737,7 +4736,7 @@ static const struct macb_config zynqmp_config = {
MACB_CAPS_GEM_HAS_PTP | MACB_CAPS_BD_RD_PREFETCH,
.dma_burst_length = 16,
.clk_init = macb_clk_init,
- .init = zynqmp_init,
+ .init = init_reset_optional,
.jumbo_max_len = 10240,
.usrio = &macb_default_usrio,
};
@@ -4751,6 +4750,17 @@ static const struct macb_config zynq_config = {
.usrio = &macb_default_usrio,
};
+static const struct macb_config mpfs_config = {
+ .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
+ MACB_CAPS_JUMBO |
+ MACB_CAPS_GEM_HAS_PTP,
+ .dma_burst_length = 16,
+ .clk_init = macb_clk_init,
+ .init = init_reset_optional,
+ .usrio = &macb_default_usrio,
+ .jumbo_max_len = 10240,
+};
+
static const struct macb_config sama7g5_gem_config = {
.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_CLK_HW_CHG |
MACB_CAPS_MIIONRGMII,
@@ -4787,6 +4797,7 @@ static const struct of_device_id macb_dt_ids[] = {
{ .compatible = "cdns,zynqmp-gem", .data = &zynqmp_config},
{ .compatible = "cdns,zynq-gem", .data = &zynq_config },
{ .compatible = "sifive,fu540-c000-gem", .data = &fu540_c000_config },
+ { .compatible = "microchip,mpfs-macb", .data = &mpfs_config },
{ .compatible = "microchip,sama7g5-gem", .data = &sama7g5_gem_config },
{ .compatible = "microchip,sama7g5-emac", .data = &sama7g5_emac_config },
{ /* sentinel */ }
--
2.36.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [RFC 6/6] riscv: dts: microchip: add mpfs specific macb reset support
2022-06-19 16:49 [RFC 0/6] PolarFire SoC Reset controller Conor Dooley
` (4 preceding siblings ...)
2022-06-19 16:49 ` [RFC 5/6] net: macb: " Conor Dooley
@ 2022-06-19 16:49 ` Conor Dooley
5 siblings, 0 replies; 10+ messages in thread
From: Conor Dooley @ 2022-06-19 16:49 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Conor Dooley, Philipp Zabel,
Geert Uytterhoeven
Cc: Daire McNamara, linux-clk, linux-kernel, linux-riscv
From: Conor Dooley <conor.dooley@microchip.com>
The macb on PolarFire SoC has reset support which the generic compatible
does not use. Add the newly introduced MPFS specific compatible as the
primary compatible to avail of this support & wire up the reset to the
clock controllers devicetree entry.
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
arch/riscv/boot/dts/microchip/mpfs.dtsi | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/boot/dts/microchip/mpfs.dtsi b/arch/riscv/boot/dts/microchip/mpfs.dtsi
index 8c3259134194..5a33cbf9467a 100644
--- a/arch/riscv/boot/dts/microchip/mpfs.dtsi
+++ b/arch/riscv/boot/dts/microchip/mpfs.dtsi
@@ -197,6 +197,7 @@ clkcfg: clkcfg@20002000 {
reg = <0x0 0x20002000 0x0 0x1000>, <0x0 0x3E001000 0x0 0x1000>;
clocks = <&refclk>;
#clock-cells = <1>;
+ #reset-cells = <1>;
};
mmuart0: serial@20000000 {
@@ -331,7 +332,7 @@ i2c1: i2c@2010b000 {
};
mac0: ethernet@20110000 {
- compatible = "cdns,macb";
+ compatible = "microchip,mpfs-macb", "cdns,macb";
reg = <0x0 0x20110000 0x0 0x2000>;
#address-cells = <1>;
#size-cells = <0>;
@@ -340,11 +341,12 @@ mac0: ethernet@20110000 {
local-mac-address = [00 00 00 00 00 00];
clocks = <&clkcfg CLK_MAC0>, <&clkcfg CLK_AHB>;
clock-names = "pclk", "hclk";
+ resets = <&clkcfg CLK_MAC0>;
status = "disabled";
};
mac1: ethernet@20112000 {
- compatible = "cdns,macb";
+ compatible = "microchip,mpfs-macb", "cdns,macb";
reg = <0x0 0x20112000 0x0 0x2000>;
#address-cells = <1>;
#size-cells = <0>;
@@ -353,6 +355,7 @@ mac1: ethernet@20112000 {
local-mac-address = [00 00 00 00 00 00];
clocks = <&clkcfg CLK_MAC1>, <&clkcfg CLK_AHB>;
clock-names = "pclk", "hclk";
+ resets = <&clkcfg CLK_MAC1>;
status = "disabled";
};
--
2.36.1
^ permalink raw reply [flat|nested] 10+ messages in thread