arm: mvebu: Implement simple mvebu-reset driver for enabling/disabling PCIe ports
authorPali Rohár <pali@kernel.org>
Tue, 21 Dec 2021 11:20:18 +0000 (12:20 +0100)
committerStefan Roese <sr@denx.de>
Fri, 14 Jan 2022 06:47:57 +0000 (07:47 +0100)
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 <pali@kernel.org>
arch/arm/dts/armada-375.dtsi
arch/arm/dts/armada-38x.dtsi
arch/arm/dts/armada-xp-98dx3236.dtsi
arch/arm/dts/armada-xp.dtsi
arch/arm/mach-mvebu/Makefile
arch/arm/mach-mvebu/system-controller.c [new file with mode: 0644]

index 62a548a..fdf2d6d 100644 (file)
                                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 {
index 72c49be..061bd78 100644 (file)
                                compatible = "marvell,armada-380-system-controller",
                                             "marvell,armada-370-xp-system-controller";
                                reg = <0x18200 0x100>;
+                               #reset-cells = <2>;
                        };
 
                        gateclk: clock-gating-control@18220 {
index 5df1d18..8369de7 100644 (file)
                        systemc: system-controller@18200 {
                                compatible = "marvell,armada-370-xp-system-controller";
                                reg = <0x18200 0x500>;
+                               #reset-cells = <2>;
                        };
 
                        gateclk: clock-gating-control@18220 {
index d856d96..fb5640b 100644 (file)
@@ -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 {
index 7e9c206..0b2c57e 100644 (file)
@@ -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 (file)
index 0000000..ea858b2
--- /dev/null
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0+
+// (C) 2021 Pali Rohár <pali@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,
+};