Linux Serial subsystem development
 help / color / mirror / Atom feed
* Re: [PATCH 1/3] dt-bindings: serial: Add binding for Cortina-Access UART
From: Krzysztof Kozlowski @ 2026-06-10 11:51 UTC (permalink / raw)
  To: Jason Li, jason.li, Greg Kroah-Hartman, Jiri Slaby
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
	Will Deacon, Arnd Bergmann, linux-serial, linux-arm-kernel,
	devicetree, linux-kernel
In-Reply-To: <20260610112821.3030099-3-jason.li@cortina-access.com>

On 10/06/2026 13:28, Jason Li wrote:
> +
> +allOf:
> +  - $ref: serial.yaml#
> +
> +properties:
> +  compatible:
> +    const: cortina-access,serial

Aren't writing bindings very clear about that? Please, take your time to
read through the docs, so we will not need to repeat basic guidance. It
is documented there on purpose.


Best regards,
Krzysztof

^ permalink raw reply

* Re: [PATCH 3/3] arm64: dts: cortina-access: Add DTS for CA8289 SoC and Venus board
From: Krzysztof Kozlowski @ 2026-06-10 11:49 UTC (permalink / raw)
  To: Jason Li, jason.li, Greg Kroah-Hartman, Jiri Slaby
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
	Will Deacon, Arnd Bergmann, linux-serial, linux-arm-kernel,
	devicetree, linux-kernel
In-Reply-To: <20260610112821.3030099-5-jason.li@cortina-access.com>

On 10/06/2026 13:28, Jason Li wrote:
> Add SoC DTSI for the Cortina-Access CA8289 (Venus) and a board DTS for
> the Venus engineering board. The description covers the minimum set of
> hardware nodes needed to boot a kernel with an INITRD rootfs: CPUs,
> GIC, timer, PSCI, fixed clock and UART.
> 
> Signed-off-by: Jason Li <jason.li@cortina-access.com>
> Assisted-by: Claude:claude-opus-4-8

SoB should be the last tag.

Also, it does not match From field.

> ---
>  MAINTAINERS                                   |   1 +
>  arch/arm64/Kconfig.platforms                  |  10 ++
>  arch/arm64/boot/dts/Makefile                  |   1 +
>  arch/arm64/boot/dts/cortina-access/Makefile   |   2 +
>  .../dts/cortina-access/ca8289-engboard.dts    |  31 +++++
>  .../boot/dts/cortina-access/ca8289-soc.dtsi   | 118 ++++++++++++++++++
>  6 files changed, 163 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/cortina-access/Makefile
>  create mode 100644 arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts
>  create mode 100644 arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 515d89d96472..ebfdb9c267cc 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2826,6 +2826,7 @@ L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
>  S:	Maintained
>  F:	Documentation/devicetree/bindings/arm/cortina-access.yaml
>  F:	Documentation/devicetree/bindings/serial/cortina-access,serial.yaml
> +F:	arch/arm64/boot/dts/cortina-access/
>  
>  ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE
>  M:	Hans Ulli Kroll <ulli.kroll@googlemail.com>
> diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
> index dc995a732117..ba6dda0660c3 100644
> --- a/arch/arm64/Kconfig.platforms
> +++ b/arch/arm64/Kconfig.platforms
> @@ -134,6 +134,16 @@ config ARCH_CIX
>  	  This enables support for the Cixtech SoC family,
>  	  like P1(sky1).
>  
> +config ARCH_CORTINA_ACCESS
> +	bool "Cortina-Access SoC Family"
> +	select GPIOLIB
> +	select PINCTRL
> +	help
> +	  This enables support for Cortina-Access SoCs.  The family
> +	  includes ARMv8-based devices targeting networking and access
> +	  applications.
> +	  If you have a Cortina-Access board, say Y here.
> +
>  config ARCH_EXYNOS
>  	bool "Samsung Exynos SoC family"
>  	select COMMON_CLK_SAMSUNG
> diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
> index 98ec8f1b76e4..a599f525fb9a 100644
> --- a/arch/arm64/boot/dts/Makefile
> +++ b/arch/arm64/boot/dts/Makefile
> @@ -16,6 +16,7 @@ subdir-y += broadcom
>  subdir-y += bst
>  subdir-y += cavium
>  subdir-y += cix
> +subdir-y += cortina-access
>  subdir-y += exynos
>  subdir-y += freescale
>  subdir-y += hisilicon
> diff --git a/arch/arm64/boot/dts/cortina-access/Makefile b/arch/arm64/boot/dts/cortina-access/Makefile
> new file mode 100644
> index 000000000000..554893f381fe
> --- /dev/null
> +++ b/arch/arm64/boot/dts/cortina-access/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0
> +dtb-$(CONFIG_ARCH_CORTINA_ACCESS) += ca8289-engboard.dtb
> diff --git a/arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts b/arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts
> new file mode 100644
> index 000000000000..c8289a0f8269
> --- /dev/null
> +++ b/arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts
> @@ -0,0 +1,31 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * dts file for Cortina Access Venus Engineering Board
> + *
> + * Copyright (C) 2026, Cortina Access Inc.
> + *
> + */
> +
> +/dts-v1/;
> +
> +#include "ca8289-soc.dtsi"
> +
> +/ {
> +	model = "Cortina Access Venus Engineering Board";
> +	compatible = "cortina-access,ca8289-engboard";
> +	#address-cells = <2>;
> +	#size-cells = <2>;
> +
> +	aliases {
> +		serial0 = &uart0;
> +	};
> +
> +	chosen {
> +		stdout-path = "serial0:115200n8";
> +	};
> +
> +	memory@0 {	/* 512MB */
> +		device_type = "memory";
> +		reg = <0x00000000 0x00000000 0x0 0x20000000>;
> +	};
> +};
> diff --git a/arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi b/arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi
> new file mode 100644
> index 000000000000..8e7ffcf4ccab
> --- /dev/null
> +++ b/arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi
> @@ -0,0 +1,118 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * dts file for Cortina Access CA8289 SoC
> + *
> + * Copyright (C) 2026, Cortina Access Inc.
> + */
> +
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/interrupt-controller/irq.h>
> +
> +/ {
> +	cpus {
> +		#address-cells = <2>;
> +		#size-cells = <0>;
> +
> +		cpu0: cpu@0 {
> +			compatible = "arm,cortex-a55", "arm,armv8";
> +			device_type = "cpu";
> +			reg = <0x0 0x0>;
> +			enable-method = "psci";
> +		};

Missing blank lines. Look at existing code how this is supposed to look
like.

> +		cpu1: cpu@100 {
> +			compatible = "arm,cortex-a55", "arm,armv8";
> +			device_type = "cpu";
> +			reg = <0x0 0x100>;
> +			enable-method = "psci";
> +		};
> +		cpu2: cpu@200 {
> +			compatible = "arm,cortex-a55", "arm,armv8";
> +			device_type = "cpu";
> +			reg = <0x0 0x200>;
> +			enable-method = "psci";
> +		};
> +		cpu3: cpu@300 {
> +			compatible = "arm,cortex-a55", "arm,armv8";
> +			device_type = "cpu";
> +			reg = <0x0 0x300>;
> +			enable-method = "psci";
> +		};
> +		cpu-map {
> +			cluster0 {
> +				core0 {
> +					cpu = <&cpu0>;
> +				};
> +				core1 {
> +					cpu = <&cpu1>;
> +				};
> +				core2 {
> +					cpu = <&cpu2>;
> +				};
> +				core3 {
> +					cpu = <&cpu3>;
> +				};
> +			};
> +		};
> +	};
> +
> +	psci {
> +		compatible = "arm,psci-0.2";
> +		method = "smc";
> +	};
> +
> +	gic: interrupt-controller@4f8000000 {

And now you repeat basic mistakes:
1. Pointed out by W=1 dtbs_check build
2. Fixed long time in every source
3. Explicitly documented in writing bindings and DTS coding style


> +		compatible = "arm,gic-v3";
> +		#interrupt-cells = <3>;
> +		interrupt-controller;
> +		#redistributor-regions = <1>;
> +		reg = <0x00000004 0xF8000000 0 0x10000>,
> +		      <0x00000004 0xF8040000 0 0x80000>;

Read DTS coding style.

> +	};
> +
> +	apb_pclk: apb-pclk {

Nope, drop entire node.

> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <125000000>;
> +	};
> +
> +	reserved-memory {
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +		ranges;
> +
> +		/* TrustZone reserved region; must not be mapped by the kernel */
> +		tz_pool: tz-buffer@f000000 {
> +			reg = <0x0 0x0F000000 0x0 0x1000000>;
> +			no-map;
> +		};
> +	};
> +
> +	/* See Documentation/devicetree/bindings/timer/arm,arch_timer.yaml */
> +	timer {
> +		compatible = "arm,armv8-timer";
> +		interrupt-parent = <&gic>;
> +		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
> +			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
> +		clock-frequency = <25000000>;
> +	};
> +
> +	uart0: serial@f4329188 {
> +		device_type = "serial";
> +		compatible = "cortina-access,serial";
> +		reg = <0x00000000 0xf4329188 0x0 0x30>;

This is AI slop. Whatever Claude convinced you to do, it is nothing like
upstream kernel source.

Best regards,
Krzysztof

^ permalink raw reply

* Re: [PATCH 1/3] dt-bindings: serial: Add binding for Cortina-Access UART
From: Krzysztof Kozlowski @ 2026-06-10 11:46 UTC (permalink / raw)
  To: Jason Li, jason.li, Greg Kroah-Hartman, Jiri Slaby
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
	Will Deacon, Arnd Bergmann, linux-serial, linux-arm-kernel,
	devicetree, linux-kernel
In-Reply-To: <20260610112821.3030099-3-jason.li@cortina-access.com>

On 10/06/2026 13:28, Jason Li wrote:
> Add DT binding schema for the Cortina-Access UART controller.
> This IP is integrated into most CAXXXX SoC family members.
> 
> Also add the vendor prefix for Cortina Access, Inc. and the
> top-level ARM board binding document for the CA8289 (Venus) SoC.
> 
> Signed-off-by: Jason Li <jason.li@cortina-access.com>
> Assisted-by: Claude:claude-opus-4-8
> ---
>  .../bindings/arm/cortina-access.yaml          | 29 ++++++++++++
>  .../serial/cortina-access,serial.yaml         | 46 +++++++++++++++++++
>  .../devicetree/bindings/vendor-prefixes.yaml  |  2 +
>  MAINTAINERS                                   |  7 +++

This is somehow complete mess. serial and arm together?

Please carefully read submitting patches (both documents!) and don't
send AI-assisted slop.

You must not combine independent works together.


>  4 files changed, 84 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/cortina-access.yaml
>  create mode 100644 Documentation/devicetree/bindings/serial/cortina-access,serial.yaml
> 
> diff --git a/Documentation/devicetree/bindings/arm/cortina-access.yaml b/Documentation/devicetree/bindings/arm/cortina-access.yaml
> new file mode 100644
> index 000000000000..ec0320ed0c0b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/cortina-access.yaml
> @@ -0,0 +1,29 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/arm/cortina-access.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Cortina-Access SoC boards
> +
> +maintainers:
> +  - Jason Li <jason.li@cortina-access.com>
> +
> +description:
> +  Boards based on Cortina-Access ARMv8 SoCs targeting networking and
> +  access applications.
> +
> +properties:
> +  $nodename:
> +    const: /
> +  compatible:
> +    oneOf:
> +      - description: Cortina-Access CA8289 (Venus) engineering board
> +        const: cortina-access,ca8289-engboard
> +
> +      - description: Cortina-Access CA8289 (Venus) reference board
> +        const: cortina-access,ca8289-refboard


Where is the SoC? This looks like very poor contribution. If you opened
any existing recent board binding you would see it is done differently.

Best regards,
Krzysztof

^ permalink raw reply

* [PATCH 3/3] arm64: dts: cortina-access: Add DTS for CA8289 SoC and Venus board
From: Jason Li @ 2026-06-10 11:28 UTC (permalink / raw)
  To: jason.li, Greg Kroah-Hartman, Jiri Slaby
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
	Will Deacon, Arnd Bergmann, linux-serial, linux-arm-kernel,
	devicetree, linux-kernel
In-Reply-To: <20260610112821.3030099-1-jason.li@cortina-access.com>

Add SoC DTSI for the Cortina-Access CA8289 (Venus) and a board DTS for
the Venus engineering board. The description covers the minimum set of
hardware nodes needed to boot a kernel with an INITRD rootfs: CPUs,
GIC, timer, PSCI, fixed clock and UART.

Signed-off-by: Jason Li <jason.li@cortina-access.com>
Assisted-by: Claude:claude-opus-4-8
---
 MAINTAINERS                                   |   1 +
 arch/arm64/Kconfig.platforms                  |  10 ++
 arch/arm64/boot/dts/Makefile                  |   1 +
 arch/arm64/boot/dts/cortina-access/Makefile   |   2 +
 .../dts/cortina-access/ca8289-engboard.dts    |  31 +++++
 .../boot/dts/cortina-access/ca8289-soc.dtsi   | 118 ++++++++++++++++++
 6 files changed, 163 insertions(+)
 create mode 100644 arch/arm64/boot/dts/cortina-access/Makefile
 create mode 100644 arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts
 create mode 100644 arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi

diff --git a/MAINTAINERS b/MAINTAINERS
index 515d89d96472..ebfdb9c267cc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2826,6 +2826,7 @@ L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	Documentation/devicetree/bindings/arm/cortina-access.yaml
 F:	Documentation/devicetree/bindings/serial/cortina-access,serial.yaml
+F:	arch/arm64/boot/dts/cortina-access/
 
 ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE
 M:	Hans Ulli Kroll <ulli.kroll@googlemail.com>
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index dc995a732117..ba6dda0660c3 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -134,6 +134,16 @@ config ARCH_CIX
 	  This enables support for the Cixtech SoC family,
 	  like P1(sky1).
 
+config ARCH_CORTINA_ACCESS
+	bool "Cortina-Access SoC Family"
+	select GPIOLIB
+	select PINCTRL
+	help
+	  This enables support for Cortina-Access SoCs.  The family
+	  includes ARMv8-based devices targeting networking and access
+	  applications.
+	  If you have a Cortina-Access board, say Y here.
+
 config ARCH_EXYNOS
 	bool "Samsung Exynos SoC family"
 	select COMMON_CLK_SAMSUNG
diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
index 98ec8f1b76e4..a599f525fb9a 100644
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -16,6 +16,7 @@ subdir-y += broadcom
 subdir-y += bst
 subdir-y += cavium
 subdir-y += cix
+subdir-y += cortina-access
 subdir-y += exynos
 subdir-y += freescale
 subdir-y += hisilicon
diff --git a/arch/arm64/boot/dts/cortina-access/Makefile b/arch/arm64/boot/dts/cortina-access/Makefile
new file mode 100644
index 000000000000..554893f381fe
--- /dev/null
+++ b/arch/arm64/boot/dts/cortina-access/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_CORTINA_ACCESS) += ca8289-engboard.dtb
diff --git a/arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts b/arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts
new file mode 100644
index 000000000000..c8289a0f8269
--- /dev/null
+++ b/arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dts file for Cortina Access Venus Engineering Board
+ *
+ * Copyright (C) 2026, Cortina Access Inc.
+ *
+ */
+
+/dts-v1/;
+
+#include "ca8289-soc.dtsi"
+
+/ {
+	model = "Cortina Access Venus Engineering Board";
+	compatible = "cortina-access,ca8289-engboard";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@0 {	/* 512MB */
+		device_type = "memory";
+		reg = <0x00000000 0x00000000 0x0 0x20000000>;
+	};
+};
diff --git a/arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi b/arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi
new file mode 100644
index 000000000000..8e7ffcf4ccab
--- /dev/null
+++ b/arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dts file for Cortina Access CA8289 SoC
+ *
+ * Copyright (C) 2026, Cortina Access Inc.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			compatible = "arm,cortex-a55", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+		};
+		cpu1: cpu@100 {
+			compatible = "arm,cortex-a55", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x100>;
+			enable-method = "psci";
+		};
+		cpu2: cpu@200 {
+			compatible = "arm,cortex-a55", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x200>;
+			enable-method = "psci";
+		};
+		cpu3: cpu@300 {
+			compatible = "arm,cortex-a55", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x0 0x300>;
+			enable-method = "psci";
+		};
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&cpu0>;
+				};
+				core1 {
+					cpu = <&cpu1>;
+				};
+				core2 {
+					cpu = <&cpu2>;
+				};
+				core3 {
+					cpu = <&cpu3>;
+				};
+			};
+		};
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	gic: interrupt-controller@4f8000000 {
+		compatible = "arm,gic-v3";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		#redistributor-regions = <1>;
+		reg = <0x00000004 0xF8000000 0 0x10000>,
+		      <0x00000004 0xF8040000 0 0x80000>;
+	};
+
+	apb_pclk: apb-pclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <125000000>;
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* TrustZone reserved region; must not be mapped by the kernel */
+		tz_pool: tz-buffer@f000000 {
+			reg = <0x0 0x0F000000 0x0 0x1000000>;
+			no-map;
+		};
+	};
+
+	/* See Documentation/devicetree/bindings/timer/arm,arch_timer.yaml */
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+		clock-frequency = <25000000>;
+	};
+
+	uart0: serial@f4329188 {
+		device_type = "serial";
+		compatible = "cortina-access,serial";
+		reg = <0x00000000 0xf4329188 0x0 0x30>;
+		clocks = <&apb_pclk>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	uart1: serial@f43291b8 {
+		device_type = "serial";
+		compatible = "cortina-access,serial";
+		reg = <0x00000000 0xf43291b8 0x0 0x30>;
+		clocks = <&apb_pclk>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+	};
+};
-- 
2.39.5


