]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
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 62a548a55f3f7792e6012695b6a28bcf11ac3924..fdf2d6dbdc8416cece93cc751132c904bfddaf69 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 72c49beb71a43902c57cadfba6d0fc4c814dc155..061bd78520812a0e18dfef2bbdd0a11337821fd9 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 5df1d1848dbcaa5a2017ad1f4039763756fb1371..8369de79afa299e748b95d304ec423b13c78f349 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 d856d96022727a7802fcd71c5b526a309d0a0bda..fb5640bbd93c75e240b971f999db8483608e9275 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 7e9c206ed6b87dafb2288beb12bdf601915a60ee..0b2c57e573604b1c1576438ec15a873c4b785e80 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,
+};