diff options
Diffstat (limited to 'arm64-socionext-96b-enablement.patch')
-rw-r--r-- | arm64-socionext-96b-enablement.patch | 420 |
1 files changed, 0 insertions, 420 deletions
diff --git a/arm64-socionext-96b-enablement.patch b/arm64-socionext-96b-enablement.patch index 0a7df3a19..d5d6cda86 100644 --- a/arm64-socionext-96b-enablement.patch +++ b/arm64-socionext-96b-enablement.patch @@ -1,423 +1,3 @@ -From 58be18a7bbf9dca67f4260ac172a44baa59d0ee9 Mon Sep 17 00:00:00 2001 -From: Ard Biesheuvel <ard.biesheuvel@linaro.org> -Date: Mon, 21 Aug 2017 10:47:48 +0100 -Subject: arm64: acpi/gtdt: validate CNTFRQ after having enabled the frame - -The ACPI GTDT code validates the CNTFRQ field of each MMIO timer -frame against the CNTFRQ system register of the current CPU, to -ensure that they are equal, which is mandated by the architecture. - -However, reading the CNTFRQ field of a frame is not possible until -the RFRQ bit in the frame's CNTACRn register is set, and doing so -before that willl produce the following error: - - arch_timer: [Firmware Bug]: CNTFRQ mismatch: frame @ 0x00000000e0be0000: (0x00000000), CPU: (0x0ee6b280) - arch_timer: Disabling MMIO timers due to CNTFRQ mismatch - arch_timer: Failed to initialize memory-mapped timer. - -The reason is that the CNTFRQ field is RES0 if access is not enabled. - -So move the validation of CNTFRQ into the loop that iterates over the -timers to find the best frame, but defer it until after we have selected -the best frame, which should also have enabled the RFRQ bit. - -Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> ---- - drivers/clocksource/arm_arch_timer.c | 38 ++++++++++++++++++++---------------- - 1 file changed, 21 insertions(+), 17 deletions(-) - -diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c -index fd4b7f6..14e2419 100644 ---- a/drivers/clocksource/arm_arch_timer.c -+++ b/drivers/clocksource/arm_arch_timer.c -@@ -1268,10 +1268,6 @@ arch_timer_mem_find_best_frame(struct arch_timer_mem *timer_mem) - - iounmap(cntctlbase); - -- if (!best_frame) -- pr_err("Unable to find a suitable frame in timer @ %pa\n", -- &timer_mem->cntctlbase); -- - return best_frame; - } - -@@ -1372,6 +1368,8 @@ static int __init arch_timer_mem_of_init(struct device_node *np) - - frame = arch_timer_mem_find_best_frame(timer_mem); - if (!frame) { -+ pr_err("Unable to find a suitable frame in timer @ %pa\n", -+ &timer_mem->cntctlbase); - ret = -EINVAL; - goto out; - } -@@ -1420,7 +1418,7 @@ arch_timer_mem_verify_cntfrq(struct arch_timer_mem *timer_mem) - static int __init arch_timer_mem_acpi_init(int platform_timer_count) - { - struct arch_timer_mem *timers, *timer; -- struct arch_timer_mem_frame *frame; -+ struct arch_timer_mem_frame *frame, *best_frame = NULL; - int timer_count, i, ret = 0; - - timers = kcalloc(platform_timer_count, sizeof(*timers), -@@ -1432,14 +1430,6 @@ static int __init arch_timer_mem_acpi_init(int platform_timer_count) - if (ret || !timer_count) - goto out; - -- for (i = 0; i < timer_count; i++) { -- ret = arch_timer_mem_verify_cntfrq(&timers[i]); -- if (ret) { -- pr_err("Disabling MMIO timers due to CNTFRQ mismatch\n"); -- goto out; -- } -- } -- - /* - * While unlikely, it's theoretically possible that none of the frames - * in a timer expose the combination of feature we want. -@@ -1448,12 +1438,26 @@ static int __init arch_timer_mem_acpi_init(int platform_timer_count) - timer = &timers[i]; - - frame = arch_timer_mem_find_best_frame(timer); -- if (frame) -- break; -+ if (!best_frame) -+ best_frame = frame; -+ -+ ret = arch_timer_mem_verify_cntfrq(timer); -+ if (ret) { -+ pr_err("Disabling MMIO timers due to CNTFRQ mismatch\n"); -+ goto out; -+ } -+ -+ if (!best_frame) /* implies !frame */ -+ /* -+ * Only complain about missing suitable frames if we -+ * haven't already found one in a previous iteration. -+ */ -+ pr_err("Unable to find a suitable frame in timer @ %pa\n", -+ &timer->cntctlbase); - } - -- if (frame) -- ret = arch_timer_mem_frame_register(frame); -+ if (best_frame) -+ ret = arch_timer_mem_frame_register(best_frame); - out: - kfree(timers); - return ret; --- -cgit v1.1 - -From 33d983b5bb2929ae242606925e708092b1dfdd8f Mon Sep 17 00:00:00 2001 -From: Ard Biesheuvel <ard.biesheuvel@linaro.org> -Date: Sat, 2 Sep 2017 11:01:22 +0100 -Subject: drivers/irqchip: gicv3: add workaround for Synquacer pre-ITS - -In their infinite wisdom, the Socionext engineers have decided -that ITS device IDs should not be hardwired, but it should be -left up to the software to assign them, by allowing it to -redirect MSI doorbell writes via a separate hardware block -that issues the doorbell write with a device ID that is -derived from the memory address. This completely breaks any -kind of isolation, or virtualization in general, for that -matter, but add support for it nonetheless. - -Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> ---- - arch/arm64/Kconfig | 8 +++++++ - drivers/irqchip/irq-gic-v3-its.c | 48 +++++++++++++++++++++++++++++++++++----- - 2 files changed, 51 insertions(+), 5 deletions(-) - -diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig -index 0df64a6..c4361df 100644 ---- a/arch/arm64/Kconfig -+++ b/arch/arm64/Kconfig -@@ -539,6 +539,14 @@ config QCOM_QDF2400_ERRATUM_0065 - - If unsure, say Y. - -+config SOCIONEXT_SYNQUACER_PREITS -+ bool "Socionext Synquacer: Workaround for GICv3 pre-ITS" -+ default y -+ help -+ Socionext Synquacer SoCs implement a separate h/w block to generate -+ MSI doorbell writes with non-zero values for the device ID. -+ -+ If unsure, say Y. - endmenu - - -diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c -index e8d8934..0d372f1 100644 ---- a/drivers/irqchip/irq-gic-v3-its.c -+++ b/drivers/irqchip/irq-gic-v3-its.c -@@ -46,6 +46,7 @@ - #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0) - #define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1) - #define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2) -+#define ITS_FLAGS_WORKAROUND_SOCIONEXT_PREITS (1ULL << 3) - - #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0) - -@@ -99,6 +100,10 @@ struct its_node { - struct its_collection *collections; - struct list_head its_device_list; - u64 flags; -+#ifdef CONFIG_SOCIONEXT_SYNQUACER_PREITS -+ u64 pre_its_base; -+ u64 pre_its_size; -+#endif - u32 ite_size; - u32 device_ids; - int numa_node; -@@ -1102,13 +1107,29 @@ static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg) - u64 addr; - - its = its_dev->its; -- addr = its->phys_base + GITS_TRANSLATER; -+ -+#ifdef CONFIG_SOCIONEXT_SYNQUACER_PREITS -+ if (its->flags & ITS_FLAGS_WORKAROUND_SOCIONEXT_PREITS) -+ -+ /* -+ * The Socionext Synquacer SoC has a so-called 'pre-ITS', -+ * which maps 32-bit writes into a separate window of size -+ * '4 << device_id_bits' onto writes to GITS_TRANSLATER with -+ * device ID taken from bits [device_id_bits + 1:2] of the -+ * window offset. -+ */ -+ addr = its->pre_its_base + (its_dev->device_id << 2); -+ else -+#endif -+ addr = its->phys_base + GITS_TRANSLATER; - - msg->address_lo = lower_32_bits(addr); - msg->address_hi = upper_32_bits(addr); - msg->data = its_get_event_id(d); - -- iommu_dma_map_msi_msg(d->irq, msg); -+ if (!IS_ENABLED(CONFIG_SOCIONEXT_SYNQUACER_PREITS) || -+ !(its->flags & ITS_FLAGS_WORKAROUND_SOCIONEXT_PREITS)) -+ iommu_dma_map_msi_msg(d->irq, msg); - } - - static int its_irq_set_irqchip_state(struct irq_data *d, -@@ -1666,6 +1687,11 @@ static int its_alloc_tables(struct its_node *its) - ids = 0x14; /* 20 bits, 8MB */ - } - -+#ifdef CONFIG_SOCIONEXT_SYNQUACER_PREITS -+ if (its->flags & ITS_FLAGS_WORKAROUND_SOCIONEXT_PREITS) -+ ids = ilog2(its->pre_its_size) - 2; -+#endif -+ - its->device_ids = ids; - - for (i = 0; i < GITS_BASER_NR_REGS; i++) { -@@ -2788,11 +2814,21 @@ static const struct gic_quirk its_quirks[] = { - } - }; - --static void its_enable_quirks(struct its_node *its) -+static void its_enable_quirks(struct its_node *its, -+ struct fwnode_handle *handle) - { - u32 iidr = readl_relaxed(its->base + GITS_IIDR); - - gic_enable_quirks(iidr, its_quirks, its); -+ -+#ifdef CONFIG_SOCIONEXT_SYNQUACER_PREITS -+ if (!fwnode_property_read_u64_array(handle, -+ "socionext,synquacer-pre-its", -+ &its->pre_its_base, 2)) { -+ its->flags |= ITS_FLAGS_WORKAROUND_SOCIONEXT_PREITS; -+ pr_info("ITS: enabling workaround for Socionext Synquacer pre-ITS\n"); -+ } -+#endif - } - - static int its_init_domain(struct fwnode_handle *handle, struct its_node *its) -@@ -2812,7 +2848,9 @@ static int its_init_domain(struct fwnode_handle *handle, struct its_node *its) - - inner_domain->parent = its_parent; - irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS); -- inner_domain->flags |= IRQ_DOMAIN_FLAG_MSI_REMAP; -+ -+ if (!(its->flags & ITS_FLAGS_WORKAROUND_SOCIONEXT_PREITS)) -+ inner_domain->flags |= IRQ_DOMAIN_FLAG_MSI_REMAP; - info->ops = &its_msi_domain_ops; - info->data = its; - inner_domain->host_data = info; -@@ -2966,7 +3004,7 @@ static int __init its_probe_one(struct resource *res, - } - its->cmd_write = its->cmd_base; - -- its_enable_quirks(its); -+ its_enable_quirks(its, handle); - - err = its_alloc_tables(its); - if (err) --- -cgit v1.1 - -From 26e7bb47b0fb03a01be1e391a08c7375b45335a2 Mon Sep 17 00:00:00 2001 -From: Ard Biesheuvel <ard.biesheuvel@linaro.org> -Date: Mon, 21 Aug 2017 20:29:05 +0100 -Subject: pci: designware: add driver for DWC controller in ECAM shift mode - -Some implementations of the Synopsys Designware PCIe controller implement -a so-called ECAM shift mode, which allows a static memory window to be -configured that covers the configuration space of the entire bus range. - -If the firmware performs all the low level configuration that is required -to expose this controller in a fully ECAM compatible manner, we can -simply describe it as "pci-host-ecam-generic" and be done with it. -However, it appears that in some cases (one of which is the Armada 80x0), -the IP is synthesized with an ATU window size that does not allow the -first bus to be mapped in a way that prevents the device on the -downstream port from appearing more than once. - -So implement a driver that relies on the firmware to perform all low -level initialization, and drives the controller in ECAM mode, but -overrides the config space accessors to take the above quirk into -account. - -Note that, unlike most drivers for this IP, this driver does not expose -a fake bridge device at B/D/F 00:00.0. There is no point in doing so, -given that this is not a true bridge, and does not require any windows -to be configured in order for the downstream device to operate correctly. -Omitting it also prevents the PCI resource allocation routines from -handing out BAR space to it unnecessarily. - -Cc: Bjorn Helgaas <bhelgaas@google.com> -Cc: Jingoo Han <jingoohan1@gmail.com> -Cc: Joao Pinto <Joao.Pinto@synopsys.com> -Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> ---- - drivers/pci/dwc/Kconfig | 11 +++++ - drivers/pci/dwc/Makefile | 1 + - drivers/pci/dwc/pcie-designware-ecam.c | 77 ++++++++++++++++++++++++++++++++++ - 3 files changed, 89 insertions(+) - create mode 100644 drivers/pci/dwc/pcie-designware-ecam.c - -diff --git a/drivers/pci/dwc/Kconfig b/drivers/pci/dwc/Kconfig -index 22ec82f..19856b1 100644 ---- a/drivers/pci/dwc/Kconfig -+++ b/drivers/pci/dwc/Kconfig -@@ -169,4 +169,15 @@ config PCIE_KIRIN - Say Y here if you want PCIe controller support - on HiSilicon Kirin series SoCs. - -+config PCIE_DW_HOST_ECAM -+ bool "Synopsys DesignWare PCIe controller in ECAM mode" -+ depends on OF && PCI -+ select PCI_HOST_COMMON -+ select IRQ_DOMAIN -+ help -+ Add support for Synopsys DesignWare PCIe controllers configured -+ by the firmware into ECAM shift mode. In some cases, these are -+ fully ECAM compliant, in which case the pci-host-generic driver -+ may be used instead. -+ - endmenu -diff --git a/drivers/pci/dwc/Makefile b/drivers/pci/dwc/Makefile -index c61be97..7d5a23e 100644 ---- a/drivers/pci/dwc/Makefile -+++ b/drivers/pci/dwc/Makefile -@@ -1,5 +1,6 @@ - # SPDX-License-Identifier: GPL-2.0 - obj-$(CONFIG_PCIE_DW) += pcie-designware.o - obj-$(CONFIG_PCIE_DW_HOST) += pcie-designware-host.o -+obj-$(CONFIG_PCIE_DW_HOST_ECAM) += pcie-designware-ecam.o - obj-$(CONFIG_PCIE_DW_EP) += pcie-designware-ep.o - obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o - ifneq ($(filter y,$(CONFIG_PCI_DRA7XX_HOST) $(CONFIG_PCI_DRA7XX_EP)),) -diff --git a/drivers/pci/dwc/pcie-designware-ecam.c b/drivers/pci/dwc/pcie-designware-ecam.c -new file mode 100644 -index 0000000..ede627d ---- /dev/null -+++ b/drivers/pci/dwc/pcie-designware-ecam.c -@@ -0,0 +1,77 @@ -+/* -+ * Driver for mostly ECAM compatible Synopsys dw PCIe controllers -+ * configured by the firmware into RC mode -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * Copyright (C) 2014 ARM Limited -+ * Copyright (C) 2017 Linaro Limited -+ * -+ * Authors: Will Deacon <will.deacon@arm.com> -+ * Ard Biesheuvel <ard.biesheuvel@linaro.org> -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/of_address.h> -+#include <linux/of_pci.h> -+#include <linux/pci-ecam.h> -+#include <linux/platform_device.h> -+ -+static int pci_dw_ecam_config_read(struct pci_bus *bus, u32 devfn, int where, -+ int size, u32 *val) -+{ -+ struct pci_config_window *cfg = bus->sysdata; -+ -+ /* -+ * The Synopsys dw PCIe controller in RC mode will not filter type 0 -+ * config TLPs sent to devices 1 and up on its downstream port, -+ * resulting in devices appearing multiple times on bus 0 unless we -+ * filter them here. -+ */ -+ if (bus->number == cfg->busr.start && PCI_SLOT(devfn) > 0) { -+ *val = 0xffffffff; -+ return PCIBIOS_DEVICE_NOT_FOUND; -+ } -+ return pci_generic_config_read(bus, devfn, where, size, val); -+} -+ -+static int pci_dw_ecam_config_write(struct pci_bus *bus, u32 devfn, int where, -+ int size, u32 val) -+{ -+ struct pci_config_window *cfg = bus->sysdata; -+ -+ if (bus->number == cfg->busr.start && PCI_SLOT(devfn) > 0) -+ return PCIBIOS_DEVICE_NOT_FOUND; -+ -+ return pci_generic_config_write(bus, devfn, where, size, val); -+} -+ -+static struct pci_ecam_ops pci_dw_ecam_bus_ops = { -+ .pci_ops.map_bus = pci_ecam_map_bus, -+ .pci_ops.read = pci_dw_ecam_config_read, -+ .pci_ops.write = pci_dw_ecam_config_write, -+ .bus_shift = 20, -+}; -+ -+static const struct of_device_id pci_dw_ecam_of_match[] = { -+ { .compatible = "marvell,armada8k-pcie-ecam" }, -+ { .compatible = "socionext,synquacer-pcie-ecam" }, -+ { .compatible = "snps,dw-pcie-ecam" }, -+ { }, -+}; -+ -+static int pci_dw_ecam_probe(struct platform_device *pdev) -+{ -+ return pci_host_common_probe(pdev, &pci_dw_ecam_bus_ops); -+} -+ -+static struct platform_driver pci_dw_ecam_driver = { -+ .driver.name = "pcie-designware-ecam", -+ .driver.of_match_table = pci_dw_ecam_of_match, -+ .driver.suppress_bind_attrs = true, -+ .probe = pci_dw_ecam_probe, -+}; -+builtin_platform_driver(pci_dw_ecam_driver); --- -cgit v1.1 - From e3dff048a10f16aa0fd32438442ce39558bbdbef Mon Sep 17 00:00:00 2001 From: Jassi Brar <jaswinder.singh@linaro.org> Date: Tue, 29 Aug 2017 22:45:59 +0530 |