^ permalink raw reply related

* [PATCH 2/3] tty: serial: Add UART driver for Cortina-Access platform
From: Jason Li @ 2026-06-10 11:28 UTC (permalink / raw)
  To: jason.li, Greg Kroah-Hartman, Jiri Slaby
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
	Will Deacon, Arnd Bergmann, linux-serial, linux-arm-kernel,
	devicetree, linux-kernel
In-Reply-To: <20260610112821.3030099-1-jason.li@cortina-access.com>

This driver supports Cortina Access UART IP integrated
in most CAXXXX line of SoCs. Earlycon is also supported.

Signed-off-by: Jason Li <jason.li@cortina-access.com>
Assisted-by: Claude:claude-opus-4-8
---
 MAINTAINERS                                |   6 +
 drivers/tty/serial/Kconfig                 |  21 +
 drivers/tty/serial/Makefile                |   1 +
 drivers/tty/serial/serial_cortina-access.c | 755 +++++++++++++++++++++
 4 files changed, 783 insertions(+)
 create mode 100644 drivers/tty/serial/serial_cortina-access.c

diff --git a/MAINTAINERS b/MAINTAINERS
index cc261888fae0..515d89d96472 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6687,6 +6687,12 @@ S:	Maintained
 F:	Documentation/hwmon/corsair-psu.rst
 F:	drivers/hwmon/corsair-psu.c
 
+CORTINA-ACCESS SERIAL CONSOLE DRIVER
+M:	Jason Li <jason.li@cortina-access.com>
+L:	linux-serial@vger.kernel.org
+S:	Supported
+F:	drivers/tty/serial/serial_cortina-access.c
+
 COUNTER SUBSYSTEM
 M:	William Breathitt Gray <wbg@kernel.org>
 L:	linux-iio@vger.kernel.org
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index cf7dba473b20..99a1c9308395 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1592,6 +1592,27 @@ config SERIAL_NUVOTON_MA35D1_CONSOLE
 	  but you can alter that using a kernel command line option such as
 	  "console=ttyNVTx".
 
+config SERIAL_CORTINA_ACCESS
+	tristate "Cortina-Access serial port support"
+	depends on OF
+	select SERIAL_CORE
+	help
+	  This driver is for the Cortina-Access SoC UART, present in the
+	  CA8289 (Venus) and related CAXXXX family of SoCs. If you have a
+	  machine based on the Cortina-Access SoC and wish to use the serial
+	  port, say 'Y' here. Otherwise, say 'N'.
+
+config SERIAL_CORTINA_ACCESS_CONSOLE
+	bool "Console on Cortina-Access serial port"
+	depends on SERIAL_CORTINA_ACCESS=y
+	select SERIAL_CORE_CONSOLE
+	select SERIAL_EARLYCON
+	help
+	  Say 'Y' here if you wish to use the Cortina-Access UART as the system
+	  console (the device which receives all kernel messages and warnings
+	  and which allows logins in single user mode).
+	  /dev/ttyS* is the default device node.
+
 endmenu
 
 config SERIAL_MCTRL_GPIO
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index bba7b21a4a1d..54866c419714 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -98,3 +98,4 @@ obj-$(CONFIG_SERIAL_MCTRL_GPIO)	+= serial_mctrl_gpio.o
 
 obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
 obj-$(CONFIG_SERIAL_NUVOTON_MA35D1) += ma35d1_serial.o
+obj-$(CONFIG_SERIAL_CORTINA_ACCESS) += serial_cortina-access.o
diff --git a/drivers/tty/serial/serial_cortina-access.c b/drivers/tty/serial/serial_cortina-access.c
new file mode 100644
index 000000000000..f25eae987ccd
--- /dev/null
+++ b/drivers/tty/serial/serial_cortina-access.c
@@ -0,0 +1,755 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  UART driver for Cortina-Access SoC platform
+ *  Copyright (C) 2026 Cortina-Access Inc.
+ */
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/sysrq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
+/***************************************
+ *	UART Related registers
+ ****************************************/
+/* register definitions */
+#define	CFG			0x00
+#define	FC			0x04
+#define	RX_SAMPLE		0x08
+#define	RT_TUNE			0x0C
+#define	TX_DAT			0x10
+#define	RX_DAT			0x14
+#define	INFO			0x18
+#define	IE			0x1C
+#define	INT			0x24
+#define	STATUS			0x2C
+
+/* CFG */
+#define	CFG_STOP_2BIT		BIT(2)
+#define	CFG_PARITY_EVEN		BIT(3)
+#define	CFG_PARITY_EN		BIT(4)
+#define	CFG_TX_EN		BIT(5)
+#define	CFG_RX_EN		BIT(6)
+#define	CFG_UART_EN		BIT(7)
+#define	CFG_BAUD_SART_SHIFT	8
+
+/* INFO */
+#define	INFO_TX_EMPTY		BIT(3)
+#define	INFO_TX_FULL		BIT(2)
+#define	INFO_RX_EMPTY		BIT(1)
+#define	INFO_RX_FULL		BIT(0)
+
+/* Interrupt */
+#define	RX_BREAK		BIT(7)
+#define	RX_FIFO_NONEMPTYE	BIT(6)
+#define	TX_FIFO_EMPTYE		BIT(5)
+#define	RX_FIFO_UNDERRUNE	BIT(4)
+#define	RX_FIFO_OVERRUNE	BIT(3)
+#define	RX_PARITY_ERRE		BIT(2)
+#define	RX_STOP_ERRE		BIT(1)
+#define	TX_FIFO_OVERRUNE	BIT(0)
+
+#define TX_TIMEOUT		5000
+#define UART_NR			4
+#define CA_UART_NAME_LEN	32
+
+struct cortina_uart_port {
+	struct uart_port uart;
+	char name[CA_UART_NAME_LEN];
+	char has_bi;
+	unsigned int may_wakeup;
+};
+
+static struct cortina_uart_port *cortina_uart_ports;
+
+static irqreturn_t cortina_uart_interrupt(int irq, void *dev_id);
+static inline void cortina_uart_interrupt_tx_chars(struct uart_port *port);
+
+/* Return uart_port pointer based on index */
+static struct cortina_uart_port *cortina_uart_get_port(unsigned int index)
+{
+	struct cortina_uart_port *pca_port = cortina_uart_ports;
+
+	if (index >= UART_NR)
+		index = 0;
+
+	pca_port += index;
+
+	return pca_port;
+}
+
+/* uart_ops functions */
+static unsigned int cortina_uart_tx_empty(struct uart_port *port)
+{
+	/* Return 0 on FIFO full condition, TIOCSER_TEMT otherwise */
+	return (readl(port->membase + INFO) & INFO_TX_EMPTY) ? TIOCSER_TEMT : 0;
+}
+
+static void cortina_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	/*
+	 * Even if we do not support configuring the modem control lines, this
+	 * function must be provided to the serial core.
+	 * port->ops->set_mctrl() is called in uart_configure_port()
+	 */
+}
+
+static unsigned int cortina_uart_get_mctrl(struct uart_port *port)
+{
+	/* Unimplemented signals asserted, per Documentation/serial/driver */
+	return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+}
+
+static void cortina_uart_stop_tx(struct uart_port *port)
+{
+	/* Turn off Tx interrupts. The port lock is held at this point */
+	unsigned int reg_v;
+
+	reg_v = readl(port->membase + IE);
+	writel(reg_v & ~TX_FIFO_EMPTYE, port->membase + IE);
+}
+
+static void cortina_uart_start_tx(struct uart_port *port)
+{
+	/* Turn on Tx interrupts. The port lock is held at this point */
+	unsigned int reg_v;
+
+	reg_v = readl(port->membase + IE);
+	writel(reg_v | TX_FIFO_EMPTYE, port->membase + IE);
+
+	reg_v = readl(port->membase + CFG);
+	writel(reg_v | CFG_TX_EN, port->membase + CFG);
+
+	/*
+	 * If TX FIFO is already empty the TX_FIFO_EMPTY interrupt may be
+	 * edge-triggered and won't fire again.  Kick-start the transmission
+	 * explicitly so the first character is not lost.
+	 */
+	if (readl(port->membase + INFO) & INFO_TX_EMPTY)
+		cortina_uart_interrupt_tx_chars(port);
+}
+
+static void cortina_uart_stop_rx(struct uart_port *port)
+{
+	/* Turn off Rx interrupts. The port lock is held at this point */
+	unsigned int reg_v;
+
+	reg_v = readl(port->membase + IE);
+	writel(reg_v & ~RX_FIFO_NONEMPTYE, port->membase + IE);
+}
+
+static void cortina_uart_enable_ms(struct uart_port *port)
+{
+	/* Nope, you really can't hope to attach a modem to this */
+}
+
+static int cortina_uart_startup(struct uart_port *port)
+{
+	unsigned int reg_v;
+	int retval;
+	unsigned long flags;
+
+	/* Disable interrupts */
+	writel(0, port->membase + IE);
+
+	retval = request_irq(port->irq, cortina_uart_interrupt, 0,
+			     "cortina_uart", port);
+	if (retval)
+		return retval;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	reg_v = readl(port->membase + CFG);
+	reg_v |= (CFG_UART_EN | CFG_TX_EN | CFG_RX_EN | 0x3 /* 8-bits data */);
+	writel(reg_v, port->membase + CFG);
+	reg_v = readl(port->membase + IE);
+	writel(reg_v | RX_FIFO_NONEMPTYE | TX_FIFO_EMPTYE, port->membase + IE);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+	return 0;
+}
+
+static void cortina_uart_shutdown(struct uart_port *port)
+{
+	cortina_uart_stop_tx(port);
+	cortina_uart_stop_rx(port);
+	free_irq(port->irq, port);
+}
+
+static void cortina_uart_set_termios(struct uart_port *port,
+				     struct ktermios *termios,
+				     const struct ktermios *old)
+{
+	unsigned long flags;
+	int baud;
+	unsigned int reg_v, sample_freq = 0;
+
+	baud = uart_get_baud_rate(port, termios, old, 0, 230400);
+	reg_v = readl(port->membase + CFG);
+	/* mask off the baud settings */
+	reg_v &= 0xff;
+	reg_v |= (port->uartclk / baud) << CFG_BAUD_SART_SHIFT;
+
+	/* Sampling rate should be half of baud count */
+	sample_freq = (reg_v >> CFG_BAUD_SART_SHIFT) / 2;
+
+	/* See include/uapi/asm-generic/termbits.h for CSIZE definition */
+	/* mask off the data width */
+	reg_v &= 0xfffffffc;
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		reg_v |= 0x0;
+		break;
+	case CS6:
+		reg_v |= 0x1;
+		break;
+	case CS7:
+		reg_v |= 0x2;
+		break;
+	case CS8:
+	default:
+		reg_v |= 0x3;
+		break;
+	}
+
+	/* mask off Stop bits */
+	reg_v &= ~(CFG_STOP_2BIT);
+	if (termios->c_cflag & CSTOPB)
+		reg_v |= CFG_STOP_2BIT;
+
+	/* Parity */
+	reg_v &= ~(CFG_PARITY_EN);
+	reg_v |= CFG_PARITY_EVEN;
+	if (termios->c_cflag & PARENB) {
+		reg_v |= CFG_PARITY_EN;
+		if (termios->c_cflag & PARODD)
+			reg_v &= ~(CFG_PARITY_EVEN);
+	}
+
+	spin_lock_irqsave(&port->lock, flags);
+	writel(reg_v, port->membase + CFG);
+	writel(sample_freq, port->membase + RX_SAMPLE);
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *cortina_uart_type(struct uart_port *port)
+{
+	return container_of(port, struct cortina_uart_port, uart)->name;
+}
+
+static void cortina_uart_config_port(struct uart_port *port, int flags)
+{
+	/*
+	 * Driver core for serial ports forces a non-zero value for port type.
+	 * Write an arbitrary value here to accommodate the serial core driver,
+	 * as ID part of UAPI is redundant.
+	 */
+	port->type = 1;
+}
+
+static int cortina_uart_verify_port(struct uart_port *port,
+				    struct serial_struct *ser)
+{
+	if (ser->type != PORT_UNKNOWN && ser->type != 1)
+		return -EINVAL;
+	return 0;
+}
+
+static void cortina_access_power(struct uart_port *port, unsigned int state,
+				 unsigned int oldstate)
+{
+	unsigned int reg_v;
+
+	reg_v = readl(port->membase + CFG);
+	switch (state) {
+	case UART_PM_STATE_ON:
+		reg_v |= CFG_UART_EN;
+		break;
+	case UART_PM_STATE_OFF:
+		reg_v &= ~CFG_UART_EN;
+		break;
+	default:
+		pr_err("cortina-access serial: Unknown PM state %d\n", state);
+	}
+	writel(reg_v, port->membase + CFG);
+}
+
+#ifdef CONFIG_CONSOLE_POLL
+static int cortina_poll_get_char(struct uart_port *port)
+{
+	if (readl(port->membase + INFO) & INFO_RX_EMPTY)
+		return NO_POLL_CHAR;
+
+	return readl(port->membase + RX_DAT);
+}
+
+static void cortina_poll_put_char(struct uart_port *port, unsigned char c)
+{
+	unsigned long time_out;
+
+	time_out = jiffies + usecs_to_jiffies(TX_TIMEOUT);
+
+	while (time_before(jiffies, time_out) &&
+	       (readl(port->membase + INFO) & INFO_TX_FULL))
+		cpu_relax();
+
+	/* Give up if FIFO stuck! */
+	if (readl(port->membase + INFO) & INFO_TX_FULL)
+		return;
+
+	writel(c, port->membase + TX_DAT);
+}
+#endif /* CONFIG_CONSOLE_POLL */
+
+static const struct uart_ops cortina_uart_ops = {
+	.tx_empty	= cortina_uart_tx_empty,
+	.set_mctrl	= cortina_uart_set_mctrl,
+	.get_mctrl	= cortina_uart_get_mctrl,
+	.stop_tx	= cortina_uart_stop_tx,
+	.start_tx	= cortina_uart_start_tx,
+	.stop_rx	= cortina_uart_stop_rx,
+	.enable_ms	= cortina_uart_enable_ms,
+	.startup	= cortina_uart_startup,
+	.shutdown	= cortina_uart_shutdown,
+	.set_termios	= cortina_uart_set_termios,
+	.type		= cortina_uart_type,
+	.config_port	= cortina_uart_config_port,
+	.verify_port	= cortina_uart_verify_port,
+	.pm		= cortina_access_power,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_get_char	= cortina_poll_get_char,
+	.poll_put_char	= cortina_poll_put_char,
+#endif
+};
+
+static inline void cortina_uart_interrupt_rx_chars(struct uart_port *port,
+						   unsigned long status)
+{
+	struct tty_port *ttyport = &port->state->port;
+	unsigned int ch;
+	unsigned int rx, flg;
+	struct cortina_uart_port *pca_port;
+
+	rx = readl(port->membase + INFO);
+	if (INFO_RX_EMPTY & rx)
+		return;
+
+	if (status & RX_FIFO_OVERRUNE)
+		port->icount.overrun++;
+
+	pca_port = cortina_uart_get_port(port->line);
+
+	/* Read characters while FIFO is not empty */
+	do {
+		flg = TTY_NORMAL;
+		port->icount.rx++;
+		ch = readl(port->membase + RX_DAT);
+		if (status & RX_PARITY_ERRE) {
+			port->icount.parity++;
+			flg = TTY_PARITY;
+		}
+
+		if (pca_port->has_bi) {
+			if (status & RX_BREAK) {
+				port->icount.brk++;
+				if (uart_handle_break(port))
+					goto ignore;
+			}
+		} else {
+			/* Treat stop err as BI */
+			if (status & RX_STOP_ERRE) {
+				port->icount.brk++;
+				if (uart_handle_break(port))
+					goto ignore;
+			}
+		}
+		if (!(ch & 0x100)) /* RX char is not valid */
+			goto ignore;
+
+		if (uart_handle_sysrq_char(port, (unsigned char)ch))
+			goto ignore;
+
+		tty_insert_flip_char(ttyport, ch, flg);
+ignore:
+		rx = readl(port->membase + INFO);
+	} while (!(INFO_RX_EMPTY & rx));
+
+	spin_unlock(&port->lock);
+	tty_flip_buffer_push(ttyport);
+	spin_lock(&port->lock);
+}
+
+static inline void cortina_uart_interrupt_tx_chars(struct uart_port *port)
+{
+	u8 ch;
+
+	/*
+	 * uart_port_tx() drains the kfifo xmit buffer, handles x_char,
+	 * calls uart_write_wakeup() and stop_tx() when the buffer empties.
+	 */
+	uart_port_tx(port, ch,
+		     !(readl(port->membase + INFO) & INFO_TX_FULL),
+		     writel(ch, port->membase + TX_DAT));
+}
+
+static irqreturn_t cortina_uart_interrupt(int irq, void *dev_id)
+{
+	struct uart_port *port = (struct uart_port *)dev_id;
+	unsigned int irq_status;
+
+	spin_lock(&port->lock);
+
+	/* Clear interrupt */
+	irq_status = readl(port->membase + INT);
+	writel(irq_status, port->membase + INT);
+
+	/* Process any Rx chars first */
+	cortina_uart_interrupt_rx_chars(port, irq_status);
+	/* Then use any Tx space */
+	cortina_uart_interrupt_tx_chars(port);
+
+	spin_unlock(&port->lock);
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_SERIAL_CORTINA_ACCESS_CONSOLE
+static void cortina_console_write(struct console *co, const char *s,
+				  unsigned int count)
+{
+	struct uart_port *port;
+	struct cortina_uart_port *pca_port;
+	unsigned int i, previous;
+	unsigned long flags;
+	int locked;
+
+	pca_port = cortina_uart_get_port(co->index);
+	port = &pca_port->uart;
+
+	local_irq_save(flags);
+	if (port->sysrq) {
+		locked = 0;
+	} else if (oops_in_progress) {
+		locked = spin_trylock(&port->lock);
+	} else {
+		spin_lock(&port->lock);
+		locked = 1;
+	}
+
+	/* Save current state */
+	previous = readl(port->membase + IE);
+	/* Disable Tx interrupts so this all goes out in one go */
+	cortina_uart_stop_tx(port);
+
+	/* Write all the chars */
+	for (i = 0; i < count; i++) {
+		/* Wait for the TX buffer to be empty */
+		while (!(readl(port->membase + INFO) & INFO_TX_EMPTY))
+			cpu_relax();
+
+		writel(*s, port->membase + TX_DAT);
+
+		/* CR/LF handling */
+		if (*s++ == '\n') {
+			while (!(readl(port->membase + INFO) & INFO_TX_EMPTY))
+				cpu_relax();
+			writel('\r', port->membase + TX_DAT);
+		}
+	}
+
+	writel(previous, port->membase + IE);	/* Restore interrupt state */
+
+	if (locked)
+		spin_unlock(&port->lock);
+	local_irq_restore(flags);
+}
+
+static int __init cortina_console_setup(struct console *co, char *options)
+{
+	struct uart_port *port;
+	struct cortina_uart_port *pca_port;
+	int baud = 115200;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	if (co->index < 0 || co->index >= UART_NR)
+		return -ENODEV;
+
+	pca_port = cortina_uart_get_port(co->index);
+	port = &pca_port->uart;
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver cortina_uart_driver;
+
+static struct console cortina_console = {
+	.name	= "ttyS",
+	.write	= cortina_console_write,
+	.device	= uart_console_device,
+	.setup	= cortina_console_setup,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
+	.data	= &cortina_uart_driver,
+};
+
+#define CORTINA_CONSOLE (&cortina_console)
+
+/* Support EARLYCON */
+static void cortina_putc(struct uart_port *port, unsigned char c)
+{
+	unsigned int tmout = TX_TIMEOUT;
+
+	/* No jiffies at early boot stage; wait up to TX_TIMEOUT us */
+	while (--tmout) {
+		if (!(readl(port->membase + INFO) & INFO_TX_FULL))
+			break;
+		udelay(1);
+	}
+
+	/* Give up if FIFO stuck */
+	if (readl(port->membase + INFO) & INFO_TX_FULL)
+		return;
+
+	writel(c, port->membase + TX_DAT);
+}
+
+static void cortina_early_write(struct console *con, const char *s,
+				unsigned int n)
+{
+	struct earlycon_device *dev = con->data;
+
+	uart_console_write(&dev->port, s, n, cortina_putc);
+}
+
+static int __init cortina_early_console_setup(struct earlycon_device *device,
+					      const char *opt)
+{
+	u32 reg_v;
+
+	if (!device->port.membase)
+		return -ENODEV;
+
+	device->con->write = cortina_early_write;
+
+	/*
+	 * If the bootloader did not enable the UART, initialise it here
+	 * at 115200 baud so that early boot messages are not lost.
+	 * The magic constant mirrors the reference BSP setting:
+	 *   CFG[31:8] = baud divisor for 115200, CFG[7] = UART_EN,
+	 *   CFG[6:5]  = RX_EN|TX_EN, CFG[1:0] = 8-bit data.
+	 */
+	reg_v = readl(device->port.membase + CFG);
+	if (!(reg_v & CFG_UART_EN)) {
+		writel(0x00043de3, device->port.membase + CFG);
+		writel(0x00043d / 2, device->port.membase + RX_SAMPLE);
+	}
+
+	return 0;
+}
+
+EARLYCON_DECLARE(ca_serial, cortina_early_console_setup);
+OF_EARLYCON_DECLARE(ca_serial, "cortina-access,serial",
+		    cortina_early_console_setup);
+#else
+#define CORTINA_CONSOLE	NULL
+#endif /* CONFIG_SERIAL_CORTINA_ACCESS_CONSOLE */
+
+static struct uart_driver cortina_uart_driver = {
+	.owner		= THIS_MODULE,
+	.driver_name	= "cortina-access_uart",
+	.dev_name	= "ttyS",
+	.major		= TTY_MAJOR,
+	.minor		= 64,
+	.nr		= UART_NR,
+	.cons		= CORTINA_CONSOLE,
+};
+
+/* Match table for of_platform binding */
+static const struct of_device_id cortina_uart_of_match[] = {
+	{ .compatible = "cortina-access,serial" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, cortina_uart_of_match);
+
+static int serial_cortina_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct cortina_uart_port *port;
+	struct resource *res;
+	struct clk *pclk_info;
+	int uart_idx;
+	int irq;
+	int ret;
+
+	if (!cortina_uart_ports) {
+		cortina_uart_ports = kcalloc(UART_NR, sizeof(*cortina_uart_ports),
+					     GFP_KERNEL);
+		if (!cortina_uart_ports)
+			return -ENOMEM;
+	}
+
+	port = cortina_uart_ports;
+	for (uart_idx = 0; uart_idx < UART_NR; ++uart_idx) {
+		/* Find first empty slot */
+		if (strlen(port->name) == 0)
+			break;
+		port++;
+	}
+
+	if (uart_idx >= UART_NR)
+		return -ENODEV;
+
+	snprintf(port->name, sizeof(port->name),
+		 "Cortina-Access UART%d", uart_idx);
+
+	/* Retrieve HW base address and reserve the I/O region */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	port->uart.mapbase = res->start;
+	port->uart.membase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(port->uart.membase))
+		return PTR_ERR(port->uart.membase);
+
+	/* Retrieve IRQ */
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	port->uart.irq = irq;
+
+	pclk_info = devm_clk_get_enabled(&pdev->dev, NULL);
+	if (IS_ERR(pclk_info)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		return PTR_ERR(pclk_info);
+	}
+
+	port->uart.uartclk	= clk_get_rate(pclk_info);
+	port->uart.ops		= &cortina_uart_ops;
+	port->uart.dev		= &pdev->dev;
+	port->uart.line		= uart_idx;
+	port->uart.iotype	= UPIO_MEM32;
+	port->uart.type		= 1;
+	port->uart.has_sysrq	= IS_ENABLED(CONFIG_SERIAL_CORTINA_ACCESS_CONSOLE);
+
+	if (of_property_read_bool(np, "wakeup-source"))
+		port->may_wakeup = true;
+	if (of_property_read_bool(np, "break-indicator"))
+		port->has_bi = true;
+
+	if (port->may_wakeup)
+		device_init_wakeup(&pdev->dev, true);
+
+	ret = uart_add_one_port(&cortina_uart_driver, &port->uart);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, port);
+
+	return 0;
+}
+
+static void serial_cortina_remove(struct platform_device *pdev)
+{
+	struct cortina_uart_port *pca_port = platform_get_drvdata(pdev);
+
+	if (pca_port) {
+		memset(pca_port->name, 0, CA_UART_NAME_LEN);
+		uart_remove_one_port(&cortina_uart_driver, &pca_port->uart);
+	}
+
+	platform_set_drvdata(pdev, NULL);
+
+	/*
+	 * Free the port array when the last port is removed, i.e. when
+	 * all slots are empty again.
+	 */
+	if (cortina_uart_ports) {
+		int i;
+
+		for (i = 0; i < UART_NR; i++) {
+			if (strlen(cortina_uart_ports[i].name) != 0)
+				return;
+		}
+		kfree(cortina_uart_ports);
+		cortina_uart_ports = NULL;
+	}
+}
+
+#ifdef CONFIG_PM
+static int serial_cortina_suspend(struct platform_device *pdev,
+				  pm_message_t state)
+{
+	struct cortina_uart_port *p = platform_get_drvdata(pdev);
+
+	uart_suspend_port(&cortina_uart_driver, &p->uart);
+
+	return 0;
+}
+
+static int serial_cortina_resume(struct platform_device *pdev)
+{
+	struct cortina_uart_port *p = platform_get_drvdata(pdev);
+
+	uart_resume_port(&cortina_uart_driver, &p->uart);
+
+	return 0;
+}
+#else
+#define serial_cortina_suspend	NULL
+#define serial_cortina_resume	NULL
+#endif
+
+static struct platform_driver serial_cortina_driver = {
+	.probe		= serial_cortina_probe,
+	.remove		= serial_cortina_remove,
+#ifdef CONFIG_PM
+	.suspend	= serial_cortina_suspend,
+	.resume		= serial_cortina_resume,
+#endif
+	.driver = {
+		.name		= "cortina-access_serial",
+		.of_match_table	= cortina_uart_of_match,
+	},
+};
+
+static int __init cortina_uart_init(void)
+{
+	int ret;
+
+	ret = uart_register_driver(&cortina_uart_driver);
+	if (ret)
+		return ret;
+
+	ret = platform_driver_register(&serial_cortina_driver);
+	if (ret)
+		uart_unregister_driver(&cortina_uart_driver);
+
+	return ret;
+}
+
+static void __exit cortina_uart_exit(void)
+{
+	platform_driver_unregister(&serial_cortina_driver);
+	uart_unregister_driver(&cortina_uart_driver);
+}
+
+module_init(cortina_uart_init);
+module_exit(cortina_uart_exit);
+
+MODULE_AUTHOR("Cortina-Access Inc.");
+MODULE_DESCRIPTION("Cortina-Access UART driver");
+MODULE_LICENSE("GPL");
-- 
2.39.5


^ permalink raw reply related

* [PATCH 1/3] dt-bindings: serial: Add binding for Cortina-Access UART
From: Jason Li @ 2026-06-10 11:28 UTC (permalink / raw)
  To: jason.li, Greg Kroah-Hartman, Jiri Slaby
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
	Will Deacon, Arnd Bergmann, linux-serial, linux-arm-kernel,
	devicetree, linux-kernel
In-Reply-To: <20260610112821.3030099-1-jason.li@cortina-access.com>

Add DT binding schema for the Cortina-Access UART controller.
This IP is integrated into most CAXXXX SoC family members.

Also add the vendor prefix for Cortina Access, Inc. and the
top-level ARM board binding document for the CA8289 (Venus) SoC.

Signed-off-by: Jason Li <jason.li@cortina-access.com>
Assisted-by: Claude:claude-opus-4-8
---
 .../bindings/arm/cortina-access.yaml          | 29 ++++++++++++
 .../serial/cortina-access,serial.yaml         | 46 +++++++++++++++++++
 .../devicetree/bindings/vendor-prefixes.yaml  |  2 +
 MAINTAINERS                                   |  7 +++
 4 files changed, 84 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/cortina-access.yaml
 create mode 100644 Documentation/devicetree/bindings/serial/cortina-access,serial.yaml

diff --git a/Documentation/devicetree/bindings/arm/cortina-access.yaml b/Documentation/devicetree/bindings/arm/cortina-access.yaml
new file mode 100644
index 000000000000..ec0320ed0c0b
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/cortina-access.yaml
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/cortina-access.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cortina-Access SoC boards
+
+maintainers:
+  - Jason Li <jason.li@cortina-access.com>
+
+description:
+  Boards based on Cortina-Access ARMv8 SoCs targeting networking and
+  access applications.
+
+properties:
+  $nodename:
+    const: /
+  compatible:
+    oneOf:
+      - description: Cortina-Access CA8289 (Venus) engineering board
+        const: cortina-access,ca8289-engboard
+
+      - description: Cortina-Access CA8289 (Venus) reference board
+        const: cortina-access,ca8289-refboard
+
+additionalProperties: true
+
+...
diff --git a/Documentation/devicetree/bindings/serial/cortina-access,serial.yaml b/Documentation/devicetree/bindings/serial/cortina-access,serial.yaml
new file mode 100644
index 000000000000..5d7fdd954491
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/cortina-access,serial.yaml
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/serial/cortina-access,serial.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cortina-Access UART controller
+
+maintainers:
+  - Jason Li <jason.li@cortina-access.com>
+
+allOf:
+  - $ref: serial.yaml#
+
+properties:
+  compatible:
+    const: cortina-access,serial
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    serial@f4329188 {
+        compatible = "cortina-access,serial";
+        reg = <0 0xf4329188 0 0x30>;
+        interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&apb_pclk>;
+    };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index dd94c50e97f9..837e2a92e7e8 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -367,6 +367,8 @@ patternProperties:
     description: Chengdu Corpro Technology Co., Ltd.
   "^corechips,.*":
     description: Shenzhen Corechips Microelectronics Co., Ltd.
+  "^cortina-access,.*":
+    description: Cortina Access, Inc.
   "^cortina,.*":
     description: Cortina Systems, Inc.
   "^cosmic,.*":
diff --git a/MAINTAINERS b/MAINTAINERS
index 20bd55913b2d..cc261888fae0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2820,6 +2820,13 @@ F:	tools/perf/tests/shell/lib/*coresight*
 F:	tools/perf/util/cs-etm-decoder/*
 F:	tools/perf/util/cs-etm.*
 
+ARM/CORTINA-ACCESS VENUS ARM ARCHITECTURE
+M:	Jason Li <jason.li@cortina-access.com>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	Documentation/devicetree/bindings/arm/cortina-access.yaml
+F:	Documentation/devicetree/bindings/serial/cortina-access,serial.yaml
+
 ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE
 M:	Hans Ulli Kroll <ulli.kroll@googlemail.com>
 M:	Linus Walleij <linusw@kernel.org>
-- 
2.39.5


^ permalink raw reply related

* [PATCH 0/3] tty: serial: Add Cortina-Access UART driver and platform support
From: Jason Li @ 2026-06-10 11:28 UTC (permalink / raw)
  To: jason.li, Greg Kroah-Hartman, Jiri Slaby
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
	Will Deacon, Arnd Bergmann, linux-serial, linux-arm-kernel,
	devicetree, linux-kernel
In-Reply-To: <20260610112821.3030099-1-jason.li@cortina-access.com>

This series adds Linux kernel support for the UART controller integrated
in Cortina-Access SoCs, with CA8289 (Venus) as the first supported device.

Patch 1 adds the DT binding schema for the UART controller and the
top-level ARM board binding document for the Cortina-Access SoC family,
along with the vendor prefix.

Patch 2 introduces the serial driver (serial_cortina-access.c).  The
UART IP has a simple FIFO-based design with a single interrupt line.
The driver uses uart_port_tx() for TX, handles earlycon initialisation
when the bootloader leaves the UART disabled, and provides a TX FIFO
kick-start in start_tx() to work around edge-triggered interrupt
behaviour.  Clock frequency is obtained exclusively via the clk
framework.

Patch 3 adds the device tree sources for the CA8289 SoC and its
engineering board, covering the minimal hardware description needed to
boot a kernel with an INITRD rootfs.

Tested on CA8289 engineering board; console and earlycon both verified
at 115200 baud.

Jason Li (3):
  dt-bindings: serial: Add binding for Cortina-Access UART
  tty: serial: Add UART driver for Cortina-Access platform
  arm64: dts: cortina-access: Add DTS for CA8289 SoC and Venus board

 .../bindings/arm/cortina-access.yaml          |  29 +
 .../serial/cortina-access,serial.yaml         |  46 ++
 .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
 MAINTAINERS                                   |  14 +
 arch/arm64/Kconfig.platforms                  |  10 +
 arch/arm64/boot/dts/Makefile                  |   1 +
 arch/arm64/boot/dts/cortina-access/Makefile   |   2 +
 .../dts/cortina-access/ca8289-engboard.dts    |  31 +
 .../boot/dts/cortina-access/ca8289-soc.dtsi   | 118 +++
 drivers/tty/serial/Kconfig                    |  21 +
 drivers/tty/serial/Makefile                   |   1 +
 drivers/tty/serial/serial_cortina-access.c    | 755 ++++++++++++++++++
 12 files changed, 1030 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/cortina-access.yaml
 create mode 100644 Documentation/devicetree/bindings/serial/cortina-access,serial.yaml
 create mode 100644 arch/arm64/boot/dts/cortina-access/Makefile
 create mode 100644 arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts
 create mode 100644 arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi
 create mode 100644 drivers/tty/serial/serial_cortina-access.c

-- 
2.39.5


^ permalink raw reply

* [PATCH 0/3] tty: serial: Add Cortina-Access UART driver and platform support
From: Jason Li @ 2026-06-10 11:28 UTC (permalink / raw)
  To: jason.li, Greg Kroah-Hartman, Jiri Slaby
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
	Will Deacon, Arnd Bergmann, linux-serial, linux-arm-kernel,
	devicetree, linux-kernel

Patch 1 adds the DT binding schema for the UART controller and the
top-level ARM board binding document for the Cortina-Access SoC family,
along with the vendor prefix.

Patch 2 introduces the serial driver (serial_cortina-access.c).  The
UART IP has a simple FIFO-based design with a single interrupt line.
The driver uses uart_port_tx() for TX, handles earlycon initialisation
when the bootloader leaves the UART disabled, and provides a TX FIFO
kick-start in start_tx() to work around edge-triggered interrupt
behaviour.  Clock frequency is obtained exclusively via the clk
framework.

Patch 3 adds the device tree sources for the CA8289 SoC and its
engineering board, covering the minimal hardware description needed to
boot a kernel with an INITRD rootfs.

Tested on CA8289 engineering board; console and earlycon both verified
at 115200 baud.

Any feedback or comments are highly appreciated.

Jason Li (3):
  dt-bindings: serial: Add binding for Cortina-Access UART
  tty: serial: Add UART driver for Cortina-Access platform
  arm64: dts: cortina-access: Add DTS for CA8289 SoC and Venus board

 .../bindings/arm/cortina-access.yaml          |  29 +
 .../serial/cortina-access,serial.yaml         |  46 ++
 .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
 MAINTAINERS                                   |  14 +
 arch/arm64/Kconfig.platforms                  |  10 +
 arch/arm64/boot/dts/Makefile                  |   1 +
 arch/arm64/boot/dts/cortina-access/Makefile   |   2 +
 .../dts/cortina-access/ca8289-engboard.dts    |  31 +
 .../boot/dts/cortina-access/ca8289-soc.dtsi   | 118 +++
 drivers/tty/serial/Kconfig                    |  21 +
 drivers/tty/serial/Makefile                   |   1 +
 drivers/tty/serial/serial_cortina-access.c    | 755 ++++++++++++++++++
 12 files changed, 1030 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/cortina-access.yaml
 create mode 100644 Documentation/devicetree/bindings/serial/cortina-access,serial.yaml
 create mode 100644 arch/arm64/boot/dts/cortina-access/Makefile
 create mode 100644 arch/arm64/boot/dts/cortina-access/ca8289-engboard.dts
 create mode 100644 arch/arm64/boot/dts/cortina-access/ca8289-soc.dtsi
 create mode 100644 drivers/tty/serial/serial_cortina-access.c

-- 
2.39.5


^ permalink raw reply

* Re: [PATCHv2 1/4] serial: mxs-auart: fix cast type for of_device_get_match_data
From: Rosen Penev @ 2026-06-10  6:06 UTC (permalink / raw)
  To: Frank Li
  Cc: linux-serial, Greg Kroah-Hartman, Jiri Slaby, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <aii6RX0321fJV99W@SMW015318>

On Tue, Jun 9, 2026 at 6:13 PM Frank Li <Frank.li@oss.nxp.com> wrote:
>
> On Tue, Jun 09, 2026 at 03:37:14PM -0700, Rosen Penev wrote:
> > of_device_get_match_data returns const void*. Cast to unsigned long to
> > avoid implicit integer truncation warnings. All the data parameters are
> > correct anyway.
>
> It is not worth to fix it by this ways. cast void * to int/long is not good
> at all.
It's just a compilation fix. The same solution is used in many other places.
>
> struct drvdata
> {
>         enum mxs_auart_type type;
> }
>
> static const struct drvata chip_imx28;
>
> &chip_imx28 as drv data.
That's a lot of work just to avoid a cast.
>
> Frank
> >
> > Assisted-by: opencode:big-pickle
> > Signed-off-by: Rosen Penev <rosenp@gmail.com>
> > ---
> >  drivers/tty/serial/mxs-auart.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
> > index 697318dbb146..de97c0f74e7d 100644
> > --- a/drivers/tty/serial/mxs-auart.c
> > +++ b/drivers/tty/serial/mxs-auart.c
> > @@ -1598,7 +1598,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
> >               return -EINVAL;
> >       }
> >
> > -     s->devtype = (enum mxs_auart_type)of_device_get_match_data(&pdev->dev);
> > +     s->devtype = (unsigned long)of_device_get_match_data(&pdev->dev);
> >
> >       ret = mxs_get_clks(s, pdev);
> >       if (ret)
> > --
> > 2.54.0
> >
> >

^ permalink raw reply

* [PATCH] serial: 8250: force synchronous probe for the ISA and PNP drivers
From: Rahul Bukte @ 2026-06-10  5:41 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby
  Cc: Ilpo Järvinen, Shashank Balaji, Daniel Palmer, linux-serial,
	linux-kernel, Rahul Bukte

On x86_64 defconfig, booting with driver_async_probe=serial hangs in early
init. The 8250 PNP driver is put onto the async probe pool.
serial8250_register_8250_port() runs in a kworker concurrently with the
ISA registration done from the serial8250_init() initcall resulting in a
deadlock or NULL dereference.

  - Deadlock: serial_core_register_port() holds port_mutex across
    serial_core_add_one_port()
        uart_configure_port()
            autoconfig_irq()
                probe_irq_on()
                    async_synchronize_full(),
    which waits for the async probe pool to drain.

    The async PNP worker reaches the "port already in use" check and
    tries to unregister it.
    serial8250_register_8250_port()
        uart_remove_one_port()
            serial_core_unregister_port()
    This blocks on port_mutex.
    The init thread waits for the worker and the worker waits for the
    init thread.

  - NULL deref: when the worker instead observes a slot whose port.dev
    is set but whose port_dev has not yet been populated, it hits the
    null pointer on the call to serial_core_get_ctrl_dev() in
    serial_core_unregister_port().

Signed-off-by: Rahul Bukte <rahul.bukte@sony.com>
---
Found while experimenting with driver_async_probe=* to improve boot time.

Tested on x86_64 defconfig under QEMU + KVM with driver_async_probe=serial.

 drivers/tty/serial/8250/8250_platform.c | 1 +
 drivers/tty/serial/8250/8250_pnp.c      | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_platform.c b/drivers/tty/serial/8250/8250_platform.c
index ad3a7bc31d6f..af946d12e764 100644
--- a/drivers/tty/serial/8250/8250_platform.c
+++ b/drivers/tty/serial/8250/8250_platform.c
@@ -284,6 +284,7 @@ static struct platform_driver serial8250_isa_driver = {
 	.driver		= {
 		.name	= "serial8250",
 		.acpi_match_table = acpi_platform_serial_table,
+		.probe_type = PROBE_FORCE_SYNCHRONOUS,
 	},
 };
 
diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
index 7a837fdf9df1..3f41a9d6cb27 100644
--- a/drivers/tty/serial/8250/8250_pnp.c
+++ b/drivers/tty/serial/8250/8250_pnp.c
@@ -521,6 +521,7 @@ static struct pnp_driver serial_pnp_driver = {
 	.remove		= serial_pnp_remove,
 	.driver         = {
 		.pm     = pm_sleep_ptr(&serial_pnp_pm_ops),
+		.probe_type = PROBE_FORCE_SYNCHRONOUS,
 	},
 	.id_table	= pnp_dev_table,
 };

base-commit: eb3f4b7426cfd2b79d65b7d37155480b32259a11
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCHv2 4/4] serial: mxs-auart: fix IRQ registration ordering and manage console clock
From: Frank Li @ 2026-06-10  1:32 UTC (permalink / raw)
  To: Rosen Penev
  Cc: linux-serial, Greg Kroah-Hartman, Jiri Slaby, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20260609223717.41670-5-rosenp@gmail.com>

On Tue, Jun 09, 2026 at 03:37:17PM -0700, Rosen Penev wrote:
> Move the main UART IRQ registration after uart_add_one_port so that
> s->port.state and s->port.lock are initialized before the interrupt
> handler can run. Mask all UART interrupts before adding the port to
> prevent spurious IRQs left by the bootloader.

Please use seperate patch to this problem only.

Frank

>
> After probe succeeds, disable the module clock for non-console ports
> since startup will re-enable it on port open. For console ports, keep
> the clock prepared so auart_console_write() can safely call
> clk_enable() from atomic context.
>
> Guard the IRQ handler and get_mctrl with clk_enable/clk_disable since
> GPIO IRQs and serial-core status queries can fire while the clock is
> disabled for non-console ports.
>
> In remove, disable the clock for console ports to balance the enable
> done in probe, preventing a clock leak on unbind.
>
> Assisted-by: opencode:big-pickle
> ---
>  drivers/tty/serial/mxs-auart.c | 49 +++++++++++++++++++++++++++-------
>  1 file changed, 39 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
> index 4499e3206e85..e2b656638ab3 100644
> --- a/drivers/tty/serial/mxs-auart.c
> +++ b/drivers/tty/serial/mxs-auart.c
> @@ -738,9 +738,13 @@ static u32 mxs_auart_modem_status(struct mxs_auart_port *s, u32 mctrl)
>  static u32 mxs_auart_get_mctrl(struct uart_port *u)
>  {
>  	struct mxs_auart_port *s = to_auart_port(u);
> -	u32 stat = mxs_read(s, REG_STAT);
> +	u32 stat;
>  	u32 mctrl = 0;
>
> +	clk_enable(s->clk);
> +	stat = mxs_read(s, REG_STAT);
> +	clk_disable(s->clk);
> +
>  	if (stat & AUART_STAT_CTS)
>  		mctrl |= TIOCM_CTS;
>
> @@ -1079,6 +1083,7 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
>  	struct mxs_auart_port *s = context;
>  	u32 mctrl_temp = s->mctrl_prev;
>
> +	clk_enable(s->clk);
>  	uart_port_lock(&s->port);
>
>  	stat = mxs_read(s, REG_STAT);
> @@ -1118,6 +1123,7 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
>  	}
>
>  	uart_port_unlock(&s->port);
> +	clk_disable(s->clk);
>
>  	return IRQ_HANDLED;
>  }
> @@ -1603,10 +1609,6 @@ static int mxs_auart_probe(struct platform_device *pdev)
>  	}
>
>  	s->port.irq = irq;
> -	ret = devm_request_irq(&pdev->dev, irq, mxs_auart_irq_handle, 0,
> -			       dev_name(&pdev->dev), s);
> -	if (ret)
> -		goto out_disable_clk;
>
>  	platform_set_drvdata(pdev, s);
>
> @@ -1627,9 +1629,28 @@ static int mxs_auart_probe(struct platform_device *pdev)
>
>  	mxs_auart_reset_deassert(s);
>
> +	/* Mask all UART interrupts to prevent spurious IRQs from bootloader */
> +	mxs_write(0, s, REG_INTR);
> +
>  	ret = uart_add_one_port(&auart_driver, &s->port);
> -	if (ret)
> -		goto out_free_qpio_irq;
> +	if (ret) {
> +		auart_port[s->port.line] = NULL;
> +		goto out_disable_clk;
> +	}
> +
> +	/*
> +	 * Request the main IRQ after uart_add_one_port so that
> +	 * s->port.state and s->port.lock are initialized before
> +	 * the handler can run in response to a bootloader-left
> +	 * interrupt.
> +	 */
> +	ret = devm_request_irq(&pdev->dev, irq, mxs_auart_irq_handle, 0,
> +			       dev_name(&pdev->dev), s);
> +	if (ret) {
> +		uart_remove_one_port(&auart_driver, &s->port);
> +		auart_port[s->port.line] = NULL;
> +		goto out_disable_clk;
> +	}
>
>  	/* ASM9260 don't have version reg */
>  	if (is_asm9260_auart(s)) {
> @@ -1641,10 +1662,16 @@ static int mxs_auart_probe(struct platform_device *pdev)
>  			 (version >> 16) & 0xff, version & 0xffff);
>  	}
>
> -	return 0;
> +	/*
> +	 * Disable clock -- startup will re-enable when the port is opened.
> +	 * For the console port the clock must stay prepared so that
> +	 * auart_console_write() can safely call clk_enable() from
> +	 * atomic context.
> +	 */
> +	if (!uart_console(&s->port))
> +		clk_disable_unprepare(s->clk);
>
> -out_free_qpio_irq:
> -	auart_port[s->port.line] = NULL;
> +	return 0;
>
>  out_disable_clk:
>  	clk_disable_unprepare(s->clk);
> @@ -1657,6 +1684,8 @@ static void mxs_auart_remove(struct platform_device *pdev)
>
>  	uart_remove_one_port(&auart_driver, &s->port);
>  	auart_port[s->port.line] = NULL;
> +	if (uart_console(&s->port))
> +		clk_disable_unprepare(s->clk);
>  }
>
>  static struct platform_driver mxs_auart_driver = {
> --
> 2.54.0
>
>

^ permalink raw reply

* Re: [PATCHv2 3/4] serial: mxs-auart: use devm resources for iomem and GPIO IRQs
From: Frank Li @ 2026-06-10  1:26 UTC (permalink / raw)
  To: Rosen Penev
  Cc: linux-serial, Greg Kroah-Hartman, Jiri Slaby, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20260609223717.41670-4-rosenp@gmail.com>

On Tue, Jun 09, 2026 at 03:37:16PM -0700, Rosen Penev wrote:
> Replace platform_get_resource + ioremap with
> devm_platform_get_and_ioremap_resource and convert GPIO IRQ
> request_irq/free_irq to devm_request_irq. This eliminates the
> mxs_auart_free_gpio_irq function and its call sites, and the
> out_iounmap error label. Simplify the remove function accordingly.

as my said before, all function need add ()

Frank
>
> Assisted-by: opencode:big-pickle
> Signed-off-by: Rosen Penev <rosenp@gmail.com>
> ---
>  drivers/tty/serial/mxs-auart.c | 53 +++++++---------------------------
>  1 file changed, 11 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
> index aa59a48bfad7..4499e3206e85 100644
> --- a/drivers/tty/serial/mxs-auart.c
> +++ b/drivers/tty/serial/mxs-auart.c
> @@ -1517,15 +1517,6 @@ static int mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
>  	return 0;
>  }
>
> -static void mxs_auart_free_gpio_irq(struct mxs_auart_port *s)
> -{
> -	enum mctrl_gpio_idx i;
> -
> -	for (i = 0; i < UART_GPIO_MAX; i++)
> -		if (s->gpio_irq[i] >= 0)
> -			free_irq(s->gpio_irq[i], s);
> -}
> -
>  static int mxs_auart_request_gpio_irq(struct mxs_auart_port *s)
>  {
>  	int *irq = s->gpio_irq;
> @@ -1537,21 +1528,13 @@ static int mxs_auart_request_gpio_irq(struct mxs_auart_port *s)
>  			continue;
>
>  		irq_set_status_flags(irq[i], IRQ_NOAUTOEN);
> -		err = request_irq(irq[i], mxs_auart_irq_handle,
> -				IRQ_TYPE_EDGE_BOTH, dev_name(s->dev), s);
> +		err = devm_request_irq(s->dev, irq[i], mxs_auart_irq_handle,
> +				       IRQ_TYPE_EDGE_BOTH, dev_name(s->dev), s);
>  		if (err)
>  			dev_err(s->dev, "%s - Can't get %d irq\n",
>  				__func__, irq[i]);
>  	}
>
> -	/*
> -	 * If something went wrong, rollback.
> -	 * Be careful: i may be unsigned.
> -	 */
> -	while (err && (i-- > 0))
> -		if (irq[i] >= 0)
> -			free_irq(irq[i], s);
> -
>  	return err;
>  }
>
> @@ -1596,18 +1579,12 @@ static int mxs_auart_probe(struct platform_device *pdev)
>  	if (ret)
>  		return ret;
>
> -	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -	if (!r) {
> -		ret = -ENXIO;
> +	s->port.membase = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
> +	if (IS_ERR(s->port.membase)) {
> +		ret = PTR_ERR(s->port.membase);
>  		goto out_disable_clk;
>  	}
> -
>  	s->port.mapbase = r->start;
> -	s->port.membase = ioremap(r->start, resource_size(r));
> -	if (!s->port.membase) {
> -		ret = -ENOMEM;
> -		goto out_disable_clk;
> -	}
>  	s->port.ops = &mxs_auart_ops;
>  	s->port.iotype = UPIO_MEM;
>  	s->port.fifosize = MXS_AUART_FIFO_SIZE;
> @@ -1622,21 +1599,21 @@ static int mxs_auart_probe(struct platform_device *pdev)
>  	irq = platform_get_irq(pdev, 0);
>  	if (irq < 0) {
>  		ret = irq;
> -		goto out_iounmap;
> +		goto out_disable_clk;
>  	}
>
>  	s->port.irq = irq;
>  	ret = devm_request_irq(&pdev->dev, irq, mxs_auart_irq_handle, 0,
>  			       dev_name(&pdev->dev), s);
>  	if (ret)
> -		goto out_iounmap;
> +		goto out_disable_clk;
>
>  	platform_set_drvdata(pdev, s);
>
>  	ret = mxs_auart_init_gpios(s, &pdev->dev);
>  	if (ret) {
>  		dev_err(&pdev->dev, "Failed to initialize GPIOs.\n");
> -		goto out_iounmap;
> +		goto out_disable_clk;
>  	}
>
>  	/*
> @@ -1644,7 +1621,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
>  	 */
>  	ret = mxs_auart_request_gpio_irq(s);
>  	if (ret)
> -		goto out_iounmap;
> +		goto out_disable_clk;
>
>  	auart_port[s->port.line] = s;
>
> @@ -1667,11 +1644,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
>  	return 0;
>
>  out_free_qpio_irq:
> -	mxs_auart_free_gpio_irq(s);
> -	auart_port[pdev->id] = NULL;
> -
> -out_iounmap:
> -	iounmap(s->port.membase);
> +	auart_port[s->port.line] = NULL;
>
>  out_disable_clk:
>  	clk_disable_unprepare(s->clk);
> @@ -1683,11 +1656,7 @@ static void mxs_auart_remove(struct platform_device *pdev)
>  	struct mxs_auart_port *s = platform_get_drvdata(pdev);
>
>  	uart_remove_one_port(&auart_driver, &s->port);
> -	auart_port[pdev->id] = NULL;
> -	mxs_auart_free_gpio_irq(s);
> -	iounmap(s->port.membase);
> -	if (is_asm9260_auart(s))
> -		clk_disable_unprepare(s->clk);
> +	auart_port[s->port.line] = NULL;
>  }
>
>  static struct platform_driver mxs_auart_driver = {
> --
> 2.54.0
>
>

^ permalink raw reply

* Re: [PATCHv2 2/4] serial: mxs-auart: rework clock handling in mxs_get_clks and probe
From: Frank Li @ 2026-06-10  1:24 UTC (permalink / raw)
  To: Rosen Penev
  Cc: linux-serial, Greg Kroah-Hartman, Jiri Slaby, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20260609223717.41670-3-rosenp@gmail.com>

On Tue, Jun 09, 2026 at 03:37:15PM -0700, Rosen Penev wrote:
> Use devm_clk_get_enabled for the AHB clock so its enable/disable
> lifetime is managed by the driver model. Move the mod clock
> (clk) prepare_enable out of mxs_get_clks and into probe so that
> clk_set_rate is called while the clock is still disabled, avoiding
> CLK_SET_RATE_GATE failures. Clean up the error labels accordingly.
>
> Assisted-by: opencode:big-pickle
> Signed-off-by: Rosen Penev <rosenp@gmail.com>
> ---
>  drivers/tty/serial/mxs-auart.c | 47 ++++++++++++----------------------
>  1 file changed, 17 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
> index de97c0f74e7d..aa59a48bfad7 100644
> --- a/drivers/tty/serial/mxs-auart.c
> +++ b/drivers/tty/serial/mxs-auart.c
> @@ -1470,34 +1470,22 @@ static int mxs_get_clks(struct mxs_auart_port *s,
>  		return PTR_ERR(s->clk);
>  	}
>
> -	s->clk_ahb = devm_clk_get(s->dev, "ahb");
> +	s->clk_ahb = devm_clk_get_enabled(s->dev, "ahb");
>  	if (IS_ERR(s->clk_ahb)) {
>  		dev_err(s->dev, "Failed to get \"ahb\" clk\n");
>  		return PTR_ERR(s->clk_ahb);
>  	}
>
> -	err = clk_prepare_enable(s->clk_ahb);
> -	if (err) {
> -		dev_err(s->dev, "Failed to enable ahb_clk!\n");
> -		return err;
> -	}
> -
> +	/*
> +	 * Set mod clock rate while it is still disabled so
> +	 * CLK_SET_RATE_GATE does not cause clk_set_rate to fail.
> +	 * The mod clock will be enabled in mxs_auart_startup()
> +	 * and in probe after mxs_get_clks returns.
> +	 */
>  	err = clk_set_rate(s->clk, clk_get_rate(s->clk_ahb));
> -	if (err) {
> +	if (err)
>  		dev_err(s->dev, "Failed to set rate!\n");
> -		goto disable_clk_ahb;
> -	}
>
> -	err = clk_prepare_enable(s->clk);
> -	if (err) {
> -		dev_err(s->dev, "Failed to enable clk!\n");
> -		goto disable_clk_ahb;
> -	}
> -
> -	return 0;
> -
> -disable_clk_ahb:
> -	clk_disable_unprepare(s->clk_ahb);

if I understand correct, after apply patch,

	if (err)
		dev_err(s->dev, ...)

	return err;


Perfer method is

	if (err)
		return dev_err_probe(s->dev, err, ...);

	return 0;

Frank

>  	return err;
>  }
>
> @@ -1604,17 +1592,21 @@ static int mxs_auart_probe(struct platform_device *pdev)
>  	if (ret)
>  		return ret;
>
> +	ret = clk_prepare_enable(s->clk);
> +	if (ret)
> +		return ret;
> +
>  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  	if (!r) {
>  		ret = -ENXIO;
> -		goto out_disable_clks;
> +		goto out_disable_clk;
>  	}
>
>  	s->port.mapbase = r->start;
>  	s->port.membase = ioremap(r->start, resource_size(r));
>  	if (!s->port.membase) {
>  		ret = -ENOMEM;
> -		goto out_disable_clks;
> +		goto out_disable_clk;
>  	}
>  	s->port.ops = &mxs_auart_ops;
>  	s->port.iotype = UPIO_MEM;
> @@ -1681,11 +1673,8 @@ static int mxs_auart_probe(struct platform_device *pdev)
>  out_iounmap:
>  	iounmap(s->port.membase);
>
> -out_disable_clks:
> -	if (is_asm9260_auart(s)) {
> -		clk_disable_unprepare(s->clk);
> -		clk_disable_unprepare(s->clk_ahb);
> -	}
> +out_disable_clk:
> +	clk_disable_unprepare(s->clk);
>  	return ret;
>  }
>
> @@ -1697,10 +1686,8 @@ static void mxs_auart_remove(struct platform_device *pdev)
>  	auart_port[pdev->id] = NULL;
>  	mxs_auart_free_gpio_irq(s);
>  	iounmap(s->port.membase);
> -	if (is_asm9260_auart(s)) {
> +	if (is_asm9260_auart(s))
>  		clk_disable_unprepare(s->clk);
> -		clk_disable_unprepare(s->clk_ahb);
> -	}
>  }
>
>  static struct platform_driver mxs_auart_driver = {
> --
> 2.54.0
>
>

^ permalink raw reply

* Re: [PATCHv2 1/4] serial: mxs-auart: fix cast type for of_device_get_match_data
From: Frank Li @ 2026-06-10  1:13 UTC (permalink / raw)
  To: Rosen Penev
  Cc: linux-serial, Greg Kroah-Hartman, Jiri Slaby, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20260609223717.41670-2-rosenp@gmail.com>

On Tue, Jun 09, 2026 at 03:37:14PM -0700, Rosen Penev wrote:
> of_device_get_match_data returns const void*. Cast to unsigned long to
> avoid implicit integer truncation warnings. All the data parameters are
> correct anyway.

It is not worth to fix it by this ways. cast void * to int/long is not good
at all.

struct drvdata
{
	enum mxs_auart_type type;
}

static const struct drvata chip_imx28;

&chip_imx28 as drv data.

Frank
>
> Assisted-by: opencode:big-pickle
> Signed-off-by: Rosen Penev <rosenp@gmail.com>
> ---
>  drivers/tty/serial/mxs-auart.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
> index 697318dbb146..de97c0f74e7d 100644
> --- a/drivers/tty/serial/mxs-auart.c
> +++ b/drivers/tty/serial/mxs-auart.c
> @@ -1598,7 +1598,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
>  		return -EINVAL;
>  	}
>
> -	s->devtype = (enum mxs_auart_type)of_device_get_match_data(&pdev->dev);
> +	s->devtype = (unsigned long)of_device_get_match_data(&pdev->dev);
>
>  	ret = mxs_get_clks(s, pdev);
>  	if (ret)
> --
> 2.54.0
>
>

^ permalink raw reply

* [PATCHv2 4/4] serial: mxs-auart: fix IRQ registration ordering and manage console clock
From: Rosen Penev @ 2026-06-09 22:37 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Jiri Slaby, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20260609223717.41670-1-rosenp@gmail.com>

Move the main UART IRQ registration after uart_add_one_port so that
s->port.state and s->port.lock are initialized before the interrupt
handler can run. Mask all UART interrupts before adding the port to
prevent spurious IRQs left by the bootloader.

After probe succeeds, disable the module clock for non-console ports
since startup will re-enable it on port open. For console ports, keep
the clock prepared so auart_console_write() can safely call
clk_enable() from atomic context.

Guard the IRQ handler and get_mctrl with clk_enable/clk_disable since
GPIO IRQs and serial-core status queries can fire while the clock is
disabled for non-console ports.

In remove, disable the clock for console ports to balance the enable
done in probe, preventing a clock leak on unbind.

Assisted-by: opencode:big-pickle
---
 drivers/tty/serial/mxs-auart.c | 49 +++++++++++++++++++++++++++-------
 1 file changed, 39 insertions(+), 10 deletions(-)

diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 4499e3206e85..e2b656638ab3 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -738,9 +738,13 @@ static u32 mxs_auart_modem_status(struct mxs_auart_port *s, u32 mctrl)
 static u32 mxs_auart_get_mctrl(struct uart_port *u)
 {
 	struct mxs_auart_port *s = to_auart_port(u);
-	u32 stat = mxs_read(s, REG_STAT);
+	u32 stat;
 	u32 mctrl = 0;
 
+	clk_enable(s->clk);
+	stat = mxs_read(s, REG_STAT);
+	clk_disable(s->clk);
+
 	if (stat & AUART_STAT_CTS)
 		mctrl |= TIOCM_CTS;
 
@@ -1079,6 +1083,7 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
 	struct mxs_auart_port *s = context;
 	u32 mctrl_temp = s->mctrl_prev;
 
+	clk_enable(s->clk);
 	uart_port_lock(&s->port);
 
 	stat = mxs_read(s, REG_STAT);
@@ -1118,6 +1123,7 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
 	}
 
 	uart_port_unlock(&s->port);
