* [PATCH v6 0/5] Add CPSW2G and CPSW9G nodes for J784S4
From: Chintan Vankar @ 2024-03-29 5:31 UTC (permalink / raw)
To: Conor Dooley, Krzysztof Kozlowski, Rob Herring, Tero Kristo,
Vignesh Raghavendra, Nishanth Menon
Cc: linux-kernel, devicetree, linux-arm-kernel, s-vadapalli,
Chintan Vankar
This series adds device-tree nodes for CPSW2G and CPSW9G instance
of the CPSW Ethernet Switch on TI's J784S4 SoC. Additionally,
two device-tree overlays are also added:
1. QSGMII mode with the CPSW9G instance via the ENET EXPANSION 1
connector.
2. USXGMII mode with MAC Ports 1 and 2 of the CPSW9G instance via
ENET EXPANSION 1 and 2 connectors, configured in fixed-link
mode of operation at 5Gbps link speed.
Link to v5:
https://lore.kernel.org/r/20240314072129.1520475-1-c-vankar@ti.com/
Changes from v5 to v6:
- Updated order of properties in Device Nodes based on
https://docs.kernel.org/devicetree/bindings/dts-coding-style.html#order-of-properties-in-device-node
Chintan Vankar (1):
arm64: dts: ti: k3-j784s4-evm: Add alias for MCU CPSW2G
Siddharth Vadapalli (4):
arm64: dts: ti: k3-j784s4-main: Add CPSW2G and CPSW9G nodes
arm64: dts: ti: k3-j784s4-evm: Enable Main CPSW2G node and add aliases
for it
arm64: dts: ti: k3-j784s4: Add overlay to enable QSGMII mode with
CPSW9G
arm64: dts: ti: k3-j784s4: Add overlay for dual port USXGMII mode
arch/arm64/boot/dts/ti/Makefile | 11 +-
.../ti/k3-j784s4-evm-quad-port-eth-exp1.dtso | 147 ++++++++++++++
.../ti/k3-j784s4-evm-usxgmii-exp1-exp2.dtso | 81 ++++++++
arch/arm64/boot/dts/ti/k3-j784s4-evm.dts | 51 +++++
arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi | 187 ++++++++++++++++++
5 files changed, 476 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/boot/dts/ti/k3-j784s4-evm-quad-port-eth-exp1.dtso
create mode 100644 arch/arm64/boot/dts/ti/k3-j784s4-evm-usxgmii-exp1-exp2.dtso
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v6 2/5] arm64: dts: ti: k3-j784s4-main: Add CPSW2G and CPSW9G nodes
From: Chintan Vankar @ 2024-03-29 5:31 UTC (permalink / raw)
To: Conor Dooley, Krzysztof Kozlowski, Rob Herring, Tero Kristo,
Vignesh Raghavendra, Nishanth Menon
Cc: linux-kernel, devicetree, linux-arm-kernel, s-vadapalli,
Chintan Vankar
In-Reply-To: <20240329053130.2822129-1-c-vankar@ti.com>
From: Siddharth Vadapalli <s-vadapalli@ti.com>
J784S4 SoC has MAIN CPSW2G and CPSW9G instances of the CPSW
Ethernet Switch. CPSW2G has 1 external port and 1 host port
while CPSW9G has 8 external ports and 1 host port.
Add device-tree nodes for MAIN CPSW2G and CPSW9G and disable
them by default. MAIN CPSW2G will be enabled in the board file
while device-tree overlays will be used to enable CPSW9G.
Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
Signed-off-by: Chintan Vankar <c-vankar@ti.com>
---
Link to v5:
https://lore.kernel.org/r/20240314072129.1520475-3-c-vankar@ti.com/
Changes from v5 to v6:
- Updated order of properties in Device Nodes based on
https://docs.kernel.org/devicetree/bindings/dts-coding-style.html#order-of-properties-in-device-node
arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi | 187 +++++++++++++++++++++
1 file changed, 187 insertions(+)
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
index b67c37460a73..7dfa43d25d38 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
@@ -48,6 +48,19 @@ scm_conf: bus@100000 {
#size-cells = <1>;
ranges = <0x00 0x00 0x00100000 0x1c000>;
+ cpsw1_phy_gmii_sel: phy@4034 {
+ compatible = "ti,am654-phy-gmii-sel";
+ reg = <0x4034 0x4>;
+ #phy-cells = <1>;
+ };
+
+ cpsw0_phy_gmii_sel: phy@4044 {
+ compatible = "ti,j784s4-cpsw9g-phy-gmii-sel";
+ reg = <0x4044 0x20>;
+ #phy-cells = <1>;
+ ti,qsgmii-main-ports = <7>, <7>;
+ };
+
serdes_ln_ctrl: mux-controller@4080 {
compatible = "reg-mux";
reg = <0x00004080 0x30>;
@@ -1439,6 +1452,180 @@ cpts@310d0000 {
};
};
+ main_cpsw0: ethernet@c000000 {
+ compatible = "ti,j784s4-cpswxg-nuss";
+ reg = <0x00 0xc000000 0x00 0x200000>;
+ reg-names = "cpsw_nuss";
+ ranges = <0x00 0x00 0x00 0xc000000 0x00 0x200000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ dma-coherent;
+ clocks = <&k3_clks 64 0>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 64 TI_SCI_PD_EXCLUSIVE>;
+
+ dmas = <&main_udmap 0xca00>,
+ <&main_udmap 0xca01>,
+ <&main_udmap 0xca02>,
+ <&main_udmap 0xca03>,
+ <&main_udmap 0xca04>,
+ <&main_udmap 0xca05>,
+ <&main_udmap 0xca06>,
+ <&main_udmap 0xca07>,
+ <&main_udmap 0x4a00>;
+ dma-names = "tx0", "tx1", "tx2", "tx3",
+ "tx4", "tx5", "tx6", "tx7",
+ "rx";
+
+ status = "disabled";
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ main_cpsw0_port1: port@1 {
+ reg = <1>;
+ label = "port1";
+ ti,mac-only;
+ status = "disabled";
+ };
+
+ main_cpsw0_port2: port@2 {
+ reg = <2>;
+ label = "port2";
+ ti,mac-only;
+ status = "disabled";
+ };
+
+ main_cpsw0_port3: port@3 {
+ reg = <3>;
+ label = "port3";
+ ti,mac-only;
+ status = "disabled";
+ };
+
+ main_cpsw0_port4: port@4 {
+ reg = <4>;
+ label = "port4";
+ ti,mac-only;
+ status = "disabled";
+ };
+
+ main_cpsw0_port5: port@5 {
+ reg = <5>;
+ label = "port5";
+ ti,mac-only;
+ status = "disabled";
+ };
+
+ main_cpsw0_port6: port@6 {
+ reg = <6>;
+ label = "port6";
+ ti,mac-only;
+ status = "disabled";
+ };
+
+ main_cpsw0_port7: port@7 {
+ reg = <7>;
+ label = "port7";
+ ti,mac-only;
+ status = "disabled";
+ };
+
+ main_cpsw0_port8: port@8 {
+ reg = <8>;
+ label = "port8";
+ ti,mac-only;
+ status = "disabled";
+ };
+ };
+
+ main_cpsw0_mdio: mdio@f00 {
+ compatible = "ti,cpsw-mdio","ti,davinci_mdio";
+ reg = <0x00 0xf00 0x00 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&k3_clks 64 0>;
+ clock-names = "fck";
+ bus_freq = <1000000>;
+ status = "disabled";
+ };
+
+ cpts@3d000 {
+ compatible = "ti,am65-cpts";
+ reg = <0x00 0x3d000 0x00 0x400>;
+ clocks = <&k3_clks 64 3>;
+ clock-names = "cpts";
+ interrupts-extended = <&gic500 GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "cpts";
+ ti,cpts-ext-ts-inputs = <4>;
+ ti,cpts-periodic-outputs = <2>;
+ };
+ };
+
+ main_cpsw1: ethernet@c200000 {
+ compatible = "ti,j721e-cpsw-nuss";
+ reg = <0x00 0xc200000 0x00 0x200000>;
+ reg-names = "cpsw_nuss";
+ ranges = <0x00 0x00 0x00 0xc200000 0x00 0x200000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ dma-coherent;
+ clocks = <&k3_clks 62 0>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 62 TI_SCI_PD_EXCLUSIVE>;
+
+ dmas = <&main_udmap 0xc640>,
+ <&main_udmap 0xc641>,
+ <&main_udmap 0xc642>,
+ <&main_udmap 0xc643>,
+ <&main_udmap 0xc644>,
+ <&main_udmap 0xc645>,
+ <&main_udmap 0xc646>,
+ <&main_udmap 0xc647>,
+ <&main_udmap 0x4640>;
+ dma-names = "tx0", "tx1", "tx2", "tx3",
+ "tx4", "tx5", "tx6", "tx7",
+ "rx";
+
+ status = "disabled";
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ main_cpsw1_port1: port@1 {
+ reg = <1>;
+ label = "port1";
+ phys = <&cpsw1_phy_gmii_sel 1>;
+ ti,mac-only;
+ status = "disabled";
+ };
+ };
+
+ main_cpsw1_mdio: mdio@f00 {
+ compatible = "ti,cpsw-mdio", "ti,davinci_mdio";
+ reg = <0x00 0xf00 0x00 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&k3_clks 62 0>;
+ clock-names = "fck";
+ bus_freq = <1000000>;
+ status = "disabled";
+ };
+
+ cpts@3d000 {
+ compatible = "ti,am65-cpts";
+ reg = <0x00 0x3d000 0x00 0x400>;
+ clocks = <&k3_clks 62 3>;
+ clock-names = "cpts";
+ interrupts-extended = <&gic500 GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "cpts";
+ ti,cpts-ext-ts-inputs = <4>;
+ ti,cpts-periodic-outputs = <2>;
+ };
+ };
+
main_mcan0: can@2701000 {
compatible = "bosch,m_can";
reg = <0x00 0x02701000 0x00 0x200>,
--
2.34.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 v4 01/15] arch: Add ARCH_HAS_KERNEL_FPU_SUPPORT
From: Samuel Holland @ 2024-03-29 7:18 UTC (permalink / raw)
To: Andrew Morton, linux-arm-kernel, x86
Cc: linux-kernel, linux-arch, linuxppc-dev, linux-riscv,
Christoph Hellwig, loongarch, amd-gfx, Samuel Holland,
Borislav Petkov, Catalin Marinas, Dave Hansen, Huacai Chen,
Ingo Molnar, Jonathan Corbet, Masahiro Yamada, Nathan Chancellor,
Nicolas Schier, Russell King, Thomas Gleixner, Will Deacon,
linux-doc, linux-kbuild
In-Reply-To: <20240329072441.591471-1-samuel.holland@sifive.com>
Several architectures provide an API to enable the FPU and run
floating-point SIMD code in kernel space. However, the function names,
header locations, and semantics are inconsistent across architectures,
and FPU support may be gated behind other Kconfig options.
Provide a standard way for architectures to declare that kernel space
FPU support is available. Architectures selecting this option must
implement what is currently the most common API (kernel_fpu_begin() and
kernel_fpu_end(), plus a new function kernel_fpu_available()) and
provide the appropriate CFLAGS for compiling floating-point C code.
Suggested-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
---
(no changes since v2)
Changes in v2:
- Add documentation explaining the built-time and runtime APIs
- Add a linux/fpu.h header for generic isolation enforcement
Documentation/core-api/floating-point.rst | 78 +++++++++++++++++++++++
Documentation/core-api/index.rst | 1 +
Makefile | 5 ++
arch/Kconfig | 6 ++
include/linux/fpu.h | 12 ++++
5 files changed, 102 insertions(+)
create mode 100644 Documentation/core-api/floating-point.rst
create mode 100644 include/linux/fpu.h
diff --git a/Documentation/core-api/floating-point.rst b/Documentation/core-api/floating-point.rst
new file mode 100644
index 000000000000..a8d0d4b05052
--- /dev/null
+++ b/Documentation/core-api/floating-point.rst
@@ -0,0 +1,78 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Floating-point API
+==================
+
+Kernel code is normally prohibited from using floating-point (FP) registers or
+instructions, including the C float and double data types. This rule reduces
+system call overhead, because the kernel does not need to save and restore the
+userspace floating-point register state.
+
+However, occasionally drivers or library functions may need to include FP code.
+This is supported by isolating the functions containing FP code to a separate
+translation unit (a separate source file), and saving/restoring the FP register
+state around calls to those functions. This creates "critical sections" of
+floating-point usage.
+
+The reason for this isolation is to prevent the compiler from generating code
+touching the FP registers outside these critical sections. Compilers sometimes
+use FP registers to optimize inlined ``memcpy`` or variable assignment, as
+floating-point registers may be wider than general-purpose registers.
+
+Usability of floating-point code within the kernel is architecture-specific.
+Additionally, because a single kernel may be configured to support platforms
+both with and without a floating-point unit, FPU availability must be checked
+both at build time and at run time.
+
+Several architectures implement the generic kernel floating-point API from
+``linux/fpu.h``, as described below. Some other architectures implement their
+own unique APIs, which are documented separately.
+
+Build-time API
+--------------
+
+Floating-point code may be built if the option ``ARCH_HAS_KERNEL_FPU_SUPPORT``
+is enabled. For C code, such code must be placed in a separate file, and that
+file must have its compilation flags adjusted using the following pattern::
+
+ CFLAGS_foo.o += $(CC_FLAGS_FPU)
+ CFLAGS_REMOVE_foo.o += $(CC_FLAGS_NO_FPU)
+
+Architectures are expected to define one or both of these variables in their
+top-level Makefile as needed. For example::
+
+ CC_FLAGS_FPU := -mhard-float
+
+or::
+
+ CC_FLAGS_NO_FPU := -msoft-float
+
+Normal kernel code is assumed to use the equivalent of ``CC_FLAGS_NO_FPU``.
+
+Runtime API
+-----------
+
+The runtime API is provided in ``linux/fpu.h``. This header cannot be included
+from files implementing FP code (those with their compilation flags adjusted as
+above). Instead, it must be included when defining the FP critical sections.
+
+.. c:function:: bool kernel_fpu_available( void )
+
+ This function reports if floating-point code can be used on this CPU or
+ platform. The value returned by this function is not expected to change
+ at runtime, so it only needs to be called once, not before every
+ critical section.
+
+.. c:function:: void kernel_fpu_begin( void )
+ void kernel_fpu_end( void )
+
+ These functions create a floating-point critical section. It is only
+ valid to call ``kernel_fpu_begin()`` after a previous call to
+ ``kernel_fpu_available()`` returned ``true``. These functions are only
+ guaranteed to be callable from (preemptible or non-preemptible) process
+ context.
+
+ Preemption may be disabled inside critical sections, so their size
+ should be minimized. They are *not* required to be reentrant. If the
+ caller expects to nest critical sections, it must implement its own
+ reference counting.
diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst
index 7a3a08d81f11..974beccd671f 100644
--- a/Documentation/core-api/index.rst
+++ b/Documentation/core-api/index.rst
@@ -48,6 +48,7 @@ Library functionality that is used throughout the kernel.
errseq
wrappers/atomic_t
wrappers/atomic_bitops
+ floating-point
Low level entry and exit
========================
diff --git a/Makefile b/Makefile
index 763b6792d3d5..710f65e4249d 100644
--- a/Makefile
+++ b/Makefile
@@ -964,6 +964,11 @@ KBUILD_CFLAGS += $(CC_FLAGS_CFI)
export CC_FLAGS_CFI
endif
+# Architectures can define flags to add/remove for floating-point support
+CC_FLAGS_FPU += -D_LINUX_FPU_COMPILATION_UNIT
+export CC_FLAGS_FPU
+export CC_FLAGS_NO_FPU
+
ifneq ($(CONFIG_FUNCTION_ALIGNMENT),0)
# Set the minimal function alignment. Use the newer GCC option
# -fmin-function-alignment if it is available, or fall back to -falign-funtions.
diff --git a/arch/Kconfig b/arch/Kconfig
index 9f066785bb71..8e34b3acf73d 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -1569,6 +1569,12 @@ config ARCH_HAS_NONLEAF_PMD_YOUNG
address translations. Page table walkers that clear the accessed bit
may use this capability to reduce their search space.
+config ARCH_HAS_KERNEL_FPU_SUPPORT
+ bool
+ help
+ Architectures that select this option can run floating-point code in
+ the kernel, as described in Documentation/core-api/floating-point.rst.
+
source "kernel/gcov/Kconfig"
source "scripts/gcc-plugins/Kconfig"
diff --git a/include/linux/fpu.h b/include/linux/fpu.h
new file mode 100644
index 000000000000..2fb63e22913b
--- /dev/null
+++ b/include/linux/fpu.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _LINUX_FPU_H
+#define _LINUX_FPU_H
+
+#ifdef _LINUX_FPU_COMPILATION_UNIT
+#error FP code must be compiled separately. See Documentation/core-api/floating-point.rst.
+#endif
+
+#include <asm/fpu.h>
+
+#endif
--
2.44.0
_______________________________________________
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 v4 03/15] ARM: crypto: Use CC_FLAGS_FPU for NEON CFLAGS
From: Samuel Holland @ 2024-03-29 7:18 UTC (permalink / raw)
To: Andrew Morton, linux-arm-kernel, x86
Cc: linux-kernel, linux-arch, linuxppc-dev, linux-riscv,
Christoph Hellwig, loongarch, amd-gfx, Samuel Holland,
Russell King
In-Reply-To: <20240329072441.591471-1-samuel.holland@sifive.com>
Now that CC_FLAGS_FPU is exported and can be used anywhere in the source
tree, use it instead of duplicating the flags here.
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
---
(no changes since v1)
arch/arm/lib/Makefile | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 650404be6768..0ca5aae1bcc3 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -40,8 +40,7 @@ $(obj)/csumpartialcopy.o: $(obj)/csumpartialcopygeneric.S
$(obj)/csumpartialcopyuser.o: $(obj)/csumpartialcopygeneric.S
ifeq ($(CONFIG_KERNEL_MODE_NEON),y)
- NEON_FLAGS := -march=armv7-a -mfloat-abi=softfp -mfpu=neon
- CFLAGS_xor-neon.o += $(NEON_FLAGS)
+ CFLAGS_xor-neon.o += $(CC_FLAGS_FPU)
obj-$(CONFIG_XOR_BLOCKS) += xor-neon.o
endif
--
2.44.0
_______________________________________________
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 v4 04/15] arm64: Implement ARCH_HAS_KERNEL_FPU_SUPPORT
From: Samuel Holland @ 2024-03-29 7:18 UTC (permalink / raw)
To: Andrew Morton, linux-arm-kernel, x86
Cc: linux-kernel, linux-arch, linuxppc-dev, linux-riscv,
Christoph Hellwig, loongarch, amd-gfx, Samuel Holland,
Catalin Marinas, Will Deacon
In-Reply-To: <20240329072441.591471-1-samuel.holland@sifive.com>
arm64 provides an equivalent to the common kernel-mode FPU API, but in a
different header and using different function names. Add a wrapper
header, and export CFLAGS adjustments as found in lib/raid6/Makefile.
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
---
(no changes since v2)
Changes in v2:
- Remove file name from header comment
arch/arm64/Kconfig | 1 +
arch/arm64/Makefile | 9 ++++++++-
arch/arm64/include/asm/fpu.h | 15 +++++++++++++++
3 files changed, 24 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/include/asm/fpu.h
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 7b11c98b3e84..67f0d3b5b7df 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -30,6 +30,7 @@ config ARM64
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_GIGANTIC_PAGE
select ARCH_HAS_KCOV
+ select ARCH_HAS_KERNEL_FPU_SUPPORT if KERNEL_MODE_NEON
select ARCH_HAS_KEEPINITRD
select ARCH_HAS_MEMBARRIER_SYNC_CORE
select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 0e075d3c546b..3e863e5b0169 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -36,7 +36,14 @@ ifeq ($(CONFIG_BROKEN_GAS_INST),y)
$(warning Detected assembler with broken .inst; disassembly will be unreliable)
endif
-KBUILD_CFLAGS += -mgeneral-regs-only \
+# The GCC option -ffreestanding is required in order to compile code containing
+# ARM/NEON intrinsics in a non C99-compliant environment (such as the kernel)
+CC_FLAGS_FPU := -ffreestanding
+# Enable <arm_neon.h>
+CC_FLAGS_FPU += -isystem $(shell $(CC) -print-file-name=include)
+CC_FLAGS_NO_FPU := -mgeneral-regs-only
+
+KBUILD_CFLAGS += $(CC_FLAGS_NO_FPU) \
$(compat_vdso) $(cc_has_k_constraint)
KBUILD_CFLAGS += $(call cc-disable-warning, psabi)
KBUILD_AFLAGS += $(compat_vdso)
diff --git a/arch/arm64/include/asm/fpu.h b/arch/arm64/include/asm/fpu.h
new file mode 100644
index 000000000000..2ae50bdce59b
--- /dev/null
+++ b/arch/arm64/include/asm/fpu.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023 SiFive
+ */
+
+#ifndef __ASM_FPU_H
+#define __ASM_FPU_H
+
+#include <asm/neon.h>
+
+#define kernel_fpu_available() cpu_has_neon()
+#define kernel_fpu_begin() kernel_neon_begin()
+#define kernel_fpu_end() kernel_neon_end()
+
+#endif /* ! __ASM_FPU_H */
--
2.44.0
_______________________________________________
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 v4 08/15] powerpc: Implement ARCH_HAS_KERNEL_FPU_SUPPORT
From: Samuel Holland @ 2024-03-29 7:18 UTC (permalink / raw)
To: Andrew Morton, linux-arm-kernel, x86
Cc: linux-kernel, linux-arch, linuxppc-dev, linux-riscv,
Christoph Hellwig, loongarch, amd-gfx, Samuel Holland,
Michael Ellerman
In-Reply-To: <20240329072441.591471-1-samuel.holland@sifive.com>
PowerPC provides an equivalent to the common kernel-mode FPU API, but in
a different header and using different function names. The PowerPC API
also requires a non-preemptible context. Add a wrapper header, and
export the CFLAGS adjustments.
Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
---
(no changes since v1)
arch/powerpc/Kconfig | 1 +
arch/powerpc/Makefile | 5 ++++-
arch/powerpc/include/asm/fpu.h | 28 ++++++++++++++++++++++++++++
3 files changed, 33 insertions(+), 1 deletion(-)
create mode 100644 arch/powerpc/include/asm/fpu.h
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 1c4be3373686..c42a57b6839d 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -137,6 +137,7 @@ config PPC
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_HUGEPD if HUGETLB_PAGE
select ARCH_HAS_KCOV
+ select ARCH_HAS_KERNEL_FPU_SUPPORT if PPC_FPU
select ARCH_HAS_MEMBARRIER_CALLBACKS
select ARCH_HAS_MEMBARRIER_SYNC_CORE
select ARCH_HAS_MEMREMAP_COMPAT_ALIGN if PPC_64S_HASH_MMU
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 65261cbe5bfd..93d89f055b70 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -153,6 +153,9 @@ CFLAGS-$(CONFIG_PPC32) += $(call cc-option, $(MULTIPLEWORD))
CFLAGS-$(CONFIG_PPC32) += $(call cc-option,-mno-readonly-in-sdata)
+CC_FLAGS_FPU := $(call cc-option,-mhard-float)
+CC_FLAGS_NO_FPU := $(call cc-option,-msoft-float)
+
ifdef CONFIG_FUNCTION_TRACER
ifdef CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY
KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
@@ -174,7 +177,7 @@ asinstr := $(call as-instr,lis 9$(comma)foo@high,-DHAVE_AS_ATHIGH=1)
KBUILD_CPPFLAGS += -I $(srctree)/arch/powerpc $(asinstr)
KBUILD_AFLAGS += $(AFLAGS-y)
-KBUILD_CFLAGS += $(call cc-option,-msoft-float)
+KBUILD_CFLAGS += $(CC_FLAGS_NO_FPU)
KBUILD_CFLAGS += $(CFLAGS-y)
CPP = $(CC) -E $(KBUILD_CFLAGS)
diff --git a/arch/powerpc/include/asm/fpu.h b/arch/powerpc/include/asm/fpu.h
new file mode 100644
index 000000000000..ca584e4bc40f
--- /dev/null
+++ b/arch/powerpc/include/asm/fpu.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023 SiFive
+ */
+
+#ifndef _ASM_POWERPC_FPU_H
+#define _ASM_POWERPC_FPU_H
+
+#include <linux/preempt.h>
+
+#include <asm/cpu_has_feature.h>
+#include <asm/switch_to.h>
+
+#define kernel_fpu_available() (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE))
+
+static inline void kernel_fpu_begin(void)
+{
+ preempt_disable();
+ enable_kernel_fp();
+}
+
+static inline void kernel_fpu_end(void)
+{
+ disable_kernel_fp();
+ preempt_enable();
+}
+
+#endif /* ! _ASM_POWERPC_FPU_H */
--
2.44.0
_______________________________________________
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 v4 10/15] x86: Implement ARCH_HAS_KERNEL_FPU_SUPPORT
From: Samuel Holland @ 2024-03-29 7:18 UTC (permalink / raw)
To: Andrew Morton, linux-arm-kernel, x86
Cc: linux-kernel, linux-arch, linuxppc-dev, linux-riscv,
Christoph Hellwig, loongarch, amd-gfx, Samuel Holland,
Borislav Petkov, Dave Hansen, Ingo Molnar, Thomas Gleixner
In-Reply-To: <20240329072441.591471-1-samuel.holland@sifive.com>
x86 already provides kernel_fpu_begin() and kernel_fpu_end(), but in a
different header. Add a wrapper header, and export the CFLAGS
adjustments as found in lib/Makefile.
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
---
(no changes since v1)
arch/x86/Kconfig | 1 +
arch/x86/Makefile | 20 ++++++++++++++++++++
arch/x86/include/asm/fpu.h | 13 +++++++++++++
3 files changed, 34 insertions(+)
create mode 100644 arch/x86/include/asm/fpu.h
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 39886bab943a..7c9d032ee675 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -83,6 +83,7 @@ config X86
select ARCH_HAS_FORTIFY_SOURCE
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_KCOV if X86_64
+ select ARCH_HAS_KERNEL_FPU_SUPPORT
select ARCH_HAS_MEM_ENCRYPT
select ARCH_HAS_MEMBARRIER_SYNC_CORE
select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 662d9d4033e6..5a5f5999c505 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -74,6 +74,26 @@ KBUILD_CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx
KBUILD_RUSTFLAGS += --target=$(objtree)/scripts/target.json
KBUILD_RUSTFLAGS += -Ctarget-feature=-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2
+#
+# CFLAGS for compiling floating point code inside the kernel.
+#
+CC_FLAGS_FPU := -msse -msse2
+ifdef CONFIG_CC_IS_GCC
+# Stack alignment mismatch, proceed with caution.
+# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
+# (8B stack alignment).
+# See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53383
+#
+# The "-msse" in the first argument is there so that the
+# -mpreferred-stack-boundary=3 build error:
+#
+# -mpreferred-stack-boundary=3 is not between 4 and 12
+#
+# can be triggered. Otherwise gcc doesn't complain.
+CC_FLAGS_FPU += -mhard-float
+CC_FLAGS_FPU += $(call cc-option,-msse -mpreferred-stack-boundary=3,-mpreferred-stack-boundary=4)
+endif
+
ifeq ($(CONFIG_X86_KERNEL_IBT),y)
#
# Kernel IBT has S_CET.NOTRACK_EN=0, as such the compilers must not generate
diff --git a/arch/x86/include/asm/fpu.h b/arch/x86/include/asm/fpu.h
new file mode 100644
index 000000000000..b2743fe19339
--- /dev/null
+++ b/arch/x86/include/asm/fpu.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023 SiFive
+ */
+
+#ifndef _ASM_X86_FPU_H
+#define _ASM_X86_FPU_H
+
+#include <asm/fpu/api.h>
+
+#define kernel_fpu_available() true
+
+#endif /* ! _ASM_X86_FPU_H */
--
2.44.0
_______________________________________________
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 v4 11/15] riscv: Add support for kernel-mode FPU
From: Samuel Holland @ 2024-03-29 7:18 UTC (permalink / raw)
To: Andrew Morton, linux-arm-kernel, x86
Cc: linux-kernel, linux-arch, linuxppc-dev, linux-riscv,
Christoph Hellwig, loongarch, amd-gfx, Samuel Holland,
Palmer Dabbelt
In-Reply-To: <20240329072441.591471-1-samuel.holland@sifive.com>
This is motivated by the amdgpu DRM driver, which needs floating-point
code to support recent hardware. That code is not performance-critical,
so only provide a minimal non-preemptible implementation for now.
Support is limited to riscv64 because riscv32 requires runtime (libgcc)
assistance to convert between doubles and 64-bit integers.
Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
Reviewed-by: Palmer Dabbelt <palmer@rivosinc.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
---
(no changes since v3)
Changes in v3:
- Limit riscv ARCH_HAS_KERNEL_FPU_SUPPORT to 64BIT
Changes in v2:
- Remove RISC-V architecture-specific preprocessor check
arch/riscv/Kconfig | 1 +
arch/riscv/Makefile | 3 +++
arch/riscv/include/asm/fpu.h | 16 ++++++++++++++++
arch/riscv/kernel/Makefile | 1 +
arch/riscv/kernel/kernel_mode_fpu.c | 28 ++++++++++++++++++++++++++++
5 files changed, 49 insertions(+)
create mode 100644 arch/riscv/include/asm/fpu.h
create mode 100644 arch/riscv/kernel/kernel_mode_fpu.c
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index be09c8836d56..3bcd0d250810 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -27,6 +27,7 @@ config RISCV
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_GIGANTIC_PAGE
select ARCH_HAS_KCOV
+ select ARCH_HAS_KERNEL_FPU_SUPPORT if 64BIT && FPU
select ARCH_HAS_MEMBARRIER_CALLBACKS
select ARCH_HAS_MEMBARRIER_SYNC_CORE
select ARCH_HAS_MMIOWB
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 252d63942f34..76ff4033c854 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -84,6 +84,9 @@ KBUILD_CFLAGS += -march=$(shell echo $(riscv-march-y) | sed -E 's/(rv32ima|rv64i
KBUILD_AFLAGS += -march=$(riscv-march-y)
+# For C code built with floating-point support, exclude V but keep F and D.
+CC_FLAGS_FPU := -march=$(shell echo $(riscv-march-y) | sed -E 's/(rv32ima|rv64ima)([^v_]*)v?/\1\2/')
+
KBUILD_CFLAGS += -mno-save-restore
KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET)
diff --git a/arch/riscv/include/asm/fpu.h b/arch/riscv/include/asm/fpu.h
new file mode 100644
index 000000000000..91c04c244e12
--- /dev/null
+++ b/arch/riscv/include/asm/fpu.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023 SiFive
+ */
+
+#ifndef _ASM_RISCV_FPU_H
+#define _ASM_RISCV_FPU_H
+
+#include <asm/switch_to.h>
+
+#define kernel_fpu_available() has_fpu()
+
+void kernel_fpu_begin(void);
+void kernel_fpu_end(void);
+
+#endif /* ! _ASM_RISCV_FPU_H */
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index 81d94a8ee10f..5b243d46f4b1 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_RISCV_MISALIGNED) += unaligned_access_speed.o
obj-$(CONFIG_RISCV_PROBE_UNALIGNED_ACCESS) += copy-unaligned.o
obj-$(CONFIG_FPU) += fpu.o
+obj-$(CONFIG_FPU) += kernel_mode_fpu.o
obj-$(CONFIG_RISCV_ISA_V) += vector.o
obj-$(CONFIG_RISCV_ISA_V) += kernel_mode_vector.o
obj-$(CONFIG_SMP) += smpboot.o
diff --git a/arch/riscv/kernel/kernel_mode_fpu.c b/arch/riscv/kernel/kernel_mode_fpu.c
new file mode 100644
index 000000000000..0ac8348876c4
--- /dev/null
+++ b/arch/riscv/kernel/kernel_mode_fpu.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023 SiFive
+ */
+
+#include <linux/export.h>
+#include <linux/preempt.h>
+
+#include <asm/csr.h>
+#include <asm/fpu.h>
+#include <asm/processor.h>
+#include <asm/switch_to.h>
+
+void kernel_fpu_begin(void)
+{
+ preempt_disable();
+ fstate_save(current, task_pt_regs(current));
+ csr_set(CSR_SSTATUS, SR_FS);
+}
+EXPORT_SYMBOL_GPL(kernel_fpu_begin);
+
+void kernel_fpu_end(void)
+{
+ csr_clear(CSR_SSTATUS, SR_FS);
+ fstate_restore(current, task_pt_regs(current));
+ preempt_enable();
+}
+EXPORT_SYMBOL_GPL(kernel_fpu_end);
--
2.44.0
_______________________________________________
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 v4 09/15] x86/fpu: Fix asm/fpu/types.h include guard
From: Samuel Holland @ 2024-03-29 7:18 UTC (permalink / raw)
To: Andrew Morton, linux-arm-kernel, x86
Cc: linux-kernel, linux-arch, linuxppc-dev, linux-riscv,
Christoph Hellwig, loongarch, amd-gfx, Samuel Holland,
Borislav Petkov, Dave Hansen, Ingo Molnar, Thomas Gleixner
In-Reply-To: <20240329072441.591471-1-samuel.holland@sifive.com>
The include guard should match the filename, or it will conflict with
the newly-added asm/fpu.h.
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
---
Changes in v4:
- New patch for v4
arch/x86/include/asm/fpu/types.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/x86/include/asm/fpu/types.h b/arch/x86/include/asm/fpu/types.h
index ace9aa3b78a3..eb17f31b06d2 100644
--- a/arch/x86/include/asm/fpu/types.h
+++ b/arch/x86/include/asm/fpu/types.h
@@ -2,8 +2,8 @@
/*
* FPU data structures:
*/
-#ifndef _ASM_X86_FPU_H
-#define _ASM_X86_FPU_H
+#ifndef _ASM_X86_FPU_TYPES_H
+#define _ASM_X86_FPU_TYPES_H
#include <asm/page_types.h>
@@ -596,4 +596,4 @@ struct fpu_state_config {
/* FPU state configuration information */
extern struct fpu_state_config fpu_kernel_cfg, fpu_user_cfg;
-#endif /* _ASM_X86_FPU_H */
+#endif /* _ASM_X86_FPU_TYPES_H */
--
2.44.0
_______________________________________________
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 v4 13/15] drm/amd/display: Use ARCH_HAS_KERNEL_FPU_SUPPORT
From: Samuel Holland @ 2024-03-29 7:18 UTC (permalink / raw)
To: Andrew Morton, linux-arm-kernel, x86
Cc: linux-kernel, linux-arch, linuxppc-dev, linux-riscv,
Christoph Hellwig, loongarch, amd-gfx, Samuel Holland,
Alex Deucher
In-Reply-To: <20240329072441.591471-1-samuel.holland@sifive.com>
Now that all previously-supported architectures select
ARCH_HAS_KERNEL_FPU_SUPPORT, this code can depend on that symbol instead
of the existing list of architectures. It can also take advantage of the
common kernel-mode FPU API and method of adjusting CFLAGS.
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
---
(no changes since v2)
Changes in v2:
- Split altivec removal to a separate patch
- Use linux/fpu.h instead of asm/fpu.h in consumers
drivers/gpu/drm/amd/display/Kconfig | 2 +-
.../gpu/drm/amd/display/amdgpu_dm/dc_fpu.c | 27 ++------------
drivers/gpu/drm/amd/display/dc/dml/Makefile | 36 ++-----------------
drivers/gpu/drm/amd/display/dc/dml2/Makefile | 36 ++-----------------
4 files changed, 7 insertions(+), 94 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig
index 901d1961b739..5fcd4f778dc3 100644
--- a/drivers/gpu/drm/amd/display/Kconfig
+++ b/drivers/gpu/drm/amd/display/Kconfig
@@ -8,7 +8,7 @@ config DRM_AMD_DC
depends on BROKEN || !CC_IS_CLANG || ARM64 || RISCV || SPARC64 || X86_64
select SND_HDA_COMPONENT if SND_HDA_CORE
# !CC_IS_CLANG: https://github.com/ClangBuiltLinux/linux/issues/1752
- select DRM_AMD_DC_FP if (X86 || LOONGARCH || (PPC64 && ALTIVEC) || (ARM64 && KERNEL_MODE_NEON && !CC_IS_CLANG))
+ select DRM_AMD_DC_FP if ARCH_HAS_KERNEL_FPU_SUPPORT && (!ARM64 || !CC_IS_CLANG)
help
Choose this option if you want to use the new display engine
support for AMDGPU. This adds required support for Vega and
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
index 0de16796466b..e46f8ce41d87 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
@@ -26,16 +26,7 @@
#include "dc_trace.h"
-#if defined(CONFIG_X86)
-#include <asm/fpu/api.h>
-#elif defined(CONFIG_PPC64)
-#include <asm/switch_to.h>
-#include <asm/cputable.h>
-#elif defined(CONFIG_ARM64)
-#include <asm/neon.h>
-#elif defined(CONFIG_LOONGARCH)
-#include <asm/fpu.h>
-#endif
+#include <linux/fpu.h>
/**
* DOC: DC FPU manipulation overview
@@ -87,16 +78,9 @@ void dc_fpu_begin(const char *function_name, const int line)
WARN_ON_ONCE(!in_task());
preempt_disable();
depth = __this_cpu_inc_return(fpu_recursion_depth);
-
if (depth == 1) {
-#if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH)
+ BUG_ON(!kernel_fpu_available());
kernel_fpu_begin();
-#elif defined(CONFIG_PPC64)
- if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE))
- enable_kernel_fp();
-#elif defined(CONFIG_ARM64)
- kernel_neon_begin();
-#endif
}
TRACE_DCN_FPU(true, function_name, line, depth);
@@ -118,14 +102,7 @@ void dc_fpu_end(const char *function_name, const int line)
depth = __this_cpu_dec_return(fpu_recursion_depth);
if (depth == 0) {
-#if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH)
kernel_fpu_end();
-#elif defined(CONFIG_PPC64)
- if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE))
- disable_kernel_fp();
-#elif defined(CONFIG_ARM64)
- kernel_neon_end();
-#endif
} else {
WARN_ON_ONCE(depth < 0);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile
index 59d3972341d2..a94b6d546cd1 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile
@@ -25,40 +25,8 @@
# It provides the general basic services required by other DAL
# subcomponents.
-ifdef CONFIG_X86
-dml_ccflags-$(CONFIG_CC_IS_GCC) := -mhard-float
-dml_ccflags := $(dml_ccflags-y) -msse
-endif
-
-ifdef CONFIG_PPC64
-dml_ccflags := -mhard-float
-endif
-
-ifdef CONFIG_ARM64
-dml_rcflags := -mgeneral-regs-only
-endif
-
-ifdef CONFIG_LOONGARCH
-dml_ccflags := -mfpu=64
-dml_rcflags := -msoft-float
-endif
-
-ifdef CONFIG_CC_IS_GCC
-ifneq ($(call gcc-min-version, 70100),y)
-IS_OLD_GCC = 1
-endif
-endif
-
-ifdef CONFIG_X86
-ifdef IS_OLD_GCC
-# Stack alignment mismatch, proceed with caution.
-# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
-# (8B stack alignment).
-dml_ccflags += -mpreferred-stack-boundary=4
-else
-dml_ccflags += -msse2
-endif
-endif
+dml_ccflags := $(CC_FLAGS_FPU)
+dml_rcflags := $(CC_FLAGS_NO_FPU)
ifneq ($(CONFIG_FRAME_WARN),0)
ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/Makefile b/drivers/gpu/drm/amd/display/dc/dml2/Makefile
index 7b51364084b5..4f6c804a26ad 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dml2/Makefile
@@ -24,40 +24,8 @@
#
# Makefile for dml2.
-ifdef CONFIG_X86
-dml2_ccflags-$(CONFIG_CC_IS_GCC) := -mhard-float
-dml2_ccflags := $(dml2_ccflags-y) -msse
-endif
-
-ifdef CONFIG_PPC64
-dml2_ccflags := -mhard-float
-endif
-
-ifdef CONFIG_ARM64
-dml2_rcflags := -mgeneral-regs-only
-endif
-
-ifdef CONFIG_LOONGARCH
-dml2_ccflags := -mfpu=64
-dml2_rcflags := -msoft-float
-endif
-
-ifdef CONFIG_CC_IS_GCC
-ifeq ($(call cc-ifversion, -lt, 0701, y), y)
-IS_OLD_GCC = 1
-endif
-endif
-
-ifdef CONFIG_X86
-ifdef IS_OLD_GCC
-# Stack alignment mismatch, proceed with caution.
-# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
-# (8B stack alignment).
-dml2_ccflags += -mpreferred-stack-boundary=4
-else
-dml2_ccflags += -msse2
-endif
-endif
+dml2_ccflags := $(CC_FLAGS_FPU)
+dml2_rcflags := $(CC_FLAGS_NO_FPU)
ifneq ($(CONFIG_FRAME_WARN),0)
ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y)
--
2.44.0
_______________________________________________
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 v4 12/15] drm/amd/display: Only use hard-float, not altivec on powerpc
From: Samuel Holland @ 2024-03-29 7:18 UTC (permalink / raw)
To: Andrew Morton, linux-arm-kernel, x86
Cc: linux-kernel, linux-arch, linuxppc-dev, linux-riscv,
Christoph Hellwig, loongarch, amd-gfx, Michael Ellerman,
Alex Deucher, Samuel Holland
In-Reply-To: <20240329072441.591471-1-samuel.holland@sifive.com>
From: Michael Ellerman <mpe@ellerman.id.au>
The compiler flags enable altivec, but that is not required; hard-float
is sufficient for the code to build and function.
Drop altivec from the compiler flags and adjust the enable/disable code
to only enable FPU use.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
---
(no changes since v2)
Changes in v2:
- New patch for v2
drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c | 12 ++----------
drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 +-
drivers/gpu/drm/amd/display/dc/dml2/Makefile | 2 +-
3 files changed, 4 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
index 4ae4720535a5..0de16796466b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
@@ -92,11 +92,7 @@ void dc_fpu_begin(const char *function_name, const int line)
#if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH)
kernel_fpu_begin();
#elif defined(CONFIG_PPC64)
- if (cpu_has_feature(CPU_FTR_VSX_COMP))
- enable_kernel_vsx();
- else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP))
- enable_kernel_altivec();
- else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE))
+ if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE))
enable_kernel_fp();
#elif defined(CONFIG_ARM64)
kernel_neon_begin();
@@ -125,11 +121,7 @@ void dc_fpu_end(const char *function_name, const int line)
#if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH)
kernel_fpu_end();
#elif defined(CONFIG_PPC64)
- if (cpu_has_feature(CPU_FTR_VSX_COMP))
- disable_kernel_vsx();
- else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP))
- disable_kernel_altivec();
- else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE))
+ if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE))
disable_kernel_fp();
#elif defined(CONFIG_ARM64)
kernel_neon_end();
diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile
index c4a5efd2dda5..59d3972341d2 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile
@@ -31,7 +31,7 @@ dml_ccflags := $(dml_ccflags-y) -msse
endif
ifdef CONFIG_PPC64
-dml_ccflags := -mhard-float -maltivec
+dml_ccflags := -mhard-float
endif
ifdef CONFIG_ARM64
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/Makefile b/drivers/gpu/drm/amd/display/dc/dml2/Makefile
index acff3449b8d7..7b51364084b5 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dml2/Makefile
@@ -30,7 +30,7 @@ dml2_ccflags := $(dml2_ccflags-y) -msse
endif
ifdef CONFIG_PPC64
-dml2_ccflags := -mhard-float -maltivec
+dml2_ccflags := -mhard-float
endif
ifdef CONFIG_ARM64
--
2.44.0
_______________________________________________
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 v4 15/15] selftests/fpu: Allow building on other architectures
From: Samuel Holland @ 2024-03-29 7:18 UTC (permalink / raw)
To: Andrew Morton, linux-arm-kernel, x86
Cc: linux-kernel, linux-arch, linuxppc-dev, linux-riscv,
Christoph Hellwig, loongarch, amd-gfx, Samuel Holland
In-Reply-To: <20240329072441.591471-1-samuel.holland@sifive.com>
Now that ARCH_HAS_KERNEL_FPU_SUPPORT provides a common way to compile
and run floating-point code, this test is no longer x86-specific.
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
---
(no changes since v1)
lib/Kconfig.debug | 2 +-
lib/Makefile | 25 ++-----------------------
lib/test_fpu_glue.c | 5 ++++-
3 files changed, 7 insertions(+), 25 deletions(-)
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index c63a5fbf1f1c..f93e778e0405 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -2890,7 +2890,7 @@ config TEST_FREE_PAGES
config TEST_FPU
tristate "Test floating point operations in kernel space"
- depends on X86 && !KCOV_INSTRUMENT_ALL
+ depends on ARCH_HAS_KERNEL_FPU_SUPPORT && !KCOV_INSTRUMENT_ALL
help
Enable this option to add /sys/kernel/debug/selftest_helpers/test_fpu
which will trigger a sequence of floating point operations. This is used
diff --git a/lib/Makefile b/lib/Makefile
index fcb35bf50979..e44ad11f77b5 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -110,31 +110,10 @@ CFLAGS_test_fprobe.o += $(CC_FLAGS_FTRACE)
obj-$(CONFIG_FPROBE_SANITY_TEST) += test_fprobe.o
obj-$(CONFIG_TEST_OBJPOOL) += test_objpool.o
-#
-# CFLAGS for compiling floating point code inside the kernel. x86/Makefile turns
-# off the generation of FPU/SSE* instructions for kernel proper but FPU_FLAGS
-# get appended last to CFLAGS and thus override those previous compiler options.
-#
-FPU_CFLAGS := -msse -msse2
-ifdef CONFIG_CC_IS_GCC
-# Stack alignment mismatch, proceed with caution.
-# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
-# (8B stack alignment).
-# See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53383
-#
-# The "-msse" in the first argument is there so that the
-# -mpreferred-stack-boundary=3 build error:
-#
-# -mpreferred-stack-boundary=3 is not between 4 and 12
-#
-# can be triggered. Otherwise gcc doesn't complain.
-FPU_CFLAGS += -mhard-float
-FPU_CFLAGS += $(call cc-option,-msse -mpreferred-stack-boundary=3,-mpreferred-stack-boundary=4)
-endif
-
obj-$(CONFIG_TEST_FPU) += test_fpu.o
test_fpu-y := test_fpu_glue.o test_fpu_impl.o
-CFLAGS_test_fpu_impl.o += $(FPU_CFLAGS)
+CFLAGS_test_fpu_impl.o += $(CC_FLAGS_FPU)
+CFLAGS_REMOVE_test_fpu_impl.o += $(CC_FLAGS_NO_FPU)
# Some KUnit files (hooks.o) need to be built-in even when KUnit is a module,
# so we can't just use obj-$(CONFIG_KUNIT).
diff --git a/lib/test_fpu_glue.c b/lib/test_fpu_glue.c
index 85963d7be826..eef282a2715f 100644
--- a/lib/test_fpu_glue.c
+++ b/lib/test_fpu_glue.c
@@ -17,7 +17,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/debugfs.h>
-#include <asm/fpu/api.h>
+#include <linux/fpu.h>
#include "test_fpu.h"
@@ -38,6 +38,9 @@ static struct dentry *selftest_dir;
static int __init test_fpu_init(void)
{
+ if (!kernel_fpu_available())
+ return -EINVAL;
+
selftest_dir = debugfs_create_dir("selftest_helpers", NULL);
if (!selftest_dir)
return -ENOMEM;
--
2.44.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [RFC 0/3] Add i.MX8Q HSIO PHY driver support
From: Richard Zhu @ 2024-03-29 7:31 UTC (permalink / raw)
To: vkoul, kishon, robh+dt, krzysztof.kozlowski+dt, conor+dt,
frank.li
Cc: hongxing.zhu, linux-phy, devicetree, linux-arm-kernel,
linux-kernel, kernel, linux-imx
i.MX8Q HSIO module has PHY and mix control regions.
This patch-set adds i.MX8Q HSIO PHY driver support, and provides
standard PHY phandles that can be used by i.MX8Q PCIe or
SATA driver later.
[RFC 1/3] dt-bindings: phy: Add i.MX8Q HSIO SerDes PHY binding
[RFC 2/3] dt-bindings: phy: phy-imx8-pcie: Add binding for i.MX8Q
[RFC 3/3] phy: freescale: imx8q-hsio: Add i.MX8Q HSIO PHY driver
Documentation/devicetree/bindings/phy/fsl,imx8q-hsio.yaml | 143 ++++++++++++++++++++++++
drivers/phy/freescale/Kconfig | 8 ++
drivers/phy/freescale/Makefile | 1 +
drivers/phy/freescale/phy-fsl-imx8q-hsio.c | 518 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/dt-bindings/phy/phy-imx8-pcie.h | 26 +++++
5 files changed, 696 insertions(+)
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [RFC 1/3] dt-bindings: phy: Add i.MX8Q HSIO SerDes PHY binding
From: Richard Zhu @ 2024-03-29 7:31 UTC (permalink / raw)
To: vkoul, kishon, robh+dt, krzysztof.kozlowski+dt, conor+dt,
frank.li
Cc: hongxing.zhu, linux-phy, devicetree, linux-arm-kernel,
linux-kernel, kernel, linux-imx
In-Reply-To: <1711697493-16151-1-git-send-email-hongxing.zhu@nxp.com>
Add i.MX8QM and i.MX8QXP HSIO SerDes PHY binding.
- Use the controller ID to specify which controller is binded to the
PHY.
- Introduce one HSIO configuration, mandatory required to set
"PCIE_AB_SELECT" and "PHY_X1_EPCS_SEL" during the initialization.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
.../bindings/phy/fsl,imx8q-hsio.yaml | 143 ++++++++++++++++++
1 file changed, 143 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/fsl,imx8q-hsio.yaml
diff --git a/Documentation/devicetree/bindings/phy/fsl,imx8q-hsio.yaml b/Documentation/devicetree/bindings/phy/fsl,imx8q-hsio.yaml
new file mode 100644
index 000000000000..506551d4d94a
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/fsl,imx8q-hsio.yaml
@@ -0,0 +1,143 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/fsl,imx8q-hsio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX8Q SoC series HSIO SERDES PHY
+
+maintainers:
+ - Richard Zhu <hongxing.zhu@nxp.com>
+
+properties:
+ compatible:
+ enum:
+ - fsl,imx8qxp-serdes
+ - fsl,imx8qm-serdes
+ reg:
+ minItems: 4
+ maxItems: 4
+
+ "#phy-cells":
+ const: 3
+ description: |
+ The first number defines the ID of the PHY contained in the HSIO macro.
+ The second defines controller ID binded to the PHY. The third defines the
+ HSIO configuratons refer to the different use cases. They are defined in
+ dt-bindings/phy/phy-imx8-pcie.h
+
+ reg-names:
+ items:
+ - const: reg
+ - const: phy
+ - const: ctrl
+ - const: misc
+
+ clocks:
+ minItems: 5
+ maxItems: 14
+
+ clock-names:
+ minItems: 5
+ maxItems: 14
+
+ fsl,refclk-pad-mode:
+ description: |
+ Specifies the mode of the refclk pad used. It can be UNUSED(PHY
+ refclock is derived from SoC internal source), INPUT(PHY refclock
+ is provided externally via the refclk pad) or OUTPUT(PHY refclock
+ is derived from SoC internal source and provided on the refclk pad).
+ Refer include/dt-bindings/phy/phy-imx8-pcie.h for the constants
+ to be used.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 1, 2 ]
+
+ power-domains:
+ description: |
+ i.MX8Q HSIO SerDes power domains. i.MX8QXP has one SerDes power domains.
+ And i.MX8QM has two.
+ minItems: 1
+ maxItems: 2
+
+required:
+ - compatible
+ - reg
+ - "#phy-cells"
+ - clocks
+ - clock-names
+ - fsl,refclk-pad-mode
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx8qxp-serdes
+ then:
+ properties:
+ clock-names:
+ items:
+ - const: apb_pclk0
+ - const: pclk0
+ - const: phy0_crr
+ - const: ctl0_crr
+ - const: misc_crr
+ power-domains:
+ minItems: 1
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx8qm-serdes
+ then:
+ properties:
+ clock-names:
+ items:
+ - const: pclk0
+ - const: pclk1
+ - const: apb_pclk0
+ - const: apb_pclk1
+ - const: pclk2
+ - const: epcs_tx
+ - const: epcs_rx
+ - const: apb_pclk2
+ - const: phy0_crr
+ - const: phy1_crr
+ - const: ctl0_crr
+ - const: ctl1_crr
+ - const: ctl2_crr
+ - const: misc_crr
+ power-domains:
+ minItems: 2
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/imx8-clock.h>
+ #include <dt-bindings/clock/imx8-lpcg.h>
+ #include <dt-bindings/firmware/imx/rsrc.h>
+ #include <dt-bindings/phy/phy-imx8-pcie.h>
+
+ serdes: phy@5f1a0000 {
+ compatible = "fsl,imx8qxp-serdes";
+ reg = <0x5f1a0000 0x10000>,
+ <0x5f120000 0x10000>,
+ <0x5f140000 0x10000>,
+ <0x5f160000 0x10000>;
+ reg-names = "reg", "phy", "ctrl", "misc";
+ clocks = <&phyx1_lpcg IMX_LPCG_CLK_0>,
+ <&phyx1_lpcg IMX_LPCG_CLK_4>,
+ <&phyx1_crr1_lpcg IMX_LPCG_CLK_4>,
+ <&pcieb_crr3_lpcg IMX_LPCG_CLK_4>,
+ <&misc_crr5_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "apb_pclk0", "pclk0", "phy0_crr", "ctl0_crr",
+ "misc_crr";
+ power-domains = <&pd IMX_SC_R_SERDES_1>;
+ #phy-cells = <3>;
+ status = "disabled";
+ };
+...
--
2.37.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
* [RFC 2/3] dt-bindings: phy: phy-imx8-pcie: Add binding for i.MX8Q HSIO SerDes PHY
From: Richard Zhu @ 2024-03-29 7:31 UTC (permalink / raw)
To: vkoul, kishon, robh+dt, krzysztof.kozlowski+dt, conor+dt,
frank.li
Cc: hongxing.zhu, linux-phy, devicetree, linux-arm-kernel,
linux-kernel, kernel, linux-imx
In-Reply-To: <1711697493-16151-1-git-send-email-hongxing.zhu@nxp.com>
Add binding for controller ID and HSIO configuration setting of the
i.MX8Q HSIO SerDes PHY.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
include/dt-bindings/phy/phy-imx8-pcie.h | 26 +++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/include/dt-bindings/phy/phy-imx8-pcie.h b/include/dt-bindings/phy/phy-imx8-pcie.h
index 8bbe2d6538d8..5cd5580879fa 100644
--- a/include/dt-bindings/phy/phy-imx8-pcie.h
+++ b/include/dt-bindings/phy/phy-imx8-pcie.h
@@ -11,4 +11,30 @@
#define IMX8_PCIE_REFCLK_PAD_INPUT 1
#define IMX8_PCIE_REFCLK_PAD_OUTPUT 2
+/*
+ * i.MX8QM HSIO subsystem has three lane PHYs and three controllers:
+ * PCIEA(2 lanes capapble PCIe controller), PCIEB (only support one
+ * lane) and SATA.
+ * In the different use cases. PCIEA can be binded to PHY lane0, lane1
+ * or Lane0 and lane1. PCIEB can be binded to lane1 or lane2 PHY. SATA
+ * can only be binded to last lane2 PHY.
+ * Define i.MX8Q HSIO controller ID here to specify the controller
+ * binded to the PHY.
+ * Meanwhile, i.MX8QXP HSIO subsystem has one lane PHY and PCIEB(only
+ * support one lane) controller.
+ */
+#define IMX8Q_HSIO_PCIEA_ID 0
+#define IMX8Q_HSIO_PCIEB_ID 1
+#define IMX8Q_HSIO_SATA_ID 2
+
+/*
+ * On i.MX8QM, PCIEA is mandatory required if the HSIO is enabled.
+ * Define configurations beside PCIEA is enabled.
+ * On i.MX8QXP, HSIO module only has PCIEB and one lane PHY.
+ * The "IMX8Q_HSIO_CFG_PCIEB" can be used on i.MX8QXP platforms.
+ */
+#define IMX8Q_HSIO_CFG_SATA 1
+#define IMX8Q_HSIO_CFG_PCIEB 2
+#define IMX8Q_HSIO_CFG_PCIEBSATA 3
+
#endif /* _DT_BINDINGS_IMX8_PCIE_H */
--
2.37.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
* [RFC 3/3] phy: freescale: imx8q-hsio: Add i.MX8Q HSIO PHY driver support
From: Richard Zhu @ 2024-03-29 7:31 UTC (permalink / raw)
To: vkoul, kishon, robh+dt, krzysztof.kozlowski+dt, conor+dt,
frank.li
Cc: hongxing.zhu, linux-phy, devicetree, linux-arm-kernel,
linux-kernel, kernel, linux-imx
In-Reply-To: <1711697493-16151-1-git-send-email-hongxing.zhu@nxp.com>
Add i.MX8Q HSIO PHY driver support.
- Add one HSIO configuration property, that used to select the
"PCIE_AB_SELECT" and "PHY_X1_EPCS_SEL" during the initialization.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
drivers/phy/freescale/Kconfig | 8 +
drivers/phy/freescale/Makefile | 1 +
drivers/phy/freescale/phy-fsl-imx8q-hsio.c | 518 +++++++++++++++++++++
3 files changed, 527 insertions(+)
create mode 100644 drivers/phy/freescale/phy-fsl-imx8q-hsio.c
diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig
index 853958fb2c06..bcddddef1cbb 100644
--- a/drivers/phy/freescale/Kconfig
+++ b/drivers/phy/freescale/Kconfig
@@ -35,6 +35,14 @@ config PHY_FSL_IMX8M_PCIE
Enable this to add support for the PCIE PHY as found on
i.MX8M family of SOCs.
+config PHY_FSL_IMX8Q_HSIO
+ tristate "Freescale i.MX8Q HSIO PHY"
+ depends on OF && HAS_IOMEM
+ select GENERIC_PHY
+ help
+ Enable this to add support for the HSIO PHY as found on
+ i.MX8Q family of SOCs.
+
endif
config PHY_FSL_LYNX_28G
diff --git a/drivers/phy/freescale/Makefile b/drivers/phy/freescale/Makefile
index cedb328bc4d2..db888c37fcf9 100644
--- a/drivers/phy/freescale/Makefile
+++ b/drivers/phy/freescale/Makefile
@@ -3,4 +3,5 @@ obj-$(CONFIG_PHY_FSL_IMX8MQ_USB) += phy-fsl-imx8mq-usb.o
obj-$(CONFIG_PHY_MIXEL_LVDS_PHY) += phy-fsl-imx8qm-lvds-phy.o
obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY) += phy-fsl-imx8-mipi-dphy.o
obj-$(CONFIG_PHY_FSL_IMX8M_PCIE) += phy-fsl-imx8m-pcie.o
+obj-$(CONFIG_PHY_FSL_IMX8Q_HSIO) += phy-fsl-imx8q-hsio.o
obj-$(CONFIG_PHY_FSL_LYNX_28G) += phy-fsl-lynx-28g.o
diff --git a/drivers/phy/freescale/phy-fsl-imx8q-hsio.c b/drivers/phy/freescale/phy-fsl-imx8q-hsio.c
new file mode 100644
index 000000000000..8deede5e8e8e
--- /dev/null
+++ b/drivers/phy/freescale/phy-fsl-imx8q-hsio.c
@@ -0,0 +1,518 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 NXP
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/pci_regs.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/pcie.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/phy/phy-imx8-pcie.h>
+
+#define MAX_NUM_LANES 3
+#define LANE_NUM_CLKS 5
+
+/* Parameters for the waiting for PCIe PHY PLL to lock */
+#define PHY_INIT_WAIT_USLEEP_MAX 10
+#define PHY_INIT_WAIT_TIMEOUT (1000 * PHY_INIT_WAIT_USLEEP_MAX)
+
+/* i.MX8Q HSIO registers */
+#define CTRL0 0x0
+#define APB_RSTN_0 BIT(0)
+#define APB_RSTN_1 BIT(1)
+#define PIPE_RSTN_0_MASK GENMASK(25, 24)
+#define PIPE_RSTN_1_MASK GENMASK(27, 26)
+#define MODE_MASK GENMASK(20, 17)
+#define MODE_PCIE 0x0
+#define MODE_SATA 0x4
+#define DEVICE_TYPE_MASK GENMASK(27, 24)
+#define EPCS_TXDEEMP BIT(5)
+#define EPCS_TXDEEMP_SEL BIT(6)
+#define EPCS_PHYRESET_N BIT(7)
+#define RESET_N BIT(12)
+
+#define IOB_RXENA BIT(0)
+#define IOB_TXENA BIT(1)
+#define IOB_A_0_TXOE BIT(2)
+#define IOB_A_0_M1M0_2 BIT(4)
+#define IOB_A_0_M1M0_MASK GENMASK(4, 3)
+#define PHYX1_EPCS_SEL BIT(12)
+#define PCIE_AB_SELECT BIT(13)
+#define CLKREQN_OUT_OVERRIDE GENMASK(25, 24)
+
+#define PHY_STTS0 0x4
+#define LANE0_TX_PLL_LOCK BIT(4)
+#define LANE1_TX_PLL_LOCK BIT(12)
+
+#define CTRL2 0x8
+#define LTSSM_ENABLE BIT(4)
+#define BUTTON_RST_N BIT(21)
+#define PERST_N BIT(22)
+#define POWER_UP_RST_N BIT(23)
+
+#define PCIE_STTS0 0xc
+#define PM_REQ_CORE_RST BIT(19)
+
+#define REG48_PMA_STATUS 0x30
+#define REG48_PMA_RDY BIT(7)
+
+struct imx8q_hsio_drvdata {
+ int num_lane;
+};
+
+struct imx8q_hsio_lane {
+ const char * const *clk_names;
+ struct clk_bulk_data clks[LANE_NUM_CLKS];
+ u32 clks_cnt;
+ u32 ctrl_id;
+ u32 ctrl_off;
+ u32 idx;
+ u32 phy_off;
+ struct imx8q_hsio_priv *priv;
+ struct phy *phy;
+ enum phy_mode lane_mode;
+};
+
+struct imx8q_hsio_priv {
+ void __iomem *base;
+ struct device *dev;
+ u32 refclk_pad_mode;
+ u32 hsio_cfg;
+ struct regmap *phy;
+ struct regmap *ctrl;
+ struct regmap *misc;
+ const struct imx8q_hsio_drvdata *drvdata;
+ struct imx8q_hsio_lane lane[MAX_NUM_LANES];
+};
+
+static const char * const imx8q_hsio_lan0_pcie_clks[] = {"apb_pclk0", "pclk0",
+ "ctl0_crr", "phy0_crr", "misc_crr"};
+static const char * const imx8q_hsio_lan1_pciea_clks[] = {"apb_pclk1", "pclk1",
+ "ctl0_crr", "phy0_crr", "misc_crr"};
+static const char * const imx8q_hsio_lan1_pcieb_clks[] = {"apb_pclk1", "pclk1",
+ "ctl1_crr", "phy0_crr", "misc_crr"};
+static const char * const imx8q_hsio_lan2_pcieb_clks[] = {"apb_pclk2", "pclk2",
+ "ctl1_crr", "phy1_crr", "misc_crr"};
+static const char * const imx8q_hsio_lane_sata_clks[] = {"pclk2", "epcs_tx",
+ "epcs_rx", "phy1_crr", "misc_crr"};
+
+static const struct regmap_config regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static int imx8q_hsio_init(struct phy *phy)
+{
+ int ret, i;
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx8q_hsio_priv *priv = lane->priv;
+ struct device *dev = priv->dev;
+
+ /* Assign clocks refer to different modes */
+ switch (lane->ctrl_id) {
+ case IMX8Q_HSIO_PCIEA_ID:
+ if (lane->idx > 1) {
+ dev_err(dev, "invalid lane ID.");
+ return -EINVAL;
+ }
+
+ lane->lane_mode = PHY_MODE_PCIE;
+ lane->ctrl_off = 0;
+ lane->phy_off = 0;
+
+ for (i = 0; i < LANE_NUM_CLKS; i++) {
+ if (lane->idx)
+ lane->clks[i].id = imx8q_hsio_lan1_pciea_clks[i];
+ else
+ lane->clks[i].id = imx8q_hsio_lan0_pcie_clks[i];
+ }
+ break;
+ case IMX8Q_HSIO_PCIEB_ID:
+ if (lane->idx > 2) {
+ dev_err(dev, "invalid lane ID.");
+ return -EINVAL;
+ }
+
+ lane->lane_mode = PHY_MODE_PCIE;
+ if (lane->idx == 0) {
+ /* i.MX8QXP */
+ lane->ctrl_off = 0;
+ lane->phy_off = 0;
+ } else {
+ /*
+ * On i.MX8QM, only second or third lane PHY can
+ * be binded to PCIEB.
+ */
+ lane->ctrl_off = SZ_64K;
+ if (lane->idx == 1)
+ lane->phy_off = 0;
+ else /* idx == 2, the third lane is binded to PCIEB */
+ lane->phy_off = SZ_64K;
+ }
+
+ for (i = 0; i < LANE_NUM_CLKS; i++) {
+ if (lane->idx == 1)
+ lane->clks[i].id = imx8q_hsio_lan1_pcieb_clks[i];
+ else if (lane->idx == 2)
+ lane->clks[i].id = imx8q_hsio_lan2_pcieb_clks[i];
+ else /* i.MX8QXP only has PCIEB, it's idx == 0 */
+ lane->clks[i].id = imx8q_hsio_lan0_pcie_clks[i];
+
+ }
+ break;
+ case IMX8Q_HSIO_SATA_ID:
+ /* On i.MX8QM, only the third lane PHY can be binded to SATA */
+ if (lane->idx != 2) {
+ dev_err(dev, "invalid lane ID.");
+ return -EINVAL;
+ }
+ lane->ctrl_off = SZ_128K;
+ lane->lane_mode = PHY_MODE_SATA;
+ lane->phy_off = SZ_64K;
+
+ for (i = 0; i < LANE_NUM_CLKS; i++)
+ lane->clks[i].id = imx8q_hsio_lane_sata_clks[i];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Fetch clocks */
+ ret = devm_clk_bulk_get(dev, LANE_NUM_CLKS, lane->clks);
+ if (ret)
+ return ret;
+
+ ret = clk_bulk_prepare_enable(LANE_NUM_CLKS, lane->clks);
+ if (ret)
+ return ret;
+
+ /* allow the clocks to stabilize */
+ usleep_range(200, 500);
+ return 0;
+}
+
+static int imx8q_hsio_exit(struct phy *phy)
+{
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+
+ clk_bulk_disable_unprepare(LANE_NUM_CLKS, lane->clks);
+
+ return 0;
+}
+
+static void imx8q_hsio_pcie_phy_resets(struct phy *phy)
+{
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx8q_hsio_priv *priv = lane->priv;
+
+ regmap_clear_bits(priv->ctrl, lane->ctrl_off + CTRL2, BUTTON_RST_N);
+ regmap_clear_bits(priv->ctrl, lane->ctrl_off + CTRL2, PERST_N);
+ regmap_clear_bits(priv->ctrl, lane->ctrl_off + CTRL2, POWER_UP_RST_N);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL2, BUTTON_RST_N);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL2, PERST_N);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL2, POWER_UP_RST_N);
+
+ if (lane->idx == 1) {
+ /* The second lane */
+ regmap_set_bits(priv->phy, lane->phy_off + CTRL0, APB_RSTN_1);
+ regmap_set_bits(priv->phy, lane->phy_off + CTRL0, PIPE_RSTN_1_MASK);
+ } else {
+ regmap_set_bits(priv->phy, lane->phy_off + CTRL0, APB_RSTN_0);
+ regmap_set_bits(priv->phy, lane->phy_off + CTRL0, PIPE_RSTN_0_MASK);
+ }
+}
+
+static void imx8q_hsio_sata_phy_resets(struct phy *phy)
+{
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx8q_hsio_priv *priv = lane->priv;
+
+ /* clear PHY RST, then set it */
+ regmap_clear_bits(priv->ctrl, lane->ctrl_off + CTRL0, EPCS_PHYRESET_N);
+
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL0, EPCS_PHYRESET_N);
+
+ /* CTRL RST: SET -> delay 1 us -> CLEAR -> SET */
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL0, RESET_N);
+ udelay(1);
+ regmap_clear_bits(priv->ctrl, lane->ctrl_off + CTRL0, RESET_N);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL0, RESET_N);
+}
+
+static void imx8q_hsio_configure_clk_pad(struct phy *phy)
+{
+ bool pll = false;
+ u32 pad_mode;
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx8q_hsio_priv *priv = lane->priv;
+
+ pad_mode = priv->refclk_pad_mode;
+ if (pad_mode == IMX8_PCIE_REFCLK_PAD_OUTPUT) {
+ pll = true;
+ regmap_update_bits(priv->misc, CTRL0,
+ IOB_A_0_TXOE | IOB_A_0_M1M0_MASK,
+ IOB_A_0_TXOE | IOB_A_0_M1M0_2);
+ }
+
+ regmap_update_bits(priv->misc, CTRL0, IOB_RXENA, pll ? 0 : IOB_RXENA);
+ regmap_update_bits(priv->misc, CTRL0, IOB_TXENA, pll ? IOB_TXENA : 0);
+}
+
+static int imx8q_hsio_power_on(struct phy *phy)
+{
+ int ret;
+ u32 val, cond;
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx8q_hsio_priv *priv = lane->priv;
+
+ if (lane->lane_mode == PHY_MODE_PCIE)
+ imx8q_hsio_pcie_phy_resets(phy);
+ else
+ /* SATA */
+ regmap_set_bits(priv->phy, lane->phy_off + CTRL0, APB_RSTN_0);
+
+ if (priv->hsio_cfg & IMX8Q_HSIO_CFG_PCIEB)
+ regmap_set_bits(priv->misc, CTRL0, PCIE_AB_SELECT);
+ if (priv->hsio_cfg & IMX8Q_HSIO_CFG_SATA)
+ regmap_set_bits(priv->misc, CTRL0, PHYX1_EPCS_SEL);
+
+ imx8q_hsio_configure_clk_pad(phy);
+
+ if (lane->lane_mode == PHY_MODE_SATA) {
+ /*
+ * It is possible, for PCIe and SATA are sharing
+ * the same clock source, HPLL or external oscillator.
+ * When PCIe is in low power modes (L1.X or L2 etc),
+ * the clock source can be turned off. In this case,
+ * if this clock source is required to be toggling by
+ * SATA, then SATA functions will be abnormal.
+ * Set the override here to avoid it.
+ */
+ regmap_set_bits(priv->misc, CTRL0, CLKREQN_OUT_OVERRIDE);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL0, EPCS_TXDEEMP);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL0, EPCS_TXDEEMP_SEL);
+
+ imx8q_hsio_sata_phy_resets(phy);
+ } else {
+ /* Toggle apb_pclk to make sure clear the PM_REQ_CORE_RST bit */
+ clk_disable_unprepare(lane->clks[0].clk);
+ mdelay(1);
+ ret = clk_prepare_enable(lane->clks[0].clk);
+ if (ret) {
+ dev_err(priv->dev, "unable to enable phy apb_pclk\n");
+ return ret;
+ }
+
+ /* Bit19 PM_REQ_CORE_RST of pcie_stts0 should be cleared. */
+ ret = regmap_read_poll_timeout(priv->ctrl,
+ lane->ctrl_off + PCIE_STTS0,
+ val, (val & PM_REQ_CORE_RST) == 0,
+ PHY_INIT_WAIT_USLEEP_MAX,
+ PHY_INIT_WAIT_TIMEOUT);
+ if (ret) {
+ dev_err(priv->dev, "PM_REQ_CORE_RST is set\n");
+ return ret;
+ }
+ }
+
+ /* Polling to check the PHY is ready or not. */
+ if (lane->idx == 1)
+ cond = LANE1_TX_PLL_LOCK;
+ else
+ cond = LANE0_TX_PLL_LOCK;
+
+ ret = regmap_read_poll_timeout(priv->phy, lane->phy_off + PHY_STTS0,
+ val, ((val & cond) == cond),
+ PHY_INIT_WAIT_USLEEP_MAX, PHY_INIT_WAIT_TIMEOUT);
+ if (ret)
+ dev_err(priv->dev, "IMX8Q PHY%d PLL lock timeout\n", lane->idx);
+ else
+ dev_info(priv->dev, "IMX8Q PHY%d PLL is locked\n", lane->idx);
+
+ if (lane->lane_mode == PHY_MODE_SATA) {
+ cond = REG48_PMA_RDY;
+ ret = read_poll_timeout(readb, val, ((val & cond) == cond),
+ PHY_INIT_WAIT_USLEEP_MAX, PHY_INIT_WAIT_TIMEOUT,
+ false, priv->base + REG48_PMA_STATUS);
+ if (ret)
+ dev_err(priv->dev, "PHY calibration is timeout\n");
+ else
+ dev_info(priv->dev, "PHY calibration is done\n");
+ }
+
+ return ret;
+}
+
+static int imx8q_hsio_set_mode(struct phy *phy, enum phy_mode mode,
+ int submode)
+{
+ u32 val;
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx8q_hsio_priv *priv = lane->priv;
+
+ if (lane->lane_mode != mode)
+ return -EINVAL;
+
+ val = (mode == PHY_MODE_PCIE) ? MODE_PCIE : MODE_SATA;
+ val = FIELD_PREP(MODE_MASK, val);
+ regmap_update_bits(priv->phy, lane->phy_off + CTRL0, MODE_MASK, val);
+
+ switch (submode) {
+ case PHY_MODE_PCIE_RC:
+ val = FIELD_PREP(DEVICE_TYPE_MASK, PCI_EXP_TYPE_ROOT_PORT);
+ break;
+ case PHY_MODE_PCIE_EP:
+ val = FIELD_PREP(DEVICE_TYPE_MASK, PCI_EXP_TYPE_ENDPOINT);
+ break;
+ default: /* Support only PCIe EP and RC now. */
+ return 0;
+ }
+ if (submode)
+ regmap_update_bits(priv->ctrl, lane->ctrl_off + CTRL0,
+ DEVICE_TYPE_MASK, val);
+
+ return 0;
+}
+
+static int imx8q_hsio_set_speed(struct phy *phy, int speed)
+{
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx8q_hsio_priv *priv = lane->priv;
+
+ regmap_update_bits(priv->ctrl, lane->ctrl_off + CTRL2, LTSSM_ENABLE,
+ speed ? LTSSM_ENABLE : 0);
+ return 0;
+}
+
+static const struct phy_ops imx8q_hsio_ops = {
+ .init = imx8q_hsio_init,
+ .exit = imx8q_hsio_exit,
+ .power_on = imx8q_hsio_power_on,
+ .set_mode = imx8q_hsio_set_mode,
+ .set_speed = imx8q_hsio_set_speed,
+ .owner = THIS_MODULE,
+};
+
+static const struct imx8q_hsio_drvdata imx8qxp_serdes_drvdata = {
+ .num_lane = 1,
+};
+
+static const struct imx8q_hsio_drvdata imx8qm_serdes_drvdata = {
+ .num_lane = 3,
+};
+
+static const struct of_device_id imx8q_hsio_of_match[] = {
+ {.compatible = "fsl,imx8qxp-serdes", .data = &imx8qxp_serdes_drvdata},
+ {.compatible = "fsl,imx8qm-serdes", .data = &imx8qm_serdes_drvdata},
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, imx8q_hsio_of_match);
+
+static struct phy *imx8q_hsio_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct imx8q_hsio_priv *priv = dev_get_drvdata(dev);
+ int idx = args->args[0];
+ int ctrl_id = args->args[1];
+ int hsio_cfg = args->args[2];
+
+ if (idx >= priv->drvdata->num_lane)
+ return ERR_PTR(-EINVAL);
+ priv->lane[idx].idx = idx;
+ priv->lane[idx].ctrl_id = ctrl_id;
+ priv->hsio_cfg = hsio_cfg;
+
+ return priv->lane[idx].phy;
+}
+
+static int imx8q_hsio_probe(struct platform_device *pdev)
+{
+ int i;
+ void __iomem *off;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct of_device_id *of_id;
+ struct imx8q_hsio_priv *priv;
+ struct phy_provider *provider;
+
+ of_id = of_match_device(imx8q_hsio_of_match, dev);
+ if (!of_id)
+ return -EINVAL;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ priv->dev = &pdev->dev;
+ priv->drvdata = of_device_get_match_data(dev);
+
+ /* Get PHY refclk pad mode */
+ of_property_read_u32(np, "fsl,refclk-pad-mode", &priv->refclk_pad_mode);
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ off = devm_platform_ioremap_resource_byname(pdev, "phy");
+ priv->phy = devm_regmap_init_mmio(dev, off, ®map_config);
+ if (IS_ERR(priv->phy))
+ return dev_err_probe(dev, PTR_ERR(priv->phy),
+ "unable to find phy csr registers\n");
+
+ off = devm_platform_ioremap_resource_byname(pdev, "ctrl");
+ priv->ctrl = devm_regmap_init_mmio(dev, off, ®map_config);
+ if (IS_ERR(priv->ctrl))
+ return dev_err_probe(dev, PTR_ERR(priv->ctrl),
+ "unable to find ctrl csr registers\n");
+
+ off = devm_platform_ioremap_resource_byname(pdev, "misc");
+ priv->misc = devm_regmap_init_mmio(dev, off, ®map_config);
+ if (IS_ERR(priv->misc))
+ return dev_err_probe(dev, PTR_ERR(priv->misc),
+ "unable to find misc csr registers\n");
+
+ for (i = 0; i < priv->drvdata->num_lane; i++) {
+ struct imx8q_hsio_lane *lane = &priv->lane[i];
+ struct phy *phy;
+
+ memset(lane, 0, sizeof(*lane));
+
+ phy = devm_phy_create(&pdev->dev, NULL, &imx8q_hsio_ops);
+ if (IS_ERR(phy))
+ return PTR_ERR(phy);
+
+ lane->priv = priv;
+ lane->phy = phy;
+ lane->idx = i;
+ phy_set_drvdata(phy, lane);
+ }
+
+ dev_set_drvdata(dev, priv);
+ dev_set_drvdata(&pdev->dev, priv);
+
+ provider = devm_of_phy_provider_register(&pdev->dev, imx8q_hsio_xlate);
+
+ return PTR_ERR_OR_ZERO(provider);
+}
+
+static struct platform_driver imx8q_hsio_driver = {
+ .probe = imx8q_hsio_probe,
+ .driver = {
+ .name = "imx8q-hsio-phy",
+ .of_match_table = imx8q_hsio_of_match,
+ }
+};
+module_platform_driver(imx8q_hsio_driver);
+
+MODULE_DESCRIPTION("FSL IMX8Q HSIO SERDES PHY driver");
+MODULE_LICENSE("GPL");
--
2.37.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 REVIEW] hwrng: add exynos Secure World RNG device driver
From: Gowthami Thiagarajan @ 2024-03-29 7:55 UTC (permalink / raw)
To: Alexey Klimov
Cc: olivia, herbert, sehi.kim, linux-samsung-soc, peter.griffin,
krzysztof.kozlowski, alim.akhtar, linux-crypto, linux-arm-kernel,
linux-kernel, kernel-team, andre.draszik, willmcvicker, saravanak,
elder, tudor.ambarus, klimov.linux
In-Reply-To: <20240328125056.1054878-1-alexey.klimov@linaro.org>
On 2024-03-28 at 18:20:56, Alexey Klimov (alexey.klimov@linaro.org) wrote:
> The Exynos TRNG device is controlled by firmware and shared between
> non-secure world and secure world. Access to it is exposed via SMC
> interface which is implemented here. The firmware code does
> additional security checks, start-up test and some checks on resume.
>
> This device is found, for instance, in Google Tensor GS101-family
> of devices.
>
> Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
> ---
Hi Alexey Klimov,
Please find few comments inline.
> drivers/char/hw_random/Kconfig | 12 +
> drivers/char/hw_random/Makefile | 1 +
> drivers/char/hw_random/exynos-swd-trng.c | 423 +++++++++++++++++++++++
> 3 files changed, 436 insertions(+)
> create mode 100644 drivers/char/hw_random/exynos-swd-trng.c
>
> diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
> index 442c40efb200..bff7c3ec129a 100644
> --- a/drivers/char/hw_random/Kconfig
> +++ b/drivers/char/hw_random/Kconfig
> @@ -479,6 +479,18 @@ config HW_RANDOM_EXYNOS
>
> If unsure, say Y.
>
> +config HW_RANDOM_EXYNOS_SWD
> + tristate "Exynos SWD HW random number generator support"
> + default n
> + help
> + This driver provides kernel-side support for accessing Samsung
> + TRNG hardware located in secure world using smc calls.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called exynos-swd-trng.
> +
> + If unsure, say N.
> +
> config HW_RANDOM_OPTEE
> tristate "OP-TEE based Random Number Generator support"
> depends on OPTEE
> diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
> index 32549a1186dc..ce64929d461a 100644
> --- a/drivers/char/hw_random/Makefile
> +++ b/drivers/char/hw_random/Makefile
> @@ -15,6 +15,7 @@ obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o
> n2-rng-y := n2-drv.o n2-asm.o
> obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
> obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-trng.o
> +obj-$(CONFIG_HW_RANDOM_EXYNOS_SWD) += exynos-swd-trng.o
> obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
> obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
> obj-$(CONFIG_HW_RANDOM_OMAP3_ROM) += omap3-rom-rng.o
> diff --git a/drivers/char/hw_random/exynos-swd-trng.c b/drivers/char/hw_random/exynos-swd-trng.c
> new file mode 100644
> index 000000000000..29def8e6d0b7
> --- /dev/null
> +++ b/drivers/char/hw_random/exynos-swd-trng.c
> @@ -0,0 +1,423 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * exynos-swd-trng.c - Random Number Generator driver for the exynos TRNG
> + * located in secure world
> + * Copyright (C) Linaro Ltd 2024 Alexey Klimov <alexey.klimov@linaro.org>
> + *
> + * Based on downstream driver:
> + * Copyright (C) 2018 Samsung Electronics
> + * Sehee Kim <sehi.kim@samsung.com>
> + */
> +
> +#include <linux/arm-smccc.h>
> +#include <linux/delay.h>
> +#include <linux/hw_random.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +
> +/* DTRNG smc */
> +#define SMC_CMD_RANDOM (0x82001012)
> +
> +/* DTRNG smc commands */
> +#define HWRNG_INIT (0x0)
> +#define HWRNG_EXIT (0x1)
> +#define HWRNG_GET_DATA (0x2)
> +#define HWRNG_RESUME (0x3)
> +
> +#define HWRNG_RET_OK 0
> +#define HWRNG_RET_INVALID_ERROR 1
> +#define HWRNG_RET_RETRY_ERROR 2
> +#define HWRNG_RET_INVALID_FLAG_ERROR 3
> +#define HWRNG_RET_TEST_ERROR 4
> +#define HWRNG_RET_START_UP_TEST_DONE 5
> +#define HWRNG_RET_TEST_KAT_ERROR 0xC
> +
> +#define EXYRNG_START_UP_SIZE (4096 + 1)
> +#define EXYRNG_RETRY_MAX_COUNT 1000000
> +#define EXYRNG_START_UP_TEST_MAX_RETRY 2
> +
> +#define DRVNAME "exynos_swd_trng"
> +
> +enum state {
> + INACTIVE = 0,
> + ACTIVE,
> +};
> +
> +struct exyswd_rng {
> + struct hwrng rng;
> + enum state state;
> + struct device *dev;
> + /* to track and protect state of the device */
> + struct mutex lock;
> +};
> +
> +static int __exynos_cm_smc(u64 *arg0, u64 *arg1,
> + u64 *arg2, u64 *arg3)
> +{
> + struct arm_smccc_res res;
> +
> + arm_smccc_smc(*arg0, *arg1, *arg2, *arg3, 0, 0, 0, 0, &res);
> +
> + *arg0 = res.a0;
> + *arg1 = res.a1;
> + *arg2 = res.a2;
> + *arg3 = res.a3;
> +
> + return *arg0;
> +}
> +
> +static int exynos_cm_cmd(int cmd)
> +{
> + u64 reg0, reg1, reg2, reg3;
> +
> + reg0 = SMC_CMD_RANDOM;
> + reg1 = cmd;
> + reg3 = reg2 = 0;
> +
> + return __exynos_cm_smc(®0, ®1, ®2, ®3);
> +}
> +
> +static int exynos_cm_get_data(u64 *arg0, u64 *arg1,
> + u64 *arg2, u64 *arg3)
> +{
> + *arg0 = SMC_CMD_RANDOM;
> + *arg1 = HWRNG_GET_DATA;
> + *arg3 = 0;
> +
> + return __exynos_cm_smc(arg0, arg1, arg2, arg3);
> +}
Can you avoid implementing specific SMC calls in this driver?
Instead, is it possible to use arm_smccc_1_1_invoke passing
corresponding arguements?
> +
> +static int exynos_swd_get_data(u64 *arg0, u64 *arg1, u64 *arg2, u64 *arg3,
> + struct exyswd_rng *exyswd_rng)
> +{
> + u32 retry_cnt = 0;
> + int ret;
> +
> + while (retry_cnt++ < EXYRNG_RETRY_MAX_COUNT) {
> + ret = exynos_cm_get_data(arg0, arg1, arg2, arg3);
> +
> + if (ret == HWRNG_RET_OK)
> + return 0;
> +
> + if (ret == HWRNG_RET_RETRY_ERROR) {
> + usleep_range(50, 100);
> + continue;
> + }
> +
> + if (ret == HWRNG_RET_TEST_ERROR) {
> + dev_dbg(exyswd_rng->dev, "error while testing\n");
> + return -EAGAIN;
> + }
> +
> + return -EFAULT;
> + }
> +
> + ret = -EFAULT;
> + dev_warn(exyswd_rng->dev, "retry counter is reached\n");
> + return ret;
> +}
> +
> +static int exynos_swd_init(void)
> +{
> + u32 retry_cnt = 0;
> + int ret;
> +
> + do {
> + ret = exynos_cm_cmd(HWRNG_INIT);
> + if (ret == HWRNG_RET_RETRY_ERROR) {
> + if (retry_cnt++ > EXYRNG_RETRY_MAX_COUNT)
> + break;
> +
> + usleep_range(50, 100);
> + }
> + } while (ret == HWRNG_RET_RETRY_ERROR);
> +
> + return ret;
> +}
> +
> +static void exynos_swd_exit(void)
> +{
> + u32 retry_cnt = 0;
> +
> + while (retry_cnt++ < EXYRNG_RETRY_MAX_COUNT) {
> + if (!exynos_cm_cmd(HWRNG_EXIT))
> + break;
> + usleep_range(50, 100);
> + }
> +}
> +
> +static int exynos_swd_startup_test(struct exyswd_rng *exyswd_rng)
> +{
> + u64 reg0, reg1, reg2, reg3;
> + int start_up_size = EXYRNG_START_UP_SIZE;
> + u32 retry_cnt = 0;
> + int ret;
> +
> + ret = exynos_swd_init();
> + if (ret != HWRNG_RET_OK) {
> + if (ret == HWRNG_RET_TEST_ERROR) {
> + ret = -EAGAIN;
> + goto out;
> + } else
> + return -EFAULT;
> + }
> +
> + while (start_up_size > 0) {
> + /* For start-up test the 3-rd argument has to be set to 1 */
> + reg2 = 1;
Can this be changed to a #define constant for better clarity?
> + ret = exynos_cm_get_data(®0, ®1, ®2, ®3);
> + if (ret == HWRNG_RET_RETRY_ERROR) {
> + if (retry_cnt++ > EXYRNG_RETRY_MAX_COUNT) {
> + dev_warn(exyswd_rng->dev,
> + "exceeded retry in start-up test\n");
> + break;
> + }
> + usleep_range(50, 100);
> + continue;
> + }
> +
> + if (ret == HWRNG_RET_TEST_ERROR ||
> + ret == HWRNG_RET_TEST_KAT_ERROR) {
> + dev_err(exyswd_rng->dev,
> + "malfunction of TRNG(HW) is detected\n");
> + return -EFAULT;
> + }
> +
> + if (ret == HWRNG_RET_START_UP_TEST_DONE) {
> + dev_dbg(exyswd_rng->dev,
> + "start-up test is already done\n");
> + ret = 0;
> + break;
> + }
> +
> + if (ret != HWRNG_RET_OK) {
> + dev_dbg(exyswd_rng->dev, "failed to get random data\n");
> + return -EFAULT;
> + }
> +
> + start_up_size -= 32;
Similar to the above, please change this. And why 32 bytes?
> + retry_cnt = 0;
> + }
> +
> +out:
> + exynos_swd_exit();
> + return ret;
> +}
> +
> +static int exynos_swd_read(struct hwrng *rng, void *data, size_t max, bool wait)
> +{
> + struct exyswd_rng *exyswd_rng =
> + container_of(rng, struct exyswd_rng, rng);
> + u64 reg0, reg1, reg2, reg3;
> + u32 *read_buf = data;
> + u32 read_size = max;
> + u32 retry_cnt;
> + int ret = HWRNG_RET_OK;
> +
> + mutex_lock(&exyswd_rng->lock);
> + ret = exynos_swd_init();
> + if (ret != HWRNG_RET_OK) {
> + if (ret == HWRNG_RET_TEST_ERROR) {
> + ret = -EAGAIN;
> + goto out_locked;
> + } else {
> + mutex_unlock(&exyswd_rng->lock);
> + return -EFAULT;
> + }
> + }
> +
> + exyswd_rng->state = ACTIVE;
> + mutex_unlock(&exyswd_rng->lock);
> +
> + retry_cnt = 0;
> + while (read_size >= 8) {
> + reg2 = 0;
> + ret = exynos_swd_get_data(®0, ®1, ®2, ®3, exyswd_rng);
> + if (ret)
> + goto out;
> +
> + *(u32 *)(read_buf++) = (u32)reg2;
> + *(u32 *)(read_buf++) = (u32)reg3;
> +
> + read_size -= 8;
> + retry_cnt = 0;
> + }
> +
> + /*
> + * rng_buf_size is 32 bytes or cache line usually, it is unlikely
> + * we will have remaining bytes to read here.
> + */
> + if (unlikely(read_size > 0)) {
> + reg2 = 0;
> + ret = exynos_swd_get_data(®0, ®1, ®2, ®3, exyswd_rng);
> + if (ret)
> + goto out;
> + if (read_size >= 4) {
> + *(u32 *)(read_buf++) = (u32)reg2;
> + read_size -= 4;
> + }
> +
> + if (read_size) {
> + memcpy(read_buf, ®3, read_size);
> + read_size = 0;
> + }
> + }
> +
> + ret = max;
> +out:
> + mutex_lock(&exyswd_rng->lock);
> +out_locked:
> + exynos_swd_exit();
> + exyswd_rng->state = INACTIVE;
> + mutex_unlock(&exyswd_rng->lock);
> +
> + return ret;
> +}
> +
> +static int exyswd_rng_probe(struct platform_device *pdev)
> +{
> + struct exyswd_rng *exyswd_rng;
> + int ret;
> +
> + exyswd_rng = devm_kzalloc(&pdev->dev, sizeof(*exyswd_rng), GFP_KERNEL);
> + if (!exyswd_rng)
> + return -ENOMEM;
> +
> + exyswd_rng->rng.name = DRVNAME;
> + exyswd_rng->rng.read = exynos_swd_read;
> + exyswd_rng->rng.quality = 500;
> + exyswd_rng->dev = &pdev->dev;
> + exyswd_rng->state = INACTIVE;
> + mutex_init(&exyswd_rng->lock);
> +
> + /*
> + * Do the startup test first. If it works we've got the device
> + * and can finish probe().
> + */
> + ret = exynos_swd_startup_test(exyswd_rng);
> + if (ret) {
> + dev_dbg(&pdev->dev, "start-up test failed\n");
> + return -ENODEV;
> + }
> +
> + ret = devm_hwrng_register(&pdev->dev, &exyswd_rng->rng);
> + if (ret)
> + return dev_err_probe(&pdev->dev, ret,
> + "failed to register hwrng\n");
> +
> + platform_set_drvdata(pdev, exyswd_rng);
> + dev_set_drvdata(&pdev->dev, exyswd_rng);
> +
> + dev_info(&pdev->dev, "hwrng registered\n");
> +
> + return 0;
> +}
> +
> +static int exyswd_rng_remove(struct platform_device *pdev)
> +{
> + struct exyswd_rng *exyswd_rng = platform_get_drvdata(pdev);
> +
> + devm_hwrng_unregister(&pdev->dev, &exyswd_rng->rng);
> +
> + mutex_lock(&exyswd_rng->lock);
> + if (exyswd_rng->state == ACTIVE) {
> + exynos_swd_exit();
> + exyswd_rng->state = INACTIVE;
> + }
> + mutex_unlock(&exyswd_rng->lock);
> +
> + return 0;
> +}
> +
> +#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME)
> +static int exyswd_rng_suspend(struct device *dev)
> +{
> + struct exyswd_rng *exyswd_rng = dev_get_drvdata(dev);
> + int ret = 0;
> +
> + mutex_lock(&exyswd_rng->lock);
> + if (exyswd_rng->state) {
> + ret = exynos_cm_cmd(HWRNG_EXIT);
> + if (ret != HWRNG_RET_OK)
> + dev_warn(dev,
> + "failed to enter suspend, error %d\n", ret);
> + }
> + mutex_unlock(&exyswd_rng->lock);
> +
> + return ret;
> +}
> +
> +static int exyswd_rng_resume(struct device *dev)
> +{
> + struct exyswd_rng *exyswd_rng = dev_get_drvdata(dev);
> + int ret;
> +
> + mutex_lock(&exyswd_rng->lock);
> + ret = exynos_cm_cmd(HWRNG_RESUME);
> + if (ret != HWRNG_RET_OK)
> + dev_warn(dev, "failed to resume, error %d\n", ret);
> + if (exyswd_rng->state) {
> + ret = exynos_cm_cmd(HWRNG_INIT);
> + if (ret != HWRNG_RET_OK)
> + dev_warn(dev,
> + "failed to init hwrng on resume, error %d\n",
> + ret);
> + }
> + mutex_unlock(&exyswd_rng->lock);
> +
> + return ret;
> +}
> +#endif
> +
> +static UNIVERSAL_DEV_PM_OPS(exyswd_rng_pm_ops, exyswd_rng_suspend,
> + exyswd_rng_resume, NULL);
> +
> +static struct platform_driver exyswd_rng_driver = {
> + .probe = exyswd_rng_probe,
> + .remove = exyswd_rng_remove,
> + .driver = {
> + .name = DRVNAME,
> + .owner = THIS_MODULE,
> + .pm = &exyswd_rng_pm_ops,
> + },
> +};
> +
> +static struct platform_device *exyswd_rng_pdev;
> +
> +static int __init exyswd_rng_init(void)
> +{
> + int ret;
> +
> + exyswd_rng_pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
> + if (IS_ERR(exyswd_rng_pdev))
> + pr_err(DRVNAME ": could not register device: %ld\n",
> + PTR_ERR(exyswd_rng_pdev));
> +
> + ret = platform_driver_register(&exyswd_rng_driver);
> + if (ret) {
> + platform_device_unregister(exyswd_rng_pdev);
> + return ret;
> + }
> +
> + pr_info("ExyRNG driver, (c) 2014 Samsung Electronics\n");
> +
> + return 0;
> +}
> +
> +static void __exit exyswd_rng_exit(void)
> +{
> + platform_driver_unregister(&exyswd_rng_driver);
> + platform_device_unregister(exyswd_rng_pdev);
> +}
> +
> +module_init(exyswd_rng_init);
> +module_exit(exyswd_rng_exit);
> +
> +MODULE_DESCRIPTION("Exynos SWD H/W Random Number Generator driver");
> +MODULE_AUTHOR("Alexey Klimov <alexey.klimov@linaro.org>");
> +MODULE_AUTHOR("Sehee Kim <sehi.kim@samsung.com>");
> +MODULE_LICENSE("GPL");
> --
> 2.43.0
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [Upstream] [PATCH 0/2] i.MX93 ADC calibration settings
From: Primoz Fiser @ 2024-03-29 7:58 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Andrej Picej, Jonathan Cameron, devicetree, conor+dt, lars,
krzysztof.kozlowski+dt, imx, linux-iio, festevam, s.hauer,
upstream, linux-kernel, haibo.chen, kernel, shawnguo, robh,
linux-arm-kernel
In-Reply-To: <20240325144555.00002d16@Huawei.com>
Hi Jonathan,
On 25. 03. 24 15:45, Jonathan Cameron wrote:
> On Mon, 25 Mar 2024 09:55:23 +0100
> Primoz Fiser <primoz.fiser@norik.com> wrote:
>
>> Hi Jonathan,
>>
>> On 25. 03. 24 09:32, Andrej Picej wrote:
>>> Hi Jonathan,
>>>
>>> On 24. 03. 24 14:55, Jonathan Cameron wrote:
>>>> On Wed, 20 Mar 2024 11:04:04 +0100
>>>> Andrej Picej <andrej.picej@norik.com> wrote:
>>>>
>>>>> Hi all,
>>>>>
>>>>> we had some problems with failing ADC calibration on the i.MX93 boards.
>>>>> Changing default calibration settings fixed this. The board where this
>>>>> patches are useful is not yet upstream but will be soon (hopefully).
>>>>
>>>> Tell us more. My initial instinct is that this shouldn't be board
>>>> specific.
>>>> What's the trade off we are making here? Time vs precision of
>>>> calibration or
>>>> something else? If these are set to a level by default that doesn't work
>>>> for our board, maybe we should just change them for all devices?
>>>>
>>
>> The imx93_adc driver is quite new.
>>
>> If you look at line #162, you will find a comment by the original author:
>>
>>> /*
>>> * TODO: we use the default TSAMP/NRSMPL/AVGEN in MCR,
>>> * can add the setting of these bit if need in future.
>>> */
>>
>> URL:
>> https://github.com/torvalds/linux/blob/master/drivers/iio/adc/imx93_adc.c#L162
>>
>> So, for most use-cases the default setting should work, but why not make
>> them configurable?
>>
>> So this patch-series just implement what was missing from the beginning
>> / was planned for later.
> Hi Primoz,
>
> I doubt anyone reviewed the comment closely enough to say if what it was
> suggesting was sensible or not, so the fact it was listed as a todo
> doesn't directly impact this discussion.
I agree.
However on the other hand, since we stumbled upon a use-case that
requires adjusting the driver provided default settings of the i.MX93
ADC, this TODO to us is and was a clear indication from the original
author that the driver needs little TLC.
Anyhow, a stance from the author/NXP would be highly welcoming in this
situation.
BR,
Primoz
>
>>
>> BR,
>> Primoz
>>
>>
>>>
>>> So we have two different boards with the same SoC. On one, the
>>> calibration works with the default values, on the second one the
>>> calibration fails, which makes the ADC unusable. What the ADC lines
>>> measure differ between the boards though. But the implementation is
>>> nothing out of the ordinary.
>>>
>>> We tried different things but the only thing that helped is to use
>>> different calibration properties. We tried deferring the probe and
>>> calibration until later boot and after boot, but it did not help.
>>>
>>> In the Reference Manual [1] (chapter 72.5.1) it is written:
>>>
>>>> 4. Configure desired calibration settings (default values kept for
>>>> highest accuracy maximum time).
>>>
>>> So your assumption is correct, longer calibration time (more averaging
>>> samples) -> higher precision. The default values go for a high accuracy.
>>> And since we use a NRSMPL (Number of Averaging Samples) of 32 instead of
>>> default 512, we reduce the accuracy so the calibration values pass the
>>> internal defined limits.
>
> Ouch. Let me try to dig into this. Is this effectively relaxing the
> constraints? I guess because a value that is perhaps always biased one way
> is considered within bounds if those acceptable bounds are wider because
> of lower precision?
>
> I was assuming it was the other way around and the device had fixed constraint
> limits and you needed to take more samples due to higher noise. Seems the
> opposite is true here and that worries me.
>
> I'll definitely need input from NXP on this as a workaround and their
> strong support to consider it.
>
>>>
>>> I'm not sure that changing default values is the right solution here. We
>>> saw default values work with one of the boards. And since the NXP kept
>>> these values adjustable I think there is a reason behind it.
>
> I'd assume trade off between time and calibration precision, not the
> sort of use I think you are describing.
>
>>>
>>> Note: When I say one of the boards I mean one board form. So same board
>>> version, but different HW.
>
> Superficially I'm struggling to not see this as broken hardware that it
> is out of expected tolerances in some fashion. Maybe I misunderstood
> the issue.
>
> Jonathan
>
>>>
>>> Best regards,
>>> Andrej
>>>
>>> [1] i.MX 93 Applications Processor Reference Manual, Rev. 4, 12/2023
>>> _______________________________________________
>>> upstream mailing list
>>> upstream@lists.phytec.de
>>> http://lists.phytec.de/cgi-bin/mailman/listinfo/upstream
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
--
Primoz Fiser | phone: +386-41-390-545
<tel:+386-41-390-545> |
---------------------------------------------------------|
Norik systems d.o.o. | https://www.norik.com
<https://www.norik.com> |
Your embedded software partner | email: info@norik.com
<mailto:info@norik.com> |
Slovenia, EU | phone: +386-41-540-545
<tel:+386-41-540-545> |
_______________________________________________
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 v6 3/3] pinctrl: nuvoton: Add ma35d1 pinctrl and GPIO driver
From: Jacky Huang @ 2024-03-29 8:17 UTC (permalink / raw)
To: Linus Walleij
Cc: robh+dt, krzysztof.kozlowski+dt, conor+dt, p.zabel, j.neuschaefer,
linux-arm-kernel, linux-gpio, devicetree, linux-kernel, ychuang3,
schung
In-Reply-To: <CACRpkdYnG+SgrgAWW8+qdiBwO5d+nE8g_31Evyw0pA2dXz3BPw@mail.gmail.com>
Dear Linus,
Thanks for your review.
On 2024/3/28 下午 05:10, Linus Walleij wrote:
> Hi Jacky,
>
> overall this looks very good.
>
> On Wed, Mar 13, 2024 at 4:57 AM Jacky Huang <ychuang570808@gmail.com> wrote:
>
>
>> From: Jacky Huang <ychuang3@nuvoton.com>
>>
>> Add common pinctrl and GPIO driver for Nuvoton MA35 series SoC, and
>> add support for ma35d1 pinctrl.
>>
>> Signed-off-by: Jacky Huang <ychuang3@nuvoton.com>
> (...)
>> +static int ma35_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int selector,
>> + unsigned int group)
>> +{
>> + struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
>> + struct ma35_pin_group *grp = &npctl->groups[group];
>> + struct ma35_pin_setting *setting = grp->settings;
>> + u32 i, regval;
>> +
>> + dev_dbg(npctl->dev, "enable function %s group %s\n",
>> + npctl->functions[selector].name, npctl->groups[group].name);
>> +
>> + for (i = 0; i < grp->npins; i++) {
>> + regmap_read(npctl->regmap, setting->offset, ®val);
>> + regval &= ~GENMASK(setting->shift + 3, setting->shift);
> Add a comment explaining why you add +3
The pinmux selection is 4 bits. I will use a constant for the bitmask
width instead.
>
>> +static int ma35_gpio_core_direction_in(struct gpio_chip *gc, unsigned int gpio)
>> +{
>> + struct ma35_pin_bank *bank = gpiochip_get_data(gc);
>> + void __iomem *reg_mode = bank->reg_base + MA35_GP_REG_MODE;
>> + unsigned long flags;
>> + unsigned int regval;
>> +
>> + spin_lock_irqsave(&bank->lock, flags);
>> +
>> + regval = readl(reg_mode);
>> + regval &= ~GENMASK(gpio * 2 + 1, gpio * 2);
>> + regval |= MA35_GP_MODE_INPUT << gpio * 2;
> Here the first time you do this magic explain in a comment why you
> use *2+1 and *2 overall (I guess two bits per line).
Yes, it is two bits per pin. I will add a comment to explain this.
>> +static int ma35_gpio_core_get(struct gpio_chip *gc, unsigned int gpio)
>> +{
>> + struct ma35_pin_bank *bank = gpiochip_get_data(gc);
>> +
>> + return readl(bank->reg_base + MA35_PIN_MAP_BASE + gpio * 4);
> Here add a comment explaining the *4
> I guess one 32-bit register per pin?
Yes, it maps one 32-bit register to a gpio pin.
I will add a comment to explain this.
>> +static int ma35_irq_irqtype(struct irq_data *d, unsigned int type)
>> +{
>> + struct ma35_pin_bank *bank = gpiochip_get_data(irq_data_get_irq_chip_data(d));
>> + void __iomem *reg_itype = bank->reg_base + MA35_GP_REG_INTTYPE;
>> + void __iomem *reg_ien = bank->reg_base + MA35_GP_REG_INTEN;
>> + unsigned int num = (d->hwirq);
>> +
>> + if (type == IRQ_TYPE_PROBE) {
>> + writel(readl(reg_itype) & ~BIT(num), reg_itype);
>> + writel(readl(reg_ien) | BIT(num) | BIT(num + 16), reg_ien);
>> + bank->irqtype &= ~BIT(num);
>> + bank->irqinten |= BIT(num) | BIT(num + 16);
>> + return 0;
>> + }
>> +
>> + if (type & IRQ_TYPE_LEVEL_MASK) {
>> + writel(readl(reg_itype) | BIT(num), reg_itype);
>> + writel(readl(reg_ien) & ~(BIT(num) | BIT(num + 16)), reg_ien);
>> + bank->irqtype |= BIT(num);
>> + bank->irqinten &= ~(BIT(num) | BIT(num + 16));
>> + if (type == IRQ_TYPE_LEVEL_HIGH) {
>> + writel(readl(reg_ien) | BIT(num + 16), reg_ien);
>> + bank->irqinten |= BIT(num + 16);
>> + return 0;
>> + }
>> +
>> + if (type == IRQ_TYPE_LEVEL_LOW) {
>> + writel(readl(reg_ien) | BIT(num), reg_ien);
>> + bank->irqinten |= BIT(num);
>> + return 0;
>> + }
>> +
>> + } else {
>> + writel(readl(reg_itype) & ~BIT(num), reg_itype);
>> + bank->irqtype &= ~BIT(num);
>> +
>> + if (type & IRQ_TYPE_EDGE_RISING) {
>> + writel(readl(reg_ien) | BIT(num + 16), reg_ien);
>> + bank->irqinten |= BIT(num + 16);
>> +
>> + } else {
>> + writel(readl(reg_ien) & ~BIT(num + 16), reg_ien);
>> + bank->irqinten &= ~BIT(num + 16);
>> + }
>> +
>> + if (type & IRQ_TYPE_EDGE_FALLING) {
>> + writel(readl(reg_ien) | BIT(num), reg_ien);
>> + bank->irqinten |= BIT(num);
>> +
>> + } else {
>> + writel(readl(reg_ien) & ~BIT(num), reg_ien);
>> + bank->irqinten &= ~BIT(num);
>> + }
>> + }
>> + return 0;
>> +}
> I don't understand why you don't set the irq_handler:
> irq_set_handler_locked(d, handle_edge_irq);
> irq_set_handler_locked(d, handle_level_irq);
I will add the irq_set_handler_locked().
> It seems you are not handling IRQ_TYPE_EDGE_BOTH?
> What happens if both rising and falling is specified simultaneously?
>
> The if/else nesting is hard to read.
> switch (type) {
> case IRQ_TYPE_EDGE_BOTH:
> (...)
> case IRQ_TYPE_EDGE_RISING:
> (...)
>
> See drivers/gpio/gpio-ftgpio010.c for an example.
We'll refer to this driver to modify our code.
> Have you checked that handling edge and level IRQs really work
> as expected?
This driver works with edge or level IRQs in linux-5.10, and some
modifications
have been made for upstream. We'll verify if it also works in linux-6.9.
>> +static int ma35_gpiolib_register(struct platform_device *pdev, struct ma35_pinctrl *npctl)
>> +{
>> + struct ma35_pin_ctrl *ctrl = npctl->ctrl;
>> + struct ma35_pin_bank *bank = ctrl->pin_banks;
>> + int ret;
>> + int i;
>> +
>> + for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
>> + if (!bank->valid) {
>> + dev_warn(&pdev->dev, "bank %s is not valid\n",
>> + bank->np->name);
>> + continue;
>> + }
>> + bank->irqtype = 0;
>> + bank->irqinten = 0;
>> + bank->chip.label = bank->name;
>> + bank->chip.of_gpio_n_cells = 2;
>> + bank->chip.parent = &pdev->dev;
>> + bank->chip.request = ma35_gpio_core_to_request;
>> + bank->chip.direction_input = ma35_gpio_core_direction_in;
>> + bank->chip.direction_output = ma35_gpio_core_direction_out;
>> + bank->chip.get = ma35_gpio_core_get;
>> + bank->chip.set = ma35_gpio_core_set;
>> + bank->chip.base = -1;
>> + bank->chip.ngpio = bank->nr_pins;
>> + bank->chip.can_sleep = false;
>> + spin_lock_init(&bank->lock);
>> +
>> + if (bank->irq > 0) {
>> + struct gpio_irq_chip *girq;
>> +
>> + girq = &bank->chip.irq;
>> + gpio_irq_chip_set_chip(girq, &ma35_gpio_irqchip);
>> + girq->parent_handler = ma35_irq_demux_intgroup;
>> + girq->num_parents = 1;
>> +
>> + girq->parents = devm_kcalloc(&pdev->dev, 1, sizeof(*girq->parents),
>> + GFP_KERNEL);
>> + if (!girq->parents)
>> + return -ENOMEM;
>> +
>> + girq->parents[0] = bank->irq;
>> + girq->default_type = IRQ_TYPE_NONE;
>> + girq->handler = handle_level_irq;
> Does this really work for the edge IRQs?
>
> I recommend setting this to handle_bad_irq and assign the right
> handler in .set_type().
>
> Yours,
> Linus Walleij
OK, I will fix it.
Best Regards,
Jacky Huang
_______________________________________________
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 v3 3/4] PM: EM: Add em_dev_update_chip_binning()
From: kernel test robot @ 2024-03-29 8:20 UTC (permalink / raw)
To: Lukasz Luba, linux-kernel, linux-pm, rafael
Cc: oe-kbuild-all, lukasz.luba, dietmar.eggemann, linux-arm-kernel,
sboyd, nm, linux-samsung-soc, daniel.lezcano, viresh.kumar,
krzysztof.kozlowski, alim.akhtar, m.szyprowski, mhiramat
In-Reply-To: <20240328085112.3873050-4-lukasz.luba@arm.com>
Hi Lukasz,
kernel test robot noticed the following build warnings:
[auto build test WARNING on rafael-pm/linux-next]
[also build test WARNING on krzk/for-next clk/clk-next linus/master v6.9-rc1 next-20240328]
[cannot apply to soc/for-next rafael-pm/acpi-bus rafael-pm/devprop]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Lukasz-Luba/OPP-OF-Export-dev_opp_pm_calc_power-for-usage-from-EM/20240328-165357
base: https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
patch link: https://lore.kernel.org/r/20240328085112.3873050-4-lukasz.luba%40arm.com
patch subject: [PATCH v3 3/4] PM: EM: Add em_dev_update_chip_binning()
config: i386-buildonly-randconfig-002-20240328 (https://download.01.org/0day-ci/archive/20240329/202403291602.UyrrrpzO-lkp@intel.com/config)
compiler: gcc-12 (Ubuntu 12.3.0-9ubuntu2) 12.3.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240329/202403291602.UyrrrpzO-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202403291602.UyrrrpzO-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> kernel/power/energy_model.c:814: warning: bad line: information is present in the OPPs.
vim +814 kernel/power/energy_model.c
811
812 /**
813 * em_dev_update_chip_binning() - Update Energy Model after the new voltage
> 814 information is present in the OPPs.
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [v1 0/3] Add i.MX8Q HSIO PHY driver support
From: Richard Zhu @ 2024-03-29 8:09 UTC (permalink / raw)
To: vkoul, kishon, robh+dt, krzysztof.kozlowski+dt, conor+dt,
frank.li
Cc: hongxing.zhu, linux-phy, devicetree, linux-arm-kernel,
linux-kernel, kernel, linux-imx
v1 changes:
- Rebase to the 6.9-rc1, and constify of_phandle_args in xlate.
No other changes.
i.MX8Q HSIO module has PHY and mix control regions.
This patch-set adds i.MX8Q HSIO PHY driver support, and provides
standard PHY phandles that can be used by i.MX8Q PCIe or
SATA driver later.
[PATCH v1 1/3] dt-bindings: phy: Add i.MX8Q HSIO SerDes PHY binding
[PATCH v1 2/3] dt-bindings: phy: phy-imx8-pcie: Add binding for
[PATCH v1 3/3] phy: freescale: imx8q-hsio: Add i.MX8Q HSIO PHY driver
Documentation/devicetree/bindings/phy/fsl,imx8q-hsio.yaml | 143 ++++++++++++++++++++++++
drivers/phy/freescale/Kconfig | 8 ++
drivers/phy/freescale/Makefile | 1 +
drivers/phy/freescale/phy-fsl-imx8q-hsio.c | 518 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/dt-bindings/phy/phy-imx8-pcie.h | 26 +++++
5 files changed, 696 insertions(+)
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v1 1/3] dt-bindings: phy: Add i.MX8Q HSIO SerDes PHY binding
From: Richard Zhu @ 2024-03-29 8:09 UTC (permalink / raw)
To: vkoul, kishon, robh+dt, krzysztof.kozlowski+dt, conor+dt,
frank.li
Cc: hongxing.zhu, linux-phy, devicetree, linux-arm-kernel,
linux-kernel, kernel, linux-imx
In-Reply-To: <1711699790-16494-1-git-send-email-hongxing.zhu@nxp.com>
Add i.MX8QM and i.MX8QXP HSIO SerDes PHY binding.
- Use the controller ID to specify which controller is binded to the
PHY.
- Introduce one HSIO configuration, mandatory required to set
"PCIE_AB_SELECT" and "PHY_X1_EPCS_SEL" during the initialization.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
.../bindings/phy/fsl,imx8q-hsio.yaml | 143 ++++++++++++++++++
1 file changed, 143 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/fsl,imx8q-hsio.yaml
diff --git a/Documentation/devicetree/bindings/phy/fsl,imx8q-hsio.yaml b/Documentation/devicetree/bindings/phy/fsl,imx8q-hsio.yaml
new file mode 100644
index 000000000000..506551d4d94a
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/fsl,imx8q-hsio.yaml
@@ -0,0 +1,143 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/fsl,imx8q-hsio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX8Q SoC series HSIO SERDES PHY
+
+maintainers:
+ - Richard Zhu <hongxing.zhu@nxp.com>
+
+properties:
+ compatible:
+ enum:
+ - fsl,imx8qxp-serdes
+ - fsl,imx8qm-serdes
+ reg:
+ minItems: 4
+ maxItems: 4
+
+ "#phy-cells":
+ const: 3
+ description: |
+ The first number defines the ID of the PHY contained in the HSIO macro.
+ The second defines controller ID binded to the PHY. The third defines the
+ HSIO configuratons refer to the different use cases. They are defined in
+ dt-bindings/phy/phy-imx8-pcie.h
+
+ reg-names:
+ items:
+ - const: reg
+ - const: phy
+ - const: ctrl
+ - const: misc
+
+ clocks:
+ minItems: 5
+ maxItems: 14
+
+ clock-names:
+ minItems: 5
+ maxItems: 14
+
+ fsl,refclk-pad-mode:
+ description: |
+ Specifies the mode of the refclk pad used. It can be UNUSED(PHY
+ refclock is derived from SoC internal source), INPUT(PHY refclock
+ is provided externally via the refclk pad) or OUTPUT(PHY refclock
+ is derived from SoC internal source and provided on the refclk pad).
+ Refer include/dt-bindings/phy/phy-imx8-pcie.h for the constants
+ to be used.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 1, 2 ]
+
+ power-domains:
+ description: |
+ i.MX8Q HSIO SerDes power domains. i.MX8QXP has one SerDes power domains.
+ And i.MX8QM has two.
+ minItems: 1
+ maxItems: 2
+
+required:
+ - compatible
+ - reg
+ - "#phy-cells"
+ - clocks
+ - clock-names
+ - fsl,refclk-pad-mode
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx8qxp-serdes
+ then:
+ properties:
+ clock-names:
+ items:
+ - const: apb_pclk0
+ - const: pclk0
+ - const: phy0_crr
+ - const: ctl0_crr
+ - const: misc_crr
+ power-domains:
+ minItems: 1
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx8qm-serdes
+ then:
+ properties:
+ clock-names:
+ items:
+ - const: pclk0
+ - const: pclk1
+ - const: apb_pclk0
+ - const: apb_pclk1
+ - const: pclk2
+ - const: epcs_tx
+ - const: epcs_rx
+ - const: apb_pclk2
+ - const: phy0_crr
+ - const: phy1_crr
+ - const: ctl0_crr
+ - const: ctl1_crr
+ - const: ctl2_crr
+ - const: misc_crr
+ power-domains:
+ minItems: 2
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/imx8-clock.h>
+ #include <dt-bindings/clock/imx8-lpcg.h>
+ #include <dt-bindings/firmware/imx/rsrc.h>
+ #include <dt-bindings/phy/phy-imx8-pcie.h>
+
+ serdes: phy@5f1a0000 {
+ compatible = "fsl,imx8qxp-serdes";
+ reg = <0x5f1a0000 0x10000>,
+ <0x5f120000 0x10000>,
+ <0x5f140000 0x10000>,
+ <0x5f160000 0x10000>;
+ reg-names = "reg", "phy", "ctrl", "misc";
+ clocks = <&phyx1_lpcg IMX_LPCG_CLK_0>,
+ <&phyx1_lpcg IMX_LPCG_CLK_4>,
+ <&phyx1_crr1_lpcg IMX_LPCG_CLK_4>,
+ <&pcieb_crr3_lpcg IMX_LPCG_CLK_4>,
+ <&misc_crr5_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "apb_pclk0", "pclk0", "phy0_crr", "ctl0_crr",
+ "misc_crr";
+ power-domains = <&pd IMX_SC_R_SERDES_1>;
+ #phy-cells = <3>;
+ status = "disabled";
+ };
+...
--
2.37.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 v1 3/3] phy: freescale: imx8q-hsio: Add i.MX8Q HSIO PHY driver support
From: Richard Zhu @ 2024-03-29 8:09 UTC (permalink / raw)
To: vkoul, kishon, robh+dt, krzysztof.kozlowski+dt, conor+dt,
frank.li
Cc: hongxing.zhu, linux-phy, devicetree, linux-arm-kernel,
linux-kernel, kernel, linux-imx
In-Reply-To: <1711699790-16494-1-git-send-email-hongxing.zhu@nxp.com>
Add i.MX8Q HSIO PHY driver support.
- Add one HSIO configuration property, that used to select the
"PCIE_AB_SELECT" and "PHY_X1_EPCS_SEL" during the initialization.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
drivers/phy/freescale/Kconfig | 8 +
drivers/phy/freescale/Makefile | 1 +
drivers/phy/freescale/phy-fsl-imx8q-hsio.c | 518 +++++++++++++++++++++
3 files changed, 527 insertions(+)
create mode 100644 drivers/phy/freescale/phy-fsl-imx8q-hsio.c
diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig
index 853958fb2c06..bcddddef1cbb 100644
--- a/drivers/phy/freescale/Kconfig
+++ b/drivers/phy/freescale/Kconfig
@@ -35,6 +35,14 @@ config PHY_FSL_IMX8M_PCIE
Enable this to add support for the PCIE PHY as found on
i.MX8M family of SOCs.
+config PHY_FSL_IMX8Q_HSIO
+ tristate "Freescale i.MX8Q HSIO PHY"
+ depends on OF && HAS_IOMEM
+ select GENERIC_PHY
+ help
+ Enable this to add support for the HSIO PHY as found on
+ i.MX8Q family of SOCs.
+
endif
config PHY_FSL_LYNX_28G
diff --git a/drivers/phy/freescale/Makefile b/drivers/phy/freescale/Makefile
index cedb328bc4d2..db888c37fcf9 100644
--- a/drivers/phy/freescale/Makefile
+++ b/drivers/phy/freescale/Makefile
@@ -3,4 +3,5 @@ obj-$(CONFIG_PHY_FSL_IMX8MQ_USB) += phy-fsl-imx8mq-usb.o
obj-$(CONFIG_PHY_MIXEL_LVDS_PHY) += phy-fsl-imx8qm-lvds-phy.o
obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY) += phy-fsl-imx8-mipi-dphy.o
obj-$(CONFIG_PHY_FSL_IMX8M_PCIE) += phy-fsl-imx8m-pcie.o
+obj-$(CONFIG_PHY_FSL_IMX8Q_HSIO) += phy-fsl-imx8q-hsio.o
obj-$(CONFIG_PHY_FSL_LYNX_28G) += phy-fsl-lynx-28g.o
diff --git a/drivers/phy/freescale/phy-fsl-imx8q-hsio.c b/drivers/phy/freescale/phy-fsl-imx8q-hsio.c
new file mode 100644
index 000000000000..14fc925c4f57
--- /dev/null
+++ b/drivers/phy/freescale/phy-fsl-imx8q-hsio.c
@@ -0,0 +1,518 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 NXP
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/pci_regs.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/pcie.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/phy/phy-imx8-pcie.h>
+
+#define MAX_NUM_LANES 3
+#define LANE_NUM_CLKS 5
+
+/* Parameters for the waiting for PCIe PHY PLL to lock */
+#define PHY_INIT_WAIT_USLEEP_MAX 10
+#define PHY_INIT_WAIT_TIMEOUT (1000 * PHY_INIT_WAIT_USLEEP_MAX)
+
+/* i.MX8Q HSIO registers */
+#define CTRL0 0x0
+#define APB_RSTN_0 BIT(0)
+#define APB_RSTN_1 BIT(1)
+#define PIPE_RSTN_0_MASK GENMASK(25, 24)
+#define PIPE_RSTN_1_MASK GENMASK(27, 26)
+#define MODE_MASK GENMASK(20, 17)
+#define MODE_PCIE 0x0
+#define MODE_SATA 0x4
+#define DEVICE_TYPE_MASK GENMASK(27, 24)
+#define EPCS_TXDEEMP BIT(5)
+#define EPCS_TXDEEMP_SEL BIT(6)
+#define EPCS_PHYRESET_N BIT(7)
+#define RESET_N BIT(12)
+
+#define IOB_RXENA BIT(0)
+#define IOB_TXENA BIT(1)
+#define IOB_A_0_TXOE BIT(2)
+#define IOB_A_0_M1M0_2 BIT(4)
+#define IOB_A_0_M1M0_MASK GENMASK(4, 3)
+#define PHYX1_EPCS_SEL BIT(12)
+#define PCIE_AB_SELECT BIT(13)
+#define CLKREQN_OUT_OVERRIDE GENMASK(25, 24)
+
+#define PHY_STTS0 0x4
+#define LANE0_TX_PLL_LOCK BIT(4)
+#define LANE1_TX_PLL_LOCK BIT(12)
+
+#define CTRL2 0x8
+#define LTSSM_ENABLE BIT(4)
+#define BUTTON_RST_N BIT(21)
+#define PERST_N BIT(22)
+#define POWER_UP_RST_N BIT(23)
+
+#define PCIE_STTS0 0xc
+#define PM_REQ_CORE_RST BIT(19)
+
+#define REG48_PMA_STATUS 0x30
+#define REG48_PMA_RDY BIT(7)
+
+struct imx8q_hsio_drvdata {
+ int num_lane;
+};
+
+struct imx8q_hsio_lane {
+ const char * const *clk_names;
+ struct clk_bulk_data clks[LANE_NUM_CLKS];
+ u32 clks_cnt;
+ u32 ctrl_id;
+ u32 ctrl_off;
+ u32 idx;
+ u32 phy_off;
+ struct imx8q_hsio_priv *priv;
+ struct phy *phy;
+ enum phy_mode lane_mode;
+};
+
+struct imx8q_hsio_priv {
+ void __iomem *base;
+ struct device *dev;
+ u32 refclk_pad_mode;
+ u32 hsio_cfg;
+ struct regmap *phy;
+ struct regmap *ctrl;
+ struct regmap *misc;
+ const struct imx8q_hsio_drvdata *drvdata;
+ struct imx8q_hsio_lane lane[MAX_NUM_LANES];
+};
+
+static const char * const imx8q_hsio_lan0_pcie_clks[] = {"apb_pclk0", "pclk0",
+ "ctl0_crr", "phy0_crr", "misc_crr"};
+static const char * const imx8q_hsio_lan1_pciea_clks[] = {"apb_pclk1", "pclk1",
+ "ctl0_crr", "phy0_crr", "misc_crr"};
+static const char * const imx8q_hsio_lan1_pcieb_clks[] = {"apb_pclk1", "pclk1",
+ "ctl1_crr", "phy0_crr", "misc_crr"};
+static const char * const imx8q_hsio_lan2_pcieb_clks[] = {"apb_pclk2", "pclk2",
+ "ctl1_crr", "phy1_crr", "misc_crr"};
+static const char * const imx8q_hsio_lane_sata_clks[] = {"pclk2", "epcs_tx",
+ "epcs_rx", "phy1_crr", "misc_crr"};
+
+static const struct regmap_config regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static int imx8q_hsio_init(struct phy *phy)
+{
+ int ret, i;
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx8q_hsio_priv *priv = lane->priv;
+ struct device *dev = priv->dev;
+
+ /* Assign clocks refer to different modes */
+ switch (lane->ctrl_id) {
+ case IMX8Q_HSIO_PCIEA_ID:
+ if (lane->idx > 1) {
+ dev_err(dev, "invalid lane ID.");
+ return -EINVAL;
+ }
+
+ lane->lane_mode = PHY_MODE_PCIE;
+ lane->ctrl_off = 0;
+ lane->phy_off = 0;
+
+ for (i = 0; i < LANE_NUM_CLKS; i++) {
+ if (lane->idx)
+ lane->clks[i].id = imx8q_hsio_lan1_pciea_clks[i];
+ else
+ lane->clks[i].id = imx8q_hsio_lan0_pcie_clks[i];
+ }
+ break;
+ case IMX8Q_HSIO_PCIEB_ID:
+ if (lane->idx > 2) {
+ dev_err(dev, "invalid lane ID.");
+ return -EINVAL;
+ }
+
+ lane->lane_mode = PHY_MODE_PCIE;
+ if (lane->idx == 0) {
+ /* i.MX8QXP */
+ lane->ctrl_off = 0;
+ lane->phy_off = 0;
+ } else {
+ /*
+ * On i.MX8QM, only second or third lane PHY can
+ * be binded to PCIEB.
+ */
+ lane->ctrl_off = SZ_64K;
+ if (lane->idx == 1)
+ lane->phy_off = 0;
+ else /* idx == 2, the third lane is binded to PCIEB */
+ lane->phy_off = SZ_64K;
+ }
+
+ for (i = 0; i < LANE_NUM_CLKS; i++) {
+ if (lane->idx == 1)
+ lane->clks[i].id = imx8q_hsio_lan1_pcieb_clks[i];
+ else if (lane->idx == 2)
+ lane->clks[i].id = imx8q_hsio_lan2_pcieb_clks[i];
+ else /* i.MX8QXP only has PCIEB, it's idx == 0 */
+ lane->clks[i].id = imx8q_hsio_lan0_pcie_clks[i];
+
+ }
+ break;
+ case IMX8Q_HSIO_SATA_ID:
+ /* On i.MX8QM, only the third lane PHY can be binded to SATA */
+ if (lane->idx != 2) {
+ dev_err(dev, "invalid lane ID.");
+ return -EINVAL;
+ }
+ lane->ctrl_off = SZ_128K;
+ lane->lane_mode = PHY_MODE_SATA;
+ lane->phy_off = SZ_64K;
+
+ for (i = 0; i < LANE_NUM_CLKS; i++)
+ lane->clks[i].id = imx8q_hsio_lane_sata_clks[i];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Fetch clocks */
+ ret = devm_clk_bulk_get(dev, LANE_NUM_CLKS, lane->clks);
+ if (ret)
+ return ret;
+
+ ret = clk_bulk_prepare_enable(LANE_NUM_CLKS, lane->clks);
+ if (ret)
+ return ret;
+
+ /* allow the clocks to stabilize */
+ usleep_range(200, 500);
+ return 0;
+}
+
+static int imx8q_hsio_exit(struct phy *phy)
+{
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+
+ clk_bulk_disable_unprepare(LANE_NUM_CLKS, lane->clks);
+
+ return 0;
+}
+
+static void imx8q_hsio_pcie_phy_resets(struct phy *phy)
+{
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx8q_hsio_priv *priv = lane->priv;
+
+ regmap_clear_bits(priv->ctrl, lane->ctrl_off + CTRL2, BUTTON_RST_N);
+ regmap_clear_bits(priv->ctrl, lane->ctrl_off + CTRL2, PERST_N);
+ regmap_clear_bits(priv->ctrl, lane->ctrl_off + CTRL2, POWER_UP_RST_N);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL2, BUTTON_RST_N);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL2, PERST_N);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL2, POWER_UP_RST_N);
+
+ if (lane->idx == 1) {
+ /* The second lane */
+ regmap_set_bits(priv->phy, lane->phy_off + CTRL0, APB_RSTN_1);
+ regmap_set_bits(priv->phy, lane->phy_off + CTRL0, PIPE_RSTN_1_MASK);
+ } else {
+ regmap_set_bits(priv->phy, lane->phy_off + CTRL0, APB_RSTN_0);
+ regmap_set_bits(priv->phy, lane->phy_off + CTRL0, PIPE_RSTN_0_MASK);
+ }
+}
+
+static void imx8q_hsio_sata_phy_resets(struct phy *phy)
+{
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx8q_hsio_priv *priv = lane->priv;
+
+ /* clear PHY RST, then set it */
+ regmap_clear_bits(priv->ctrl, lane->ctrl_off + CTRL0, EPCS_PHYRESET_N);
+
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL0, EPCS_PHYRESET_N);
+
+ /* CTRL RST: SET -> delay 1 us -> CLEAR -> SET */
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL0, RESET_N);
+ udelay(1);
+ regmap_clear_bits(priv->ctrl, lane->ctrl_off + CTRL0, RESET_N);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL0, RESET_N);
+}
+
+static void imx8q_hsio_configure_clk_pad(struct phy *phy)
+{
+ bool pll = false;
+ u32 pad_mode;
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx8q_hsio_priv *priv = lane->priv;
+
+ pad_mode = priv->refclk_pad_mode;
+ if (pad_mode == IMX8_PCIE_REFCLK_PAD_OUTPUT) {
+ pll = true;
+ regmap_update_bits(priv->misc, CTRL0,
+ IOB_A_0_TXOE | IOB_A_0_M1M0_MASK,
+ IOB_A_0_TXOE | IOB_A_0_M1M0_2);
+ }
+
+ regmap_update_bits(priv->misc, CTRL0, IOB_RXENA, pll ? 0 : IOB_RXENA);
+ regmap_update_bits(priv->misc, CTRL0, IOB_TXENA, pll ? IOB_TXENA : 0);
+}
+
+static int imx8q_hsio_power_on(struct phy *phy)
+{
+ int ret;
+ u32 val, cond;
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx8q_hsio_priv *priv = lane->priv;
+
+ if (lane->lane_mode == PHY_MODE_PCIE)
+ imx8q_hsio_pcie_phy_resets(phy);
+ else
+ /* SATA */
+ regmap_set_bits(priv->phy, lane->phy_off + CTRL0, APB_RSTN_0);
+
+ if (priv->hsio_cfg & IMX8Q_HSIO_CFG_PCIEB)
+ regmap_set_bits(priv->misc, CTRL0, PCIE_AB_SELECT);
+ if (priv->hsio_cfg & IMX8Q_HSIO_CFG_SATA)
+ regmap_set_bits(priv->misc, CTRL0, PHYX1_EPCS_SEL);
+
+ imx8q_hsio_configure_clk_pad(phy);
+
+ if (lane->lane_mode == PHY_MODE_SATA) {
+ /*
+ * It is possible, for PCIe and SATA are sharing
+ * the same clock source, HPLL or external oscillator.
+ * When PCIe is in low power modes (L1.X or L2 etc),
+ * the clock source can be turned off. In this case,
+ * if this clock source is required to be toggling by
+ * SATA, then SATA functions will be abnormal.
+ * Set the override here to avoid it.
+ */
+ regmap_set_bits(priv->misc, CTRL0, CLKREQN_OUT_OVERRIDE);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL0, EPCS_TXDEEMP);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + CTRL0, EPCS_TXDEEMP_SEL);
+
+ imx8q_hsio_sata_phy_resets(phy);
+ } else {
+ /* Toggle apb_pclk to make sure clear the PM_REQ_CORE_RST bit */
+ clk_disable_unprepare(lane->clks[0].clk);
+ mdelay(1);
+ ret = clk_prepare_enable(lane->clks[0].clk);
+ if (ret) {
+ dev_err(priv->dev, "unable to enable phy apb_pclk\n");
+ return ret;
+ }
+
+ /* Bit19 PM_REQ_CORE_RST of pcie_stts0 should be cleared. */
+ ret = regmap_read_poll_timeout(priv->ctrl,
+ lane->ctrl_off + PCIE_STTS0,
+ val, (val & PM_REQ_CORE_RST) == 0,
+ PHY_INIT_WAIT_USLEEP_MAX,
+ PHY_INIT_WAIT_TIMEOUT);
+ if (ret) {
+ dev_err(priv->dev, "PM_REQ_CORE_RST is set\n");
+ return ret;
+ }
+ }
+
+ /* Polling to check the PHY is ready or not. */
+ if (lane->idx == 1)
+ cond = LANE1_TX_PLL_LOCK;
+ else
+ cond = LANE0_TX_PLL_LOCK;
+
+ ret = regmap_read_poll_timeout(priv->phy, lane->phy_off + PHY_STTS0,
+ val, ((val & cond) == cond),
+ PHY_INIT_WAIT_USLEEP_MAX, PHY_INIT_WAIT_TIMEOUT);
+ if (ret)
+ dev_err(priv->dev, "IMX8Q PHY%d PLL lock timeout\n", lane->idx);
+ else
+ dev_info(priv->dev, "IMX8Q PHY%d PLL is locked\n", lane->idx);
+
+ if (lane->lane_mode == PHY_MODE_SATA) {
+ cond = REG48_PMA_RDY;
+ ret = read_poll_timeout(readb, val, ((val & cond) == cond),
+ PHY_INIT_WAIT_USLEEP_MAX, PHY_INIT_WAIT_TIMEOUT,
+ false, priv->base + REG48_PMA_STATUS);
+ if (ret)
+ dev_err(priv->dev, "PHY calibration is timeout\n");
+ else
+ dev_info(priv->dev, "PHY calibration is done\n");
+ }
+
+ return ret;
+}
+
+static int imx8q_hsio_set_mode(struct phy *phy, enum phy_mode mode,
+ int submode)
+{
+ u32 val;
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx8q_hsio_priv *priv = lane->priv;
+
+ if (lane->lane_mode != mode)
+ return -EINVAL;
+
+ val = (mode == PHY_MODE_PCIE) ? MODE_PCIE : MODE_SATA;
+ val = FIELD_PREP(MODE_MASK, val);
+ regmap_update_bits(priv->phy, lane->phy_off + CTRL0, MODE_MASK, val);
+
+ switch (submode) {
+ case PHY_MODE_PCIE_RC:
+ val = FIELD_PREP(DEVICE_TYPE_MASK, PCI_EXP_TYPE_ROOT_PORT);
+ break;
+ case PHY_MODE_PCIE_EP:
+ val = FIELD_PREP(DEVICE_TYPE_MASK, PCI_EXP_TYPE_ENDPOINT);
+ break;
+ default: /* Support only PCIe EP and RC now. */
+ return 0;
+ }
+ if (submode)
+ regmap_update_bits(priv->ctrl, lane->ctrl_off + CTRL0,
+ DEVICE_TYPE_MASK, val);
+
+ return 0;
+}
+
+static int imx8q_hsio_set_speed(struct phy *phy, int speed)
+{
+ struct imx8q_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx8q_hsio_priv *priv = lane->priv;
+
+ regmap_update_bits(priv->ctrl, lane->ctrl_off + CTRL2, LTSSM_ENABLE,
+ speed ? LTSSM_ENABLE : 0);
+ return 0;
+}
+
+static const struct phy_ops imx8q_hsio_ops = {
+ .init = imx8q_hsio_init,
+ .exit = imx8q_hsio_exit,
+ .power_on = imx8q_hsio_power_on,
+ .set_mode = imx8q_hsio_set_mode,
+ .set_speed = imx8q_hsio_set_speed,
+ .owner = THIS_MODULE,
+};
+
+static const struct imx8q_hsio_drvdata imx8qxp_serdes_drvdata = {
+ .num_lane = 1,
+};
+
+static const struct imx8q_hsio_drvdata imx8qm_serdes_drvdata = {
+ .num_lane = 3,
+};
+
+static const struct of_device_id imx8q_hsio_of_match[] = {
+ {.compatible = "fsl,imx8qxp-serdes", .data = &imx8qxp_serdes_drvdata},
+ {.compatible = "fsl,imx8qm-serdes", .data = &imx8qm_serdes_drvdata},
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, imx8q_hsio_of_match);
+
+static struct phy *imx8q_hsio_xlate(struct device *dev,
+ const struct of_phandle_args *args)
+{
+ struct imx8q_hsio_priv *priv = dev_get_drvdata(dev);
+ int idx = args->args[0];
+ int ctrl_id = args->args[1];
+ int hsio_cfg = args->args[2];
+
+ if (idx >= priv->drvdata->num_lane)
+ return ERR_PTR(-EINVAL);
+ priv->lane[idx].idx = idx;
+ priv->lane[idx].ctrl_id = ctrl_id;
+ priv->hsio_cfg = hsio_cfg;
+
+ return priv->lane[idx].phy;
+}
+
+static int imx8q_hsio_probe(struct platform_device *pdev)
+{
+ int i;
+ void __iomem *off;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct of_device_id *of_id;
+ struct imx8q_hsio_priv *priv;
+ struct phy_provider *provider;
+
+ of_id = of_match_device(imx8q_hsio_of_match, dev);
+ if (!of_id)
+ return -EINVAL;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ priv->dev = &pdev->dev;
+ priv->drvdata = of_device_get_match_data(dev);
+
+ /* Get PHY refclk pad mode */
+ of_property_read_u32(np, "fsl,refclk-pad-mode", &priv->refclk_pad_mode);
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ off = devm_platform_ioremap_resource_byname(pdev, "phy");
+ priv->phy = devm_regmap_init_mmio(dev, off, ®map_config);
+ if (IS_ERR(priv->phy))
+ return dev_err_probe(dev, PTR_ERR(priv->phy),
+ "unable to find phy csr registers\n");
+
+ off = devm_platform_ioremap_resource_byname(pdev, "ctrl");
+ priv->ctrl = devm_regmap_init_mmio(dev, off, ®map_config);
+ if (IS_ERR(priv->ctrl))
+ return dev_err_probe(dev, PTR_ERR(priv->ctrl),
+ "unable to find ctrl csr registers\n");
+
+ off = devm_platform_ioremap_resource_byname(pdev, "misc");
+ priv->misc = devm_regmap_init_mmio(dev, off, ®map_config);
+ if (IS_ERR(priv->misc))
+ return dev_err_probe(dev, PTR_ERR(priv->misc),
+ "unable to find misc csr registers\n");
+
+ for (i = 0; i < priv->drvdata->num_lane; i++) {
+ struct imx8q_hsio_lane *lane = &priv->lane[i];
+ struct phy *phy;
+
+ memset(lane, 0, sizeof(*lane));
+
+ phy = devm_phy_create(&pdev->dev, NULL, &imx8q_hsio_ops);
+ if (IS_ERR(phy))
+ return PTR_ERR(phy);
+
+ lane->priv = priv;
+ lane->phy = phy;
+ lane->idx = i;
+ phy_set_drvdata(phy, lane);
+ }
+
+ dev_set_drvdata(dev, priv);
+ dev_set_drvdata(&pdev->dev, priv);
+
+ provider = devm_of_phy_provider_register(&pdev->dev, imx8q_hsio_xlate);
+
+ return PTR_ERR_OR_ZERO(provider);
+}
+
+static struct platform_driver imx8q_hsio_driver = {
+ .probe = imx8q_hsio_probe,
+ .driver = {
+ .name = "imx8q-hsio-phy",
+ .of_match_table = imx8q_hsio_of_match,
+ }
+};
+module_platform_driver(imx8q_hsio_driver);
+
+MODULE_DESCRIPTION("FSL IMX8Q HSIO SERDES PHY driver");
+MODULE_LICENSE("GPL");
--
2.37.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 v1 2/3] dt-bindings: phy: phy-imx8-pcie: Add binding for i.MX8Q HSIO SerDes PHY
From: Richard Zhu @ 2024-03-29 8:09 UTC (permalink / raw)
To: vkoul, kishon, robh+dt, krzysztof.kozlowski+dt, conor+dt,
frank.li
Cc: hongxing.zhu, linux-phy, devicetree, linux-arm-kernel,
linux-kernel, kernel, linux-imx
In-Reply-To: <1711699790-16494-1-git-send-email-hongxing.zhu@nxp.com>
Add binding for controller ID and HSIO configuration setting of the
i.MX8Q HSIO SerDes PHY.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
include/dt-bindings/phy/phy-imx8-pcie.h | 26 +++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/include/dt-bindings/phy/phy-imx8-pcie.h b/include/dt-bindings/phy/phy-imx8-pcie.h
index 8bbe2d6538d8..5cd5580879fa 100644
--- a/include/dt-bindings/phy/phy-imx8-pcie.h
+++ b/include/dt-bindings/phy/phy-imx8-pcie.h
@@ -11,4 +11,30 @@
#define IMX8_PCIE_REFCLK_PAD_INPUT 1
#define IMX8_PCIE_REFCLK_PAD_OUTPUT 2
+/*
+ * i.MX8QM HSIO subsystem has three lane PHYs and three controllers:
+ * PCIEA(2 lanes capapble PCIe controller), PCIEB (only support one
+ * lane) and SATA.
+ * In the different use cases. PCIEA can be binded to PHY lane0, lane1
+ * or Lane0 and lane1. PCIEB can be binded to lane1 or lane2 PHY. SATA
+ * can only be binded to last lane2 PHY.
+ * Define i.MX8Q HSIO controller ID here to specify the controller
+ * binded to the PHY.
+ * Meanwhile, i.MX8QXP HSIO subsystem has one lane PHY and PCIEB(only
+ * support one lane) controller.
+ */
+#define IMX8Q_HSIO_PCIEA_ID 0
+#define IMX8Q_HSIO_PCIEB_ID 1
+#define IMX8Q_HSIO_SATA_ID 2
+
+/*
+ * On i.MX8QM, PCIEA is mandatory required if the HSIO is enabled.
+ * Define configurations beside PCIEA is enabled.
+ * On i.MX8QXP, HSIO module only has PCIEB and one lane PHY.
+ * The "IMX8Q_HSIO_CFG_PCIEB" can be used on i.MX8QXP platforms.
+ */
+#define IMX8Q_HSIO_CFG_SATA 1
+#define IMX8Q_HSIO_CFG_PCIEB 2
+#define IMX8Q_HSIO_CFG_PCIEBSATA 3
+
#endif /* _DT_BINDINGS_IMX8_PCIE_H */
--
2.37.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 v11 00/11] Support page table check PowerPC
From: Christophe Leroy @ 2024-03-29 8:29 UTC (permalink / raw)
To: Rohan McLure, linuxppc-dev@lists.ozlabs.org
Cc: mpe@ellerman.id.au, linux-mm@kvack.org,
linux-riscv@lists.infradead.org,
linux-arm-kernel@lists.infradead.org, x86@kernel.org
In-Reply-To: <eb906bc3-b372-449b-a351-eb739ffa7418@csgroup.eu>
Le 28/03/2024 à 08:57, Christophe Leroy a écrit :
>
>
> Le 28/03/2024 à 07:52, Christophe Leroy a écrit :
>>
>>
>> Le 28/03/2024 à 05:55, Rohan McLure a écrit :
>>> Support page table check on all PowerPC platforms. This works by
>>> serialising assignments, reassignments and clears of page table
>>> entries at each level in order to ensure that anonymous mappings
>>> have at most one writable consumer, and likewise that file-backed
>>> mappings are not simultaneously also anonymous mappings.
>>>
>>> In order to support this infrastructure, a number of stubs must be
>>> defined for all powerpc platforms. Additionally, seperate set_pte_at()
>>> and set_pte_at_unchecked(), to allow for internal, uninstrumented
>>> mappings.
>>
>> I gave it a try on QEMU e500 (64 bits), and get the following Oops.
>> What do I have to look for ?
>>
>> Freeing unused kernel image (initmem) memory: 2588K
>> This architecture does not have kernel memory protection.
>> Run /init as init process
>> ------------[ cut here ]------------
>> kernel BUG at mm/page_table_check.c:119!
>> Oops: Exception in kernel mode, sig: 5 [#1]
>> BE PAGE_SIZE=4K SMP NR_CPUS=32 QEMU e500
>
> Same problem on my 8xx board:
>
> [ 7.358146] Freeing unused kernel image (initmem) memory: 448K
> [ 7.363957] Run /init as init process
> [ 7.370955] ------------[ cut here ]------------
> [ 7.375411] kernel BUG at mm/page_table_check.c:119!
> [ 7.380393] Oops: Exception in kernel mode, sig: 5 [#1]
> [ 7.385621] BE PAGE_SIZE=16K PREEMPT CMPC885
Both problems are fixed by following change:
diff --git a/arch/powerpc/include/asm/nohash/pgtable.h
b/arch/powerpc/include/asm/nohash/pgtable.h
index 413d01a51e6f..5b932632a5d7 100644
--- a/arch/powerpc/include/asm/nohash/pgtable.h
+++ b/arch/powerpc/include/asm/nohash/pgtable.h
@@ -29,6 +29,8 @@ static inline pte_basic_t pte_update(struct mm_struct
*mm, unsigned long addr, p
#ifndef __ASSEMBLY__
+#include <linux/page_table_check.h>
+
extern int icache_44x_need_flush;
/*
@@ -92,7 +94,11 @@ static inline void ptep_set_wrprotect(struct
mm_struct *mm, unsigned long addr,
static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned
long addr,
pte_t *ptep)
{
- return __pte(pte_update(mm, addr, ptep, ~0UL, 0, 0));
+ pte_t old_pte = __pte(pte_update(mm, addr, ptep, ~0UL, 0, 0));
+
+ page_table_check_pte_clear(mm, addr, old_pte);
+
+ return old_pte;
}
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
_______________________________________________
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