* [PATCH v2 16/32] pinctrl: mediatek: mt8365: Enable module build support
From: Justin Yeh @ 2026-06-26 1:31 UTC (permalink / raw)
To: Sean Wang, Linus Walleij, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Project_Global_Chrome_Upstream_Group, linux-mediatek, linux-gpio,
linux-kernel, linux-arm-kernel, Justin Yeh
In-Reply-To: <20260626013217.2373808-1-justin.yeh@mediatek.com>
Add MODULE_LICENSE("GPL") macro and change Kconfig option from
bool to tristate to allow building as a loadable kernel module.
This is required for Android GKI + vendor_dlkm deployments where
vendor-specific drivers must be kept separate from the GKI vmlinux.
Fixes: e94d8b6fb83a ("pinctrl: mediatek: add support for mt8365 SoC")
Signed-off-by: Justin Yeh <justin.yeh@mediatek.com>
---
drivers/pinctrl/mediatek/Kconfig | 2 +-
drivers/pinctrl/mediatek/pinctrl-mt8365.c | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index 7bb9cb15dfba..5d0d96fd75d5 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -308,7 +308,7 @@ config PINCTRL_MT8196
map specific eint which doesn't have real gpio pin.
config PINCTRL_MT8365
- bool "MediaTek MT8365 pin control"
+ tristate "MediaTek MT8365 pin control"
depends on OF
depends on ARM64 || COMPILE_TEST
default ARM64 && ARCH_MEDIATEK
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8365.c b/drivers/pinctrl/mediatek/pinctrl-mt8365.c
index c20b9e2e02dd..d41d99ab8c36 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8365.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8365.c
@@ -494,4 +494,5 @@ static int __init mtk_pinctrl_init(void)
arch_initcall(mtk_pinctrl_init);
MODULE_DESCRIPTION("MediaTek MT8365 Pinctrl Driver");
+MODULE_LICENSE("GPL");
MODULE_AUTHOR("Zhiyong Tao <zhiyong.tao@mediatek.com>");
--
2.45.2
^ permalink raw reply related
* [PATCH v2 01/32] pinctrl: mediatek: mt8189: Enable module build support
From: Justin Yeh @ 2026-06-26 1:31 UTC (permalink / raw)
To: Sean Wang, Linus Walleij, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Project_Global_Chrome_Upstream_Group, linux-mediatek, linux-gpio,
linux-kernel, linux-arm-kernel, Justin Yeh
In-Reply-To: <20260626013217.2373808-1-justin.yeh@mediatek.com>
Add MODULE_LICENSE("GPL") macro and change Kconfig option from
bool to tristate to allow building as a loadable kernel module.
This is required for Android GKI + vendor_dlkm deployments where
vendor-specific drivers must be kept separate from the GKI vmlinux.
Fixes: a3fe1324c3c5 ("pinctrl: mediatek: Add pinctrl driver for mt8189")
Signed-off-by: Justin Yeh <justin.yeh@mediatek.com>
---
drivers/pinctrl/mediatek/Kconfig | 2 +-
drivers/pinctrl/mediatek/pinctrl-mt8189.c | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index 4819617d9368..a75434e7e989 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -270,7 +270,7 @@ config PINCTRL_MT8188
map specific eint which doesn't have real gpio pin.
config PINCTRL_MT8189
- bool "MediaTek MT8189 pin control"
+ tristate "MediaTek MT8189 pin control"
depends on OF
depends on ARM64 || COMPILE_TEST
default ARM64 && ARCH_MEDIATEK
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8189.c b/drivers/pinctrl/mediatek/pinctrl-mt8189.c
index cd4cdff309a1..67ae7170670c 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8189.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8189.c
@@ -1696,3 +1696,4 @@ static int __init mt8189_pinctrl_init(void)
arch_initcall(mt8189_pinctrl_init);
MODULE_DESCRIPTION("MediaTek MT8189 Pinctrl Driver");
+MODULE_LICENSE("GPL");
--
2.45.2
^ permalink raw reply related
* [PATCH v2 09/32] pinctrl: mediatek: mt8173: Enable module build support
From: Justin Yeh @ 2026-06-26 1:31 UTC (permalink / raw)
To: Sean Wang, Linus Walleij, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Project_Global_Chrome_Upstream_Group, linux-mediatek, linux-gpio,
linux-kernel, linux-arm-kernel, Justin Yeh
In-Reply-To: <20260626013217.2373808-1-justin.yeh@mediatek.com>
Add MODULE_LICENSE("GPL") macro and change Kconfig option from
bool to tristate to allow building as a loadable kernel module.
This is required for Android GKI + vendor_dlkm deployments where
vendor-specific drivers must be kept separate from the GKI vmlinux.
Fixes: 30f010f5c4cf ("arm64: mediatek: Add Pinctrl/GPIO/EINT driver for mt8173.")
Signed-off-by: Justin Yeh <justin.yeh@mediatek.com>
---
drivers/pinctrl/mediatek/Kconfig | 2 +-
drivers/pinctrl/mediatek/pinctrl-mt8173.c | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index 20d84d6bd9d1..8cdba1f719ef 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -237,7 +237,7 @@ config PINCTRL_MT8167
select PINCTRL_MTK
config PINCTRL_MT8173
- bool "MediaTek MT8173 pin control"
+ tristate "MediaTek MT8173 pin control"
depends on OF
depends on ARM64 || COMPILE_TEST
default ARM64 && ARCH_MEDIATEK
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8173.c b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
index b214deeafbf1..a6d1e4aedb5e 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
@@ -356,3 +356,6 @@ static int __init mtk_pinctrl_init(void)
return platform_driver_register(&mtk_pinctrl_driver);
}
arch_initcall(mtk_pinctrl_init);
+
+MODULE_DESCRIPTION("MediaTek MT8173 Pinctrl Driver");
+MODULE_LICENSE("GPL");
--
2.45.2
^ permalink raw reply related
* [PATCH v2 04/32] pinctrl: mediatek: mt7622: Enable module build support
From: Justin Yeh @ 2026-06-26 1:31 UTC (permalink / raw)
To: Sean Wang, Linus Walleij, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Project_Global_Chrome_Upstream_Group, linux-mediatek, linux-gpio,
linux-kernel, linux-arm-kernel, Justin Yeh
In-Reply-To: <20260626013217.2373808-1-justin.yeh@mediatek.com>
Add MODULE_LICENSE("GPL") macro and change Kconfig option from
bool to tristate to allow building as a loadable kernel module.
This is required for Android GKI + vendor_dlkm deployments where
vendor-specific drivers must be kept separate from the GKI vmlinux.
Fixes: d6ed93551320 ("pinctrl: mediatek: add pinctrl driver for MT7622 SoC")
Signed-off-by: Justin Yeh <justin.yeh@mediatek.com>
---
drivers/pinctrl/mediatek/Kconfig | 2 +-
drivers/pinctrl/mediatek/pinctrl-mt7622.c | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index 3e4002a6ce78..77f974bdfe90 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -202,7 +202,7 @@ config PINCTRL_MT6893
on the MediaTek Dimensity 1200 MT6893 Smartphone SoC.
config PINCTRL_MT7622
- bool "MediaTek MT7622 pin control"
+ tristate "MediaTek MT7622 pin control"
depends on OF
depends on ARM64 || COMPILE_TEST
default ARM64 && ARCH_MEDIATEK
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7622.c b/drivers/pinctrl/mediatek/pinctrl-mt7622.c
index d5777889448a..5516656e630b 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt7622.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7622.c
@@ -893,3 +893,6 @@ static int __init mt7622_pinctrl_init(void)
return platform_driver_register(&mt7622_pinctrl_driver);
}
arch_initcall(mt7622_pinctrl_init);
+
+MODULE_DESCRIPTION("MediaTek MT7622 Pinctrl Driver");
+MODULE_LICENSE("GPL");
--
2.45.2
^ permalink raw reply related
* [PATCH v2 03/32] pinctrl: mediatek: mt6893: Enable module build support
From: Justin Yeh @ 2026-06-26 1:31 UTC (permalink / raw)
To: Sean Wang, Linus Walleij, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Project_Global_Chrome_Upstream_Group, linux-mediatek, linux-gpio,
linux-kernel, linux-arm-kernel, Justin Yeh
In-Reply-To: <20260626013217.2373808-1-justin.yeh@mediatek.com>
Add MODULE_LICENSE("GPL") macro and change Kconfig option from
bool to tristate to allow building as a loadable kernel module.
This is required for Android GKI + vendor_dlkm deployments where
vendor-specific drivers must be kept separate from the GKI vmlinux.
Fixes: 8004507179c8 ("pinctrl: mediatek: Add pinctrl driver for MT6893 Dimensity 1200")
Signed-off-by: Justin Yeh <justin.yeh@mediatek.com>
---
drivers/pinctrl/mediatek/Kconfig | 2 +-
drivers/pinctrl/mediatek/pinctrl-mt6893.c | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index 2859ac27dbfd..3e4002a6ce78 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -192,7 +192,7 @@ config PINCTRL_MT6878
on the MediaTek MT6878 SoC.
config PINCTRL_MT6893
- bool "MediaTek Dimensity MT6893 pin control"
+ tristate "MediaTek Dimensity MT6893 pin control"
depends on OF
depends on ARM64 || COMPILE_TEST
default ARM64 && ARCH_MEDIATEK
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6893.c b/drivers/pinctrl/mediatek/pinctrl-mt6893.c
index 468ce0109b07..b4d8bec8a481 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt6893.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt6893.c
@@ -877,3 +877,4 @@ static int __init mt6893_pinctrl_init(void)
arch_initcall(mt6893_pinctrl_init);
MODULE_DESCRIPTION("MediaTek MT6893 Pinctrl Driver");
+MODULE_LICENSE("GPL");
--
2.45.2
^ permalink raw reply related
* [PATCH v2 00/32] pinctrl: mediatek: Enable module build support for all drivers
From: Justin Yeh @ 2026-06-26 1:31 UTC (permalink / raw)
To: Sean Wang, Linus Walleij, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Project_Global_Chrome_Upstream_Group, linux-mediatek, linux-gpio,
linux-kernel, linux-arm-kernel, Justin Yeh
This series enables all MediaTek pinctrl drivers to be built as loadable
kernel modules. This is required for Android GKI (Generic Kernel Image) +
vendor_dlkm deployments where vendor-specific drivers must be kept separate
from the GKI vmlinux.
Each patch adds MODULE_LICENSE("GPL") and MODULE_DESCRIPTION() macros where
missing, and changes the Kconfig option from bool to tristate. This allows
these drivers to be properly packaged as vendor kernel modules while
maintaining the existing built-in option.
Changes in v2:
* Squash MODULE_LICENSE and tristate changes into single patch per driver
* Extend fix to all MediaTek pinctrl drivers (32 total), not just MT8189
* Add Android GKI + vendor_dlkm context to cover letter
* Add MODULE_DESCRIPTION() where it was missing
* Add Fixes: tags referencing the original commits that added each driver
Justin Yeh (32):
pinctrl: mediatek: mt8189: Enable module build support
pinctrl: mediatek: mt6878: Enable module build support
pinctrl: mediatek: mt6893: Enable module build support
pinctrl: mediatek: mt7622: Enable module build support
pinctrl: mediatek: mt7981: Enable module build support
pinctrl: mediatek: mt7986: Enable module build support
pinctrl: mediatek: mt7988: Enable module build support
pinctrl: mediatek: mt8167: Enable module build support
pinctrl: mediatek: mt8173: Enable module build support
pinctrl: mediatek: mt8183: Enable module build support
pinctrl: mediatek: mt8186: Enable module build support
pinctrl: mediatek: mt8188: Enable module build support
pinctrl: mediatek: mt8192: Enable module build support
pinctrl: mediatek: mt8195: Enable module build support
pinctrl: mediatek: mt8196: Enable module build support
pinctrl: mediatek: mt8365: Enable module build support
pinctrl: mediatek: mt8516: Enable module build support
pinctrl: mediatek: mt2701: Enable module build support
pinctrl: mediatek: mt7623: Enable module build support
pinctrl: mediatek: mt7629: Enable module build support
pinctrl: mediatek: mt8135: Enable module build support
pinctrl: mediatek: mt8127: Enable module build support
pinctrl: mediatek: mt7620: Enable module build support
pinctrl: mediatek: mt7621: Enable module build support
pinctrl: mediatek: mt76x8: Enable module build support
pinctrl: mediatek: rt2880: Enable module build support
pinctrl: mediatek: rt305x: Enable module build support
pinctrl: mediatek: rt3883: Enable module build support
pinctrl: mediatek: mt6397: Enable module build support
pinctrl: mediatek: mt2712: Enable module build support
pinctrl: mediatek: mt6795: Enable module build support
pinctrl: mediatek: mt6797: Enable module build support
drivers/pinctrl/mediatek/Kconfig | 64 +++++++++++------------
drivers/pinctrl/mediatek/pinctrl-mt2701.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt2712.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt6397.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt6795.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt6797.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt6878.c | 1 +
drivers/pinctrl/mediatek/pinctrl-mt6893.c | 1 +
drivers/pinctrl/mediatek/pinctrl-mt7620.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt7621.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt7622.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt7623.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt7629.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt76x8.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt7981.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt7986.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt7988.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt8127.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt8135.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt8167.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt8173.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt8183.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt8186.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt8188.c | 1 +
drivers/pinctrl/mediatek/pinctrl-mt8189.c | 1 +
drivers/pinctrl/mediatek/pinctrl-mt8192.c | 1 +
drivers/pinctrl/mediatek/pinctrl-mt8195.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-mt8196.c | 1 +
drivers/pinctrl/mediatek/pinctrl-mt8365.c | 1 +
drivers/pinctrl/mediatek/pinctrl-mt8516.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-rt2880.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-rt305x.c | 3 ++
drivers/pinctrl/mediatek/pinctrl-rt3883.c | 3 ++
33 files changed, 114 insertions(+), 32 deletions(-)
--
2.45.2
^ permalink raw reply
* [PATCH] arm64/mm: Optimize TLB flush in unmap_hotplug_[pmd|pud]_range()
From: Anshuman Khandual @ 2026-06-26 1:28 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Anshuman Khandual, Catalin Marinas, Will Deacon, Ryan Roberts,
David Hildenbrand, linux-kernel, Ben Hutchings
flush_tlb_kernel_range() could flush down an entire block mapping just with
a single PAGE_SIZE stride. This capability was being used umapping PMD and
PUD based block mappings in unmap_hotplug_[pmd|pud]_range().
But later on the commit 48478b9f7913
("arm64/mm: Enable batched TLB flush in unmap_hotplug_range()") replaced
this PAGE_SIZE stride with [PMD|PUD]_SIZE strides, hence forcing multiple
PAGE_SIZE stride based TLB flushes on platforms where TLB range operation
is not supported. Revert back to the earlier TLB behaviour along with the
required comments that were dropped earlier.
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: David Hildenbrand <david@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Reported-by: Ben Hutchings <ben@decadent.org.uk>
Closes: https://lore.kernel.org/all/b0d5836032ce3135bfc473f6bff791306d086925.camel@decadent.org.uk/
Fixes: 48478b9f7913 ("arm64/mm: Enable batched TLB flush in unmap_hotplug_range()")
Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
---
arch/arm64/mm/mmu.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 8242f93f05e4..5ff0041f4a5f 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -1509,7 +1509,11 @@ static void unmap_hotplug_pmd_range(pud_t *pudp, unsigned long addr,
if (free_mapped) {
/* CONT blocks are not supported in the vmemmap */
WARN_ON(pmd_cont(pmd));
- flush_tlb_kernel_range(addr, addr + PMD_SIZE);
+ /*
+ * One TLBI should be sufficient here as the PMD_SIZE
+ * range is mapped with a single block entry.
+ */
+ flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
free_hotplug_page_range(pmd_page(pmd),
PMD_SIZE, altmap);
}
@@ -1539,7 +1543,11 @@ static void unmap_hotplug_pud_range(p4d_t *p4dp, unsigned long addr,
if (pud_leaf(pud)) {
pud_clear(pudp);
if (free_mapped) {
- flush_tlb_kernel_range(addr, addr + PUD_SIZE);
+ /*
+ * One TLBI should be sufficient here as the PUD_SIZE
+ * range is mapped with a single block entry.
+ */
+ flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
free_hotplug_page_range(pud_page(pud),
PUD_SIZE, altmap);
}
--
2.30.2
^ permalink raw reply related
* [PATCH RFC 3/4] media: i2c: Add Samsung S5K3L6 image sensor driver
From: Vincent Cloutier @ 2026-06-26 0:06 UTC (permalink / raw)
To: linux-media, devicetree, linux-arm-kernel
Cc: linux-kernel, linux-imx, kernel, Vincent Cloutier,
Mauro Carvalho Chehab, Sakari Ailus, Hans Verkuil, Hans de Goede,
Vladimir Zapolskiy, Mehdi Djait, Laurent Pinchart, Xiaolei Wang,
Walter Werner Schneider, Kate Hsuan, Hardevsinh Palaniya,
Himanshu Bhavani, Svyatoslav Ryhel
In-Reply-To: <20260626000715.1111803-1-vincent.cloutier@icloud.com>
From: Vincent Cloutier <vincent@cloutier.co>
Add a V4L2 sub-device driver for the Samsung S5K3L6 raw Bayer image
sensor.
The initial driver supports the production path used by the Librem 5 rear
camera: a 25 MHz input clock, two MIPI CSI-2 data lanes, RAW8 and RAW10
Bayer modes derived from the full 4208x3120 active array, runtime PM, CCI
register access, basic exposure/gain/blanking controls, test patterns, and
fwnode orientation controls.
This driver is derived from the Librem 5 downstream S5K3L6 carry, initially
authored by Martin Kepplinger and substantially developed by Dorota
Czaplejewicz and Sebastian Krzyszkowiak. The upstream submission rewrites
and collapses that history into a current V4L2 sensor driver shape.
Signed-off-by: Vincent Cloutier <vincent@cloutier.co>
Assisted-by: OpenCode:gpt-5.5
---
drivers/media/i2c/Kconfig | 10 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/s5k3l6.c | 1055 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 1066 insertions(+)
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 5d173e0ecf42..5ec4db05920a 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -781,6 +781,16 @@ config VIDEO_S5K3M5
To compile this driver as a module, choose M here: the
module will be called s5k3m5.
+config VIDEO_S5K3L6
+ tristate "Samsung S5K3L6 sensor support"
+ select V4L2_CCI_I2C
+ help
+ This is a V4L2 sensor driver for Samsung S5K3L6 13MP raw
+ camera sensor.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s5k3l6.
+
config VIDEO_S5K5BAF
tristate "Samsung S5K5BAF sensor support"
help
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index e45359efe0e4..f3360e97aa38 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -128,6 +128,7 @@ obj-$(CONFIG_VIDEO_RDACM21) += rdacm21.o
obj-$(CONFIG_VIDEO_RJ54N1) += rj54n1cb0c.o
obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/
obj-$(CONFIG_VIDEO_S5K3M5) += s5k3m5.o
+obj-$(CONFIG_VIDEO_S5K3L6) += s5k3l6.o
obj-$(CONFIG_VIDEO_S5K5BAF) += s5k5baf.o
obj-$(CONFIG_VIDEO_S5K6A3) += s5k6a3.o
obj-$(CONFIG_VIDEO_S5KJN1) += s5kjn1.o
diff --git a/drivers/media/i2c/s5k3l6.c b/drivers/media/i2c/s5k3l6.c
new file mode 100644
index 000000000000..f70f83e9de17
--- /dev/null
+++ b/drivers/media/i2c/s5k3l6.c
@@ -0,0 +1,1055 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2020-2021 Purism SPC
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/units.h>
+
+#include <media/v4l2-cci.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
+
+#define S5K3L6_MCLK_FREQ (25 * HZ_PER_MHZ)
+#define S5K3L6_DATA_LANES 2
+
+#define S5K3L6_LINK_FREQ_537P5MHZ (537500ULL * HZ_PER_KHZ)
+#define S5K3L6_LINK_FREQ_600MHZ (600ULL * HZ_PER_MHZ)
+#define S5K3L6_LINK_FREQ_625MHZ (625ULL * HZ_PER_MHZ)
+
+/* Downstream mode tables use a fixed 480 MHz VT pixel clock. */
+#define S5K3L6_PIXEL_RATE (480ULL * HZ_PER_MHZ)
+
+#define S5K3L6_PIXEL_ARRAY_WIDTH 4224
+#define S5K3L6_PIXEL_ARRAY_HEIGHT 3136
+#define S5K3L6_ACTIVE_LEFT 8
+#define S5K3L6_ACTIVE_TOP 8
+#define S5K3L6_ACTIVE_WIDTH 4208
+#define S5K3L6_ACTIVE_HEIGHT 3120
+
+#define S5K3L6_CHIP_ID 0x30c6
+#define S5K3L6_REVISION 0xb0
+
+#define S5K3L6_REG_CHIP_ID CCI_REG16(0x0000)
+#define S5K3L6_REG_REVISION CCI_REG8(0x0002)
+#define S5K3L6_REG_MODE_SELECT CCI_REG8(0x0100)
+#define S5K3L6_MODE_STANDBY 0x00
+#define S5K3L6_MODE_STREAMING 0x01
+
+#define S5K3L6_REG_LANE_MODE CCI_REG8(0x0114)
+#define S5K3L6_REG_DATA_FORMAT CCI_REG16(0x0112)
+#define S5K3L6_DATA_FORMAT_RAW8 0x0808
+#define S5K3L6_DATA_FORMAT_RAW10 0x0a0a
+
+#define S5K3L6_REG_OP_PLL_MULTIPLIER CCI_REG16(0x030e)
+#define S5K3L6_REG_REQUESTED_LINK_RATE CCI_REG16(0x0820)
+#define S5K3L6_REG_FRAME_LENGTH CCI_REG16(0x0340)
+#define S5K3L6_REG_LINE_LENGTH CCI_REG16(0x0342)
+#define S5K3L6_REG_X_ADDR_START CCI_REG16(0x0344)
+#define S5K3L6_REG_Y_ADDR_START CCI_REG16(0x0346)
+#define S5K3L6_REG_X_ADDR_END CCI_REG16(0x0348)
+#define S5K3L6_REG_Y_ADDR_END CCI_REG16(0x034a)
+#define S5K3L6_REG_X_OUTPUT_SIZE CCI_REG16(0x034c)
+#define S5K3L6_REG_Y_OUTPUT_SIZE CCI_REG16(0x034e)
+
+#define S5K3L6_REG_EXPOSURE CCI_REG16(0x0202)
+#define S5K3L6_EXPOSURE_MIN 2
+#define S5K3L6_EXPOSURE_MARGIN 2
+
+#define S5K3L6_REG_ANALOG_GAIN CCI_REG16(0x0204)
+#define S5K3L6_ANALOG_GAIN_MIN 0x20
+#define S5K3L6_ANALOG_GAIN_MAX 0x200
+#define S5K3L6_ANALOG_GAIN_DEFAULT 0x20
+
+#define S5K3L6_REG_DIGITAL_GAIN CCI_REG16(0x020e)
+#define S5K3L6_DIGITAL_GAIN_MIN 0x100
+#define S5K3L6_DIGITAL_GAIN_MAX 0x300
+#define S5K3L6_DIGITAL_GAIN_DEFAULT 0x100
+
+#define S5K3L6_REG_TEST_PATTERN CCI_REG8(0x0601)
+
+#define S5K3L6_REG_BPC CCI_REG8(0x3403)
+#define S5K3L6_BPC_FILTER BIT(0)
+#define S5K3L6_BPC_AF_FILTER BIT(2)
+
+#define S5K3L6_REG_PLL_PD CCI_REG8(0x3c1e)
+#define S5K3L6_REG_MIPI_CONTINUOUS CCI_REG8(0x38a1)
+
+#define to_s5k3l6(_sd) container_of(_sd, struct s5k3l6, sd)
+
+static const s64 s5k3l6_link_freq_menu[] = {
+ S5K3L6_LINK_FREQ_537P5MHZ,
+ S5K3L6_LINK_FREQ_600MHZ,
+ S5K3L6_LINK_FREQ_625MHZ,
+};
+
+static const char *const s5k3l6_supply_names[] = {
+ "vddio",
+ "vdda",
+ "vddd",
+};
+
+#define S5K3L6_NUM_SUPPLIES ARRAY_SIZE(s5k3l6_supply_names)
+
+struct s5k3l6_reg_list {
+ const struct cci_reg_sequence *regs;
+ unsigned int num_regs;
+};
+
+struct s5k3l6_mode {
+ u32 width;
+ u32 height;
+ u32 code;
+ u32 hts;
+ u32 vts;
+ u32 data_format;
+ u16 op_pll_multiplier;
+ u8 binning;
+ u8 link_freq_index;
+
+ const struct s5k3l6_reg_list reg_list;
+};
+
+struct s5k3l6 {
+ struct device *dev;
+ struct regmap *regmap;
+ struct clk *mclk;
+ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data supplies[S5K3L6_NUM_SUPPLIES];
+
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct v4l2_ctrl *link_freq;
+ struct v4l2_ctrl *pixel_rate;
+ struct v4l2_ctrl *hblank;
+ struct v4l2_ctrl *vblank;
+ struct v4l2_ctrl *exposure;
+
+ const struct s5k3l6_mode *mode;
+};
+
+static const struct cci_reg_sequence s5k3l6_binning_4x4[] = {
+ { CCI_REG8(0x0900), 0x01 },
+ { CCI_REG8(0x0901), 0x44 },
+ { CCI_REG8(0x0387), 0x07 },
+ { CCI_REG16(0x3090), 0x8000 },
+ { CCI_REG16(0x314a), 0x5f02 },
+ { CCI_REG16(0x32b2), 0x0006 },
+ { CCI_REG16(0x32b4), 0x0006 },
+ { CCI_REG16(0x32b6), 0x0006 },
+ { CCI_REG16(0x32b8), 0x0006 },
+ { CCI_REG16(0x3238), 0x000a },
+ { CCI_REG16(0x380c), 0x003b },
+};
+
+static const struct cci_reg_sequence s5k3l6_binning_2x2[] = {
+ { CCI_REG8(0x0900), 0x01 },
+ { CCI_REG8(0x0901), 0x22 },
+ { CCI_REG8(0x0387), 0x03 },
+ { CCI_REG16(0x3090), 0x8000 },
+ { CCI_REG16(0x314a), 0x5f02 },
+ { CCI_REG16(0x32b2), 0x0003 },
+ { CCI_REG16(0x32b4), 0x0003 },
+ { CCI_REG16(0x32b6), 0x0003 },
+ { CCI_REG16(0x32b8), 0x0003 },
+ { CCI_REG16(0x3238), 0x000b },
+ { CCI_REG16(0x380c), 0x0049 },
+};
+
+static const struct cci_reg_sequence s5k3l6_no_binning[] = {
+ { CCI_REG8(0x0900), 0x00 },
+ { CCI_REG8(0x0387), 0x01 },
+ { CCI_REG16(0x3090), 0x8800 },
+ { CCI_REG16(0x314a), 0x5f00 },
+ { CCI_REG16(0x32b2), 0x0000 },
+ { CCI_REG16(0x32b4), 0x0000 },
+ { CCI_REG16(0x32b6), 0x0000 },
+ { CCI_REG16(0x32b8), 0x0000 },
+ { CCI_REG16(0x3238), 0x000c },
+ { CCI_REG16(0x380c), 0x0090 },
+};
+
+static const struct cci_reg_sequence s5k3l6_common_regs[] = {
+ { CCI_REG16(0x0136), 0x1900 },
+ { CCI_REG16(0x0300), 0x0005 },
+ { CCI_REG16(0x0304), 0x0004 },
+ { CCI_REG16(0x0306), 0x0060 },
+ { CCI_REG16(0x030c), 0x0004 },
+ { CCI_REG16(0x3002), 0x0e00 },
+ { CCI_REG16(0x3006), 0x1000 },
+ { CCI_REG16(0x300a), 0x0c00 },
+ { CCI_REG16(0x3018), 0xc500 },
+ { CCI_REG16(0x3024), 0x0016 },
+ { CCI_REG16(0x306a), 0x2f4c },
+ { CCI_REG16(0x3070), 0x3d00 },
+ { CCI_REG16(0x3072), 0x0013 },
+ { CCI_REG16(0x3074), 0x0977 },
+ { CCI_REG16(0x3076), 0x9411 },
+ { CCI_REG16(0x307a), 0x0d20 },
+ { CCI_REG16(0x3084), 0x1314 },
+ { CCI_REG16(0x309c), 0x0640 },
+ { CCI_REG16(0x309e), 0x002d },
+ { CCI_REG16(0x3266), 0x0001 },
+ { CCI_REG16(0x3452), 0x0000 },
+ { CCI_REG16(0x345a), 0x0000 },
+ { CCI_REG16(0x345c), 0x0000 },
+ { CCI_REG16(0x345e), 0x0000 },
+ { CCI_REG16(0x3460), 0x0000 },
+ { CCI_REG16(0x38da), 0x000a },
+ { CCI_REG16(0x38dc), 0x000b },
+ { CCI_REG16(0x38d6), 0x000a },
+ { CCI_REG16(0x3932), 0x1000 },
+ { CCI_REG16(0x393e), 0x4000 },
+ { CCI_REG16(0x3c36), 0x2800 },
+ { CCI_REG16(0x3c38), 0x0028 },
+ { S5K3L6_REG_MIPI_CONTINUOUS, 0x7e },
+ { S5K3L6_REG_BPC,
+ 0x42 | S5K3L6_BPC_FILTER | S5K3L6_BPC_AF_FILTER },
+};
+
+static const struct s5k3l6_mode s5k3l6_supported_modes[] = {
+ {
+ .width = 1052,
+ .height = 780,
+ .code = MEDIA_BUS_FMT_SGRBG8_1X8,
+ .hts = 0x1320,
+ .vts = 0x0331,
+ .data_format = S5K3L6_DATA_FORMAT_RAW8,
+ .op_pll_multiplier = 0x56,
+ .binning = 4,
+ .link_freq_index = 0,
+ .reg_list = {
+ .regs = s5k3l6_binning_4x4,
+ .num_regs = ARRAY_SIZE(s5k3l6_binning_4x4),
+ },
+ }, {
+ .width = 2104,
+ .height = 1560,
+ .code = MEDIA_BUS_FMT_SGRBG8_1X8,
+ .hts = 0x1320,
+ .vts = 0x0662,
+ .data_format = S5K3L6_DATA_FORMAT_RAW8,
+ .op_pll_multiplier = 0x56,
+ .binning = 2,
+ .link_freq_index = 0,
+ .reg_list = {
+ .regs = s5k3l6_binning_2x2,
+ .num_regs = ARRAY_SIZE(s5k3l6_binning_2x2),
+ },
+ }, {
+ .width = 4208,
+ .height = 3120,
+ .code = MEDIA_BUS_FMT_SGRBG8_1X8,
+ .hts = 0x1ce0,
+ .vts = 0x0cbc,
+ .data_format = S5K3L6_DATA_FORMAT_RAW8,
+ .op_pll_multiplier = 0x64,
+ .binning = 1,
+ .link_freq_index = 2,
+ .reg_list = {
+ .regs = s5k3l6_no_binning,
+ .num_regs = ARRAY_SIZE(s5k3l6_no_binning),
+ },
+ }, {
+ .width = 1052,
+ .height = 780,
+ .code = MEDIA_BUS_FMT_SGRBG10_1X10,
+ .hts = 0x1320,
+ .vts = 0x0331,
+ .data_format = S5K3L6_DATA_FORMAT_RAW10,
+ .op_pll_multiplier = 0x56,
+ .binning = 4,
+ .link_freq_index = 0,
+ .reg_list = {
+ .regs = s5k3l6_binning_4x4,
+ .num_regs = ARRAY_SIZE(s5k3l6_binning_4x4),
+ },
+ }, {
+ .width = 2104,
+ .height = 1560,
+ .code = MEDIA_BUS_FMT_SGRBG10_1X10,
+ .hts = 0x1320,
+ .vts = 0x0662,
+ .data_format = S5K3L6_DATA_FORMAT_RAW10,
+ .op_pll_multiplier = 0x60,
+ .binning = 2,
+ .link_freq_index = 1,
+ .reg_list = {
+ .regs = s5k3l6_binning_2x2,
+ .num_regs = ARRAY_SIZE(s5k3l6_binning_2x2),
+ },
+ }, {
+ .width = 4208,
+ .height = 3120,
+ .code = MEDIA_BUS_FMT_SGRBG10_1X10,
+ .hts = 0x2650,
+ .vts = 0x0cbc,
+ .data_format = S5K3L6_DATA_FORMAT_RAW10,
+ .op_pll_multiplier = 0x64,
+ .binning = 1,
+ .link_freq_index = 2,
+ .reg_list = {
+ .regs = s5k3l6_no_binning,
+ .num_regs = ARRAY_SIZE(s5k3l6_no_binning),
+ },
+ },
+};
+
+static const char *const s5k3l6_test_pattern_menu[] = {
+ "Disabled",
+ "Solid color",
+ "Color bars",
+};
+
+static bool s5k3l6_code_supported(u32 code)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(s5k3l6_supported_modes); i++) {
+ if (s5k3l6_supported_modes[i].code == code)
+ return true;
+ }
+
+ return false;
+}
+
+static const struct s5k3l6_mode *s5k3l6_find_mode(u32 code, u32 width,
+ u32 height)
+{
+ const struct s5k3l6_mode *best = NULL;
+ u32 best_delta = U32_MAX;
+ unsigned int i;
+
+ if (!s5k3l6_code_supported(code))
+ code = s5k3l6_supported_modes[0].code;
+
+ for (i = 0; i < ARRAY_SIZE(s5k3l6_supported_modes); i++) {
+ const struct s5k3l6_mode *mode = &s5k3l6_supported_modes[i];
+ u32 delta;
+
+ if (mode->code != code)
+ continue;
+
+ delta = abs((int)mode->width - (int)width) +
+ abs((int)mode->height - (int)height);
+ if (!best || delta < best_delta) {
+ best = mode;
+ best_delta = delta;
+ }
+ }
+
+ return best;
+}
+
+static void s5k3l6_update_pad_format(const struct s5k3l6_mode *mode,
+ struct v4l2_mbus_framefmt *fmt)
+{
+ fmt->code = mode->code;
+ fmt->width = mode->width;
+ fmt->height = mode->height;
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->colorspace = V4L2_COLORSPACE_RAW;
+ fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+ fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+ fmt->xfer_func = V4L2_XFER_FUNC_NONE;
+}
+
+static void s5k3l6_update_controls(struct s5k3l6 *s5k3l6,
+ const struct s5k3l6_mode *mode)
+{
+ u32 hblank = mode->hts - mode->width;
+ u32 vblank = mode->vts - mode->height;
+ u32 exposure_max = mode->vts - S5K3L6_EXPOSURE_MARGIN;
+ u32 exposure_default = min_t(u32, 0x03de, exposure_max);
+
+ __v4l2_ctrl_s_ctrl(s5k3l6->link_freq, mode->link_freq_index);
+ __v4l2_ctrl_modify_range(s5k3l6->hblank, hblank, hblank, 1, hblank);
+ __v4l2_ctrl_modify_range(s5k3l6->vblank, vblank,
+ 0xffff - mode->height, 1, vblank);
+ __v4l2_ctrl_s_ctrl(s5k3l6->vblank, vblank);
+ __v4l2_ctrl_modify_range(s5k3l6->exposure, S5K3L6_EXPOSURE_MIN,
+ exposure_max, 1, exposure_default);
+ __v4l2_ctrl_s_ctrl(s5k3l6->exposure, exposure_default);
+}
+
+static int s5k3l6_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct s5k3l6 *s5k3l6 =
+ container_of(ctrl->handler, struct s5k3l6, ctrl_handler);
+ const struct s5k3l6_mode *mode = s5k3l6->mode;
+ u32 frame_length;
+ u32 exposure_max;
+ int active;
+ int ret;
+
+ if (ctrl->id == V4L2_CID_VBLANK) {
+ exposure_max =
+ mode->height + ctrl->val - S5K3L6_EXPOSURE_MARGIN;
+ __v4l2_ctrl_modify_range(s5k3l6->exposure,
+ S5K3L6_EXPOSURE_MIN, exposure_max, 1,
+ s5k3l6->exposure->default_value);
+ }
+
+ active = pm_runtime_get_if_active(s5k3l6->dev);
+ if (!active)
+ return 0;
+ if (active < 0)
+ return active;
+
+ switch (ctrl->id) {
+ case V4L2_CID_ANALOGUE_GAIN:
+ ret = cci_write(s5k3l6->regmap, S5K3L6_REG_ANALOG_GAIN,
+ ctrl->val, NULL);
+ break;
+ case V4L2_CID_DIGITAL_GAIN:
+ ret = cci_write(s5k3l6->regmap, S5K3L6_REG_DIGITAL_GAIN,
+ ctrl->val, NULL);
+ break;
+ case V4L2_CID_EXPOSURE:
+ ret = cci_write(s5k3l6->regmap, S5K3L6_REG_EXPOSURE,
+ ctrl->val, NULL);
+ break;
+ case V4L2_CID_VBLANK:
+ frame_length = mode->height + ctrl->val;
+ ret = cci_write(s5k3l6->regmap, S5K3L6_REG_FRAME_LENGTH,
+ frame_length, NULL);
+ break;
+ case V4L2_CID_TEST_PATTERN:
+ ret = cci_write(s5k3l6->regmap, S5K3L6_REG_TEST_PATTERN,
+ ctrl->val, NULL);
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+
+ pm_runtime_put(s5k3l6->dev);
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops s5k3l6_ctrl_ops = {
+ .s_ctrl = s5k3l6_set_ctrl,
+};
+
+static int s5k3l6_init_controls(struct s5k3l6 *s5k3l6)
+{
+ struct v4l2_ctrl_handler *ctrl_hdlr = &s5k3l6->ctrl_handler;
+ const struct v4l2_ctrl_ops *ops = &s5k3l6_ctrl_ops;
+ const struct s5k3l6_mode *mode = s5k3l6->mode;
+ struct v4l2_fwnode_device_properties props;
+ u32 hblank = mode->hts - mode->width;
+ u32 vblank = mode->vts - mode->height;
+ u32 exposure_max = mode->vts - S5K3L6_EXPOSURE_MARGIN;
+ u32 exposure_default = min_t(u32, 0x03de, exposure_max);
+ int ret;
+
+ v4l2_ctrl_handler_init(ctrl_hdlr, 10);
+
+ s5k3l6->link_freq =
+ v4l2_ctrl_new_int_menu(ctrl_hdlr, &s5k3l6_ctrl_ops,
+ V4L2_CID_LINK_FREQ,
+ ARRAY_SIZE(s5k3l6_link_freq_menu) - 1,
+ mode->link_freq_index,
+ s5k3l6_link_freq_menu);
+ if (s5k3l6->link_freq)
+ s5k3l6->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ s5k3l6->pixel_rate =
+ v4l2_ctrl_new_std(ctrl_hdlr, &s5k3l6_ctrl_ops,
+ V4L2_CID_PIXEL_RATE, S5K3L6_PIXEL_RATE,
+ S5K3L6_PIXEL_RATE, 1, S5K3L6_PIXEL_RATE);
+ if (s5k3l6->pixel_rate)
+ s5k3l6->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ s5k3l6->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &s5k3l6_ctrl_ops,
+ V4L2_CID_HBLANK, hblank, hblank, 1,
+ hblank);
+ if (s5k3l6->hblank)
+ s5k3l6->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ s5k3l6->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &s5k3l6_ctrl_ops,
+ V4L2_CID_VBLANK, vblank,
+ 0xffff - mode->height, 1, vblank);
+
+ v4l2_ctrl_new_std(ctrl_hdlr, &s5k3l6_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
+ S5K3L6_ANALOG_GAIN_MIN, S5K3L6_ANALOG_GAIN_MAX, 1,
+ S5K3L6_ANALOG_GAIN_DEFAULT);
+
+ v4l2_ctrl_new_std(ctrl_hdlr, &s5k3l6_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
+ S5K3L6_DIGITAL_GAIN_MIN, S5K3L6_DIGITAL_GAIN_MAX,
+ 1, S5K3L6_DIGITAL_GAIN_DEFAULT);
+
+ s5k3l6->exposure =
+ v4l2_ctrl_new_std(ctrl_hdlr, ops, V4L2_CID_EXPOSURE,
+ S5K3L6_EXPOSURE_MIN, exposure_max, 1,
+ exposure_default);
+
+ v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &s5k3l6_ctrl_ops,
+ V4L2_CID_TEST_PATTERN,
+ ARRAY_SIZE(s5k3l6_test_pattern_menu) - 1,
+ 0, 0, s5k3l6_test_pattern_menu);
+
+ if (ctrl_hdlr->error) {
+ ret = ctrl_hdlr->error;
+ goto error_free_hdlr;
+ }
+
+ ret = v4l2_fwnode_device_parse(s5k3l6->dev, &props);
+ if (ret)
+ goto error_free_hdlr;
+
+ ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &s5k3l6_ctrl_ops,
+ &props);
+ if (ret)
+ goto error_free_hdlr;
+
+ s5k3l6->sd.ctrl_handler = ctrl_hdlr;
+
+ return 0;
+
+error_free_hdlr:
+ v4l2_ctrl_handler_free(ctrl_hdlr);
+
+ return ret;
+}
+
+static int s5k3l6_write_mode(struct s5k3l6 *s5k3l6)
+{
+ const struct s5k3l6_mode *mode = s5k3l6->mode;
+ u64 link_freq = s5k3l6_link_freq_menu[mode->link_freq_index];
+ /*
+ * Match downstream integer-MHz programming. The 537.5 MHz mode uses
+ * 1074 here, not the rounded 1075 Mb/s DDR lane rate.
+ */
+ u16 link_rate = div_u64(link_freq, HZ_PER_MHZ) * 2;
+ u32 crop_width = mode->width * mode->binning;
+ u32 crop_height = mode->height * mode->binning;
+ u32 x_start = S5K3L6_ACTIVE_LEFT;
+ u32 y_start = S5K3L6_ACTIVE_TOP;
+ u32 x_end = x_start + crop_width - 1;
+ u32 y_end = y_start + crop_height - 1;
+ struct cci_reg_sequence crop_regs[] = {
+ { S5K3L6_REG_X_OUTPUT_SIZE, mode->width },
+ { S5K3L6_REG_Y_OUTPUT_SIZE, mode->height },
+ { S5K3L6_REG_Y_ADDR_START, y_start },
+ { S5K3L6_REG_Y_ADDR_END, y_end },
+ { S5K3L6_REG_X_ADDR_START, x_start },
+ { S5K3L6_REG_X_ADDR_END, x_end },
+ };
+ struct cci_reg_sequence format_regs[] = {
+ { S5K3L6_REG_DATA_FORMAT, mode->data_format },
+ { S5K3L6_REG_LANE_MODE, S5K3L6_DATA_LANES - 1 },
+ { S5K3L6_REG_OP_PLL_MULTIPLIER, mode->op_pll_multiplier },
+ { S5K3L6_REG_REQUESTED_LINK_RATE, link_rate },
+ { S5K3L6_REG_LINE_LENGTH, mode->hts },
+ };
+ int ret = 0;
+
+ cci_multi_reg_write(s5k3l6->regmap, crop_regs, ARRAY_SIZE(crop_regs),
+ &ret);
+ cci_multi_reg_write(s5k3l6->regmap, mode->reg_list.regs,
+ mode->reg_list.num_regs, &ret);
+ cci_multi_reg_write(s5k3l6->regmap, s5k3l6_common_regs,
+ ARRAY_SIZE(s5k3l6_common_regs), &ret);
+ cci_multi_reg_write(s5k3l6->regmap, format_regs,
+ ARRAY_SIZE(format_regs), &ret);
+
+ return ret;
+}
+
+static int s5k3l6_enable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
+{
+ struct s5k3l6 *s5k3l6 = to_s5k3l6(sd);
+ int ret;
+
+ ret = pm_runtime_resume_and_get(s5k3l6->dev);
+ if (ret)
+ return ret;
+
+ cci_write(s5k3l6->regmap, S5K3L6_REG_PLL_PD, 0x01, &ret);
+ if (ret)
+ goto error;
+
+ ret = s5k3l6_write_mode(s5k3l6);
+ if (ret)
+ goto error;
+
+ ret = __v4l2_ctrl_handler_setup(s5k3l6->sd.ctrl_handler);
+ if (ret)
+ goto error;
+
+ cci_write(s5k3l6->regmap, S5K3L6_REG_MODE_SELECT,
+ S5K3L6_MODE_STREAMING, &ret);
+ cci_write(s5k3l6->regmap, S5K3L6_REG_PLL_PD, 0x00, &ret);
+ if (ret)
+ goto error;
+
+ return 0;
+
+error:
+ dev_err(s5k3l6->dev, "failed to start streaming: %d\n", ret);
+ pm_runtime_put_autosuspend(s5k3l6->dev);
+
+ return ret;
+}
+
+static int s5k3l6_disable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
+{
+ struct s5k3l6 *s5k3l6 = to_s5k3l6(sd);
+ int ret;
+
+ ret = cci_write(s5k3l6->regmap, S5K3L6_REG_MODE_SELECT,
+ S5K3L6_MODE_STANDBY, NULL);
+ if (ret)
+ dev_err(s5k3l6->dev, "failed to stop streaming: %d\n", ret);
+
+ pm_runtime_put_autosuspend(s5k3l6->dev);
+
+ return ret;
+}
+
+static int s5k3l6_set_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct s5k3l6 *s5k3l6 = to_s5k3l6(sd);
+ const struct s5k3l6_mode *mode;
+
+ mode = s5k3l6_find_mode(fmt->format.code, fmt->format.width,
+ fmt->format.height);
+ s5k3l6_update_pad_format(mode, &fmt->format);
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE && s5k3l6->mode != mode) {
+ s5k3l6->mode = mode;
+ s5k3l6_update_controls(s5k3l6, mode);
+ }
+
+ *v4l2_subdev_state_get_format(state, 0) = fmt->format;
+
+ return 0;
+}
+
+static int s5k3l6_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ static const u32 codes[] = {
+ MEDIA_BUS_FMT_SGRBG8_1X8,
+ MEDIA_BUS_FMT_SGRBG10_1X10,
+ };
+
+ if (code->index >= ARRAY_SIZE(codes))
+ return -EINVAL;
+
+ code->code = codes[code->index];
+
+ return 0;
+}
+
+static int s5k3l6_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ unsigned int index = 0;
+ unsigned int i;
+
+ if (!s5k3l6_code_supported(fse->code))
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(s5k3l6_supported_modes); i++) {
+ const struct s5k3l6_mode *mode = &s5k3l6_supported_modes[i];
+
+ if (mode->code != fse->code)
+ continue;
+
+ if (index++ != fse->index)
+ continue;
+
+ fse->min_width = mode->width;
+ fse->max_width = mode->width;
+ fse->min_height = mode->height;
+ fse->max_height = mode->height;
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int s5k3l6_get_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_selection *sel)
+{
+ switch (sel->target) {
+ case V4L2_SEL_TGT_NATIVE_SIZE:
+ sel->r.left = 0;
+ sel->r.top = 0;
+ sel->r.width = S5K3L6_PIXEL_ARRAY_WIDTH;
+ sel->r.height = S5K3L6_PIXEL_ARRAY_HEIGHT;
+ return 0;
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ case V4L2_SEL_TGT_CROP:
+ sel->r.left = S5K3L6_ACTIVE_LEFT;
+ sel->r.top = S5K3L6_ACTIVE_TOP;
+ sel->r.width = S5K3L6_ACTIVE_WIDTH;
+ sel->r.height = S5K3L6_ACTIVE_HEIGHT;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int s5k3l6_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
+ struct v4l2_mbus_config *config)
+{
+ struct s5k3l6 *s5k3l6 = to_s5k3l6(sd);
+ const struct s5k3l6_mode *mode = s5k3l6->mode;
+
+ if (pad)
+ return -EINVAL;
+
+ *config = (struct v4l2_mbus_config) {
+ .type = V4L2_MBUS_CSI2_DPHY,
+ .link_freq = s5k3l6_link_freq_menu[mode->link_freq_index],
+ };
+ config->bus.mipi_csi2.num_data_lanes = S5K3L6_DATA_LANES;
+
+ return 0;
+}
+
+static int s5k3l6_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
+{
+ struct s5k3l6 *s5k3l6 = to_s5k3l6(sd);
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ .pad = 0,
+ .format = {
+ .code = s5k3l6->mode->code,
+ .width = s5k3l6->mode->width,
+ .height = s5k3l6->mode->height,
+ },
+ };
+
+ s5k3l6_set_pad_format(sd, state, &fmt);
+
+ return 0;
+}
+
+static const struct v4l2_subdev_video_ops s5k3l6_video_ops = {
+ .s_stream = v4l2_subdev_s_stream_helper,
+};
+
+static const struct v4l2_subdev_pad_ops s5k3l6_pad_ops = {
+ .set_fmt = s5k3l6_set_pad_format,
+ .get_fmt = v4l2_subdev_get_fmt,
+ .get_selection = s5k3l6_get_selection,
+ .get_mbus_config = s5k3l6_get_mbus_config,
+ .enum_mbus_code = s5k3l6_enum_mbus_code,
+ .enum_frame_size = s5k3l6_enum_frame_size,
+ .enable_streams = s5k3l6_enable_streams,
+ .disable_streams = s5k3l6_disable_streams,
+};
+
+static const struct v4l2_subdev_ops s5k3l6_subdev_ops = {
+ .video = &s5k3l6_video_ops,
+ .pad = &s5k3l6_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops s5k3l6_internal_ops = {
+ .init_state = s5k3l6_init_state,
+};
+
+static const struct media_entity_operations s5k3l6_entity_ops = {
+ .link_validate = v4l2_subdev_link_validate,
+};
+
+static int s5k3l6_identify_sensor(struct s5k3l6 *s5k3l6)
+{
+ u64 val;
+ int ret;
+
+ ret = cci_read(s5k3l6->regmap, S5K3L6_REG_CHIP_ID, &val, NULL);
+ if (ret)
+ return dev_err_probe(s5k3l6->dev, ret,
+ "failed to read chip id\n");
+
+ if (val != S5K3L6_CHIP_ID)
+ return dev_err_probe(s5k3l6->dev, -ENODEV,
+ "chip id mismatch: %x != %llx\n",
+ S5K3L6_CHIP_ID, val);
+
+ ret = cci_read(s5k3l6->regmap, S5K3L6_REG_REVISION, &val, NULL);
+ if (ret)
+ return dev_err_probe(s5k3l6->dev, ret,
+ "failed to read revision\n");
+
+ if (val != S5K3L6_REVISION)
+ return dev_err_probe(s5k3l6->dev, -ENODEV,
+ "revision mismatch: %x != %llx\n",
+ S5K3L6_REVISION, val);
+
+ return 0;
+}
+
+static int s5k3l6_check_hwcfg(struct s5k3l6 *s5k3l6)
+{
+ struct fwnode_handle *fwnode = dev_fwnode(s5k3l6->dev);
+ struct v4l2_fwnode_endpoint bus_cfg = {
+ .bus = {
+ .mipi_csi2 = {
+ .num_data_lanes = S5K3L6_DATA_LANES,
+ },
+ },
+ .bus_type = V4L2_MBUS_CSI2_DPHY,
+ };
+ struct fwnode_handle *ep;
+ unsigned long freq_bitmap;
+ unsigned long expected_bitmap;
+ int ret;
+
+ if (!fwnode)
+ return -ENODEV;
+
+ ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
+ if (!ep)
+ return -EINVAL;
+
+ ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
+ fwnode_handle_put(ep);
+ if (ret)
+ return ret;
+
+ if (bus_cfg.bus.mipi_csi2.num_data_lanes != S5K3L6_DATA_LANES) {
+ dev_err(s5k3l6->dev, "only %u data lanes are supported\n",
+ S5K3L6_DATA_LANES);
+ ret = -EINVAL;
+ goto endpoint_free;
+ }
+
+ ret = v4l2_link_freq_to_bitmap(s5k3l6->dev, bus_cfg.link_frequencies,
+ bus_cfg.nr_of_link_frequencies,
+ s5k3l6_link_freq_menu,
+ ARRAY_SIZE(s5k3l6_link_freq_menu),
+ &freq_bitmap);
+ if (ret)
+ goto endpoint_free;
+
+ expected_bitmap = GENMASK(ARRAY_SIZE(s5k3l6_link_freq_menu) - 1, 0);
+ if (freq_bitmap != expected_bitmap) {
+ dev_err(s5k3l6->dev, "not all link frequencies are listed\n");
+ ret = -EINVAL;
+ }
+
+endpoint_free:
+ v4l2_fwnode_endpoint_free(&bus_cfg);
+
+ return ret;
+}
+
+static int s5k3l6_power_on(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct s5k3l6 *s5k3l6 = to_s5k3l6(sd);
+ int ret;
+
+ ret = regulator_bulk_enable(S5K3L6_NUM_SUPPLIES, s5k3l6->supplies);
+ if (ret)
+ return ret;
+
+ usleep_range(10, 20);
+
+ ret = clk_prepare_enable(s5k3l6->mclk);
+ if (ret)
+ goto disable_regulators;
+
+ gpiod_set_value_cansleep(s5k3l6->reset_gpio, 0);
+ usleep_range(USEC_PER_MSEC, 1200);
+
+ gpiod_set_value_cansleep(s5k3l6->reset_gpio, 1);
+ usleep_range(400, 800);
+ gpiod_set_value_cansleep(s5k3l6->reset_gpio, 0);
+
+ usleep_range(10 * USEC_PER_MSEC, 11 * USEC_PER_MSEC);
+
+ return 0;
+
+disable_regulators:
+ regulator_bulk_disable(S5K3L6_NUM_SUPPLIES, s5k3l6->supplies);
+
+ return ret;
+}
+
+static int s5k3l6_power_off(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct s5k3l6 *s5k3l6 = to_s5k3l6(sd);
+
+ gpiod_set_value_cansleep(s5k3l6->reset_gpio, 1);
+ clk_disable_unprepare(s5k3l6->mclk);
+
+ return regulator_bulk_disable(S5K3L6_NUM_SUPPLIES,
+ s5k3l6->supplies);
+}
+
+static int s5k3l6_probe(struct i2c_client *client)
+{
+ struct s5k3l6 *s5k3l6;
+ unsigned long freq;
+ unsigned int i;
+ int ret;
+
+ s5k3l6 = devm_kzalloc(&client->dev, sizeof(*s5k3l6), GFP_KERNEL);
+ if (!s5k3l6)
+ return -ENOMEM;
+
+ s5k3l6->dev = &client->dev;
+ v4l2_i2c_subdev_init(&s5k3l6->sd, client, &s5k3l6_subdev_ops);
+
+ s5k3l6->regmap = devm_cci_regmap_init_i2c(client, 16);
+ if (IS_ERR(s5k3l6->regmap))
+ return dev_err_probe(s5k3l6->dev, PTR_ERR(s5k3l6->regmap),
+ "failed to init CCI\n");
+
+ s5k3l6->mclk = devm_v4l2_sensor_clk_get(s5k3l6->dev, NULL);
+ if (IS_ERR(s5k3l6->mclk))
+ return dev_err_probe(s5k3l6->dev, PTR_ERR(s5k3l6->mclk),
+ "failed to get clock\n");
+
+ freq = clk_get_rate(s5k3l6->mclk);
+ if (freq != S5K3L6_MCLK_FREQ)
+ return dev_err_probe(s5k3l6->dev, -EINVAL,
+ "clock frequency %lu is not supported\n",
+ freq);
+
+ ret = s5k3l6_check_hwcfg(s5k3l6);
+ if (ret)
+ return dev_err_probe(s5k3l6->dev, ret,
+ "failed to check HW configuration\n");
+
+ s5k3l6->reset_gpio =
+ devm_gpiod_get_optional(s5k3l6->dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(s5k3l6->reset_gpio))
+ return dev_err_probe(s5k3l6->dev,
+ PTR_ERR(s5k3l6->reset_gpio),
+ "failed to get reset GPIO\n");
+
+ for (i = 0; i < S5K3L6_NUM_SUPPLIES; i++)
+ s5k3l6->supplies[i].supply = s5k3l6_supply_names[i];
+
+ ret = devm_regulator_bulk_get(s5k3l6->dev, S5K3L6_NUM_SUPPLIES,
+ s5k3l6->supplies);
+ if (ret)
+ return dev_err_probe(s5k3l6->dev, ret,
+ "failed to get supplies\n");
+
+ ret = s5k3l6_power_on(s5k3l6->dev);
+ if (ret)
+ return ret;
+
+ ret = s5k3l6_identify_sensor(s5k3l6);
+ if (ret)
+ goto power_off;
+
+ s5k3l6->mode = &s5k3l6_supported_modes[0];
+ ret = s5k3l6_init_controls(s5k3l6);
+ if (ret)
+ goto power_off;
+
+ s5k3l6->sd.state_lock = s5k3l6->ctrl_handler.lock;
+ s5k3l6->sd.internal_ops = &s5k3l6_internal_ops;
+ s5k3l6->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ s5k3l6->sd.entity.ops = &s5k3l6_entity_ops;
+ s5k3l6->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+ s5k3l6->pad.flags = MEDIA_PAD_FL_SOURCE;
+
+ ret = media_entity_pads_init(&s5k3l6->sd.entity, 1, &s5k3l6->pad);
+ if (ret)
+ goto free_ctrls;
+
+ ret = v4l2_subdev_init_finalize(&s5k3l6->sd);
+ if (ret)
+ goto cleanup_entity;
+
+ pm_runtime_set_active(s5k3l6->dev);
+ pm_runtime_enable(s5k3l6->dev);
+
+ ret = v4l2_async_register_subdev_sensor(&s5k3l6->sd);
+ if (ret)
+ goto cleanup_subdev;
+
+ pm_runtime_set_autosuspend_delay(s5k3l6->dev, 1000);
+ pm_runtime_use_autosuspend(s5k3l6->dev);
+ pm_runtime_idle(s5k3l6->dev);
+
+ return 0;
+
+cleanup_subdev:
+ v4l2_subdev_cleanup(&s5k3l6->sd);
+ pm_runtime_disable(s5k3l6->dev);
+ pm_runtime_set_suspended(s5k3l6->dev);
+
+cleanup_entity:
+ media_entity_cleanup(&s5k3l6->sd.entity);
+
+free_ctrls:
+ v4l2_ctrl_handler_free(s5k3l6->sd.ctrl_handler);
+
+power_off:
+ s5k3l6_power_off(s5k3l6->dev);
+
+ return ret;
+}
+
+static void s5k3l6_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct s5k3l6 *s5k3l6 = to_s5k3l6(sd);
+
+ v4l2_async_unregister_subdev(sd);
+ v4l2_subdev_cleanup(sd);
+ media_entity_cleanup(&sd->entity);
+ v4l2_ctrl_handler_free(sd->ctrl_handler);
+ pm_runtime_disable(s5k3l6->dev);
+
+ if (!pm_runtime_status_suspended(s5k3l6->dev)) {
+ s5k3l6_power_off(s5k3l6->dev);
+ pm_runtime_set_suspended(s5k3l6->dev);
+ }
+}
+
+static const struct dev_pm_ops s5k3l6_pm_ops = {
+ SET_RUNTIME_PM_OPS(s5k3l6_power_off, s5k3l6_power_on, NULL)
+};
+
+static const struct of_device_id s5k3l6_of_match[] = {
+ { .compatible = "samsung,s5k3l6" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, s5k3l6_of_match);
+
+static struct i2c_driver s5k3l6_i2c_driver = {
+ .driver = {
+ .name = "s5k3l6",
+ .pm = &s5k3l6_pm_ops,
+ .of_match_table = s5k3l6_of_match,
+ },
+ .probe = s5k3l6_probe,
+ .remove = s5k3l6_remove,
+};
+
+module_i2c_driver(s5k3l6_i2c_driver);
+
+MODULE_DESCRIPTION("Samsung S5K3L6 image sensor driver");
+MODULE_LICENSE("GPL");
--
2.53.0
^ permalink raw reply related
* [PATCH RFC 4/4] arm64: dts: imx8mq-librem5: Add rear camera
From: Vincent Cloutier @ 2026-06-26 0:07 UTC (permalink / raw)
To: linux-media, devicetree, linux-arm-kernel
Cc: linux-kernel, linux-imx, kernel, Vincent Cloutier, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, imx
In-Reply-To: <20260626000715.1111803-1-vincent.cloutier@icloud.com>
From: Vincent Cloutier <vincent@cloutier.co>
Add the Librem 5 rear camera sensor node and enable the second CSI-2
capture path that receives data from it.
Describe the Samsung S5K3L6 sensor with the upstream binding property
names, including reset-gpios and the link frequencies used by the initial
two-lane RAW8/RAW10 driver modes.
Signed-off-by: Vincent Cloutier <vincent@cloutier.co>
Assisted-by: OpenCode:gpt-5.5
---
arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi | 51 +++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
index f5d529c5baf3..12d5fb3440c5 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
@@ -318,6 +318,10 @@ &csi1 {
status = "okay";
};
+&csi2 {
+ status = "okay";
+};
+
&ddrc {
operating-points-v2 = <&ddrc_opp_table>;
status = "okay";
@@ -434,6 +438,13 @@ MX8MQ_IOMUXC_ENET_RXC_GPIO1_IO25 0x83
>;
};
+ pinctrl_csi2: csi2grp {
+ fsl,pins = <
+ /* CSI2_NRST */
+ MX8MQ_IOMUXC_ENET_RD0_GPIO1_IO26 0x83
+ >;
+ };
+
pinctrl_charger_in: chargeringrp {
fsl,pins = <
/* CHRG_INT */
@@ -1175,6 +1186,31 @@ vcm@c {
vcc-supply = <®_csi_1v8>;
};
+ camera_rear: camera@2d {
+ compatible = "samsung,s5k3l6";
+ reg = <0x2d>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_csi2>;
+ clocks = <&clk IMX8MQ_CLK_CLKO2>;
+ assigned-clocks = <&clk IMX8MQ_CLK_CLKO2>;
+ assigned-clock-rates = <25000000>;
+ reset-gpios = <&gpio1 26 GPIO_ACTIVE_LOW>;
+ vdda-supply = <®_vcam_2v8>;
+ vddd-supply = <®_vcam_1v2>;
+ vddio-supply = <®_csi_1v8>;
+ rotation = <270>;
+ orientation = <1>;
+
+ port {
+ camera2_ep: endpoint {
+ data-lanes = <1 2>;
+ link-frequencies = /bits/ 64
+ <537500000 600000000 625000000>;
+ remote-endpoint = <&mipi2_sensor_ep>;
+ };
+ };
+ };
+
bat: fuel-gauge@36 {
compatible = "maxim,max17055";
reg = <0x36>;
@@ -1226,6 +1262,21 @@ mipi1_sensor_ep: endpoint {
};
};
+&mipi_csi2 {
+ status = "okay";
+
+ ports {
+ port@0 {
+ reg = <0>;
+
+ mipi2_sensor_ep: endpoint {
+ remote-endpoint = <&camera2_ep>;
+ data-lanes = <1 2>;
+ };
+ };
+ };
+};
+
&mipi_dsi {
#address-cells = <1>;
#size-cells = <0>;
--
2.53.0
^ permalink raw reply related
* [PATCH RFC 2/4] dt-bindings: media: i2c: Add Samsung S5K3L6 image sensor
From: Vincent Cloutier @ 2026-06-26 0:06 UTC (permalink / raw)
To: linux-media, devicetree, linux-arm-kernel
Cc: linux-kernel, linux-imx, kernel, Vincent Cloutier,
Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
In-Reply-To: <20260626000715.1111803-1-vincent.cloutier@icloud.com>
From: Vincent Cloutier <vincent@cloutier.co>
Add a devicetree binding for the Samsung S5K3L6 13MP raw Bayer image
sensor.
This starts the upstreaming work for the Librem 5 rear camera path. The
binding describes the validated two-lane MIPI CSI-2 configuration.
Signed-off-by: Vincent Cloutier <vincent@cloutier.co>
Assisted-by: OpenCode:gpt-5.5
---
.../bindings/media/i2c/samsung,s5k3l6.yaml | 117 +++++++++++++++++++++
1 file changed, 117 insertions(+)
diff --git a/Documentation/devicetree/bindings/media/i2c/samsung,s5k3l6.yaml b/Documentation/devicetree/bindings/media/i2c/samsung,s5k3l6.yaml
new file mode 100644
index 000000000000..96150764b341
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/samsung,s5k3l6.yaml
@@ -0,0 +1,117 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/samsung,s5k3l6.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung S5K3L6 13MP MIPI CSI-2 image sensor
+
+maintainers:
+ - Vincent Cloutier <vincent@cloutier.co>
+ - Purism Kernel Team <kernel@puri.sm>
+
+description: |-
+ The Samsung S5K3L6 is a raw Bayer image sensor with a MIPI CSI-2 image
+ data interface and an I2C-compatible control bus.
+
+allOf:
+ - $ref: /schemas/media/video-interface-devices.yaml#
+
+properties:
+ compatible:
+ const: samsung,s5k3l6
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ description: Reference to the sensor input clock.
+ maxItems: 1
+
+ reset-gpios:
+ description: Active-low reset GPIO.
+ maxItems: 1
+
+ vdda-supply:
+ description: Analog power supply.
+
+ vddd-supply:
+ description: Digital core power supply.
+
+ vddio-supply:
+ description: Digital I/O power supply.
+
+ port:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ items:
+ - const: 1
+ - const: 2
+
+ link-frequencies:
+ minItems: 3
+ maxItems: 3
+ items:
+ - const: 537500000
+ - const: 600000000
+ - const: 625000000
+
+ required:
+ - data-lanes
+ - link-frequencies
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - vdda-supply
+ - vddd-supply
+ - vddio-supply
+ - port
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/imx8mq-clock.h>
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ camera@2d {
+ compatible = "samsung,s5k3l6";
+ reg = <0x2d>;
+
+ clocks = <&clk IMX8MQ_CLK_CLKO2>;
+ assigned-clocks = <&clk IMX8MQ_CLK_CLKO2>;
+ assigned-clock-rates = <25000000>;
+
+ reset-gpios = <&gpio1 26 GPIO_ACTIVE_LOW>;
+ vdda-supply = <®_camera_vdda>;
+ vddd-supply = <®_camera_vddd>;
+ vddio-supply = <®_camera_vddio>;
+
+ orientation = <1>;
+ rotation = <270>;
+
+ port {
+ camera_out: endpoint {
+ data-lanes = <1 2>;
+ link-frequencies = /bits/ 64
+ <537500000 600000000 625000000>;
+ remote-endpoint = <&mipi_csi2_in>;
+ };
+ };
+ };
+ };
+...
--
2.53.0
^ permalink raw reply related
* [PATCH RFC 1/4] media: imx8mq-mipi-csi2: Make reset release SoC-specific
From: Vincent Cloutier @ 2026-06-26 0:06 UTC (permalink / raw)
To: linux-media, devicetree, linux-arm-kernel
Cc: linux-kernel, linux-imx, kernel, Vincent Cloutier,
Laurent Pinchart, Frank Li, Martin Kepplinger-Novakovic,
Rui Miguel Silva, Mauro Carvalho Chehab, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Philipp Zabel, imx
In-Reply-To: <20260626000715.1111803-1-vincent.cloutier@icloud.com>
From: Vincent Cloutier <vincent@cloutier.co>
The CSI-2 software reset helper currently asserts the reset control and
then releases it again unconditionally.
That release step is required by the i.MX8QXP path, but it changes the
reset sequence used by i.MX8MQ. On Librem 5r4, which is i.MX8MQ-based,
the unconditional release step prevents the camera pipeline from producing
frames after reset; captures time out waiting for EOF from the CSI bridge.
This series enables the Librem 5 rear camera on the second i.MX8MQ CSI-2
receiver. Keep the i.MX8MQ path on the known-working assert-only software
reset sequence while preserving the explicit release step for i.MX8QXP.
Make reset release opt-in through platform data.
Tested on Librem 5r4 with the existing HI846 front camera and the S5K3L6
rear camera added by this series.
Signed-off-by: Vincent Cloutier <vincent@cloutier.co>
Assisted-by: OpenCode:gpt-5.5
---
drivers/media/platform/nxp/imx8mq-mipi-csi2.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/media/platform/nxp/imx8mq-mipi-csi2.c b/drivers/media/platform/nxp/imx8mq-mipi-csi2.c
index 950793297496..xxxxxxxxxxxx 100644
--- a/drivers/media/platform/nxp/imx8mq-mipi-csi2.c
+++ b/drivers/media/platform/nxp/imx8mq-mipi-csi2.c
@@ -76,6 +76,7 @@ struct imx8mq_plat_data {
int (*enable)(struct csi_state *state, u32 hs_settle);
void (*disable)(struct csi_state *state);
bool use_reg_csr;
+ bool needs_reset_deassert;
};
/*
@@ -244,6 +245,7 @@ static const struct imx8mq_plat_data imx8qxp_data = {
.enable = imx8qxp_gpr_enable,
.disable = imx8qxp_gpr_disable,
.use_reg_csr = true,
+ .needs_reset_deassert = true,
};
static const struct csi2_pix_format imx8mq_mipi_csi_formats[] = {
@@ -363,8 +365,12 @@ static int imx8mq_mipi_csi_sw_reset(struct csi_state *state)
return ret;
}
- /* Explicitly release reset to make sure reset bits are cleared. */
- return reset_control_deassert(state->rst);
+ /*
+ * Some SoC integrations require an explicit release after reset
+ * assertion. Keep this SoC-specific so i.MX8MQ retains its
+ * known-working assert-only sequence.
+ */
+ if (!state->pdata->needs_reset_deassert)
+ return 0;
+
+ return reset_control_deassert(state->rst);
}
static void imx8mq_mipi_csi_set_params(struct csi_state *state)
--
2.53.0
^ permalink raw reply
* [PATCH RFC 0/4] media: i2c: Add Samsung S5K3L6 and Librem 5 rear camera
From: Vincent Cloutier @ 2026-06-26 0:06 UTC (permalink / raw)
To: linux-media, devicetree, linux-arm-kernel
Cc: linux-kernel, linux-imx, kernel, Vincent Cloutier
From: Vincent Cloutier <vincent@cloutier.co>
This RFC fixes the i.MX8MQ CSI-2 reset path needed by Librem 5 camera
capture, adds initial upstream support for the Samsung S5K3L6 image
sensor, and wires it up as the rear camera on the Purism Librem 5.
This is intentionally a rewrite, not a direct forwarding of the Librem 5
downstream S5K3L6 carry. The downstream history is a long bring-up
series with debugfs register overrides, debug-frame plumbing, commented-out
old subdev code, FIXME/TODO scaffolding, and several API-era migrations.
This RFC collapses the usable production path into a current V4L2 sensor
driver using CCI regmap, runtime PM, fwnode endpoint validation, and the
current subdev stream API.
Many thanks to Martin Kepplinger, Dorota Czaplejewicz, and Sebastian
Krzyszkowiak for the original Librem 5 S5K3L6 driver work and rear-camera
bring-up. Martin authored the initial downstream driver, and Dorota and
Sebastian substantially developed the mode tables, controls, power-up
sequence, and sensor tuning that this rewrite is based on.
This series covers:
- 25 MHz input clock, matching the Librem 5 downstream configuration
- two MIPI CSI-2 data lanes
- RAW8 and RAW10 SGRBG modes at 1052x780, 2104x1560, and 4208x3120
- exposure, analogue gain, digital gain, blanking, pixel-rate,
link-frequency, test-pattern, orientation, and rotation controls
- Librem 5 DTS integration for the rear sensor and second CSI-2 path
The rewritten driver and DTS path have now been tested on Librem 5r4
hardware in a v7.1.1 carry build, with the i.MX8MQ CSI-2 reset fix from this
series applied.
Patch 1 keeps the i.MX8MQ CSI-2 software reset sequence compatible with
the Librem 5 camera pipeline by making the post-assert reset release
SoC-specific. This is included as an RFC prerequisite for the Librem 5
rear-camera enablement; if preferred, it can be split out and handled as
a separate media/platform fix.
Vincent Cloutier (4):
media: imx8mq-mipi-csi2: Keep i.MX8MQ reset assert-only
dt-bindings: media: i2c: Add Samsung S5K3L6 image sensor
media: i2c: Add Samsung S5K3L6 image sensor driver
arm64: dts: imx8mq-librem5: Add rear camera
.../bindings/media/i2c/samsung,s5k3l6.yaml | 117 ++
arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi | 51 +
drivers/media/i2c/Kconfig | 10 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/s5k3l6.c | 1055 +++++++++++++++++
drivers/media/platform/nxp/imx8mq-mipi-csi2.c | 9 +-
6 files changed, 1241 insertions(+), 2 deletions(-)
--
2.53.0
^ permalink raw reply
* Re: [PATCH v4 2/2] tracing: Remove trace_printk.h from kernel.h
From: Nathan Chancellor @ 2026-06-25 23:41 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-kernel, linux-trace-kernel, Masami Hiramatsu, Mark Rutland,
Mathieu Desnoyers, Andrew Morton, Linus Torvalds,
Sebastian Andrzej Siewior, John Ogness, Thomas Gleixner,
Peter Zijlstra, Julia Lawall, Yury Norov, linux-doc, linux-kbuild,
linuxppc-dev, dri-devel, linux-stm32, linux-arm-kernel,
linux-rdma, linux-usb, linux-ext4, linux-nfs, kvm, intel-gfx
In-Reply-To: <20260625104402.210473477@kernel.org>
Hi Steve,
On Thu, Jun 25, 2026 at 06:40:09AM -0400, Steven Rostedt wrote:
> From: Steven Rostedt <rostedt@goodmis.org>
>
> There have been complaints about trace_printk.h causing more build time
> for being in kernel.h if it changes. There is also an effort to clean up
> kernel.h to have it not include unneeded header files. Move trace_printk.h
> out of kernel.h and place it in the headers and C files that use it.
>
> Link: https://lore.kernel.org/all/CAHk-=wikCBeVFjVXiY4o-oepdbjAoir5+TcAgtL12c4u1TpZLQ@mail.gmail.com/
>
> Suggested-by: Yury Norov <yury.norov@gmail.com>
> Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This patch breaks lib/test_context-analysis.c for me in several
configurations:
In file included from lib/test_context-analysis.c:9:
In file included from include/linux/local_lock.h:5:
include/linux/local_lock_internal.h:46:2: error: use of undeclared identifier '_THIS_IP_'
46 | lock_map_acquire(&l->dep_map);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/lockdep.h:541:69: note: expanded from macro 'lock_map_acquire'
541 | #define lock_map_acquire(l) lock_acquire_exclusive(l, 0, 0, NULL, _THIS_IP_)
| ^~~~~~~~~
In file included from lib/test_context-analysis.c:9:
In file included from include/linux/local_lock.h:5:
include/linux/local_lock_internal.h:53:2: error: use of undeclared identifier '_THIS_IP_'
53 | lock_map_acquire_try(&l->dep_map);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/lockdep.h:542:73: note: expanded from macro 'lock_map_acquire_try'
542 | #define lock_map_acquire_try(l) lock_acquire_exclusive(l, 0, 1, NULL, _THIS_IP_)
| ^~~~~~~~~
In file included from lib/test_context-analysis.c:9:
In file included from include/linux/local_lock.h:5:
include/linux/local_lock_internal.h:62:2: error: use of undeclared identifier '_THIS_IP_'
62 | lock_map_release(&l->dep_map);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/lockdep.h:545:47: note: expanded from macro 'lock_map_release'
545 | #define lock_map_release(l) lock_release(l, _THIS_IP_)
| ^~~~~~~~~
3 errors generated.
The following diff resolves it for me, should I send it as a separate
patch or do you want to just fold it in with a note?
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 621566345406..2301a701ffbb 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -10,6 +10,7 @@
#ifndef __LINUX_LOCKDEP_H
#define __LINUX_LOCKDEP_H
+#include <linux/instruction_pointer.h>
#include <linux/lockdep_types.h>
#include <linux/smp.h>
#include <asm/percpu.h>
--
Cheers,
Nathan
^ permalink raw reply related
* Re: [PATCH net] net: airoha: dma map xmit frags with skb_frag_dma_map()
From: Harshitha Ramamurthy @ 2026-06-25 22:59 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, linux-arm-kernel, linux-mediatek, netdev
In-Reply-To: <20260625-airoha-eth-skb_frag_dma_map-v1-1-31d9e460aae6@kernel.org>
On Thu, Jun 25, 2026 at 2:43 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
>
> Map xmit skb fragments using skb_frag_dma_map() instead of
> dma_map_single(skb_frag_address()). skb_frag_address() relies on
> page_address() to obtain a kernel virtual address, which is not
> guaranteed to work for all page types (e.g. highmem pages or
> user-pinned pages from MSG_ZEROCOPY).
> skb_frag_dma_map() maps the fragment directly via its struct page and
> offset through dma_map_page(), avoiding the need for a kernel virtual
> address entirely.
> Introduce an enum airoha_dma_map_type to track how each queue entry was
> mapped (single vs page), so that the matching unmap function is called
> on completion and in error paths.
>
> Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: Harshitha Ramamurthy <hramamurthy@google.com>
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 61 ++++++++++++++++++++------------
> drivers/net/ethernet/airoha/airoha_eth.h | 7 ++++
> 2 files changed, 45 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 932b3a3df2e5..1caf6766f2c0 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -944,6 +944,25 @@ static void airoha_qdma_wake_netdev_txqs(struct airoha_queue *q)
> q->txq_stopped = false;
> }
>
> +static void airoha_unmap_xmit_buf(struct airoha_eth *eth,
> + struct airoha_queue_entry *e)
> +{
> + switch (e->dma_type) {
> + case AIROHA_DMA_MAP_PAGE:
> + dma_unmap_page(eth->dev, e->dma_addr, e->dma_len,
> + DMA_TO_DEVICE);
> + break;
> + case AIROHA_DMA_MAP_SINGLE:
> + dma_unmap_single(eth->dev, e->dma_addr, e->dma_len,
> + DMA_TO_DEVICE);
> + break;
> + case AIROHA_DMA_UNMAPPED:
> + default:
> + break;
> + }
> + e->dma_type = AIROHA_DMA_UNMAPPED;
> +}
> +
> static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget)
> {
> struct airoha_tx_irq_queue *irq_q;
> @@ -1006,9 +1025,7 @@ static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget)
> skb = e->skb;
> e->skb = NULL;
>
> - dma_unmap_single(eth->dev, e->dma_addr, e->dma_len,
> - DMA_TO_DEVICE);
> - e->dma_addr = 0;
> + airoha_unmap_xmit_buf(eth, e);
> list_add_tail(&e->list, &q->tx_list);
>
> WRITE_ONCE(desc->msg0, 0);
> @@ -1177,12 +1194,10 @@ static void airoha_qdma_tx_cleanup(struct airoha_qdma *qdma)
> struct airoha_qdma_desc *desc = &q->desc[j];
> struct sk_buff *skb = e->skb;
>
> - if (!e->dma_addr)
> + if (e->dma_type == AIROHA_DMA_UNMAPPED)
> continue;
>
> - dma_unmap_single(qdma->eth->dev, e->dma_addr,
> - e->dma_len, DMA_TO_DEVICE);
> - e->dma_addr = 0;
> + airoha_unmap_xmit_buf(qdma->eth, e);
> list_add_tail(&e->list, &q->tx_list);
>
> WRITE_ONCE(desc->ctrl, 0);
> @@ -2193,8 +2208,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> struct netdev_queue *txq;
> struct airoha_queue *q;
> LIST_HEAD(tx_list);
> + dma_addr_t addr;
> int i = 0, qid;
> - void *data;
> u16 index;
> u8 fport;
>
> @@ -2250,24 +2265,22 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> return NETDEV_TX_BUSY;
> }
>
> - len = skb_headlen(skb);
> - data = skb->data;
> -
> e = list_first_entry(&q->tx_list, struct airoha_queue_entry,
> list);
> + len = skb_headlen(skb);
> + addr = dma_map_single(netdev->dev.parent, skb->data, len,
> + DMA_TO_DEVICE);
> + if (unlikely(dma_mapping_error(netdev->dev.parent, addr)))
> + goto error_unlock;
> +
> + e->dma_type = AIROHA_DMA_MAP_SINGLE;
> index = e - q->entry;
>
> while (true) {
> struct airoha_qdma_desc *desc = &q->desc[index];
> skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
> - dma_addr_t addr;
> u32 val;
>
> - addr = dma_map_single(netdev->dev.parent, data, len,
> - DMA_TO_DEVICE);
> - if (unlikely(dma_mapping_error(netdev->dev.parent, addr)))
> - goto error_unmap;
> -
> list_move_tail(&e->list, &tx_list);
> e->skb = i == nr_frags - 1 ? skb : NULL;
> e->dma_addr = addr;
> @@ -2291,8 +2304,13 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> if (++i == nr_frags)
> break;
>
> - data = skb_frag_address(frag);
> len = skb_frag_size(frag);
> + addr = skb_frag_dma_map(netdev->dev.parent, frag, 0, len,
> + DMA_TO_DEVICE);
> + if (unlikely(dma_mapping_error(netdev->dev.parent, addr)))
> + goto error_unmap;
> +
> + e->dma_type = AIROHA_DMA_MAP_PAGE;
> }
> q->queued += i;
>
> @@ -2313,11 +2331,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> return NETDEV_TX_OK;
>
> error_unmap:
> - list_for_each_entry(e, &tx_list, list) {
> - dma_unmap_single(netdev->dev.parent, e->dma_addr, e->dma_len,
> - DMA_TO_DEVICE);
> - e->dma_addr = 0;
> - }
> + list_for_each_entry(e, &tx_list, list)
> + airoha_unmap_xmit_buf(dev->eth, e);
> list_splice(&tx_list, &q->tx_list);
> error_unlock:
> spin_unlock_bh(&q->lock);
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index d7ff8c5200e2..2765244d937c 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -170,12 +170,19 @@ enum trtcm_param {
> #define TRTCM_TOKEN_RATE_MASK GENMASK(23, 6)
> #define TRTCM_TOKEN_RATE_FRACTION_MASK GENMASK(5, 0)
>
> +enum airoha_dma_map_type {
> + AIROHA_DMA_UNMAPPED,
> + AIROHA_DMA_MAP_SINGLE,
> + AIROHA_DMA_MAP_PAGE,
> +};
> +
> struct airoha_queue_entry {
> union {
> void *buf;
> struct {
> struct list_head list;
> struct sk_buff *skb;
> + enum airoha_dma_map_type dma_type;
> };
> };
> dma_addr_t dma_addr;
>
> ---
> base-commit: 232c4ca2343d1181cbfc061f9856d9591e397579
> change-id: 20260625-airoha-eth-skb_frag_dma_map-bcccd5d6e4b1
>
> Best regards,
> --
> Lorenzo Bianconi <lorenzo@kernel.org>
>
>
^ permalink raw reply
* Re: [PATCH v14 4/5] gpio: rpmsg: add generic rpmsg GPIO driver
From: Julian Braha @ 2026-06-25 22:17 UTC (permalink / raw)
To: Shenwei Wang, Linus Walleij, Bartosz Golaszewski, Jonathan Corbet,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Mathieu Poirier, Frank Li, Sascha Hauer
Cc: Shuah Khan, linux-gpio, linux-doc, linux-kernel,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
devicetree, linux-remoteproc, imx, linux-arm-kernel, linux-imx,
Arnaud POULIQUEN, b-padhi, Andrew Lunn, Bartosz Golaszewski
In-Reply-To: <20260625155432.815185-5-shenwei.wang@oss.nxp.com>
Hi Shenwei,
On 6/25/26 16:54, Shenwei Wang wrote:
> +config GPIO_RPMSG
> + tristate "Generic RPMSG GPIO support"
> + depends on OF && REMOTEPROC
> + select GPIOLIB_IRQCHIP
> + default REMOTEPROC
> + help
> + Say yes here to support the generic GPIO functions over the RPMSG
> + bus. Currently supported devices: i.MX7ULP, i.MX8ULP, i.MX8x, and
> + i.MX9x.
> +
> + If unsure, say N.
You've got GPIO_RPMSG defaulting to REMOTEPROC, which is also a
dependency, so it's effectively the same as using 'default y'.
But then you've got "If unsure, say N" in the help text. Usually this is
used when the default is N.
- Julian Braha
^ permalink raw reply
* Re: [PATCH v3 2/3] selftests/resctrl: Replace counter index references with pointers
From: Reinette Chatre @ 2026-06-25 22:14 UTC (permalink / raw)
To: Yifan Wu, tony.luck, Dave.Martin, james.morse, babu.moger, shuah,
tan.shaopeng, fenghuay, ben.horgan, zengheng4, linux-kernel,
linux-arm-kernel, linux-kselftest, linuxarm
Cc: xiaqinxin, prime.zeng, wangyushan12, xuwei5, fanghao11, wangzhou1
In-Reply-To: <20260522090540.444554-3-wuyifan50@huawei.com>
Hi Yifan,
Thank you. I just have a few style fixup comments ...
On 5/22/26 2:05 AM, Yifan Wu wrote:
> Replace direct counter number references with pointers to remove the
> dependency on fixed array indexing and enable the use of different
> data structures for counter management.
>
> Signed-off-by: Yifan Wu <wuyifan50@huawei.com>
> ---
> tools/testing/selftests/resctrl/resctrl_val.c | 62 +++++++++----------
> 1 file changed, 31 insertions(+), 31 deletions(-)
>
> diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c
> index a72dc4ae61fe..3d2b6919717a 100644
> --- a/tools/testing/selftests/resctrl/resctrl_val.c
> +++ b/tools/testing/selftests/resctrl/resctrl_val.c
> @@ -42,40 +42,40 @@ static struct imc_counter_config imc_counters_config[MAX_IMCS];
> LIST_HEAD(imc_counters_list);
> static const struct resctrl_test *current_test;
>
> -static void read_mem_bw_initialize_perf_event_attr(int i)
> +static void read_mem_bw_initialize_perf_event_attr(struct imc_counter_config *imc_counter)
> {
> - memset(&imc_counters_config[i].pe, 0,
> + memset(&imc_counter->pe, 0,
> sizeof(struct perf_event_attr));
nit: above can fit on a single line
> - imc_counters_config[i].pe.type = imc_counters_config[i].type;
> - imc_counters_config[i].pe.size = sizeof(struct perf_event_attr);
> - imc_counters_config[i].pe.disabled = 1;
> - imc_counters_config[i].pe.inherit = 1;
> - imc_counters_config[i].pe.exclude_guest = 0;
> - imc_counters_config[i].pe.config =
> - imc_counters_config[i].umask << 8 |
> - imc_counters_config[i].event;
> - imc_counters_config[i].pe.sample_type = PERF_SAMPLE_IDENTIFIER;
> - imc_counters_config[i].pe.read_format =
> + imc_counter->pe.type = imc_counter->type;
> + imc_counter->pe.size = sizeof(struct perf_event_attr);
> + imc_counter->pe.disabled = 1;
> + imc_counter->pe.inherit = 1;
> + imc_counter->pe.exclude_guest = 0;
> + imc_counter->pe.config =
> + imc_counter->umask << 8 |
> + imc_counter->event;
nit: above can fit on a single line
> + imc_counter->pe.sample_type = PERF_SAMPLE_IDENTIFIER;
> + imc_counter->pe.read_format =
> PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING;
> }
>
...
> @@ -89,21 +89,21 @@ static void get_read_event_and_umask(char *cas_count_cfg, unsigned int count)
> if (!token[i])
> break;
> if (strcmp(token[i], "event") == 0)
> - imc_counters_config[count].event = strtol(token[i + 1], NULL, 16);
> + imc_counter->event = strtol(token[i + 1], NULL, 16);
> if (strcmp(token[i], "umask") == 0)
> - imc_counters_config[count].umask = strtol(token[i + 1], NULL, 16);
> + imc_counter->umask = strtol(token[i + 1], NULL, 16);
> }
> }
>
> -static int open_perf_read_event(int i, int cpu_no)
> +static int open_perf_read_event(int cpu_no, struct imc_counter_config *imc_counter)
> {
> - imc_counters_config[i].fd =
> - perf_event_open(&imc_counters_config[i].pe, -1, cpu_no, -1,
> + imc_counter->fd =
> + perf_event_open(&imc_counter->pe, -1, cpu_no, -1,
> PERF_FLAG_FD_CLOEXEC);
Please improve readibility here by moving the above two lines up while ensuring alignment with
open parenthesis. Specifically:
imc_counter->fd = perf_event_open(&imc_counter->pe, -1, cpu_no, -1,
PERF_FLAG_FD_CLOEXEC);
...
With the style fixups:
| Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
Reinette
^ permalink raw reply
* Re: [PATCH v3 1/3] selftests/resctrl: Introduce linked list management for IMC counters
From: Reinette Chatre @ 2026-06-25 22:14 UTC (permalink / raw)
To: Yifan Wu, tony.luck, Dave.Martin, james.morse, babu.moger, shuah,
tan.shaopeng, fenghuay, ben.horgan, zengheng4, linux-kernel,
linux-arm-kernel, linux-kselftest, linuxarm
Cc: xiaqinxin, prime.zeng, wangyushan12, xuwei5, fanghao11, wangzhou1
In-Reply-To: <20260522090540.444554-2-wuyifan50@huawei.com>
Hi Yifan,
On 5/22/26 2:05 AM, Yifan Wu wrote:
> The static array approach to managing IMC counters has fixed size
> constraints and limited compatibility and scalability. Introduce
> a linked list-based dynamic management infrastructure to address
> these limitations. Add the core data structure definitions and
> memory allocation and cleanup functions for dynamic counter
> configurations.
>
> Signed-off-by: Yifan Wu <wuyifan50@huawei.com>
> ---
Thank you.
Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
Reinette
^ permalink raw reply
* Re: [PATCH v3 3/3] selftests/resctrl: Enable dynamic management of IMC counters via linked list
From: Reinette Chatre @ 2026-06-25 22:14 UTC (permalink / raw)
To: Yifan Wu, tony.luck, Dave.Martin, james.morse, babu.moger, shuah,
tan.shaopeng, fenghuay, ben.horgan, zengheng4, linux-kernel,
linux-arm-kernel, linux-kselftest, linuxarm
Cc: xiaqinxin, prime.zeng, wangyushan12, xuwei5, fanghao11, wangzhou1
In-Reply-To: <20260522090540.444554-4-wuyifan50@huawei.com>
Hi Yifan,
On 5/22/26 2:05 AM, Yifan Wu wrote:
> @@ -242,14 +233,13 @@ static int read_from_imc_dir(char *imc_dir, unsigned int *count)
> * counter's event and umask for the memory read events that will be
> * measured.
> *
> - * Enumerate all these details into an array of structures.
> + * Enumerate all these details into a linked list of structures.
> *
> * Return: >= 0 on success. < 0 on failure.
> */
> -static int num_of_imcs(void)
> +static int enumerate_imcs(void)
The first sentence of this function's comments still describes the behavior being
changed in this patch. How about a fixup like below:
diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c
index 129e8d76222a..fe3b3517ae49 100644
--- a/tools/testing/selftests/resctrl/resctrl_val.c
+++ b/tools/testing/selftests/resctrl/resctrl_val.c
@@ -226,12 +226,10 @@ static int read_from_imc_dir(char *imc_dir)
}
/*
- * A system can have 'n' number of iMC (Integrated Memory Controller)
- * counters, get that 'n'. Discover the properties of the available
- * counters in support of needed performance measurement via perf.
- * For each iMC counter get it's type and config. Also obtain each
- * counter's event and umask for the memory read events that will be
- * measured.
+ * Discover the properties of the available iMC (Integrated Memory Controller)
+ * counters in support of needed performance measurement via perf. For each iMC
+ * counter get it's type and config. Also obtain each counter's event and umask
+ * for the memory read events that will be measured.
*
* Enumerate all these details into a linked list of structures.
*
...
> int initialize_read_mem_bw_imc(void)
> {
> - int imc;
> + struct imc_counter_config *imc_counter;
> + int ret;
>
> - imcs = num_of_imcs();
> - if (imcs <= 0)
> - return imcs;
> + ret = enumerate_imcs();
> + if (ret < 0)
> + return ret;
>
> /* Initialize perf_event_attr structures for all iMC's */
> - for (imc = 0; imc < imcs; imc++)
> - read_mem_bw_initialize_perf_event_attr(&imc_counters_config[imc]);
> + list_for_each_entry(imc_counter, &imc_counters_list, entry) {
> + read_mem_bw_initialize_perf_event_attr(imc_counter);
> + }
nit: unnecessary braces
>
> return 0;
> }
> @@ -328,11 +320,11 @@ void cleanup_read_mem_bw_imc(void)
>
> static void perf_close_imc_read_mem_bw(void)
> {
> - int mc;
> + struct imc_counter_config *imc_counter;
>
> - for (mc = 0; mc < imcs; mc++) {
> - if (imc_counters_config[mc].fd != -1)
> - close(imc_counters_config[mc].fd);
> + list_for_each_entry(imc_counter, &imc_counters_list, entry) {
> + if (imc_counter->fd != -1)
> + close(imc_counter->fd);
> }
> }
>
With fixup applied and nit addressed:
| Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
Reinette
^ permalink raw reply related
* [PATCH 4/4] PCI: mediatek-gen3: Add 2-lanes mode support for Airoha AN7581
From: Christian Marangi @ 2026-06-25 21:57 UTC (permalink / raw)
To: Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas,
Krzysztof Kozlowski, Conor Dooley, Ryder Lee, Michael Turquette,
Stephen Boyd, Brian Masney, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Christian Marangi, Jianjun Wang,
linux-pci, devicetree, linux-kernel, linux-mediatek, linux-clk,
linux-arm-kernel
In-Reply-To: <20260625215741.3253212-1-ansuelsmth@gmail.com>
The Airoha AN7581 SoC supports configuring the first PCIe0 line to 2-lanes
mode by bonding it with the second PCIe line. This is done by configuring
the PCIe MUX in the SCU register.
To correctly configure the line for 2-lanes mode, it's required to define
in DT an additional reg, 'sec-pcie-mac' for the secondary PCIe.
It's also needed to define the additional reset and the PERSTOUT reset.
Also 'airoha,scu' property is mandatory to correctly configure the SCU
register for the PCIe MUX.
Finally to toggle 2-lanes mode, it's needed to define in DT 'num-lanes' as
2.
In such configuration the EQ preset are configured to the same values.
To permit correct configuration of the PCIe line, additional logic is added
to assert and deassert the PERSTOUT resets.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/pci/controller/pcie-mediatek-gen3.c | 98 +++++++++++++++++----
1 file changed, 80 insertions(+), 18 deletions(-)
diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c
index b0accd828589..f750759bbc1d 100644
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
@@ -32,6 +32,11 @@
#include "../pci.h"
+/* AN7581 SCU register */
+#define SCU_PCIC 0x88
+#define SCU_PCIC_PCIE_CTRL GENMASK(7, 0)
+
+/* PCIe register */
#define PCIE_BASE_CFG_REG 0x14
#define PCIE_BASE_CFG_SPEED GENMASK(15, 8)
@@ -131,6 +136,7 @@
#define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2)
#define MAX_NUM_PHY_RESETS 3
+#define MAX_NUM_PERSTOUT_RESETS 2
#define PCIE_MTK_RESET_TIME_US 10
@@ -203,9 +209,11 @@ struct mtk_msi_set {
struct mtk_gen3_pcie {
struct device *dev;
void __iomem *base;
+ void __iomem *sec_base;
phys_addr_t reg_base;
struct reset_control *mac_reset;
struct reset_control_bulk_data phy_resets[MAX_NUM_PHY_RESETS];
+ struct reset_control_bulk_data perstout_resets[MAX_NUM_PERSTOUT_RESETS];
struct phy *phy;
struct clk_bulk_data *clks;
int num_clks;
@@ -222,6 +230,9 @@ struct mtk_gen3_pcie {
DECLARE_BITMAP(msi_irq_in_use, PCIE_MSI_IRQS_NUM);
const struct mtk_gen3_pcie_pdata *soc;
+
+ /* AN7581 specific */
+ struct regmap *scu;
};
/* LTSSM state in PCIE_LTSSM_STATUS_REG bit[28:24] */
@@ -928,6 +939,14 @@ static int mtk_pcie_parse_port(struct mtk_gen3_pcie *pcie)
if (ret)
return dev_err_probe(dev, ret, "failed to get PHY bulk reset\n");
+ pcie->perstout_resets[0].id = "perstout";
+ pcie->perstout_resets[1].id = "sec-perstout";
+
+ ret = devm_reset_control_bulk_get_optional_exclusive(dev, MAX_NUM_PERSTOUT_RESETS,
+ pcie->perstout_resets);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get PERSTOUT bulk reset\n");
+
pcie->mac_reset = devm_reset_control_get_optional_exclusive(dev, "mac");
if (IS_ERR(pcie->mac_reset))
return dev_err_probe(dev, PTR_ERR(pcie->mac_reset), "failed to get MAC reset\n");
@@ -955,12 +974,29 @@ static int mtk_pcie_parse_port(struct mtk_gen3_pcie *pcie)
static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie)
{
struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
+ unsigned int num_lanes = max(1, pcie->num_lanes);
struct device *dev = pcie->dev;
struct resource_entry *entry;
struct regmap *pbus_regmap;
u32 val, args[2], size;
resource_size_t addr;
- int err;
+ int i, err;
+
+ if (num_lanes == 2) {
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *regs;
+
+ regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sec-pcie-mac");
+ if (!regs)
+ return -EINVAL;
+ pcie->sec_base = devm_ioremap_resource(dev, regs);
+ if (IS_ERR(pcie->sec_base))
+ return dev_err_probe(dev, PTR_ERR(pcie->sec_base), "failed to map secondary register base\n");
+
+ pcie->scu = syscon_regmap_lookup_by_phandle(dev->of_node, "airoha,scu");
+ if (IS_ERR(pcie->scu))
+ return dev_err_probe(dev, PTR_ERR(pcie->scu), "failed to map SCU regmap\n");
+ }
/*
* The controller may have been left out of reset by the bootloader
@@ -1024,34 +1060,60 @@ static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie)
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
- val = FIELD_PREP(PCIE_VAL_LN0_DOWNSTREAM, 0x47) |
- FIELD_PREP(PCIE_VAL_LN1_DOWNSTREAM, 0x47) |
- FIELD_PREP(PCIE_VAL_LN0_UPSTREAM, 0x41) |
- FIELD_PREP(PCIE_VAL_LN1_UPSTREAM, 0x41);
- writel_relaxed(val, pcie->base + PCIE_EQ_PRESET_01_REG);
+ /* Assert PERSTOUT for all relevant lines */
+ err = reset_control_bulk_assert(MAX_NUM_PERSTOUT_RESETS,
+ pcie->perstout_resets);
+ if (err) {
+ dev_err(dev, "failed to assert PERSTOUTs\n");
+ goto err_perstout_assert;
+ }
+
+ /* Configure SCU MUX to disable PCIE1 for 2 lines mode */
+ if (num_lanes == 2)
+ regmap_update_bits(pcie->scu, SCU_PCIC, SCU_PCIC_PCIE_CTRL,
+ FIELD_PREP(SCU_PCIC_PCIE_CTRL, BIT(1)));
- val = PCIE_K_PHYPARAM_QUERY | PCIE_K_QUERY_TIMEOUT |
- FIELD_PREP(PCIE_K_PRESET_TO_USE_16G, 0x80) |
- FIELD_PREP(PCIE_K_PRESET_TO_USE, 0x2) |
- FIELD_PREP(PCIE_K_FINETUNE_MAX, 0xf);
- writel_relaxed(val, pcie->base + PCIE_PIPE4_PIE8_REG);
err = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);
if (err) {
dev_err(dev, "failed to prepare clock\n");
- goto err_clk_prepare_enable;
+ goto err_perstout_assert;
}
- /*
- * Airoha EN7581 performs PCIe reset via clk callbacks since it has a
- * hw issue with PCIE_PE_RSTB signal. Add wait for the time needed to
- * complete the PCIe reset.
- */
+ /* Wait for refclk to stabilize */
msleep(PCIE_T_PVPERL_MS);
+ /* Configure all the lines to the same EQ config */
+ for (i = 0; i < num_lanes; i++) {
+ void __iomem *base = pcie->base;
+
+ if (i == 1)
+ base = pcie->sec_base;
+
+ val = FIELD_PREP(PCIE_VAL_LN0_DOWNSTREAM, 0x47) |
+ FIELD_PREP(PCIE_VAL_LN1_DOWNSTREAM, 0x47) |
+ FIELD_PREP(PCIE_VAL_LN0_UPSTREAM, 0x41) |
+ FIELD_PREP(PCIE_VAL_LN1_UPSTREAM, 0x41);
+ writel_relaxed(val, base + PCIE_EQ_PRESET_01_REG);
+
+ val = PCIE_K_PHYPARAM_QUERY | PCIE_K_QUERY_TIMEOUT |
+ FIELD_PREP(PCIE_K_PRESET_TO_USE_16G, 0x80) |
+ FIELD_PREP(PCIE_K_PRESET_TO_USE, 0x2) |
+ FIELD_PREP(PCIE_K_FINETUNE_MAX, 0xf);
+ writel_relaxed(val, base + PCIE_PIPE4_PIE8_REG);
+ }
+
+ /* Deassert PERSTOUT for all relevant lines */
+ err = reset_control_bulk_deassert(MAX_NUM_PERSTOUT_RESETS,
+ pcie->perstout_resets);
+ if (err) {
+ dev_err(dev, "failed to deassert PERSTOUTs\n");
+ goto err_perstout_assert;
+ }
+
return 0;
-err_clk_prepare_enable:
+err_perstout_assert:
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
reset_control_bulk_assert(pcie->soc->phy_resets.num_resets,
--
2.53.0
^ permalink raw reply related
* [PATCH 3/4] dt-bindings: PCI: mediatek-gen3: Split Airoha schema and document 2-lanes
From: Christian Marangi @ 2026-06-25 21:57 UTC (permalink / raw)
To: Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas,
Krzysztof Kozlowski, Conor Dooley, Ryder Lee, Michael Turquette,
Stephen Boyd, Brian Masney, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Christian Marangi, Jianjun Wang,
linux-pci, devicetree, linux-kernel, linux-mediatek, linux-clk,
linux-arm-kernel
In-Reply-To: <20260625215741.3253212-1-ansuelsmth@gmail.com>
To permit proper documentation of required property to support PCIe
configured for 2-lanes mode, split the Airoha schema part from the
mediatek-gen3 schema to a dedicated schema.
A PCIe configured for 2-lanes mode require an additional reg for the
secondary PCIe to be configured and the airoha,scu phandle to correctly
configure the PCIe MUX.
Rework the mediatek-gen3 schema to drop any redundant constraint previsouly
introduced for Airoha PCIe properties.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
.../bindings/pci/airoha,en7581-pcie.yaml | 251 ++++++++++++++++++
.../bindings/pci/mediatek-pcie-gen3.yaml | 77 +-----
2 files changed, 256 insertions(+), 72 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pci/airoha,en7581-pcie.yaml
diff --git a/Documentation/devicetree/bindings/pci/airoha,en7581-pcie.yaml b/Documentation/devicetree/bindings/pci/airoha,en7581-pcie.yaml
new file mode 100644
index 000000000000..977c1816572c
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/airoha,en7581-pcie.yaml
@@ -0,0 +1,251 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/airoha,en7581-pcie.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Gen3 PCIe controller on Airoha SoCs
+
+maintainers:
+ - Christian Marangi <ansuelsmth@gmail.com>
+
+description: |+
+ PCIe Gen3 MAC controller for Airoha SoCs, it supports Gen3 speed
+ and compatible with Gen2, Gen1 speed.
+
+ This PCIe controller supports up to 256 MSI vectors, the MSI hardware
+ block diagram is as follows:
+
+ +-----+
+ | GIC |
+ +-----+
+ ^
+ |
+ port->irq
+ |
+ +-+-+-+-+-+-+-+-+
+ |0|1|2|3|4|5|6|7| (PCIe intc)
+ +-+-+-+-+-+-+-+-+
+ ^ ^ ^
+ | | ... |
+ +-------+ +------+ +-----------+
+ | | |
+ +-+-+---+--+--+ +-+-+---+--+--+ +-+-+---+--+--+
+ |0|1|...|30|31| |0|1|...|30|31| |0|1|...|30|31| (MSI sets)
+ +-+-+---+--+--+ +-+-+---+--+--+ +-+-+---+--+--+
+ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
+ | | | | | | | | | | | | (MSI vectors)
+ | | | | | | | | | | | |
+
+ (MSI SET0) (MSI SET1) ... (MSI SET7)
+
+ With 256 MSI vectors supported, the MSI vectors are composed of 8 sets,
+ each set has its own address for MSI message, and supports 32 MSI vectors
+ to generate interrupt.
+
+properties:
+ compatible:
+ const: airoha,en7581-pcie
+
+ reg:
+ minItems: 1
+ maxItems: 2
+
+ reg-names:
+ minItems: 1
+ maxItems: 2
+
+ interrupts:
+ maxItems: 1
+
+ ranges:
+ minItems: 1
+ maxItems: 8
+
+ iommu-map:
+ maxItems: 1
+
+ iommu-map-mask:
+ const: 0
+
+ resets:
+ minItems: 1
+ maxItems: 4
+
+ reset-names:
+ minItems: 1
+ maxItems: 4
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: sys-ck
+
+ phys:
+ maxItems: 1
+
+ phy-names:
+ items:
+ - const: pcie-phy
+
+ num-lanes:
+ enum: [1, 2]
+
+ mediatek,pbus-csr:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ items:
+ - items:
+ - description: phandle to pbus-csr syscon
+ - description: offset of pbus-csr base address register
+ - description: offset of pbus-csr base address mask register
+ description:
+ Phandle with two arguments to the syscon node used to detect if
+ a given address is accessible on PCIe controller.
+
+ airoha,scu:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ items:
+ - items:
+ - description: phandle to airoha SCU syscon
+ description:
+ Phandle to SCU syscon to configure PCIe MUX for 2 lines support.
+
+ '#interrupt-cells':
+ const: 1
+
+ interrupt-controller:
+ description: Interrupt controller node for handling legacy PCI interrupts.
+ type: object
+ properties:
+ '#address-cells':
+ const: 0
+ '#interrupt-cells':
+ const: 1
+ interrupt-controller: true
+
+ required:
+ - '#address-cells'
+ - '#interrupt-cells'
+ - interrupt-controller
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - interrupts
+ - ranges
+ - clocks
+ - clock-names
+ - '#interrupt-cells'
+ - interrupt-controller
+
+allOf:
+ - $ref: /schemas/pci/pci-host-bridge.yaml#
+ - if:
+ properties:
+ num-lanes:
+ const: 2
+ then:
+ properties:
+ regs:
+ minItems: 2
+
+ reg-names:
+ items:
+ - const: pcie-mac
+ - const: sec-pcie-mac
+
+ resets:
+ minItems: 4
+
+ reset-names:
+ items:
+ - const: phy-lane0
+ - const: phy-lane1
+ - const: perstout
+ - const: sec-perstout
+
+ required:
+ - airoha,scu
+
+ else:
+ properties:
+ reg:
+ maxItems: 1
+
+ reg-names:
+ items:
+ - const: pcie-mac
+
+ resets:
+ minItems: 2
+ maxItems: 3
+
+ reset-names:
+ minItems: 2
+ items:
+ - enum: [ phy-lane0, phy-lane1, phy-lan2 ]
+ - enum: [ phy-lane1, perstout ]
+ - const: phy-lane2
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pcie@1fc00000 {
+ compatible = "airoha,en7581-pcie";
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ reg = <0x0 0x1fc00000 0x0 0x1670>,
+ <0x0 0x1fc20000 0x0 0x1670>;
+ reg-names = "pcie-mac", "sec-pcie-mac";
+
+ clocks = <&scuclk 7>;
+ clock-names = "sys-ck";
+
+ phys = <&pciephy>;
+ phy-names = "pcie-phy";
+
+ ranges = <0x02000000 0 0x20000000 0x0 0x20000000 0 0x4000000>;
+
+ resets = <&scuclk 48>,
+ <&scuclk 49>,
+ <&scuclk 53>,
+ <&scuclk 54>;
+ reset-names = "phy-lane0", "phy-lane1",
+ "perstout", "sec-perstout";
+
+ num-lanes = <2>;
+
+ mediatek,pbus-csr = <&pbus_csr 0x0 0x4>;
+
+ airoha,scu = <&scuclk>;
+
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ bus-range = <0x00 0xff>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &pcie_intc 0>,
+ <0 0 0 2 &pcie_intc 1>,
+ <0 0 0 3 &pcie_intc 2>,
+ <0 0 0 4 &pcie_intc 3>;
+ pcie_intc: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml b/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
index 4db700fc36ba..510f1f2b1c5a 100644
--- a/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
@@ -59,7 +59,6 @@ properties:
- const: mediatek,mt8196-pcie
- const: mediatek,mt8192-pcie
- const: mediatek,mt8196-pcie
- - const: airoha,en7581-pcie
reg:
maxItems: 1
@@ -83,20 +82,20 @@ properties:
resets:
minItems: 1
- maxItems: 3
+ maxItems: 2
reset-names:
minItems: 1
- maxItems: 3
+ maxItems: 2
items:
- enum: [ phy, mac, phy-lane0, phy-lane1, phy-lane2 ]
+ enum: [ phy, mac ]
clocks:
- minItems: 1
+ minItems: 4
maxItems: 6
clock-names:
- minItems: 1
+ minItems: 4
maxItems: 6
assigned-clocks:
@@ -115,17 +114,6 @@ properties:
power-domains:
maxItems: 1
- mediatek,pbus-csr:
- $ref: /schemas/types.yaml#/definitions/phandle-array
- items:
- - items:
- - description: phandle to pbus-csr syscon
- - description: offset of pbus-csr base address register
- - description: offset of pbus-csr base address mask register
- description:
- Phandle with two arguments to the syscon node used to detect if
- a given address is accessible on PCIe controller.
-
'#interrupt-cells':
const: 1
@@ -177,16 +165,6 @@ allOf:
- const: peri_26m
- const: top_133m
- resets:
- minItems: 1
- maxItems: 2
-
- reset-names:
- minItems: 1
- maxItems: 2
-
- mediatek,pbus-csr: false
-
- if:
properties:
compatible:
@@ -208,16 +186,6 @@ allOf:
- const: peri_26m
- const: peri_mem
- resets:
- minItems: 1
- maxItems: 2
-
- reset-names:
- minItems: 1
- maxItems: 2
-
- mediatek,pbus-csr: false
-
- if:
properties:
compatible:
@@ -246,8 +214,6 @@ allOf:
- const: phy
- const: mac
- mediatek,pbus-csr: false
-
- if:
properties:
compatible:
@@ -257,7 +223,6 @@ allOf:
then:
properties:
clocks:
- minItems: 4
maxItems: 4
clock-names:
@@ -267,38 +232,6 @@ allOf:
- const: peri_26m
- const: top_133m
- resets:
- minItems: 1
- maxItems: 2
-
- reset-names:
- minItems: 1
- maxItems: 2
-
- mediatek,pbus-csr: false
-
- - if:
- properties:
- compatible:
- const: airoha,en7581-pcie
- then:
- properties:
- clocks:
- maxItems: 1
-
- clock-names:
- items:
- - const: sys-ck
-
- resets:
- minItems: 3
-
- reset-names:
- items:
- - const: phy-lane0
- - const: phy-lane1
- - const: phy-lane2
-
unevaluatedProperties: false
examples:
--
2.53.0
^ permalink raw reply related
* [PATCH 2/4] clk: en7523: add support for dedicated PCIe PERSTOUT reset
From: Christian Marangi @ 2026-06-25 21:57 UTC (permalink / raw)
To: Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas,
Krzysztof Kozlowski, Conor Dooley, Ryder Lee, Michael Turquette,
Stephen Boyd, Brian Masney, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Christian Marangi, Jianjun Wang,
linux-pci, devicetree, linux-kernel, linux-mediatek, linux-clk,
linux-arm-kernel
In-Reply-To: <20260625215741.3253212-1-ansuelsmth@gmail.com>
Add support for resetting the PCIe lines with the PERSTOUT reset. These
special reset are controlled by the PCIC register and are specific to each
of the 3 PCIe lines.
Notice that reset logic is inverted for these bit where 0 is assert and 1
deassert. This is intenrally handled in the reset function.
PCI enable/disable are updated to drop PERSTOUT bits in favor dedicated
reset handling.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/clk/clk-en7523.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
index 1ab0e2eca5d3..a33cf2e1b76f 100644
--- a/drivers/clk/clk-en7523.c
+++ b/drivers/clk/clk-en7523.c
@@ -338,6 +338,7 @@ static const struct en_clk_desc en7581_base_clks[] = {
static const u16 en7581_rst_ofs[] = {
REG_RST_CTRL2,
REG_RST_CTRL1,
+ REG_NP_SCU_PCIC,
};
static const u16 en751221_rst_ofs[] = {
@@ -450,6 +451,11 @@ static const u16 en7581_rst_map[] = {
[EN7581_CPU_TIMER_RST] = RST_NR_PER_BANK + 28,
[EN7581_PCIE_HB_RST] = RST_NR_PER_BANK + 29,
[EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
+
+ /* RST_PCIC */
+ [EN7581_PCIC_PERSTOUT0_RST] = 2 * RST_NR_PER_BANK + 29,
+ [EN7581_PCIC_PERSTOUT1_RST] = 2 * RST_NR_PER_BANK + 26,
+ [EN7581_PCIC_PERSTOUT2_RST] = 2 * RST_NR_PER_BANK + 16,
};
static const u16 en751221_rst_map[] = {
@@ -635,9 +641,7 @@ static int en7581_pci_enable(struct clk_hw *hw)
void __iomem *np_base = cg->base;
u32 val, mask;
- mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
- REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
- REG_PCI_CONTROL_PERSTOUT;
+ mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1;
val = readl(np_base + REG_PCI_CONTROL);
writel(val | mask, np_base + REG_PCI_CONTROL);
@@ -650,9 +654,7 @@ static void en7581_pci_disable(struct clk_hw *hw)
void __iomem *np_base = cg->base;
u32 val, mask;
- mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
- REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
- REG_PCI_CONTROL_PERSTOUT;
+ mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1;
val = readl(np_base + REG_PCI_CONTROL);
writel(val & ~mask, np_base + REG_PCI_CONTROL);
usleep_range(1000, 2000);
@@ -754,14 +756,21 @@ static int en7523_reset_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
- void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
+ u32 offset = rst_data->bank_ofs[id / RST_NR_PER_BANK];
+ void __iomem *addr = rst_data->base + offset;
+ bool inverted = false;
u32 val;
+ /* For PCIC reset logic is inverted, 0:assert 1:deassert*/
+ if (offset == REG_NP_SCU_PCIC)
+ inverted = true;
+
val = readl(addr);
+ val &= ~BIT(id % RST_NR_PER_BANK);
if (assert)
- val |= BIT(id % RST_NR_PER_BANK);
+ val |= inverted ? 0 : BIT(id % RST_NR_PER_BANK);
else
- val &= ~BIT(id % RST_NR_PER_BANK);
+ val |= inverted ? BIT(id % RST_NR_PER_BANK) : 0;
writel(val, addr);
return 0;
--
2.53.0
^ permalink raw reply related
* [PATCH 1/4] dt-bindings: clock: airoha: Add additional reset for PCIe PERSTOUT
From: Christian Marangi @ 2026-06-25 21:57 UTC (permalink / raw)
To: Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas,
Krzysztof Kozlowski, Conor Dooley, Ryder Lee, Michael Turquette,
Stephen Boyd, Brian Masney, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Christian Marangi, Jianjun Wang,
linux-pci, devicetree, linux-kernel, linux-mediatek, linux-clk,
linux-arm-kernel
In-Reply-To: <20260625215741.3253212-1-ansuelsmth@gmail.com>
Add additional reset to control PCIe PERSTOUT reset line for each of the 3
PCIe lines.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
include/dt-bindings/reset/airoha,en7581-reset.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/dt-bindings/reset/airoha,en7581-reset.h b/include/dt-bindings/reset/airoha,en7581-reset.h
index 6544a1790b83..25e75534daa9 100644
--- a/include/dt-bindings/reset/airoha,en7581-reset.h
+++ b/include/dt-bindings/reset/airoha,en7581-reset.h
@@ -62,5 +62,9 @@
#define EN7581_CPU_TIMER_RST 50
#define EN7581_PCIE_HB_RST 51
#define EN7581_XPON_MAC_RST 52
+/* RST_PCIC */
+#define EN7581_PCIC_PERSTOUT0_RST 53
+#define EN7581_PCIC_PERSTOUT1_RST 54
+#define EN7581_PCIC_PERSTOUT2_RST 55
#endif /* __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7581_H_ */
--
2.53.0
^ permalink raw reply related
* [PATCH 0/4] PCI: mediatek-gen3: Add 2-lanes mode support + clock
From: Christian Marangi @ 2026-06-25 21:57 UTC (permalink / raw)
To: Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas,
Krzysztof Kozlowski, Conor Dooley, Ryder Lee, Michael Turquette,
Stephen Boyd, Brian Masney, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Christian Marangi, Jianjun Wang,
linux-pci, devicetree, linux-kernel, linux-mediatek, linux-clk,
linux-arm-kernel
This small series introduce support for 2-lanes mode for Airoha AN7581
SoC. This is needed for correctly functionality of Eagle WiFi Card
normally attached to this SoC that require a 2-line PCIe card to
correctly work (and give the proper performance)
The first 2 patch address a limitation of the PCIe implementation
where the PERSTOUT reset were indirectly asserted and deasserted
all at the same time (for all the 3 PCIe card) with PCIe
enable and disable.
The 2 patch address this and introduce correct reset to control
reset line for the relevant PCIe line.
The last 2 patch add additional logic and support to assert
and deassert the PERSTOUT and also apply the required configuration
for 2-lanes mode.
2-lanes mode is implemented in DT by adding the required property
and by defining the "num-lanes" to 2.
Christian Marangi (4):
dt-bindings: clock: airoha: Add additional reset for PCIe PERSTOUT
clk: en7523: add support for dedicated PCIe PERSTOUT reset
dt-bindings: PCI: mediatek-gen3: Split Airoha schema and document
2-lanes
PCI: mediatek-gen3: Add 2-lanes mode support for Airoha AN7581
.../bindings/pci/airoha,en7581-pcie.yaml | 251 ++++++++++++++++++
.../bindings/pci/mediatek-pcie-gen3.yaml | 77 +-----
drivers/clk/clk-en7523.c | 27 +-
drivers/pci/controller/pcie-mediatek-gen3.c | 98 +++++--
.../dt-bindings/reset/airoha,en7581-reset.h | 4 +
5 files changed, 358 insertions(+), 99 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pci/airoha,en7581-pcie.yaml
--
2.53.0
^ permalink raw reply
* Re: [PATCH] arm64: dts: ti: k3-am62a7-sk: Add bootph-all property in cpsw_mac_syscon node
From: Andrew Davis @ 2026-06-25 20:48 UTC (permalink / raw)
To: Chintan Vankar, Conor Dooley, Krzysztof Kozlowski, Rob Herring,
Tero Kristo, Vignesh Raghavendra, Nishanth Menon
Cc: linux-kernel, devicetree, linux-arm-kernel
In-Reply-To: <20260625113223.1711052-1-c-vankar@ti.com>
On 6/25/26 6:32 AM, Chintan Vankar wrote:
> Ethernet boot requires CPSW node to be present starting from R5 SPL stage.
> Add "bootph-all" property in CPSW MAC's eFuse node "cpsw_mac_syscon" to
> enable this node during SPL stage along with later boot stage so that CPSW
> port will get static MAC address.
>
> Signed-off-by: Chintan Vankar <c-vankar@ti.com>
> ---
>
> Hello All,
>
> This patch is based on linux-next tagged next-20260623.
>
> arch/arm64/boot/dts/ti/k3-am62a7-sk.dts | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
> index 821a9705bb7d..d3b3675e7a8f 100644
> --- a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
> +++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
> @@ -230,6 +230,10 @@ AM62AX_MCU_IOPAD(0x0030, PIN_OUTPUT, 0) /* (C8) WKUP_UART0_RTSn */
> };
> };
>
> +&cpsw_mac_syscon {
> + bootph-all;
Seems you need this because cpsw_port1 uses it though a phandle reference.
cpsw_port1 has bootph-all, why is this property not transitive though
phandles? Would not having that cause missing references when the phandles
are resolved to nodes that get dropped for some given boot stage?
Andrew
> +};
> +
> /* WKUP UART0 is used for DM firmware logs */
> &wkup_uart0 {
> pinctrl-names = "default";
^ permalink raw reply
* Re: [PATCH 2/2] arm64: dts: ti: Add support for the phyCORE-AM67x
From: Andrew Davis @ 2026-06-25 20:37 UTC (permalink / raw)
To: Nathan Morrisson, nm, vigneshr, kristo, robh, krzk+dt, conor+dt
Cc: linux-arm-kernel, devicetree, linux-kernel, upstream
In-Reply-To: <20260625160214.4001298-2-nmorrisson@phytec.com>
On 6/25/26 11:02 AM, Nathan Morrisson wrote:
> Add support for the PHYTEC phyCORE-AM67x SoM [1] and the
> corresponding phyBOARD-Rigel carrier board [2]. The phyCORE-AM67x SoM
> uses the TI AM67x SoC and can come with different sizes and models of
> DDR, eMMC, and SPI NOR Flash.
>
> Supported features:
> * Audio playback and recording
> * CAN
> * Debug UART
> * eMMC
> * Ethernet
> * GPIO buttons
> * Heartbeat LED
> * I2C Current sensor
> * I2C EEPROM
> * I2C Light sensor
> * I2C RTC
> * Micro SD card
> * PCIe
> * SPI NOR flash
> * USB
>
> [1] https://www.phytec.com/product/phycore-am67x/
> [2] https://www.phytec.com/product/phyboard-am67x-development-kit/
>
> Signed-off-by: Nathan Morrisson <nmorrisson@phytec.com>
> ---
> arch/arm64/boot/dts/ti/Makefile | 1 +
> .../boot/dts/ti/k3-am67-phycore-som.dtsi | 328 ++++++++++++
> .../boot/dts/ti/k3-am6754-phyboard-rigel.dts | 502 ++++++++++++++++++
> 3 files changed, 831 insertions(+)
> create mode 100644 arch/arm64/boot/dts/ti/k3-am67-phycore-som.dtsi
> create mode 100644 arch/arm64/boot/dts/ti/k3-am6754-phyboard-rigel.dts
>
> diff --git a/arch/arm64/boot/dts/ti/Makefile b/arch/arm64/boot/dts/ti/Makefile
> index 371f9a043fe5..623ee2369132 100644
> --- a/arch/arm64/boot/dts/ti/Makefile
> +++ b/arch/arm64/boot/dts/ti/Makefile
> @@ -184,6 +184,7 @@ dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm-pcie1-ep.dtbo
> dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm-usb0-type-a.dtbo
>
> # Boards with J722s SoC
> +dtb-$(CONFIG_ARCH_K3) += k3-am6754-phyboard-rigel.dtb
> dtb-$(CONFIG_ARCH_K3) += k3-am67a-beagley-ai.dtb
> dtb-$(CONFIG_ARCH_K3) += k3-j722s-evm.dtb
> dtb-$(CONFIG_ARCH_K3) += k3-j722s-evm-csi2-quad-rpi-cam-imx219.dtbo
> diff --git a/arch/arm64/boot/dts/ti/k3-am67-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am67-phycore-som.dtsi
> new file mode 100644
> index 000000000000..8a40f648098e
> --- /dev/null
> +++ b/arch/arm64/boot/dts/ti/k3-am67-phycore-som.dtsi
> @@ -0,0 +1,328 @@
> +// SPDX-License-Identifier: GPL-2.0-only OR MIT
> +/*
> + * Copyright (C) 2026 PHYTEC America LLC
> + * Author: Nathan Morrisson <nmorrisson@phytec.com>
> + */
> +
> +#include <dt-bindings/net/ti-dp83867.h>
> +#include <dt-bindings/leds/common.h>
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/interrupt-controller/irq.h>
> +
> +/ {
> + compatible = "phytec,am67-phycore-som", "ti,j722s";
> + model = "PHYTEC phyCORE-AM67";
> +
> + aliases {
> + ethernet0 = &cpsw_port1;
> + gpio0 = &main_gpio0;
> + mmc0 = &sdhci0;
> + rtc0 = &i2c_som_rtc;
> + rtc1 = &wkup_rtc0;
> + spi0 = &ospi0;
> + };
> +
> + memory@80000000 {
> + /* 4G RAM */
> + reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
> + <0x00000008 0x80000000 0x00000000 0x80000000>;
> + device_type = "memory";
> + bootph-all;
> + };
> +
> + reserved_memory: reserved-memory {
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> +
> + secure_tfa_ddr: tfa@9e780000 {
> + reg = <0x00 0x9e780000 0x00 0x80000>;
> + no-map;
> + };
> +
> + secure_ddr: optee@9e800000 {
> + reg = <0x00 0x9e800000 0x00 0x01800000>;
> + no-map;
> + };
> +
> + wkup_r5fss0_core0_dma_memory_region: memory@a0000000 {
> + compatible = "shared-dma-pool";
> + reg = <0x00 0xa0000000 0x00 0x100000>;
> + no-map;
> + };
> +
> + wkup_r5fss0_core0_memory_region: memory@a0100000 {
> + compatible = "shared-dma-pool";
> + reg = <0x00 0xa0100000 0x00 0xf00000>;
> + no-map;
> + };
> + };
> +
> + vcc_5v0_som: regulator-vcc-5v0-som {
> + compatible = "regulator-fixed";
> + regulator-name = "VCC_5V0_SOM";
> + regulator-min-microvolt = <5000000>;
> + regulator-max-microvolt = <5000000>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + leds {
> + compatible = "gpio-leds";
> + pinctrl-names = "default";
> + pinctrl-0 = <&leds_pins_default>;
> +
> + led-0 {
> + color = <LED_COLOR_ID_GREEN>;
> + gpios = <&main_gpio0 13 GPIO_ACTIVE_HIGH>;
> + linux,default-trigger = "heartbeat";
> + function = LED_FUNCTION_HEARTBEAT;
> + };
> + };
> +};
> +
> +&main_pmx0 {
> + leds_pins_default: leds-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x034, PIN_OUTPUT, 7) /* (K22) OSPI0_CSN2.GPIO0_13 */
> + >;
> + };
> +
> + mdio_pins_default: mdio-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x0160, PIN_OUTPUT, 0) /* (AC24) MDIO0_MDC */
> + J722S_IOPAD(0x015c, PIN_INPUT, 0) /* (AD25) MDIO0_MDIO */
> + >;
> + bootph-all;
> + };
> +
> + ospi0_pins_default: ospi0-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x000, PIN_OUTPUT, 0) /* (L24) OSPI0_CLK */
> + J722S_IOPAD(0x02c, PIN_OUTPUT, 0) /* (K26) OSPI0_CSn0 */
> + J722S_IOPAD(0x00c, PIN_INPUT, 0) /* (K27) OSPI0_D0 */
> + J722S_IOPAD(0x010, PIN_INPUT, 0) /* (L27) OSPI0_D1 */
> + J722S_IOPAD(0x014, PIN_INPUT, 0) /* (L26) OSPI0_D2 */
> + J722S_IOPAD(0x018, PIN_INPUT, 0) /* (L25) OSPI0_D3 */
> + J722S_IOPAD(0x01c, PIN_INPUT, 0) /* (L21) OSPI0_D4 */
> + J722S_IOPAD(0x020, PIN_INPUT, 0) /* (M26) OSPI0_D5 */
> + J722S_IOPAD(0x024, PIN_INPUT, 0) /* (N27) OSPI0_D6 */
> + J722S_IOPAD(0x028, PIN_INPUT, 0) /* (M27) OSPI0_D7 */
> + J722S_IOPAD(0x008, PIN_INPUT, 0) /* (L22) OSPI0_DQS */
> + J722S_IOPAD(0x038, PIN_INPUT, 7) /* (J22) OSPI0_CSn3.GPIO0_14 */
> + >;
> + bootph-all;
> + };
> +
> + pmic_irq_pins_default: pmic-irq-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x030, PIN_INPUT, 7) /* (K23) OSPI0_CSN1.GPIO0_12 */
> + >;
> + };
> +
> + rgmii1_pins_default: rgmii1-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x014c, PIN_INPUT, 0) /* (AC25) RGMII1_RD0 */
> + J722S_IOPAD(0x0150, PIN_INPUT, 0) /* (AD27) RGMII1_RD1 */
> + J722S_IOPAD(0x0154, PIN_INPUT, 0) /* (AE24) RGMII1_RD2 */
> + J722S_IOPAD(0x0158, PIN_INPUT, 0) /* (AE26) RGMII1_RD3 */
> + J722S_IOPAD(0x0148, PIN_INPUT, 0) /* (AE27) RGMII1_RXC */
> + J722S_IOPAD(0x0144, PIN_INPUT, 0) /* (AD23) RGMII1_RX_CTL */
> + J722S_IOPAD(0x0134, PIN_OUTPUT, 0) /* (AF27) RGMII1_TD0 */
> + J722S_IOPAD(0x0138, PIN_OUTPUT, 0) /* (AE23) RGMII1_TD1 */
> + J722S_IOPAD(0x013c, PIN_OUTPUT, 0) /* (AG25) RGMII1_TD2 */
> + J722S_IOPAD(0x0140, PIN_OUTPUT, 0) /* (AF24) RGMII1_TD3 */
> + J722S_IOPAD(0x0130, PIN_OUTPUT, 0) /* (AG26) RGMII1_TXC */
> + J722S_IOPAD(0x012c, PIN_OUTPUT, 0) /* (AF25) RGMII1_TX_CTL */
> + >;
> + bootph-all;
> + };
> +};
> +
> +&mcu_pmx0 {
> + wkup_i2c0_pins_default: wkup-i2c0-default-pins {
> + pinctrl-single,pins = <
> + J722S_MCU_IOPAD(0x04c, PIN_INPUT_PULLUP, 0) /* (B9) WKUP_I2C0_SCL */
> + J722S_MCU_IOPAD(0x050, PIN_INPUT_PULLUP, 0) /* (D11) WKUP_I2C0_SDA */
> + >;
> + bootph-all;
> + };
> +};
> +
> +&cpsw3g {
> + pinctrl-names = "default";
> + pinctrl-0 = <&rgmii1_pins_default>;
> + bootph-all;
> + status = "okay";
> +};
> +
> +&cpsw3g_mdio {
> + pinctrl-names = "default";
> + pinctrl-0 = <&mdio_pins_default>;
> + status = "okay";
> +
> + cpsw3g_phy1: ethernet-phy@1 {
> + compatible = "ethernet-phy-ieee802.3-c22";
> + reg = <1>;
> + ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
> + tx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
> + ti,min-output-impedance;
> + };
> +};
> +
> +&cpsw_port1 {
> + phy-mode = "rgmii-id";
> + phy-handle = <&cpsw3g_phy1>;
> + status = "okay";
> +};
> +
> +&cpsw_port2 {
> + status = "disabled";
This should already be default disabled in the SoC dtsi,
no need to re-disable it here.
> +};
> +
> +&ospi0 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&ospi0_pins_default>;
> + bootph-all;
> + status = "okay";
> +
> + serial_flash: flash@0 {
> + compatible = "jedec,spi-nor";
> + reg = <0x0>;
> + spi-tx-bus-width = <8>;
> + spi-rx-bus-width = <8>;
> + spi-max-frequency = <25000000>;
> + vcc-supply = <&vdd_1v8>;
> + cdns,tshsl-ns = <60>;
> + cdns,tsd2d-ns = <60>;
> + cdns,tchsh-ns = <60>;
> + cdns,tslch-ns = <60>;
> + cdns,read-delay = <0>;
> + };
> +};
> +
> +&sdhci0 {
> + non-removable;
> + bootph-all;
> + ti,driver-strength-ohm = <50>;
> + status = "okay";
> +};
> +
> +&wkup_i2c0 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&wkup_i2c0_pins_default>;
> + clock-frequency = <400000>;
> + bootph-all;
> + status = "okay";
> +
> + pmic@30 {
> + compatible = "ti,tps65219";
> + reg = <0x30>;
> + buck1-supply = <&vcc_5v0_som>;
> + buck2-supply = <&vcc_5v0_som>;
> + buck3-supply = <&vcc_5v0_som>;
> + ldo1-supply = <&vdd_3v3>;
> + ldo2-supply = <&vdd_1v8>;
> + ldo3-supply = <&vdd_3v3>;
> + ldo4-supply = <&vdd_3v3>;
> +
> + pinctrl-names = "default";
> + pinctrl-0 = <&pmic_irq_pins_default>;
> + interrupt-parent = <&main_gpio0>;
> + interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
> + interrupt-controller;
> + #interrupt-cells = <1>;
> +
> + system-power-controller;
> + ti,power-button;
> +
> + regulators {
> + vdd_3v3: buck1 {
> + regulator-name = "VDD_3V3";
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-boot-on;
> + regulator-always-on;
> + };
> +
> + vdd_1v8: buck2 {
> + regulator-name = "VDD_1V8";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + regulator-boot-on;
> + regulator-always-on;
> + };
> +
> + vdd_lpddr4: buck3 {
> + regulator-name = "VDD_LPDDR4";
> + regulator-min-microvolt = <1100000>;
> + regulator-max-microvolt = <1100000>;
> + regulator-boot-on;
> + regulator-always-on;
> + };
> +
> + vddshv_sdio: ldo1 {
> + regulator-name = "VDDSHV_SDIO";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-allow-bypass;
> + regulator-boot-on;
> + regulator-always-on;
> + };
> +
> + vdd_1v2: ldo2 {
> + regulator-name = "VDD_1V2";
> + regulator-min-microvolt = <1200000>;
> + regulator-max-microvolt = <1200000>;
> + regulator-boot-on;
> + regulator-always-on;
> + };
> +
> + vdda_1v8_phy: ldo3 {
> + regulator-name = "VDDA_1V8_PHY";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + regulator-boot-on;
> + regulator-always-on;
> + };
> +
> + vdd_1v8_pll: ldo4 {
> + regulator-name = "VDD_1V8_PLL";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + regulator-boot-on;
> + regulator-always-on;
> + };
> + };
> + };
> +
> + vdd_core: regulator-vdd-core@44 {
> + compatible = "ti,tps62873";
> + reg = <0x44>;
> + bootph-pre-ram;
> + regulator-name = "VDD_CORE";
> + regulator-min-microvolt = <850000>;
> + regulator-max-microvolt = <850000>;
> + regulator-boot-on;
> + regulator-always-on;
> + };
> +
> + eeprom@50 {
> + compatible = "atmel,24c32";
> + reg = <0x50>;
> + pagesize = <32>;
> + };
> +
> + som_eeprom_opt: eeprom@51 {
> + compatible = "atmel,24c32";
> + reg = <0x51>;
> + pagesize = <32>;
> + };
> +
> + i2c_som_rtc: rtc@52 {
> + compatible = "microcrystal,rv3028";
> + reg = <0x52>;
> + };
> +};
> +
> +#include "k3-j722s-ti-ipc-firmware.dtsi"
> diff --git a/arch/arm64/boot/dts/ti/k3-am6754-phyboard-rigel.dts b/arch/arm64/boot/dts/ti/k3-am6754-phyboard-rigel.dts
> new file mode 100644
> index 000000000000..7853d4f5d3b9
> --- /dev/null
> +++ b/arch/arm64/boot/dts/ti/k3-am6754-phyboard-rigel.dts
> @@ -0,0 +1,502 @@
> +// SPDX-License-Identifier: GPL-2.0-only OR MIT
> +/*
> + * Copyright (C) 2026 PHYTEC America LLC
> + * Author: Nathan Morrisson <nmorrisson@phytec.com>
> + */
> +
> +/dts-v1/;
> +
> +#include <dt-bindings/input/input.h>
> +#include <dt-bindings/phy/phy.h>
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/interrupt-controller/irq.h>
> +#include "k3-serdes.h"
> +#include "k3-j722s.dtsi"
This should be included by the som.dtsi, keeps the include chain sane.
Andrew
> +#include "k3-am67-phycore-som.dtsi"
> +
> +/ {
> + compatible = "phytec,am6754-phyboard-rigel",
> + "phytec,am67-phycore-som", "ti,j722s";
> + model = "PHYTEC phyBOARD-Rigel AM67";
> +
> + aliases {
> + gpio1 = &main_gpio1;
> + mmc1 = &sdhci1;
> + serial2 = &main_uart0;
> + usb0 = &usb0;
> + usb1 = &usb1;
> + };
> +
> + can_tc0: can-phy0 {
> + compatible = "ti,tcan1042";
> + #phy-cells = <0>;
> + max-bitrate = <8000000>;
> + standby-gpios = <&gpio_exp1 1 GPIO_ACTIVE_HIGH>;
> + };
> +
> + usb0_connector: connector {
> + compatible = "gpio-usb-b-connector", "usb-b-connector";
> + label = "USB-C";
> + data-role = "dual";
> +
> + pinctrl-names = "default";
> + pinctrl-0 = <&main_usbc_power_pins_default>;
> +
> + id-gpios = <&main_gpio1 15 GPIO_ACTIVE_HIGH>;
> +
> + port {
> + usb0_con: endpoint {
> + remote-endpoint = <&usb0_ep>;
> + };
> + };
> + };
> +
> + keys {
> + compatible = "gpio-keys";
> + autorepeat;
> + pinctrl-names = "default";
> + pinctrl-0 = <&gpio_keys_pins_default>;
> +
> + key-home {
> + label = "home";
> + linux,code = <KEY_HOME>;
> + gpios = <&main_gpio1 23 GPIO_ACTIVE_HIGH>;
> + };
> +
> + key-menu {
> + label = "menu";
> + linux,code = <KEY_MENU>;
> + gpios = <&gpio_exp1 4 GPIO_ACTIVE_HIGH>;
> + };
> + };
> +
> + pcie_refclk0: pcie-refclk0 {
> + compatible = "gpio-gate-clock";
> + pinctrl-names = "default";
> + pinctrl-0 = <&main_pcie_usb_sel_pins_default>;
> + clocks = <&serdes_refclk>;
> + #clock-cells = <0>;
> + enable-gpios = <&main_gpio0 22 GPIO_ACTIVE_LOW>;
> + };
> +
> + vcc_1v8: regulator-vcc-1v8 {
> + compatible = "regulator-fixed";
> + regulator-name = "VCC_1V8";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + vcc_3v3_aud: regulator-vcc-3v3-aud {
> + compatible = "regulator-fixed";
> + regulator-name = "VCC_3V3_AUD";
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + vcc_3v3_mmc: regulator-vcc-3v3-mmc {
> + /* TPS22963C OUTPUT */
> + compatible = "regulator-fixed";
> + regulator-name = "VCC_3V3_MMC";
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + vcc_3v3_sw: regulator-vcc-3v3-sw {
> + compatible = "regulator-fixed";
> + regulator-name = "VCC_3V3_SW";
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + vcc_speaker: regulator-vcc-speaker {
> + compatible = "regulator-fixed";
> + regulator-name = "VCC_SPEAKER";
> + regulator-min-microvolt = <5000000>;
> + regulator-max-microvolt = <5000000>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + sound {
> + compatible = "simple-audio-card";
> + simple-audio-card,widgets =
> + "Microphone", "Mic Jack",
> + "Headphone", "Headphone Jack",
> + "Line", "Stereo Jack",
> + "Speaker", "L SPKR",
> + "Speaker", "R SPKR";
> + simple-audio-card,routing =
> + "MIC1RP", "Mic Jack",
> + "Mic Jack", "MICBIAS",
> + "Headphone Jack", "HPL",
> + "Headphone Jack", "HPR",
> + "MIC1LM", "Stereo Jack",
> + "MIC1LP", "Stereo Jack",
> + "SPL", "L SPKR",
> + "SPR", "R SPKR";
> + simple-audio-card,name = "phyBOARD-Rigel";
> + simple-audio-card,format = "dsp_b";
> + simple-audio-card,bitclock-master = <&sound_master>;
> + simple-audio-card,frame-master = <&sound_master>;
> + simple-audio-card,bitclock-inversion;
> +
> + simple-audio-card,cpu {
> + sound-dai = <&mcasp0>;
> + };
> +
> + sound_master: simple-audio-card,codec {
> + sound-dai = <&audio_codec>;
> + clocks = <&audio_refclk1>;
> + };
> + };
> +};
> +
> +&main_pmx0 {
> + audio_ext_refclk1_pins_default: audio-ext-refclk1-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x0a0, PIN_OUTPUT, 1) /* (N24) GPMC0_WPn.AUDIO_EXT_REFCLK1 */
> + >;
> + };
> +
> + gpio_exp0_int_pins_default: gpio-exp0-int-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x0054, PIN_INPUT, 7) /* (T21) GPMC0_AD6.GPIO0_21 */
> + >;
> + };
> +
> + gpio_exp1_int_pins_default: gpio-exp1-int-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x0244, PIN_INPUT, 7) /* (A24) MMC1_SDWP.GPIO1_49 */
> + >;
> + };
> +
> + gpio_exp2_int_pins_default: gpio-exp2-int-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x0050, PIN_INPUT, 7) /* (T24) GPMC0_AD5.GPIO0_20 */
> + >;
> + };
> +
> + gpio_keys_pins_default: gpio-keys-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x01d4, PIN_INPUT, 7) /* (B21) UART0_RTSn.GPIO1_23 */
> + >;
> + };
> +
> + main_i2c0_pins_default: main-i2c0-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x01e0, PIN_INPUT_PULLUP, 0) /* (D23) I2C0_SCL */
> + J722S_IOPAD(0x01e4, PIN_INPUT_PULLUP, 0) /* (B22) I2C0_SDA */
> + >;
> + bootph-all;
> + };
> +
> + main_i2c1_pins_default: main-i2c1-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x01e8, PIN_INPUT_PULLUP, 0) /* (C24) I2C1_SCL */
> + J722S_IOPAD(0x01ec, PIN_INPUT_PULLUP, 0) /* (A22) I2C1_SDA */
> + >;
> + bootph-all;
> + };
> +
> + main_mcan0_pins_default: main-mcan0-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x1dc, PIN_INPUT, 0) /* (C22) MCAN0_RX */
> + J722S_IOPAD(0x1d8, PIN_OUTPUT, 0) /* (D22) MCAN0_TX */
> + >;
> + };
> +
> + main_mcasp0_pins_default: main-mcasp0-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x1a8, PIN_INPUT, 0) /* (C26) MCASP0_AFSX */
> + J722S_IOPAD(0x1a4, PIN_INPUT, 0) /* (D25) MCASP0_ACLKX */
> + J722S_IOPAD(0x198, PIN_OUTPUT, 0) /* (A26) MCASP0_AXR2 */
> + J722S_IOPAD(0x194, PIN_INPUT, 0) /* (A25) MCASP0_AXR3 */
> + >;
> + };
> +
> + main_mcasp1_pins_default: main-mcasp1-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x0090, PIN_INPUT, 2) /* (P27) GPMC0_BE0n_CLE.MCASP1_ACLKX */
> + J722S_IOPAD(0x0098, PIN_INPUT, 2) /* (V21) GPMC0_WAIT0.MCASP1_AFSX */
> + J722S_IOPAD(0x008c, PIN_OUTPUT, 2) /* (N23) GPMC0_WEn.MCASP1_AXR0 */
> + >;
> + };
> +
> + main_mmc1_pins_default: main-mmc1-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x023c, PIN_INPUT, 0) /* (H22) MMC1_CMD */
> + J722S_IOPAD(0x0234, PIN_INPUT, 0) /* (H24) MMC1_CLK */
> + J722S_IOPAD(0x0230, PIN_INPUT, 0) /* (H23) MMC1_DAT0 */
> + J722S_IOPAD(0x022c, PIN_INPUT, 0) /* (H20) MMC1_DAT1 */
> + J722S_IOPAD(0x0228, PIN_INPUT, 0) /* (J23) MMC1_DAT2 */
> + J722S_IOPAD(0x0224, PIN_INPUT, 0) /* (H25) MMC1_DAT3 */
> + J722S_IOPAD(0x0240, PIN_INPUT, 0) /* (B24) MMC1_SDCD */
> + >;
> + bootph-all;
> + };
> +
> + main_pcie_pins_default: main-pcie-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x07c, PIN_INPUT, 7) /* (T23) GPMC0_CLK.GPIO0_31 */
> + >;
> + };
> +
> + main_pcie_usb_sel_pins_default: main-pcie-usb-sel-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x058, PIN_INPUT, 7) /* (T22) GPMC0_AD7.GPIO0_22 */
> + >;
> + };
> +
> + main_uart0_pins_default: main-uart0-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x01c8, PIN_INPUT, 0) /* (F19) UART0_RXD */
> + J722S_IOPAD(0x01cc, PIN_OUTPUT, 0) /* (F20) UART0_TXD */
> + >;
> + bootph-all;
> + };
> +
> + main_usbc_power_pins_default: main-usbc-power-default-pins {
> + pinctrl-single,pins = <
> + J722S_IOPAD(0x1b4, PIN_INPUT, 7) /* (B20) SPI0_CS0.GPIO1_15 */
> + >;
> + };
> +};
> +
> +&audio_refclk1 {
> + assigned-clock-rates = <25000000>;
> +};
> +
> +&main_i2c0 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&main_i2c0_pins_default>;
> + clock-frequency = <400000>;
> + status = "okay";
> +
> + veml6030: light-sensor@10 {
> + compatible = "vishay,veml6030";
> + reg = <0x10>;
> + vdd-supply = <&vcc_3v3_sw>;
> + };
> +};
> +
> +&main_i2c1 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&main_i2c1_pins_default>;
> + clock-frequency = <100000>;
> + status = "okay";
> +
> + audio_codec: audio-codec@18 {
> + compatible = "ti,tlv320aic3110";
> + reg = <0x18>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&audio_ext_refclk1_pins_default>;
> + #sound-dai-cells = <0>;
> + ai3xx-micbias-vg = <2>;
> + reset-gpios = <&gpio_exp1 7 GPIO_ACTIVE_LOW>;
> +
> + HPVDD-supply = <&vcc_3v3_aud>;
> + SPRVDD-supply = <&vcc_speaker>;
> + SPLVDD-supply = <&vcc_speaker>;
> + AVDD-supply = <&vcc_3v3_aud>;
> + IOVDD-supply = <&vcc_3v3_aud>;
> + DVDD-supply = <&vcc_1v8>;
> + };
> +
> + gpio_exp0: gpio@20 {
> + compatible = "nxp,pcf8574";
> + reg = <0x20>;
> + gpio-controller;
> + #gpio-cells = <2>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&gpio_exp0_int_pins_default>;
> + interrupt-parent = <&main_gpio0>;
> + interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
> + gpio-line-names = "CSI3_STROBE", "CSI3_TRIGGER",
> + "CSI3_SHUTTER", "CSI3_OE",
> + "CSI2_STROBE", "CSI2_TRIGGER",
> + "CSI2_SHUTTER", "CSI2_OE";
> + };
> +
> + gpio_exp1: gpio@21 {
> + compatible = "nxp,pcf8574";
> + reg = <0x21>;
> + gpio-controller;
> + #gpio-cells = <2>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&gpio_exp1_int_pins_default>;
> + interrupt-parent = <&main_gpio1>;
> + interrupts = <49 IRQ_TYPE_LEVEL_LOW>;
> + gpio-line-names = "GPIO0_HDMI_RST", "GPIO1_CAN_nEN",
> + "GPIO2_LED", "GPIO3_MCU_CAN0_nEN",
> + "GPIO4_BUT2", "GPIO5_MCU_CAN1_nEN",
> + "GPIO6_AUDIO_GPIO", "GPIO7_AUDIO_USER_RESET";
> + };
> +
> + gpio_exp2: gpio@23 {
> + compatible = "nxp,pcf8574";
> + reg = <0x23>;
> + gpio-controller;
> + #gpio-cells = <2>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&gpio_exp2_int_pins_default>;
> + interrupt-parent = <&main_gpio0>;
> + interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
> + gpio-line-names = "CSI1_STROBE", "CSI1_TRIGGER",
> + "CSI1_SHUTTER", "CSI1_OE",
> + "CSI0_STROBE", "CSI0_TRIGGER",
> + "CSI0_SHUTTER", "CSI0_OE";
> + };
> +
> + current-sensor@40 {
> + compatible = "ti,ina233";
> + reg = <0x40>;
> + shunt-resistor = <18000>;
> + };
> +
> + eeprom@51 {
> + compatible = "atmel,24c02";
> + reg = <0x51>;
> + pagesize = <16>;
> + };
> +};
> +
> +&main_mcan0 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&main_mcan0_pins_default>;
> + phys = <&can_tc0>;
> + status = "okay";
> +};
> +
> +&main_uart0 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&main_uart0_pins_default>;
> + bootph-all;
> + status = "okay";
> +};
> +
> +&mcasp0 {
> + #sound-dai-cells = <0>;
> + op-mode = <0>; /* MCASP_IIS_MODE */
> + pinctrl-names = "default";
> + pinctrl-0 = <&main_mcasp0_pins_default>;
> + tdm-slots = <2>;
> + serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
> + 0 0 1 2
> + 0 0 0 0
> + 0 0 0 0
> + 0 0 0 0
> + >;
> + status = "okay";
> +};
> +
> +&mcasp1 {
> + #sound-dai-cells = <0>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&main_mcasp1_pins_default>;
> + op-mode = <0>; /* MCASP_IIS_MODE */
> + tdm-slots = <2>;
> + serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
> + 1 0 2 0
> + 0 0 0 0
> + 0 0 0 0
> + 0 0 0 0
> + >;
> + status = "okay";
> +};
> +
> +&pcie0_rc {
> + pinctrl-names = "default";
> + pinctrl-0 = <&main_pcie_pins_default>;
> + num-lanes = <1>;
> + phys = <&serdes1_pcie_link>;
> + phy-names = "pcie-phy";
> + reset-gpios = <&main_gpio0 31 GPIO_ACTIVE_HIGH>;
> + status = "okay";
> +};
> +
> +&sdhci1 {
> + /* SD/MMC */
> + vmmc-supply = <&vcc_3v3_mmc>;
> + vqmmc-supply = <&vddshv_sdio>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&main_mmc1_pins_default>;
> + disable-wp;
> + no-1-8-v;
> + bootph-all;
> + status = "okay";
> +};
> +
> +&serdes_ln_ctrl {
> + idle-states = <J722S_SERDES0_LANE0_USB>,
> + <J722S_SERDES1_LANE0_PCIE0_LANE0>;
> +};
> +
> +&serdes0 {
> + status = "okay";
> +
> + serdes0_usb_link: phy@0 {
> + reg = <0>;
> + cdns,num-lanes = <1>;
> + #phy-cells = <0>;
> + cdns,phy-type = <PHY_TYPE_USB3>;
> + resets = <&serdes_wiz0 1>;
> + };
> +};
> +
> +&serdes_wiz0 {
> + status = "okay";
> +};
> +
> +&serdes1 {
> + status = "okay";
> +
> + serdes1_pcie_link: phy@0 {
> + reg = <0>;
> + cdns,num-lanes = <1>;
> + #phy-cells = <0>;
> + cdns,phy-type = <PHY_TYPE_PCIE>;
> + resets = <&serdes_wiz1 1>;
> + };
> +};
> +
> +&serdes_wiz1 {
> + clocks = <&k3_clks 280 0>, <&k3_clks 280 1>, <&pcie_refclk0>;
> + status = "okay";
> +};
> +
> +&usbss0 {
> + ti,vbus-divider;
> + status = "okay";
> +};
> +
> +&usb0 {
> + dr_mode = "otg";
> + usb-role-switch;
> + maximum-speed = "high-speed";
> +
> + port {
> + usb0_ep: endpoint {
> + remote-endpoint = <&usb0_con>;
> + };
> + };
> +};
> +
> +&usbss1 {
> + ti,vbus-divider;
> + status = "okay";
> +};
> +
> +&usb1 {
> + dr_mode = "host";
> + phys = <&serdes0_usb_link>;
> + phy-names = "cdns3,usb3-phy";
> + maximum-speed = "super-speed";
> +};
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox