diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/Kconfig | 12 | ||||
-rw-r--r-- | drivers/ata/Makefile | 2 | ||||
-rw-r--r-- | drivers/ata/ahci_generic.c (renamed from drivers/ata/ahci_mvebu.c) | 17 | ||||
-rw-r--r-- | drivers/core/acpi.c | 16 | ||||
-rw-r--r-- | drivers/cpu/Kconfig | 7 | ||||
-rw-r--r-- | drivers/cpu/Makefile | 2 | ||||
-rw-r--r-- | drivers/cpu/armv8_cpu.c | 151 | ||||
-rw-r--r-- | drivers/cpu/armv8_cpu.h | 31 | ||||
-rw-r--r-- | drivers/cpu/bcm283x_cpu.c | 214 | ||||
-rw-r--r-- | drivers/misc/irq-uclass.c | 66 | ||||
-rw-r--r-- | drivers/pci/pcie_brcmstb.c | 101 | ||||
-rw-r--r-- | drivers/serial/serial_pl01x.c | 24 | ||||
-rw-r--r-- | drivers/usb/host/Kconfig | 8 | ||||
-rw-r--r-- | drivers/usb/host/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/host/xhci-generic.c | 75 |
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, +}; |