* [PATCH 16/17] arm64: KVM: Device mappings should be execute-never
From: Marc Zyngier @ 2019-09-09 13:48 UTC (permalink / raw)
To: Paolo Bonzini, Radim Krčmář
Cc: Mark Rutland, kvm, Andre Przywara, Eric Auger, James Morse,
Zenghui Yu, Alexandru Elisei, kvmarm, linux-arm-kernel
In-Reply-To: <20190909134807.27978-1-maz@kernel.org>
From: James Morse <james.morse@arm.com>
Since commit 2f6ea23f63cca ("arm64: KVM: Avoid marking pages as XN in
Stage-2 if CTR_EL0.DIC is set"), KVM has stopped marking normal memory
as execute-never at stage2 when the system supports D->I Coherency at
the PoU. This avoids KVM taking a trap when the page is first executed,
in order to clean it to PoU.
The patch that added this change also wrapped PAGE_S2_DEVICE mappings
up in this too. The upshot is, if your CPU caches support DIC ...
you can execute devices.
Revert the PAGE_S2_DEVICE change so PTE_S2_XN is always used
directly.
Fixes: 2f6ea23f63cca ("arm64: KVM: Avoid marking pages as XN in Stage-2 if CTR_EL0.DIC is set")
Signed-off-by: James Morse <james.morse@arm.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/include/asm/pgtable-prot.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
index 92d2e9f28f28..9a21b84536f2 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -77,7 +77,7 @@
})
#define PAGE_S2 __pgprot(_PROT_DEFAULT | PAGE_S2_MEMATTR(NORMAL) | PTE_S2_RDONLY | PAGE_S2_XN)
-#define PAGE_S2_DEVICE __pgprot(_PROT_DEFAULT | PAGE_S2_MEMATTR(DEVICE_nGnRE) | PTE_S2_RDONLY | PAGE_S2_XN)
+#define PAGE_S2_DEVICE __pgprot(_PROT_DEFAULT | PAGE_S2_MEMATTR(DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_S2_XN)
#define PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN)
#define PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 17/17] KVM: arm/arm64: vgic: Allow more than 256 vcpus for KVM_IRQ_LINE
From: Marc Zyngier @ 2019-09-09 13:48 UTC (permalink / raw)
To: Paolo Bonzini, Radim Krčmář
Cc: Mark Rutland, kvm, Andre Przywara, Eric Auger, James Morse,
Zenghui Yu, Alexandru Elisei, kvmarm, linux-arm-kernel
In-Reply-To: <20190909134807.27978-1-maz@kernel.org>
While parts of the VGIC support a large number of vcpus (we
bravely allow up to 512), other parts are more limited.
One of these limits is visible in the KVM_IRQ_LINE ioctl, which
only allows 256 vcpus to be signalled when using the CPU or PPI
types. Unfortunately, we've cornered ourselves badly by allocating
all the bits in the irq field.
Since the irq_type subfield (8 bit wide) is currently only taking
the values 0, 1 and 2 (and we have been careful not to allow anything
else), let's reduce this field to only 4 bits, and allocate the
remaining 4 bits to a vcpu2_index, which acts as a multiplier:
vcpu_id = 256 * vcpu2_index + vcpu_index
With that, and a new capability (KVM_CAP_ARM_IRQ_LINE_LAYOUT_2)
allowing this to be discovered, it becomes possible to inject
PPIs to up to 4096 vcpus. But please just don't.
Whilst we're there, add a clarification about the use of KVM_IRQ_LINE
on arm, which is not completely conditionned by KVM_CAP_IRQCHIP.
Reported-by: Zenghui Yu <yuzenghui@huawei.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
Documentation/virt/kvm/api.txt | 12 ++++++++++--
arch/arm/include/uapi/asm/kvm.h | 4 +++-
arch/arm64/include/uapi/asm/kvm.h | 4 +++-
include/uapi/linux/kvm.h | 1 +
virt/kvm/arm/arm.c | 2 ++
5 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/Documentation/virt/kvm/api.txt b/Documentation/virt/kvm/api.txt
index 2d067767b617..25931ca1cb38 100644
--- a/Documentation/virt/kvm/api.txt
+++ b/Documentation/virt/kvm/api.txt
@@ -753,8 +753,8 @@ in-kernel irqchip (GIC), and for in-kernel irqchip can tell the GIC to
use PPIs designated for specific cpus. The irq field is interpreted
like this:
- bits: | 31 ... 24 | 23 ... 16 | 15 ... 0 |
- field: | irq_type | vcpu_index | irq_id |
+ bits: | 31 ... 28 | 27 ... 24 | 23 ... 16 | 15 ... 0 |
+ field: | vcpu2_index | irq_type | vcpu_index | irq_id |
The irq_type field has the following values:
- irq_type[0]: out-of-kernel GIC: irq_id 0 is IRQ, irq_id 1 is FIQ
@@ -766,6 +766,14 @@ The irq_type field has the following values:
In both cases, level is used to assert/deassert the line.
+When KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 is supported, the target vcpu is
+identified as (256 * vcpu2_index + vcpu_index). Otherwise, vcpu2_index
+must be zero.
+
+Note that on arm/arm64, the KVM_CAP_IRQCHIP capability only conditions
+injection of interrupts for the in-kernel irqchip. KVM_IRQ_LINE can always
+be used for a userspace interrupt controller.
+
struct kvm_irq_level {
union {
__u32 irq; /* GSI */
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index a4217c1a5d01..2769360f195c 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -266,8 +266,10 @@ struct kvm_vcpu_events {
#define KVM_DEV_ARM_ITS_CTRL_RESET 4
/* KVM_IRQ_LINE irq field index values */
+#define KVM_ARM_IRQ_VCPU2_SHIFT 28
+#define KVM_ARM_IRQ_VCPU2_MASK 0xf
#define KVM_ARM_IRQ_TYPE_SHIFT 24
-#define KVM_ARM_IRQ_TYPE_MASK 0xff
+#define KVM_ARM_IRQ_TYPE_MASK 0xf
#define KVM_ARM_IRQ_VCPU_SHIFT 16
#define KVM_ARM_IRQ_VCPU_MASK 0xff
#define KVM_ARM_IRQ_NUM_SHIFT 0
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 9a507716ae2f..67c21f9bdbad 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -325,8 +325,10 @@ struct kvm_vcpu_events {
#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
/* KVM_IRQ_LINE irq field index values */
+#define KVM_ARM_IRQ_VCPU2_SHIFT 28
+#define KVM_ARM_IRQ_VCPU2_MASK 0xf
#define KVM_ARM_IRQ_TYPE_SHIFT 24
-#define KVM_ARM_IRQ_TYPE_MASK 0xff
+#define KVM_ARM_IRQ_TYPE_MASK 0xf
#define KVM_ARM_IRQ_VCPU_SHIFT 16
#define KVM_ARM_IRQ_VCPU_MASK 0xff
#define KVM_ARM_IRQ_NUM_SHIFT 0
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 5e3f12d5359e..5414b6588fbb 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -996,6 +996,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_ARM_PTRAUTH_ADDRESS 171
#define KVM_CAP_ARM_PTRAUTH_GENERIC 172
#define KVM_CAP_PMU_EVENT_FILTER 173
+#define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174
#ifdef KVM_CAP_IRQ_ROUTING
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 35a069815baf..86c6aa1cb58e 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -196,6 +196,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_MP_STATE:
case KVM_CAP_IMMEDIATE_EXIT:
case KVM_CAP_VCPU_EVENTS:
+ case KVM_CAP_ARM_IRQ_LINE_LAYOUT_2:
r = 1;
break;
case KVM_CAP_ARM_SET_DEVICE_ADDR:
@@ -888,6 +889,7 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
irq_type = (irq >> KVM_ARM_IRQ_TYPE_SHIFT) & KVM_ARM_IRQ_TYPE_MASK;
vcpu_idx = (irq >> KVM_ARM_IRQ_VCPU_SHIFT) & KVM_ARM_IRQ_VCPU_MASK;
+ vcpu_idx += ((irq >> KVM_ARM_IRQ_VCPU2_SHIFT) & KVM_ARM_IRQ_VCPU2_MASK) * (KVM_ARM_IRQ_VCPU_MASK + 1);
irq_num = (irq >> KVM_ARM_IRQ_NUM_SHIFT) & KVM_ARM_IRQ_NUM_MASK;
trace_kvm_irq_line(irq_type, vcpu_idx, irq_num, irq_level->level);
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH v5 0/5] Add HDMI jack support on RK3288
From: Mark Brown @ 2019-09-09 13:53 UTC (permalink / raw)
To: Neil Armstrong
Cc: ALSA development, Heiko Stuebner, Liam Girdwood, David Airlie,
dri-devel, Linux Kernel Mailing List, Hans Verkuil, Andrzej Hajda,
Laurent Pinchart, Cheng-yi Chiang, linux-rockchip, Takashi Iwai,
Tzung-Bi Shih, Dylan Reid, tzungbi, Jonas Karlman, Russell King,
Jaroslav Kysela, linux-arm-kernel, Jernej Skrabec,
Douglas Anderson, Daniel Vetter
In-Reply-To: <7019a223-cc97-e1c6-907b-e6b3d626164f@baylibre.com>
[-- Attachment #1.1: Type: text/plain, Size: 548 bytes --]
On Mon, Sep 09, 2019 at 09:37:14AM +0200, Neil Armstrong wrote:
> I'd like some review from ASoC people and other drm bridge reviewers,
> Jernej, Jonas & Andrzej.
> Jonas could have some comments on the overall patchset.
The ASoC bits look basically fine, I've gone ahead and applied
patch 1 as is since we're just before the merge window and that
way we reduce potential cross tree issues. I know there's a lot
of discussion on the DRM side about how they want to handle
things with jacks, I'm not 100% sure what the latest thinking is
there.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 2/9] crypto: Add Allwinner sun8i-ce Crypto Engine
From: Maxime Ripard @ 2019-09-09 13:59 UTC (permalink / raw)
To: Corentin Labbe
Cc: mark.rutland, devicetree, herbert, linux-sunxi, linux,
linux-kernel, wens, robh+dt, linux-crypto, davem,
linux-arm-kernel
In-Reply-To: <20190909131906.GA12882@Red>
On Mon, Sep 09, 2019 at 03:19:06PM +0200, Corentin Labbe wrote:
> On Mon, Sep 09, 2019 at 01:38:37PM +0200, Maxime Ripard wrote:
> > On Sat, Sep 07, 2019 at 09:04:08PM +0200, Corentin Labbe wrote:
> > > > Also, I'm not sure what is the point of having the clocks names be
> > > > parameters there as well. It's constant across all the compatibles,
> > > > the only thing that isn't is the number of clocks and the module clock
> > > > rate. It's what you should have in there.
> > >
> > > Since the datasheet give some max frequency, I think I will add a
> > > max_freq and add a check to verify if the clock is in the right
> > > range
> >
> > It's a bit pointless. What are you going to do if it's not correct?
> > What are you trying to fix / report with this?
>
> I thinked to print a warning. If someone want to play with
> overclocking for example, the driver should said that probably some
> result could be invalid.
If someone wants to play with overclocking, the crypto engine is going
to be the least of their concern.
> > > > > +int sun8i_ce_get_engine_number(struct sun8i_ce_dev *ce)
> > > > > +{
> > > > > + return atomic_inc_return(&ce->flow) % ce->variant->maxflow;
> > > > > +}
> > > >
> > > > I'm not sure what this is supposed to be doing, but that mod there
> > > > seems pretty dangerous.
> > > >
> > > > ...
> > >
> > > This mod do a round robin on each channel.
> > > I dont see why it is dangerous.
> >
> > Well, you're using the atomic API here which is most commonly used for
> > refcounting, while you're using a mod.
> >
> > Plus, while the increment is atomic, the modulo isn't, so you can end
> > up in a case where you would be preempted between the
> > atomic_inc_return and the mod, which is dangerous.
> >
> > Again, I'm not sure what this function is doing (which is also a
> > problem in itself). I guess you should just make it clearer what it
> > does, and then we can discuss it properly.
>
> Each request need to be assigned to a channel.
> Each channel are identified by a number from 1 to 4.
>
> So this function return the channel to use, 1 then 2 then 3 then 4 then 1...
>
> Note that this is uncritical. If, due to anything, two request are
> assigned to the same channel, nothing will break.
I'm not sure why you're using the atomic API then?
Also, I guess a bitfield and find_first_bit (and a different function
name) would be more obvious to the reader.
Thanks!
Maxime
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 3/3] arm64: alpine: select AL_POS
From: Shenhar, Talel @ 2019-09-09 13:58 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Mark Rutland, mjourdan, Catalin Marinas, Linus Walleij,
linux-kernel@vger.kernel.org, jonnyc, Mauro Carvalho Chehab,
ronenk, Will Deacon, Benjamin Herrenschmidt, DTML, Maxime Ripard,
Rob Herring, Santosh Shilimkar, Thomas Gleixner, hanochu,
Linux ARM, barakw, hhhawa, gregkh, paul.kocialkowski,
Patrick Venture, Olof Johansson, David Miller, David Woodhouse
In-Reply-To: <CAK8P3a34eKFXoAPOfkFN5+H4kxOhRjXgws_0wy+d-186LFxcTw@mail.gmail.com>
On 9/9/2019 4:45 PM, Arnd Bergmann wrote:
> On Mon, Sep 9, 2019 at 12:17 PM Shenhar, Talel <talel@amazon.com> wrote:
>> On 9/9/2019 12:40 PM, Arnd Bergmann wrote:
>>> On Mon, Sep 9, 2019 at 11:14 AM Talel Shenhar <talel@amazon.com> wrote:
>>>> diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
>>>> index 4778c77..bd86b15 100644
>>>> --- a/arch/arm64/Kconfig.platforms
>>>> +++ b/arch/arm64/Kconfig.platforms
>>>> @@ -25,6 +25,7 @@ config ARCH_SUNXI
>>>> config ARCH_ALPINE
>>>> bool "Annapurna Labs Alpine platform"
>>>> select ALPINE_MSI if PCI
>>>> + select AL_POS
>>>> help
>>>> This enables support for the Annapurna Labs Alpine
>>>> Soc family.
>>> Generally I think this kind of thing should go into the defconfig
>>> rather than being hard-selected. There might be users that
>>> want to not enable the driver.
>> The reason for selecting it is because this is a driver that we will
>> always want for ARCH_ALPINE.
> Can you put the exact requirement (other than "we want this")
> in the changelog text then? It's still not clear to me what breaks
> without this driver.
>
> Arnd
Its not that something will get broken. its error event detector for POS
events which allows seeing bad accesses to registers.
What is the general rule of which configs to put under select and which
under defconfig?
I was thinking that "general" SoC support is good under select - those
things that we always want.
And specific features, e.g. RAID support or features that supported only
on specific HW shall go under defconfig.
Similar, I see ARCH_LAYERSCAPE selecting EDAC_SUPPORT.
Will love to hear the general rule for select vs defconfig.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH V5 02/11] dt-bindings: clock: imx-lpcg: add support to parse clocks from device tree
From: Dong Aisheng @ 2019-09-10 2:09 UTC (permalink / raw)
To: linux-clk
Cc: Dong Aisheng, devicetree, sboyd, mturquette, linux-imx, kernel,
fabio.estevam, shawnguo, linux-arm-kernel
In-Reply-To: <1568081408-26800-1-git-send-email-aisheng.dong@nxp.com>
MX8QM and MX8QXP LPCG Clocks are mostly the same except they may reside
in different subsystems across CPUs and also vary a bit on the availability.
Same as SCU clock, we want to move the clock definition into device tree
which can fully decouple the dependency of Clock ID definition from device
tree and make us be able to write a fully generic lpcg clock driver.
And we can also use the existence of clock nodes in device tree to address
the device and clock availability differences across different SoCs.
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: devicetree@vger.kernel.org
Acked-by: Shawn Guo <shawnguo@kernel.org>
Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v4->v5:
: no changes
v3->v4:
* change bit-offset property to clock-indices
* use constant macro to define clock indinces
* drop hw-autogate property which is still not used by drivers
v2->v3:
* no changes
v1->v2:
* Update example
* Add power domain property
---
.../devicetree/bindings/clock/imx8qxp-lpcg.txt | 36 ++++++++++++++++++----
include/dt-bindings/clock/imx8-lpcg.h | 14 +++++++++
2 files changed, 44 insertions(+), 6 deletions(-)
create mode 100644 include/dt-bindings/clock/imx8-lpcg.h
diff --git a/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
index 965cfa4..cad8fc4 100644
--- a/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
+++ b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
@@ -11,6 +11,21 @@ enabled by these control bits, it might still not be running based
on the base resource.
Required properties:
+- compatible: Should be one of:
+ "fsl,imx8qxp-lpcg"
+ "fsl,imx8qm-lpcg" followed by "fsl,imx8qxp-lpcg".
+- reg: Address and length of the register set.
+- #clock-cells: Should be 1. One LPCG supports multiple clocks.
+- clocks: Input parent clocks phandle array for each clock.
+- clock-indices: An integer array indicating the bit offset for each clock.
+ Refer to <include/dt-bindings/clock/imx8-lpcg.h> for the
+ supported LPCG clock indices.
+- clock-output-names: Shall be the corresponding names of the outputs.
+ NOTE this property must be specified in the same order
+ as the clock-indices property.
+- power-domains: Should contain the power domain used by this clock.
+
+Legacy binding (DEPRECATED):
- compatible: Should be one of:
"fsl,imx8qxp-lpcg-adma",
"fsl,imx8qxp-lpcg-conn",
@@ -33,10 +48,19 @@ Examples:
#include <dt-bindings/clock/imx8qxp-clock.h>
-conn_lpcg: clock-controller@5b200000 {
- compatible = "fsl,imx8qxp-lpcg-conn";
- reg = <0x5b200000 0xb0000>;
+sdhc0_lpcg: clock-controller@5b200000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5b200000 0x10000>;
#clock-cells = <1>;
+ clocks = <&sdhc0_clk IMX_SC_PM_CLK_PER>,
+ <&conn_ipg_clk>, <&conn_axi_clk>;
+ clock-indices = <IMX_LPCG_CLK_0>,
+ <IMX_LPCG_CLK_4>,
+ <IMX_LPCG_CLK_5>;
+ clock-output-names = "sdhc0_lpcg_per_clk",
+ "sdhc0_lpcg_ipg_clk",
+ "sdhc0_lpcg_ahb_clk";
+ power-domains = <&pd IMX_SC_R_SDHC_0>;
};
usdhc1: mmc@5b010000 {
@@ -44,8 +68,8 @@ usdhc1: mmc@5b010000 {
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
reg = <0x5b010000 0x10000>;
- clocks = <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_IPG_CLK>,
- <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_PER_CLK>,
- <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_HCLK>;
+ clocks = <&sdhc0_lpcg IMX_LPCG_CLK_4>,
+ <&sdhc0_lpcg IMX_LPCG_CLK_0>,
+ <&sdhc0_lpcg IMX_LPCG_CLK_5>;
clock-names = "ipg", "per", "ahb";
};
diff --git a/include/dt-bindings/clock/imx8-lpcg.h b/include/dt-bindings/clock/imx8-lpcg.h
new file mode 100644
index 0000000..df90aad
--- /dev/null
+++ b/include/dt-bindings/clock/imx8-lpcg.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2019 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#define IMX_LPCG_CLK_0 0
+#define IMX_LPCG_CLK_1 4
+#define IMX_LPCG_CLK_2 8
+#define IMX_LPCG_CLK_3 12
+#define IMX_LPCG_CLK_4 16
+#define IMX_LPCG_CLK_5 20
+#define IMX_LPCG_CLK_6 24
+#define IMX_LPCG_CLK_7 28
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH V5 06/11] clk: imx: scu: add runtime pm support
From: Dong Aisheng @ 2019-09-10 2:10 UTC (permalink / raw)
To: linux-clk
Cc: Dong Aisheng, sboyd, mturquette, linux-imx, kernel, fabio.estevam,
shawnguo, linux-arm-kernel
In-Reply-To: <1568081408-26800-1-git-send-email-aisheng.dong@nxp.com>
Add runtime pm support
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Michael Turquette <mturquette@baylibre.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v4->v5: no changes
v3: new patch
---
drivers/clk/imx/clk-scu.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c
index 5b6ed89..04a0514 100644
--- a/drivers/clk/imx/clk-scu.c
+++ b/drivers/clk/imx/clk-scu.c
@@ -11,6 +11,7 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include "clk-scu.h"
@@ -450,15 +451,32 @@ static int imx_clk_scu_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct imx_scu_clk_node *clk = dev_get_platdata(dev);
struct clk_hw *hw;
+ int ret;
+
+ pm_runtime_set_suspended(dev);
+ pm_runtime_set_autosuspend_delay(dev, 50);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_enable(dev);
+
+ ret = pm_runtime_get_sync(dev);
+ if (ret) {
+ pm_runtime_disable(dev);
+ return ret;
+ }
- hw = __imx_clk_scu(NULL, clk->name, clk->parents, clk->num_parents,
+ hw = __imx_clk_scu(dev, clk->name, clk->parents, clk->num_parents,
clk->rsrc, clk->clk_type);
- if (IS_ERR(hw))
+ if (IS_ERR(hw)) {
+ pm_runtime_disable(dev);
return PTR_ERR(hw);
+ }
clk->hw = hw;
list_add_tail(&clk->node, &imx_scu_clks[clk->rsrc]);
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
+
dev_dbg(dev, "register SCU clock rsrc:%d type:%d\n", clk->rsrc,
clk->clk_type);
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH V5 05/11] clk: imx: scu: allow scu clk to take device pointer
From: Dong Aisheng @ 2019-09-10 2:10 UTC (permalink / raw)
To: linux-clk
Cc: Dong Aisheng, sboyd, mturquette, linux-imx, kernel, fabio.estevam,
shawnguo, linux-arm-kernel
In-Reply-To: <1568081408-26800-1-git-send-email-aisheng.dong@nxp.com>
Used to support runtime pm.
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Michael Turquette <mturquette@baylibre.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v4->v5:
* no changes
v3->v4:
* add the missing dev poninter when call __imx_clk_scu in probe
v3: new patch
---
drivers/clk/imx/clk-scu.c | 9 +++++----
drivers/clk/imx/clk-scu.h | 9 +++++----
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c
index 85afe30..5b6ed89 100644
--- a/drivers/clk/imx/clk-scu.c
+++ b/drivers/clk/imx/clk-scu.c
@@ -384,8 +384,9 @@ static const struct clk_ops clk_scu_cpu_ops = {
.unprepare = clk_scu_unprepare,
};
-struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
- int num_parents, u32 rsrc_id, u8 clk_type)
+struct clk_hw *__imx_clk_scu(struct device *dev, const char *name,
+ const char * const *parents, int num_parents,
+ u32 rsrc_id, u8 clk_type)
{
struct clk_init_data init;
struct clk_scu *clk;
@@ -419,7 +420,7 @@ struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
clk->hw.init = &init;
hw = &clk->hw;
- ret = clk_hw_register(NULL, hw);
+ ret = clk_hw_register(dev, hw);
if (ret) {
kfree(clk);
hw = ERR_PTR(ret);
@@ -450,7 +451,7 @@ static int imx_clk_scu_probe(struct platform_device *pdev)
struct imx_scu_clk_node *clk = dev_get_platdata(dev);
struct clk_hw *hw;
- hw = __imx_clk_scu(clk->name, clk->parents, clk->num_parents,
+ hw = __imx_clk_scu(NULL, clk->name, clk->parents, clk->num_parents,
clk->rsrc, clk->clk_type);
if (IS_ERR(hw))
return PTR_ERR(hw);
diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h
index 819dc32..a2c6b42 100644
--- a/drivers/clk/imx/clk-scu.h
+++ b/drivers/clk/imx/clk-scu.h
@@ -20,8 +20,9 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
const char * const *parents,
int num_parents, u32 rsrc_id, u8 clk_type);
-struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
- int num_parents, u32 rsrc_id, u8 clk_type);
+struct clk_hw *__imx_clk_scu(struct device *dev, const char *name,
+ const char * const *parents, int num_parents,
+ u32 rsrc_id, u8 clk_type);
static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id,
u8 clk_type)
@@ -29,7 +30,7 @@ static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id,
if (clock_cells == 2)
return imx_clk_scu_alloc_dev(name, NULL, 0, rsrc_id, clk_type);
else
- return __imx_clk_scu(name, NULL, 0, rsrc_id, clk_type);
+ return __imx_clk_scu(NULL, name, NULL, 0, rsrc_id, clk_type);
}
static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const *parents,
@@ -38,7 +39,7 @@ static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const *
if (clock_cells == 2)
return imx_clk_scu_alloc_dev(name, parents, num_parents, rsrc_id, clk_type);
else
- return __imx_clk_scu(name, parents, num_parents, rsrc_id, clk_type);
+ return __imx_clk_scu(NULL, name, parents, num_parents, rsrc_id, clk_type);
}
struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH V5 03/11] clk: imx: scu: add two cells binding support
From: Dong Aisheng @ 2019-09-10 2:10 UTC (permalink / raw)
To: linux-clk
Cc: Dong Aisheng, sboyd, mturquette, linux-imx, kernel, fabio.estevam,
shawnguo, linux-arm-kernel
In-Reply-To: <1568081408-26800-1-git-send-email-aisheng.dong@nxp.com>
This patch implements the new two cells binding for SCU clocks.
The usage is as follows:
clocks = <&uart0_clk IMX_SC_R_UART_0 IMX_SC_PM_CLK_PER>
Due to each SCU clock is associated with a power domain, without power
on the domain, the SCU clock can't work. So we create platform devices
for each domain clock respectively and manually attach the required domain
before register the clock devices, then we can register clocks in the
clock platform driver accordingly.
Note because we do not have power domain info in device tree and the SCU
resource ID is the same for power domain and clock, so we use resource ID
to find power domains.
Later, we will also use this clock platform driver to support suspend/resume
and runtime pm.
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Michael Turquette <mturquette@baylibre.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v4->v5:
* put node after using of_find_compatible_node()
* using ERR_PTR(ret) instead of ERR_PTR(-ENOMEM)
v4: no changes
v3: new patch
---
drivers/clk/imx/clk-imx8qxp.c | 9 ++-
drivers/clk/imx/clk-scu.c | 140 +++++++++++++++++++++++++++++++++++++++++-
drivers/clk/imx/clk-scu.h | 21 ++++++-
3 files changed, 163 insertions(+), 7 deletions(-)
diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c
index 5e2903e..1ad3f2a 100644
--- a/drivers/clk/imx/clk-imx8qxp.c
+++ b/drivers/clk/imx/clk-imx8qxp.c
@@ -24,7 +24,7 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
struct clk_hw **clks;
int ret, i;
- ret = imx_clk_scu_init();
+ ret = imx_clk_scu_init(ccm_node);
if (ret)
return ret;
@@ -134,7 +134,12 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
i, PTR_ERR(clks[i]));
}
- return of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data);
+ if (clock_cells == 2)
+ ret = of_clk_add_hw_provider(ccm_node, imx_scu_of_clk_src_get, imx_scu_clks);
+ else
+ ret = of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data);
+
+ return ret;
}
static const struct of_device_id imx8qxp_match[] = {
diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c
index fbef740..e4216bd 100644
--- a/drivers/clk/imx/clk-scu.c
+++ b/drivers/clk/imx/clk-scu.c
@@ -8,6 +8,9 @@
#include <linux/arm-smccc.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
#include <linux/slab.h>
#include "clk-scu.h"
@@ -16,6 +19,21 @@
#define IMX_SIP_SET_CPUFREQ 0x00
static struct imx_sc_ipc *ccm_ipc_handle;
+struct device_node *pd_np;
+u32 clock_cells;
+
+struct imx_scu_clk_node {
+ const char *name;
+ u32 rsrc;
+ u8 clk_type;
+ const char * const *parents;
+ int num_parents;
+
+ struct clk_hw *hw;
+ struct list_head node;
+};
+
+struct list_head imx_scu_clks[IMX_SC_R_LAST];
/*
* struct clk_scu - Description of one SCU clock
@@ -128,9 +146,31 @@ static inline struct clk_scu *to_clk_scu(struct clk_hw *hw)
return container_of(hw, struct clk_scu, hw);
}
-int imx_clk_scu_init(void)
+int imx_clk_scu_init(struct device_node *np)
{
- return imx_scu_get_handle(&ccm_ipc_handle);
+ struct platform_device *pd_dev;
+ int ret, i;
+
+ ret = imx_scu_get_handle(&ccm_ipc_handle);
+ if (ret)
+ return ret;
+
+ if (of_property_read_u32(np, "#clock-cells", &clock_cells))
+ return -EINVAL;
+
+ if (clock_cells == 2) {
+ for (i = 0; i < IMX_SC_R_LAST; i++)
+ INIT_LIST_HEAD(&imx_scu_clks[i]);
+
+ pd_np = of_find_compatible_node(NULL, NULL, "fsl,scu-pd");
+ pd_dev = of_find_device_by_node(pd_np);
+ if (!pd_dev || !device_is_bound(&pd_dev->dev)) {
+ of_node_put(pd_np);
+ return -EPROBE_DEFER;
+ }
+ }
+
+ return 0;
}
/*
@@ -387,3 +427,99 @@ struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
return hw;
}
+
+struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec,
+ void *data)
+{
+ unsigned int rsrc = clkspec->args[0];
+ unsigned int idx = clkspec->args[1];
+ struct list_head *scu_clks = data;
+ struct imx_scu_clk_node *clk;
+
+ list_for_each_entry(clk, &scu_clks[rsrc], node) {
+ if (clk->clk_type == idx)
+ return clk->hw;
+ }
+
+ return ERR_PTR(-ENODEV);
+}
+
+static int imx_clk_scu_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct imx_scu_clk_node *clk = dev_get_platdata(dev);
+ struct clk_hw *hw;
+
+ hw = __imx_clk_scu(clk->name, clk->parents, clk->num_parents,
+ clk->rsrc, clk->clk_type);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+
+ clk->hw = hw;
+ list_add_tail(&clk->node, &imx_scu_clks[clk->rsrc]);
+
+ dev_dbg(dev, "register SCU clock rsrc:%d type:%d\n", clk->rsrc,
+ clk->clk_type);
+
+ return 0;
+}
+
+static struct platform_driver imx_clk_scu_driver = {
+ .driver = {
+ .name = "imx-scu-clk",
+ .suppress_bind_attrs = true,
+ },
+ .probe = imx_clk_scu_probe,
+};
+builtin_platform_driver(imx_clk_scu_driver);
+
+static int imx_clk_scu_attach_pd(struct device *dev, u32 rsrc_id)
+{
+ struct of_phandle_args genpdspec = {
+ .np = pd_np,
+ .args_count = 1,
+ .args[0] = rsrc_id,
+ };
+
+ return of_genpd_add_device(&genpdspec, dev);
+}
+
+struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
+ const char * const *parents,
+ int num_parents, u32 rsrc_id, u8 clk_type)
+{
+ struct imx_scu_clk_node clk = {
+ .name = name,
+ .rsrc = rsrc_id,
+ .clk_type = clk_type,
+ .parents = parents,
+ .num_parents = num_parents,
+ };
+ struct platform_device *pdev;
+ int ret;
+
+ pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE);
+ if (!pdev) {
+ pr_err("%s: failed to allocate scu clk dev rsrc %d type %d\n",
+ name, rsrc_id, clk_type);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ ret = platform_device_add_data(pdev, &clk, sizeof(clk));
+ if (ret) {
+ platform_device_put(pdev);
+ return ERR_PTR(ret);
+ }
+
+ pdev->driver_override = "imx-scu-clk";
+
+ ret = imx_clk_scu_attach_pd(&pdev->dev, rsrc_id);
+ if (ret)
+ pr_warn("%s: failed to attached the power domain %d\n",
+ name, ret);
+
+ platform_device_add(pdev);
+
+ /* For API backwards compatiblilty, simply return NULL for success */
+ return NULL;
+}
diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h
index 2bcfaf0..819dc32 100644
--- a/drivers/clk/imx/clk-scu.h
+++ b/drivers/clk/imx/clk-scu.h
@@ -8,8 +8,17 @@
#define __IMX_CLK_SCU_H
#include <linux/firmware/imx/sci.h>
+#include <linux/of.h>
-int imx_clk_scu_init(void);
+extern u32 clock_cells;
+extern struct list_head imx_scu_clks[];
+
+int imx_clk_scu_init(struct device_node *np);
+struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec,
+ void *data);
+struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
+ const char * const *parents,
+ int num_parents, u32 rsrc_id, u8 clk_type);
struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
int num_parents, u32 rsrc_id, u8 clk_type);
@@ -17,13 +26,19 @@ struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id,
u8 clk_type)
{
- return __imx_clk_scu(name, NULL, 0, rsrc_id, clk_type);
+ if (clock_cells == 2)
+ return imx_clk_scu_alloc_dev(name, NULL, 0, rsrc_id, clk_type);
+ else
+ return __imx_clk_scu(name, NULL, 0, rsrc_id, clk_type);
}
static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const *parents,
int num_parents, u32 rsrc_id, u8 clk_type)
{
- return __imx_clk_scu(name, parents, num_parents, rsrc_id, clk_type);
+ if (clock_cells == 2)
+ return imx_clk_scu_alloc_dev(name, parents, num_parents, rsrc_id, clk_type);
+ else
+ return __imx_clk_scu(name, parents, num_parents, rsrc_id, clk_type);
}
struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH 2/3] soc: amazon: al-pos: Introduce Amazon's Annapurna Labs POS driver
From: Shenhar, Talel @ 2019-09-09 14:11 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Mark Rutland, mjourdan, Catalin Marinas, Linus Walleij,
linux-kernel@vger.kernel.org, jonnyc, Mauro Carvalho Chehab,
ronenk, Will Deacon, Benjamin Herrenschmidt, DTML, Maxime Ripard,
Rob Herring, Santosh Shilimkar, Thomas Gleixner, hanochu,
Linux ARM, barakw, hhhawa, gregkh, paul.kocialkowski,
Patrick Venture, Olof Johansson, David Miller, David Woodhouse
In-Reply-To: <CAK8P3a1NVGwYa1bw_vjBatd1xe-i875X1Vq1M+2G_Zxd2Oqusg@mail.gmail.com>
On 9/9/2019 4:41 PM, Arnd Bergmann wrote:
> On Mon, Sep 9, 2019 at 1:13 PM Shenhar, Talel <talel@amazon.com> wrote:
>> On 9/9/2019 12:44 PM, Arnd Bergmann wrote:
>>> On Mon, Sep 9, 2019 at 11:14 AM Talel Shenhar <talel@amazon.com> wrote:
>>>> + writel_relaxed(0, pos->mmio_base + AL_POS_ERROR_LOG_1);
>>> Why do you require _relaxed() accessors here? Please add a comment
>>> explaining that, or use the regular readl()/writel().
>> I don't think commenting is needed here as there is nothing special in
>> this type of access.
>>
>> I don't see this is common to comment the use of the _relaxed accessors.
> I usually mention it in driver reviews, but most authors revert back
> to the normal accessors when there is no difference.
>
>> This driver is for SoC using arm64 cpu.
>>
>> If one uses the non-relaxed version of readl while running on arm64, he
>> shall cause read barrier, which is then doing dsm(ld).. This barrier is
>> not needed here, so we spare the use of the more heavy readl in favor of
>> the less "harmful" one.
>>
>> Let me know what you think.
> If the barrier causes no harm, just leave it in to keep the code more
> readable. Most developers don't need to know the difference between
> the two, so using the less common interface just makes the reader
> curious about why it was picked.
>
> Avoiding the barrier can make a huge performance difference in a
> hot code path, but the downside is that it can behave in unexpected
> ways if the same code is run on a different CPU architecture that
> does not have the exact same rules about what _relaxed() means.
>
> In fact, replacing a 'readl()' with 'readl_relaxed() + rmb()' can lead
> to slower rather than faster code when the explicit barrier is heavier
> than the implied one (e.g. on x86), or readl_relaxed() does not skip
> the barrier.
>
> The general rule with kernel interfaces when you have two versions
> that both do what you want is to pick the one with the shorter name.
> See spin_lock()/spin_lock_irqsave(), ioremap()/ioremap_nocache(),
> or ktime_get()/ktime_get_clocktai_ts64(). (yes, there are also
> exceptions)
>
> Arnd
Thanks for the detailed response.
In current implementation of v1, I am not doing any read barrier, Hence,
using the non-relaxed will add unneeded memory barrier.
I have no strong objection moving to the non-relaxed version and have an
unneeded memory barrier, as this path is not "hot" one.
Beside of avoiding the unneeded memory barrier, I would be happy to keep
common behavior for our drivers:
e.g.
https://github.com/torvalds/linux/blob/master/drivers/irqchip/irq-al-fic.c#L49
So what do you think we should go with? relaxed or non-relaxed?
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH V5 01/11] dt-bindings: firmware: imx-scu: new binding to parse clocks from device tree
From: Dong Aisheng @ 2019-09-10 2:09 UTC (permalink / raw)
To: linux-clk
Cc: Dong Aisheng, devicetree, sboyd, mturquette, linux-imx, kernel,
fabio.estevam, shawnguo, linux-arm-kernel
In-Reply-To: <1568081408-26800-1-git-send-email-aisheng.dong@nxp.com>
There's a few limitations on the original one cell clock binding
(#clock-cells = <1>) that we have to define some SW clock IDs for device
tree to reference. This may cause troubles if we want to use common
clock IDs for multi platforms support when the clock of those platforms
are mostly the same.
e.g. Current clock IDs name are defined with SS prefix.
However the device may reside in different SS across CPUs, that means the
SS prefix may not valid anymore for a new SoC. Furthermore, the device
availability of those clocks may also vary a bit.
For such situation, we want to eliminate the using of SW Clock IDs and
change to use a more close to HW one instead.
For SCU clocks usage, only two params required: Resource id + Clock Type.
Both parameters are platform independent. So we could use two cells binding
to pass those parameters,
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: devicetree@vger.kernel.org
Acked-by: Shawn Guo <shawnguo@kernel.org>
Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v3->v4:
* add some comments for various clock types
v2->v3:
* Changed to two cells binding and register all clocks in driver
instead of parse from device tree.
v1->v2:
* changed to one cell binding inspired by arm,scpi.txt
Documentation/devicetree/bindings/arm/arm,scpi.txt
Resource ID is encoded in 'reg' property.
Clock type is encoded in generic clock-indices property.
Then we don't have to search all the DT nodes to fetch
those two value to construct clocks which is relatively
low efficiency.
* Add required power-domain property as well.
---
.../devicetree/bindings/arm/freescale/fsl,scu.txt | 12 ++++++-----
include/dt-bindings/firmware/imx/rsrc.h | 23 ++++++++++++++++++++++
2 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
index a575e42..8cee5bf 100644
--- a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
+++ b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
@@ -89,7 +89,10 @@ Required properties:
"fsl,imx8qm-clock"
"fsl,imx8qxp-clock"
followed by "fsl,scu-clk"
-- #clock-cells: Should be 1. Contains the Clock ID value.
+- #clock-cells: Should be either
+ 2: Contains the Resource and Clock ID value.
+ or
+ 1: Contains the Clock ID value. (DEPRECATED)
- clocks: List of clock specifiers, must contain an entry for
each required entry in clock-names
- clock-names: Should include entries "xtal_32KHz", "xtal_24MHz"
@@ -184,7 +187,7 @@ firmware {
clk: clk {
compatible = "fsl,imx8qxp-clk", "fsl,scu-clk";
- #clock-cells = <1>;
+ #clock-cells = <2>;
};
iomuxc {
@@ -229,8 +232,7 @@ serial@5a060000 {
...
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lpuart0>;
- clocks = <&clk IMX8QXP_UART0_CLK>,
- <&clk IMX8QXP_UART0_IPG_CLK>;
- clock-names = "per", "ipg";
+ clocks = <&uart0_clk IMX_SC_R_UART_0 IMX_SC_PM_CLK_PER>;
+ clock-names = "ipg";
power-domains = <&pd IMX_SC_R_UART_0>;
};
diff --git a/include/dt-bindings/firmware/imx/rsrc.h b/include/dt-bindings/firmware/imx/rsrc.h
index 4e61f64..24c153d 100644
--- a/include/dt-bindings/firmware/imx/rsrc.h
+++ b/include/dt-bindings/firmware/imx/rsrc.h
@@ -547,4 +547,27 @@
#define IMX_SC_R_ATTESTATION 545
#define IMX_SC_R_LAST 546
+/*
+ * Defines for SC PM CLK
+ */
+
+/* Normal device resource clock */
+#define IMX_SC_PM_CLK_SLV_BUS 0 /* Slave bus clock */
+#define IMX_SC_PM_CLK_MST_BUS 1 /* Master bus clock */
+#define IMX_SC_PM_CLK_PER 2 /* Peripheral clock */
+#define IMX_SC_PM_CLK_PHY 3 /* Phy clock */
+#define IMX_SC_PM_CLK_MISC 4 /* Misc clock */
+
+/* Special clock types which do not belong to above normal clock types */
+#define IMX_SC_PM_CLK_MISC0 0 /* Misc 0 clock */
+#define IMX_SC_PM_CLK_MISC1 1 /* Misc 1 clock */
+#define IMX_SC_PM_CLK_MISC2 2 /* Misc 2 clock */
+#define IMX_SC_PM_CLK_MISC3 3 /* Misc 3 clock */
+#define IMX_SC_PM_CLK_MISC4 4 /* Misc 4 clock */
+
+/* Special clock types for CPU/PLL/BYPASS only */
+#define IMX_SC_PM_CLK_CPU 2 /* CPU clock */
+#define IMX_SC_PM_CLK_PLL 4 /* PLL */
+#define IMX_SC_PM_CLK_BYPASS 4 /* Bypass clock */
+
#endif /* __DT_BINDINGS_RSCRC_IMX_H */
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH V5 04/11] clk: imx: scu: bypass cpu power domains
From: Dong Aisheng @ 2019-09-10 2:10 UTC (permalink / raw)
To: linux-clk
Cc: Dong Aisheng, sboyd, mturquette, linux-imx, kernel, fabio.estevam,
shawnguo, linux-arm-kernel
In-Reply-To: <1568081408-26800-1-git-send-email-aisheng.dong@nxp.com>
Bypass cpu power domains which are owned by ATF.
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v5:
* remove unnecessary ()
v4: no changes
v3: new patch
---
drivers/clk/imx/clk-scu.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c
index e4216bd..85afe30 100644
--- a/drivers/clk/imx/clk-scu.c
+++ b/drivers/clk/imx/clk-scu.c
@@ -481,6 +481,10 @@ static int imx_clk_scu_attach_pd(struct device *dev, u32 rsrc_id)
.args[0] = rsrc_id,
};
+ if (rsrc_id == IMX_SC_R_A35 || rsrc_id == IMX_SC_R_A53 ||
+ rsrc_id == IMX_SC_R_A72)
+ return 0;
+
return of_genpd_add_device(&genpdspec, dev);
}
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH V5 00/11] clk: imx8: add new clock binding for better pm support
From: Dong Aisheng @ 2019-09-10 2:09 UTC (permalink / raw)
To: linux-clk
Cc: Dong Aisheng, sboyd, mturquette, linux-imx, kernel, fabio.estevam,
shawnguo, linux-arm-kernel
This is a follow up of this patch series.
https://patchwork.kernel.org/cover/10924029/
[V2,0/2] clk: imx: scu: add parsing clocks from device tree support
This patch series is a preparation for the MX8 Architecture improvement.
As for IMX SCU based platforms like MX8QM and MX8QXP, they are comprised
of a couple of SS(Subsystems) while most of them within the same SS
can be shared. e.g. Clocks, Devices and etc.
However, current clock binding is using SW IDs for device tree to use
which can cause troubles in writing the common <soc>-ss-xx.dtsi file for
different SoCs.
This patch series aims to introduce a new binding which is more close to
hardware and platform independent and can makes us write a more general
drivers for different SCU based SoCs.
Another important thing is that on MX8, each Clock resource is associated
with a power domain. So we have to attach that clock device to the power
domain in order to make it work properly. Further more, the clock state
will be lost when its power domain is completely off during suspend/resume,
so we also introduce the clock state save&restore mechanism.
ChangeLog:
v4->v5:
* Address many comments from Stephen
v3->v4:
* use clk-indices for LPCG to fetch each clks offset from dt
v2->v3:
* change scu clk into two cells binding
* add clk pm patches to ease the understand of the changes
v1->v2:
* SCU clock changed to one cell clock binding inspired by arm,scpi.txt
Documentation/devicetree/bindings/arm/arm,scpi.txt
* Add required power domain property
* Dropped PATCH 3&4 first, will send the updated version accordingly
after the binding is finally determined,
Dong Aisheng (11):
dt-bindings: firmware: imx-scu: new binding to parse clocks from
device tree
dt-bindings: clock: imx-lpcg: add support to parse clocks from device
tree
clk: imx: scu: add two cells binding support
clk: imx: scu: bypass cpu power domains
clk: imx: scu: allow scu clk to take device pointer
clk: imx: scu: add runtime pm support
clk: imx: scu: add suspend/resume support
clk: imx: imx8qxp-lpcg: add parsing clocks from device tree
clk: imx: lpcg: allow lpcg clk to take device pointer
clk: imx: clk-imx8qxp-lpcg: add runtime pm support
clk: imx: lpcg: add suspend/resume support
.../devicetree/bindings/arm/freescale/fsl,scu.txt | 12 +-
.../devicetree/bindings/clock/imx8qxp-lpcg.txt | 36 +++-
drivers/clk/imx/clk-imx8qxp-lpcg.c | 124 ++++++++++++
drivers/clk/imx/clk-imx8qxp.c | 9 +-
drivers/clk/imx/clk-lpcg-scu.c | 45 ++++-
drivers/clk/imx/clk-scu.c | 218 ++++++++++++++++++++-
drivers/clk/imx/clk-scu.h | 50 ++++-
include/dt-bindings/clock/imx8-lpcg.h | 14 ++
include/dt-bindings/firmware/imx/rsrc.h | 23 +++
9 files changed, 501 insertions(+), 30 deletions(-)
create mode 100644 include/dt-bindings/clock/imx8-lpcg.h
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH V5 08/11] clk: imx: imx8qxp-lpcg: add parsing clocks from device tree
From: Dong Aisheng @ 2019-09-10 2:10 UTC (permalink / raw)
To: linux-clk
Cc: Dong Aisheng, sboyd, mturquette, linux-imx, kernel, fabio.estevam,
shawnguo, linux-arm-kernel
In-Reply-To: <1568081408-26800-1-git-send-email-aisheng.dong@nxp.com>
One LPCG controller supports up to 8 clock outputs while each of them
is fixed to 4 bits. It supports only gating function with fixed bits.
So we can use the clk-indices to fetch the corresponding clock idx from
device tree. With this way, we can write a generic LPCG clock drivers.
This patch add that support to parse clocks from device tree.
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Michael Turquette <mturquette@baylibre.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
Changelog:
v4->v5:
* add more commit message
* a few minor updates
v3->v4:
* remove hw_autogate which is not still used by driver
* use clock-indices to indicate LPCG clock bit offset
v1->v3: no changes
---
drivers/clk/imx/clk-imx8qxp-lpcg.c | 103 +++++++++++++++++++++++++++++++++++++
1 file changed, 103 insertions(+)
diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c
index c0aff7c..31efc7a 100644
--- a/drivers/clk/imx/clk-imx8qxp-lpcg.c
+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c
@@ -9,6 +9,7 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -157,6 +158,101 @@ static const struct imx8qxp_ss_lpcg imx8qxp_ss_lsio = {
.num_max = IMX_LSIO_LPCG_CLK_END,
};
+#define IMX_LPCG_MAX_CLKS 8
+
+static struct clk_hw *imx_lpcg_of_clk_src_get(struct of_phandle_args *clkspec,
+ void *data)
+{
+ struct clk_hw_onecell_data *hw_data = data;
+ unsigned int idx = clkspec->args[0] / 4;
+
+ if (idx >= hw_data->num) {
+ pr_err("%s: invalid index %u\n", __func__, idx);
+ return ERR_PTR(-EINVAL);
+ }
+
+ return hw_data->hws[idx];
+}
+
+static int imx_lpcg_parse_clks_from_dt(struct platform_device *pdev,
+ struct device_node *np)
+{
+ const char *output_names[IMX_LPCG_MAX_CLKS];
+ const char *parent_names[IMX_LPCG_MAX_CLKS];
+ unsigned int bit_offset[IMX_LPCG_MAX_CLKS];
+ struct clk_hw_onecell_data *clk_data;
+ struct clk_hw **clk_hws;
+ struct resource *res;
+ void __iomem *base;
+ int count;
+ int idx;
+ int ret;
+ int i;
+
+ if (!of_device_is_compatible(np, "fsl,imx8qxp-lpcg"))
+ return -EINVAL;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ count = of_property_count_u32_elems(np, "clock-indices");
+ if (count < 0) {
+ dev_err(&pdev->dev, "failed to count clocks\n");
+ return -EINVAL;
+ }
+
+ clk_data = devm_kzalloc(&pdev->dev, struct_size(clk_data, hws,
+ IMX_LPCG_MAX_CLKS), GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+
+ clk_data->num = IMX_LPCG_MAX_CLKS;
+ clk_hws = clk_data->hws;
+
+ ret = of_property_read_u32_array(np, "clock-indices", bit_offset,
+ count);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to read clock-indices\n");
+ return -EINVAL;
+ }
+
+ ret = of_clk_parent_fill(np, parent_names, count);
+ if (ret != count) {
+ dev_err(&pdev->dev, "failed to get clock parent names\n");
+ return count;
+ }
+
+ ret = of_property_read_string_array(np, "clock-output-names",
+ output_names, count);
+ if (ret != count) {
+ dev_err(&pdev->dev, "failed to read clock-output-names\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < count; i++) {
+ idx = bit_offset[i] / 4;
+ if (idx > IMX_LPCG_MAX_CLKS) {
+ dev_warn(&pdev->dev, "invalid bit offset of clock %d\n",
+ i);
+ return -EINVAL;
+ }
+
+ clk_hws[idx] = imx_clk_lpcg_scu(output_names[i],
+ parent_names[i], 0, base,
+ bit_offset[i], false);
+ if (IS_ERR(clk_hws[idx])) {
+ dev_warn(&pdev->dev, "failed to register clock %d\n",
+ idx);
+ return -EINVAL;
+ }
+ }
+
+ return devm_of_clk_add_hw_provider(&pdev->dev, imx_lpcg_of_clk_src_get,
+ clk_data);
+}
+
static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -167,8 +263,14 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
struct resource *res;
struct clk_hw **clks;
void __iomem *base;
+ int ret;
int i;
+ /* try new binding to parse clocks from device tree first */
+ ret = imx_lpcg_parse_clks_from_dt(pdev, np);
+ if (!ret)
+ return 0;
+
ss_lpcg = of_device_get_match_data(dev);
if (!ss_lpcg)
return -ENODEV;
@@ -208,6 +310,7 @@ static const struct of_device_id imx8qxp_lpcg_match[] = {
{ .compatible = "fsl,imx8qxp-lpcg-adma", &imx8qxp_ss_adma, },
{ .compatible = "fsl,imx8qxp-lpcg-conn", &imx8qxp_ss_conn, },
{ .compatible = "fsl,imx8qxp-lpcg-lsio", &imx8qxp_ss_lsio, },
+ { .compatible = "fsl,imx8qxp-lpcg", NULL },
{ /* sentinel */ }
};
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH V5 07/11] clk: imx: scu: add suspend/resume support
From: Dong Aisheng @ 2019-09-10 2:10 UTC (permalink / raw)
To: linux-clk
Cc: Dong Aisheng, sboyd, mturquette, linux-imx, kernel, fabio.estevam,
shawnguo, linux-arm-kernel
In-Reply-To: <1568081408-26800-1-git-send-email-aisheng.dong@nxp.com>
Clock state will be lost when its power domain is completely off
during system suspend/resume. So we save and restore the state
accordingly in suspend/resume callback.
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Michael Turquette <mturquette@baylibre.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v5:
* make suspend/resume function static
v4: no changes
v3: new patch
---
drivers/clk/imx/clk-scu.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c
index 04a0514..000ce6e 100644
--- a/drivers/clk/imx/clk-scu.c
+++ b/drivers/clk/imx/clk-scu.c
@@ -46,6 +46,10 @@ struct clk_scu {
struct clk_hw hw;
u16 rsrc_id;
u8 clk_type;
+
+ /* for state save&restore */
+ bool is_enabled;
+ u32 rate;
};
/*
@@ -427,6 +431,9 @@ struct clk_hw *__imx_clk_scu(struct device *dev, const char *name,
hw = ERR_PTR(ret);
}
+ if (dev)
+ dev_set_drvdata(dev, clk);
+
return hw;
}
@@ -483,10 +490,52 @@ static int imx_clk_scu_probe(struct platform_device *pdev)
return 0;
}
+static int __maybe_unused imx_clk_scu_suspend(struct device *dev)
+{
+ struct clk_scu *clk = dev_get_drvdata(dev);
+
+ clk->rate = clk_hw_get_rate(&clk->hw);
+ clk->is_enabled = clk_hw_is_enabled(&clk->hw);
+
+ if (clk->rate)
+ dev_dbg(dev, "save rate %d\n", clk->rate);
+
+ if (clk->is_enabled)
+ dev_dbg(dev, "save enabled state\n");
+
+ return 0;
+}
+
+static int __maybe_unused imx_clk_scu_resume(struct device *dev)
+{
+ struct clk_scu *clk = dev_get_drvdata(dev);
+ int ret = 0;
+
+ if (clk->rate) {
+ ret = clk_scu_set_rate(&clk->hw, clk->rate, 0);
+ dev_dbg(dev, "restore rate %d %s\n", clk->rate,
+ !ret ? "success" : "failed");
+ }
+
+ if (clk->is_enabled) {
+ ret = clk_scu_prepare(&clk->hw);
+ dev_dbg(dev, "restore enabled state %s\n",
+ !ret ? "success" : "failed");
+ }
+
+ return ret;
+}
+
+static const struct dev_pm_ops imx_clk_scu_pm_ops = {
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_scu_suspend,
+ imx_clk_scu_resume)
+};
+
static struct platform_driver imx_clk_scu_driver = {
.driver = {
.name = "imx-scu-clk",
.suppress_bind_attrs = true,
+ .pm = &imx_clk_scu_pm_ops,
},
.probe = imx_clk_scu_probe,
};
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH V5 09/11] clk: imx: lpcg: allow lpcg clk to take device pointer
From: Dong Aisheng @ 2019-09-10 2:10 UTC (permalink / raw)
To: linux-clk
Cc: Dong Aisheng, sboyd, mturquette, linux-imx, kernel, fabio.estevam,
shawnguo, linux-arm-kernel
In-Reply-To: <1568081408-26800-1-git-send-email-aisheng.dong@nxp.com>
Used to support runtime pm.
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v4->v5: no changes
v3: new patch
---
drivers/clk/imx/clk-lpcg-scu.c | 8 ++++----
drivers/clk/imx/clk-scu.h | 23 ++++++++++++++++++++---
2 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c
index a73a799..3c092a0 100644
--- a/drivers/clk/imx/clk-lpcg-scu.c
+++ b/drivers/clk/imx/clk-lpcg-scu.c
@@ -80,9 +80,9 @@ static const struct clk_ops clk_lpcg_scu_ops = {
.disable = clk_lpcg_scu_disable,
};
-struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
- unsigned long flags, void __iomem *reg,
- u8 bit_idx, bool hw_gate)
+struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 bit_idx, bool hw_gate)
{
struct clk_lpcg_scu *clk;
struct clk_init_data init;
@@ -106,7 +106,7 @@ struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
clk->hw.init = &init;
hw = &clk->hw;
- ret = clk_hw_register(NULL, hw);
+ ret = clk_hw_register(dev, hw);
if (ret) {
kfree(clk);
hw = ERR_PTR(ret);
diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h
index a2c6b42..84efda3 100644
--- a/drivers/clk/imx/clk-scu.h
+++ b/drivers/clk/imx/clk-scu.h
@@ -24,6 +24,10 @@ struct clk_hw *__imx_clk_scu(struct device *dev, const char *name,
const char * const *parents, int num_parents,
u32 rsrc_id, u8 clk_type);
+struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 bit_idx, bool hw_gate);
+
static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id,
u8 clk_type)
{
@@ -42,7 +46,20 @@ static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const *
return __imx_clk_scu(NULL, name, parents, num_parents, rsrc_id, clk_type);
}
-struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
- unsigned long flags, void __iomem *reg,
- u8 bit_idx, bool hw_gate);
+static inline struct clk_hw *imx_clk_lpcg_scu_dev(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 bit_idx, bool hw_gate)
+{
+ return __imx_clk_lpcg_scu(dev, name, parent_name, flags, reg,
+ bit_idx, hw_gate);
+}
+
+static inline struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
+ unsigned long flags, void __iomem *reg,
+ u8 bit_idx, bool hw_gate)
+{
+ return __imx_clk_lpcg_scu(NULL, name, parent_name, flags, reg,
+ bit_idx, hw_gate);
+}
+
#endif
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH V5 10/11] clk: imx: clk-imx8qxp-lpcg: add runtime pm support
From: Dong Aisheng @ 2019-09-10 2:10 UTC (permalink / raw)
To: linux-clk
Cc: Dong Aisheng, sboyd, mturquette, linux-imx, kernel, fabio.estevam,
shawnguo, linux-arm-kernel
In-Reply-To: <1568081408-26800-1-git-send-email-aisheng.dong@nxp.com>
add runtime pm support
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v4->v5:
* no changes
v3->v4:
* disable rpm when error out
v3: new patch
---
drivers/clk/imx/clk-imx8qxp-lpcg.c | 34 +++++++++++++++++++++++++++-------
1 file changed, 27 insertions(+), 7 deletions(-)
diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c
index 31efc7a..f395eb5 100644
--- a/drivers/clk/imx/clk-imx8qxp-lpcg.c
+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c
@@ -12,6 +12,7 @@
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include "clk-scu.h"
@@ -231,26 +232,45 @@ static int imx_lpcg_parse_clks_from_dt(struct platform_device *pdev,
return -EINVAL;
}
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
for (i = 0; i < count; i++) {
idx = bit_offset[i] / 4;
if (idx > IMX_LPCG_MAX_CLKS) {
dev_warn(&pdev->dev, "invalid bit offset of clock %d\n",
i);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
- clk_hws[idx] = imx_clk_lpcg_scu(output_names[i],
- parent_names[i], 0, base,
- bit_offset[i], false);
+ clk_hws[idx] = imx_clk_lpcg_scu_dev(&pdev->dev, output_names[i],
+ parent_names[i], 0, base,
+ bit_offset[i], false);
if (IS_ERR(clk_hws[idx])) {
dev_warn(&pdev->dev, "failed to register clock %d\n",
idx);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
}
- return devm_of_clk_add_hw_provider(&pdev->dev, imx_lpcg_of_clk_src_get,
- clk_data);
+ ret = devm_of_clk_add_hw_provider(&pdev->dev, imx_lpcg_of_clk_src_get,
+ clk_data);
+ if (ret)
+ goto out;
+
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
+
+ return 0;
+
+out:
+ pm_runtime_disable(&pdev->dev);
+ return ret;
}
static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH V5 11/11] clk: imx: lpcg: add suspend/resume support
From: Dong Aisheng @ 2019-09-10 2:10 UTC (permalink / raw)
To: linux-clk
Cc: Dong Aisheng, sboyd, mturquette, linux-imx, kernel, fabio.estevam,
shawnguo, linux-arm-kernel
In-Reply-To: <1568081408-26800-1-git-send-email-aisheng.dong@nxp.com>
LPCG clock state may be lost when it's power domain is completely
off during system suspend/resume and we need save and restore the
state properly.
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v5:
* make suspend/resume function static
* improve code comments
v4: no changes
v3: new patch
---
drivers/clk/imx/clk-imx8qxp-lpcg.c | 1 +
drivers/clk/imx/clk-lpcg-scu.c | 37 +++++++++++++++++++++++++++++++++++++
drivers/clk/imx/clk-scu.h | 1 +
3 files changed, 39 insertions(+)
diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c
index f395eb5..99a5f55 100644
--- a/drivers/clk/imx/clk-imx8qxp-lpcg.c
+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c
@@ -338,6 +338,7 @@ static struct platform_driver imx8qxp_lpcg_clk_driver = {
.driver = {
.name = "imx8qxp-lpcg-clk",
.of_match_table = imx8qxp_lpcg_match,
+ .pm = &imx_clk_lpcg_scu_pm_ops,
.suppress_bind_attrs = true,
},
.probe = imx8qxp_lpcg_clk_probe,
diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c
index 3c092a0..1dd928a 100644
--- a/drivers/clk/imx/clk-lpcg-scu.c
+++ b/drivers/clk/imx/clk-lpcg-scu.c
@@ -33,6 +33,9 @@ struct clk_lpcg_scu {
void __iomem *reg;
u8 bit_idx;
bool hw_gate;
+
+ /* for state save&restore */
+ u32 state;
};
#define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw)
@@ -112,5 +115,39 @@ struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name,
hw = ERR_PTR(ret);
}
+ if (dev)
+ dev_set_drvdata(dev, clk);
+
return hw;
}
+
+static int __maybe_unused imx_clk_lpcg_scu_suspend(struct device *dev)
+{
+ struct clk_lpcg_scu *clk = dev_get_drvdata(dev);
+
+ clk->state = readl_relaxed(clk->reg);
+ dev_dbg(dev, "save lpcg state 0x%x\n", clk->state);
+
+ return 0;
+}
+
+static int __maybe_unused imx_clk_lpcg_scu_resume(struct device *dev)
+{
+ struct clk_lpcg_scu *clk = dev_get_drvdata(dev);
+
+ /*
+ * FIXME: Sometimes writes don't work unless the CPU issues
+ * them twice
+ */
+
+ writel(clk->state, clk->reg);
+ writel(clk->state, clk->reg);
+ dev_dbg(dev, "restore lpcg state 0x%x\n", clk->state);
+
+ return 0;
+}
+
+const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops = {
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_lpcg_scu_suspend,
+ imx_clk_lpcg_scu_resume)
+};
diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h
index 84efda3..6d4b6e2 100644
--- a/drivers/clk/imx/clk-scu.h
+++ b/drivers/clk/imx/clk-scu.h
@@ -12,6 +12,7 @@
extern u32 clock_cells;
extern struct list_head imx_scu_clks[];
+extern const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops;
int imx_clk_scu_init(struct device_node *np);
struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec,
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH v3] gpio/mpc8xxx: change irq handler from chained to normal
From: Fabio Estevam @ 2019-09-09 14:14 UTC (permalink / raw)
To: Hui Song
Cc: Mark Rutland,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list:GPIO SUBSYSTEM, Linus Walleij, linux-kernel, Li Yang,
Bartosz Golaszewski, Rob Herring, Shawn Guo,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20190909021214.25646-1-hui.song_1@nxp.com>
Hi Song,
On Mon, Sep 9, 2019 at 11:12 AM Hui Song <hui.song_1@nxp.com> wrote:
> static void mpc8xxx_irq_unmask(struct irq_data *d)
> @@ -409,8 +409,14 @@ static int mpc8xxx_probe(struct platform_device *pdev)
> if (devtype->gpio_dir_in_init)
> devtype->gpio_dir_in_init(gc);
>
> - irq_set_chained_handler_and_data(mpc8xxx_gc->irqn,
> - mpc8xxx_gpio_irq_cascade, mpc8xxx_gc);
> + ret = request_irq(mpc8xxx_gc->irqn, mpc8xxx_gpio_irq_cascade,
> + IRQF_NO_THREAD | IRQF_SHARED, "gpio-cascade", mpc8xxx_gc);
> + if (ret) {
> + pr_err("%s: failed to request_irq(%d), ret = %d\n",
In drivers, it is preferred to use dev_err() instead of pr_err().
Please swicth for dev_err().
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* RE: [PATCH V5 00/11] clk: imx8: add new clock binding for better pm support
From: Aisheng Dong @ 2019-09-09 14:19 UTC (permalink / raw)
To: Aisheng Dong, linux-clk@vger.kernel.org
Cc: sboyd@kernel.org, mturquette@baylibre.com, Oliver Graute,
dl-linux-imx, kernel@pengutronix.de, Fabio Estevam,
shawnguo@kernel.org, linux-arm-kernel@lists.infradead.org
In-Reply-To: <1568081408-26800-1-git-send-email-aisheng.dong@nxp.com>
> This patch series is a preparation for the MX8 Architecture improvement.
> As for IMX SCU based platforms like MX8QM and MX8QXP, they are comprised
> of a couple of SS(Subsystems) while most of them within the same SS can be
> shared. e.g. Clocks, Devices and etc.
>
> However, current clock binding is using SW IDs for device tree to use which can
> cause troubles in writing the common <soc>-ss-xx.dtsi file for different SoCs.
>
> This patch series aims to introduce a new binding which is more close to
> hardware and platform independent and can makes us write a more general
> drivers for different SCU based SoCs.
>
> Another important thing is that on MX8, each Clock resource is associated with
> a power domain. So we have to attach that clock device to the power domain
> in order to make it work properly. Further more, the clock state will be lost
> when its power domain is completely off during suspend/resume, so we also
> introduce the clock state save&restore mechanism.
>
For this patch series, missed to add Oliver's former tag:
Tested-by: Oliver Graute <oliver.graute@kococonnector.com>
Regards
Aisheng
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 01/15] arm64: dts: imx8qxp: add fallback compatible string for scu pd
From: Dong Aisheng @ 2019-09-09 14:27 UTC (permalink / raw)
To: Oliver Graute
Cc: Dong Aisheng, devicetree, Catalin Marinas, Will Deacon,
Rob Herring, dl-linux-imx, Sascha Hauer, Fabio Estevam,
Mark Rutland, Shawn Guo,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20190829102009.GA22728@optiplex>
Hi Oliver,
On Thu, Aug 29, 2019 at 6:20 PM Oliver Graute <oliver.graute@gmail.com> wrote:
>
> On 16/07/19, Dong Aisheng wrote:
> > According to binding doc, add the fallback compatible string for
> > scu pd.
>
> This Patch series (v2) is running fine for some weeks on my iMX8QM Board.
>
> So feel free to use my Tag:
> Tested-by: Oliver Graute <oliver.graute@kococonnector.com>
>
> Will there be an updated version of this Patch series which apply on
> latest linux next?
Thanks for the test.
I have a local version, will rebase to latest next and resend.
Regards
Aisheng
>
> Best Regards,
>
> Oliver
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v9 6/8] mm: Introduce Reported pages
From: Kirill A. Shutemov @ 2019-09-09 14:42 UTC (permalink / raw)
To: Alexander Duyck
Cc: yang.zhang.wz, pagupta, kvm, david, catalin.marinas, mhocko,
linux-mm, alexander.h.duyck, will, aarcange, virtio-dev, mst,
willy, wei.w.wang, ying.huang, riel, dan.j.williams, lcapitulino,
linux-arm-kernel, osalvador, nitesh, konrad.wilk, dave.hansen,
linux-kernel, pbonzini, akpm, fengguang.wu, kirill.shutemov
In-Reply-To: <20190907172553.10910.72962.stgit@localhost.localdomain>
On Sat, Sep 07, 2019 at 10:25:53AM -0700, Alexander Duyck wrote:
> From: Alexander Duyck <alexander.h.duyck@linux.intel.com>
>
> In order to pave the way for free page reporting in virtualized
> environments we will need a way to get pages out of the free lists and
> identify those pages after they have been returned. To accomplish this,
> this patch adds the concept of a Reported Buddy, which is essentially
> meant to just be the Uptodate flag used in conjunction with the Buddy
> page type.
>
> It adds a set of pointers we shall call "boundary" which represents the
> upper boundary between the unreported and reported pages. The general idea
> is that in order for a page to cross from one side of the boundary to the
> other it will need to go through the reporting process. Ultimately a
> free_list has been fully processed when the boundary has been moved from
> the tail all they way up to occupying the first entry in the list.
>
> Doing this we should be able to make certain that we keep the reported
> pages as one contiguous block in each free list. This will allow us to
> efficiently manipulate the free lists whenever we need to go in and start
> sending reports to the hypervisor that there are new pages that have been
> freed and are no longer in use.
>
> An added advantage to this approach is that we should be reducing the
> overall memory footprint of the guest as it will be more likely to recycle
> warm pages versus trying to allocate the reported pages that were likely
> evicted from the guest memory.
>
> Since we will only be reporting one zone at a time we keep the boundary
> limited to being defined for just the zone we are currently reporting pages
> from. Doing this we can keep the number of additional pointers needed quite
> small. To flag that the boundaries are in place we use a single bit
> in the zone to indicate that reporting and the boundaries are active.
>
> The determination of when to start reporting is based on the tracking of
> the number of free pages in a given area versus the number of reported
> pages in that area. We keep track of the number of reported pages per
> free_area in a separate zone specific area. We do this to avoid modifying
> the free_area structure as this can lead to false sharing for the highest
> order with the zone lock which leads to a noticeable performance
> degradation.
>
> Signed-off-by: Alexander Duyck <alexander.h.duyck@linux.intel.com>
> ---
> include/linux/mmzone.h | 52 +++++-
> include/linux/page-flags.h | 11 +
> include/linux/page_reporting.h | 178 ++++++++++++++++++++
> mm/Kconfig | 5 +
> mm/Makefile | 1
> mm/memory_hotplug.c | 1
> mm/page_alloc.c | 115 ++++++++++++-
> mm/page_reporting.c | 358 ++++++++++++++++++++++++++++++++++++++++
> 8 files changed, 711 insertions(+), 10 deletions(-)
> create mode 100644 include/linux/page_reporting.h
> create mode 100644 mm/page_reporting.c
>
> diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
> index 2ddf1f1971c0..4b2c44d7e266 100644
> --- a/include/linux/mmzone.h
> +++ b/include/linux/mmzone.h
> @@ -463,6 +463,14 @@ struct zone {
> seqlock_t span_seqlock;
> #endif
>
> +#ifdef CONFIG_PAGE_REPORTING
> + /*
> + * Pointer to reported page tracking statistics array. The size of
> + * the array is MAX_ORDER - PAGE_REPORTING_MIN_ORDER. NULL when
> + * unused page reporting is not present.
> + */
> + unsigned long *reported_pages;
> +#endif
> int initialized;
>
> /* Write-intensive fields used from the page allocator */
> @@ -538,6 +546,14 @@ enum zone_flags {
> ZONE_BOOSTED_WATERMARK, /* zone recently boosted watermarks.
> * Cleared when kswapd is woken.
> */
> + ZONE_PAGE_REPORTING_REQUESTED, /* zone enabled page reporting and has
> + * requested flushing the data out of
> + * higher order pages.
> + */
> + ZONE_PAGE_REPORTING_ACTIVE, /* zone enabled page reporting and is
> + * activly flushing the data out of
> + * higher order pages.
> + */
> };
>
> static inline unsigned long zone_managed_pages(struct zone *zone)
> @@ -764,6 +780,8 @@ static inline bool pgdat_is_empty(pg_data_t *pgdat)
> return !pgdat->node_start_pfn && !pgdat->node_spanned_pages;
> }
>
> +#include <linux/page_reporting.h>
> +
> /* Used for pages not on another list */
> static inline void add_to_free_list(struct page *page, struct zone *zone,
> unsigned int order, int migratetype)
> @@ -778,24 +796,48 @@ static inline void add_to_free_list(struct page *page, struct zone *zone,
> static inline void add_to_free_list_tail(struct page *page, struct zone *zone,
> unsigned int order, int migratetype)
> {
> - struct free_area *area = &zone->free_area[order];
> + struct list_head *tail = get_unreported_tail(zone, order, migratetype);
>
> - list_add_tail(&page->lru, &area->free_list[migratetype]);
> - area->nr_free++;
> + /*
> + * To prevent the unreported pages from being interleaved with the
> + * reported ones while we are actively processing pages we will use
> + * the head of the reported pages to determine the tail of the free
> + * list.
> + */
> + list_add_tail(&page->lru, tail);
> + zone->free_area[order].nr_free++;
> }
>
> /* Used for pages which are on another list */
> static inline void move_to_free_list(struct page *page, struct zone *zone,
> unsigned int order, int migratetype)
> {
> - struct free_area *area = &zone->free_area[order];
> + struct list_head *tail = get_unreported_tail(zone, order, migratetype);
> +
> + /*
> + * We must get the tail for our target list before moving the page on
> + * the reported list as we will possibly be replacing the tail page of
> + * the list with our current page if it is reported.
> + */
> + if (unlikely(PageReported(page)))
> + move_page_to_reported_list(page, zone, migratetype);
>
> - list_move(&page->lru, &area->free_list[migratetype]);
> + /*
> + * To prevent unreported pages from being mixed with the reported
> + * ones we add pages to the tail of the list. By doing this the function
> + * above can either label them as included in the reported list or not
> + * and the result will be consistent.
> + */
> + list_move_tail(&page->lru, tail);
> }
>
> static inline void del_page_from_free_list(struct page *page, struct zone *zone,
> unsigned int order)
> {
> + /* remove page from reported list, and clear reported state */
> + if (unlikely(PageReported(page)))
> + del_page_from_reported_list(page, zone);
> +
> list_del(&page->lru);
> __ClearPageBuddy(page);
> set_page_private(page, 0);
> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> index f91cb8898ff0..759a3b3956f2 100644
> --- a/include/linux/page-flags.h
> +++ b/include/linux/page-flags.h
> @@ -163,6 +163,9 @@ enum pageflags {
>
> /* non-lru isolated movable page */
> PG_isolated = PG_reclaim,
> +
> + /* Buddy pages. Used to track which pages have been reported */
> + PG_reported = PG_uptodate,
> };
>
> #ifndef __GENERATING_BOUNDS_H
> @@ -432,6 +435,14 @@ static inline bool set_hwpoison_free_buddy_page(struct page *page)
> #endif
>
> /*
> + * PageReported() is used to track reported free pages within the Buddy
> + * allocator. We can use the non-atomic version of the test and set
> + * operations as both should be shielded with the zone lock to prevent
> + * any possible races on the setting or clearing of the bit.
> + */
> +__PAGEFLAG(Reported, reported, PF_NO_COMPOUND)
> +
> +/*
> * On an anonymous page mapped into a user virtual memory area,
> * page->mapping points to its anon_vma, not to a struct address_space;
> * with the PAGE_MAPPING_ANON bit set to distinguish it. See rmap.h.
> diff --git a/include/linux/page_reporting.h b/include/linux/page_reporting.h
> new file mode 100644
> index 000000000000..836033ca237b
> --- /dev/null
> +++ b/include/linux/page_reporting.h
> @@ -0,0 +1,178 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _LINUX_PAGE_REPORTING_H
> +#define _LINUX_PAGE_REPORTING_H
> +
> +#include <linux/mmzone.h>
> +#include <linux/jump_label.h>
> +#include <linux/pageblock-flags.h>
> +
> +#define PAGE_REPORTING_MIN_ORDER pageblock_order
> +#define PAGE_REPORTING_HWM 32
> +
> +#ifdef CONFIG_PAGE_REPORTING
> +struct page_reporting_dev_info {
> + /* function that alters pages to make them "reported" */
> + void (*report)(struct page_reporting_dev_info *phdev,
> + unsigned int nents);
> +
> + /* scatterlist containing pages to be processed */
> + struct scatterlist *sg;
> +
> + /*
> + * Upper limit on the number of pages that the react function
> + * expects to be placed into the batch list to be processed.
> + */
> + unsigned long capacity;
> +
> + /* work struct for processing reports */
> + struct delayed_work work;
> +
> + /*
> + * The number of zones requesting reporting, plus one additional if
> + * processing thread is active.
> + */
> + atomic_t refcnt;
> +};
> +
> +/* Boundary functions */
> +struct list_head *__page_reporting_get_boundary(unsigned int order,
> + int migratetype);
> +void page_reporting_del_from_boundary(struct page *page);
> +void page_reporting_add_to_boundary(struct page *page, int migratetype);
> +void page_reporting_move_to_boundary(struct page *page, struct zone *zone,
> + int migratetype);
> +
> +/* Reported page accessors, defined in page_alloc.c */
> +struct page *get_unreported_page(struct zone *zone, unsigned int order,
> + int migratetype);
> +void free_reported_page(struct page *page, unsigned int order);
> +
> +/* Tear-down and bring-up for page reporting devices */
> +void page_reporting_shutdown(struct page_reporting_dev_info *phdev);
> +int page_reporting_startup(struct page_reporting_dev_info *phdev);
> +
> +void __page_reporting_free_stats(struct zone *zone);
> +void __page_reporting_request(struct zone *zone);
> +
> +static inline void __del_page_from_reported_list(struct page *page,
> + struct zone *zone)
> +{
> + /* page_private will contain the page order, so just use it directly */
> + zone->reported_pages[page_private(page) - PAGE_REPORTING_MIN_ORDER]--;
> +
> + /* clear the flag so we can report on it when it returns */
> + __ClearPageReported(page);
> +}
> +#endif /* CONFIG_PAGE_REPORTING */
> +
> +/*
> + * Method for obtaining the tail of the free list. Using this allows for
> + * tail insertions of unreported pages into the region that is currently
> + * being scanned so as to avoid interleaving reported and unreported pages.
> + */
> +static inline struct list_head *
> +get_unreported_tail(struct zone *zone, unsigned int order, int migratetype)
> +{
> +#ifdef CONFIG_PAGE_REPORTING
> + if (order >= PAGE_REPORTING_MIN_ORDER &&
> + test_bit(ZONE_PAGE_REPORTING_ACTIVE, &zone->flags))
> + return __page_reporting_get_boundary(order, migratetype);
> +#endif
> + return &zone->free_area[order].free_list[migratetype];
> +}
> +
> +/*
> + * Functions for adding/removing pages from reported end of list.
> + * All of them expect the zone lock to be held to maintain
> + * consistency of the reported list as a subset of the free list.
> + */
> +static inline void add_page_to_reported_list(struct page *page,
> + struct zone *zone,
> + int order,
> + int migratetype)
> +{
> +#ifdef CONFIG_PAGE_REPORTING
Instead of ifdefing full body of the helpers, can we have two sets of
these helpres defined for CONFIG_PAGE_REPORTING and for
!CONFIG_PAGE_REPORTING cases?
Or can we get all this working with IS_ENABLED() instead of #ifdef?
> + /* flag page as reported */
> + __SetPageReported(page);
> +
> + /* update areated page accounting */
> + zone->reported_pages[order - PAGE_REPORTING_MIN_ORDER]++;
> +
> + /* update boundary of new migratetype and record it */
> + page_reporting_add_to_boundary(page, migratetype);
> +#endif
> +}
> +
> +static inline void del_page_from_reported_list(struct page *page,
> + struct zone *zone)
> +{
> +#ifdef CONFIG_PAGE_REPORTING
> + /* push boundary back if we removed the upper boundary */
> + if (test_bit(ZONE_PAGE_REPORTING_ACTIVE, &zone->flags))
> + page_reporting_del_from_boundary(page);
> +
> + __del_page_from_reported_list(page, zone);
> +#endif
> +}
> +
> +static inline void move_page_to_reported_list(struct page *page,
> + struct zone *zone,
> + int migratetype)
> +{
> +#ifdef CONFIG_PAGE_REPORTING
> + page_reporting_move_to_boundary(page, zone, migratetype);
> +#endif
> +}
> +
> +/* Free reported_pages and reset reported page tracking count to 0 */
> +static inline void page_reporting_reset(struct zone *zone)
> +{
> +#ifdef CONFIG_PAGE_REPORTING
> + if (zone->reported_pages)
> + __page_reporting_free_stats(zone);
> +#endif
> +}
> +
> +DECLARE_STATIC_KEY_FALSE(page_reporting_notify_enabled);
> +
> +/**
> + * page_reporting_notify_free - Free page notification to start page processing
> + * @zone: Pointer to current zone of last page processed
> + * @order: Order of last page added to zone
> + *
> + * This function is meant to act as a screener for __page_reporting_request
> + * which will determine if a give zone has crossed over the high-water mark
> + * that will justify us beginning page treatment. If we have crossed that
> + * threshold then it will start the process of pulling some pages and
> + * placing them in the batch list for treatment.
> + */
> +static inline void page_reporting_notify_free(struct zone *zone, int order)
> +{
> +#ifdef CONFIG_PAGE_REPORTING
> + unsigned long nr_reported;
> +
> + /* Called from hot path in __free_one_page() */
> + if (!static_branch_unlikely(&page_reporting_notify_enabled))
> + return;
> +
> + /* Limit notifications only to higher order pages */
> + if (order < PAGE_REPORTING_MIN_ORDER)
> + return;
> +
> + /* Do not bother with tests if we have already requested reporting */
> + if (test_bit(ZONE_PAGE_REPORTING_REQUESTED, &zone->flags))
> + return;
How is it not racy wrt page_reporting_fill()? Do we hold zone->lock or
something?
> +
> + /* If reported_pages is not populated, assume 0 */
> + nr_reported = zone->reported_pages ?
> + zone->reported_pages[order - PAGE_REPORTING_MIN_ORDER] : 0;
> +
> + /* Only request it if we have enough to begin the page reporting */
> + if (zone->free_area[order].nr_free < nr_reported + PAGE_REPORTING_HWM)
> + return;
> +
> + /* This is slow, but should be called very rarely */
> + __page_reporting_request(zone);
> +#endif
> +}
> +#endif /*_LINUX_PAGE_REPORTING_H */
> diff --git a/mm/Kconfig b/mm/Kconfig
> index a5dae9a7eb51..be1a5db50df5 100644
> --- a/mm/Kconfig
> +++ b/mm/Kconfig
> @@ -237,6 +237,11 @@ config COMPACTION
> linux-mm@kvack.org.
>
> #
> +# support for unused page reporting
> +config PAGE_REPORTING
> + bool
> +
> +#
Proper description for the config option?
> # support for page migration
> #
> config MIGRATION
> diff --git a/mm/Makefile b/mm/Makefile
> index d996846697ef..fc4fa17b6c83 100644
> --- a/mm/Makefile
> +++ b/mm/Makefile
> @@ -107,3 +107,4 @@ obj-$(CONFIG_PERCPU_STATS) += percpu-stats.o
> obj-$(CONFIG_ZONE_DEVICE) += memremap.o
> obj-$(CONFIG_HMM_MIRROR) += hmm.o
> obj-$(CONFIG_MEMFD_CREATE) += memfd.o
> +obj-$(CONFIG_PAGE_REPORTING) += page_reporting.o
> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
> index 49f7bf91c25a..cb71a7190682 100644
> --- a/mm/memory_hotplug.c
> +++ b/mm/memory_hotplug.c
> @@ -1613,6 +1613,7 @@ static int __ref __offline_pages(unsigned long start_pfn,
> if (!populated_zone(zone)) {
> zone_pcp_reset(zone);
> build_all_zonelists(NULL);
> + page_reporting_reset(zone);
> } else
> zone_pcp_update(zone);
>
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index f85dc1561b85..615aea24c082 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -68,6 +68,7 @@
> #include <linux/lockdep.h>
> #include <linux/nmi.h>
> #include <linux/psi.h>
> +#include <linux/page_reporting.h>
>
> #include <asm/sections.h>
> #include <asm/tlbflush.h>
> @@ -916,7 +917,7 @@ static inline struct capture_control *task_capc(struct zone *zone)
> static inline void __free_one_page(struct page *page,
> unsigned long pfn,
> struct zone *zone, unsigned int order,
> - int migratetype)
> + int migratetype, bool reported)
> {
> struct capture_control *capc = task_capc(zone);
> unsigned long uninitialized_var(buddy_pfn);
> @@ -991,11 +992,20 @@ static inline void __free_one_page(struct page *page,
> done_merging:
> set_page_order(page, order);
>
> - if (is_shuffle_order(order) ? shuffle_pick_tail() :
> - buddy_merge_likely(pfn, buddy_pfn, page, order))
> + if (reported ||
> + (is_shuffle_order(order) ? shuffle_pick_tail() :
> + buddy_merge_likely(pfn, buddy_pfn, page, order)))
> add_to_free_list_tail(page, zone, order, migratetype);
> else
> add_to_free_list(page, zone, order, migratetype);
> +
> + /*
> + * No need to notify on a reported page as the total count of
> + * unreported pages will not have increased since we have essentially
> + * merged the reported page with one or more unreported pages.
> + */
> + if (!reported)
> + page_reporting_notify_free(zone, order);
> }
>
> /*
> @@ -1306,7 +1316,7 @@ static void free_pcppages_bulk(struct zone *zone, int count,
> if (unlikely(isolated_pageblocks))
> mt = get_pageblock_migratetype(page);
>
> - __free_one_page(page, page_to_pfn(page), zone, 0, mt);
> + __free_one_page(page, page_to_pfn(page), zone, 0, mt, false);
> trace_mm_page_pcpu_drain(page, 0, mt);
> }
> spin_unlock(&zone->lock);
> @@ -1322,7 +1332,7 @@ static void free_one_page(struct zone *zone,
> is_migrate_isolate(migratetype))) {
> migratetype = get_pfnblock_migratetype(page, pfn);
> }
> - __free_one_page(page, pfn, zone, order, migratetype);
> + __free_one_page(page, pfn, zone, order, migratetype, false);
> spin_unlock(&zone->lock);
> }
>
> @@ -2184,6 +2194,101 @@ struct page *__rmqueue_smallest(struct zone *zone, unsigned int order,
> return NULL;
> }
>
> +#ifdef CONFIG_PAGE_REPORTING
> +/**
> + * free_reported_page - Return a now-reported page back where we got it
> + * @page: Page that was reported
> + * @order: Order of the reported page
> + *
> + * This function will pull the migratetype and order information out
> + * of the page and attempt to return it where it found it. If the page
> + * is added to the free list without changes we will mark it as being
> + * reported.
> + */
> +void free_reported_page(struct page *page, unsigned int order)
> +{
> + struct zone *zone = page_zone(page);
> + unsigned long pfn;
> + unsigned int mt;
> +
> + /* zone lock should be held when this function is called */
> + lockdep_assert_held(&zone->lock);
> +
> + pfn = page_to_pfn(page);
> + mt = get_pfnblock_migratetype(page, pfn);
> + __free_one_page(page, pfn, zone, order, mt, true);
> +
> + /*
> + * If page was not comingled with another page we can consider
> + * the result to be "reported" since part of the page hasn't been
> + * modified, otherwise we would need to report on the new larger
> + * page.
> + */
> + if (PageBuddy(page) && page_order(page) == order)
> + add_page_to_reported_list(page, zone, order, mt);
> +}
> +
> +/**
> + * get_unreported_page - Pull an unreported page from the free_list
> + * @zone: Zone to draw pages from
> + * @order: Order to draw pages from
> + * @mt: Migratetype to draw pages from
> + *
> + * This function will obtain a page from the free list. It will start by
> + * attempting to pull from the tail of the free list and if that is already
> + * reported on it will instead pull the head if that is unreported.
> + *
> + * The page will have the migrate type and order stored in the page
> + * metadata. While being processed the page will not be avaialble for
> + * allocation.
> + *
> + * Return: page pointer if raw page found, otherwise NULL
> + */
> +struct page *get_unreported_page(struct zone *zone, unsigned int order, int mt)
> +{
> + struct list_head *tail = get_unreported_tail(zone, order, mt);
> + struct free_area *area = &(zone->free_area[order]);
> + struct list_head *list = &area->free_list[mt];
> + struct page *page;
> +
> + /* zone lock should be held when this function is called */
> + lockdep_assert_held(&zone->lock);
> +
> + /* Find a page of the appropriate size in the preferred list */
> + page = list_last_entry(tail, struct page, lru);
> + list_for_each_entry_from_reverse(page, list, lru) {
> + /* If we entered this loop then the "raw" list isn't empty */
> +
> + /* If the page is reported try the head of the list */
> + if (PageReported(page)) {
> + page = list_first_entry(list, struct page, lru);
> +
> + /*
> + * If both the head and tail are reported then reset
> + * the boundary so that we read as an empty list
> + * next time and bail out.
> + */
> + if (PageReported(page)) {
> + page_reporting_add_to_boundary(page, mt);
> + break;
> + }
> + }
> +
> + del_page_from_free_list(page, zone, order);
> +
> + /*
> + * Page will not be available for allocation while we are
> + * processing it so update the freepage state.
> + */
> + __mod_zone_freepage_state(zone, -(1 << order), mt);
> +
> + return page;
> + }
> +
> + return NULL;
> +}
> +#endif /* CONFIG_PAGE_REPORTING */
> +
> /*
> * This array describes the order lists are fallen back to when
> * the free lists for the desirable migrate type are depleted
> diff --git a/mm/page_reporting.c b/mm/page_reporting.c
> new file mode 100644
> index 000000000000..a59ef53eb0b8
> --- /dev/null
> +++ b/mm/page_reporting.c
> @@ -0,0 +1,358 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <linux/mm.h>
> +#include <linux/mmzone.h>
> +#include <linux/page-isolation.h>
> +#include <linux/gfp.h>
> +#include <linux/export.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/scatterlist.h>
> +#include "internal.h"
> +
> +static struct page_reporting_dev_info __rcu *ph_dev_info __read_mostly;
> +struct list_head **boundary __read_mostly;
> +
> +static inline struct list_head **get_boundary_ptr(unsigned int order,
> + unsigned int migratetype)
> +{
> + return boundary +
> + (order - PAGE_REPORTING_MIN_ORDER) * MIGRATE_TYPES + migratetype;
> +}
> +
> +static void page_reporting_reset_boundary(struct zone *zone, unsigned int order,
> + unsigned int migratetype)
> +{
> + struct list_head **tail = get_boundary_ptr(order, migratetype);
> +
> + *tail = &zone->free_area[order].free_list[migratetype];
> +}
> +
> +#define for_each_reporting_migratetype_order(_order, _type) \
> + for (_order = MAX_ORDER; _order-- != PAGE_REPORTING_MIN_ORDER;) \
> + for (_type = MIGRATE_TYPES; _type--;) \
> + if (!is_migrate_isolate(_type))
> +
> +static int page_reporting_populate_metadata(struct zone *zone)
> +{
> + unsigned int order, mt;
> +
> + /*
> + * We need to make sure we have somewhere to store the tracking
> + * data for how many reported pages are in the zone. To do that
> + * we need to make certain zone->reported_pages is populated.
> + */
> + if (!zone->reported_pages) {
> + zone->reported_pages =
> + kcalloc(MAX_ORDER - PAGE_REPORTING_MIN_ORDER,
> + sizeof(unsigned long),
> + GFP_KERNEL);
> + if (!zone->reported_pages)
> + return -ENOMEM;
> + }
> +
> + /* Update boundary data to reflect the zone we are currently working */
> + for_each_reporting_migratetype_order(order, mt)
> + page_reporting_reset_boundary(zone, order, mt);
> +
> + return 0;
> +}
> +
> +struct list_head *__page_reporting_get_boundary(unsigned int order,
> + int migratetype)
> +{
> + return *get_boundary_ptr(order, migratetype);
> +}
> +
> +void page_reporting_del_from_boundary(struct page *page)
> +{
> + unsigned int order = page_private(page);
> + int mt = get_pcppage_migratetype(page);
> + struct list_head **tail = get_boundary_ptr(order, mt);
> +
> + if (*tail == &page->lru)
> + *tail = page->lru.next;
> +}
> +
> +void page_reporting_add_to_boundary(struct page *page, int migratetype)
> +{
> + unsigned int order = page_private(page);
> + struct list_head **tail = get_boundary_ptr(order, migratetype);
> +
> + *tail = &page->lru;
> + set_pcppage_migratetype(page, migratetype);
> +}
> +
> +void page_reporting_move_to_boundary(struct page *page, struct zone *zone,
> + int dest_mt)
> +{
> + /*
> + * We essentially have two options available to us. The first is to
> + * move the page from the boundary list on one migratetype to the
> + * list for the new migratetype assuming reporting is still active.
> + *
> + * The other option is to clear the reported state of the page as
> + * we will not be adding it to the group of pages that were already
> + * reported. It is cheaper to just rereport such pages then go
> + * through and do a special search to skip over them. If the page
> + * is being moved into isolation we can defer this until the page
> + * comes out of isolation since we do not scan the isolated
> + * migratetype.
> + */
> + if (test_bit(ZONE_PAGE_REPORTING_ACTIVE, &zone->flags)) {
> + page_reporting_del_from_boundary(page);
> + page_reporting_add_to_boundary(page, dest_mt);
> + } else if (!is_migrate_isolate(dest_mt)) {
> + __del_page_from_reported_list(page, zone);
> + }
> +}
> +
> +static unsigned int page_reporting_fill(struct zone *zone,
> + struct page_reporting_dev_info *phdev)
> +{
> + struct scatterlist *sg = phdev->sg;
> + unsigned int order, mt, count = 0;
> +
> + sg_init_table(phdev->sg, phdev->capacity);
> +
> + for_each_reporting_migratetype_order(order, mt) {
> + struct page *page;
> +
> + /*
> + * Pull pages from free list until we have drained
> + * it or we have reached capacity.
> + */
> + while ((page = get_unreported_page(zone, order, mt))) {
> + sg_set_page(&sg[count], page, PAGE_SIZE << order, 0);
> +
> + if (++count == phdev->capacity)
> + return count;
> + }
> + }
> +
> + /* mark end of scatterlist due to underflow */
> + if (count)
> + sg_mark_end(&sg[count - 1]);
> +
> + /*
> + * If there are no longer enough free pages to fully populate
> + * the scatterlist, then we can just shut it down for this zone.
> + */
> + __clear_bit(ZONE_PAGE_REPORTING_REQUESTED, &zone->flags);
> + atomic_dec(&phdev->refcnt);
> +
> + return count;
> +}
> +
> +static void page_reporting_drain(struct page_reporting_dev_info *phdev)
> +{
> + struct scatterlist *sg = phdev->sg;
> +
> + /*
> + * Drain the now reported pages back into their respective
> + * free lists/areas. We assume at least one page is populated.
> + */
> + do {
> + free_reported_page(sg_page(sg), get_order(sg->length));
> + } while (!sg_is_last(sg++));
> +}
> +
> +/*
> + * The page reporting cycle consists of 4 stages, fill, report, drain, and idle.
> + * We will cycle through the first 3 stages until we fail to obtain any
> + * pages, in that case we will switch to idle.
> + */
> +static void page_reporting_cycle(struct zone *zone,
> + struct page_reporting_dev_info *phdev)
> +{
> + /*
> + * Guarantee boundaries and stats are populated before we
> + * start placing reported pages in the zone.
> + */
> + if (page_reporting_populate_metadata(zone))
> + return;
> +
> + spin_lock_irq(&zone->lock);
> +
> + /* set bit indicating boundaries are present */
> + __set_bit(ZONE_PAGE_REPORTING_ACTIVE, &zone->flags);
> +
> + do {
> + /* Pull pages out of allocator into a scaterlist */
> + unsigned int nents = page_reporting_fill(zone, phdev);
> +
> + /* no pages were acquired, give up */
> + if (!nents)
> + break;
> +
> + spin_unlock_irq(&zone->lock);
> +
> + /* begin processing pages in local list */
> + phdev->report(phdev, nents);
> +
> + spin_lock_irq(&zone->lock);
> +
> + /*
> + * We should have a scatterlist of pages that have been
> + * processed. Return them to their original free lists.
> + */
> + page_reporting_drain(phdev);
> +
> + /* keep pulling pages till there are none to pull */
> + } while (test_bit(ZONE_PAGE_REPORTING_REQUESTED, &zone->flags));
> +
> + /* processing of the zone is complete, we can disable boundaries */
> + __clear_bit(ZONE_PAGE_REPORTING_ACTIVE, &zone->flags);
> +
> + spin_unlock_irq(&zone->lock);
> +}
> +
> +static void page_reporting_process(struct work_struct *work)
> +{
> + struct delayed_work *d_work = to_delayed_work(work);
> + struct page_reporting_dev_info *phdev =
> + container_of(d_work, struct page_reporting_dev_info, work);
> + struct zone *zone = first_online_pgdat()->node_zones;
> +
> + do {
> + if (test_bit(ZONE_PAGE_REPORTING_REQUESTED, &zone->flags))
> + page_reporting_cycle(zone, phdev);
> +
> + /* Move to next zone, if at end of list start over */
> + zone = next_zone(zone) ? : first_online_pgdat()->node_zones;
> +
> + /*
> + * As long as refcnt has not reached zero there are still
> + * zones to be processed.
> + */
> + } while (atomic_read(&phdev->refcnt));
> +}
> +
> +/* request page reporting on this zone */
> +void __page_reporting_request(struct zone *zone)
> +{
> + struct page_reporting_dev_info *phdev;
> +
> + rcu_read_lock();
> +
> + /*
> + * We use RCU to protect the ph_dev_info pointer. In almost all
> + * cases this should be present, however in the unlikely case of
> + * a shutdown this will be NULL and we should exit.
> + */
> + phdev = rcu_dereference(ph_dev_info);
> + if (unlikely(!phdev))
> + goto out;
> +
> + /*
> + * We can use separate test and set operations here as there
> + * is nothing else that can set or clear this bit while we are
> + * holding the zone lock. The advantage to doing it this way is
> + * that we don't have to dirty the cacheline unless we are
> + * changing the value.
> + */
> + __set_bit(ZONE_PAGE_REPORTING_REQUESTED, &zone->flags);
> +
> + /*
> + * Delay the start of work to allow a sizable queue to
> + * build. For now we are limiting this to running no more
> + * than 10 times per second.
> + */
> + if (!atomic_fetch_inc(&phdev->refcnt))
> + schedule_delayed_work(&phdev->work, HZ / 10);
> +out:
> + rcu_read_unlock();
> +}
> +
> +void __page_reporting_free_stats(struct zone *zone)
> +{
> + /* free reported_page statisitics */
> + kfree(zone->reported_pages);
> + zone->reported_pages = NULL;
> +}
> +
> +static DEFINE_MUTEX(page_reporting_mutex);
> +DEFINE_STATIC_KEY_FALSE(page_reporting_notify_enabled);
> +
> +void page_reporting_shutdown(struct page_reporting_dev_info *phdev)
> +{
> + mutex_lock(&page_reporting_mutex);
> +
> + if (rcu_access_pointer(ph_dev_info) == phdev) {
> + /* Disable page reporting notification */
> + static_branch_disable(&page_reporting_notify_enabled);
> + RCU_INIT_POINTER(ph_dev_info, NULL);
> + synchronize_rcu();
> +
> + /* Flush any existing work, and lock it out */
> + cancel_delayed_work_sync(&phdev->work);
> +
> + /* Free scatterlist */
> + kfree(phdev->sg);
> + phdev->sg = NULL;
> +
> + /* Free boundaries */
> + kfree(boundary);
> + boundary = NULL;
> + }
> +
> + mutex_unlock(&page_reporting_mutex);
> +}
> +EXPORT_SYMBOL_GPL(page_reporting_shutdown);
> +
> +int page_reporting_startup(struct page_reporting_dev_info *phdev)
> +{
> + struct zone *zone;
> + int err = 0;
> +
> + /* No point in enabling this if it cannot handle any pages */
> + if (!phdev->capacity)
> + return -EINVAL;
Looks like a usage error. Maybe WARN_ON()?
> +
> + mutex_lock(&page_reporting_mutex);
> +
> + /* nothing to do if already in use */
> + if (rcu_access_pointer(ph_dev_info)) {
> + err = -EBUSY;
> + goto err_out;
> + }
Again, it's from "something went horribly wrong" category.
Maybe WARN_ON()?
> +
> + boundary = kcalloc(MAX_ORDER - PAGE_REPORTING_MIN_ORDER,
> + sizeof(struct list_head *) * MIGRATE_TYPES,
> + GFP_KERNEL);
Could you comment here on why this size of array is allocated?
The calculation is not obvious to a reader.
> + if (!boundary) {
> + err = -ENOMEM;
> + goto err_out;
> + }
> +
> + /* allocate scatterlist to store pages being reported on */
> + phdev->sg = kcalloc(phdev->capacity, sizeof(*phdev->sg), GFP_KERNEL);
> + if (!phdev->sg) {
> + err = -ENOMEM;
> +
> + kfree(boundary);
> + boundary = NULL;
> +
> + goto err_out;
> + }
> +
> +
> + /* initialize refcnt and work structures */
> + atomic_set(&phdev->refcnt, 0);
> + INIT_DELAYED_WORK(&phdev->work, &page_reporting_process);
> +
> + /* assign device, and begin initial flush of populated zones */
> + rcu_assign_pointer(ph_dev_info, phdev);
> + for_each_populated_zone(zone) {
> + spin_lock_irq(&zone->lock);
> + __page_reporting_request(zone);
> + spin_unlock_irq(&zone->lock);
> + }
> +
> + /* enable page reporting notification */
> + static_branch_enable(&page_reporting_notify_enabled);
> +err_out:
> + mutex_unlock(&page_reporting_mutex);
> +
> + return err;
> +}
> +EXPORT_SYMBOL_GPL(page_reporting_startup);
>
>
--
Kirill A. Shutemov
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 0/6] arm64: meson-gx: misc fixes and updates
From: Christian Hewitt @ 2019-09-09 15:01 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Kevin Hilman, devicetree,
linux-arm-kernel, linux-amlogic, linux-kernel
Cc: Chrisitian Hewitt
This patchset:
- Fixes bluetooth on Khadas VIM2
- Fixes bluetooth on Khadas VIM
- Fixes GPIO key dt on Khadas VIM
- Updates model for AML-S805X-CC
- Updates model/compatible for AML-S905X-CC
Christian Hewitt (6):
arm64: dts: meson-gxl-s905x-khadas-vim: fix gpio-keys-polled node
arm64: dts: meson-gxl-s905x-khadas-vim: fix uart_A bluetooth node
arm64: dts: meson-gxm-khadas-vim2: fix uart_A bluetooth node
arm64: dts: meson: libretech-ac: update model description
dt-bindings: arm: amlogic: update libretech-cc compatible
arm64: dts: meson: libretech-cc: update model and compatible
Documentation/devicetree/bindings/arm/amlogic.yaml | 2 +-
arch/arm64/boot/dts/amlogic/meson-gxl-s805x-libretech-ac.dts | 2 +-
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts | 7 ++++---
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts | 5 +++--
arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts | 3 +++
5 files changed, 12 insertions(+), 7 deletions(-)
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 2/6] arm64: dts: meson-gxl-s905x-khadas-vim: fix uart_A bluetooth node
From: Christian Hewitt @ 2019-09-09 15:01 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Kevin Hilman, devicetree,
linux-arm-kernel, linux-amlogic, linux-kernel
Cc: Chrisitian Hewitt
In-Reply-To: <1568041287-7805-1-git-send-email-christianshewitt@gmail.com>
Fixes: dd5297cc8b8 ("arm64: dts: meson-gxl-s905x-khadas-vim enable Bluetooth")
Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
---
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
index 41be2af..2ab7d84 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
@@ -190,6 +190,9 @@
bluetooth {
compatible = "brcm,bcm43438-bt";
shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
+ max-speed = <2000000>;
+ clocks = <&wifi32k>;
+ clock-names = "lpo";
};
};
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 1/6] arm64: dts: meson-gxl-s905x-khadas-vim: fix gpio-keys-polled node
From: Christian Hewitt @ 2019-09-09 15:01 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Kevin Hilman, devicetree,
linux-arm-kernel, linux-amlogic, linux-kernel
Cc: Chrisitian Hewitt
In-Reply-To: <1568041287-7805-1-git-send-email-christianshewitt@gmail.com>
Fix DTC warnings:
arch/arm/dts/meson-gxl-s905x-khadas-vim.dtb: Warning (avoid_unnecessary_addr_size):
/gpio-keys-polled: unnecessary #address-cells/#size-cells
without "ranges" or child "reg" property
Fixes: e15d2774b8c ("ARM64: dts: meson-gxl: add support for the Khadas VIM board")
Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
---
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
index 5499e8d..41be2af 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
@@ -33,11 +33,9 @@
gpio-keys-polled {
compatible = "gpio-keys-polled";
- #address-cells = <1>;
- #size-cells = <0>;
poll-interval = <100>;
- button@0 {
+ power-button {
label = "power";
linux,code = <KEY_POWER>;
gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_LOW>;
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
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