+	clk_disable(s->clk);
 
 	return IRQ_HANDLED;
 }
@@ -1603,10 +1609,6 @@ static int mxs_auart_probe(struct platform_device *pdev)
 	}
 
 	s->port.irq = irq;
-	ret = devm_request_irq(&pdev->dev, irq, mxs_auart_irq_handle, 0,
-			       dev_name(&pdev->dev), s);
-	if (ret)
-		goto out_disable_clk;
 
 	platform_set_drvdata(pdev, s);
 
@@ -1627,9 +1629,28 @@ static int mxs_auart_probe(struct platform_device *pdev)
 
 	mxs_auart_reset_deassert(s);
 
+	/* Mask all UART interrupts to prevent spurious IRQs from bootloader */
+	mxs_write(0, s, REG_INTR);
+
 	ret = uart_add_one_port(&auart_driver, &s->port);
-	if (ret)
-		goto out_free_qpio_irq;
+	if (ret) {
+		auart_port[s->port.line] = NULL;
+		goto out_disable_clk;
+	}
+
+	/*
+	 * Request the main IRQ after uart_add_one_port so that
+	 * s->port.state and s->port.lock are initialized before
+	 * the handler can run in response to a bootloader-left
+	 * interrupt.
+	 */
+	ret = devm_request_irq(&pdev->dev, irq, mxs_auart_irq_handle, 0,
+			       dev_name(&pdev->dev), s);
+	if (ret) {
+		uart_remove_one_port(&auart_driver, &s->port);
+		auart_port[s->port.line] = NULL;
+		goto out_disable_clk;
+	}
 
 	/* ASM9260 don't have version reg */
 	if (is_asm9260_auart(s)) {
@@ -1641,10 +1662,16 @@ static int mxs_auart_probe(struct platform_device *pdev)
 			 (version >> 16) & 0xff, version & 0xffff);
 	}
 
-	return 0;
+	/*
+	 * Disable clock -- startup will re-enable when the port is opened.
+	 * For the console port the clock must stay prepared so that
+	 * auart_console_write() can safely call clk_enable() from
+	 * atomic context.
+	 */
+	if (!uart_console(&s->port))
+		clk_disable_unprepare(s->clk);
 
-out_free_qpio_irq:
-	auart_port[s->port.line] = NULL;
+	return 0;
 
 out_disable_clk:
 	clk_disable_unprepare(s->clk);
@@ -1657,6 +1684,8 @@ static void mxs_auart_remove(struct platform_device *pdev)
 
 	uart_remove_one_port(&auart_driver, &s->port);
 	auart_port[s->port.line] = NULL;
+	if (uart_console(&s->port))
+		clk_disable_unprepare(s->clk);
 }
 
 static struct platform_driver mxs_auart_driver = {
-- 
2.54.0


^ permalink raw reply related

* [PATCHv2 3/4] serial: mxs-auart: use devm resources for iomem and GPIO IRQs
From: Rosen Penev @ 2026-06-09 22:37 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Jiri Slaby, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20260609223717.41670-1-rosenp@gmail.com>

Replace platform_get_resource + ioremap with
devm_platform_get_and_ioremap_resource and convert GPIO IRQ
request_irq/free_irq to devm_request_irq. This eliminates the
mxs_auart_free_gpio_irq function and its call sites, and the
out_iounmap error label. Simplify the remove function accordingly.

Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 drivers/tty/serial/mxs-auart.c | 53 +++++++---------------------------
 1 file changed, 11 insertions(+), 42 deletions(-)

diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index aa59a48bfad7..4499e3206e85 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -1517,15 +1517,6 @@ static int mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
 	return 0;
 }
 
-static void mxs_auart_free_gpio_irq(struct mxs_auart_port *s)
-{
-	enum mctrl_gpio_idx i;
-
-	for (i = 0; i < UART_GPIO_MAX; i++)
-		if (s->gpio_irq[i] >= 0)
-			free_irq(s->gpio_irq[i], s);
-}
-
 static int mxs_auart_request_gpio_irq(struct mxs_auart_port *s)
 {
 	int *irq = s->gpio_irq;
@@ -1537,21 +1528,13 @@ static int mxs_auart_request_gpio_irq(struct mxs_auart_port *s)
 			continue;
 
 		irq_set_status_flags(irq[i], IRQ_NOAUTOEN);
-		err = request_irq(irq[i], mxs_auart_irq_handle,
-				IRQ_TYPE_EDGE_BOTH, dev_name(s->dev), s);
+		err = devm_request_irq(s->dev, irq[i], mxs_auart_irq_handle,
+				       IRQ_TYPE_EDGE_BOTH, dev_name(s->dev), s);
 		if (err)
 			dev_err(s->dev, "%s - Can't get %d irq\n",
 				__func__, irq[i]);
 	}
 
-	/*
-	 * If something went wrong, rollback.
-	 * Be careful: i may be unsigned.
-	 */
-	while (err && (i-- > 0))
-		if (irq[i] >= 0)
-			free_irq(irq[i], s);
-
 	return err;
 }
 
@@ -1596,18 +1579,12 @@ static int mxs_auart_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!r) {
-		ret = -ENXIO;
+	s->port.membase = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
+	if (IS_ERR(s->port.membase)) {
+		ret = PTR_ERR(s->port.membase);
 		goto out_disable_clk;
 	}
-
 	s->port.mapbase = r->start;
-	s->port.membase = ioremap(r->start, resource_size(r));
-	if (!s->port.membase) {
-		ret = -ENOMEM;
-		goto out_disable_clk;
-	}
 	s->port.ops = &mxs_auart_ops;
 	s->port.iotype = UPIO_MEM;
 	s->port.fifosize = MXS_AUART_FIFO_SIZE;
@@ -1622,21 +1599,21 @@ static int mxs_auart_probe(struct platform_device *pdev)
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		ret = irq;
-		goto out_iounmap;
+		goto out_disable_clk;
 	}
 
 	s->port.irq = irq;
 	ret = devm_request_irq(&pdev->dev, irq, mxs_auart_irq_handle, 0,
 			       dev_name(&pdev->dev), s);
 	if (ret)
-		goto out_iounmap;
+		goto out_disable_clk;
 
 	platform_set_drvdata(pdev, s);
 
 	ret = mxs_auart_init_gpios(s, &pdev->dev);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to initialize GPIOs.\n");
-		goto out_iounmap;
+		goto out_disable_clk;
 	}
 
 	/*
@@ -1644,7 +1621,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
 	 */
 	ret = mxs_auart_request_gpio_irq(s);
 	if (ret)
-		goto out_iounmap;
+		goto out_disable_clk;
 
 	auart_port[s->port.line] = s;
 
@@ -1667,11 +1644,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
 	return 0;
 
 out_free_qpio_irq:
-	mxs_auart_free_gpio_irq(s);
-	auart_port[pdev->id] = NULL;
-
-out_iounmap:
-	iounmap(s->port.membase);
+	auart_port[s->port.line] = NULL;
 
 out_disable_clk:
 	clk_disable_unprepare(s->clk);
@@ -1683,11 +1656,7 @@ static void mxs_auart_remove(struct platform_device *pdev)
 	struct mxs_auart_port *s = platform_get_drvdata(pdev);
 
 	uart_remove_one_port(&auart_driver, &s->port);
-	auart_port[pdev->id] = NULL;
-	mxs_auart_free_gpio_irq(s);
-	iounmap(s->port.membase);
-	if (is_asm9260_auart(s))
-		clk_disable_unprepare(s->clk);
+	auart_port[s->port.line] = NULL;
 }
 
 static struct platform_driver mxs_auart_driver = {
-- 
2.54.0


^ permalink raw reply related

* [PATCHv2 2/4] serial: mxs-auart: rework clock handling in mxs_get_clks and probe
From: Rosen Penev @ 2026-06-09 22:37 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Jiri Slaby, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20260609223717.41670-1-rosenp@gmail.com>

Use devm_clk_get_enabled for the AHB clock so its enable/disable
lifetime is managed by the driver model. Move the mod clock
(clk) prepare_enable out of mxs_get_clks and into probe so that
clk_set_rate is called while the clock is still disabled, avoiding
CLK_SET_RATE_GATE failures. Clean up the error labels accordingly.

Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 drivers/tty/serial/mxs-auart.c | 47 ++++++++++++----------------------
 1 file changed, 17 insertions(+), 30 deletions(-)

diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index de97c0f74e7d..aa59a48bfad7 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -1470,34 +1470,22 @@ static int mxs_get_clks(struct mxs_auart_port *s,
 		return PTR_ERR(s->clk);
 	}
 
-	s->clk_ahb = devm_clk_get(s->dev, "ahb");
+	s->clk_ahb = devm_clk_get_enabled(s->dev, "ahb");
 	if (IS_ERR(s->clk_ahb)) {
 		dev_err(s->dev, "Failed to get \"ahb\" clk\n");
 		return PTR_ERR(s->clk_ahb);
 	}
 
-	err = clk_prepare_enable(s->clk_ahb);
-	if (err) {
-		dev_err(s->dev, "Failed to enable ahb_clk!\n");
-		return err;
-	}
-
+	/*
+	 * Set mod clock rate while it is still disabled so
+	 * CLK_SET_RATE_GATE does not cause clk_set_rate to fail.
+	 * The mod clock will be enabled in mxs_auart_startup()
+	 * and in probe after mxs_get_clks returns.
+	 */
 	err = clk_set_rate(s->clk, clk_get_rate(s->clk_ahb));
-	if (err) {
+	if (err)
 		dev_err(s->dev, "Failed to set rate!\n");
-		goto disable_clk_ahb;
-	}
 
-	err = clk_prepare_enable(s->clk);
-	if (err) {
-		dev_err(s->dev, "Failed to enable clk!\n");
-		goto disable_clk_ahb;
-	}
-
-	return 0;
-
-disable_clk_ahb:
-	clk_disable_unprepare(s->clk_ahb);
 	return err;
 }
 
@@ -1604,17 +1592,21 @@ static int mxs_auart_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	ret = clk_prepare_enable(s->clk);
+	if (ret)
+		return ret;
+
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r) {
 		ret = -ENXIO;
-		goto out_disable_clks;
+		goto out_disable_clk;
 	}
 
 	s->port.mapbase = r->start;
 	s->port.membase = ioremap(r->start, resource_size(r));
 	if (!s->port.membase) {
 		ret = -ENOMEM;
-		goto out_disable_clks;
+		goto out_disable_clk;
 	}
 	s->port.ops = &mxs_auart_ops;
 	s->port.iotype = UPIO_MEM;
@@ -1681,11 +1673,8 @@ static int mxs_auart_probe(struct platform_device *pdev)
 out_iounmap:
 	iounmap(s->port.membase);
 
-out_disable_clks:
-	if (is_asm9260_auart(s)) {
-		clk_disable_unprepare(s->clk);
-		clk_disable_unprepare(s->clk_ahb);
-	}
+out_disable_clk:
+	clk_disable_unprepare(s->clk);
 	return ret;
 }
 
@@ -1697,10 +1686,8 @@ static void mxs_auart_remove(struct platform_device *pdev)
 	auart_port[pdev->id] = NULL;
 	mxs_auart_free_gpio_irq(s);
 	iounmap(s->port.membase);
-	if (is_asm9260_auart(s)) {
+	if (is_asm9260_auart(s))
 		clk_disable_unprepare(s->clk);
-		clk_disable_unprepare(s->clk_ahb);
-	}
 }
 
 static struct platform_driver mxs_auart_driver = {
-- 
2.54.0


^ permalink raw reply related

* [PATCHv2 1/4] serial: mxs-auart: fix cast type for of_device_get_match_data
From: Rosen Penev @ 2026-06-09 22:37 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Jiri Slaby, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20260609223717.41670-1-rosenp@gmail.com>

of_device_get_match_data returns const void*. Cast to unsigned long to
avoid implicit integer truncation warnings. All the data parameters are
correct anyway.

Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 drivers/tty/serial/mxs-auart.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 697318dbb146..de97c0f74e7d 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -1598,7 +1598,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	s->devtype = (enum mxs_auart_type)of_device_get_match_data(&pdev->dev);
+	s->devtype = (unsigned long)of_device_get_match_data(&pdev->dev);
 
 	ret = mxs_get_clks(s, pdev);
 	if (ret)
-- 
2.54.0


^ permalink raw reply related

* [PATCHv2 0/4] serial: mxs-auart: devm conversion, clock rework, and IRQ ordering fixes
From: Rosen Penev @ 2026-06-09 22:37 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Jiri Slaby, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	open list:TTY LAYER AND SERIAL DRIVERS,
	open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

This series cleans up the mxs-auart driver by converting to devm-managed
resources, fixing clock prepare/enable ordering, and addressing IRQ
registration races.

Patch 1 fixes compilation on 64-bit build with W=1

Patch 2 reworks the clock handling to use devm_clk_get_enabled and
reorders clk_prepare_enable after clk_set_rate to avoid
CLK_SET_RATE_GATE failures.

Patch 3 converts iomem mapping and GPIO IRQ requests to devm,
removing the manual cleanup paths.

Patch 4 moves the main UART IRQ registration after uart_add_one_port
so the port state is initialized before the handler can run, and
manages the module clock for console vs non-console ports correctly.

v2: split off of_device_get_match_data change.

Rosen Penev (4):
  serial: mxs-auart: fix cast type for of_device_get_match_data
  serial: mxs-auart: rework clock handling in mxs_get_clks and probe
  serial: mxs-auart: use devm resources for iomem and GPIO IRQs
  serial: mxs-auart: fix IRQ registration ordering and manage console
    clock

 drivers/tty/serial/mxs-auart.c | 141 +++++++++++++++------------------
 1 file changed, 63 insertions(+), 78 deletions(-)

--
2.54.0


^ permalink raw reply

* Re: [PATCH] serial: max310x: implement gpio_chip::get_direction()
From: Hugo Villeneuve @ 2026-06-09 19:47 UTC (permalink / raw)
  To: Tapio Reijonen
  Cc: Greg Kroah-Hartman, Jiri Slaby, Linus Walleij,
	Bartosz Golaszewski, Alexander Shiyan, linux-kernel, linux-serial,
	linux-gpio
In-Reply-To: <20260602-b4-serial-max310x-gpio-get-direction-v1-1-23bf84e8ee14@vaisala.com>

Hi Tapio,

On Tue, 02 Jun 2026 10:02:35 +0000
Tapio Reijonen <tapio.reijonen@vaisala.com> wrote:

> It's strongly recommended for GPIO drivers to always implement the
> .get_direction() callback - even when the direction is tracked in
> software. The GPIO core emits a warning when the callback is missing
> and a user reads the direction of a line, e.g. via
> /sys/kernel/debug/gpio.
> 
> The MAX310X keeps the GPIO direction in the GPIOCFG register (a set bit
> selects output), which the existing direction_input/output callbacks
> already program, so the current direction can be read back directly.
> 
> Fixes: f65444187a66 ("serial: New serial driver MAX310X")
> Signed-off-by: Tapio Reijonen <tapio.reijonen@vaisala.com>
> ---
> Found and HW-tested on an i.MX6 SoloX board with a MAX14830 over SPI:
> without this, "cat /sys/kernel/debug/gpio" triggers the gpiolib.c:429
> WARNING (tainting the kernel W) on each queried MAX14830 line; with it
> applied the lines report their in/out direction and the WARNING is gone.
> ---
>  drivers/tty/serial/max310x.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
> index ac7d3f197c3a5ce3531d5607f48e21a807314021..96df54a90b009d1b547f7a639b0b9a4281daf073 100644
> --- a/drivers/tty/serial/max310x.c
> +++ b/drivers/tty/serial/max310x.c
> @@ -1212,6 +1212,18 @@ static int max310x_gpio_set(struct gpio_chip *chip, unsigned int offset,
>  	return 0;
>  }
>  
> +static int max310x_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
> +{
> +	struct max310x_port *s = gpiochip_get_data(chip);
> +	struct uart_port *port = &s->p[offset / 4].port;
> +	unsigned int val;
> +
> +	val = max310x_port_read(port, MAX310X_GPIOCFG_REG);
> +
> +	return (val & (1 << (offset % 4))) ? GPIO_LINE_DIRECTION_OUT
> +					   : GPIO_LINE_DIRECTION_IN;

Small nit to improve readability:

... val & BIT(offset % 4) ...

you could also put this return statement on a single line (less than
100 columns).


> +}
> +
>  static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
>  {
>  	struct max310x_port *s = gpiochip_get_data(chip);
> @@ -1421,6 +1433,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
>  	s->gpio.owner		= THIS_MODULE;
>  	s->gpio.parent		= dev;
>  	s->gpio.label		= devtype->name;
> +	s->gpio.get_direction	= max310x_gpio_get_direction;
>  	s->gpio.direction_input	= max310x_gpio_direction_input;
>  	s->gpio.get		= max310x_gpio_get;
>  	s->gpio.direction_output= max310x_gpio_direction_output;
> 
> ---
> base-commit: e7ae89a0c97ce2b68b0983cd01eda67cf373517d
> change-id: 20260602-b4-serial-max310x-gpio-get-direction-b10ee5be4f24
> 
> Best regards,
> -- 
> Tapio Reijonen <tapio.reijonen@vaisala.com>
> 
> 


-- 
Hugo Villeneuve

^ permalink raw reply

* Re: [PATCH RESEND v2 1/2] serial: earlycon: add uart_clk_freq parameter
From: Markus Probst @ 2026-06-09 14:56 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Rafael J. Wysocki, Len Brown, Thomas Bogendoerfer, Ard Biesheuvel,
	Ilias Apalodimas, Greg Kroah-Hartman, Jiri Slaby, linux-acpi,
	linux-kernel, linux-m68k, linux-mips, linux-efi, linux-serial
In-Reply-To: <CAMuHMdXH0mR9Sr+ze2_m94uc46_7gubApzWOkf+vUO+w=DmNoQ@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2270 bytes --]

On Tue, 2026-06-09 at 08:53 +0200, Geert Uytterhoeven wrote:
> Hi Markus,
> 
> On Tue, 9 Jun 2026 at 00:40, Markus Probst <markus.probst@posteo.de> wrote:
> > Add `uart_clk_freq` parameter to `setup_earlycon`. This allows the
> > options string to be reused with `add_preferred_console`, while still
> > allowing to set the uart clock frequency. This will be used in the
> > following commit ("ACPI: SPCR: Support UART clock frequency field").
> > 
> > No logical change intended.
> > 
> > Signed-off-by: Markus Probst <markus.probst@posteo.de>
> 
> > --- a/drivers/tty/serial/earlycon.c
> > +++ b/drivers/tty/serial/earlycon.c
> > @@ -135,11 +135,14 @@ static int __init parse_options(struct earlycon_device *device, char *options)
> >         return 0;
> >  }
> > 
> > -static int __init register_earlycon(char *buf, const struct earlycon_id *match)
> > +static int __init register_earlycon(char *buf, unsigned int uart_clk_freq,
> > +                                   const struct earlycon_id *match)
> >  {
> >         int err;
> >         struct uart_port *port = &early_console_dev.port;
> > 
> > +       port->uartclk = uart_clk_freq;
> 
> Who is actually consuming this value?

I think primarily init_port in drivers/tty/serial/8250/8250_early.c.

> Earlycon typically works with the serial console, as configured before
> Linux boot by the firmware.
Thats defined in the SPCR table. If "Configured Baud Rate" is set to 0,
it will use it as is [1]. If not, it will configure it.

Thanks
- Markus Probst

[1]https://learn.microsoft.com/en-us/windows-hardware/drivers/bringup/serial-port-console-redirection-table

> The Microsoft doc referenced in patch 2 seem to agree with that:
> 
>    "On a system where the BIOS or system firmware uses the serial
>     port for console input/output, this table should be used to convey
>     information about the settings, to ensure a seamless transition
>     between the firmware console output and Windows EMS output."
> 
> > +
> >         /* On parsing error, pass the options buf to the setup function */
> >         if (buf && !parse_options(&early_console_dev, buf))
> >                 buf = NULL;
> 
> Gr{oetje,eeting}s,
> 
>                         Geert

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 870 bytes --]

^ permalink raw reply

* Re: [Kernel Bug] INFO: task hung in show_cons_active
From: Greg KH @ 2026-06-09 12:10 UTC (permalink / raw)
  To: Longxing Li; +Cc: syzkaller, jirislaby, linux-kernel, linux-serial
In-Reply-To: <CAHPqNmzFQPFCom1Ng-FhbeRm=maLsKW1T4ZasGm40OkrxJfuwg@mail.gmail.com>

On Tue, Jun 09, 2026 at 07:49:13PM +0800, Longxing Li wrote:
> Dear Linux kernel developers and maintainers,
> 
> We would like to report a new kernel bug found by our tool. INFO: task
> hung in show_cons_active. Details are as follows.
> 
> Kernel commit: v7.0.6
> Kernel config: see attachment
> report: see attachment
> C repro and Syz repro: see attachment

There are no attachments here, nor any real information.

> We are currently analyzing the root cause and  working on a
> reproducible PoC. We will provide further updates in this thread as
> soon as we have more information.

Please just send a fix for the issue, that's the best way to get this
resolved.

thanks,

greg k-h

^ permalink raw reply

* [Kernel Bug] INFO: task hung in show_cons_active
From: Longxing Li @ 2026-06-09 11:49 UTC (permalink / raw)
  To: syzkaller, gregkh, jirislaby, linux-kernel, linux-serial

Dear Linux kernel developers and maintainers,

We would like to report a new kernel bug found by our tool. INFO: task
hung in show_cons_active. Details are as follows.

Kernel commit: v7.0.6
Kernel config: see attachment
report: see attachment
C repro and Syz repro: see attachment

We are currently analyzing the root cause and  working on a
reproducible PoC. We will provide further updates in this thread as
soon as we have more information.

Best regards,
Longxing Li

==================================================================
https://drive.google.com/file/d/1Bx2unEf-QntjVi8g6Zw7QNO6OP4cjGO_/view?usp=drive_link

https://drive.google.com/file/d/11hRSaOi-v5Ova5uFzNwCHD2qwF3C-dTV/view?usp=drive_link

https://drive.google.com/file/d/1VsRjuOkgL9Gp3uqRFVnCg9V4KUWLsVYP/view?usp=drive_link

https://drive.google.com/file/d/1P8ALUdJVTdZqwWjlLv11As0b0qJEp1hN/view?usp=drive_link

^ permalink raw reply

* Re: [PATCH RESEND v2 1/2] serial: earlycon: add uart_clk_freq parameter
From: Geert Uytterhoeven @ 2026-06-09  6:53 UTC (permalink / raw)
  To: Markus Probst
  Cc: Rafael J. Wysocki, Len Brown, Thomas Bogendoerfer, Ard Biesheuvel,
	Ilias Apalodimas, Greg Kroah-Hartman, Jiri Slaby, linux-acpi,
	linux-kernel, linux-m68k, linux-mips, linux-efi, linux-serial
In-Reply-To: <20260609-acpi_spcr-v2-1-3cd9a3bda727@posteo.de>

Hi Markus,

On Tue, 9 Jun 2026 at 00:40, Markus Probst <markus.probst@posteo.de> wrote:
> Add `uart_clk_freq` parameter to `setup_earlycon`. This allows the
> options string to be reused with `add_preferred_console`, while still
> allowing to set the uart clock frequency. This will be used in the
> following commit ("ACPI: SPCR: Support UART clock frequency field").
>
> No logical change intended.
>
> Signed-off-by: Markus Probst <markus.probst@posteo.de>

> --- a/drivers/tty/serial/earlycon.c
> +++ b/drivers/tty/serial/earlycon.c
> @@ -135,11 +135,14 @@ static int __init parse_options(struct earlycon_device *device, char *options)
>         return 0;
>  }
>
> -static int __init register_earlycon(char *buf, const struct earlycon_id *match)
> +static int __init register_earlycon(char *buf, unsigned int uart_clk_freq,
> +                                   const struct earlycon_id *match)
>  {
>         int err;
>         struct uart_port *port = &early_console_dev.port;
>
> +       port->uartclk = uart_clk_freq;

Who is actually consuming this value?
Earlycon typically works with the serial console, as configured before
Linux boot by the firmware.
The Microsoft doc referenced in patch 2 seem to agree with that:

   "On a system where the BIOS or system firmware uses the serial
    port for console input/output, this table should be used to convey
    information about the settings, to ensure a seamless transition
    between the firmware console output and Windows EMS output."

> +
>         /* On parsing error, pass the options buf to the setup function */
>         if (buf && !parse_options(&early_console_dev, buf))
>                 buf = NULL;

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH] serial: 8250_pnp: Drop unused assignments from pnp_device_id arrays
From: Uwe Kleine-König (The Capable Hub) @ 2026-06-09  6:46 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: Greg Kroah-Hartman, linux-kernel, linux-serial
In-Reply-To: <fd9576ec-0dbc-4ecf-bc5d-2630c7df637e@kernel.org>

[-- Attachment #1: Type: text/plain, Size: 1451 bytes --]

Hello Jiri,

On Tue, Jun 09, 2026 at 06:33:28AM +0200, Jiri Slaby wrote:
> On 08. 06. 26, 19:00, Uwe Kleine-König (The Capable Hub) wrote:
> > Explicitly assigning .driver_data in drivers that don't use this member
> > is silly and a bit irritating. Drop these.
> 
> You do not do that in the patch though.

Oh, I used the wrong commit message template. I wouldn't drop the
explicit zeros here because .driver_data is used as a bitmap and some
entries actually use a non-zero value here. So IMHO having the explicit
assignments is fine.

I'll send a v2 with the following commit log end of the week or so to
allow further feedback:

    serial: 8250_pnp: Use named initializers for pnp_device_id array

    While being less compact, using named initializers allows to more easily
    see which members of the structs are assigned which value without having
    to lookup the declaration of the struct. And it's also more robust
    against changes to the struct definition.

    The mentioned robustness is relevant for a planned change to struct
    pnp_device_id that replaces .driver_data by an anonymous union.

    This patch doesn't modify the compiled array, only their representation
    in source form benefits. The former was confirmed with x86 and arm64
    builds.

    Also simplify the list terminator and use a consistent and more common
    indention.

Thanks for paying attention, best regards
Uwe

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox