Enabling and disabling PCIe ports is done via address space of system
controller. All 32-bit Armada SoCs use low 4 bits in SoC Control 1 Register
for enabling and disabling some or more PCIe ports. Correct mapping needs
to be set in particular DTS files.

DT API for mvebu-reset is prepared for implementing resets also for other
HW blocks, but currently only PCIe is implemented via index 0.

Currently this driver is not used as PCIe ports are automatically enabled
by SerDes code executed by U-Boot SPL. But this will change in followup
patches.

Signed-off-by: Pali Rohár <p...@kernel.org>
---
 arch/arm/dts/armada-375.dtsi            |   3 +-
 arch/arm/dts/armada-38x.dtsi            |   1 +
 arch/arm/dts/armada-xp-98dx3236.dtsi    |   1 +
 arch/arm/dts/armada-xp.dtsi             |   1 +
 arch/arm/mach-mvebu/Makefile            |   1 +
 arch/arm/mach-mvebu/system-controller.c | 105 ++++++++++++++++++++++++
 6 files changed, 111 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-mvebu/system-controller.c

diff --git a/arch/arm/dts/armada-375.dtsi b/arch/arm/dts/armada-375.dtsi
index 62a548a55f3f..fdf2d6dbdc84 100644
--- a/arch/arm/dts/armada-375.dtsi
+++ b/arch/arm/dts/armada-375.dtsi
@@ -384,9 +384,10 @@
                                interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
-                       system-controller@18200 {
+                       systemc: system-controller@18200 {
                                compatible = 
"marvell,armada-375-system-controller";
                                reg = <0x18200 0x100>;
+                               #reset-cells = <2>;
                        };
 
                        gateclk: clock-gating-control@18220 {
diff --git a/arch/arm/dts/armada-38x.dtsi b/arch/arm/dts/armada-38x.dtsi
index 72c49beb71a4..061bd7852081 100644
--- a/arch/arm/dts/armada-38x.dtsi
+++ b/arch/arm/dts/armada-38x.dtsi
@@ -328,6 +328,7 @@
                                compatible = 
"marvell,armada-380-system-controller",
                                             
"marvell,armada-370-xp-system-controller";
                                reg = <0x18200 0x100>;
+                               #reset-cells = <2>;
                        };
 
                        gateclk: clock-gating-control@18220 {
diff --git a/arch/arm/dts/armada-xp-98dx3236.dtsi 
b/arch/arm/dts/armada-xp-98dx3236.dtsi
index 5df1d1848dbc..8369de79afa2 100644
--- a/arch/arm/dts/armada-xp-98dx3236.dtsi
+++ b/arch/arm/dts/armada-xp-98dx3236.dtsi
@@ -136,6 +136,7 @@
                        systemc: system-controller@18200 {
                                compatible = 
"marvell,armada-370-xp-system-controller";
                                reg = <0x18200 0x500>;
+                               #reset-cells = <2>;
                        };
 
                        gateclk: clock-gating-control@18220 {
diff --git a/arch/arm/dts/armada-xp.dtsi b/arch/arm/dts/armada-xp.dtsi
index d856d9602272..fb5640bbd93c 100644
--- a/arch/arm/dts/armada-xp.dtsi
+++ b/arch/arm/dts/armada-xp.dtsi
@@ -78,6 +78,7 @@
                        systemc: system-controller@18200 {
                                compatible = 
"marvell,armada-370-xp-system-controller";
                                reg = <0x18200 0x500>;
+                               #reset-cells = <2>;
                        };
 
                        gateclk: clock-gating-control@18220 {
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 7e9c206ed6b8..0b2c57e57360 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -21,6 +21,7 @@ else # CONFIG_ARCH_KIRKWOOD
 
 obj-y  = cpu.o
 obj-y  += dram.o
+obj-$(CONFIG_DM_RESET) += system-controller.o
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_ARMADA_375) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_38X) += ../../../drivers/ddr/marvell/a38x/xor.o
diff --git a/arch/arm/mach-mvebu/system-controller.c 
b/arch/arm/mach-mvebu/system-controller.c
new file mode 100644
index 000000000000..a59fc26e38b1
--- /dev/null
+++ b/arch/arm/mach-mvebu/system-controller.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0+
+// (C) 2021 Pali Rohár <p...@kernel.org>
+
+#include <common.h>
+#include <dm.h>
+#include <reset-uclass.h>
+#include <asm/io.h>
+
+#define MVEBU_SOC_CONTROL_1_REG 0x4
+
+#define MVEBU_PCIE_ID 0
+
+struct mvebu_reset_data {
+       void *base;
+};
+
+static int mvebu_reset_of_xlate(struct reset_ctl *rst,
+                               struct ofnode_phandle_args *args)
+{
+       if (args->args_count < 2)
+               return -EINVAL;
+
+       rst->id = args->args[0];
+       rst->data = args->args[1];
+
+       /* Currently only PCIe is implemented */
+       if (rst->id != MVEBU_PCIE_ID)
+               return -EINVAL;
+
+       /* Four PCIe enable bits are shared across more PCIe links */
+       if (!(rst->data >= 0 && rst->data <= 3))
+               return -EINVAL;
+
+       return 0;
+}
+
+static int mvebu_reset_request(struct reset_ctl *rst)
+{
+       return 0;
+}
+
+static int mvebu_reset_free(struct reset_ctl *rst)
+{
+       return 0;
+}
+
+static int mvebu_reset_assert(struct reset_ctl *rst)
+{
+       struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+
+       clrbits_32(data->base + MVEBU_SOC_CONTROL_1_REG, BIT(rst->data));
+       return 0;
+}
+
+static int mvebu_reset_deassert(struct reset_ctl *rst)
+{
+       struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+
+       setbits_32(data->base + MVEBU_SOC_CONTROL_1_REG, BIT(rst->data));
+       return 0;
+}
+
+static int mvebu_reset_status(struct reset_ctl *rst)
+{
+       struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+
+       return !(readl(data->base + MVEBU_SOC_CONTROL_1_REG) & BIT(rst->data));
+}
+
+static int mvebu_reset_of_to_plat(struct udevice *dev)
+{
+       struct mvebu_reset_data *data = dev_get_priv(dev);
+
+       data->base = (void *)dev_read_addr(dev);
+       if ((fdt_addr_t)data->base == FDT_ADDR_T_NONE)
+               return -EINVAL;
+
+       return 0;
+}
+
+static const struct udevice_id mvebu_reset_of_match[] = {
+       { .compatible = "marvell,armada-370-xp-system-controller" },
+       { .compatible = "marvell,armada-375-system-controller" },
+       { .compatible = "marvell,armada-380-system-controller" },
+       { .compatible = "marvell,armada-390-system-controller" },
+       { },
+};
+
+static struct reset_ops mvebu_reset_ops = {
+       .of_xlate = mvebu_reset_of_xlate,
+       .request = mvebu_reset_request,
+       .rfree = mvebu_reset_free,
+       .rst_assert = mvebu_reset_assert,
+       .rst_deassert = mvebu_reset_deassert,
+       .rst_status = mvebu_reset_status,
+};
+
+U_BOOT_DRIVER(mvebu_reset) = {
+       .name = "mvebu-reset",
+       .id = UCLASS_RESET,
+       .of_match = mvebu_reset_of_match,
+       .of_to_plat = mvebu_reset_of_to_plat,
+       .priv_auto = sizeof(struct mvebu_reset_data),
+       .ops = &mvebu_reset_ops,
+};
-- 
2.20.1

Reply via email to