* [PATCH v4 3/8] arm: fix return value of parse_cpu_capacity
From: Juri Lelli @ 2017-04-20 14:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170420144316.15632-1-juri.lelli@arm.com>
parse_cpu_capacity() has to return 0 on failure, but it currently returns
1 instead if raw_capacity kcalloc failed.
Fix it (by directly returning 0).
Cc: Russell King <linux@arm.linux.org.uk>
Reported-by: Morten Rasmussen <morten.rasmussen@arm.com>
Fixes: 06073ee26775 ('ARM: 8621/3: parse cpu capacity-dmips-mhz from DT')
Signed-off-by: Juri Lelli <juri.lelli@arm.com>
Acked-by: Russell King <rmk+kernel@armlinux.org.uk>
---
Changes from v3:
- directly return 0 on failure (as pointed out by Vincent)
---
arch/arm/kernel/topology.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index f8a3ab82e77f..1b8ec3054642 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -166,7 +166,7 @@ static int __init parse_cpu_capacity(struct device_node *cpu_node, int cpu)
if (!raw_capacity) {
pr_err("cpu_capacity: failed to allocate memory for raw capacities\n");
cap_parsing_failed = true;
- return !ret;
+ return 0;
}
}
capacity_scale = max(cpu_capacity, capacity_scale);
--
2.10.0
^ permalink raw reply related
* [PATCH v4 2/8] Documentation/ABI: add information about cpu_capacity
From: Juri Lelli @ 2017-04-20 14:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170420144316.15632-1-juri.lelli@arm.com>
/sys/devices/system/cpu/cpu#/cpu_capacity describe information about
CPUs heterogeneity (ref. to Documentation/devicetree/bindings/arm/
cpu-capacity.txt).
Add such description.
Signed-off-by: Juri Lelli <juri.lelli@arm.com>
Acked-by: Russell King <rmk+kernel@armlinux.org.uk>
---
Documentation/ABI/testing/sysfs-devices-system-cpu | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 2a4a423d08e0..f3d5817c4ef0 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -366,3 +366,10 @@ Contact: Linux ARM Kernel Mailing list <linux-arm-kernel@lists.infradead.org>
Description: AArch64 CPU registers
'identification' directory exposes the CPU ID registers for
identifying model and revision of the CPU.
+
+What: /sys/devices/system/cpu/cpu#/cpu_capacity
+Date: December 2016
+Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
+Description: information about CPUs heterogeneity.
+
+ cpu_capacity: capacity of cpu#.
--
2.10.0
^ permalink raw reply related
* [PATCH v4 1/8] Documentation: arm: fix wrong reference number in DT definition
From: Juri Lelli @ 2017-04-20 14:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170420144316.15632-1-juri.lelli@arm.com>
Reference to cpu capacity binding has a wrong number. Fix it.
Reported-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Juri Lelli <juri.lelli@arm.com>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Russell King <rmk+kernel@armlinux.org.uk>
---
Documentation/devicetree/bindings/arm/cpus.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
index 698ad1f097fa..83ec3fa0a05e 100644
--- a/Documentation/devicetree/bindings/arm/cpus.txt
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -248,7 +248,7 @@ nodes to be present and contain the properties described below.
Usage: Optional
Value type: <u32>
Definition:
- # u32 value representing CPU capacity [3] in
+ # u32 value representing CPU capacity [4] in
DMIPS/MHz, relative to highest capacity-dmips-mhz
in the system.
@@ -475,5 +475,5 @@ cpus {
[2] arm/msm/qcom,kpss-acc.txt
[3] ARM Linux kernel documentation - idle states bindings
Documentation/devicetree/bindings/arm/idle-states.txt
-[3] ARM Linux kernel documentation - cpu capacity bindings
+[4] ARM Linux kernel documentation - cpu capacity bindings
Documentation/devicetree/bindings/arm/cpu-capacity.txt
--
2.10.0
^ permalink raw reply related
* [PATCH v4 0/8] Fix issues and factorize arm/arm64 capacity information code
From: Juri Lelli @ 2017-04-20 14:43 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
arm and arm64 topology.c share a lot of code related to parsing of capacity
information. This is v4 of a solution [1] (based on Will's, Catalin's and
Mark's off-line suggestions) to move such common code in a single place:
drivers/base/arch_topology.c (by creating such file and conditionally compiling
it for arm and arm64 only).
First 4 patches are actually fixes for the current code.
Patch 5 is the actual refactoring.
Patch 6 removes one of the extern symbols by changing a bit the now common
code.
Patch 7 removes the remaining externs (as required by Russell during v1 review)
by creating a new header file include/linux/arch_topology.h and including that
from arm, arm64 and drivers.
Last patch addresses Dietmar's comments to v1 and adds a 'atd_' prefix to
interfaces exported by drivers code and used by arch (and potentially others in
the future).
Changes from v3:
- rebase on top of 4.11-rc7
- addressed Vincent's comment on patch 3/8
- removed v3 6/9 as discussed with Russell
- added Russell and Catalin's Acked-by
The set is based on top of linux/master (4.11-rc7 f61143c45077) and it is also
available from:
git://linux-arm.org/linux-jl.git upstream/default_caps_factorize-v4
Best,
- Juri
[1] v1 - https://marc.info/?l=linux-kernel&m=148483680119355&w=2
v2 - https://marc.info/?l=linux-kernel&m=148663344018205&w=2
v3 - http://marc.info/?l=linux-kernel&m=149062080701399&w=2
Juri Lelli (8):
Documentation: arm: fix wrong reference number in DT definition
Documentation/ABI: add information about cpu_capacity
arm: fix return value of parse_cpu_capacity
arm: remove wrong CONFIG_PROC_SYSCTL ifdef
arm, arm64: factorize common cpu capacity default code
arm,arm64,drivers: reduce scope of cap_parsing_failed
arm,arm64,drivers: move externs in a new header file
arm,arm64,drivers: add a prefix to drivers arch_topology interfaces
Documentation/ABI/testing/sysfs-devices-system-cpu | 7 +
Documentation/devicetree/bindings/arm/cpus.txt | 4 +-
arch/arm/Kconfig | 1 +
arch/arm/kernel/topology.c | 221 +------------------
arch/arm64/Kconfig | 1 +
arch/arm64/kernel/topology.c | 226 +------------------
drivers/base/Kconfig | 8 +
drivers/base/Makefile | 1 +
drivers/base/arch_topology.c | 243 +++++++++++++++++++++
include/linux/arch_topology.h | 17 ++
10 files changed, 290 insertions(+), 439 deletions(-)
create mode 100644 drivers/base/arch_topology.c
create mode 100644 include/linux/arch_topology.h
--
2.10.0
^ permalink raw reply
* [PATCH v4 05/11] drm/sun4i: abstract a engine type
From: Maxime Ripard @ 2017-04-20 14:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5F52665D-8A24-40D3-B84B-E8991B3BE457@aosc.io>
On Tue, Apr 18, 2017 at 07:05:12PM +0800, Icenowy Zheng wrote:
> >> @@ -56,7 +55,7 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc
> >*crtc,
> >>
> >> DRM_DEBUG_DRIVER("Committing plane changes\n");
> >>
> >> - sun4i_backend_commit(scrtc->backend);
> >> + scrtc->engine_ops->commit(scrtc->engine);
> >
> >You rely on the backend having setup things properly, which is pretty
> >fragile. Ideally, you should have a function to check that engine_ops
> >and commit is !NULL, and call it, and the consumers would use that
> >function...
>
> If it's really NULL how should the function return?
It depends on the return code. ENOSYS if it returns an int, and simply
does nothing if it's a void. I don't think any of the current
functions return an error code at the moment though, so I'd just keep
the current behaviour and just call the function if it's set.
You cannot fail in atomic_flush anyway.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170420/92199a8f/attachment.sig>
^ permalink raw reply
* [PATCH v4 02/11] clk: sunxi-ng: add support for DE2 CCU
From: Maxime Ripard @ 2017-04-20 14:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170420140252.vd6aeeweshx2tdou@rob-hp-laptop>
Hi Rob,
On Thu, Apr 20, 2017 at 09:02:53AM -0500, Rob Herring wrote:
> On Sun, Apr 16, 2017 at 08:08:40PM +0800, Icenowy Zheng wrote:
> > diff --git a/include/dt-bindings/clock/sun8i-de2.h b/include/dt-bindings/clock/sun8i-de2.h
> > new file mode 100644
> > index 000000000000..982c6d18c75b
> > --- /dev/null
> > +++ b/include/dt-bindings/clock/sun8i-de2.h
> > @@ -0,0 +1,54 @@
> > +/*
> > + * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.io>
> > + *
> > + * This file is dual-licensed: you can use it either under the terms
> > + * of the GPL or the X11 license, at your option. Note that this dual
> > + * licensing only applies to this file, and not this project as a
> > + * whole.
> > + *
> > + * a) This file is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License as
> > + * published by the Free Software Foundation; either version 2 of the
> > + * License, or (at your option) any later version.
> > + *
> > + * This file is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + *
> > + * Or, alternatively,
> > + *
> > + * b) Permission is hereby granted, free of charge, to any person
> > + * obtaining a copy of this software and associated documentation
> > + * files (the "Software"), to deal in the Software without
> > + * restriction, including without limitation the rights to use,
> > + * copy, modify, merge, publish, distribute, sublicense, and/or
> > + * sell copies of the Software, and to permit persons to whom the
> > + * Software is furnished to do so, subject to the following
> > + * conditions:
> > + *
> > + * The above copyright notice and this permission notice shall be
> > + * included in all copies or substantial portions of the Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> > + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> > + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> > + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> > + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> > + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> > + * OTHER DEALINGS IN THE SOFTWARE.
> > + */
>
> You can use SPDX tag here:
>
> SPDX-License-Identifier: (GPL-2.0+ OR MIT)
I don't think you ever addressed Russell's comment about what would
happen to the license if and when the SPDX doc is changed or goes
offline?
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170420/a8b92e0c/attachment-0001.sig>
^ permalink raw reply
* [PATCH V11 00/11] IOMMU probe deferral support
From: Joerg Roedel @ 2017-04-20 14:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1491823266-1209-1-git-send-email-sricharan@codeaurora.org>
On Mon, Apr 10, 2017 at 04:50:55PM +0530, Sricharan R wrote:
> arch/arm64/mm/dma-mapping.c | 142 +++++---------------------------------
> drivers/acpi/arm64/iort.c | 48 ++++++++++++-
> drivers/acpi/glue.c | 5 --
> drivers/acpi/scan.c | 11 ++-
> drivers/base/dd.c | 9 +++
> drivers/base/dma-mapping.c | 41 +++++++++++
> drivers/iommu/arm-smmu-v3.c | 46 +-----------
> drivers/iommu/arm-smmu.c | 110 +++++++++++++----------------
> drivers/iommu/of_iommu.c | 126 ++++++++++++++++++++++++---------
> drivers/of/device.c | 23 +++++-
> drivers/of/platform.c | 10 +--
> drivers/pci/probe.c | 28 --------
> include/acpi/acpi_bus.h | 2 +-
> include/asm-generic/vmlinux.lds.h | 1 -
> include/linux/acpi.h | 7 +-
> include/linux/acpi_iort.h | 3 -
> include/linux/dma-mapping.h | 12 ++++
> include/linux/of_device.h | 10 ++-
> 18 files changed, 312 insertions(+), 322 deletions(-)
Applied, thanks.
^ permalink raw reply
* [PATCH v4 2/2] PCI: Add tango PCIe host bridge support
From: Marc Gonzalez @ 2017-04-20 14:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <d054300a-5891-0a25-8726-2be6b1beff6c@sigmadesigns.com>
This driver is required to work around several hardware bugs in the
PCIe controller.
NB: Revision 1 does not support legacy interrupts, or IO space.
Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
---
Documentation/devicetree/bindings/pci/tango-pcie.txt | 32 ++++++++
drivers/pci/host/Kconfig | 8 ++
drivers/pci/host/Makefile | 1 +
drivers/pci/host/pcie-tango.c | 161 +++++++++++++++++++++++++++++++++++++++
include/linux/pci_ids.h | 2 +
5 files changed, 204 insertions(+)
diff --git a/Documentation/devicetree/bindings/pci/tango-pcie.txt b/Documentation/devicetree/bindings/pci/tango-pcie.txt
new file mode 100644
index 000000000000..3353b4e77309
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/tango-pcie.txt
@@ -0,0 +1,32 @@
+Sigma Designs Tango PCIe controller
+
+Required properties:
+
+- compatible: "sigma,smp8759-pcie"
+- reg: address/size of PCI configuration space, address/size of register area
+- device_type: "pci"
+- #size-cells: <2>
+- #address-cells: <3>
+- #interrupt-cells: <1>
+- ranges: translation from system to bus addresses
+- interrupts: spec for misc interrupts, spec for MSI
+- msi-controller
+
+http://elinux.org/Device_Tree_Usage#PCI_Address_Translation
+http://elinux.org/Device_Tree_Usage#Advanced_Interrupt_Mapping
+
+Example:
+
+ pcie at 2e000 {
+ compatible = "sigma,smp8759-pcie";
+ reg = <0x50000000 SZ_4M>, <0x2e000 0x100>;
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ #interrupt-cells = <1>;
+ ranges = <0x02000000 0x0 0x00400000 0x50400000 0x0 SZ_60M>;
+ msi-controller;
+ interrupts =
+ <54 IRQ_TYPE_LEVEL_HIGH>, /* misc interrupts */
+ <55 IRQ_TYPE_LEVEL_HIGH>; /* MSI */
+ };
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index d7e7c0a827c3..5183d9095c3a 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -285,6 +285,14 @@ config PCIE_ROCKCHIP
There is 1 internal PCIe port available to support GEN2 with
4 slots.
+config PCIE_TANGO
+ bool "Tango PCIe controller"
+ depends on ARCH_TANGO && PCI_MSI && OF
+ select PCI_HOST_COMMON
+ help
+ Say Y here to enable PCIe controller support for Sigma Designs
+ Tango systems, such as SMP8759 and later chips.
+
config VMD
depends on PCI_MSI && X86_64
tristate "Intel Volume Management Device Driver"
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 084cb4983645..fc7ea90196f3 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -32,4 +32,5 @@ obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o
obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o
obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
+obj-$(CONFIG_PCIE_TANGO) += pcie-tango.o
obj-$(CONFIG_VMD) += vmd.o
diff --git a/drivers/pci/host/pcie-tango.c b/drivers/pci/host/pcie-tango.c
index ada8d35066ab..7eb74e82d325 100644
--- a/drivers/pci/host/pcie-tango.c
+++ b/drivers/pci/host/pcie-tango.c
@@ -230,3 +230,164 @@ static int tango_msi_probe(struct platform_device *pdev, struct tango_pcie *pcie
return 0;
}
+
+/*** HOST BRIDGE SUPPORT ***/
+
+static int smp8759_config_read(struct pci_bus *bus,
+ unsigned int devfn, int where, int size, u32 *val)
+{
+ int ret;
+ struct pci_config_window *cfg = bus->sysdata;
+ struct tango_pcie *pcie = dev_get_drvdata(cfg->parent);
+
+ /*
+ * QUIRK #1
+ * Reads in configuration space outside devfn 0 return garbage.
+ */
+ if (devfn != 0)
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+ /*
+ * QUIRK #2
+ * Unfortunately, config and mem spaces are muxed.
+ * Linux does not support such a setting, since drivers are free
+ * to access mem space directly, at any time.
+ * Therefore, we can only PRAY that config and mem space accesses
+ * NEVER occur concurrently.
+ */
+ writel_relaxed(1, pcie->mux);
+ ret = pci_generic_config_read(bus, devfn, where, size, val);
+ writel_relaxed(0, pcie->mux);
+
+ return ret;
+}
+
+static int smp8759_config_write(struct pci_bus *bus,
+ unsigned int devfn, int where, int size, u32 val)
+{
+ int ret;
+ struct pci_config_window *cfg = bus->sysdata;
+ struct tango_pcie *pcie = dev_get_drvdata(cfg->parent);
+
+ writel_relaxed(1, pcie->mux);
+ ret = pci_generic_config_write(bus, devfn, where, size, val);
+ writel_relaxed(0, pcie->mux);
+
+ return ret;
+}
+
+static struct pci_ecam_ops smp8759_ecam_ops = {
+ .bus_shift = 20,
+ .pci_ops = {
+ .map_bus = pci_ecam_map_bus,
+ .read = smp8759_config_read,
+ .write = smp8759_config_write,
+ }
+};
+
+static const struct of_device_id tango_pcie_ids[] = {
+ { .compatible = "sigma,smp8759-pcie" },
+ { /* sentinel */ },
+};
+
+static int tango_check_pcie_link(void __iomem *test_out)
+{
+ int i;
+
+ writel_relaxed(16, test_out);
+ for (i = 0; i < 10; ++i) {
+ u32 ltssm_state = readl_relaxed(test_out) >> 8;
+ if ((ltssm_state & 0x1f) == 0xf) /* L0 */
+ return 0;
+ usleep_range(3000, 4000);
+ }
+
+ return -ENODEV;
+}
+
+static int smp8759_init(struct tango_pcie *pcie, void __iomem *base)
+{
+ pcie->mux = base + 0x48;
+ pcie->msi_status = base + 0x80;
+ pcie->msi_enable = base + 0xa0;
+ pcie->msi_doorbell = 0xa0000000 + 0x2e07c;
+
+ return tango_check_pcie_link(base + 0x74);
+}
+
+static int tango_pcie_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ void __iomem *base;
+ struct resource *res;
+ struct tango_pcie *pcie;
+ struct device *dev = &pdev->dev;
+
+ pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
+ if (!pcie)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, pcie);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ if (of_device_is_compatible(dev->of_node, "sigma,smp8759-pcie"))
+ ret = smp8759_init(pcie, base);
+
+ if (ret)
+ return ret;
+
+ ret = tango_msi_probe(pdev, pcie);
+ if (ret)
+ return ret;
+
+ return pci_host_common_probe(pdev, &smp8759_ecam_ops);
+}
+
+static int tango_pcie_remove(struct platform_device *pdev)
+{
+ return tango_msi_remove(pdev);
+}
+
+static struct platform_driver tango_pcie_driver = {
+ .probe = tango_pcie_probe,
+ .remove = tango_pcie_remove,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = tango_pcie_ids,
+ },
+};
+
+builtin_platform_driver(tango_pcie_driver);
+
+/*
+ * QUIRK #3
+ * The root complex advertizes the wrong device class.
+ * Header Type 1 is for PCI-to-PCI bridges.
+ */
+static void tango_fixup_class(struct pci_dev *dev)
+{
+ dev->class = PCI_CLASS_BRIDGE_PCI << 8;
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIGMA, 0x24, tango_fixup_class);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIGMA, 0x28, tango_fixup_class);
+
+/*
+ * QUIRK #4
+ * The root complex exposes a "fake" BAR, which is used to filter
+ * bus-to-system accesses. Only accesses within the range defined
+ * by this BAR are forwarded to the host, others are ignored.
+ *
+ * By default, the DMA framework expects an identity mapping,
+ * and DRAM0 is mapped@0x80000000.
+ */
+static void tango_fixup_bar(struct pci_dev *dev)
+{
+ dev->non_compliant_bars = true;
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0x80000000);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIGMA, 0x24, tango_fixup_bar);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIGMA, 0x28, tango_fixup_bar);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index f020ab4079d3..b577dbe46f8f 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1369,6 +1369,8 @@
#define PCI_DEVICE_ID_TTI_HPT374 0x0008
#define PCI_DEVICE_ID_TTI_HPT372N 0x0009 /* apparently a 372N variant? */
+#define PCI_VENDOR_ID_SIGMA 0x1105
+
#define PCI_VENDOR_ID_VIA 0x1106
#define PCI_DEVICE_ID_VIA_8763_0 0x0198
#define PCI_DEVICE_ID_VIA_8380_0 0x0204
--
2.11.0
^ permalink raw reply related
* [PATCH v4 1/2] PCI: Add tango MSI controller support
From: Marc Gonzalez @ 2017-04-20 14:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <d054300a-5891-0a25-8726-2be6b1beff6c@sigmadesigns.com>
The MSI controller in Tango supports 256 message-signaled interrupts,
and a single doorbell address.
Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
---
drivers/pci/host/pcie-tango.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 232 insertions(+)
diff --git a/drivers/pci/host/pcie-tango.c b/drivers/pci/host/pcie-tango.c
new file mode 100644
index 000000000000..ada8d35066ab
--- /dev/null
+++ b/drivers/pci/host/pcie-tango.c
@@ -0,0 +1,232 @@
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/pci-ecam.h>
+#include <linux/delay.h>
+#include <linux/msi.h>
+
+#define MSI_MAX 256
+
+struct tango_pcie {
+ DECLARE_BITMAP(bitmap, MSI_MAX);
+ spinlock_t lock;
+ void __iomem *mux;
+ void __iomem *msi_status;
+ void __iomem *msi_enable;
+ phys_addr_t msi_doorbell;
+ struct irq_domain *irq_dom;
+ struct irq_domain *msi_dom;
+ int irq;
+};
+
+/*** MSI CONTROLLER SUPPORT ***/
+
+static void dispatch(struct tango_pcie *pcie, unsigned long status, int base)
+{
+ unsigned int pos, virq;
+
+ for_each_set_bit(pos, &status, 32) {
+ virq = irq_find_mapping(pcie->irq_dom, base + pos);
+ generic_handle_irq(virq);
+ }
+}
+
+static void tango_msi_isr(struct irq_desc *desc)
+{
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct tango_pcie *pcie = irq_desc_get_handler_data(desc);
+ unsigned int status, base, pos = 0;
+
+ chained_irq_enter(chip, desc);
+
+ while ((pos = find_next_bit(pcie->bitmap, MSI_MAX, pos)) < MSI_MAX) {
+ base = round_down(pos, 32);
+ status = readl_relaxed(pcie->msi_status + base / 8);
+ dispatch(pcie, status, base);
+ pos = base + 32;
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void tango_ack(struct irq_data *data)
+{
+ u32 bit = BIT(data->hwirq);
+ struct tango_pcie *pcie = irq_data_get_irq_chip_data(data);
+
+ writel_relaxed(bit, pcie->msi_status);
+}
+
+static void update_msi_enable(struct irq_data *data, bool unmask)
+{
+ unsigned long flags;
+ u32 val, bit = BIT(data->hwirq % 32);
+ int byte_offset = (data->hwirq / 32) * 4;
+ struct tango_pcie *pcie = data->chip_data;
+
+ spin_lock_irqsave(&pcie->lock, flags);
+ val = readl_relaxed(pcie->msi_enable + byte_offset);
+ val = unmask ? val | bit : val & ~bit;
+ writel_relaxed(val, pcie->msi_enable + byte_offset);
+ spin_unlock_irqrestore(&pcie->lock, flags);
+}
+
+static void tango_mask(struct irq_data *data)
+{
+ update_msi_enable(data, false);
+}
+
+static void tango_unmask(struct irq_data *data)
+{
+ update_msi_enable(data, true);
+}
+
+static int tango_set_affinity(struct irq_data *data,
+ const struct cpumask *mask, bool force)
+{
+ return -EINVAL;
+}
+
+static void tango_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+ struct tango_pcie *pcie = irq_data_get_irq_chip_data(data);
+
+ msg->address_lo = lower_32_bits(pcie->msi_doorbell);
+ msg->address_hi = upper_32_bits(pcie->msi_doorbell);
+ msg->data = data->hwirq;
+}
+
+static struct irq_chip tango_chip = {
+ .irq_ack = tango_ack,
+ .irq_mask = tango_mask,
+ .irq_unmask = tango_unmask,
+ .irq_set_affinity = tango_set_affinity,
+ .irq_compose_msi_msg = tango_compose_msi_msg,
+};
+
+static void msi_ack(struct irq_data *data)
+{
+ irq_chip_ack_parent(data);
+}
+
+static void msi_mask(struct irq_data *data)
+{
+ pci_msi_mask_irq(data);
+ irq_chip_mask_parent(data);
+}
+
+static void msi_unmask(struct irq_data *data)
+{
+ pci_msi_unmask_irq(data);
+ irq_chip_unmask_parent(data);
+}
+
+static struct irq_chip msi_chip = {
+ .name = "MSI",
+ .irq_ack = msi_ack,
+ .irq_mask = msi_mask,
+ .irq_unmask = msi_unmask,
+};
+
+static struct msi_domain_info msi_dom_info = {
+ .flags = MSI_FLAG_PCI_MSIX
+ | MSI_FLAG_USE_DEF_DOM_OPS
+ | MSI_FLAG_USE_DEF_CHIP_OPS,
+ .chip = &msi_chip,
+};
+
+static int find_free_msi(struct irq_domain *dom, unsigned int virq)
+{
+ unsigned int pos;
+ struct tango_pcie *pcie = dom->host_data;
+
+ pos = find_first_zero_bit(pcie->bitmap, MSI_MAX);
+ if (pos >= MSI_MAX)
+ return -ENOSPC;
+ __set_bit(pos, pcie->bitmap);
+
+ irq_domain_set_info(dom, virq, pos, &tango_chip, pcie,
+ handle_edge_irq, NULL, NULL);
+
+ return 0;
+}
+
+static int tango_irq_domain_alloc(struct irq_domain *dom,
+ unsigned int virq, unsigned int nr_irqs, void *args)
+{
+ int err;
+ unsigned long flags;
+ struct tango_pcie *pcie = dom->host_data;
+
+ spin_lock_irqsave(&pcie->lock, flags);
+ err = find_free_msi(dom, virq);
+ spin_unlock_irqrestore(&pcie->lock, flags);
+
+ return err;
+}
+
+static void tango_irq_domain_free(struct irq_domain *dom,
+ unsigned int virq, unsigned int nr_irqs)
+{
+ unsigned long flags;
+ struct irq_data *data = irq_domain_get_irq_data(dom, virq);
+ struct tango_pcie *pcie = irq_data_get_irq_chip_data(data);
+
+ spin_lock_irqsave(&pcie->lock, flags);
+ __clear_bit(data->hwirq, pcie->bitmap);
+ spin_unlock_irqrestore(&pcie->lock, flags);
+}
+
+static const struct irq_domain_ops irq_dom_ops = {
+ .alloc = tango_irq_domain_alloc,
+ .free = tango_irq_domain_free,
+};
+
+static int tango_msi_remove(struct platform_device *pdev)
+{
+ struct tango_pcie *pcie = platform_get_drvdata(pdev);
+
+ irq_set_chained_handler_and_data(pcie->irq, NULL, NULL);
+ irq_domain_remove(pcie->msi_dom);
+ irq_domain_remove(pcie->irq_dom);
+
+ return 0;
+}
+
+static int tango_msi_probe(struct platform_device *pdev, struct tango_pcie *pcie)
+{
+ int i, virq;
+ struct irq_domain *msi_dom, *irq_dom;
+ struct fwnode_handle *fwnode = of_node_to_fwnode(pdev->dev.of_node);
+
+ spin_lock_init(&pcie->lock);
+ for (i = 0; i < MSI_MAX / 32; ++i)
+ writel_relaxed(0, pcie->msi_enable + i * 4);
+
+ irq_dom = irq_domain_create_linear(fwnode, MSI_MAX, &irq_dom_ops, pcie);
+ if (!irq_dom) {
+ pr_err("Failed to create IRQ domain\n");
+ return -ENOMEM;
+ }
+
+ msi_dom = pci_msi_create_irq_domain(fwnode, &msi_dom_info, irq_dom);
+ if (!msi_dom) {
+ pr_err("Failed to create MSI domain\n");
+ irq_domain_remove(irq_dom);
+ return -ENOMEM;
+ }
+
+ virq = platform_get_irq(pdev, 1);
+ if (virq <= 0) {
+ pr_err("Failed to map IRQ\n");
+ irq_domain_remove(msi_dom);
+ irq_domain_remove(irq_dom);
+ return -ENXIO;
+ }
+
+ pcie->irq_dom = irq_dom;
+ pcie->msi_dom = msi_dom;
+ pcie->irq = virq;
+ irq_set_chained_handler_and_data(virq, tango_msi_isr, pcie);
+
+ return 0;
+}
--
2.11.0
^ permalink raw reply related
* [PATCH v4 0/2] Tango PCIe controller support
From: Marc Gonzalez @ 2017-04-20 14:24 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
This patch was split in two, to ease review of two orthogonal
parts (MSI controller and host bridge). NB: the patch is
just split in two where host bridge support starts.
Changes from v3 to v4
In the MSI part:
- Support 256 MSIs instead of only 32
- Define tango_{ack,mask,unmask} callbacks for the HW irq_chip
- Use a spinlock instead of a mutex
- Rename msi_mask register to msi_enable
In the host bridge part:
- Move several quirk-handling snippets out of the config space read function
- Check whether the PCIe link is up at probe-time
Other files
- Let the framework compute the bus-range from the config space width
- Be slightly more verbose in the Kconfig help
What has *not* changed, waiting from feedback from Bjorn:
- Pray that config and mem space accesses NEVER occur concurrently.
- Using of_device_is_compatible() vs of_device_get_match_data()
Marc Gonzalez (2):
PCI: Add tango MSI controller support
PCI: Add tango PCIe host bridge support
Documentation/devicetree/bindings/pci/tango-pcie.txt | 32 ++++
drivers/pci/host/Kconfig | 8 +
drivers/pci/host/Makefile | 1 +
drivers/pci/host/pcie-tango.c | 393 +++++++++++++++++++++++++++++++++++++++
include/linux/pci_ids.h | 2 +
5 files changed, 436 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pci/tango-pcie.txt
create mode 100644 drivers/pci/host/pcie-tango.c
--
2.11.0
^ permalink raw reply
* [PATCH 1/3] Documentation: dt-bindings: iio: adc: add Meson8 and Meson8b support
From: Rob Herring @ 2017-04-20 14:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170417182820.26670-2-martin.blumenstingl@googlemail.com>
On Mon, Apr 17, 2017 at 08:28:18PM +0200, Martin Blumenstingl wrote:
> The Amlogic Meson SAR ADC driver can be used on Meson8 and Meson8b
> (probably on earlier SoC generations as well, but I don't have any
> hardware available for testing that).
> Add a separate compatible for Meson8 and Meson8b because it does not
> need any of the BL30 magic (unlike the GX SoCs).
>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
> ---
> Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt | 2 ++
> 1 file changed, 2 insertions(+)
I'd prefer "Documentation: " prefix is dropped as that's implied with
"dt-bindings". Otherwise,
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH V3 2/2] ARM64: dts: hi6220-hikey: Add clock binding for the pmic mfd
From: Rob Herring @ 2017-04-20 14:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492449567-31399-2-git-send-email-daniel.lezcano@linaro.org>
On Mon, Apr 17, 2017 at 07:19:26PM +0200, Daniel Lezcano wrote:
Commit msg?
> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> ---
> Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt | 6 ++++++
> arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts | 1 +
> 2 files changed, 7 insertions(+)
Otherwise,
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH 2/3] ARM: dts: sk-rzg1m: add SCIF0 pins
From: Geert Uytterhoeven @ 2017-04-20 14:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170414211509.818645915@cogentembedded.com>
Hi Sergei,
On Fri, Apr 14, 2017 at 11:09 PM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
> Add the (previously omitted) SCIF0 pin data to the SK-RZG1M board's
> device tree.
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
>
> ---
> arch/arm/boot/dts/r8a7743-sk-rzg1m.dts | 12 +++++++++++-
> 1 file changed, 11 insertions(+), 1 deletion(-)
>
> Index: renesas/arch/arm/boot/dts/r8a7743-sk-rzg1m.dts
> ===================================================================
> --- renesas.orig/arch/arm/boot/dts/r8a7743-sk-rzg1m.dts
> +++ renesas/arch/arm/boot/dts/r8a7743-sk-rzg1m.dts
> @@ -1,7 +1,7 @@
> /*
> * Device Tree Source for the SK-RZG1M board
> *
> - * Copyright (C) 2016 Cogent Embedded, Inc.
> + * Copyright (C) 2016-2017 Cogent Embedded, Inc.
> *
> * This file is licensed under the terms of the GNU General Public License
> * version 2. This program is licensed "as is" without any warranty of any
> @@ -39,7 +39,17 @@
> clock-frequency = <20000000>;
> };
>
> +&pfc {
> + scif0_pins: scif0 {
> + groups = "scif0_data";
I don't have schematics for this board, but you told me it's very similar to
Porter. Hence I'd expect "scif0_data_d" instead.
In my experience, when changing pinctrl to map the lines of a device to a new
set of pins, but not mapping another device to the old set of pins, it may
output the signals on both the old and the new set of pins.
Does serial console input work with "scif0_data"?
> + function = "scif0";
> + };
> +};
> +
> &scif0 {
> + pinctrl-0 = <&scif0_pins>;
> + pinctrl-names = "default";
> +
> status = "okay";
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH v3 03/12] dt-bindings: make AXP20X compatible strings one per line
From: Rob Herring @ 2017-04-20 14:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170417115747.7300-4-icenowy@aosc.io>
On Mon, Apr 17, 2017 at 07:57:38PM +0800, Icenowy Zheng wrote:
> In the binding documentation of AXP20X mfd, the compatible strings used
> to be listed for three per line, which leads to some mess when trying to
> add AXP803 compatible string (as we have already AXP806 and AXP809
> compatibles, which is after AXP803 in ascending order).
>
> Make the compatible strings one per line, so that inserting a new
> compatible string will be directly a new line.
>
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> ---
> New patch in v3.
>
> Documentation/devicetree/bindings/mfd/axp20x.txt | 11 ++++++++---
> 1 file changed, 8 insertions(+), 3 deletions(-)
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH 22/29] dt-bindings: Clarify compatible property for rockchip timers
From: Rob Herring @ 2017-04-20 14:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492374441-23336-22-git-send-email-daniel.lezcano@linaro.org>
On Sun, Apr 16, 2017 at 10:27:12PM +0200, Daniel Lezcano wrote:
> From: Alexander Kochetkov <al.kochet@gmail.com>
>
> Make all properties description in form '"rockchip,<chip>-timer",
> "rockchip,rk3288-timer"' for all chips found in linux kernel.
>
> Suggested-by: Heiko St?bner <heiko@sntech.de>
> Signed-off-by: Alexander Kochetkov <al.kochet@gmail.com>
> Acked-by: Rob Herring <robh@kernel.org>
> Reviewed-by: Heiko Stuebner <heiko@sntech.de>
> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> ---
> .../devicetree/bindings/timer/rockchip,rk-timer.txt | 12 +++++++++---
> 1 file changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt b/Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt
> index a41b184..16a5f45 100644
> --- a/Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt
> +++ b/Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt
> @@ -1,9 +1,15 @@
> Rockchip rk timer
>
> Required properties:
> -- compatible: shall be one of:
> - "rockchip,rk3288-timer" - for rk3066, rk3036, rk3188, rk322x, rk3288, rk3368
> - "rockchip,rk3399-timer" - for rk3399
> +- compatible: should be:
should be one of:
> + "rockchip,rk3036-timer", "rockchip,rk3288-timer": for Rockchip RK3036
> + "rockchip,rk3066-timer", "rockchip,rk3288-timer": for Rockchip RK3066
> + "rockchip,rk3188-timer", "rockchip,rk3288-timer": for Rockchip RK3188
> + "rockchip,rk3228-timer", "rockchip,rk3288-timer": for Rockchip RK3228
> + "rockchip,rk3229-timer", "rockchip,rk3288-timer": for Rockchip RK3229
> + "rockchip,rk3288-timer": for Rockchip RK3288
> + "rockchip,rk3368-timer", "rockchip,rk3288-timer": for Rockchip RK3368
> + "rockchip,rk3399-timer": for Rockchip RK3399
I find the "for Rockchip RKxxxx" a bit redundant, but it's fine with or
without. Otherwise,
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH 1/3] ARM: dts: r8a7745: add PFC support
From: Geert Uytterhoeven @ 2017-04-20 14:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170415202036.987901107@cogentembedded.com>
On Sat, Apr 15, 2017 at 10:18 PM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
> Define the generic R8A7745 part of the PFC device node.
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH 1/3] ARM: dts: r8a7743: add PFC support
From: Geert Uytterhoeven @ 2017-04-20 14:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170414211505.733692280@cogentembedded.com>
On Fri, Apr 14, 2017 at 11:09 PM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
> Define the generic R8A7743 part of the PFC device node.
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH v4 03/11] dt-bindings: add bindings for DE2 on V3s SoC
From: Rob Herring @ 2017-04-20 14:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170416120849.54542-4-icenowy@aosc.io>
On Sun, Apr 16, 2017 at 08:08:41PM +0800, Icenowy Zheng wrote:
> Allwinner V3s SoC have a display engine which have a different pipeline
> with older SoCs.
>
> Add document for it (new compatibles and the new "mixer" part).
>
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> ---
> Changes in v4:
> - Removed the refactor at TCON chapter.
>
> Changes in v3:
> - Remove the description of having a BE directly as allwinner,pipeline.
>
> .../bindings/display/sunxi/sun4i-drm.txt | 29 ++++++++++++++++++++--
> 1 file changed, 27 insertions(+), 2 deletions(-)
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH v4 02/11] clk: sunxi-ng: add support for DE2 CCU
From: Rob Herring @ 2017-04-20 14:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170416120849.54542-3-icenowy@aosc.io>
On Sun, Apr 16, 2017 at 08:08:40PM +0800, Icenowy Zheng wrote:
> The "Display Engine 2.0" in Allwinner newer SoCs contains a clock
> management unit for its subunits, like the DE CCU in A80.
>
> Add a sunxi-ng style driver for it.
>
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> ---
> Changes in v4:
> - Fixed the inconsistence between mixer_div clocks' number and real clock.
> Changes in v2:
> - Rename sunxi-de2-ccu to sun8i-de2-ccu.
>
> drivers/clk/sunxi-ng/Kconfig | 5 +
> drivers/clk/sunxi-ng/Makefile | 1 +
> drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 218 ++++++++++++++++++++++++++++++++++
> drivers/clk/sunxi-ng/ccu-sun8i-de2.h | 28 +++++
> include/dt-bindings/clock/sun8i-de2.h | 54 +++++++++
> include/dt-bindings/reset/sun8i-de2.h | 50 ++++++++
These 2 includes belong with the binding patch.
> 6 files changed, 356 insertions(+)
> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.c
> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.h
> create mode 100644 include/dt-bindings/clock/sun8i-de2.h
> create mode 100644 include/dt-bindings/reset/sun8i-de2.h
> diff --git a/include/dt-bindings/clock/sun8i-de2.h b/include/dt-bindings/clock/sun8i-de2.h
> new file mode 100644
> index 000000000000..982c6d18c75b
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun8i-de2.h
> @@ -0,0 +1,54 @@
> +/*
> + * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.io>
> + *
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL or the X11 license, at your option. Note that this dual
> + * licensing only applies to this file, and not this project as a
> + * whole.
> + *
> + * a) This file is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This file is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Or, alternatively,
> + *
> + * b) Permission is hereby granted, free of charge, to any person
> + * obtaining a copy of this software and associated documentation
> + * files (the "Software"), to deal in the Software without
> + * restriction, including without limitation the rights to use,
> + * copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following
> + * conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> + * included in all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
You can use SPDX tag here:
SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +
> +#ifndef _DT_BINDINGS_CLOCK_SUN8I_DE2_H_
> +#define _DT_BINDINGS_CLOCK_SUN8I_DE2_H_
> +
> +#define CLK_BUS_MIXER0 0
> +#define CLK_BUS_MIXER1 1
> +#define CLK_BUS_WB 2
> +
> +#define CLK_MIXER0 6
> +#define CLK_MIXER1 7
> +#define CLK_WB 8
> +
> +#endif /* _DT_BINDINGS_CLOCK_SUN8I_DE2_H_ */
> diff --git a/include/dt-bindings/reset/sun8i-de2.h b/include/dt-bindings/reset/sun8i-de2.h
> new file mode 100644
> index 000000000000..52af2dc55376
> --- /dev/null
> +++ b/include/dt-bindings/reset/sun8i-de2.h
> @@ -0,0 +1,50 @@
> +/*
> + * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.io>
> + *
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL or the X11 license, at your option. Note that this dual
> + * licensing only applies to this file, and not this project as a
> + * whole.
> + *
> + * a) This file is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This file is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Or, alternatively,
> + *
> + * b) Permission is hereby granted, free of charge, to any person
> + * obtaining a copy of this software and associated documentation
> + * files (the "Software"), to deal in the Software without
> + * restriction, including without limitation the rights to use,
> + * copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following
> + * conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> + * included in all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
And here.
Rob
^ permalink raw reply
* [PATCH v4 01/11] dt-bindings: add binding for the Allwinner DE2 CCU
From: Rob Herring @ 2017-04-20 13:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170416120849.54542-2-icenowy@aosc.io>
On Sun, Apr 16, 2017 at 08:08:39PM +0800, Icenowy Zheng wrote:
> Allwinner "Display Engine 2.0" contains some clock controls in it.
>
> In order to add them as clock drivers, we need a device tree binding.
> Add the binding here.
>
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> ---
> Changes in v4:
> - Dropped the leading 0 in clock at 1000000 .
> Changes in v3:
> - Fill the address space length of DE2 CCU to 0x100000, just reach the start of mixer0.
>
> .../devicetree/bindings/clock/sun8i-de2.txt | 31 ++++++++++++++++++++++
> 1 file changed, 31 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH 2/2] gpio: omap: compute debounce-time from actual debounce-clock rate
From: David Rivshin @ 2017-04-20 13:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5d0fab0d-bc9d-5148-063c-8bfe9e26f9a5@ti.com>
On Fri, 17 Mar 2017 19:06:47 -0500
Grygorii Strashko <grygorii.strashko@ti.com> wrote:
> CC: Tero
Gentle ping. Any thoughts on this? Is there anything I should
investigate, or other information you'd like me to provide?
> On 03/17/2017 06:14 PM, David Rivshin wrote:
> > On Fri, 17 Mar 2017 14:43:02 -0500
> > Grygorii Strashko <grygorii.strashko@ti.com> wrote:
> >
> >> On 03/16/2017 07:57 PM, David Rivshin wrote:
> >>> From: David Rivshin <DRivshin@allworx.com>
> >>>
> >>> omap2_set_gpio_debounce() assumes the debounce clock runs at 32768Hz,
> >>> leading to 31us granularity. In reality the debounce clock (which
> >>> is provided by other modules) could be at different rate, leading to
> >>> an incorrect computation of the number of debounce clock cycles for
> >>> GPIO_DEBOUNCINGTIME[DEBOUNCETIME].
> >>>
> >>> Also, even with a standard 32768Hz input clock, the actual granularity
> >>> is ~30.5us. This leads to the actual debounce time being ~1.5% too
> >>> short.
> >>>
> >>> Fix both issues by simply querying the dbck rate, rather than
> >>> hardcoding.
> >>
> >> Pls, hold on with this - I'm trying to check it, as it doesn't follow TRMs.
> >
> > Yes, the TRMs are somewhat cryptic about the details, perhaps I can give
> > some more background on how I came to this. I think the chapters for the
> > GPIO block are written with a strong assumption that the input debounce
> > clock is 32768Hz, and further round 1/32768Hz to the nearest whole
> > microsecond (~30.5us->31us).
> >
> > However, at least on AM335x the debounce clock (i.e. the CLK_32KHZ) can
> > be made to run at other rates via the Control Module.
> >
> > Here is an example from clk_summary:
> > clk_24mhz 1 1 24000000 0 0
> > clkdiv32k_ck 1 1 65536 0 0
> > clkdiv32k_ick 2 6 65536 0 0
> > timer7_fck 1 1 65536 0 0
> > wdt1_fck 0 1 65536 0 0
> > gpio3_dbclk 0 2 65536 0 0
> > gpio2_dbclk 0 2 65536 0 0
> > gpio1_dbclk 0 2 65536 0 0
> >
> > This is accomplished by setting clk32kdivratio_ctl[clkdivopp50_en] to 1
> > even while in OPP100, and adjusting the devicetree to match. Timer7 is
> > known to truly have a 65536Hz fck by configuring it as a 50% duty cycle
> > PWM and measuring with an oscilloscope.
> >
> > Here are some relevant sections from the AM335x TRM (spruh73o):
> > 25.2.2 GPIO Clock and Reset Management
> > Debounce Functional clock (GPIO[123]) comes from CLK_32KHZ.
> > 8.1.6.8 Peripheral PLL Description
> > CLK_32KHZ is CLK_24 divided by either 732.4219 or 366.2109.
> > In OPP100 this results in either 32768Hz or 65536Hz.
> > In OPP50 this results in either 16384Hz or 32768Hz.
> > 9.3.1.8 clk32kdivratio_ctrl Register
> > Names of the register and field differ from 8.1.6.8, but it's
> > clear they are the same.
> >
> > I'm not sure if other devices can be similarly cajoled into running
> > their equivalent 32KHZ clocks at a different rate, but it certainly
> > works for AM335x. Checking OMAP4430 TRM as an example makes it look
> > like OMAP44xx has a fixed 32768Hz clock with no adjustment possible
> > (backed up by omap44xx-clocks.dtsi having it just be a fixed-clock).
> >
> >
> >>>
> >>> Fixes: e85ec6c3047b ("gpio: omap: fix omap2_set_gpio_debounce")
> >>> Cc: <stable@vger.kernel.org> # 4.3+
> >>> Signed-off-by: David Rivshin <drivshin@allworx.com>
> >>> ---
> >>>
> >>> This logical bug existed before e85ec6c3047b, but if backporting
> >>> further it's probably best to just cherry-pick/backport e85ec6c3047b
> >>> first.
> >>>
> >>> drivers/gpio/gpio-omap.c | 8 +++++---
> >>> 1 file changed, 5 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
> >>> index 33ec02d..865a831 100644
> >>> --- a/drivers/gpio/gpio-omap.c
> >>> +++ b/drivers/gpio/gpio-omap.c
> >>> @@ -205,8 +205,8 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
> >>> * @offset: the gpio number on this @bank
> >>> * @debounce: debounce time to use
> >>> *
> >>> - * OMAP's debounce time is in 31us steps
> >>> - * <debounce time> = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) x 31
> >>> + * OMAP's debounce time is in 1/DBCK steps
> >>> + * <debounce time> = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) / DBCK
> >>> * so we need to convert and round up to the closest unit.
> >>> *
> >>> * Return: 0 on success, negative error otherwise.
> >>> @@ -223,7 +223,9 @@ static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
> >>> return -ENOTSUPP;
> >>>
> >>> if (enable) {
> >>> - debounce = DIV_ROUND_UP(debounce, 31) - 1;
> >>> + u64 tmp = (u64)debounce * clk_get_rate(bank->dbck);
> >>> +
> >>> + debounce = DIV_ROUND_UP_ULL(tmp, 1000000) - 1;
> >>> if ((debounce & OMAP4_GPIO_DEBOUNCINGTIME_MASK) != debounce)
> >>> return -EINVAL;
> >>> }
> >>>
> >>
> >
>
^ permalink raw reply
* [PATCH v2 3/3] mmc: sdio: mediatek: Support SDIO feature
From: Ulf Hansson @ 2017-04-20 13:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492510391-704-4-git-send-email-yong.mao@mediatek.com>
On 18 April 2017 at 12:13, Yong Mao <yong.mao@mediatek.com> wrote:
> From: yong mao <yong.mao@mediatek.com>
>
> 1. Add irqlock to protect accessing the shared register
> 2. Implement enable_sdio_irq interface
> 3. Add msdc_recheck_sdio_irq mechanism to make sure all interrupts
> can be processed immediately
I think this should be split up in more pieces. Perhaps three as the
changelog describes.
Moreover I would appreciate some more information about why/how.
>
> Signed-off-by: Yong Mao <yong.mao@mediatek.com>
> Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
> ---
> drivers/mmc/host/mtk-sd.c | 182 +++++++++++++++++++++++++++++++++++----------
> 1 file changed, 143 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> index 07f3236..fdae197 100644
> --- a/drivers/mmc/host/mtk-sd.c
> +++ b/drivers/mmc/host/mtk-sd.c
> @@ -118,6 +118,7 @@
> #define MSDC_PS_CDSTS (0x1 << 1) /* R */
> #define MSDC_PS_CDDEBOUNCE (0xf << 12) /* RW */
> #define MSDC_PS_DAT (0xff << 16) /* R */
> +#define MSDC_PS_DATA1 (0x1 << 17) /* R */
> #define MSDC_PS_CMD (0x1 << 24) /* R */
> #define MSDC_PS_WP (0x1 << 31) /* R */
>
> @@ -312,6 +313,7 @@ struct msdc_host {
> int cmd_rsp;
>
> spinlock_t lock;
> + spinlock_t irqlock; /* irq lock */
> struct mmc_request *mrq;
> struct mmc_command *cmd;
> struct mmc_data *data;
> @@ -330,12 +332,14 @@ struct msdc_host {
> struct pinctrl_state *pins_uhs;
> struct delayed_work req_timeout;
> int irq; /* host interrupt */
> + bool irq_thread_alive;
>
> struct clk *src_clk; /* msdc source clock */
> struct clk *h_clk; /* msdc h_clk */
> u32 mclk; /* mmc subsystem clock frequency */
> u32 src_clk_freq; /* source clock frequency */
> u32 sclk; /* SD/MS bus clock frequency */
> + bool clock_on;
> unsigned char timing;
> bool vqmmc_enabled;
> u32 hs400_ds_delay;
> @@ -343,6 +347,7 @@ struct msdc_host {
> u32 hs400_cmd_int_delay; /* cmd internal delay for HS400 */
> bool hs400_cmd_resp_sel_rising;
> /* cmd response sample selection for HS400 */
> + u32 clk_pad_delay;
Parsing and using of pad_delay seems like it also should be a separate change.
> bool hs400_mode; /* current eMMC will run at hs400 mode */
> struct msdc_save_para save_para; /* used when gate HCLK */
> struct msdc_tune_para def_tune_para; /* default tune setting */
> @@ -399,6 +404,7 @@ static void msdc_reset_hw(struct msdc_host *host)
>
> static void msdc_cmd_next(struct msdc_host *host,
> struct mmc_request *mrq, struct mmc_command *cmd);
> +static void msdc_recheck_sdio_irq(struct msdc_host *host);
>
> static const u32 cmd_ints_mask = MSDC_INTEN_CMDRDY | MSDC_INTEN_RSPCRCERR |
> MSDC_INTEN_CMDTMO | MSDC_INTEN_ACMDRDY |
> @@ -525,6 +531,7 @@ static void msdc_gate_clock(struct msdc_host *host)
> {
> clk_disable_unprepare(host->src_clk);
> clk_disable_unprepare(host->h_clk);
> + host->clock_on = false;
This looks weird. Why do you need to keep track of this?
> }
>
> static void msdc_ungate_clock(struct msdc_host *host)
> @@ -533,6 +540,7 @@ static void msdc_ungate_clock(struct msdc_host *host)
> clk_prepare_enable(host->src_clk);
> while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
> cpu_relax();
> + host->clock_on = true;
Ditto.
> }
>
> static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
> @@ -541,6 +549,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
> u32 flags;
> u32 div;
> u32 sclk;
> + unsigned long irq_flags;
>
> if (!hz) {
> dev_dbg(host->dev, "set mclk to 0\n");
> @@ -549,8 +558,11 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
> return;
> }
>
> + spin_lock_irqsave(&host->irqlock, irq_flags);
Why is the spin_lock needed now, and not before. Could you elaborate on that?
No matter what, seems like it should be separate change.
> flags = readl(host->base + MSDC_INTEN);
> sdr_clr_bits(host->base + MSDC_INTEN, flags);
> + spin_unlock_irqrestore(&host->irqlock, irq_flags);
> +
> sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_HS400_CK_MODE);
> if (timing == MMC_TIMING_UHS_DDR50 ||
> timing == MMC_TIMING_MMC_DDR52 ||
> @@ -600,7 +612,10 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
> host->timing = timing;
> /* need because clk changed. */
> msdc_set_timeout(host, host->timeout_ns, host->timeout_clks);
> +
> + spin_lock_irqsave(&host->irqlock, irq_flags);
> sdr_set_bits(host->base + MSDC_INTEN, flags);
> + spin_unlock_irqrestore(&host->irqlock, irq_flags);
>
> /*
> * mmc_select_hs400() will drop to 50Mhz and High speed mode,
> @@ -708,6 +723,7 @@ static inline u32 msdc_cmd_prepare_raw_cmd(struct msdc_host *host,
> static void msdc_start_data(struct msdc_host *host, struct mmc_request *mrq,
> struct mmc_command *cmd, struct mmc_data *data)
> {
> + unsigned long flags;
> bool read;
>
> WARN_ON(host->data);
> @@ -716,8 +732,12 @@ static void msdc_start_data(struct msdc_host *host, struct mmc_request *mrq,
>
> mod_delayed_work(system_wq, &host->req_timeout, DAT_TIMEOUT);
> msdc_dma_setup(host, &host->dma, data);
> +
> + spin_lock_irqsave(&host->irqlock, flags);
> sdr_set_bits(host->base + MSDC_INTEN, data_ints_mask);
> sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_START, 1);
> + spin_unlock_irqrestore(&host->irqlock, flags);
> +
> dev_dbg(host->dev, "DMA start\n");
> dev_dbg(host->dev, "%s: cmd=%d DMA data: %d blocks; read=%d\n",
> __func__, cmd->opcode, data->blocks, read);
> @@ -774,6 +794,8 @@ static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
> if (mrq->data)
> msdc_unprepare_data(host, mrq);
> mmc_request_done(host->mmc, mrq);
> +
> + msdc_recheck_sdio_irq(host);
This I don't get. Why checking for SDIO IRQ here? Is it like an
optimization thing or?
> }
>
> /* returns true if command is fully handled; returns false otherwise */
> @@ -797,15 +819,17 @@ static bool msdc_cmd_done(struct msdc_host *host, int events,
> | MSDC_INT_CMDTMO)))
> return done;
>
> - spin_lock_irqsave(&host->lock, flags);
> done = !host->cmd;
> + spin_lock_irqsave(&host->lock, flags);
> host->cmd = NULL;
> spin_unlock_irqrestore(&host->lock, flags);
>
> if (done)
> return true;
>
> + spin_lock_irqsave(&host->irqlock, flags);
> sdr_clr_bits(host->base + MSDC_INTEN, cmd_ints_mask);
> + spin_unlock_irqrestore(&host->irqlock, flags);
>
> if (cmd->flags & MMC_RSP_PRESENT) {
> if (cmd->flags & MMC_RSP_136) {
> @@ -883,6 +907,7 @@ static inline bool msdc_cmd_is_ready(struct msdc_host *host,
> static void msdc_start_command(struct msdc_host *host,
> struct mmc_request *mrq, struct mmc_command *cmd)
> {
> + unsigned long flags;
> u32 rawcmd;
>
> WARN_ON(host->cmd);
> @@ -901,7 +926,10 @@ static void msdc_start_command(struct msdc_host *host,
> rawcmd = msdc_cmd_prepare_raw_cmd(host, mrq, cmd);
> mod_delayed_work(system_wq, &host->req_timeout, DAT_TIMEOUT);
>
> + spin_lock_irqsave(&host->irqlock, flags);
> sdr_set_bits(host->base + MSDC_INTEN, cmd_ints_mask);
> + spin_unlock_irqrestore(&host->irqlock, flags);
> +
> writel(cmd->arg, host->base + SDC_ARG);
> writel(rawcmd, host->base + SDC_CMD);
> }
> @@ -993,8 +1021,8 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
> | MSDC_INT_DMA_BDCSERR | MSDC_INT_DMA_GPDCSERR
> | MSDC_INT_DMA_PROTECT);
>
> - spin_lock_irqsave(&host->lock, flags);
> done = !host->data;
> + spin_lock_irqsave(&host->lock, flags);
> if (check_data)
> host->data = NULL;
> spin_unlock_irqrestore(&host->lock, flags);
> @@ -1009,7 +1037,11 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
> 1);
> while (readl(host->base + MSDC_DMA_CFG) & MSDC_DMA_CFG_STS)
> cpu_relax();
> +
> + spin_lock_irqsave(&host->irqlock, flags);
> sdr_clr_bits(host->base + MSDC_INTEN, data_ints_mask);
> + spin_unlock_irqrestore(&host->irqlock, flags);
> +
> dev_dbg(host->dev, "DMA stop\n");
>
> if ((events & MSDC_INT_XFER_COMPL) && (!stop || !stop->error)) {
> @@ -1123,44 +1155,47 @@ static void msdc_request_timeout(struct work_struct *work)
>
> static irqreturn_t msdc_irq(int irq, void *dev_id)
> {
> + unsigned long flags;
> struct msdc_host *host = (struct msdc_host *) dev_id;
> + struct mmc_request *mrq;
> + struct mmc_command *cmd;
> + struct mmc_data *data;
> + u32 events, event_mask;
> +
> + spin_lock_irqsave(&host->irqlock, flags);
> + events = readl(host->base + MSDC_INT);
> + event_mask = readl(host->base + MSDC_INTEN);
> + /* clear interrupts */
> + writel(events & event_mask, host->base + MSDC_INT);
> +
> + mrq = host->mrq;
> + cmd = host->cmd;
> + data = host->data;
> + spin_unlock_irqrestore(&host->irqlock, flags);
> +
> + if ((events & event_mask) & MSDC_INT_SDIOIRQ) {
> + mmc_signal_sdio_irq(host->mmc);
> + if (!mrq)
> + return IRQ_HANDLED;
> + }
>
> - while (true) {
> - unsigned long flags;
> - struct mmc_request *mrq;
> - struct mmc_command *cmd;
> - struct mmc_data *data;
> - u32 events, event_mask;
> -
> - spin_lock_irqsave(&host->lock, flags);
> - events = readl(host->base + MSDC_INT);
> - event_mask = readl(host->base + MSDC_INTEN);
> - /* clear interrupts */
> - writel(events & event_mask, host->base + MSDC_INT);
> -
> - mrq = host->mrq;
> - cmd = host->cmd;
> - data = host->data;
> - spin_unlock_irqrestore(&host->lock, flags);
> -
> - if (!(events & event_mask))
> - break;
> + if (!(events & (event_mask & ~MSDC_INT_SDIOIRQ)))
> + return IRQ_HANDLED;
>
> - if (!mrq) {
> - dev_err(host->dev,
> - "%s: MRQ=NULL; events=%08X; event_mask=%08X\n",
> - __func__, events, event_mask);
> - WARN_ON(1);
> - break;
> - }
> + if (!mrq) {
> + dev_err(host->dev,
> + "%s: MRQ=NULL; events=%08X; event_mask=%08X\n",
> + __func__, events, event_mask);
> + WARN_ON(1);
> + return IRQ_HANDLED;
> + }
>
> - dev_dbg(host->dev, "%s: events=%08X\n", __func__, events);
> + dev_dbg(host->dev, "%s: events=%08X\n", __func__, events);
>
> - if (cmd)
> - msdc_cmd_done(host, events, mrq, cmd);
> - else if (data)
> - msdc_data_xfer_done(host, events, mrq, data);
> - }
> + if (cmd)
> + msdc_cmd_done(host, events, mrq, cmd);
> + else if (data)
> + msdc_data_xfer_done(host, events, mrq, data);
>
> return IRQ_HANDLED;
> }
> @@ -1168,6 +1203,7 @@ static irqreturn_t msdc_irq(int irq, void *dev_id)
> static void msdc_init_hw(struct msdc_host *host)
> {
> u32 val;
> + unsigned long flags;
>
> /* Configure to MMC/SD mode, clock free running */
> sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_MODE | MSDC_CFG_CKPDN);
> @@ -1179,11 +1215,14 @@ static void msdc_init_hw(struct msdc_host *host)
> sdr_clr_bits(host->base + MSDC_PS, MSDC_PS_CDEN);
>
> /* Disable and clear all interrupts */
> + spin_lock_irqsave(&host->irqlock, flags);
> writel(0, host->base + MSDC_INTEN);
> val = readl(host->base + MSDC_INT);
> writel(val, host->base + MSDC_INT);
> + spin_unlock_irqrestore(&host->irqlock, flags);
>
> - writel(0, host->base + MSDC_PAD_TUNE);
> + sdr_set_field(host->base + MSDC_PAD_TUNE,
> + MSDC_PAD_TUNE_CLKTDLY, host->clk_pad_delay);
> writel(0, host->base + MSDC_IOCON);
> sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 0);
> writel(0x403c0046, host->base + MSDC_PATCH_BIT);
> @@ -1196,9 +1235,11 @@ static void msdc_init_hw(struct msdc_host *host)
> */
> sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIO);
>
> - /* disable detect SDIO device interrupt function */
> - sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
> -
> + if (host->mmc->caps & MMC_CAP_SDIO_IRQ)
> + sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
> + else
> + /* disable detect SDIO device interrupt function */
> + sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
> /* Configure to default data timeout */
> sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, 3);
>
> @@ -1210,11 +1251,15 @@ static void msdc_init_hw(struct msdc_host *host)
> static void msdc_deinit_hw(struct msdc_host *host)
> {
> u32 val;
> + unsigned long flags;
> +
> /* Disable and clear all interrupts */
> + spin_lock_irqsave(&host->irqlock, flags);
> writel(0, host->base + MSDC_INTEN);
>
> val = readl(host->base + MSDC_INT);
> writel(val, host->base + MSDC_INT);
> + spin_unlock_irqrestore(&host->irqlock, flags);
> }
>
> /* init gpd and bd list in msdc_drv_probe */
> @@ -1582,6 +1627,48 @@ static void msdc_hw_reset(struct mmc_host *mmc)
> sdr_clr_bits(host->base + EMMC_IOCON, 1);
> }
>
> +/**
> + * msdc_recheck_sdio_irq - recheck whether the SDIO IRQ is lost
> + * @host: The host to check.
> + *
> + * Host controller may lost interrupt in some special case.
> + * Add sdio IRQ recheck mechanism to make sure all interrupts
> + * can be processed immediately
> + */
> +static void msdc_recheck_sdio_irq(struct msdc_host *host)
> +{
> + u32 reg_int, reg_ps;
> +
> + if (host->clock_on && (host->mmc->caps & MMC_CAP_SDIO_IRQ) &&
> + host->irq_thread_alive) {
> + reg_int = readl(host->base + MSDC_INT);
> + reg_ps = readl(host->base + MSDC_PS);
> + if (!((reg_int & MSDC_INT_SDIOIRQ) ||
> + (reg_ps & MSDC_PS_DATA1)))
> + mmc_signal_sdio_irq(host->mmc);
> + }
> +}
> +
> +static void msdc_enable_sdio_irq(struct mmc_host *mmc, int enable)
> +{
> + unsigned long flags;
> + struct msdc_host *host = mmc_priv(mmc);
> +
> + host->irq_thread_alive = true;
> + if (enable) {
> + msdc_recheck_sdio_irq(host);
> +
> + spin_lock_irqsave(&host->irqlock, flags);
> + sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
> + sdr_set_bits(host->base + MSDC_INTEN, MSDC_INTEN_SDIOIRQ);
> + spin_unlock_irqrestore(&host->irqlock, flags);
> + } else {
> + spin_lock_irqsave(&host->irqlock, flags);
> + sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INTEN_SDIOIRQ);
> + spin_unlock_irqrestore(&host->irqlock, flags);
> + }
> +}
> +
> static struct mmc_host_ops mt_msdc_ops = {
> .post_req = msdc_post_req,
> .pre_req = msdc_pre_req,
> @@ -1593,6 +1680,7 @@ static void msdc_hw_reset(struct mmc_host *mmc)
> .execute_tuning = msdc_execute_tuning,
> .prepare_hs400_tuning = msdc_prepare_hs400_tuning,
> .hw_reset = msdc_hw_reset,
> + .enable_sdio_irq = msdc_enable_sdio_irq,
> };
>
> static void msdc_of_property_parse(struct platform_device *pdev,
> @@ -1612,6 +1700,9 @@ static void msdc_of_property_parse(struct platform_device *pdev,
> host->hs400_cmd_resp_sel_rising = true;
> else
> host->hs400_cmd_resp_sel_rising = false;
> +
> + of_property_read_u32(pdev->dev.of_node, "mediatek,clk-pad-delay",
> + &host->clk_pad_delay);
> }
>
> static int msdc_drv_probe(struct platform_device *pdev)
> @@ -1705,6 +1796,7 @@ static int msdc_drv_probe(struct platform_device *pdev)
> mmc_dev(mmc)->dma_mask = &host->dma_mask;
>
> host->timeout_clks = 3 * 1048576;
> + host->irq_thread_alive = false;
> host->dma.gpd = dma_alloc_coherent(&pdev->dev,
> 2 * sizeof(struct mt_gpdma_desc),
> &host->dma.gpd_addr, GFP_KERNEL);
> @@ -1718,6 +1810,7 @@ static int msdc_drv_probe(struct platform_device *pdev)
> msdc_init_gpd_bd(host, &host->dma);
> INIT_DELAYED_WORK(&host->req_timeout, msdc_request_timeout);
> spin_lock_init(&host->lock);
> + spin_lock_init(&host->irqlock);
I don't get why the host->lock can't be used here? Why do you need a new one?
>
> platform_set_drvdata(pdev, mmc);
> msdc_ungate_clock(host);
> @@ -1732,6 +1825,10 @@ static int msdc_drv_probe(struct platform_device *pdev)
> pm_runtime_set_autosuspend_delay(host->dev, MTK_MMC_AUTOSUSPEND_DELAY);
> pm_runtime_use_autosuspend(host->dev);
> pm_runtime_enable(host->dev);
> +
> + /* In SDIO irq mode, DATA1 slways need to be detected */
> + if (host->mmc->caps & MMC_CAP_SDIO_IRQ)
> + pm_runtime_get_sync(host->dev);
This seems reasonable, however I think we can make this more fine grained.
It is actually not until there is a SDIO func driver that has claimed
an SDIO IRQ, to when you need to make sure to keep the host runtime PM
resumed.
Please look into the following series [1], which I recently posted and
try to see if using MMC_CAP2_SDIO_IRQ_NOTHREAD can suite you. In
principle I think $subject patch can be greatly simplified if you
convert to MMC_CAP2_SDIO_IRQ_NOTHREAD.
> ret = mmc_add_host(mmc);
>
> if (ret)
> @@ -1821,6 +1918,10 @@ static int msdc_runtime_suspend(struct device *dev)
>
> msdc_save_reg(host);
> msdc_gate_clock(host);
> + if (host->mmc->caps & MMC_CAP_SDIO_IRQ) {
> + pm_runtime_mark_last_busy(dev);
> + pm_runtime_put_autosuspend(dev);
> + }
> return 0;
> }
>
> @@ -1829,6 +1930,9 @@ static int msdc_runtime_resume(struct device *dev)
> struct mmc_host *mmc = dev_get_drvdata(dev);
> struct msdc_host *host = mmc_priv(mmc);
>
> + /* In SDIO irq mode, DATA1 slways need to be detected */
> + if (host->mmc->caps & MMC_CAP_SDIO_IRQ)
> + pm_runtime_get_sync(host->dev);
> msdc_ungate_clock(host);
> msdc_restore_reg(host);
> return 0;
> --
> 1.7.9.5
>
Kind regards
Uffe
[1]
https://www.spinics.net/lists/linux-mmc/msg43763.html
^ permalink raw reply
* [PATCH v4 00/21] PCI: fix config space memory mappings
From: Bjorn Helgaas @ 2017-04-20 13:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170419164913.19674-1-lorenzo.pieralisi@arm.com>
On Wed, Apr 19, 2017 at 05:48:49PM +0100, Lorenzo Pieralisi wrote:
> This patch series[1] is a v4 of a previous version:
Applied to pci/ioremap for v4.12, thanks, Lorenzo!
> v3 -> v4:
> - Reverted back to pci_remap_cfgspace() interface for lack of
> consensus on ioremap_nopost() semantics
> - Dropped pci_remap_iospace() rework (owing to lack of adequate
> pgprot_* attribute description across arches)
> - Updated pci_remap_cfgspace() comments
>
> v3: http://lists.infradead.org/pipermail/linux-arm-kernel/2017-April/500838.html
>
> v2 -> v3:
> - Created a default ioremap_nopost() implementation in a separate
> asm-generic header and patched all arches to make use of it
> - Removed PCI drivers patches from the series to simplify the
> review, they will be posted separately once the ioremap_nopost()
> interface is settled
> - Fixed devm_ioremap_* BUS offset comments and implemented
> nopost interface on top of it
> - Added collected tags
>
> v2: https://lkml.org/lkml/2017/3/27/220
>
> v2 -> v3:
> - Fixed devm_ioremap_* BUS offset comments and implemented
> nopost interface on top of it
> - Added collected tags
>
> v1: https://lkml.org/lkml/2017/2/27/228
>
> v1 -> v2:
> - Changed pci_remap_cfgspace() to more generic ioremap_nopost()
> interface
> - Added pgprot_nonposted
> - Fixed build errors on arches not relying on asm-generic headers
> - Added PCI versatile host controller driver patch
> - Added missing config space remapping to hisilicon host controller
>
> PCI local bus specifications (Rev3.0, 3.2.5 "Transaction Ordering
> and Posting") strictly require PCI configuration and I/O Address space
> write transactions to be non-posted.
>
> Current crop of DT/ACPI PCI host controllers drivers relies on
> the ioremap interface to map ECAM and ECAM-derivative PCI config
> regions and pci_remap_iospace() to create a VMA for mapping
> PCI host bridge I/O Address space transactions to CPU virtual address
> space.
>
> On some platforms (ie ARM/ARM64) ioremap fails to comply with the PCI
> configuration non-posted write transactions requirement, because it
> provides a memory mapping that issues "bufferable" or, in PCI terms
> "posted" write transactions. Likewise, the current pci_remap_iospace()
> implementation maps the physical address range that the PCI translates
> to I/O space cycles to virtual address space through pgprot_device()
> attributes that on eg ARM64 provides a memory mapping issuing
> posted writes transactions, which is not PCI specifications compliant.
>
> This patch series[1] addresses both issues in one go:
>
> - It updates the pci_remap_iospace() function to use a page mapping
> that guarantees non-posted write transactions for I/O space addresses
> - It adds a kernel API to remap PCI config space resources, so that
> architecture can override it with a mapping implementation that
> guarantees PCI specifications compliancy wrt non-posted write
> configuration transactions
> - It updates all PCI host controller implementations (and the generic
> ECAM layer) to use the newly introduced mapping interface
>
> Tested on Juno ECAM based interface (DT/ACPI).
>
> Non-ECAM PCI host controller drivers patches need checking to make
> sure that:
>
> - I patched the correct resource region mapping for config space
> - There are not any other ways to ensure posted-write completion
> in the respective pci_ops that make the relevant patch unnecessary
>
> [1] git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git pci/config-io-mappings-fix-v4
>
> Cc: Pratyush Anand <pratyush.anand@gmail.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Jonathan Corbet <corbet@lwn.net>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Jingoo Han <jingoohan1@gmail.com>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Mingkai Hu <mingkai.hu@freescale.com>
> Cc: Tanmay Inamdar <tinamdar@apm.com>
> Cc: Murali Karicheri <m-karicheri2@ti.com>
> Cc: Russell King <linux@armlinux.org.uk>
> Cc: Bharat Kumar Gogada <bharat.kumar.gogada@xilinx.com>
> Cc: Ray Jui <rjui@broadcom.com>
> Cc: Wenrui Li <wenrui.li@rock-chips.com>
> Cc: Shawn Lin <shawn.lin@rock-chips.com>
> Cc: Minghuan Lian <minghuan.Lian@freescale.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Jon Mason <jonmason@broadcom.com>
> Cc: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Cc: Joao Pinto <Joao.Pinto@synopsys.com>
> Cc: Thierry Reding <thierry.reding@gmail.com>
> Cc: Luis R. Rodriguez <mcgrof@kernel.org>
> Cc: Michal Simek <michal.simek@xilinx.com>
> Cc: Stanimir Varbanov <svarbanov@mm-sol.com>
> Cc: Zhou Wang <wangzhou1@hisilicon.com>
> Cc: Roy Zang <tie-fei.zang@freescale.com>
>
> Lorenzo Pieralisi (21):
> PCI: remove __weak tag from pci_remap_iospace()
> linux/io.h: add PCI config space remap interface
> ARM64: implement pci_remap_cfgspace() interface
> ARM: implement pci_remap_cfgspace() interface
> lib: fix Devres devm_ioremap_* offset parameter kerneldoc description
> PCI: implement Devres interface to map PCI config space
> PCI: ECAM: use pci_remap_cfgspace() to map config region
> PCI: xilinx: update PCI config space remap function
> PCI: xilinx-nwl: update PCI config space remap function
> PCI: spear13xx: update PCI config space remap function
> PCI: rockchip: update PCI config space remap function
> PCI: qcom: update PCI config space remap function
> PCI: iproc-platform: update PCI config space remap function
> PCI: designware: update PCI config space remap function
> PCI: armada8k: update PCI config space remap function
> PCI: xgene: update PCI config space remap function
> PCI: tegra: update PCI config space remap function
> PCI: hisi: update PCI config space remap function
> PCI: layerscape: update PCI config space remap function
> PCI: keystone-dw: update PCI config space remap function
> PCI: versatile: update PCI config space remap function
>
> Documentation/driver-model/devres.txt | 6 ++-
> arch/arm/include/asm/io.h | 10 ++++
> arch/arm/mm/ioremap.c | 7 +++
> arch/arm/mm/nommu.c | 12 +++++
> arch/arm64/include/asm/io.h | 10 ++++
> drivers/pci/dwc/pci-keystone-dw.c | 2 +-
> drivers/pci/dwc/pci-layerscape.c | 2 +-
> drivers/pci/dwc/pcie-armada8k.c | 2 +-
> drivers/pci/dwc/pcie-designware-host.c | 12 +++--
> drivers/pci/dwc/pcie-hisi.c | 7 ++-
> drivers/pci/dwc/pcie-qcom.c | 2 +-
> drivers/pci/dwc/pcie-spear13xx.c | 2 +-
> drivers/pci/ecam.c | 6 ++-
> drivers/pci/host/pci-tegra.c | 4 +-
> drivers/pci/host/pci-versatile.c | 3 +-
> drivers/pci/host/pci-xgene.c | 4 +-
> drivers/pci/host/pcie-iproc-platform.c | 3 +-
> drivers/pci/host/pcie-rockchip.c | 2 +-
> drivers/pci/host/pcie-xilinx-nwl.c | 2 +-
> drivers/pci/host/pcie-xilinx.c | 2 +-
> drivers/pci/pci.c | 84 +++++++++++++++++++++++++++++++++-
> include/linux/io.h | 19 ++++++++
> include/linux/pci.h | 5 ++
> lib/devres.c | 6 +--
> 24 files changed, 183 insertions(+), 31 deletions(-)
>
> --
> 2.10.0
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v5 2/2] PCI: quirks: Fix ThunderX2 dma alias handling
From: Bjorn Helgaas @ 2017-04-20 13:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <832cb9b3-ceaf-6771-bfc9-7bae35494f6d@redhat.com>
On Wed, Apr 19, 2017 at 7:25 PM, Jon Masters <jcm@redhat.com> wrote:
> One additional footnote. I spent a bunch of time recently on my personal
> Xeon systems walking through the PCIe topology and aligning on how to
> advise the ARM server community proceed going forward. If you look at
> how Intel vs AMD handle their host bridges for example, you'll see two
> very different approaches to the case of cross-socket PCIe.
As a learning opportunity for me, can you share "lspci -vv" examples
that show this Intel vs AMD difference? Maybe the ACPI host bridge
descriptions from dmesg are relevant too?
> But my
> operating assumption is that anything longer term which looks boring and
> x86 enough is probably fine from an ARM server point of view.
That sounds pretty safe to me.
Bjorn
^ permalink raw reply
* [PATCH v4 02/21] linux/io.h: add PCI config space remap interface
From: Bjorn Helgaas @ 2017-04-20 13:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170420105153.GA9741@red-moon>
On Thu, Apr 20, 2017 at 5:51 AM, Lorenzo Pieralisi
<lorenzo.pieralisi@arm.com> wrote:
> [+ Michael]
>
> On Wed, Apr 19, 2017 at 05:48:51PM +0100, Lorenzo Pieralisi wrote:
>> The PCI specifications (Rev 3.0, 3.2.5 "Transaction Ordering and
>> Posting") mandate non-posted configuration transactions. As further
>> highlighted in the PCIe specifications (4.0 - Rev0.3, "Ordering
>> Considerations for the Enhanced Configuration Access Mechanism"),
>> through ECAM and ECAM-derivative configuration mechanism, the memory
>> mapped transactions from the host CPU into Configuration Requests on the
>> PCI express fabric may create ordering problems for software because
>> writes to memory address are typically posted transactions (unless the
>> architecture can enforce through virtual address mapping non-posted
>> write transactions behaviour) but writes to Configuration Space are not
>> posted on the PCI express fabric.
>>
>> Current DT and ACPI host bridge controllers map PCI configuration space
>> (ECAM and ECAM-derivative) into the virtual address space through
>> ioremap() calls, that are non-cacheable device accesses on most
>> architectures, but may provide "bufferable" or "posted" write semantics
>> in architecture like eg ARM/ARM64 that allow ioremap'ed regions writes
>> to be buffered in the bus connecting the host CPU to the PCI fabric;
>> this behaviour, as underlined in the PCIe specifications, may trigger
>> transactions ordering rules and must be prevented.
>>
>> Introduce a new generic and explicit API to create a memory
>> mapping for ECAM and ECAM-derivative config space area that
>> defaults to ioremap_nocache() (which should provide a sane default
>> behaviour) but still allowing architectures on which ioremap_nocache()
>> results in posted write transactions to override the function
>> call with an arch specific implementation that complies with
>> the PCI specifications for configuration transactions.
>>
>> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Arnd Bergmann <arnd@arndb.de>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Bjorn Helgaas <bhelgaas@google.com>
>> Cc: Russell King <linux@armlinux.org.uk>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> ---
>> include/linux/io.h | 19 +++++++++++++++++++
>> 1 file changed, 19 insertions(+)
>>
>> diff --git a/include/linux/io.h b/include/linux/io.h
>> index 82ef36e..3934aba 100644
>> --- a/include/linux/io.h
>> +++ b/include/linux/io.h
>> @@ -91,6 +91,25 @@ void devm_memunmap(struct device *dev, void *addr);
>> void *__devm_memremap_pages(struct device *dev, struct resource *res);
>>
>> /*
>> + * The PCI specifications (Rev 3.0, 3.2.5 "Transaction Ordering and
>> + * Posting") mandate non-posted configuration transactions. There is
>> + * no ioremap API in the kernel that can guarantee non-posted write
>> + * semantics across arches so provide a default implementation for
>> + * mapping PCI config space that defaults to ioremap_nocache(); arches
>> + * should override it if they have memory mapping implementations that
>> + * guarantee non-posted writes semantics to make the memory mapping
>> + * compliant with the PCI specification.
>> + */
>> +#ifndef pci_remap_cfgspace
>> +#define pci_remap_cfgspace pci_remap_cfgspace
>> +static inline void __iomem *pci_remap_cfgspace(phys_addr_t offset,
>> + size_t size)
>> +{
>> + return ioremap_nocache(offset, size);
>> +}
>> +#endif
>> +
>> +/*
>
> As an heads-up, this patch strictly depends on:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/arch/powerpc/include/asm/io.h?id=590c369e7ecc00be736be39ae0c62d1b5d563a51
>
> to go upstream first, otherwise we would break powerpc compilation
> (owing to powerpc including linux/io.h before ioremap_nocache() is
> defined in arch/powerpc/include/asm/io.h).
>
> If we want to decouple them I must drop the static inline and make
> it a #define, it is not ideal but we must be aware of this, I really
> want to prevent breakage if we go ahead with this set (and -next can
> hide the issue).
It looks like Stephen merges powerpc/next into linux-next before
pci/next, so this will probably be OK there. I'll try to remember to
wait for the powerpc stuff to make it to Linus' tree during the merge
window before I send my pull request.
Bjorn
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox