summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/Kconfig12
-rw-r--r--drivers/ata/Makefile2
-rw-r--r--drivers/ata/ahci_generic.c (renamed from drivers/ata/ahci_mvebu.c)17
-rw-r--r--drivers/core/acpi.c16
-rw-r--r--drivers/cpu/Kconfig7
-rw-r--r--drivers/cpu/Makefile2
-rw-r--r--drivers/cpu/armv8_cpu.c151
-rw-r--r--drivers/cpu/armv8_cpu.h31
-rw-r--r--drivers/cpu/bcm283x_cpu.c214
-rw-r--r--drivers/misc/irq-uclass.c66
-rw-r--r--drivers/pci/pcie_brcmstb.c101
-rw-r--r--drivers/serial/serial_pl01x.c24
-rw-r--r--drivers/usb/host/Kconfig8
-rw-r--r--drivers/usb/host/Makefile1
-rw-r--r--drivers/usb/host/xhci-generic.c75
15 files changed, 621 insertions, 106 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 6cca561f974..4fbb63a148a 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -78,14 +78,16 @@ config MTK_AHCI
Enable this driver to support Sata devices through
Mediatek AHCI controller (e.g. MT7622).
-config AHCI_MVEBU
- bool "Marvell EBU AHCI SATA support"
- depends on ARCH_MVEBU || ARCH_OCTEON
+config AHCI_GENERIC
+ bool "Generic AHCI SATA support"
+ depends on OF_CONTROL
select SCSI_AHCI
select SCSI
help
- This option enables support for the Marvell EBU SoC's
- onboard AHCI SATA.
+ This option enables support for generic onboard AHCI SATA controller
+ that do not need platform specific quirks, like emulated devices,
+ Marvell EBU SoC's onboard AHCI SATA controllers or Cavium's Octeon
+ 7130 AHCI controllers.
If unsure, say N.
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index ee10c4445b0..69fa9b707e0 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -14,6 +14,6 @@ obj-$(CONFIG_SATA) += sata.o sata_bootdev.o
obj-$(CONFIG_SATA_CEVA) += sata_ceva.o
obj-$(CONFIG_SATA_MV) += sata_mv.o
obj-$(CONFIG_SATA_SIL) += sata_sil.o
-obj-$(CONFIG_AHCI_MVEBU) += ahci_mvebu.o
+obj-$(CONFIG_AHCI_GENERIC) += ahci_generic.o
obj-$(CONFIG_SUNXI_AHCI) += ahci_sunxi.o
obj-$(CONFIG_MTK_AHCI) += mtk_ahci.o
diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_generic.c
index f6e2d6bee45..6e5a6cbafd8 100644
--- a/drivers/ata/ahci_mvebu.c
+++ b/drivers/ata/ahci_generic.c
@@ -16,7 +16,7 @@ __weak int board_ahci_enable(void)
return 0;
}
-static int mvebu_ahci_bind(struct udevice *dev)
+static int generic_ahci_bind(struct udevice *dev)
{
struct udevice *scsi_dev;
int ret;
@@ -30,7 +30,7 @@ static int mvebu_ahci_bind(struct udevice *dev)
return 0;
}
-static int mvebu_ahci_probe(struct udevice *dev)
+static int generic_ahci_probe(struct udevice *dev)
{
/*
* Board specific SATA / AHCI enable code, e.g. enable the
@@ -43,18 +43,19 @@ static int mvebu_ahci_probe(struct udevice *dev)
return 0;
}
-static const struct udevice_id mvebu_ahci_ids[] = {
+static const struct udevice_id generic_ahci_ids[] = {
{ .compatible = "marvell,armada-380-ahci" },
{ .compatible = "marvell,armada-3700-ahci" },
{ .compatible = "marvell,armada-8k-ahci" },
{ .compatible = "cavium,octeon-7130-ahci" },
+ { .compatible = "generic-ahci" },
{ }
};
-U_BOOT_DRIVER(ahci_mvebu_drv) = {
- .name = "ahci_mvebu",
+U_BOOT_DRIVER(ahci_generic_drv) = {
+ .name = "ahci_generic",
.id = UCLASS_AHCI,
- .of_match = mvebu_ahci_ids,
- .bind = mvebu_ahci_bind,
- .probe = mvebu_ahci_probe,
+ .of_match = generic_ahci_ids,
+ .bind = generic_ahci_bind,
+ .probe = generic_ahci_probe,
};
diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c
index 9f784228921..4763963914b 100644
--- a/drivers/core/acpi.c
+++ b/drivers/core/acpi.c
@@ -48,6 +48,7 @@ enum method_t {
METHOD_FILL_SSDT,
METHOD_INJECT_DSDT,
METHOD_SETUP_NHLT,
+ METHOD_FILL_MADT,
};
/* Prototype for all methods */
@@ -282,6 +283,8 @@ acpi_method acpi_get_method(struct udevice *dev, enum method_t method)
switch (method) {
case METHOD_WRITE_TABLES:
return aops->write_tables;
+ case METHOD_FILL_MADT:
+ return aops->fill_madt;
case METHOD_FILL_SSDT:
return aops->fill_ssdt;
case METHOD_INJECT_DSDT:
@@ -328,6 +331,19 @@ int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent,
return 0;
}
+int acpi_fill_madt_subtbl(struct acpi_ctx *ctx)
+{
+ int ret;
+
+ log_debug("Writing MADT table\n");
+ ret = acpi_recurse_method(ctx, dm_root(), METHOD_FILL_MADT, TYPE_NONE);
+ log_debug("Writing MADT finished, err=%d\n", ret);
+ if (ret)
+ return log_msg_ret("build", ret);
+
+ return ret;
+}
+
int acpi_fill_ssdt(struct acpi_ctx *ctx)
{
void *start = ctx->current;
diff --git a/drivers/cpu/Kconfig b/drivers/cpu/Kconfig
index 5c06cd9f60e..4cc3679c009 100644
--- a/drivers/cpu/Kconfig
+++ b/drivers/cpu/Kconfig
@@ -26,6 +26,13 @@ config CPU_RISCV
help
Support CPU cores for RISC-V architecture.
+config CPU_ARMV8
+ bool "Enable generic ARMv8 CPU driver"
+ depends on CPU && ARM64
+ select IRQ
+ help
+ Support CPU cores for armv8 architecture.
+
config CPU_MICROBLAZE
bool "Enable Microblaze CPU driver"
depends on CPU && MICROBLAZE
diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile
index bc75d9b974e..eaf494706e2 100644
--- a/drivers/cpu/Makefile
+++ b/drivers/cpu/Makefile
@@ -6,10 +6,12 @@
obj-$(CONFIG_CPU) += cpu-uclass.o
+obj-$(CONFIG_ARCH_BCM283X) += bcm283x_cpu.o
obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o
obj-$(CONFIG_ARCH_IMX8) += imx8_cpu.o
obj-$(CONFIG_ARCH_AT91) += at91_cpu.o
obj-$(CONFIG_ARCH_MEDIATEK) += mtk_cpu.o
+obj-$(CONFIG_CPU_ARMV8) += armv8_cpu.o
obj-$(CONFIG_CPU_IMX) += imx8_cpu.o
obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o
diff --git a/drivers/cpu/armv8_cpu.c b/drivers/cpu/armv8_cpu.c
new file mode 100644
index 00000000000..4eedfe5e2c5
--- /dev/null
+++ b/drivers/cpu/armv8_cpu.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 9elements GmbH
+ */
+#include <cpu.h>
+#include <dm.h>
+#include <irq.h>
+#include <acpi/acpigen.h>
+#include <asm/armv8/cpu.h>
+#include <asm/io.h>
+#include <dm/acpi.h>
+#include <linux/bitops.h>
+#include <linux/printk.h>
+#include <linux/sizes.h>
+
+static int armv8_cpu_get_desc(const struct udevice *dev, char *buf, int size)
+{
+ int cpuid;
+
+ cpuid = (read_midr() & MIDR_PARTNUM_MASK) >> MIDR_PARTNUM_SHIFT;
+
+ snprintf(buf, size, "CPU MIDR %04x", cpuid);
+
+ return 0;
+}
+
+static int armv8_cpu_get_info(const struct udevice *dev,
+ struct cpu_info *info)
+{
+ info->cpu_freq = 0;
+ info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU);
+
+ return 0;
+}
+
+static int armv8_cpu_get_count(const struct udevice *dev)
+{
+ return uclass_id_count(UCLASS_CPU);
+}
+
+#ifdef CONFIG_ACPIGEN
+int armv8_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
+{
+ uint core_id = dev_seq(dev);
+
+ acpigen_write_processor_device(ctx, core_id);
+
+ return 0;
+}
+
+int armv8_cpu_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx)
+{
+ struct acpi_madt_gicc *gicc;
+ struct cpu_plat *cpu_plat;
+ struct udevice *gic;
+ u64 gicc_gicv = 0;
+ u64 gicc_gich = 0;
+ u64 gicc_gicr_base = 0;
+ u64 gicc_phys_base = 0;
+ u32 gicc_perf_gsiv = 0;
+ u64 gicc_mpidr;
+ u32 gicc_vgic_maint_irq = 0;
+ int addr_index;
+ fdt_addr_t addr;
+ int ret;
+ struct irq req_irq;
+
+ cpu_plat = dev_get_parent_plat(dev);
+ if (!cpu_plat)
+ return 0;
+
+ ret = irq_get_interrupt_parent(dev, &gic);
+ if (ret) {
+ log_err("%s: Failed to find interrupt parent for %s\n",
+ __func__, dev->name);
+ return -ENODEV;
+ }
+
+ addr_index = 1;
+
+ if (device_is_compatible(gic, "arm,gic-v3")) {
+ addr = dev_read_addr_index(gic, addr_index++);
+ if (addr != FDT_ADDR_T_NONE)
+ gicc_gicr_base = addr;
+ }
+
+ addr = dev_read_addr_index(gic, addr_index++);
+ if (addr != FDT_ADDR_T_NONE)
+ gicc_phys_base = addr;
+
+ addr = dev_read_addr_index(gic, addr_index++);
+ if (addr != FDT_ADDR_T_NONE)
+ gicc_gich = addr;
+
+ addr = dev_read_addr_index(gic, addr_index++);
+ if (addr != FDT_ADDR_T_NONE)
+ gicc_gicv = addr;
+
+ ret = irq_get_by_index(gic, 0, &req_irq);
+ if (!ret)
+ gicc_vgic_maint_irq = req_irq.id;
+
+ gicc_mpidr = dev_read_u64_default(dev, "reg", 0);
+ if (!gicc_mpidr)
+ gicc_mpidr = dev_read_u32_default(dev, "reg", 0);
+
+ /*
+ * gicc_vgic_maint_irq and gicc_gicv are the same for every CPU
+ */
+ gicc = ctx->current;
+ acpi_write_madt_gicc(gicc,
+ dev_seq(dev),
+ gicc_perf_gsiv, /* FIXME: needs a PMU driver */
+ gicc_phys_base,
+ gicc_gicv,
+ gicc_gich,
+ gicc_vgic_maint_irq,
+ gicc_gicr_base,
+ gicc_mpidr,
+ 0); /* FIXME: Not defined in DT */
+
+ acpi_inc(ctx, gicc->length);
+
+ return 0;
+}
+
+struct acpi_ops armv8_cpu_acpi_ops = {
+ .fill_ssdt = armv8_cpu_fill_ssdt,
+ .fill_madt = armv8_cpu_fill_madt,
+};
+#endif
+
+static const struct cpu_ops cpu_ops = {
+ .get_count = armv8_cpu_get_count,
+ .get_desc = armv8_cpu_get_desc,
+ .get_info = armv8_cpu_get_info,
+};
+
+static const struct udevice_id cpu_ids[] = {
+ { .compatible = "arm,armv8" },
+ {}
+};
+
+U_BOOT_DRIVER(arm_cpu) = {
+ .name = "arm-cpu",
+ .id = UCLASS_CPU,
+ .of_match = cpu_ids,
+ .ops = &cpu_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+ ACPI_OPS_PTR(&armv8_cpu_acpi_ops)
+};
diff --git a/drivers/cpu/armv8_cpu.h b/drivers/cpu/armv8_cpu.h
new file mode 100644
index 00000000000..48c705e98de
--- /dev/null
+++ b/drivers/cpu/armv8_cpu.h
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 9elements GmbH
+ */
+#include <dm/acpi.h>
+#include <dm/device.h>
+
+#ifndef _ARMV8_CPU_H_
+#define _ARMV8_CPU_H_
+
+/**
+ * armv8_cpu_fill_ssdt() - Fill the SSDT
+ * Parses the FDT and writes the SSDT nodes.
+ *
+ * @dev: cpu device to generate ACPI tables for
+ * @ctx: ACPI context pointer
+ * @return: 0 if OK, or a negative error code.
+ */
+int armv8_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx);
+
+/**
+ * armv8_cpu_fill_madt() - Fill the MADT
+ * Parses the FDT and writes the MADT subtables.
+ *
+ * @dev: cpu device to generate ACPI tables for
+ * @ctx: ACPI context pointer
+ * @return: 0 if OK, or a negative error code.
+ */
+int armv8_cpu_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx);
+
+#endif \ No newline at end of file
diff --git a/drivers/cpu/bcm283x_cpu.c b/drivers/cpu/bcm283x_cpu.c
new file mode 100644
index 00000000000..59a7b142c95
--- /dev/null
+++ b/drivers/cpu/bcm283x_cpu.c
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 9elements GmbH
+ */
+
+#include <cpu.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <fdt_support.h>
+#include <acpi/acpigen.h>
+#include <asm/armv8/cpu.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/global_data.h>
+#include <asm/system.h>
+#include <asm-generic/sections.h>
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include "armv8_cpu.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct bcm_plat {
+ u64 release_addr;
+};
+
+static int cpu_bcm_get_desc(const struct udevice *dev, char *buf, int size)
+{
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+ const char *name;
+
+ if (size < 32)
+ return -ENOSPC;
+
+ if (device_is_compatible(dev, "arm,cortex-a53"))
+ name = "A53";
+ else if (device_is_compatible(dev, "arm,cortex-a72"))
+ name = "A72";
+ else
+ name = "?";
+
+ snprintf(buf, size, "Broadcom Cortex-%s at %u MHz\n",
+ name, plat->timebase_freq);
+
+ return 0;
+}
+
+static int cpu_bcm_get_info(const struct udevice *dev, struct cpu_info *info)
+{
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+
+ info->cpu_freq = plat->timebase_freq * 1000;
+ info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU);
+
+ return 0;
+}
+
+static int cpu_bcm_get_count(const struct udevice *dev)
+{
+ return uclass_id_count(UCLASS_CPU);
+}
+
+static int cpu_bcm_get_vendor(const struct udevice *dev, char *buf, int size)
+{
+ snprintf(buf, size, "Broadcom");
+
+ return 0;
+}
+
+static int cpu_bcm_is_current(struct udevice *dev)
+{
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+
+ if (plat->cpu_id == (read_mpidr() & 0xffff))
+ return 1;
+
+ return 0;
+}
+
+/**
+ * bcm_cpu_on - Releases the secondary CPU from it's spintable
+ *
+ * Write the CPU's spintable mailbox and let the CPU enter U-Boot.
+ *
+ * @dev: Device to start
+ * @return: zero on success or error code on failure.
+ */
+static int bcm_cpu_on(struct udevice *dev)
+{
+ struct bcm_plat *plat = dev_get_plat(dev);
+ ulong *start_address;
+
+ if (plat->release_addr == ~0ULL)
+ return -ENODATA;
+
+ start_address = map_physmem(plat->release_addr, sizeof(uintptr_t), MAP_NOCACHE);
+
+ /* Point secondary CPU to U-Boot entry */
+ *start_address = (uintptr_t)_start;
+
+ /* Make sure the other CPUs see the written start address */
+ if (!CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
+ flush_dcache_all();
+
+ /* Send an event to wake up the secondary CPU. */
+ asm("dsb ishst\n"
+ "sev");
+
+ unmap_physmem(start_address, MAP_NOCACHE);
+
+ return 0;
+}
+
+static const struct cpu_ops cpu_bcm_ops = {
+ .get_desc = cpu_bcm_get_desc,
+ .get_info = cpu_bcm_get_info,
+ .get_count = cpu_bcm_get_count,
+ .get_vendor = cpu_bcm_get_vendor,
+ .is_current = cpu_bcm_is_current,
+};
+
+static const struct udevice_id cpu_bcm_ids[] = {
+ { .compatible = "arm,cortex-a53" }, /* RPi 3 */
+ { .compatible = "arm,cortex-a72" }, /* RPi 4 */
+ { }
+};
+
+static int bcm_cpu_bind(struct udevice *dev)
+{
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+
+ plat->cpu_id = dev_read_addr(dev);
+
+ return 0;
+}
+
+/**
+ * bcm_cpu_of_to_plat - Gather spin-table release address
+ *
+ * Read the spin-table release address to allow all seconary CPUs to enter
+ * U-Boot when necessary.
+ *
+ * @dev: Device to start
+ */
+static int bcm_cpu_of_to_plat(struct udevice *dev)
+{
+ struct bcm_plat *plat = dev_get_plat(dev);
+ const char *prop;
+
+ if (CONFIG_IS_ENABLED(ARMV8_MULTIENTRY)) {
+ plat->release_addr = ~0ULL;
+
+ prop = dev_read_string(dev, "enable-method");
+ if (!prop || strcmp(prop, "spin-table"))
+ return -ENODEV;
+
+ plat->release_addr = dev_read_u64_default(dev, "cpu-release-addr", ~0ULL);
+
+ if (plat->release_addr == ~0ULL)
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int bcm_cpu_probe(struct udevice *dev)
+{
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+ struct clk clk;
+ int ret;
+
+ /* Get a clock if it exists */
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (!ret) {
+ ret = clk_enable(&clk);
+ if (ret && (ret != -ENOSYS || ret != -EOPNOTSUPP))
+ return ret;
+ ret = clk_get_rate(&clk);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+ plat->timebase_freq = ret;
+ }
+
+ /*
+ * The armstub holds the secondary CPUs in a spinloop. When
+ * ARMV8_MULTIENTRY is enabled release the secondary CPUs and
+ * let them enter U-Boot as well.
+ */
+ if (CONFIG_IS_ENABLED(ARMV8_MULTIENTRY)) {
+ ret = bcm_cpu_on(dev);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+struct acpi_ops bcm283x_cpu_acpi_ops = {
+ .fill_ssdt = armv8_cpu_fill_ssdt,
+ .fill_madt = armv8_cpu_fill_madt,
+};
+
+U_BOOT_DRIVER(cpu_bcm_drv) = {
+ .name = "bcm283x_cpu",
+ .id = UCLASS_CPU,
+ .of_match = cpu_bcm_ids,
+ .ops = &cpu_bcm_ops,
+ .probe = bcm_cpu_probe,
+ .bind = bcm_cpu_bind,
+ .of_to_plat = bcm_cpu_of_to_plat,
+ .plat_auto = sizeof(struct bcm_plat),
+ ACPI_OPS_PTR(&bcm283x_cpu_acpi_ops)
+};
diff --git a/drivers/misc/irq-uclass.c b/drivers/misc/irq-uclass.c
index 79eb7c200dc..ac778593c96 100644
--- a/drivers/misc/irq-uclass.c
+++ b/drivers/misc/irq-uclass.c
@@ -62,6 +62,40 @@ int irq_read_and_clear(struct irq *irq)
return ops->read_and_clear(irq);
}
+int irq_get_interrupt_parent(const struct udevice *dev,
+ struct udevice **interrupt_parent)
+{
+ struct ofnode_phandle_args phandle_args;
+ struct udevice *irq = NULL;
+ ofnode node;
+ int ret;
+
+ if (!dev || !interrupt_parent)
+ return -EINVAL;
+
+ *interrupt_parent = NULL;
+
+ node = dev_ofnode(dev);
+ if (!ofnode_valid(node))
+ return -EINVAL;
+
+ while (ofnode_valid(node)) {
+ ret = ofnode_parse_phandle_with_args(node, "interrupt-parent",
+ NULL, 0, 0, &phandle_args);
+ if (!ret && !device_get_global_by_ofnode(phandle_args.node, &irq))
+ break;
+ node = ofnode_get_parent(node);
+ }
+
+ if (!irq) {
+ log_err("Cannot find an interrupt parent for device %s\n", dev->name);
+ return -ENODEV;
+ }
+ *interrupt_parent = irq;
+
+ return 0;
+}
+
#if CONFIG_IS_ENABLED(OF_PLATDATA)
int irq_get_by_phandle(struct udevice *dev, const struct phandle_2_arg *cells,
struct irq *irq)
@@ -142,10 +176,40 @@ err:
int irq_get_by_index(struct udevice *dev, int index, struct irq *irq)
{
struct ofnode_phandle_args args;
- int ret;
+ struct udevice *interrupt_parent;
+ int ret, size, i;
+ const __be32 *list;
+ u32 count;
ret = dev_read_phandle_with_args(dev, "interrupts-extended",
"#interrupt-cells", 0, index, &args);
+ if (ret) {
+ list = dev_read_prop(dev, "interrupts", &size);
+ if (!list)
+ return -ENOENT;
+
+ ret = irq_get_interrupt_parent(dev, &interrupt_parent);
+ if (ret)
+ return -ENODEV;
+ args.node = dev_ofnode(interrupt_parent);
+
+ if (dev_read_u32(interrupt_parent, "#interrupt-cells", &count)) {
+ log_err("%s: could not get #interrupt-cells for %s\n",
+ __func__, dev->name);
+ return -ENOENT;
+ }
+
+ if (index * count >= size / sizeof(*list))
+ return -ENOENT;
+ if (count > OF_MAX_PHANDLE_ARGS)
+ count = OF_MAX_PHANDLE_ARGS;
+ args.args_count = count;
+ for (i = 0; i < count; i++)
+ args.args[i] = be32_to_cpup(&list[index * count + i]);
+
+ return irq_get_by_index_tail(ret, dev_ofnode(dev), &args,
+ "interrupts", index, irq);
+ }
return irq_get_by_index_tail(ret, dev_ofnode(dev), &args,
"interrupts-extended", index > 0, irq);
diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
index f978c64365c..f089c48f028 100644
--- a/drivers/pci/pcie_brcmstb.c
+++ b/drivers/pci/pcie_brcmstb.c
@@ -12,6 +12,7 @@
* Copyright (C) 2020 Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
*/
+#include <asm/arch/acpi/bcm2711.h>
#include <errno.h>
#include <dm.h>
#include <dm/ofnode.h>
@@ -21,88 +22,6 @@
#include <linux/log2.h>
#include <linux/iopoll.h>
-/* Offset of the mandatory PCIe capability config registers */
-#define BRCM_PCIE_CAP_REGS 0x00ac
-
-/* The PCIe controller register offsets */
-#define PCIE_RC_CFG_VENDOR_SPECIFIC_REG1 0x0188
-#define VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK 0xc
-#define VENDOR_SPECIFIC_REG1_LITTLE_ENDIAN 0x0
-
-#define PCIE_RC_CFG_PRIV1_ID_VAL3 0x043c
-#define CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff
-
-#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc
-#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK 0xc00
-
-#define PCIE_RC_DL_MDIO_ADDR 0x1100
-#define PCIE_RC_DL_MDIO_WR_DATA 0x1104
-#define PCIE_RC_DL_MDIO_RD_DATA 0x1108
-
-#define PCIE_MISC_MISC_CTRL 0x4008
-#define MISC_CTRL_SCB_ACCESS_EN_MASK 0x1000
-#define MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000
-#define MISC_CTRL_MAX_BURST_SIZE_MASK 0x300000
-#define MISC_CTRL_MAX_BURST_SIZE_128 0x0
-#define MISC_CTRL_SCB0_SIZE_MASK 0xf8000000
-
-#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO 0x400c
-#define PCIE_MEM_WIN0_LO(win) \
- PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + ((win) * 4)
-
-#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI 0x4010
-#define PCIE_MEM_WIN0_HI(win) \
- PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + ((win) * 4)
-
-#define PCIE_MISC_RC_BAR1_CONFIG_LO 0x402c
-#define RC_BAR1_CONFIG_LO_SIZE_MASK 0x1f
-
-#define PCIE_MISC_RC_BAR2_CONFIG_LO 0x4034
-#define RC_BAR2_CONFIG_LO_SIZE_MASK 0x1f
-#define PCIE_MISC_RC_BAR2_CONFIG_HI 0x4038
-
-#define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
-#define RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f
-
-#define PCIE_MISC_PCIE_STATUS 0x4068
-#define STATUS_PCIE_PORT_MASK 0x80
-#define STATUS_PCIE_PORT_SHIFT 7
-#define STATUS_PCIE_DL_ACTIVE_MASK 0x20
-#define STATUS_PCIE_DL_ACTIVE_SHIFT 5
-#define STATUS_PCIE_PHYLINKUP_MASK 0x10
-#define STATUS_PCIE_PHYLINKUP_SHIFT 4
-
-#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT 0x4070
-#define MEM_WIN0_BASE_LIMIT_LIMIT_MASK 0xfff00000
-#define MEM_WIN0_BASE_LIMIT_BASE_MASK 0xfff0
-#define MEM_WIN0_BASE_LIMIT_BASE_HI_SHIFT 12
-#define PCIE_MEM_WIN0_BASE_LIMIT(win) \
- PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT + ((win) * 4)
-
-#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI 0x4080
-#define MEM_WIN0_BASE_HI_BASE_MASK 0xff
-#define PCIE_MEM_WIN0_BASE_HI(win) \
- PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI + ((win) * 8)
-
-#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI 0x4084
-#define PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK 0xff
-#define PCIE_MEM_WIN0_LIMIT_HI(win) \
- PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI + ((win) * 8)
-
-#define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204
-#define PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
-
-#define PCIE_MSI_INTR2_CLR 0x4508
-#define PCIE_MSI_INTR2_MASK_SET 0x4510
-
-#define PCIE_EXT_CFG_DATA 0x8000
-
-#define PCIE_EXT_CFG_INDEX 0x9000
-
-#define PCIE_RGR1_SW_INIT_1 0x9210
-#define RGR1_SW_INIT_1_PERST_MASK 0x1
-#define RGR1_SW_INIT_1_INIT_MASK 0x2
-
/* PCIe parameters */
#define BRCM_NUM_PCIE_OUT_WINS 4
@@ -447,7 +366,7 @@ static int brcm_pcie_probe(struct udevice *dev)
* This will need to be changed when support for other SoCs is added.
*/
setbits_le32(base + PCIE_RGR1_SW_INIT_1,
- RGR1_SW_INIT_1_INIT_MASK | RGR1_SW_INIT_1_PERST_MASK);
+ PCIE_RGR1_SW_INIT_1_INIT_MASK | PCIE_RGR1_SW_INIT_1_PERST_MASK);
/*
* The delay is a safety precaution to preclude the reset signal
* from looking like a glitch.
@@ -455,7 +374,7 @@ static int brcm_pcie_probe(struct udevice *dev)
udelay(100);
/* Take the bridge out of reset */
- clrbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_INIT_MASK);
+ clrbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_INIT_MASK);
clrbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG,
PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
@@ -508,7 +427,7 @@ static int brcm_pcie_probe(struct udevice *dev)
/* Unassert the fundamental reset */
clrbits_le32(pcie->base + PCIE_RGR1_SW_INIT_1,
- RGR1_SW_INIT_1_PERST_MASK);
+ PCIE_RGR1_SW_INIT_1_PERST_MASK);
/*
* Wait for 100ms after PERST# deassertion; see PCIe CEM specification
@@ -552,7 +471,7 @@ static int brcm_pcie_probe(struct udevice *dev)
* a PCIe-PCIe bridge (the default setting is to be EP mode).
*/
clrsetbits_le32(base + PCIE_RC_CFG_PRIV1_ID_VAL3,
- CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK, 0x060400);
+ PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK, 0x060400);
if (pcie->ssc) {
ret = brcm_pcie_set_ssc(pcie->base);
@@ -570,8 +489,8 @@ static int brcm_pcie_probe(struct udevice *dev)
nlw, ssc_good ? "(SSC)" : "(!SSC)");
/* PCIe->SCB endian mode for BAR */
- clrsetbits_le32(base + PCIE_RC_CFG_VENDOR_SPECIFIC_REG1,
- VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK,
+ clrsetbits_le32(base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1,
+ PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK,
VENDOR_SPECIFIC_REG1_LITTLE_ENDIAN);
/*
@@ -584,7 +503,7 @@ static int brcm_pcie_probe(struct udevice *dev)
* let's instead just unadvertise ASPM support.
*/
clrbits_le32(base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY,
- PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK);
+ LINK_CAPABILITY_ASPM_SUPPORT_MASK);
return 0;
}
@@ -595,14 +514,14 @@ static int brcm_pcie_remove(struct udevice *dev)
void __iomem *base = pcie->base;
/* Assert fundamental reset */
- setbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_PERST_MASK);
+ setbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_PERST_MASK);
/* Turn off SerDes */
setbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG,
PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
/* Shutdown bridge */
- setbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_INIT_MASK);
+ setbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_INIT_MASK);
return 0;
}
diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index 80c35963b8f..e6bf0c2935b 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -19,6 +19,7 @@
#include <watchdog.h>
#include <asm/io.h>
#include <serial.h>
+#include <spl.h>
#include <dm/device_compat.h>
#include <dm/platform_data/serial_pl01x.h>
#include <linux/compiler.h>
@@ -272,6 +273,28 @@ __weak struct serial_device *default_serial_console(void)
return &pl01x_serial_drv;
}
#else
+
+static int pl01x_serial_getinfo(struct udevice *dev,
+ struct serial_device_info *info)
+{
+ struct pl01x_serial_plat *plat = dev_get_plat(dev);
+
+ /* save code size */
+ if (!not_xpl())
+ return -ENOSYS;
+
+ info->type = SERIAL_CHIP_PL01X;
+ info->addr_space = SERIAL_ADDRESS_SPACE_MEMORY;
+ info->addr = plat->base;
+ info->size = 0x1000;
+ info->reg_width = 4;
+ info->reg_shift = 2;
+ info->reg_offset = 0;
+ info->clock = plat->clock;
+
+ return 0;
+}
+
int pl01x_serial_setbrg(struct udevice *dev, int baudrate)
{
struct pl01x_serial_plat *plat = dev_get_plat(dev);
@@ -341,6 +364,7 @@ static const struct dm_serial_ops pl01x_serial_ops = {
.pending = pl01x_serial_pending,
.getc = pl01x_serial_getc,
.setbrg = pl01x_serial_setbrg,
+ .getinfo = pl01x_serial_getinfo,
};
#if CONFIG_IS_ENABLED(OF_REAL)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 6e10b629a3c..bb5893d56db 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -68,6 +68,14 @@ config USB_XHCI_MVEBU
SoCs, which includes Armada8K, Armada3700 and other Armada
family SoCs.
+config USB_XHCI_GENERIC
+ bool "Generic SoC USB 3.0 support"
+ depends on OF_CONTROL
+ default n
+ help
+ Choose this option to add support for USB 3.0 driver for SoCs
+ that do not need platform specific code, like on emulated targets.
+
config USB_XHCI_OCTEON
bool "Support for Marvell Octeon family on-chip xHCI USB controller"
depends on ARCH_OCTEON
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 792956e647a..301bb9fdee1 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o
obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o
obj-$(CONFIG_USB_XHCI_MTK) += xhci-mtk.o
obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o
+obj-$(CONFIG_USB_XHCI_GENERIC) += xhci-generic.o
obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
obj-$(CONFIG_USB_XHCI_RCAR) += xhci-rcar.o
diff --git a/drivers/usb/host/xhci-generic.c b/drivers/usb/host/xhci-generic.c
new file mode 100644
index 00000000000..355d4883176
--- /dev/null
+++ b/drivers/usb/host/xhci-generic.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2024 9elements GmbH
+ *
+ * GENERIC USB HOST xHCI Controller
+ */
+#include <dm.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <usb.h>
+#include <asm/io.h>
+#include <dm/device_compat.h>
+#include <usb/xhci.h>
+
+struct generic_xhci_plat {
+ fdt_addr_t hcd_base;
+};
+
+/**
+ * Contains pointers to register base addresses
+ * for the usb controller.
+ */
+struct generic_xhci {
+ struct xhci_ctrl ctrl; /* Needs to come first in this struct! */
+ struct usb_plat usb_plat;
+ struct xhci_hccr *hcd;
+};
+
+static int xhci_usb_probe(struct udevice *dev)
+{
+ struct generic_xhci_plat *plat = dev_get_plat(dev);
+ struct generic_xhci *ctx = dev_get_priv(dev);
+ struct xhci_hcor *hcor;
+ int len;
+
+ ctx->hcd = (struct xhci_hccr *)phys_to_virt(plat->hcd_base);
+ len = HC_LENGTH(xhci_readl(&ctx->hcd->cr_capbase));
+ hcor = (struct xhci_hcor *)((uintptr_t)ctx->hcd + len);
+
+ return xhci_register(dev, ctx->hcd, hcor);
+}
+
+static int xhci_usb_of_to_plat(struct udevice *dev)
+{
+ struct generic_xhci_plat *plat = dev_get_plat(dev);
+
+ /*
+ * Get the base address for XHCI controller from the device node
+ */
+ plat->hcd_base = dev_read_addr(dev);
+ if (plat->hcd_base == FDT_ADDR_T_NONE) {
+ dev_dbg(dev, "Can't get the XHCI register base address\n");
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id xhci_usb_ids[] = {
+ { .compatible = "generic-xhci" },
+ { }
+};
+
+U_BOOT_DRIVER(usb_xhci) = {
+ .name = "xhci_generic",
+ .id = UCLASS_USB,
+ .of_match = xhci_usb_ids,
+ .of_to_plat = xhci_usb_of_to_plat,
+ .probe = xhci_usb_probe,
+ .remove = xhci_deregister,
+ .ops = &xhci_usb_ops,
+ .plat_auto = sizeof(struct generic_xhci_plat),
+ .priv_auto = sizeof(struct generic_xhci),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};